Add a docker-compose & let's encrypt user-guide
This commit is contained in:
parent
c2d440a914
commit
63a07fe6cf
10 changed files with 629 additions and 0 deletions
|
@ -0,0 +1,40 @@
|
||||||
|
version: "3.3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
traefik:
|
||||||
|
image: "traefik:v2.0.0-beta1"
|
||||||
|
container_name: "traefik"
|
||||||
|
command:
|
||||||
|
#- "--log.level=DEBUG"
|
||||||
|
- "--api=true"
|
||||||
|
- "--providers.docker=true"
|
||||||
|
- "--providers.docker.exposedbydefault=false"
|
||||||
|
- "--entrypoints.web.address=:80"
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
|
||||||
|
#- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.email=postmaster@mydomain.com"
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- "8080:8080"
|
||||||
|
environment:
|
||||||
|
- "OVH_ENDPOINT=xxx"
|
||||||
|
- "OVH_APPLICATION_KEY=xxx"
|
||||||
|
- "OVH_APPLICATION_SECRET=xxx"
|
||||||
|
- "OVH_CONSUMER_KEY=xxx"
|
||||||
|
volumes:
|
||||||
|
- "./letsencrypt:/letsencrypt"
|
||||||
|
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||||
|
|
||||||
|
whoami:
|
||||||
|
image: "containous/whoami"
|
||||||
|
container_name: "simple-service"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||||
|
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.whoami.tls.certresolver=mydnschallenge"
|
|
@ -0,0 +1,55 @@
|
||||||
|
version: "3.3"
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
ovh_endpoint:
|
||||||
|
file: "./secrets/ovh_endpoint.secret"
|
||||||
|
ovh_application_key:
|
||||||
|
file: "./secrets/ovh_application_key.secret"
|
||||||
|
ovh_application_secret:
|
||||||
|
file: "./secrets/ovh_application_secret.secret"
|
||||||
|
ovh_consumer_key:
|
||||||
|
file: "./secrets/ovh_consumer_key.secret"
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
traefik:
|
||||||
|
image: "traefik:v2.0.0-beta1"
|
||||||
|
container_name: "traefik"
|
||||||
|
command:
|
||||||
|
#- "--log.level=DEBUG"
|
||||||
|
- "--api=true"
|
||||||
|
- "--providers.docker=true"
|
||||||
|
- "--providers.docker.exposedbydefault=false"
|
||||||
|
- "--entrypoints.web.address=:80"
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
|
||||||
|
#- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.email=postmaster@mydomain.com"
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- "8080:8080"
|
||||||
|
secrets:
|
||||||
|
- "ovh_endpoint"
|
||||||
|
- "ovh_application_key"
|
||||||
|
- "ovh_application_secret"
|
||||||
|
- "ovh_consumer_key"
|
||||||
|
environment:
|
||||||
|
- "OVH_ENDPOINT_FILE=/run/secrets/ovh_endpoint"
|
||||||
|
- "OVH_APPLICATION_KEY_FILE=/run/secrets/ovh_application_key"
|
||||||
|
- "OVH_APPLICATION_SECRET_FILE=/run/secrets/ovh_application_secret"
|
||||||
|
- "OVH_CONSUMER_KEY_FILE=/run/secrets/ovh_consumer_key"
|
||||||
|
volumes:
|
||||||
|
- "./letsencrypt:/letsencrypt"
|
||||||
|
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||||
|
|
||||||
|
whoami:
|
||||||
|
image: "containous/whoami"
|
||||||
|
container_name: "simple-service"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||||
|
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.whoami.tls.certresolver=mydnschallenge"
|
183
docs/content/user-guides/docker-compose/acme-dns/index.md
Normal file
183
docs/content/user-guides/docker-compose/acme-dns/index.md
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
# Docker-compose with let's encrypt: DNS Challenge
|
||||||
|
|
||||||
|
This guide aim to demonstrate how to create a certificate with the let's encrypt DNS challenge to use https on a simple service exposed with Traefik.
|
||||||
|
Please also read the [basic example](../basic-example) for details on how to expose such a service.
|
||||||
|
|
||||||
|
## Prerequisite
|
||||||
|
|
||||||
|
For the DNS challenge, you'll need:
|
||||||
|
|
||||||
|
- A working [provider](https://docs.traefik.io/v2.0/https/acme/#providers) along with the credentials allowing to create and remove DNS records.
|
||||||
|
|
||||||
|
!!! info "Variables may vary depending on the Provider."
|
||||||
|
Please note this guide may vary depending on the provider you use.
|
||||||
|
The only things changing are the names of the variables you will need to define in order to configure your provider so it can create DNS records.
|
||||||
|
Please refer the [list of providers](../../../https/acme.md#providers) given right above and replace all the environment variables with the ones described in this documentation.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
- Create a `docker-compose.yml` file with the following content:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
--8<-- "content/user-guides/docker-compose/acme-dns/docker-compose.yml"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace the environment variables by your own:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
environment:
|
||||||
|
- "OVH_ENDPOINT=[YOUR_OWN_VALUE]"
|
||||||
|
- "OVH_APPLICATION_KEY=[YOUR_OWN_VALUE]"
|
||||||
|
- "OVH_APPLICATION_SECRET=[YOUR_OWN_VALUE]"
|
||||||
|
- "OVH_CONSUMER_KEY=[YOUR_OWN_VALUE]"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `postmaster@mydomain.com` by your **own email** within the `certificatesresolvers.mydnschallenge.acme.email` command line argument of the `traefik` service.
|
||||||
|
- Replace `whoami.mydomain.com` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
||||||
|
- Optionally uncomment the following lines if you want to test/debug:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
#- "--log.level=DEBUG"
|
||||||
|
#- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Run `docker-compose up -d` within the folder where you created the previous file.
|
||||||
|
- Wait a bit and visit `https://your_own_domain` to confirm everything went fine.
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
If you uncommented the `acme.caserver` line, you will get an SSL error, but if you display the certificate and see it was emitted by `Fake LE Intermediate X1` then it means all is good.
|
||||||
|
(It is the staging environment intermediate certificate used by let's encrypt).
|
||||||
|
You can now safely comment the `acme.caserver` line, remove the `letsencrypt/acme.json` file and restart Traefik to issue a valid certificate.
|
||||||
|
|
||||||
|
## Explanation
|
||||||
|
|
||||||
|
What changed between the initial setup:
|
||||||
|
|
||||||
|
- We configure a second entry point for the https traffic:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
command:
|
||||||
|
# Traefik will listen to incoming request on the port 443 (https)
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
ports:
|
||||||
|
- "443:443"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We configure the DNS let's encrypt challenge:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
command:
|
||||||
|
# Enable a dns challenge named "mydnschallenge"
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
|
||||||
|
# Tell which provider to use
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
|
||||||
|
# The email to provide to let's encrypt
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.email=postmaster@mydomain.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We provide the required configuration to our provider via environment variables:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
environment:
|
||||||
|
- "OVH_ENDPOINT=xxx"
|
||||||
|
- "OVH_APPLICATION_KEY=xxx"
|
||||||
|
- "OVH_APPLICATION_SECRET=xxx"
|
||||||
|
- "OVH_CONSUMER_KEY=xxx"
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
This is the step that may vary depending on the provider you use.
|
||||||
|
Just define the variables required by your provider.
|
||||||
|
(see the prerequisite for a list)
|
||||||
|
|
||||||
|
- We add a volume to store our certificates:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
volumes:
|
||||||
|
# Create a letsencrypt dir within the folder where the docker-compose file is
|
||||||
|
- "./letsencrypt:/letsencrypt"
|
||||||
|
|
||||||
|
command:
|
||||||
|
# Tell to store the certificate on a path under our volume
|
||||||
|
- "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We configure the `whoami` service to tell Traefik to use the certificate resolver named `mydnschallenge` we just configured:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
- "traefik.http.routers.whoami.tls.certresolver=mydnschallenge" # Uses the Host rule to define which certificate to issue
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use Secrets
|
||||||
|
|
||||||
|
To configure the provider, and avoid having the secrets exposed in plaintext within the docker-compose environment section,
|
||||||
|
you could use docker secrets.
|
||||||
|
The point is to manage those secret files by another mean, and read them from the `docker-compose.yml` file making the docker-compose file itself less sensitive.
|
||||||
|
|
||||||
|
- Create a directory named `secrets`, and create a file for each parameters required to configure you provider containing the value of the parameter:
|
||||||
|
for example, the `ovh_endpoint.secret` file contain `ovh-eu`
|
||||||
|
|
||||||
|
```text
|
||||||
|
./secrets
|
||||||
|
├── ovh_application_key.secret
|
||||||
|
├── ovh_application_secret.secret
|
||||||
|
├── ovh_consumer_key.secret
|
||||||
|
└── ovh_endpoint.secret
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
You could store those secrets anywhere on the server,
|
||||||
|
just make sure to use the proper path for the `file` directive fo the secrets definition in the `docker-compose.yml` file.
|
||||||
|
|
||||||
|
- Use this `docker-compose.yml` file:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
--8<-- "content/user-guides/docker-compose/acme-dns/docker-compose_secrets.yml"
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
Still think about changing `postmaster@mydomain.com` & `whoami.mydomain.com` by your own values.
|
||||||
|
|
||||||
|
Let's explain a bit what we just did:
|
||||||
|
|
||||||
|
- The following section allow to read files on the docker host, and expose those file under `/run/secrets/[NAME_OF_THE_SECRET]` within the container:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
secrets:
|
||||||
|
# secret name also used to name the file exposed within the container
|
||||||
|
ovh_endpoint:
|
||||||
|
# path on the host
|
||||||
|
file: "./secrets/ovh_endpoint.secret"
|
||||||
|
ovh_application_key:
|
||||||
|
file: "./secrets/ovh_application_key.secret"
|
||||||
|
ovh_application_secret:
|
||||||
|
file: "./secrets/ovh_application_secret.secret"
|
||||||
|
ovh_consumer_key:
|
||||||
|
file: "./secrets/ovh_consumer_key.secret"
|
||||||
|
|
||||||
|
services:
|
||||||
|
traefik:
|
||||||
|
# expose the predefined secret to the container by name
|
||||||
|
secrets:
|
||||||
|
- "ovh_endpoint"
|
||||||
|
- "ovh_application_key"
|
||||||
|
- "ovh_application_secret"
|
||||||
|
- "ovh_consumer_key"
|
||||||
|
```
|
||||||
|
|
||||||
|
- The environment variable within our `whoami` service are suffixed by `_FILE` which allow us to point to files containing the value, instead of exposing the value itself.
|
||||||
|
The acme client will read the content of those file to get the required configuration values.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
environment:
|
||||||
|
# expose the path to file provided by docker containing the value we want for OVH_ENDPOINT.
|
||||||
|
- "OVH_ENDPOINT_FILE=/run/secrets/ovh_endpoint"
|
||||||
|
- "OVH_APPLICATION_KEY_FILE=/run/secrets/ovh_application_key"
|
||||||
|
- "OVH_APPLICATION_SECRET_FILE=/run/secrets/ovh_application_secret"
|
||||||
|
- "OVH_CONSUMER_KEY_FILE=/run/secrets/ovh_consumer_key"
|
||||||
|
```
|
|
@ -0,0 +1,35 @@
|
||||||
|
version: "3.3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
traefik:
|
||||||
|
image: "traefik:v2.0.0-beta1"
|
||||||
|
container_name: "traefik"
|
||||||
|
command:
|
||||||
|
#- "--log.level=DEBUG"
|
||||||
|
- "--api=true"
|
||||||
|
- "--providers.docker=true"
|
||||||
|
- "--providers.docker.exposedbydefault=false"
|
||||||
|
- "--entrypoints.web.address=:80"
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
|
||||||
|
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
|
||||||
|
#- "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
- "--certificatesresolvers.myhttpchallenge.acme.email=postmaster@mydomain.com"
|
||||||
|
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- ":8080:8080"
|
||||||
|
volumes:
|
||||||
|
- "./letsencrypt:/letsencrypt"
|
||||||
|
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||||
|
|
||||||
|
whoami:
|
||||||
|
image: "containous/whoami"
|
||||||
|
container_name: "simple-service"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||||
|
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.whoami.tls.certresolver=myhttpchallenge"
|
83
docs/content/user-guides/docker-compose/acme-http/index.md
Normal file
83
docs/content/user-guides/docker-compose/acme-http/index.md
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
# Docker-compose with let's encrypt : HTTP Challenge
|
||||||
|
|
||||||
|
This guide aim to demonstrate how to create a certificate with the let's encrypt HTTP challenge to use https on a simple service exposed with Traefik.
|
||||||
|
Please also read the [basic example](../basic-example) for details on how to expose such a service.
|
||||||
|
|
||||||
|
## Prerequisite
|
||||||
|
|
||||||
|
For the HTTP challenge you will need:
|
||||||
|
|
||||||
|
- A publicly accessible host allowing connections on port `80` & `443` with docker & docker-compose installed.
|
||||||
|
- A DNS record with the domain you want to expose pointing to this host.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
- Create a `docker-compose.yml` on your remote server with the following content:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
--8<-- "content/user-guides/docker-compose/acme-http/docker-compose.yml"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `postmaster@mydomain.com` by your **own email** within the `certificatesresolvers.myhttpchallenge.acme.email` command line argument of the `traefik` service.
|
||||||
|
- Replace `whoami.mydomain.com` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
||||||
|
- Optionally uncomment the following lines if you want to test/debug:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
#- "--log.level=DEBUG"
|
||||||
|
#- "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Run `docker-compose up -d` within the folder where you created the previous file.
|
||||||
|
- Wait a bit and visit `https://your_own_domain` to confirm everything went fine.
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
If you uncommented the `acme.caserver` line, you will get an SSL error, but if you display the certificate and see it was emitted by `Fake LE Intermediate X1` then it means all is good.
|
||||||
|
(It is the staging environment intermediate certificate used by let's encrypt).
|
||||||
|
You can now safely comment the `acme.caserver` line, remove the `letsencrypt/acme.json` file and restart Traefik to issue a valid certificate.
|
||||||
|
|
||||||
|
## Explanation
|
||||||
|
|
||||||
|
What changed between the basic example:
|
||||||
|
|
||||||
|
- We configure a second entry point for the HTTPS traffic:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
command:
|
||||||
|
# Traefik will listen to incoming request on the port 443 (https)
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
ports:
|
||||||
|
- "443:443"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We configure the HTTPS let's encrypt challenge:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
command:
|
||||||
|
# Enable a http challenge named "myhttpchallenge"
|
||||||
|
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
|
||||||
|
# Tell it to use our predefined entrypoint named "web"
|
||||||
|
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
|
||||||
|
# The email to provide to let's encrypt
|
||||||
|
- "--certificatesresolvers.myhttpchallenge.acme.email=postmaster@mydomain.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We add a volume to store our certificates:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
volumes:
|
||||||
|
# Create a letsencrypt dir within the folder where the docker-compose file is
|
||||||
|
- "./letsencrypt:/letsencrypt"
|
||||||
|
|
||||||
|
command:
|
||||||
|
# Tell to store the certificate on a path under our volume
|
||||||
|
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We configure the `whoami` service to tell Traefik to use the certificate resolver named `myhttpchallenge` we just configured:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
# Uses the Host rule to define which certificate to issue
|
||||||
|
- "traefik.http.routers.whoami.tls.certresolver=myhttpchallenge"
|
||||||
|
```
|
|
@ -0,0 +1,32 @@
|
||||||
|
version: "3.3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
traefik:
|
||||||
|
image: "traefik:v2.0.0-beta1"
|
||||||
|
container_name: "traefik"
|
||||||
|
command:
|
||||||
|
#- "--log.level=DEBUG"
|
||||||
|
- "--api=true"
|
||||||
|
- "--providers.docker=true"
|
||||||
|
- "--providers.docker.exposedbydefault=false"
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
|
||||||
|
#- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
- "--certificatesresolvers.mytlschallenge.acme.email=postmaster@mydomain.com"
|
||||||
|
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
|
||||||
|
ports:
|
||||||
|
- "443:443"
|
||||||
|
- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
- "./letsencrypt:/letsencrypt"
|
||||||
|
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||||
|
|
||||||
|
whoami:
|
||||||
|
image: "containous/whoami"
|
||||||
|
container_name: "simple-service"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||||
|
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.whoami.tls.certresolver=mytlschallenge"
|
79
docs/content/user-guides/docker-compose/acme-tls/index.md
Normal file
79
docs/content/user-guides/docker-compose/acme-tls/index.md
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# Docker-compose with let's encrypt: TLS Challenge
|
||||||
|
|
||||||
|
This guide aim to demonstrate how to create a certificate with the let's encrypt TLS challenge to use https on a simple service exposed with Traefik.
|
||||||
|
Please also read the [basic example](../basic-example) for details on how to expose such a service.
|
||||||
|
|
||||||
|
## Prerequisite
|
||||||
|
|
||||||
|
For the TLS challenge you will need:
|
||||||
|
|
||||||
|
- A publicly accessible host allowing connections on port `443` with docker & docker-compose installed.
|
||||||
|
- A DNS record with the domain you want to expose pointing to this host.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
- Create a `docker-compose.yml` on your remote server with the following content:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
--8<-- "content/user-guides/docker-compose/acme-tls/docker-compose.yml"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `postmaster@mydomain.com` by your **own email** within the `certificatesresolvers.mytlschallenge.acme.email` command line argument of the `traefik` service.
|
||||||
|
- Replace `whoami.mydomain.com` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
||||||
|
- Optionally uncomment the following lines if you want to test/debug:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
#- "--log.level=DEBUG"
|
||||||
|
#- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Run `docker-compose up -d` within the folder where you created the previous file.
|
||||||
|
- Wait a bit and visit `https://your_own_domain` to confirm everything went fine.
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
If you uncommented the `acme.caserver` line, you will get an SSL error, but if you display the certificate and see it was emitted by `Fake LE Intermediate X1` then it means all is good.
|
||||||
|
(It is the staging environment intermediate certificate used by let's encrypt).
|
||||||
|
You can now safely comment the `acme.caserver` line, remove the `letsencrypt/acme.json` file and restart Traefik to issue a valid certificate.
|
||||||
|
|
||||||
|
## Explanation
|
||||||
|
|
||||||
|
What changed between the basic example:
|
||||||
|
|
||||||
|
- We replace the `web` entry point by one for the https traffic:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
command:
|
||||||
|
# Traefik will listen to incoming request on the port 443 (https)
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
ports:
|
||||||
|
- "443:443"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We configure the Https let's encrypt challenge:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
command:
|
||||||
|
# Enable a tls challenge named "mytlschallenge"
|
||||||
|
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We add a volume to store our certificates:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
volumes:
|
||||||
|
# Create a letsencrypt dir within the folder where the docker-compose file is
|
||||||
|
- "./letsencrypt:/letsencrypt"
|
||||||
|
|
||||||
|
command:
|
||||||
|
# Tell to store the certificate on a path under our volume
|
||||||
|
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We configure the `whoami` service to tell Traefik to use the certificate resolver named `mytlschallenge` we just configured:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
# Uses the Host rule to define which certificate to issue
|
||||||
|
- "traefik.http.routers.whoami.tls.certresolver=mytlschallenge"
|
||||||
|
```
|
|
@ -0,0 +1,26 @@
|
||||||
|
version: "3.3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
traefik:
|
||||||
|
image: "traefik:v2.0.0-beta1"
|
||||||
|
container_name: "traefik"
|
||||||
|
command:
|
||||||
|
#- "--log.level=DEBUG"
|
||||||
|
- "--api=true"
|
||||||
|
- "--providers.docker=true"
|
||||||
|
- "--providers.docker.exposedbydefault=false"
|
||||||
|
- "--entrypoints.web.address=:80"
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||||
|
|
||||||
|
whoami:
|
||||||
|
image: "containous/whoami"
|
||||||
|
container_name: "simple-service"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
|
||||||
|
- "traefik.http.routers.whoami.entrypoints=web"
|
|
@ -0,0 +1,90 @@
|
||||||
|
# Docker-compose basic example
|
||||||
|
|
||||||
|
In this section we quickly go over a basic docker-compose file exposing a simple service using the docker provider.
|
||||||
|
This will also be used as a starting point for the the other docker-compose guides.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
- Edit a `docker-compose.yml` file with the following content:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
--8<-- "content/user-guides/docker-compose/basic-example/docker-compose.yml"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `whoami.localhost` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
||||||
|
- Run `docker-compose up -d` within the folder where you created the previous file.
|
||||||
|
- Wait a bit and visit `http://your_own_domain` to confirm everything went fine.
|
||||||
|
You should see the output of the whoami service. Something similar to:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Hostname: d7f919e54651
|
||||||
|
IP: 127.0.0.1
|
||||||
|
IP: 192.168.64.2
|
||||||
|
GET / HTTP/1.1
|
||||||
|
Host: whoami.localhost
|
||||||
|
User-Agent: curl/7.52.1
|
||||||
|
Accept: */*
|
||||||
|
Accept-Encoding: gzip
|
||||||
|
X-Forwarded-For: 192.168.64.1
|
||||||
|
X-Forwarded-Host: whoami.localhost
|
||||||
|
X-Forwarded-Port: 80
|
||||||
|
X-Forwarded-Proto: http
|
||||||
|
X-Forwarded-Server: 7f0c797dbc51
|
||||||
|
X-Real-Ip: 192.168.64.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
- As an example we use [whoami](https://github.com/containous/whoami) (a tiny Go server that prints os information and HTTP request to output) which was used to define our `simple-service` container.
|
||||||
|
|
||||||
|
- We define an entry point, along with the exposure of the matching port within docker-compose, which basically allow us to "open and accept" HTTP traffic:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
command:
|
||||||
|
# Traefik will listen to incoming request on the port 80 (HTTP)
|
||||||
|
- "--entrypoints.web.address=:80"
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
```
|
||||||
|
|
||||||
|
- We expose the Traefik API to be able to check the configuration if needed:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
command:
|
||||||
|
# Traefik will listen on port 8080 by default for API request.
|
||||||
|
- "--api=true"
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
If you are working on a remote server, you can use the following command to display configuration (require `curl` & `jq`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s 127.0.0.1:8080/api/rawdata | jq .
|
||||||
|
```
|
||||||
|
|
||||||
|
- We allow Traefik to gather configuration from Docker:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
traefik:
|
||||||
|
command:
|
||||||
|
# Enabling docker provider
|
||||||
|
- "--providers.docker=true"
|
||||||
|
# Do not expose containers unless explicitly told so
|
||||||
|
- "--providers.docker.exposedbydefault=false"
|
||||||
|
volumes:
|
||||||
|
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||||
|
|
||||||
|
whoami:
|
||||||
|
labels:
|
||||||
|
# Explicitly tell Traefik to expose this container
|
||||||
|
- "traefik.enable=true"
|
||||||
|
# The domain the service will respond to
|
||||||
|
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
|
||||||
|
# Allow request only from the predefined entry point named "web"
|
||||||
|
- "traefik.http.routers.whoami.entrypoints=web"
|
||||||
|
```
|
|
@ -137,6 +137,12 @@ nav:
|
||||||
- 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md'
|
- 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md'
|
||||||
- 'gRPC Examples': 'user-guides/grpc.md'
|
- 'gRPC Examples': 'user-guides/grpc.md'
|
||||||
- 'Marathon': 'user-guides/marathon.md'
|
- 'Marathon': 'user-guides/marathon.md'
|
||||||
|
- 'Docker':
|
||||||
|
- 'Basic Example': 'user-guides/docker-compose/basic-example/index.md'
|
||||||
|
- 'HTTPS with Let''s Encrypt':
|
||||||
|
- 'TLS Challenge': 'user-guides/docker-compose/acme-tls/index.md'
|
||||||
|
- 'HTTP Challenge': 'user-guides/docker-compose/acme-http/index.md'
|
||||||
|
- 'DNS Challenge': 'user-guides/docker-compose/acme-dns/index.md'
|
||||||
- 'Contributing':
|
- 'Contributing':
|
||||||
- 'Thank You!': 'contributing/thank-you.md'
|
- 'Thank You!': 'contributing/thank-you.md'
|
||||||
- 'Submitting Issues': 'contributing/submitting-issues.md'
|
- 'Submitting Issues': 'contributing/submitting-issues.md'
|
||||||
|
|
Loading…
Reference in a new issue