1
0
Fork 0

[skip ci] Documentation rework (#493)

This commit is contained in:
Nicolas Duchon 2019-01-11 18:58:49 +01:00 committed by GitHub
parent 407c7c4467
commit cff8e96da6
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 862 additions and 205 deletions

View File

@ -1,4 +1,5 @@
+.*
+docs
+go
+test
+LICENSE

280
README.md
View File

@ -4,239 +4,109 @@
[![Docker stars](https://img.shields.io/docker/stars/jrcs/letsencrypt-nginx-proxy-companion.svg)](https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion "Click to view the image on Docker Hub")
[![Docker pulls](https://img.shields.io/docker/pulls/jrcs/letsencrypt-nginx-proxy-companion.svg)](https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion "Click to view the image on Docker Hub")
letsencrypt-nginx-proxy-companion is a lightweight companion container for the [nginx-proxy](https://github.com/jwilder/nginx-proxy). It allows the creation/renewal of Let's Encrypt certificates automatically. See [Let's Encrypt section](#lets-encrypt) for configuration details.
**letsencrypt-nginx-proxy-companion** is a lightweight companion container for [**nginx-proxy**](https://github.com/jwilder/nginx-proxy).
It handles the automated creation, renewal and use of Let's Encrypt certificates for proxyed Docker containers.
Please note that [letsencrypt-nginx-proxy-companion does not work with ACME v2 endpoints yet](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/issues/319).
### Features:
* Automatic creation/renewal of Let's Encrypt certificates using original nginx-proxy container.
* Support creation of Multi-Domain ([SAN](https://www.digicert.com/subject-alternative-name.htm)) Certificates.
* Automatic creation of a Strong Diffie-Hellman Group (for having an A+ Rate on the [Qualsys SSL Server Test](https://www.ssllabs.com/ssltest/)).
* Automatic creation of a self-signed [default certificate](https://github.com/jwilder/nginx-proxy#how-ssl-support-works) if a user-provided one can't be found.
* Automated creation/renewal of Let's Encrypt (or other ACME CAs) certificates using [**simp_le**](https://github.com/zenhack/simp_le).
* Let's Encrypt / ACME domain validation through `http-01` challenge only.
* Automated update and reload of nginx config on certificate creation/renewal.
* Support creation of Multi-Domain (SAN) Certificates.
* Creation of a Strong Diffie-Hellman Group at startup.
* Work with all versions of docker.
![schema](./schema.png)
### Requirements:
* Your host **must** be publicly reachable on **both** port `80` and `443`.
* Check your firewall rules and **do not attempt to block port `80`** as that will prevent `http-01` challenges from completing.
* For the same reason, you can't use nginx-proxy's [`HTTPS_METHOD=nohttp`](https://github.com/jwilder/nginx-proxy#how-ssl-support-works).
* The (sub)domains you want to issue certificates for must correctly resolve to the host.
* Your DNS provider must [answers correctly to CAA record requests](https://letsencrypt.org/docs/caa/).
* If your (sub)domains have AAAA records set, the host must be publicly reachable over IPv6 on port `80` and `443`.
#### Usage
![schema](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/blob/master/schema.png)
To use it with original [nginx-proxy](https://github.com/jwilder/nginx-proxy) container you must declare 3 writable volumes from the [nginx-proxy](https://github.com/jwilder/nginx-proxy) container:
* `/etc/nginx/certs` to create/renew Let's Encrypt certificates
* `/etc/nginx/vhost.d` to change the configuration of vhosts (needed by Let's Encrypt)
* `/usr/share/nginx/html` to write challenge files.
## Basic usage (with the nginx-proxy container)
Three writable volumes must be declared on the **nginx-proxy** container so that they can be shared with the **letsencrypt-nginx-proxy-companion** container:
* `/etc/nginx/certs` to store certificates, private keys and ACME account keys (readonly for the **nginx-proxy** container).
* `/etc/nginx/vhost.d` to change the configuration of vhosts (required so the CA may access `http-01` challenge files).
* `/usr/share/nginx/html` to write `http-01` challenge files.
Example of use:
* First start nginx with the 3 volumes declared:
```bash
$ docker run -d -p 80:80 -p 443:443 \
### Step 1 - nginx-proxy
Start **nginx-proxy** with the three additional volumes declared:
```shell
$ docker run --detach \
--name nginx-proxy \
-v /path/to/certs:/etc/nginx/certs:ro \
-v /etc/nginx/vhost.d \
-v /usr/share/nginx/html \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy \
--publish 80:80 \
--publish 443:443 \
--volume /etc/nginx/certs \
--volume /etc/nginx/vhost.d \
--volume /usr/share/nginx/html \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \
jwilder/nginx-proxy
```
The "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy" label is needed so that the letsencrypt container knows which nginx proxy container to use.
* Second start this container:
```bash
$ docker run -d \
-v /path/to/certs:/etc/nginx/certs:rw \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
Binding the host docker socket (`/var/run/docker.sock`) inside the container to `/tmp/docker.sock` is a requirement of **ninx-proxy**.
### Step 2 - letsencrypt-nginx-proxy-companion
Start the **letsencrypt-nginx-proxy-companion** container, getting the volumes from **nginx-proxy** with `--volumes-from`:
```shell
$ docker run --detach \
--name nginx-proxy-letsencrypt \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
jrcs/letsencrypt-nginx-proxy-companion
```
Then start any containers you want proxied with a env var `VIRTUAL_HOST=subdomain.youdomain.com`
The host docker socket has to be bound inside this container too, this time to `/var/run/docker.sock`.
$ docker run -e "VIRTUAL_HOST=foo.bar.com" ...
### Step 3 - proxyed container(s)
The containers being proxied must [expose](https://docs.docker.com/reference/run/#expose-incoming-ports) 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`. See [nginx-proxy](https://github.com/jwilder/nginx-proxy) for more informations. To generate automatically Let's Encrypt certificates see next section.
Once both **nginx-proxy** and **letsencrypt-nginx-proxy-companion** containers are up and running, start any container you want proxyed with environment variables `VIRTUAL_HOST` and `LETSENCRYPT_HOST` both set to the domain(s) your proxyed container is going to use.
#### Separate Containers
nginx proxy can also be run as two separate containers using the [jwilder/docker-gen](https://github.com/jwilder/docker-gen)
image and the official [nginx](https://hub.docker.com/_/nginx/) image.
[`VIRTUAL_HOST`](https://github.com/jwilder/nginx-proxy#usage) control proxying by **nginx-proxy** and `LETSENCRYPT_HOST` control certificate creation and SSL enabling by **letsencrypt-nginx-proxy-companion**.
You may want to do this to prevent having the docker socket bound to a publicly exposed container service (avoid to mount the docker socket in the nginx exposed container). It's better in a security point of view.
Certificates will only be issued for containers that have both `VIRTUAL_HOST` and `LETSENCRYPT_HOST` variables set to domain(s) that correctly resolve to the host, provided the host is publicly reachable.
To run nginx proxy as a separate container you'll need:
1) To mount the template file [nginx.tmpl](https://github.com/jwilder/nginx-proxy/blob/master/nginx.tmpl) into the docker-gen container. You can get the latest official [nginx.tmpl](https://github.com/jwilder/nginx-proxy/blob/master/nginx.tmpl) with a command like:
```bash
curl https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl > /path/to/nginx.tmpl
```
2) Use the `com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen` label on the docker-gen container, or explicitly set the `NGINX_DOCKER_GEN_CONTAINER` environment variable to the name or id of that container.
Examples:
* First start nginx (official image) with volumes:
```bash
$ docker run -d -p 80:80 -p 443:443 \
--name nginx \
-v /etc/nginx/conf.d \
-v /etc/nginx/vhost.d \
-v /usr/share/nginx/html \
-v /path/to/certs:/etc/nginx/certs:ro \
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy \
```shell
$ docker run --detach \
--name your-proxyed-app
--env "VIRTUAL_HOST=subdomain.yourdomain.tld" \
--env "LETSENCRYPT_HOST=subdomain.yourdomain.tld" \
--env "LETSENCRYPT_EMAIL=mail@yourdomain.tld" \
nginx
```
* Second start the docker-gen container with the shared volumes and the template file:
```bash
$ docker run -d \
--name nginx-gen \
--volumes-from nginx \
-v /path/to/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen \
jwilder/docker-gen \
-notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
Albeit **optional**, it is **recommended** to provide a valid email address through the `LETSENCRYPT_EMAIL` environment variable, so that Let's Encrypt can warn you about expiring certificates and allow you to recover your account.
The 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 proxyed container listen on and expose another port than the default `80`, you can force **nginx-proxy** to use this port with the [`VIRTUAL_PORT`](https://github.com/jwilder/nginx-proxy#multiple-ports) environment variable.
Example using [Grafana](https://hub.docker.com/r/grafana/grafana/) (expose and listen on port 3000):
```shell
$ docker run --detach \
--name grafana
--env "VIRTUAL_HOST=othersubdomain.yourdomain.tld" \
--env "VIRTUAL_PORT=3000" \
--env "LETSENCRYPT_HOST=othersubdomain.yourdomain.tld" \
--env "LETSENCRYPT_EMAIL=mail@yourdomain.tld" \
grafana/grafana
```
* Then start this container:
```bash
$ docker run -d \
--name nginx-letsencrypt \
--volumes-from nginx \
-v /path/to/certs:/etc/nginx/certs:rw \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
jrcs/letsencrypt-nginx-proxy-companion
```
Repeat [Step 3](#step-3---proxyed-containers) for any other container you want to proxy.
* Then start any containers to be proxied as described previously.
## Additional documentation
Note:
If the 3 containers are using static names, both labels `com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy` on nginx container and `com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen` on the docker-gen container can be removed.
The docker environment variables to be set on the letsencrypt container are:
* `NGINX_PROXY_CONTAINER` set to the name of the nginx container (here `nginx`)
* `NGINX_DOCKER_GEN_CONTAINER` set to the name of the docker-gen container (here `nginx-gen`)
Example:
```bash
$ docker run -d \
--name nginx-letsencrypt \
--volumes-from nginx \
-v /path/to/certs:/etc/nginx/certs:rw \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-e NGINX_DOCKER_GEN_CONTAINER=nginx-gen \
-e NGINX_PROXY_CONTAINER=nginx \
jrcs/letsencrypt-nginx-proxy-companion
```
#### Let's Encrypt
To use the Let's Encrypt service to automatically create a valid certificate for virtual host(s), declare the `LETSENCRYPT_HOST` environment variable in each to-be-proxied application containers.
The `LETSENCRYPT_HOST` variable most likely needs to be set to the same value as the `VIRTUAL_HOST` variable and must be publicly reachable domains. Specify multiple hosts with a comma delimiter.
##### Example:
```bash
$ docker run -d \
--name example-app \
-e "VIRTUAL_HOST=example.com,www.example.com,mail.example.com" \
-e "LETSENCRYPT_HOST=example.com,www.example.com,mail.example.com" \
-e "LETSENCRYPT_EMAIL=foo@bar.com" \
tutum/apache-php
```
**Note:** the `VIRTUAL_HOST` (and `LETSENCRYPT_HOST`) must be (a) reachable domain(s) for LetEncrypt to be able to validate the challenge and provide the certificate.
**Note on CAA**: 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](https://letsencrypt.org/docs/caa/). Let's Encrypt do not require that you set a CAA record on your domain, just that your DNS provider answers correctly.
**Note on IPv6**: If the domain or subdomain you want to issue certificate for has an AAAA record set, Let's Encrypt will favor challenge validation over IPv6. [There is an IPv6 to IPv4 fallback in place but Let's Encrypt cannot guarantee it'll work in every possible case](https://github.com/letsencrypt/boulder/issues/2770#issuecomment-340489871), so bottom line is **if you are not sure of both your host and your host's Docker reachability over IPv6, do not advertise an AAAA record** or LE challenge validation might fail.
The following environment variables are optional and parameterize the way the Let's Encrypt client works.
##### Contact address
The `LETSENCRYPT_EMAIL` variable must be a valid email and will be used by Let's Encrypt to warn you of impeding certificate expiration (should the automated renewal fail) or for account recovery. It is strongly advised to provide a valid contact address using this variable.
##### Private key size
The `LETSENCRYPT_KEYSIZE` variable determines the size of the requested key (in bit, defaults to 4096).
##### Multi-domain ([SAN](https://www.digicert.com/subject-alternative-name.htm)) certificates
If you want to create multi-domain ([SAN](https://www.digicert.com/subject-alternative-name.htm)) certificates add the base domain as the first domain of the `LETSENCRYPT_HOST` environment variable (see [the example](#example) above).
##### Test certificates
If you want to create test certificates that don't have the 5 certs/week/domain limits define the `LETSENCRYPT_TEST` environment variable with a value of `true` (in the containers where you request certificates with `LETSENCRYPT_HOST`). If you want to do this globally for all containers, set `ACME_CA_URI` as described below.
##### Automatic certificate renewal
Every hour (3600 seconds) the certificates are checked and per default every certificate that will expire in the next [30 days](https://github.com/zenhack/simp_le/blob/a8a8013c097910f8f3cce046f1077b41b745673b/simp_le.py#L73) (90 days / 3) is renewed.
If you want to manually set a different minimum validity for certificates, you can set the `LETSENCRYPT_MIN_VALIDIDTY` environment variable (in each container that defines the `LETSENCRYPT_HOST` variable) to the desired period in seconds.
Note that the possible values are internally capped at an upper bound of 7603200 (88 days) and a lower bound of 7200 (2 hours) as a security margin, considering that the Let's Encrypt CA does only issues certificates with a lifetime of [90 days](https://letsencrypt.org/2015/11/09/why-90-days.html) (upper bound), the rate limits imposed on certificate renewals are [5 per week](https://letsencrypt.org/docs/rate-limits/) (upper bound), and the fact that the certificates are checked and renewed accordingly every hour (lower bound).
##### Force certificates renewal
If needed, you can force a running letsencrypt-nginx-proxy-companion container to renew all certificates that are currently in use. Replace `nginx-letsencrypt` with the name of your letsencrypt-nginx-proxy-companion container in the following command:
```bash
$ docker exec nginx-letsencrypt /app/force_renew
```
##### Restart container on certificate renewal
Per default letsencrypt-nginx-proxy-companion only reloads the nginx-proxy container when new certificates are issued or renewed. But it may be desirable to use the certificates inside the containers for other purposes than HTTPS (e.g. FTPS Server), and that would require to also restart the containers using the certificates, whenever these certificates are renewed. This can be achieved by defining the `LETSENCRYPT_RESTART_CONTAINER` environment variable with a value of `true` for the containers that you want to be restarted on certificate renewal (and have the `LETSENCRYPT_HOST` variable set).
##### Show certificates informations
To display informations about your existing certificates, use the following command:
```bash
$ docker exec nginx-letsencrypt /app/cert_status
```
As for the forced renewal command, replace `nginx-letsencrypt` with the name of your letsencrypt-nginx-proxy-companion container.
##### ACME account keys
By default the container will save the first ACME account key created for each ACME API endpoint used, and will reuse it for all subsequent authorizations and issuances requests made to this endpoint. This behavior is enabled by default to avoid running into Let's Encrypt account [rate limits](https://letsencrypt.org/docs/rate-limits/).
For instance, when using the default Let's Encrypt production endpoint, the container will save the first account key created for this endpoint as `/etc/nginx/certs/accounts/acme-v01.api.letsencrypt.org/directory/default.json` and will reuse it for future requests made to this endpoint.
If required, you can use multiple accounts for the same ACME API endpoint by using the `LETSENCRYPT_ACCOUNT_ALIAS` environment variable on your proxyed container. This instruct the letsencrypt_nginx_proxy_companion container to look for an account key named after the provided alias instead of `default.json`. For example, `LETSENCRYPT_ACCOUNT_ALIAS=client1` will use the key named `client1.json` in the corresponding ACME API endpoint folder for this proxyed container (or will create it if it does not exists yet).
Please see the **One Account or Many?** paragraph on [Let's Encrypt Integration Guide](https://letsencrypt.org/docs/integration-guide/) for additional informations.
If you want to disable the account key reutilization entirely, you can set the environment variable `REUSE_ACCOUNT_KEYS` to `false` on the letsencrypt_nginx_proxy_companion container. This creates a new ACME registration with a corresponding account key for each new certificate issuance. Note that this won't create new account keys for certs already issued before `REUSE_ACCOUNT_KEYS` is set to `false`. This is not recommended unless you have specific reasons to do so.
#### Optional container environment variables
Optional letsencrypt-nginx-proxy-companion container environment variables for custom configuration.
* `ACME_CA_URI` - Directory URI for the CA ACME API endpoint (default: ``https://acme-v01.api.letsencrypt.org/directory``). If you set it's value to `https://acme-staging.api.letsencrypt.org/directory` letsencrypt will use test servers that don't have the 5 certs/week/domain limits. You can also create test certificates per container (see [let's encrypt test certificates](#test-certificates))
For example
```bash
$ docker run -d \
-e "ACME_CA_URI=https://acme-staging.api.letsencrypt.org/directory" \
-v /path/to/certs:/etc/nginx/certs:rw \
--volumes-from nginx-proxy \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
jrcs/letsencrypt-nginx-proxy-companion
```
* `DEBUG` - Set it to `true` to enable debugging of the entrypoint script and generation of LetsEncrypt certificates, which could help you pin point any configuration issues.
* `REUSE_ACCOUNT_KEYS` - Set it to `false` to disable the account keys reutilization (see [ACME account keys](#acme-account-keys)).
* `REUSE_PRIVATE_KEYS` - Set it to `true` to make simp_le reuse previously generated private key for each certificate instead of creating a new one on certificate renewal. Recommended if you intend to use HPKP.
* The `com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy` label - set this label on the nginx-proxy container to tell the docker-letsencrypt-nginx-proxy-companion container to use it as the proxy.
* The `com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen` label - set this label on the docker-gen container to tell the docker-letsencrypt-nginx-proxy-companion container to use it as the docker-gen when it's split from nginx (separate containers).
* `DHPARAM_BITS` - Change the size of the Diffie-Hellman key generated by the container from the default value of 2048 bits. For example `-e DHPARAM_BITS=1024` to support some older clients like Java 6 and 7.
#### Examples:
If you want other examples how to use this container, look at:
* [Evert Ramos's Examples](https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion) - using docker-compose version '3'
* [Karl Fathi's Examples](https://github.com/fatk/docker-letsencrypt-nginx-proxy-companion-examples)
* [More examples from Karl](https://github.com/pixelfordinner/pixelcloud-docker-apps/tree/master/nginx-proxy)
* [George Ilyes' Examples](https://github.com/gilyes/docker-nginx-letsencrypt-sample)
* [Dmitry's simple docker-compose example](https://github.com/dmitrym0/simple-lets-encrypt-docker-compose-sample)
* [Radek's docker-compose jenkins example](https://github.com/dataminelab/docker-jenkins-nginx-letsencrypt)
Please check the [docs section](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/tree/master/docs) or the [project's wiki](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/wiki).

81
docs/Advanced-usage.md Normal file
View File

@ -0,0 +1,81 @@
## Advanced usage (with the nginx and docker-gen containers)
**nginx-proxy** can also be run as two separate containers using the [jwilder/**docker-gen**](https://github.com/jwilder/docker-gen) image and the official [**nginx**](https://hub.docker.com/_/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).
**NOTE**: The first time this container is launched in a three container setup, it will generates a new 2048 bits Diffie-Hellman parameters file. This process can take up to several minutes to complete on lower end hosts, and certificates creation won't start before that (be patient).
Please read and try [basic usage](./Basic-usage.md) before using the three containers setup. In addition to the steps described there, running **nginx-proxy** as two separate containers with **letsencrypt-nginx-proxy-companion** requires the following:
1) Download and mount the template file [nginx.tmpl](https://github.com/jwilder/nginx-proxy/blob/master/nginx.tmpl) into the **docker-gen** container. You can get the nginx.tmpl file with a command like:
```
curl https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl > /path/to/nginx.tmpl
```
2) Use the `com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen` label on the **docker-gen** container, or explicitly set the `NGINX_DOCKER_GEN_CONTAINER` environment variable on the **letsencrypt-nginx-proxy-companion** container to the name or id of the **docker-gen** container (we'll use the later method in the example).
3) Declare `/etc/nginx/conf.d` as 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)](https://hub.docker.com/_/nginx/) with the required volumes:
```shell
$ docker run --detach \
--name nginx-proxy \
--publish 80:80 \
--publish 443:443 \
--name nginx \
--volume /etc/nginx/conf.d \
--volume /etc/nginx/vhost.d \
--volume /usr/share/nginx/html \
--volume /etc/nginx/certs \
nginx
```
### Step 2 - docker-gen
* Start the **docker-gen** container with the shared volumes (with `--volume-from`), the template file and the docker socket:
```shell
$ 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 \
jwilder/docker-gen \
-notify-sighup nginx-proxy -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
```
Note that you must pass the exact name of the **nginx** container to **docker-gen** `-notify-sighup` argument (here `nginx-proxy`).
### Step 3 - letsencrypt-nginx-proxy-companion
* Start the **letsencrypt-nginx-proxy-companion** container with the `NGINX_DOCKER_GEN_CONTAINER` environment variable correctly set:
```shell
$ docker run --detach \
--name nginx-proxy-letsencrypt \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--env "NGINX_DOCKER_GEN_CONTAINER=nginx-proxy-gen" \
jrcs/letsencrypt-nginx-proxy-companion
```
### Step 4 - proxyed container(s)
* Once the three containers are up, start any containers to be proxied as described in [basic usage](./Basic-usage.md).
```shell
$ docker run --detach \
--name your-proxyed-app
--env "VIRTUAL_HOST=subdomain.yourdomain.tld" \
--env "LETSENCRYPT_HOST=subdomain.yourdomain.tld" \
--env "LETSENCRYPT_EMAIL=mail@yourdomain.tld" \
nginx
```
If you are experiencing issues with this setup, fall back to the [basic setup](./Basic-usage.md). The advanced setup is not meant to be obligatory.

78
docs/Basic-usage.md Normal file
View File

@ -0,0 +1,78 @@
## Basic usage (with the nginx-proxy container)
Three writable volumes must be declared on the **nginx-proxy** container so that they can be shared with the **letsencrypt-nginx-proxy-companion** container:
* `/etc/nginx/certs` to store certificates, private keys and ACME account keys (readonly for the **nginx-proxy** container).
* `/etc/nginx/vhost.d` to change the configuration of vhosts (required so the CA may access `http-01` challenge files).
* `/usr/share/nginx/html` to write `http-01` challenge files.
Example of use:
### Step 1 - nginx-proxy
Start **nginx-proxy** with the three additional volumes declared:
```shell
$ docker run --detach \
--name nginx-proxy \
--publish 80:80 \
--publish 443:443 \
--volume /etc/nginx/certs \
--volume /etc/nginx/vhost.d \
--volume /usr/share/nginx/html \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \
jwilder/nginx-proxy
```
Binding the host docker socket (`/var/run/docker.sock`) inside the container to `/tmp/docker.sock` is a requirement of **ninx-proxy**.
### Step 2 - letsencrypt-nginx-proxy-companion
Start the **letsencrypt-nginx-proxy-companion** container, getting the volumes from **nginx-proxy** with `--volumes-from`:
```shell
$ docker run --detach \
--name nginx-proxy-letsencrypt \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
jrcs/letsencrypt-nginx-proxy-companion
```
The host docker socket has to be bound inside this container too, this time to `/var/run/docker.sock`.
### Step 3 - proxyed container(s)
Once both **nginx-proxy** and **letsencrypt-nginx-proxy-companion** containers are up and running, start any container you want proxyed with environment variables `VIRTUAL_HOST` and `LETSENCRYPT_HOST` both set to the domain(s) your proxyed container is going to use.
[`VIRTUAL_HOST`](https://github.com/jwilder/nginx-proxy#usage) control proxying by **nginx-proxy** and `LETSENCRYPT_HOST` control certificate creation and SSL enabling by **letsencrypt-nginx-proxy-companion**.
Certificates will only be issued for containers that have both `VIRTUAL_HOST` and `LETSENCRYPT_HOST` variables set to domain(s) that correctly resolve to the host, provided the host is publicly reachable.
```shell
$ docker run --detach \
--name your-proxyed-app
--env "VIRTUAL_HOST=subdomain.yourdomain.tld" \
--env "LETSENCRYPT_HOST=subdomain.yourdomain.tld" \
--env "LETSENCRYPT_EMAIL=mail@yourdomain.tld" \
nginx
```
Albeit **optional**, it is **recommended** to provide a valid email address through the `LETSENCRYPT_EMAIL` environment variable, so that Let's Encrypt can warn you about expiring certificates and allow you to recover your account.
The 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 proxyed container listen on and expose another port than the default `80`, you can force **nginx-proxy** to use this port with the [`VIRTUAL_PORT`](https://github.com/jwilder/nginx-proxy#multiple-ports) environment variable.
Example using [Grafana](https://hub.docker.com/r/grafana/grafana/) (expose and listen on port 3000):
```shell
$ docker run --detach \
--name grafana
--env "VIRTUAL_HOST=othersubdomain.yourdomain.tld" \
--env "VIRTUAL_PORT=3000" \
--env "LETSENCRYPT_HOST=othersubdomain.yourdomain.tld" \
--env "LETSENCRYPT_EMAIL=mail@yourdomain.tld" \
grafana/grafana
```
Repeat [Step 3](#step-3---proxyed-containers) for any other container you want to proxy.

View File

@ -0,0 +1,26 @@
## Optional container environment variables for custom configuration.
* `ACME_CA_URI` - Directory URI for the CA ACME API endpoint (defaults to ``https://acme-v01.api.letsencrypt.org/directory``).
If you set this environment variable value to `https://acme-staging.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](https://letsencrypt.org/docs/rate-limits/) (but are not trusted by browsers).
For example
```bash
$ docker run --detach \
--name nginx-proxy-letsencrypt \
--volumes-from nginx-proxy \
--volume /path/to/certs:/etc/nginx/certs:rw \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--env "ACME_CA_URI=https://acme-staging.api.letsencrypt.org/directory" \
jrcs/letsencrypt-nginx-proxy-companion
```
You can also create test certificates per container (see [Test certificates](./Let's-Encrypt-and-ACME.md#test-certificates))
* `DEBUG` - Set it to `true` to enable debugging output one the container logs, which could help you troubleshoot configuration issues.
* `REUSE_ACCOUNT_KEYS` - Set it to `false` to disable the account keys reutilization (see [ACME account keys](./Let's-Encrypt-and-ACME.md#acme-account-keys)).
* `REUSE_PRIVATE_KEYS` - Set it to `true` to make `simp_le` reuse previously generated private key for each certificate instead of creating a new one on certificate renewal. Recommended if you intend to use [HPKP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Public_Key_Pinning) (please not however that HPKP has been deprecated by Google's Chrome and that its use is therefore not recommended).
* `DHPARAM_BITS` - Change the size of the Diffie-Hellman key generated by the container from the default value of 2048 bits. For example `--env DHPARAM_BITS=1024` to support some older clients like Java 6 and 7.

View File

@ -0,0 +1,23 @@
The container provide the following utilities (replace `nginx-letsencrypt` with the name or ID of your **letsencrypt-nginx-proxy-companion** container when executing the commands):
### Force certificates renewal
If needed, you can force a running **letsencrypt-nginx-proxy-companion** container to renew all certificates that are currently in use with the following command:
```bash
$ docker exec nginx-letsencrypt /app/force_renew
```
### Manually trigger the service loop
You can trigger the execution of the service loop before the hourly execution with:
```bash
$ docker exec nginx-letsencrypt /app/signal_le_service
```
Unlike 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:
```bash
$ docker exec nginx-letsencrypt /app/cert_status
```

117
docs/Docker-Compose.md Normal file
View File

@ -0,0 +1,117 @@
## Usage with Docker Compose
As stated by its repository, [Docker Compose](https://github.com/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 **letsencrypt-nginx-proxy-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](./Basic-usage.md) and [avanced](./Advanced-usage.md) non compose setups, and Docker Compose usage.
Please read [getting container IDs](./Getting-containers-IDs.md) and be aware that the `--volumes-from method` is **only** available on compose file version 2.
The following examples are minimal, clean starting points using compose file version 2. Again they are not intended as a definitive reference.
The use of named containers and volume is not required but helps keeping everything clear and organized.
### Two containers example
```yaml
version: '2'
services:
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- conf:/etc/nginx/conf.d
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- dhparam:/etc/nginx/dhparam
- certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
network_mode: bridge
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: nginx-proxy-le
volumes_from:
- nginx-proxy
volumes:
- certs:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
network_mode: bridge
volumes:
conf:
vhost:
html:
dhparam:
certs:
```
**Note:** **nginx-proxy** Dockerfile [create a volume for `/etc/nginx/dhparam`](https://github.com/jwilder/nginx-proxy/blob/e80fc0b304bcbcf703d86392394c1a5adb823e3c/Dockerfile#L34), so this compose file include it as a named volume instead of letting it be created anyway as an anonymous volume.
### Three containers example
```yaml
version: '2'
services:
nginx-proxy:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- conf:/etc/nginx/conf.d
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- certs:/etc/nginx/certs:ro
network_mode: bridge
docker-gen:
image: jwilder/docker-gen
container_name: nginx-proxy-gen
command: -notify-sighup nginx-proxy -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
volumes_from:
- nginx-proxy
volumes:
- /path/to/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen"
network_mode: bridge
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: nginx-proxy-le
volumes_from:
- nginx-proxy
volumes:
- certs:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
network_mode: bridge
volumes:
conf:
vhost:
html:
certs:
```
**Note:** don't forget to replace `/path/to/nginx.tmpl` with the actual path to the [`nginx.tmpl`](https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl) file you downloaded.
### Other (external) examples
If you want other examples how to use this container with Docker Compose, look at:
* [Nicolas Duchon's Examples](https://github.com/buchdag/letsencrypt-nginx-proxy-companion-compose) - with automated testing
* [Evert Ramos's Examples](https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion) - using docker-compose version '3'
* [Karl Fathi's Examples](https://github.com/fatk/docker-letsencrypt-nginx-proxy-companion-examples)
* [More examples from Karl](https://github.com/pixelfordinner/pixelcloud-docker-apps/tree/master/nginx-proxy)
* [George Ilyes' Examples](https://github.com/gilyes/docker-nginx-letsencrypt-sample)
* [Dmitry's simple docker-compose example](https://github.com/dmitrym0/simple-lets-encrypt-docker-compose-sample)
* [Radek's docker-compose jenkins example](https://github.com/dataminelab/docker-jenkins-nginx-letsencrypt)

View File

@ -0,0 +1,96 @@
## Getting nginx-proxy/nginx/docker-gen containers IDs
For **letsencrypt-nginx-proxy-companion** to work properly, it needs to know the ID of the **nginx**/**nginx-proxy** container (in both [two](./Basic-usage.md) and [three](./Advanced-usage.md) containers setups), plus the ID of the **docker-gen** container in a [three container setup](./Advanced-usage.md).
There are three methods to inform the **letsencrypt-nginx-proxy-companion** container of the **nginx**/**nginx-proxy** container ID:
* `label` method: add the label `com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy` to the **nginx**/**nginx-proxy** container.
* `environment variable` method: assign a fixed name to the **nginx**/**nginx-proxy** container with `container_name:` and set the environment variable `NGINX_PROXY_CONTAINER` to this name on the **letsencrypt-nginx-proxy-companion** container.
* `volumes_from` method. Using this method, the **letsencrypt-nginx-proxy-companion** container will get the **nginx**/**nginx-proxy** container ID from the volumes it got using the `volumes_from` option.
And two methods to inform the **letsencrypt-nginx-proxy-companion** container of the **docker-gen** container ID:
* `label` method: add the label `com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen` to the **docker-gen** container.
* `environment variable` method: assign a fixed name to the **docker-gen** container with `container_name:` and set the environment variable `NGINX_DOCKER_GEN_CONTAINER` to this name on the **letsencrypt-nginx-proxy-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 **letsencrypt-nginx-proxy-companion** in environments where containers names are dynamic, like in Swarm Mode or in Docker Cloud. Howhever 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 jwilder/docker-gen with a fork that has this ability like [herlderco/docker-gen](https://github.com/helderco/docker-gen). Be advised that for now, this works to a very limited extent [(everything has to be on the same node)](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/pull/231#issuecomment-330624331).
#### Examples with three containers setups:
`label` method.
```
$ docker run --detach \
[...]
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy \
nginx
$ docker run --detach \
[...]
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen \
jwilder/docker-gen
$ docker run --detach \
[...]
jrcs/letsencrypt-nginx-proxy-companion
```
`environment variable` method
```
$ docker run --detach \
[...]
--name unique-container-name \
nginx
$ docker run --detach \
[...]
--name another-unique-container-name \
jwilder/docker-gen
$ docker run --detach \
[...]
--env NGINX_PROXY_CONTAINER=unique-container-name \
--env NGINX_DOCKER_GEN_CONTAINER=another-unique-container-name \
jrcs/letsencrypt-nginx-proxy-companion
```
`volumes_from` (**nginx**) + `label` (**docker-gen**) method
```
$ docker run --detach \
[...]
--name unique-container-name \
nginx
$ docker run --detach \
[...]
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen \
jwilder/docker-gen
$ docker run --detach \
[...]
--volumes-from unique-container-name \
jrcs/letsencrypt-nginx-proxy-companion
```
`volumes_from` (**nginx**) + `environment variable` (**docker-gen**) method
```
$ docker run --detach \
[...]
--name unique-container-name \
nginx
$ docker run --detach \
[...]
--name another-unique-container-name \
jwilder/docker-gen
$ docker run --detach \
[...]
--volumes-from unique-container-name \
--env NGINX_DOCKER_GEN_CONTAINER=another-unique-container-name \
jrcs/letsencrypt-nginx-proxy-companion
```

View File

@ -0,0 +1,74 @@
## Troubleshooting failing authorizations
The first two things to do in case of failing authorization are to run the **letsencrypt-nginx-proxy-companion** container with the environment variable `DEBUG=true` to enable the more detailed error messages, and to [request test certificates](./Let's-Encrypt-and-ACME.md#test-certificates) while troubleshooting the issue.
Common causes of of failing authorizations:
#### port `80` or `443` on your host are closed / filtered from the outside, possibly because of a misconfigured firewall.
Check your host `80` and `443` ports **from the outside** (as in from a host having a different public IP) with `nmap` or a similar tool.
#### your domain name does not resolve to your host IPv4 and/or IPv6.
Check that your domain name A (and AAAA, if present) records points to the correct adresses using `drill`, `dig` or `nslookup`.
#### your domain name advertise an AAAA (IPv6) record, but your host or your host's docker isn't actually reachable over IPv6.
Create a test nginx container on your host and try to reach it over both IPv4 and IPv6.
```bash
you@remotedockerhost$ docker run -d -p 80:80 nginx:alpine
you@localcomputer$ curl http://your.domain.tld
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
[...]
</html>
you@localcomputer$ curl -6 http://your.domain.tld
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
[...]
</html>
```
If you are unsure of your host/hosts's docker IPv6 connectivity, drop the AAAA record from your domain name and wait for the modification to propagate.
#### your domain name DNS provider answers incorrectly to CAA record requests.
Read https://letsencrypt.org/docs/caa/ and test with https://unboundtest.com/
#### the **nginx-proxy**/**nginx**/**docker-gen**/**letsencrypt-nginx-proxy-companion** containers where misconfigured.
Review [basic usage](./Basic-usage.md) or [advanced usage](./Advanced-usage.md), plus the [nginx-proxy documentation](https://github.com/jwilder/nginx-proxy).
Pay special attention to the fact that the volumes **MUST** be shared between the different containers.
#### you forgot to set both `VIRTUAL_HOST` and `LETSENCRYPT_HOST` on the proxyed container.
Both are required. Every domain on `LETSENCRYPT_HOST`**must** be on `VIRTUAL_HOST`too.
#### you are using an outdated version of either **letsencrypt-nginx-proxy-companion** or the nginx.tmpl file (if running a 3 containers setup)
Pull `jrcs/letsencrypt-nginx-proxy-companion:latest` again and get the latest [latest nginx.tmpl](https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl).
***
The challenge files are automatically cleaned up **after** the authorization process, wether it succeeded or failed, so trying to `curl` them from the outside won't yeld any result. You can however create a test file inside the same folder and use it to test the challenge files reachability from the outside (over both IPv4 and IPv6 if you want to use the latter):
```
you@remotedockerhost$ docker exec your-le-container bash -c 'echo "Hello world!" > /usr/share/nginx/html/.well-known/acme-challenge/hello-world'
you@localcomputer$ curl http://yourdomain.tld/.well-known/acme-challenge/hello-world
Hello world!
you@localcomputer$ curl -6 http://yourdomain.tld/.well-known/acme-challenge/hello-world
Hello world!
```
If you have issues with the [advanced setup](./Advanced-usage.md), fallback to the [basic setup](./Basic-usage.md). The advanced setup is not meant to be obligatory.

View File

@ -0,0 +1,66 @@
## Let's Encrypt / ACME
**NOTE on CAA**: 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](https://letsencrypt.org/docs/caa/). Let's Encrypt do not require that you set a CAA record on your domain, just that your DNS provider answers correctly.
**NOTE on IPv6**: If the domain or sub domain you want to issue certificate for has an AAAA record set, Let's Encrypt will favor challenge validation over IPv6. [There is an IPv6 to IPv4 fallback in place but Let's Encrypt can't guarantee it'll work in every possible case](https://github.com/letsencrypt/boulder/issues/2770#issuecomment-340489871), so bottom line is **if you are not sure of both your host and your host's Docker reachability over IPv6, do not advertise an AAAA record** or LE challenge validation might fail.
As described on [basic usage](./Basic-usage.md), the `LETSENCRYPT_HOST` environment variables needs to be declared in each to-be-proxied application containers for which you want to enable SSL and create certificate. It most likely needs to be the same as the `VIRTUAL_HOST` variable and must resolve to your host (which has to be publicly reachable).
Specify multiple hosts with a comma delimiter to create multi-domain ([SAN](https://www.digicert.com/subject-alternative-name.htm)) certificates (the first domain in the list will be the base domain).
The following environment variables are optional and parametrize the way the Let's Encrypt client works.
### per proxyed container
#### Automatic certificate renewal
Every hour (3600 seconds) the certificates are checked and per default every certificate that will expire in the next [30 days](https://github.com/zenhack/simp_le/blob/a8a8013c097910f8f3cce046f1077b41b745673b/simp_le.py#L73) (90 days / 3) is renewed.
The `LETSENCRYPT_MIN_VALIDITY` environment variable can be used to set a different minimum validity (in seconds) for certificates. Note that the possible values are internally capped at an upper bound of 7603200 (88 days) and a lower bound of 7200 (2 hours) as a security margin, considering that the Let's Encrypt CA does only issues certificates with a lifetime of [90 days](https://letsencrypt.org/2015/11/09/why-90-days.html) (upper bound), the rate limits imposed on certificate renewals are [5 per week](https://letsencrypt.org/docs/rate-limits/) (upper bound), and the fact that the certificates are checked and renewed accordingly every hour (lower bound).
#### Contact address
The `LETSENCRYPT_EMAIL` environment variable must be a valid email and will be used by Let's Encrypt to warn you of impeding certificate expiration (should the automated renewal fail) and to recover an account. It is **recommended** to provide a valid contact address using this variable.
#### Private key size
The `LETSENCRYPT_KEYSIZE` environment variable determines the size of the requested key (in bit, defaults to 4096).
#### Test certificates
The `LETSENCRYPT_TEST` environment variable, when set to `true` on a proxyed application container, will create a test certificates that don't have the [5 certs/week/domain limits](https://letsencrypt.org/docs/rate-limits/) and are signed by an untrusted intermediate (they won't be trusted by browsers).
#### Container restart on cert renewal
The `LETSENCRYPT_RESTART_CONTAINER` environment variable, when set to `true` on an application container, will restart this container whenever the corresponding cert (`LETSENCRYPT_HOST`) is renewed. This is useful when certificates are directly used inside a container for other purposes than HTTPS (e.g. an FTPS server), to make sure those containers always use an up to date certificate.
#### ACME account alias
See the [ACME account keys](#multiple-account-keys-per-endpoint) section.
### global (set on letsencrypt-nginx-proxy-companion container)
#### Private key re-utilization
The `REUSE_PRIVATE_KEYS` environment variable, when set to `true` on the **letsencrypt-nginx-proxy-companion** container, will set **simp_le** to reuse previously generated private key instead of generating a new one at renewal for all domains.
Reusing private keys can help if you intend to use HPKP, but please note that HPKP will be deprecated by at least one major browser (Chrome), and that it is therefore strongly discouraged to use it at all.
#### ACME account key re-utilization
See the [ACME account keys](#disable-account-keys-re-utilization) section.
## ACME account keys
By default the container will save the first ACME account key created for each ACME API endpoint used, and will reuse it for all subsequent authorization and issuance requests made to this endpoint. This behavior is enabled by default to avoid running into Let's Encrypt account [rate limits](https://letsencrypt.org/docs/rate-limits/).
For instance, when using the default Let's Encrypt production endpoint, the container will save the first account key created for this endpoint as `/etc/nginx/certs/accounts/acme-v01.api.letsencrypt.org/directory/default.json` and will reuse it for future requests made to this endpoint.
#### Multiple account keys per endpoint
If required, you can use multiple accounts for the same ACME API endpoint by using the `LETSENCRYPT_ACCOUNT_ALIAS` environment variable on your proxyed container. This instruct the **letsencrypt-nginx-proxy-companion** container to look for an account key named after the provided alias instead of `default.json`. For example, `LETSENCRYPT_ACCOUNT_ALIAS=client1` will use the key named `client1.json` in the corresponding ACME API endpoint folder for this proxyed container (or will create it if it does not exists yet).
Please see the *One Account or Many?* paragraph on [Let's Encrypt Integration Guide](https://letsencrypt.org/docs/integration-guide/) for additional information.
#### Disable account keys re-utilization
If you want to disable the account key re-utilization entirely, you can set the environment variable `REUSE_ACCOUNT_KEYS` to `false` on the **letsencrypt-nginx-proxy-companion** container. This creates a new ACME registration with a corresponding account key for each new certificate issuance. Note that this won't create new account keys for certs already issued before `REUSE_ACCOUNT_KEYS` is set to `false`. This is not recommended unless you have specific reasons to do so.

122
docs/Persistent-data.md Normal file
View File

@ -0,0 +1,122 @@
## Persistent data
### Anonymous volumes
When you follow instructions from Basic usage or Advanced usage, Docker will automatically create **anonymous volumes** (volumes with a random name) for every `--volume` / `-v` argument passed:
```shell
$ docker run -d \
--name nginx-proxy \
-p 80:80 \
-p 443:443 \
-v /etc/nginx/certs \
-v /etc/nginx/vhost.d \
-v /usr/share/nginx/html \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
jwilder/nginx-proxy
$ docker volume ls
DRIVER VOLUME NAME
local 287be3abd610e5566500d719ceb8b952952f12c9324ef02d05785d4ee9737ae9
local 6530b1b40cf89efb71aa7fd19bddec927fa2bcae59b04b9c1c850af72ffe0123
local f260f71fefadcdfc311d285d69151f2312915174d3fb1fab89949ec5ec871a54
local f2cd94ca48904dc9cfc840ce4b265a04831c580d525253d7a0e5aac4d1dca340
```
### Named volumes (recommended)
Using **named volumes** instead make managing volumes easier:
```shell
$ docker run -d \
--name nginx-proxy \
-p 80:80 \
-p 443:443 \
-v certs:/etc/nginx/certs \
-v vhost:/etc/nginx/vhost.d \
-v html:/usr/share/nginx/html \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
jwilder/nginx-proxy
$ docker volume ls
DRIVER VOLUME NAME
local certs
local vhost
local html
```
### Host volumes
Alternatively, you might want to store the certificates on a local folder rather than letting Docker create and manage a volume for them. This is easily achieved by using a **host volume** (binding an absolute path on your host to the `/ect/nginx/certs` folder on your containers):
`-v /path/to/certificates:/etc/nginx/certs`
No matter the type of volume you choose, if you set them on the nginx-proxy or nginx container and use `--volumes_from` on the others containers, they will automatically be mounted inside the container to the path your first defined.
### Restraining other containers write permission
If you want to restrain the **nginx** and **docker-gen** processes to read only access on the certificates, you'll have to use different volume flags depending on the container.
Example with named volumes:
`-v certs:/etc/nginx/certs:ro` on the **nginx-proxy** or **nginx** + **docker-gen** container(s).
`-v certs:/etc/nginx/certs:rw` on the **letsencrypt-nginx-proxy-companion** container.
## Ownership & permissions of private and ACME account keys
By default, the **letsencrypt-nginx-proxy-companion** container will enforce the following ownership and permissions scheme on the files it creates and manage:
```
[drwxr-xr-x] /etc/nginx/certs
├── [drwxr-xr-x root root] accounts
│ └── [drwxr-xr-x root root] acme-v01.api.letsencrypt.org
│ └── [drwxr-xr-x root root] directory
│ └── [-rw-r--r-- root root] default.json
├── [-rw-r--r-- root root] dhparam.pem
├── [-rw-r--r-- root root] default.crt
├── [-rw-r--r-- root root] default.key
├── [drwxr-xr-x root root] domain.tld
│ ├── [lrwxrwxrwx root root] account_key.json -> ../accounts/acme-v01.api.letsencrypt.org/directory/default.json
│ ├── [-rw-r--r-- root root] cert.pem
│ ├── [-rw-r--r-- root root] chain.pem
│ ├── [-rw-r--r-- root root] fullchain.pem
│ └── [-rw-r--r-- root root] key.pem
├── [lrwxrwxrwx root root] domain.tld.chain.pem -> ./domain.tld/chain.pem
├── [lrwxrwxrwx root root] domain.tld.crt -> ./domain.tld/fullchain.pem
├── [lrwxrwxrwx root root] domain.tld.dhparam.pem -> ./dhparam.pem
└── [lrwxrwxrwx root root] domain.tld.key -> ./domain.tld/key.pem
```
This behavior can be customized using the following environment variable on the **letsencrypt-nginx-proxy-companion** container:
* `FILES_UID` - Set the user owning the files and folders managed by the container. The variable can be either a user name if this user exists inside the container or a user numeric ID. Default to `root` (user ID `0`).
* `FILES_GID` - Set the group owning the files and folders managed by the container. The variable can be either a group name if this group exists inside the container or a group numeric ID. Default to the same value as `FILES_UID`.
* `FILES_PERMS` - Set the permissions of the private keys and ACME account keys. The variable must be a valid octal permission setting and defaults to `644`.
* `FOLDERS_PERMS` - Set the permissions of the folders managed by the container. The variable must be a valid octal permission setting and defaults to `755`.
For example, `FILES_UID=1000`, `FILES_PERMS=600` and `FOLDERS_PERMS=700` will result in the following:
```
[drwxr-xr-x] /etc/nginx/certs
├── [drwx------ 1000 1000] accounts
│ └── [drwx------ 1000 1000] acme-v01.api.letsencrypt.org
│ └── [drwx------ 1000 1000] directory
│ └── [-rw------- 1000 1000] default.json
├── [-rw-r--r-- 1000 1000] dhparam.pem
├── [-rw-r--r-- 1000 1000] default.crt
├── [-rw------- 1000 1000] default.key
├── [drwx------ 1000 1000] domain.tld
│ ├── [lrwxrwxrwx 1000 1000] account_key.json -> ../accounts/acme-v01.api.letsencrypt.org/directory/default.json
│ ├── [-rw-r--r-- 1000 1000] cert.pem
│ ├── [-rw-r--r-- 1000 1000] chain.pem
│ ├── [-rw-r--r-- 1000 1000] fullchain.pem
│ └── [-rw------- 1000 1000] key.pem
├── [lrwxrwxrwx 1000 1000] domain.tld.chain.pem -> ./domain.tld/chain.pem
├── [lrwxrwxrwx 1000 1000] domain.tld.crt -> ./domain.tld/fullchain.pem
├── [lrwxrwxrwx 1000 1000] domain.tld.dhparam.pem -> ./dhparam.pem
└── [lrwxrwxrwx 1000 1000] domain.tld.key -> ./domain.tld/key.pem
```
If you just want to make the most sensitive files (private keys and ACME account keys) root readable only, set the environment variable `FILES_PERMS` to `600` on your **letsencrypt-nginx-proxy-companion** container.

25
docs/README.md Normal file
View File

@ -0,0 +1,25 @@
#### Usage:
[Basic (two containers).](./Basic-usage.md)
[Advanced (three containers).](./Advanced-usage.md)
[Getting containers IDs](./Getting-containers-IDs.md)
[with Docker Compose](./Docker-Compose.md)
[Container utilities](./Container-utilities.md)
#### Additional configuration:
[Let's Encrypt / ACME](./Let's-Encrypt-and-ACME.md)
[Container configuration](./Container-configuration.md)
[Persistent data](./Persistent-data.md)
[Standalone certificates](./Standalone-certificates-(beta).md) **(Beta)**
#### Troubleshooting:
[Invalid / failing authorizations](./Invalid-authorizations.md)

View File

@ -0,0 +1,78 @@
## Standalone certificates
**This feature is only present on the `dev` branch / image.**
**It's still considered experimental and subject to change.**
You can generate certificate that are not tied to containers environment variable by mounting a user configuration file inside the container at `/app/letsencrypt_user_data`. This feature also require sharing the `/etc/nginx/conf.d` folder between the **nginx-proxy** and **letsencrypt-nginx-proxy-companion** container (and the **docker-gen** container if you are running a [three container setup](./Advanced-usage.md)):
```bash
$ docker run --detach \
--name nginx-proxy \
--publish 80:80 \
--publish 443:443 \
--volume /etc/nginx/certs \
--volume /etc/nginx/vhost.d \
--volume /etc/nginx/conf.d \
--volume /usr/share/nginx/html \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \
jwilder/nginx-proxy
```
```bash
$ docker run --detach \
--name nginx-proxy-letsencrypt \
--volumes-from nginx-proxy \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--volume /path/to/your/config_file:/app/letsencrypt_user_data:ro \
jrcs/letsencrypt-nginx-proxy-companion
```
The user configuration file is a collection of bash variables and array, and follows the syntax of the `/app/letsencrypt_service_data` file that get created by **docker-gen**.
### Required configuration parameters:
`LETSENCRYPT_STANDALONE_CERTS` : a bash array containing identifier(s) for you standalone certificate(s). Each element in the array has to be unique. Those identifiers are internal to the container process and won't ever be visible to the outside world or appear on your certificate.
`LETSENCRYPT_uniqueidentifier_HOST` : a bash array containing domain(s) that will be covered by the certificate corresponding to `uniqueidentifier`.
Each identifier in `LETSENCRYPT_STANDALONE_CERTS` must have its own corresponding `LETSENCRYPT_uniqueidentifier_HOST` array.
**Minimal example generating a single certificate for a single domain:**
```bash
LETSENCRYPT_STANDALONE_CERTS=('uniqueidentifier')
LETSENCRYPT_uniqueidentifier_HOST=('yourdomain.tld')
```
**Example with multiple certificates and domains:**
```bash
LETSENCRYPT_STANDALONE_CERTS=('web' 'app' 'othersite')
LETSENCRYPT_web_HOST=('yourdomain.tld' 'www.yourdomain.tld')
LETSENCRYPT_app_HOST=('myapp.yourdomain.tld' 'myapp.yourotherdomain.tld' 'service.yourotherdomain.tld')
LETSENCRYPT_othersite_HOST=('yetanotherdomain.tld')
```
### Optional configuration parameters:
Those are all single bash variables.
`LETSENCRYPT_uniqueidentifier_EMAIL` : must be a valid email and will be used by Let's Encrypt to warn you of impeding certificate expiration (should the automated renewal fail).
`LETSENCRYPT_uniqueidentifier_KEYSIZE` : determines the size of the requested private key (in bit, defaults to 4096).
`LETSENCRYPT_uniqueidentifier_TEST` : if set to true, the corresponding certificate will be a test certificates: it won't have the 5 certs/week/domain limits and will be signed by an untrusted intermediate (ie it won't be trusted by browsers).
`LETSENCRYPT_uniqueidentifier_ACCOUNT_ALIAS` : see the [ACME account keys documentation](./Let's-Encrypt-and-ACME.md#disable-account-keys-re-utilization).
### Picking up changes to letsencrypt_user_data
The container does not actively watch the `/app/letsencrypt_user_data` file for changes.
Changes will either be picked up every hour when the service loop execute again, or by using `docker exec your-le-container-name-or-id /app/signal_le_service` to manually trigger the service loop execution.
### Proxying to something else than a Docker container
Please see the [**nginx-proxy** documentation](https://github.com/jwilder/nginx-proxy#proxy-wide).
No support will be provided on the **letsencrypt-nginx-proxy-companion** repo for proxying related issues or questions.