├── .gitignore ├── LICENSE ├── README.md └── docker-compose.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | data/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Igor Bubelov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Traefik + Let’s Encrypt + Docker Compose 2 | 3 | This guide shows you how to deploy your containers behind Traefik reverse-proxy. It will obtain and refresh HTTPS certificates automatically and it comes with password-protected Traefik dashboard. 4 | 5 | ## Testing on Your Local Computer 6 | 7 | ### Step 1: Make Sure You Have Required Dependencies 8 | 9 | - Git 10 | - Docker 11 | - Docker Compose 12 | 13 | #### Example Installation on Debian-based Systems: 14 | 15 | ``` 16 | sudo apt install git docker.io docker-compose 17 | ``` 18 | 19 | ### Step 2: Clone the Repository 20 | 21 | ```bash 22 | git clone git@github.com:bubelov/traefik-letsencrypt-compose.git 23 | cd traefik-letsencrypt-compose 24 | ``` 25 | 26 | ### Step 3: Add Environment Variables 27 | 28 | ```bash 29 | nano .env 30 | ``` 31 | 32 | ```bash 33 | DOMAIN=localhost 34 | EMAIL=admin@localhost 35 | CERT_RESOLVER= 36 | TRAEFIK_USER=admin 37 | TRAEFIK_PASSWORD_HASH=$2y$10$zi5n43jq9S63gBqSJwHTH.nCai2vB0SW/ABPGg2jSGmJBVRo0A.ni 38 | ``` 39 | 40 | Note that you should leave `CERT_RESOLVER` variable empty if you test your deployment locally. The password is `admin` and you might want to change it before deploying to production. 41 | 42 | ### Step 4: Set Your Own Password 43 | 44 | If you're curious about HTTP basic auth and how it can be used with Traefik, you can read [the full post](https://bubelov.com/blog/basic-auth-reverse-proxy/). Here is the excerpt and it assumes you already installed `htpasswd`: 45 | 46 | ```bash 47 | htpasswd -nBC 10 admin 48 | 49 | New password: 50 | Re-type new password: 51 | 52 | admin:$2y$10$zi5n43jq9S63gBqSJwHTH.nCai2vB0SW/ABPGg2jSGmJBVRo0A.ni 53 | ``` 54 | 55 | The output has the following format: `username`:`password_hash`. The username doesn't have to be `admin`, feel free to change it (in the first line). 56 | 57 | You can paste the username into the `TRAEFIK_USER` environment variable. The other part, `hashedPassword`, should be assigned to `TRAEFIK_PASSWORD_HASH`. Now you have your own `username`:`password` pair. 58 | 59 | ### Step 5: Launch Your Deployment 60 | 61 | ```bash 62 | sudo docker-compose up -d 63 | ``` 64 | 65 | ### Step 6: Test Your Deployment 66 | 67 | ```bash 68 | curl --insecure https://localhost/ 69 | ``` 70 | 71 | You can also test it in the browser: 72 | 73 | https://localhost/ 74 | 75 | https://traefik.localhost/ 76 | 77 | ## Deploying on a Public Server With Real Domain 78 | 79 | Let's say you have a domain `example.com` and it's DNS records point to your production server. Just repeat the local deployment steps, but don't forget to update `DOMAIN`, `EMAIL` and `CERT_RESOLVER` environment variables. In case of `example.com`, your `.env` file should have the following lines: 80 | 81 | ```bash 82 | DOMAIN=example.com 83 | EMAIL=your@email.com 84 | CERT_RESOLVER=letsencrypt 85 | ``` 86 | 87 | Setting correct email is important because it allows Let’s Encrypt to contact you in case there are any present and future issues with your certificates. 88 | 89 | That's it! Let me know if something was unclear to you or if you find any errors. 90 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | services: 3 | 4 | traefik: 5 | image: traefik:2.4.8 6 | command: 7 | # Try to enable this if something isn't working. 8 | # Chances are, Traefik will tell you why. 9 | # Be careful in production as it exposes the traffic you might not want to expose. 10 | #--log.level=DEBUG 11 | 12 | - --entrypoints.http.address=:80 13 | - --entrypoints.https.address=:443 14 | 15 | - --providers.docker=true 16 | 17 | - --api=true 18 | 19 | # LetsEncrypt Staging Server - uncomment when testing 20 | # - --certificatesResolvers.letsencrypt.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory 21 | 22 | - --certificatesresolvers.letsencrypt.acme.httpchallenge=true 23 | - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http 24 | - --certificatesresolvers.letsencrypt.acme.email=${EMAIL} 25 | - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json 26 | labels: 27 | # Redirect all HTTP traffic to HTTPS 28 | - traefik.http.routers.to-https.rule=HostRegexp(`{host:.+}`) 29 | - traefik.http.routers.to-https.entrypoints=http 30 | - traefik.http.routers.to-https.middlewares=to-https 31 | 32 | - traefik.http.routers.traefik.rule=Host(`traefik.${DOMAIN}`) 33 | - traefik.http.routers.traefik.entrypoints=https 34 | - traefik.http.routers.traefik.middlewares=auth 35 | - traefik.http.routers.traefik.service=api@internal 36 | - traefik.http.routers.traefik.tls=true 37 | - traefik.http.routers.traefik.tls.certresolver=${CERT_RESOLVER} 38 | 39 | - traefik.http.middlewares.to-https.redirectscheme.scheme=https 40 | - traefik.http.middlewares.auth.basicauth.users=${TRAEFIK_USER}:${TRAEFIK_PASSWORD_HASH} 41 | ports: 42 | - 80:80 43 | - 443:443 44 | volumes: 45 | - ./data/letsencrypt:/letsencrypt 46 | - /var/run/docker.sock:/var/run/docker.sock:ro 47 | 48 | whoami: 49 | image: containous/whoami 50 | labels: 51 | - traefik.http.routers.https.rule=Host(`${DOMAIN}`) 52 | - traefik.http.routers.https.entrypoints=https 53 | - traefik.http.routers.https.tls=true 54 | - traefik.http.routers.https.tls.certresolver=${CERT_RESOLVER} 55 | --------------------------------------------------------------------------------