docs: ssl.md - Revise letsencrypt section (#2209)

Below commit messages are roughly equivalent to what is listed on the PR. The PR provides additional linked resources for reference to support commit message statements.

---

* docs: Add CT log warning

- Added a warning to make users aware that using a public CA like _Let's Encrypt_ will publicly log information that may be somewhat sensitive, or undesirable to have historic records made public which cannot be redacted.

* docs: Revise the manual `certbot` guide

- The `letsencrypt` repo that was linked early in this guide now redirects to the [Certbot repo](https://github.com/certbot/certbot).

- More explicit volume mount instruction for CertBot; the local location was a tad vague.

- Better clarified `/etc/letsencrypt/live` contents structure, as well as FQDN info. Removed the misleading `fqdn:` from `docker-compose.yml` example snippet.

* docs: Revise certbot with Docker guide

- General rewrite of the Docker Certbot section with additional tips (_renewals with automation, and using a alternative CA_).

- Generalized tone and paths in content.

- Update volume mount paths to be consistent with recent normalization effort.

- Moved some instructions into inline-comments for script examples instead.

* docs: Revise Docker with `nginx-proxy` and `acme-companion`

- Break apart into individual steps, indenting content into the step as appropriate.

- Use normalized volume paths (`docker-data/<service>/` prefix).

- `letsencrypt-nginx-proxy-companion` has _changed project name to `acme-companion`_, and _transferred to new maintainers and the `nginx-proxy` organization_. This also affects the DockerHub image references.

- `acme-companion` has _switched from using `simp_le` to `acme.sh`_ for provisioning certificates. This requires mounting an additional volume for persisting provisioner state.

- The dummy container (_webmail_) is no longer `library/nginx`, just [`nginx`](https://hub.docker.com/_/nginx). This container also doesn't appear to be required. I've verified that the ENV can be given to the `mailserver` service container directly. Retained for now.

* docs: Revise Docker Compose with `nginx-proxy` and `acme-companion`

Heavy rewrite of this section. Like the previous commit mentions, this content was outdated. It has been simplified with improved documentation and reference links.

It also looks like there was a mistake in the existing config example as it uses the regular `nginx` image instead of `nginx-proxy`.

- The bulk of the `mailserver` service has been removed, users are advised to have an existing `docker-compose.yml` config for `docker-mailserver` and update only what is relevant to integrate with the cert provisioner.

- `DEBUG` is _false_ by default.

- The `networks:` portion of the example appears to be taken from upstream, _which that has since dropped it_. While we could continue to document this, I consider it more of an advanced config detail that we don't need to touch on in our docs.

- The `htpasswd` volume is unnecessary, only relevant if using _"Basic Authentication"_ to protect access to web service endpoints. `conf.d/` is also not required by default, it can be useful for the `standalone` mode (_documented as a `tip`_). Remaining volumes have inline-comments to document their purpose.

- `volumes_from:` is _not supported in v3 Compose format_, _only v2_ and the Docker CLI. I did not want to advise v2, so I've duplicated the volumes between the two containers instead. Internally `acme-companion` would rely on `volumes_from:` to identify the `nginx-proxy` container, it _provides alternative discovery methods_, the label is outdated and refers the legacy label (_their script logic is the same_); using the ENV `NGINX_PROXY_CONTAINER` seemed most appropriate and has been added.

- Upstream `acme-companion` docs only cover support for v2 Compose format. _There is a note regarding `nginx-proxy`_ having _volumes configured in it's Dockerfile_. Providing a volume for `/etc/nginx/dhparam` is required to avoid creating anonymous volumes each run of `nginx-proxy`. I've used a named data volume here to make it stick out more, it's not desirable and upstream should fix this, then we can drop it.

- I've also opted to only demonstrate the _Two Container (Basic) setup_ that upstream documents. Previously our docs have been showing _`docker-gen` with the Three Container (Advanced) setup_, which allows for not having the Docker API socket attached as a volume to a container exposed to the web. This reduces the security a bit, and I have not mentioned that on our docs. I could caution the reader with a link to upstream about the risk, but I don't think we should maintain the `docker-gen` setup.

* docs(fix): Update anchor links

These mismatched the current section headers they were meant to link to.
This commit is contained in:
Brennan Kinney 2021-09-27 12:40:54 +13:00 committed by GitHub
parent dd33567ec9
commit 4f91620a7f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -6,232 +6,288 @@ There are multiple options to enable SSL (via [`SSL_TYPE`][docs-env::ssl-type]):
- Using [letsencrypt](#lets-encrypt-recommended) (recommended) - Using [letsencrypt](#lets-encrypt-recommended) (recommended)
- Using [Caddy](#caddy) - Using [Caddy](#caddy)
- Using [Traefik](#traefik) - Using [Traefik](#traefik-v2)
- Using [self-signed certificates](#self-signed-certificates-testing-only) - Using [self-signed certificates](#self-signed-certificates)
- Using [your own certificates](#custom-certificate-files) - Using [your own certificates](#bring-your-own-certificates)
After installation, you can test your setup with: After installation, you can test your setup with:
- [`checktls.com`](https://www.checktls.com/TestReceiver) - [`checktls.com`](https://www.checktls.com/TestReceiver)
- [`testssl.sh`](https://github.com/drwetter/testssl.sh) - [`testssl.sh`](https://github.com/drwetter/testssl.sh)
!!! warning "Exposure of DNS labels through Certificate Transparency"
All public Certificate Authorities (CAs) are required to log certificates they issue publicly via [Certificate Transparency][certificate-transparency]. This helps to better establish trust.
When using a public CA for certificates used in private networks, be aware that the associated DNS labels in the certificate are logged publicly and [easily searchable][ct-search]. These logs are _append only_, you **cannot** redact this information.
You could use a [wildcard certificate][wildcard-cert]. This avoids accidentally leaking information to the internet, but keep in mind the [potential security risks][security::wildcard-cert] of wildcard certs.
## Let's Encrypt (Recommended) ## Let's Encrypt (Recommended)
To enable Let's Encrypt for `docker-mailserver`, you have to: To enable _Let's Encrypt_ for `docker-mailserver`, you have to:
- Get your certificate using [letsencrypt client](https://github.com/letsencrypt/letsencrypt) 1. Get your certificate using the _Let's Encrypt_ client [Certbot][certbot::github].
- Add an environment variable `SSL_TYPE` with value `letsencrypt` (see [`docker-compose.yml`][github-file-compose]) 2. For your `docker-mailserver` container:
- Mount your whole `letsencrypt` folder to `/etc/letsencrypt`
- The certs folder name located in `letsencrypt/live/` must be the `fqdn` of your container responding to the `hostname` command. The `fqdn` (full qualified domain name) inside the docker container is built combining the `hostname` and `domainname` values of the `docker-compose` file, eg: 1. Add the environment variable `SSL_TYPE=letsencrypt`.
2. Mount [your local `letsencrypt` folder][certbot::certs-storage] as a volume to `/etc/letsencrypt`.
You don't have to do anything else. Enjoy!
!!! note
`/etc/letsencrypt/live` stores provisioned certificates in individual folders named by their FQDN (_Fully Qualified Domain Name_). `docker-mailserver` looks for it's certificate folder via the `hostname` command. The FQDN inside the docker container is derived from the `--hostname` and `--domainname` options.
!!! example
Add these additions to the `mailserver` service in your [`docker-compose.yml`][github-file-compose]:
```yaml ```yaml
services: services:
mailserver: mailserver:
# For the FQDN 'mail.example.com':
hostname: mail hostname: mail
domainname: example.com domainname: example.com
fqdn: mail.example.com environment:
- SSL_TYPE=letsencrypt
volumes:
- /etc/letsencrypt:/etc/letsencrypt
``` ```
You don't have anything else to do. Enjoy. ### Example using Docker for _Let's Encrypt_
### Example using Docker for Let's Encrypt - Certbot provisions certificates to `/etc/letsencrypt`. Add a volume to store these, so that they can later be accessed by `docker-mailserver` container.
- You may also want to persist Certbot [logs][certbot::log-rotation], just in case you need to troubleshoot.
1. Make a directory to store your letsencrypt logs and configs. In my case: 1. Getting a certificate is this simple! (_Referencing: [Certbot docker instructions][certbot::docker] and [`certonly --standalone` mode][certbot::standalone]_):
```sh
mkdir -p /home/ubuntu/docker/letsencrypt
cd /home/ubuntu/docker/letsencrypt
```
2. Now get the certificate (modify `mail.example.com`) and following the certbot instructions.
3. This will need access to port 80 from the internet, adjust your firewall if needed:
```sh ```sh
# Change `mail.example.com` below to your own FQDN.
# Requires access to port 80 from the internet, adjust your firewall if needed.
docker run --rm -it \ docker run --rm -it \
-v $PWD/log/:/var/log/letsencrypt/ \ -v "${PWD}/docker-data/certbot/certs/:/etc/letsencrypt/" \
-v $PWD/etc/:/etc/letsencrypt/ \ -v "${PWD}/docker-data/certbot/logs/:/var/log/letsencrypt/" \
-p 80:80 \ -p 80:80 \
certbot/certbot certonly --standalone -d mail.example.com certbot/certbot certonly --standalone -d mail.example.com
``` ```
4. You can now mount `/home/ubuntu/docker/letsencrypt/etc/` in `/etc/letsencrypt` of `docker-mailserver`. 2. Add a volume for `docker-mailserver` that maps the _local `certbot/certs/` folder_ to the container path `/etc/letsencrypt/`.
3. The certificate setup is complete, but remember _it will expire_. Consider automating renewals.
To renew your certificate just run (this will need access to port 443 from the internet, adjust your firewall if needed): !!! tip "Renewing Certificates"
When running the above `certonly --standalone` snippet again, the existing certificate is renewed if it would expire within 30 days.
Alternatively, Certbot can look at all the certificates it manages, and only renew those nearing their expiry via the [`renew` command][certbot::renew]:
```sh ```sh
# This will need access to port 443 from the internet, adjust your firewall if needed.
docker run --rm -it \ docker run --rm -it \
-v $PWD/log/:/var/log/letsencrypt/ \ -v "${PWD}/docker-data/certbot/certs/:/etc/letsencrypt/" \
-v $PWD/etc/:/etc/letsencrypt/ \ -v "${PWD}/docker-data/certbot/logs/:/var/log/letsencrypt/" \
-p 80:80 \ -p 80:80 \
-p 443:443 \ -p 443:443 \
certbot/certbot renew certbot/certbot renew
``` ```
### Example using Docker, `nginx-proxy` and `letsencrypt-nginx-proxy-companion` This process can also be [automated via _cron_ or _systemd timers_][certbot::automated-renewal].
If you are running a web server already, it is non-trivial to generate a Let's Encrypt certificate for your `docker-mailserver` using `certbot`, because port 80 is already occupied. In the following example, we show how `docker-mailserver` can be run alongside the docker containers `nginx-proxy` and `letsencrypt-nginx-proxy-companion`. !!! note "Using a different ACME CA"
There are several ways to start `nginx-proxy` and `letsencrypt-nginx-proxy-companion`. Any method should be suitable here. Certbot does support [alternative certificate providers via the `--server`][certbot::custom-ca] option. In most cases you'll want to use the default _Let's Encrypt_.
For example start `nginx-proxy` as in the `letsencrypt-nginx-proxy-companion` [documentation](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion): ### Example using `nginx-proxy` and `acme-companion` with Docker
```sh If you are running a web server already, port 80 will be in use which Certbot requires. You could use the [Certbot `--webroot`][certbot::webroot] feature, but it is more common to leverage a _reverse proxy_ that manages the provisioning and renewal of certificates for your services automatically.
docker run --detach \
In the following example, we show how `docker-mailserver` can be run alongside the docker containers [`nginx-proxy`][nginx-proxy::github] and [`acme-companion`][acme-companion::github] (_Referencing: [`acme-companion` documentation][acme-companion::docs]_):
1. Start the _reverse proxy_ (`nginx-proxy`):
```sh
docker run --detach \
--name nginx-proxy \ --name nginx-proxy \
--restart always \ --restart always \
--publish 80:80 \ --publish 80:80 \
--publish 443:443 \ --publish 443:443 \
--volume /server/letsencrypt/etc:/etc/nginx/certs:ro \ --volume "${PWD}/docker-data/nginx-proxy/html/:/usr/share/nginx/html/" \
--volume /etc/nginx/vhost.d \ --volume "${PWD}/docker-data/nginx-proxy/vhost.d/:/etc/nginx/vhost.d/" \
--volume /usr/share/nginx/html \ --volume "${PWD}/docker-data/acme-companion/certs/:/etc/nginx/certs/:ro" \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \ --volume '/var/run/docker.sock:/tmp/docker.sock:ro' \
jwilder/nginx-proxy nginxproxy/nginx-proxy
``` ```
Then start `nginx-proxy-letsencrypt`: 2. Then start the _certificate provisioner_ (`acme-companion`), which will provide certificates to `nginx-proxy`:
```sh ```sh
docker run --detach \ # Inherit `nginx-proxy` volumes via `--volumes-from`, but make `certs/` writeable:
--name nginx-proxy-letsencrypt \ docker run --detach \
--name nginx-proxy-acme \
--restart always \ --restart always \
--volume /server/letsencrypt/etc:/etc/nginx/certs:rw \
--volumes-from nginx-proxy \ --volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \ --volume "${PWD}/docker-data/acme-companion/certs/:/etc/nginx/certs/:rw" \
jrcs/letsencrypt-nginx-proxy-companion --volume "${PWD}/docker-data/acme-companion/acme-state/:/etc/acme.sh/" \
``` --volume '/var/run/docker.sock:/var/run/docker.sock:ro' \
--env 'DEFAULT_EMAIL=admin@example.com' \
nginxproxy/acme-companion
```
Start the rest of your web server containers as usual. 3. Start the rest of your web server containers as usual.
Start another container for your `mail.example.com`. This will generate a Let's Encrypt certificate for your domain, which can be used by `docker-mailserver`. It will also run a web server on port 80 at that address: 4. Start a _dummy container_ to provision certificatess for your FQDN (eg: `mail.example.com`). `acme-companion` will detect the container and generate a _Let's Encrypt_ certificate for your domain, which can be used by `docker-mailserver`:
```sh ```sh
docker run -d \ docker run --detach \
--name webmail \ --name webmail \
-e "VIRTUAL_HOST=mail.example.com" \ --env 'VIRTUAL_HOST=mail.example.com' \
-e "LETSENCRYPT_HOST=mail.example.com" \ --env 'LETSENCRYPT_HOST=mail.example.com' \
-e "LETSENCRYPT_EMAIL=admin@example.com" \ --env 'LETSENCRYPT_EMAIL=admin@example.com' \
library/nginx nginx
``` ```
You may want to add `-e LETSENCRYPT_TEST=true` to the above while testing to avoid the Let's Encrypt certificate generation rate limits. You may want to add `--env LETSENCRYPT_TEST=true` to the above while testing, to avoid the _Let's Encrypt_ certificate generation rate limits.
Make sure your mount path to the letsencrypt certificates is correct. Edit your `/path/to/mailserver/docker-compose.yml` for the `mailserver` service to have volumes added like the example below: 5. Make sure your mount path to the `letsencrypt` certificates directory is correct. Edit your `docker-compose.yml` for the `mailserver` service to have volumes added like below:
```yaml ```yaml
volumes: volumes:
- ./docker-data/dms/mail-data/:/var/mail/ - ./docker-data/dms/mail-data/:/var/mail/
- ./docker-data/dms/mail-state/:/var/mail-state/ - ./docker-data/dms/mail-state/:/var/mail-state/
- ./docker-data/dms/config/:/tmp/docker-mailserver/ - ./docker-data/dms/config/:/tmp/docker-mailserver/
- /server/letsencrypt/etc:/etc/letsencrypt/live - ./docker-data/acme-companion/certs/:/etc/letsencrypt/live/:ro
```
Then from the `docker-compose.yml` directory, run: `docker-compose up -d mailserver`.
### Example using Docker, `nginx-proxy` and `letsencrypt-nginx-proxy-companion` with `docker-compose`
The following `docker-compose.yml` is the basic setup you need for using `letsencrypt-nginx-proxy-companion`. It is mainly derived from its own wiki/documenation.
???+ example "Example Code"
```yaml
version: "2"
services:
nginx:
image: nginx
container_name: nginx
ports:
- 80:80
- 443:443
volumes:
- /mnt/data/nginx/htpasswd:/etc/nginx/htpasswd
- /mnt/data/nginx/conf.d:/etc/nginx/conf.d
- /mnt/data/nginx/vhost.d:/etc/nginx/vhost.d
- /mnt/data/nginx/html:/usr/share/nginx/html
- /mnt/data/nginx/certs:/etc/nginx/certs:ro
networks:
- proxy-tier
restart: always
nginx-gen:
image: jwilder/docker-gen
container_name: nginx-gen
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /mnt/data/nginx/templates/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
volumes_from:
- nginx
entrypoint: /usr/local/bin/docker-gen -notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
restart: always
letsencrypt-nginx-proxy-companion:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: letsencrypt-companion
volumes_from:
- nginx
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /mnt/data/nginx/certs:/etc/nginx/certs:rw
environment:
- NGINX_DOCKER_GEN_CONTAINER=nginx-gen
- DEBUG=false
restart: always
networks:
proxy-tier:
external:
name: nginx-proxy
``` ```
The second part of the setup is the `docker-mailserver` container. So, in another folder, create another `docker-compose.yml` with the following content (Removed all ENV variables for this example): 6. Then from the `docker-compose.yml` project directory, run: `docker-compose up -d mailserver`.
???+ example "Example Code" ### Example using `nginx-proxy` and `acme-companion` with `docker-compose`
The following example is the [basic setup][acme-companion::basic-setup] you need for using `nginx-proxy` and `acme-companion` with `docker-mailserver` (_Referencing: [`acme-companion` documentation][acme-companion::docs]_):
???+ example "Example: `docker-compose.yml`"
You should have an existing `docker-compose.yml` with a `mailserver` service. Below are the modifications to add for integrating with `nginx-proxy` and `acme-companion` services:
```yaml ```yaml
version: '3.8' version: '3.8'
services: services:
# Add the following `environment` and `volumes` to your existing `mailserver` service:
mailserver: mailserver:
image: docker.io/mailserver/docker-mailserver:latest
container_name: mailserver
hostname: mail
domainname: example.com
ports:
- "25:25"
- "143:143"
- "465:465"
- "587:587"
- "993:993"
volumes:
- ./docker-data/dms/mail-data/:/var/mail/
- ./docker-data/dms/mail-state/:/var/mail-state/
- ./docker-data/dms/config/:/tmp/docker-mailserver/
- ./docker-data/nginx-proxy/certs/:/etc/letsencrypt/live/:ro
cap_add:
- NET_ADMIN
- SYS_PTRACE
restart: always
cert-companion:
image: nginx
environment: environment:
- "VIRTUAL_HOST=" # SSL_TYPE: Uses the `letsencrypt` method to find mounted certificates.
- "VIRTUAL_NETWORK=nginx-proxy" # VIRTUAL_HOST: The FQDN that `nginx-proxy` will configure itself to handle for HTTP[S] connections.
- "LETSENCRYPT_HOST=" # LETSENCRYPT_HOST: The FQDN for a certificate that `acme-companion` will provision and renew.
- "LETSENCRYPT_EMAIL=" - SSL_TYPE=letsencrypt
networks: - VIRTUAL_HOST=mail.example.com
- proxy-tier - LETSENCRYPT_HOST=mail.example.com
restart: always volumes:
- ./docker-data/acme-companion/certs/:/etc/letsencrypt/live/:ro
networks: # If you don't yet have your own `nginx-proxy` and `acme-companion` setup,
proxy-tier: # here is an example you can use:
external: reverse-proxy:
name: nginx-proxy image: nginxproxy/nginx-proxy
container_name: nginx-proxy
restart: always
ports:
# Port 80: Required for HTTP-01 challenges to `acme-companion`.
# Port 443: Only required for containers that need access over HTTPS. TLS-ALPN-01 challenge not supported.
- "80:80"
- "443:443"
volumes:
# `certs/`: Managed by the `acme-companion` container (_read-only_).
# `docker.sock`: Required to interact with containers via the Docker API.
# `dhparam`: A named data volume to prevent `nginx-proxy` creating an anonymous volume each time.
- ./docker-data/nginx-proxy/html/:/usr/share/nginx/html/
- ./docker-data/nginx-proxy/vhost.d/:/etc/nginx/vhost.d/
- ./docker-data/acme-companion/certs/:/etc/nginx/certs/:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
- dhparam:/etc/nginx/dhparam
acme-companion:
image: nginxproxy/acme-companion
container_name: nginx-proxy-acme
restart: always
environment:
# Only docker-compose v2 supports: `volumes_from: [nginx-proxy]`,
# reference the _reverse-proxy_ `container_name` here:
- NGINX_PROXY_CONTAINER=nginx-proxy
volumes:
# `html/`: Write ACME HTTP-01 challenge files that `nginx-proxy` will serve.
# `vhost.d/`: To enable web access via `nginx-proxy` to HTTP-01 challenge files.
# `certs/`: To store certificates and private keys.
# `acme-state/`: To persist config and state for the ACME provisioner (`acme.sh`).
# `docker.sock`: Required to interact with containers via the Docker API.
- ./docker-data/nginx-proxy/html/:/usr/share/nginx/html/
- ./docker-data/nginx-proxy/vhost.d/:/etc/nginx/vhost.d/
- ./docker-data/acme-companion/certs/:/etc/nginx/certs/:rw
- ./docker-data/acme-companion/acme-state/:/etc/acme.sh/
- /var/run/docker.sock:/var/run/docker.sock:ro
# Once `nginx-proxy` fixes their Dockerfile, this named data volume can be removed from docs.
# Users can opt for a local bind mount volume like all others if they prefer, but this volume
# is only intended to be temporary.
volumes:
dhparam:
``` ```
`docker-mailserver` needs to have the letsencrypt certificate folder mounted as a volume. No further changes are needed. The second container is a dummy-sidecar we need, because the mail-container do not expose any web-ports. Set your ENV variables as you need. (`VIRTUAL_HOST` and `LETSENCRYPT_HOST` are mandandory, see documentation) !!! tip "Optional ENV vars worth knowing about"
### Example using the Let's Encrypt Certificates on a Synology NAS [Per container ENV][acme-companion::env-container] that `acme-companion` will detect to override default provisioning settings:
- `LETSENCRYPT_TEST=true`: _Recommended during initial setup_. Otherwise the default production endpoint has a [rate limit of 5 duplicate certificates per week][letsencrypt::limits]. Overrides `ACME_CA_URI` to use the _Let's Encrypt_ staging endpoint.
- `LETSENCRYPT_EMAIL`: For when you don't use `DEFAULT_EMAIL` on `acme-companion`, or want to assign a different email contact for this container.
- `LETSENCRYPT_KEYSIZE`: Allows you to configure the type (RSA or ECDSA) and size of the private key for your certificate. Default is RSA 4096.
- `LETSENCRYPT_RESTART_CONTAINER=true`: When the certificate is renewed, the entire container will be restarted to ensure the new certificate is used.
[`acme-companion` ENV for default settings][acme-companion::env-config] that apply to all containers using `LETSENCRYPT_HOST`:
- `DEFAULT_EMAIL`: An email address that the CA (_eg: Let's Encrypt_) can contact you about expiring certificates, failed renewals, or for account recovery. You may want to use an email address not handled by your mail-server to ensure deliverability in the event your mail-server breaks.
- `CERTS_UPDATE_INTERVAL`: If you need to adjust the frequency to check for renewals. 3600 seconds (1 hour) by default.
- `DEBUG=1`: Should be helpful when [troubleshooting provisioning issues][acme-companion::troubleshooting] from `acme-companion` logs.
- `ACME_CA_URI`: Useful in combination with `CA_BUNDLE` to use a private CA. To change the default _Let's Encrypt_ endpoint to the staging endpoint, use `https://acme-staging-v02.api.letsencrypt.org/directory`.
- `CA_BUNDLE`: If you want to use a private CA instead of _Let's Encrypt_.
!!! tip "Alternative to required ENV on `mailserver` service"
While you will still need both `nginx-proxy` and `acme-companion` containers, you can manage certificates without adding ENV vars to containers. Instead the ENV is moved into a file and uses the `acme-companion` feature [Standalone certificates][acme-companion::standalone].
This requires adding another shared volume between `nginx-proxy` and `acme-companion`:
```yaml
services:
reverse-proxy:
volumes:
- ./docker-data/nginx-proxy/conf.d/:/etc/nginx/conf.d/
acme-companion:
volumes:
- ./docker-data/nginx-proxy/conf.d/:/etc/nginx/conf.d/
- ./docker-data/acme-companion/standalone.sh:/app/letsencrypt_user_data:ro
```
`acme-companion` mounts a shell script (`standalone.sh`), which defines variables to customize certificate provisioning:
```sh
# A list IDs for certificates to provision:
LETSENCRYPT_STANDALONE_CERTS=('mail')
# Each ID inserts itself into the standard `acme-companion` supported container ENV vars below.
# The LETSENCRYPT_<ID>_HOST var is a list of FQDNs to provision a certificate for as the SAN field:
LETSENCRYPT_mail_HOST=('mail.example.com')
# Optional variables:
LETSENCRYPT_mail_TEST=true
LETSENCRYPT_mail_EMAIL='admin@example.com'
# RSA-4096 => `4096`, ECDSA-256 => `ec-256`:
LETSENCRYPT_mail_KEYSIZE=4096
```
Unlike with the equivalent ENV for containers, [changes to this file will **not** be detected automatically][acme-companion::standalone-changes]. You would need to wait until the next renewal check by `acme-companion` (_every hour by default_), restart `acme-companion`, or [manually invoke the _service loop_][acme-companion::service-loop]:
`#!bash docker exec nginx-proxy-acme /app/signal_le_service`
### Example using _Let's Encrypt_ Certificates with a _Synology NAS_
Version 6.2 and later of the Synology NAS DSM OS now come with an interface to generate and renew letencrypt certificates. Navigation into your DSM control panel and go to Security, then click on the tab Certificate to generate and manage letsencrypt certificates. Version 6.2 and later of the Synology NAS DSM OS now come with an interface to generate and renew letencrypt certificates. Navigation into your DSM control panel and go to Security, then click on the tab Certificate to generate and manage letsencrypt certificates.
@ -687,3 +743,30 @@ Despite this, if you must use non-standard DH parameters or you would like to sw
[ietf::rfc::ffdhe]: https://datatracker.ietf.org/doc/html/rfc7919 [ietf::rfc::ffdhe]: https://datatracker.ietf.org/doc/html/rfc7919
[ffdhe4096-src]: https://github.com/internetstandards/dhe_groups [ffdhe4096-src]: https://github.com/internetstandards/dhe_groups
[dh-avoid-selfgenerated]: https://crypto.stackexchange.com/questions/29926/what-diffie-hellman-parameters-should-i-use [dh-avoid-selfgenerated]: https://crypto.stackexchange.com/questions/29926/what-diffie-hellman-parameters-should-i-use
[certificate-transparency]: https://certificate.transparency.dev/
[ct-search]: https://crt.sh/
[wildcard-cert]: https://en.wikipedia.org/wiki/Wildcard_certificate#Examples
[security::wildcard-cert]: https://gist.github.com/joepie91/7e5cad8c0726fd6a5e90360a754fc568
[letsencrypt::limits]: https://letsencrypt.org/docs/rate-limits/
[certbot::github]: https://github.com/certbot/certbot
[certbot::certs-storage]: https://certbot.eff.org/docs/using.html#where-are-my-certificates
[certbot::log-rotation]: https://certbot.eff.org/docs/using.html#log-rotation
[certbot::docker]: https://certbot.eff.org/docs/install.html#running-with-docker
[certbot::standalone]: https://certbot.eff.org/docs/using.html#standalone
[certbot::renew]: https://certbot.eff.org/docs/using.html#renewing-certificates
[certbot::automated-renewal]: https://certbot.eff.org/docs/using.html#automated-renewals
[certbot::custom-ca]: https://certbot.eff.org/docs/using.htmlchanging-the-acme-server
[certbot::webroot]: https://certbot.eff.org/docs/using.html#webroot
[nginx-proxy::github]: https://github.com/nginx-proxy/nginx-proxy
[acme-companion::github]: https://github.com/nginx-proxy/acme-companion
[acme-companion::docs]: https://github.com/nginx-proxy/acme-companion/blob/main/docs
[acme-companion::basic-setup]: https://github.com/nginx-proxy/acme-companion#basic-usage-with-the-nginx-proxy-container
[acme-companion::env-container]: https://github.com/nginx-proxy/acme-companion/blob/main/docs/Let's-Encrypt-and-ACME.md
[acme-companion::env-config]: https://github.com/nginx-proxy/acme-companion/blob/main/docs/Container-configuration.md
[acme-companion::troubleshooting]: https://github.com/nginx-proxy/acme-companion/blob/main/docs/Invalid-authorizations.md
[acme-companion::standalone]: https://github.com/nginx-proxy/acme-companion/blob/main/docs/Standalone-certificates.md
[acme-companion::standalone-changes]: https://github.com/nginx-proxy/acme-companion/blob/main/docs/Standalone-certificates.md#picking-up-changes-to-letsencrypt_user_data
[acme-companion::service-loop]: https://github.com/nginx-proxy/acme-companion/blob/main/docs/Container-utilities.md