File: README.md
acme-companion
acme-companion is a lightweight companion container for nginx-proxy.
It handles the automated creation, renewal and use of SSL certificates for proxied Docker containers through the ACME protocol.
Features:
- Automated creation/renewal of Let's Encrypt (or other ACME CAs) certificates using acme.sh.
- Let's Encrypt / ACME domain validation through
HTTP-01(by default) orDNS-01challenge. - Automated update and reload of nginx config on certificate creation/renewal.
- Support creation of Multi-Domain (SAN) Certificates.
- Support creation of Wildcard Certificates (with
DNS-01challenge only). - Creation of a strong RFC7919 Diffie-Hellman Group at startup.
- Work with all versions of docker.
HTTP-01 challenge requirements:
- Your host must be publicly reachable on both port
80and443. - Check your firewall rules and do not attempt to block port
80as that will preventHTTP-01challenges from completing. - For the same reason, you can't use nginx-proxy's
HTTPS_METHOD=nohttp. - The (sub)domains you want to issue certificates for must correctly resolve to the host.
- If your (sub)domains have AAAA records set, the host must be publicly reachable over IPv6 on port
80and443.
If you can't meet these requirements, you can use the DNS-01 challenge instead. Please refer to the documentation for more information.
In addition to the above, please ensure that your DNS provider answers correctly to CAA record requests. If your DNS provider answer with an error, Let's Encrypt won't issue a certificate for your domain. Let's Encrypt do not require that you set a CAA record on your domain, just that your DNS provider answers correctly.
Basic usage (with the nginx-proxy container)
Two writable volumes must be declared on the nginx-proxy container so that they can be shared with the acme-companion container:
/etc/nginx/certsto store certificates and private keys (readonly for the nginx-proxy container)./usr/share/nginx/htmlto writehttp-01challenge files.
Additionally, a third volume must be declared on the acme-companion container to store acme.sh configuration and state: /etc/acme.sh.
Please also read the doc about data persistence.
Example of use:
Step 1 - nginx-proxy
Start nginx-proxy with the two additional volumes declared:
$ docker run --detach \
--name nginx-proxy \
--publish 80:80 \
--publish 443:443 \
--volume certs:/etc/nginx/certs \
--volume html:/usr/share/nginx/html \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \
nginxproxy/nginx-proxyBinding the host docker socket (/var/run/docker.sock) inside the container to /tmp/docker.sock is a requirement of nginx-proxy.
Step 2 - acme-companion
Start the acme-companion container, getting the volumes from nginx-proxy with --volumes-from:
$ docker run --detach \
--name nginx-proxy-acme \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--volume acme:/etc/acme.sh \
--env "[email protected]" \
nginxproxy/acme-companionThe host docker socket has to be bound inside this container too, this time to /var/run/docker.sock.
Albeit optional, it is recommended to provide a valid default email address through the DEFAULT_EMAIL environment variable, so that Let's Encrypt can warn you about expiring certificates and allow you to recover your account.
Step 3 - proxied container(s)
Once both nginx-proxy and acme-companion containers are up and running, start any container you want proxied with environment variables VIRTUAL_HOST and ACME_HOST both set to the domain(s) your proxied container is going to use.
VIRTUAL_HOST controls proxying by nginx-proxy and ACME_HOST controls certificate creation and SSL enabling by acme-companion.
Certificates will only be issued for containers that have both VIRTUAL_HOST and ACME_HOST variables set to domain(s) that correctly resolve to the host, provided the host is publicly reachable.
$ docker run --detach \
--name your-proxied-app \
--env "VIRTUAL_HOST=subdomain.yourdomain.tld" \
--env "ACME_HOST=subdomain.yourdomain.tld" \
nginxThe containers being proxied must expose the port to be proxied, either by using the EXPOSE directive in their Dockerfile or by using the --expose flag to docker run or docker create.
If the proxied container listen on and expose another port than the default 80, you can force nginx-proxy to use this port with the VIRTUAL_PORT environment variable.
Example using Grafana (expose and listen on port 3000):
$ docker run --detach \
--name grafana \
--env "VIRTUAL_HOST=othersubdomain.yourdomain.tld" \
--env "VIRTUAL_PORT=3000" \
--env "ACME_HOST=othersubdomain.yourdomain.tld" \
--env "[email protected]" \
grafana/grafanaRepeat Step 3 for any other container you want to proxy.
Additional documentation
Please check the docs section and the environment variables reference for more information about the available configuration options.
About this repository
[!NOTE]
This repository is officially maintained by ZeroSSL as part of our commitment to secure and reliable SSL/TLS solutions.
We welcome contributions and feedback from the community!
For more information about our services, including free and paid SSL/TLS certificates, visit https://zerossl.com.
File: docs/Advanced-usage.md
Advanced usage (with the nginx and docker-gen containers)
nginx-proxy can also be run as two separate containers using the nginx-proxy/docker-gen image and the official nginx image. You may want to do this to prevent having the docker socket bound to a publicly exposed container service (ie avoid mounting the docker socket in the nginx exposed container).
Please read and try basic usage, and validate that you have a working two containers setup before using the three containers setup. In addition to the steps described there, running nginx-proxy as two separate containers with acme-companion requires the following:
- Download and mount the template file nginx.tmpl into the docker-gen container. You can get the nginx.tmpl file with a command like:
curl https://raw.githubusercontent.com/nginx-proxy/nginx-proxy/main/nginx.tmpl > /path/to/nginx.tmplUse the
com.github.nginx-proxy.docker-genlabel on the docker-gen container, or explicitly set theNGINX_DOCKER_GEN_CONTAINERenvironment variable on the acme-companion container to the name or id of the docker-gen container (we'll use the later method in the example).Declare
/etc/nginx/conf.das a volume on the nginx container so that it can be shared with the docker-gen container.
Example:
Step 1 - nginx
- Start nginx (official image) with the required volumes:
$ docker run --detach \
--name nginx-proxy \
--publish 80:80 \
--publish 443:443 \
--volume conf:/etc/nginx/conf.d \
--volume html:/usr/share/nginx/html \
--volume certs:/etc/nginx/certs \
nginxStep 2 - docker-gen
- Start the docker-gen container with the shared volumes (with
--volume-from), the template file and the docker socket:
$ docker run --detach \
--name nginx-proxy-gen \
--volumes-from nginx-proxy \
--volume /path/to/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \
nginxproxy/docker-gen \
-notify-sighup nginx-proxy -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.confNote that you must pass the exact name of the nginx container to docker-gen -notify-sighup argument (here nginx-proxy).
Step 3 - acme-companion
- Start the acme-companion container with the
NGINX_DOCKER_GEN_CONTAINERenvironment variable correctly set:
$ docker run --detach \
--name nginx-proxy-acme \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--volume acme:/etc/acme.sh \
--env "NGINX_DOCKER_GEN_CONTAINER=nginx-proxy-gen" \
--env "[email protected]" \
nginxproxy/acme-companionStep 4 - proxied container(s)
- Once the three containers are up, start any containers to be proxied as described in basic usage.
$ docker run --detach \
--name your-proxyed-app \
--env "VIRTUAL_HOST=subdomain.yourdomain.tld" \
--env "ACME_HOST=subdomain.yourdomain.tld" \
nginxIf you are experiencing issues with this setup, fall back to the basic setup. The advanced setup is not meant to be obligatory.
File: docs/Basic-usage.md
Basic usage (with the nginx-proxy container)
Two writable volumes must be declared on the nginx-proxy container so that they can be shared with the acme-companion container:
/etc/nginx/certsto store certificates and private keys (readonly for the nginx-proxy container)./usr/share/nginx/htmlto writeHTTP-01challenge files.
Additionally, a third volume must be declared on the acme-companion container to store acme.sh configuration and state: /etc/acme.sh.
Please also read the doc about data persistence.
Example of use:
Step 1 - nginx-proxy
Start nginx-proxy with the two additional volumes declared:
$ docker run --detach \
--name nginx-proxy \
--publish 80:80 \
--publish 443:443 \
--volume certs:/etc/nginx/certs \
--volume html:/usr/share/nginx/html \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \
nginxproxy/nginx-proxyBinding the host docker socket (/var/run/docker.sock) inside the container to /tmp/docker.sock is a requirement of nginx-proxy.
Step 2 - acme-companion
Start the acme-companion container, getting the volumes from nginx-proxy with --volumes-from:
$ docker run --detach \
--name nginx-proxy-acme \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--volume acme:/etc/acme.sh \
--env "[email protected]" \
nginxproxy/acme-companionThe host docker socket has to be bound inside this container too, this time to /var/run/docker.sock.
Albeit optional, it is recommended to provide a valid default email address through the DEFAULT_EMAIL environment variable, so that Let's Encrypt can warn you about expiring certificates and allow you to recover your account.
Step 3 - proxied container(s)
Once both nginx-proxy and acme-companion containers are up and running, start any container you want proxied with environment variables VIRTUAL_HOST and ACME_HOST both set to the domain(s) your proxied container is going to use. Multiple hosts can be separated using commas.
VIRTUAL_HOST controls proxying by nginx-proxy and ACME_HOST controls certificate creation and SSL enabling by acme-companion.
Certificates will only be issued for containers that have both VIRTUAL_HOST and ACME_HOST variables set to domain(s) that correctly resolve to the host, provided the host is publicly reachable.
$ docker run --detach \
--name your-proxyed-app \
--env "VIRTUAL_HOST=subdomain.yourdomain.tld" \
--env "ACME_HOST=subdomain.yourdomain.tld" \
nginxThe containers being proxied must expose the port to be proxied, either by using the EXPOSE directive in their Dockerfile or by using the --expose flag to docker run or docker create.
If the proxied container listen on and expose another port than the default 80, you can force nginx-proxy to use this port with the VIRTUAL_PORT environment variable.
Example using Grafana (expose and listen on port 3000):
$ docker run --detach \
--name grafana \
--env "VIRTUAL_HOST=othersubdomain.yourdomain.tld" \
--env "VIRTUAL_PORT=3000" \
--env "ACME_HOST=othersubdomain.yourdomain.tld" \
--env "[email protected]" \
grafana/grafanaRepeat Step 3 for any other container you want to proxy.
File: docs/Container-configuration.md
Optional container environment variables for custom configuration.
ACME_CA_URI- Directory URI for the CA ACME API endpoint (defaults tohttps://acme-v02.api.letsencrypt.org/directory).
If you set this environment variable value to https://acme-staging-v02.api.letsencrypt.org/directory the container will obtain its certificates from Let's Encrypt test API endpoint that don't have the 5 certs/week/domain limit (but are not trusted by browsers).
For example
$ docker run --detach \
--name nginx-proxy-acme \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--volume certs:/etc/nginx/certs:rw \
--volume acme:/etc/acme.sh \
--env "ACME_CA_URI=https://acme-staging-v02.api.letsencrypt.org/directory" \
nginxproxy/acme-companionYou can also create test certificates per container (see Test certificates)
DEBUG- Set it to1to enable debugging of the entrypoint script and generation of LetsEncrypt certificates, which could help you pinpoint any configuration issues. When enabled,acme.sh's own detailed log is also sent to the container output (visible throughdocker logs) instead of being discarded, which is especially useful for diagnosing DNS-01 challenge failures.RENEW_PRIVATE_KEYS- Set it tofalseto makeacme.shreuse previously generated private key for each certificate instead of creating a new one on certificate renewal. Reusing private keys can help if you intend to use HPKP, but please note that HPKP has been deprecated by Google's Chrome and that it is therefore strongly discouraged to use it at all. This can also be set per proxied container by settingACME_RENEW_PRIVATE_KEYSon that container, which overrides the global value for its certificate (e.g. to keep a stable key for a DANE/TLSA mail certificate while still rotating keys elsewhere).DHPARAM_BITS- Change the key size of the RFC7919 Diffie-Hellman group used by the container from the default value of 4096 bits. Supported values are2048,3072and4096. The DH group file will be located in the container at/etc/nginx/certs/dhparam.pem. Mounting a differentdhparam.pemfile at that location will override the RFC7919 group creation by the acme-companion container. COMPATIBILITY WARNING: some older clients (like Java 6 and 7) do not support DH keys with over 1024 bits. In order to support these clients, you must provide your owndhparam.pem.DHPARAM_SKIP- Set it totrueto disable the Diffie-Hellman group creation by the container entirely.ACME_CA_BUNDLE- This variable changes the trusted root CA used byacme.sh, from the default Alpine trust store to the CA bundle file located at the provided path (inside the container). This can be useful if you are running your own ACME CA.CERTS_UPDATE_INTERVAL- 3600 seconds by default, this defines how often the container will check if the certificates require update.ACME_PRE_HOOK- The provided command will be run before every certificate issuance. The action is limited to the commands available inside the acme-companion container. For example--env "ACME_PRE_HOOK=echo 'start'". For more information see Pre- and Post-HookACME_POST_HOOK- The provided command will be run after every certificate issuance. The action is limited to the commands available inside the acme-companion container. For example--env "ACME_POST_HOOK=echo 'end'". For more information see Pre- and Post-HookACME_RENEW_AFTER- 60 days by default, this defines the number of days between certificate renewals attempts. For certificates issued by certain Certificate Authorities, such as Buypass, which have a lifespan of 180 days, it may be advisable to initiate the renewal process on day 150 rather than the default day 60. See BuyPass.com CA for more detail. This can also be set per-container (see Certificate renewal timing).DEFAULT_RENEW- DEPRECATED: This variable is deprecated and replaced byACME_RENEW_AFTER. It still works for backward compatibility, but a warning will be logged on container startup. Please migrate toACME_RENEW_AFTER.ACME_HTTP_CHALLENGE_LOCATION- Previously acme-companion automatically added the ACME HTTP challenge location to the nginx configuration through files generated in/etc/nginx/vhost.d. Recent versions of nginx-proxy (>=1.6) already include the required location configuration, which remove the need for acme-companion to attempt to dynamically add them. If you're running and older version of nginx-proxy (or docker-gen with an older version of thenginx.tmplfile), you can re-enable this behaviour by settingACME_HTTP_CHALLENGE_LOCATIONtotrue.ENABLE_IPV6- Set it totrueto make the standalone ACME HTTP challenge configuration (used for domains not served by nginx-proxy, e.g.ACME_STANDALONE_CERTS) also listen over IPv6 (listen [::]:80;) in addition to IPv4. This matches nginx-proxy'sENABLE_IPV6option, so set the same value on both containers. Leave it unset (orfalse) unless your host and its Docker networking actually support IPv6, otherwise nginx may fail to bind the IPv6 socket. Only the standalone challenge config is affected; challenges served through nginx-proxy already follow nginx-proxy's own IPv6 setting.RELOAD_NGINX_ONLY_ONCE- The companion reload nginx configuration after every new or renewed certificate. Previously this was done only once per service loop, at the end of the loop (this was causing delayed availability of HTTPS enabled application when multiple new certificates where requested at once, see issue #1147). You can restore the previous behaviour if needed by setting the environment variableRELOAD_NGINX_ONLY_ONCEtotrue.DOCKER_CONTAINER_FILTERS- You can filter which containers are considered by acme-companion by using theDOCKER_CONTAINER_FILTERSenvironment variable (by default, acme-companion will consider all running containers). It takes a comma separated list ofkey=valuepairs. For example, settingDOCKER_CONTAINER_FILTERSenvironment variable tonetwork=mynetworkwill cause acme-companion to consider only containers connected to themynetworknetwork. See the Docker CLI documentation for details on available filters.DOCKER_HOST- The Docker API endpoint acme-companion talks to. Defaults tounix:///var/run/docker.sock(the mounted Docker socket). To connect to a remote or TLS-protected Docker daemon over TCP, set it totcp://<host>:(the conventional Docker TLS port is2376).DOCKER_TLS_VERIFYandDOCKER_CERT_PATH- Enable TLS client-certificate authentication when connecting to the Docker daemon overtcp://. SetDOCKER_TLS_VERIFYtotrueandDOCKER_CERT_PATHto the in-container path of a directory containingca.pem,cert.pemandkey.pem. These variable names and file names match the Docker CLI convention and the ones used by docker-gen, so the same certificate directory can be shared across containers.Important:
DOCKER_CERT_PATHis a path inside the container. You must mount your certificate directory into the container with a volume, otherwise the files will not be found and the container will exit on startup with an error.For example, connecting to a TLS-protected Docker daemon over TCP (note that the Docker socket is not mounted in this case):
bash$ docker run --detach \ --name nginx-proxy-acme \ --volumes-from nginx-proxy \ --volume certs:/etc/nginx/certs:rw \ --volume acme:/etc/acme.sh \ --volume /path/to/docker/certs:/docker-certs:ro \ --env "DOCKER_HOST=tcp://docker-host.example.com:2376" \ --env "DOCKER_TLS_VERIFY=true" \ --env "DOCKER_CERT_PATH=/docker-certs" \ nginxproxy/acme-companion
File: docs/Container-utilities.md
The container provide the following utilities (replace nginx-proxy-acme with the name or ID of your acme-companion container when executing the commands):
Force certificates renewal
If needed, you can force a running acme-companion container to renew all certificates that are currently in use with the following command:
$ docker exec nginx-proxy-acme force_renewManually trigger the service loop
You can trigger the execution of the service loop before the hourly execution with:
$ docker exec nginx-proxy-acme signal_le_serviceUnlike the previous command, this won't force renewal of certificates that don't need to be renewed.
Show certificates informations
To display informations about your existing certificates, use the following command:
$ docker exec nginx-proxy-acme cert_statusFile: docs/Docker-Compose.md
Usage with Docker Compose
As stated by its repository, Docker Compose is a tool for defining and running multi-container Docker applications using a single Compose file. This Wiki page is not meant to be a definitive reference on how to run nginx-proxy and acme-companion with Docker Compose, as the number of possible setups is quite extensive and they can't be all covered.
Before your start
Be sure to be familiar with both the basic and advanced non compose setups, and Docker Compose usage.
The following examples are minimal, clean starting points, not a definitive reference. They follow current Docker Compose conventions:
- The top-level
version:key is intentionally omitted: it is obsolete in the Compose Specification and ignored by Docker Compose. - They do not use
volumes_from(a compose file version 2 only feature): every volume is mounted explicitly on each container instead. - acme-companion finds the nginx/nginx-proxy (and docker-gen) container through the
labelmethod, see getting container IDs. TheNGINX_PROXY_CONTAINER/NGINX_DOCKER_GEN_CONTAINERenvironment variable method documented there is an equally valid alternative.
If you still rely on a volumes_from based compose file, see getting container IDs for the docker run --volumes-from method (still supported) and this page's git history for the previous examples.
The use of named containers and volumes is not required but helps keeping everything clear and organized.
Two containers example
services:
nginx-proxy:
image: nginxproxy/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
labels:
- "com.github.nginx-proxy.nginx"
volumes:
- certs:/etc/nginx/certs:ro
- html:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
# The vhost and conf volumes are only required
# if you plan to obtain standalone certificates
# - vhost:/etc/nginx/vhost.d
# - conf:/etc/nginx/conf.d
acme-companion:
image: nginxproxy/acme-companion
container_name: nginx-proxy-acme
environment:
- [email protected]
volumes:
- certs:/etc/nginx/certs:rw
- html:/usr/share/nginx/html:rw
- acme:/etc/acme.sh
- /var/run/docker.sock:/var/run/docker.sock:ro
# The vhost and conf volumes are only required
# if you plan to obtain standalone certificates
# - vhost:/etc/nginx/vhost.d
# - conf:/etc/nginx/conf.d
# A user-defined network is optional; Compose creates a default one per project.
#networks:
# default:
# name: nginx-proxy
volumes:
certs:
html:
acme:
# vhost:
# conf:Three containers example
services:
nginx:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
labels:
- "com.github.nginx-proxy.nginx"
volumes:
- conf:/etc/nginx/conf.d:ro
- html:/usr/share/nginx/html
- certs:/etc/nginx/certs:ro
# The vhost volume is only required if you
# plan to obtain standalone certificates
# - vhost:/etc/nginx/vhost.d
docker-gen:
image: nginxproxy/docker-gen
container_name: nginx-proxy-gen
command: -notify-sighup nginx-proxy -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
labels:
- "com.github.nginx-proxy.docker-gen"
volumes:
- conf:/etc/nginx/conf.d:rw
- certs:/etc/nginx/certs:ro
- /path/to/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
# The vhost volume is only required if you
# plan to obtain standalone certificates
# - vhost:/etc/nginx/vhost.d
acme-companion:
image: nginxproxy/acme-companion
container_name: nginx-proxy-acme
environment:
- [email protected]
volumes:
- certs:/etc/nginx/certs:rw
- html:/usr/share/nginx/html:rw
- acme:/etc/acme.sh
- /var/run/docker.sock:/var/run/docker.sock:ro
# The vhost and conf volumes are only required
# if you plan to obtain standalone certificates
# - vhost:/etc/nginx/vhost.d
# - conf:/etc/nginx/conf.d
#networks:
# default:
# name: nginx-proxy
volumes:
conf:
html:
certs:
acme:
# vhost:Note: don't forget to replace /path/to/nginx.tmpl with the actual path to the nginx.tmpl file you downloaded.
Other (external) examples
Warning: some of those examples might be outdated and not working properly with version >= 2.0 of this project.
If you want other examples how to use this container with Docker Compose, look at:
- Nicolas Duchon's Examples - with automated testing
- Evert Ramos's Examples - using docker-compose version '3'
- Karl Fathi's Examples
- More examples from Karl
- George Ilyes' Examples
- Dmitry's simple docker-compose example
- Radek's docker-compose jenkins example
File: docs/Getting-containers-IDs.md
Getting nginx-proxy/nginx/docker-gen containers IDs
For acme-companion to work properly, it needs to know the ID of the nginx/nginx-proxy container (in both two and three containers setups), plus the ID of the docker-gen container in a three container setup.
There are three methods to inform the acme-companion container of the nginx/nginx-proxy container ID:
labelmethod: add the labelcom.github.nginx-proxy.nginxto the nginx/nginx-proxy container.environment variablemethod: assign a fixed name to the nginx/nginx-proxy container withcontainer_name:and set the environment variableNGINX_PROXY_CONTAINERto this name on the acme-companion container.volumes_frommethod. Using this method, the acme-companion container will get the nginx/nginx-proxy container ID from the volumes it got using thevolumes_fromoption.
And two methods to inform the acme-companion container of the docker-gen container ID:
labelmethod: add the labelcom.github.nginx-proxy.docker-gento the docker-gen container.environment variablemethod: assign a fixed name to the docker-gen container withcontainer_name:and set the environment variableNGINX_DOCKER_GEN_CONTAINERto this name on the acme-companion container.
The methods for each container are sorted by order of precedence, meaning that if you use both the label and the volumes_from method, the ID of the nginx/nginx-proxy container that will be used will be the one found using the label. There is no point in using more than one method at a time for either the nginx/nginx-proxy or docker-gen container beside potentially confusing yourself.
The advantage the label methods have over the environment variable (and volumes_from) methods is enabling the use of the acme-companion in environments where containers names are dynamic, like in Swarm Mode or in Docker Cloud. However if you intend to do so, as upstream docker-gen lacks the ability to identify containers from labels, you'll need both to either use the two containers setup or to replace nginx-proxy/docker-gen with a fork that has this ability like herlderco/docker-gen. Be advised that for now, this works to a very limited extent (everything has to be on the same node).
Examples with three containers setups:
label method.
$ docker run --detach \
[...]
--label com.github.nginx-proxy.nginx \
nginx
$ docker run --detach \
[...]
--label com.github.nginx-proxy.docker-gen \
nginxproxy/docker-gen
$ docker run --detach \
[...]
nginxproxy/acme-companionenvironment variable method
$ docker run --detach \
[...]
--name unique-container-name \
nginx
$ docker run --detach \
[...]
--name another-unique-container-name \
nginxproxy/docker-gen
$ docker run --detach \
[...]
--env NGINX_PROXY_CONTAINER=unique-container-name \
--env NGINX_DOCKER_GEN_CONTAINER=another-unique-container-name \
nginxproxy/acme-companionvolumes_from (nginx) + label (docker-gen) method
$ docker run --detach \
[...]
--name unique-container-name \
nginx
$ docker run --detach \
[...]
--label com.github.nginx-proxy.docker-gen \
nginxproxy/docker-gen
$ docker run --detach \
[...]
--volumes-from unique-container-name \
nginxproxy/acme-companionvolumes_from (nginx) + environment variable (docker-gen) method
$ docker run --detach \
[...]
--name unique-container-name \
nginx
$ docker run --detach \
[...]
--name another-unique-container-name \
nginxproxy/docker-gen
$ docker run --detach \
[...]
--volumes-from unique-container-name \
--env NGINX_DOCKER_GEN_CONTAINER=another-unique-container-name \
nginxproxy/acme-companionFile: docs/Google-Trust-Services.md
Google Trust Services
Google Trust Service is an ACME CA with generous default quota and high ubiquity.
Using Google Trust Services through an ACME client, like in this container, allows for unlimited 90 days and multi-domains (SAN) certificates.
Activation
Google Trust Services support is activated when the ACME_CA_URI environment variable is set to the Google Trust Services ACME endpoint (https://dv.acme-v02.api.pki.goog/directory).
Account
Google Trust Services requires the use of an externally bound account. First create a Google Trust Services account:
- provide the pre-generated EAB credentials using the
ACME_EAB_KIDandACME_EAB_HMAC_KEYenvironment variables.
These variables can be set on the proxied containers or directly on the acme-companion container.
When registering a new ACME account with EAB, Google Trust Services expects a contact email. Set either ACME_EMAIL on the proxied container or DEFAULT_EMAIL on the acme-companion container so the initial acme.sh --register-account call includes it.
If both are unset or blank, acme-companion will still try to register the EAB account without an email and log a warning, but Google Trust Services may reject the registration.
File: docs/Hooks.md
Pre-Hooks and Post-Hooks
The Pre- and Post-Hooks of acme.sh are available through the corresponding environment variables. This allows to trigger actions just before and after certificates are issued (see acme.sh documentation).
If you set ACME_PRE_HOOK and/or ACME_POST_HOOK on the acme-companion container, the actions for all certificates will be the same. If you want specific actions to be run for specific certificates, set the ACME_PRE_HOOK / ACME_POST_HOOK environment variable(s) on the proxied container(s) instead. Default (on the acme-companion container) and per-container ACME_PRE_HOOK / ACME_POST_HOOK environment variables aren't combined : if both default and per-container variables are set for a given proxied container, the per-container variables will take precedence over the default.
If you want to run the same default hooks for most containers but not for some of them, you can set the ACME_PRE_HOOK / ACME_POST_HOOK environment variables to the Bash noop operator (ie, ACME_PRE_HOOK=:) on those containers.
Pre-Hook: `ACME_PRE_HOOK`
This command will be run before certificates are issued.
For example echo 'start' on the acme-companion container (setting a default Pre-Hook):
$ docker run --detach \
--name nginx-proxy-acme \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--volume acme:/etc/acme.sh \
--env "[email protected]" \
--env "ACME_PRE_HOOK=echo 'start'" \
nginxproxy/acme-companionAnd on a proxied container (setting a per-container Pre-Hook):
$ docker run --detach \
--name your-proxyed-app \
--env "VIRTUAL_HOST=yourdomain.tld" \
--env "ACME_HOST=yourdomain.tld" \
--env "ACME_PRE_HOOK=echo 'start'" \
nginxPost-Hook: `ACME_POST_HOOK`
This command will be run after certificates are issued.
For example echo 'end' on the acme-companion container (setting a default Post-Hook):
$ docker run --detach \
--name nginx-proxy-acme \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--volume acme:/etc/acme.sh \
--env "[email protected]" \
--env "ACME_POST_HOOK=echo 'end'" \
nginxproxy/acme-companionAnd on a proxied container (setting a per-container Post-Hook):
$ docker run --detach \
--name your-proxyed-app \
--env "VIRTUAL_HOST=yourdomain.tld" \
--env "ACME_HOST=yourdomain.tld" \
--env "ACME_POST_HOOK=echo 'start'" \
nginxVerification:
If you want to check wether the hook-command is delivered properly to acme.sh, you should check /etc/acme.sh/[EMAILADDRESS]/[DOMAIN]/[DOMAIN].conf.
The variable Le_PreHook contains the Pre-Hook-Command base64 encoded.
The variable Le_PostHook contains the Post-Hook-Command base64 encoded.
Limitations
- The commands that can be used in the hooks are limited to the commands available inside the acme-companion container.
curlandwgetare available, therefore it is possible to communicate with tools outside the container via HTTP, allowing for complex actions to be implemented outside or in other containers.
Use-cases
- Changing some firewall rules just for the ACME authorization, so the ports 80 and/or 443 don't have to be publicly reachable at all time.
- Certificate "post processing" / conversion to another format.
- Monitoring.