diff --git a/README.md b/README.md index 2d040bc..dc531ae 100644 --- a/README.md +++ b/README.md @@ -235,7 +235,7 @@ Caveats: - The port 2080 is reserved for the certbot and should not be exposed. - You cannot set the port 443 for the container with the Letsencrypt. EasyHAProxy will handle this automatically once the certificate is issued. - If you don't run the EasyHAProxy with the parameter `EASYHAPROXY_LETSENCRYPT_EMAIL` no certificate will be issued. -- Be aware about the issue limits - https://letsencrypt.org/docs/rate-limits/ +- Be aware about issue limits - https://letsencrypt.org/docs/duplicate-certificate-limit/ and https://letsencrypt.org/docs/rate-limits/ ## Exposing Ports @@ -267,6 +267,17 @@ docker run \ -d byjg/easy-haproxy ``` +## Mapping ssl certificates volumes + +EasyHAProxy stores the certificates inside the folder `/certs/haproxy` and `/certs/letsencrypt`. If you want to preserve the certificates between reloads, just map the folder `/certs` to your volume. + +```bash +docker run \ + /* other parameters */ + -v /your/certs/folder:/certs \ + -d byjg/easy-haproxy +``` + ## Handling SSL You can attach a valid SSL certificate to the request. diff --git a/assets/etc/haproxy/certs/.place_holder_cert.pem b/assets/certs/haproxy/.place_holder_cert.pem similarity index 100% rename from assets/etc/haproxy/certs/.place_holder_cert.pem rename to assets/certs/haproxy/.place_holder_cert.pem diff --git a/assets/scripts/certbot.sh b/assets/scripts/certbot.sh index acf9e76..76f1774 100755 --- a/assets/scripts/certbot.sh +++ b/assets/scripts/certbot.sh @@ -15,12 +15,12 @@ REQUEST_CERTS="" RENEW_CERTS="" for domain in $(cat /scripts/letsencrypt_hosts.txt); do - if [ ! -f "/etc/haproxy/certs/$domain.pem" ]; then + if [ ! -f "/certs/letsencrypt/$domain.pem" ]; then REQUEST_CERTS="$REQUES_CERTS -d $domain" continue fi - if [[ $(find "/etc/haproxy/certs/$domain.pem" -mtime +30 -print) ]]; then + if [[ $(find "/certs/letsencrypt/$domain.pem" -mtime +30 -print) ]]; then RENEW_CERTS="$RENEW_CERTS -d $domain" fi done diff --git a/assets/scripts/certbot_to_haproxy.sh b/assets/scripts/certbot_to_haproxy.sh index f7833f6..7d84250 100755 --- a/assets/scripts/certbot_to_haproxy.sh +++ b/assets/scripts/certbot_to_haproxy.sh @@ -5,7 +5,7 @@ for CERTIFICATE in `find /etc/letsencrypt/live/* -type d`; do CERTIFICATE=`basename $CERTIFICATE` # Combine certificate and private key to single file - cat /etc/letsencrypt/live/$CERTIFICATE/fullchain.pem /etc/letsencrypt/live/$CERTIFICATE/privkey.pem > /etc/haproxy/certs/$CERTIFICATE.pem + cat /etc/letsencrypt/live/$CERTIFICATE/fullchain.pem /etc/letsencrypt/live/$CERTIFICATE/privkey.pem > /certs/letsencrypt/$CERTIFICATE.pem done # It will be checked on haproxy-reload.sh diff --git a/easymapping/__init__.py b/easymapping/__init__.py index 541528e..44e3e64 100644 --- a/easymapping/__init__.py +++ b/easymapping/__init__.py @@ -46,17 +46,18 @@ class DockerLabelHandler: class HaproxyConfigGenerator: - def __init__(self, mapping, ssl_cert_folder="/etc/haproxy/certs/discover"): + def __init__(self, mapping, ssl_cert_folder="/certs"): self.mapping = mapping self.mapping.setdefault("ssl_mode", 'default') self.mapping["ssl_mode"] = self.mapping["ssl_mode"].lower() self.label = DockerLabelHandler(mapping['lookup_label'] if 'lookup_label' in mapping else "easyhaproxy") - self.ssl_cert_folder = ssl_cert_folder + self.ssl_cert_haproxy = ssl_cert_folder + "/haproxy" + self.ssl_cert_letsecncrypt = ssl_cert_folder + "/letsencrypt" self.letsencrypt_hosts = [] self.letsencrypt_email = os.getenv("EASYHAPROXY_LETSENCRYPT_EMAIL", "") - os.makedirs(self.ssl_cert_folder, exist_ok=True) - - + os.makedirs(self.ssl_cert_haproxy, exist_ok=True) + os.makedirs(self.ssl_cert_letsecncrypt, exist_ok=True) + def generate(self, line_list = []): self.mapping.setdefault("easymapping", []) @@ -163,7 +164,7 @@ class HaproxyConfigGenerator: } easymapping["443"]["hosts"][hostname] = dict(easymapping[port]["hosts"][hostname]) easymapping["443"]["hosts"][hostname]["letsencrypt"] = False - easymapping["443"]["ssl_cert"] = "/etc/haproxy/certs" + easymapping["443"]["ssl_cert"] = self.ssl_cert_letsecncrypt self.letsencrypt_hosts.append(hostname) if hostname not in self.letsencrypt_hosts else self.letsencrypt_hosts @@ -171,7 +172,7 @@ class HaproxyConfigGenerator: ssl_label = self.label.create([definition, "sslcert"]) if self.label.has_label(ssl_label): filename = "{}/{}.pem".format( - self.ssl_cert_folder, d[host_label] + self.ssl_cert_haproxy, d[host_label] ) easymapping[port]["ssl_cert"] = filename with open(filename, 'wb') as file: diff --git a/examples/static/config.yml b/examples/static/config.yml index 3ededd6..f3d9073 100644 --- a/examples/static/config.yml +++ b/examples/static/config.yml @@ -12,7 +12,7 @@ easymapping: www.host1.local: https://host1.local - port: 443 - ssl_cert: /etc/certs/host1.local.pem + ssl_cert: /certs/haproxy/host1.local.pem hosts: host1.local: containers: diff --git a/examples/static/docker-compose.yml b/examples/static/docker-compose.yml index 055f997..118084b 100644 --- a/examples/static/docker-compose.yml +++ b/examples/static/docker-compose.yml @@ -8,7 +8,7 @@ services: image: byjg/easy-haproxy volumes: - ./config.yml:/etc/haproxy/easyconfig.yml - - ./host1.local.pem:/etc/certs/host1.local.pem + - ./certs:/certs - /var/run/docker.sock:/var/run/docker.sock environment: EASYHAPROXY_DISCOVER: static diff --git a/templates/bind.j2 b/templates/bind.j2 index 334f72c..aba571c 100644 --- a/templates/bind.j2 +++ b/templates/bind.j2 @@ -1,5 +1,5 @@ {% if "ssl_cert" in o %} - bind *:{{ o["port"] }} ssl crt /etc/haproxy/certs/discover/ alpn http/1.1 crt /etc/haproxy/certs/ alpn http/1.1 + bind *:{{ o["port"] }} ssl crt /certs/letsencrypt/ alpn http/1.1 crt /certs/haproxy/ alpn http/1.1 {% elif "h2" in o and o["h2"] %} bind *:{{ o["port"] }} proto h2 option http-use-htx diff --git a/tests/expected/services-redirect-ssl.txt b/tests/expected/services-redirect-ssl.txt index 342c2bc..9317251 100644 --- a/tests/expected/services-redirect-ssl.txt +++ b/tests/expected/services-redirect-ssl.txt @@ -50,7 +50,7 @@ backend srv_host1_local_80 server srv-0 78a90f5c2d8a:80 check weight 1 frontend http_in_443 - bind *:443 ssl crt /etc/haproxy/certs/discover/ alpn http/1.1 crt /etc/haproxy/certs/ alpn http/1.1 + bind *:443 ssl crt /certs/letsencrypt/ alpn http/1.1 crt /certs/haproxy/ alpn http/1.1 mode http acl is_rule_host2_local_443_1 hdr(host) -i host2.local diff --git a/tests/expected/services.txt b/tests/expected/services.txt index bea8444..8e4d03f 100644 --- a/tests/expected/services.txt +++ b/tests/expected/services.txt @@ -66,7 +66,7 @@ backend srv_node-exporter_quantum_example_org_31337 server srv-0 my-stack_node-exporter:9100 check weight 1 frontend http_in_443 - bind *:443 ssl crt /etc/haproxy/certs/discover/ alpn http/1.1 crt /etc/haproxy/certs/ alpn http/1.1 + bind *:443 ssl crt /certs/letsencrypt/ alpn http/1.1 crt /certs/haproxy/ alpn http/1.1 mode http redirect prefix https://www.somehost.com.br code 301 if { hdr(host) -i somehost.com.br } redirect prefix https://www.somehost.com.br code 301 if { hdr(host) -i somehost.com } diff --git a/tests/expected/static.txt b/tests/expected/static.txt index 9ea729a..ad76627 100644 --- a/tests/expected/static.txt +++ b/tests/expected/static.txt @@ -76,7 +76,7 @@ backend srv_host2_com_br_80 server srv-0 other:3000 check weight 1 frontend http_in_443 - bind *:443 ssl crt /etc/haproxy/certs/discover/ alpn http/1.1 crt /etc/haproxy/certs/ alpn http/1.1 + bind *:443 ssl crt /certs/letsencrypt/ alpn http/1.1 crt /certs/haproxy/ alpn http/1.1 mode http acl is_rule_host1_com_br_443_1 hdr(host) -i host1.com.br diff --git a/tests/fixtures/static.yml b/tests/fixtures/static.yml index 51498d5..90c2b1d 100644 --- a/tests/fixtures/static.yml +++ b/tests/fixtures/static.yml @@ -19,7 +19,7 @@ easymapping: www.host1.com.br: http://host1.com.br - port: 443 - ssl_cert: /etc/haproxy/certs/mycert.pem + ssl_cert: /certs/haproxy/mycert.pem hosts: host1.com.br: containers: diff --git a/tests/test_parser.py b/tests/test_parser.py index 3d597ff..a36516f 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -4,7 +4,7 @@ import os import yaml CERTS_FOLDER="/tmp/certs" -CERT_FILE="/tmp/certs/www.somehost.com.br.pem" +CERT_FILE="/tmp/certs/haproxy/www.somehost.com.br.pem" LETSENCRYPT_EMAIL="some@email.com" def load_fixture(file): @@ -241,7 +241,7 @@ def test_parser_static_raw(): }, { "port": 443, - "ssl_cert": "/etc/haproxy/certs/mycert.pem", + "ssl_cert": "/certs/haproxy/mycert.pem", "hosts": { "host1.com.br": { "containers": [