LocalCerts

Automatic HTTPS and local domain routing for Docker Compose services using Traefik, DPS and Step-CA.

Created by @Sajito

## Setup 1. Clone this repository and navigate into the directory. 2. Start the services: ```shell docker compose up -d ``` 3. Trust the Step-CA root certificate: Download the `roots.pem` from [https://localhost:9000/roots.pem](https://localhost:9000/roots.pem) and trust it on your system. This is necessary for the certificates to be trusted by your browser. - Linux ```shell sudo trust anchor --store roots.pem ``` - Windows ```powershell Import-Certificate -FilePath "roots.pem" -CertStoreLocation "Cert:\LocalMachine\Root" ``` - macOS ```shell sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain roots.pem ``` ## How to Use 1. Add a label to your docker compose service: ```yaml labels: serviceName: my-app ``` 2. Your service will be accessible at `https://my-app.dev.local`. ## Troubleshooting - If routes do not work you can open the traefik dashboard under [https://traefik.vm](https://traefik.vm) and check if the service and route exist. - If your service is not reachable it could mean that traefik did not detect the correct port. You can set the port manually in your docker compose file: ```yaml labels: traefik.http.services.my-app.loadbalancer.server.port: 8080 ``` > [!IMPORTANT] > For each overwritten port you need to specify a custom `service-label` `traefik.http.services.[service-label]`. Otherwise the custom port will not be detected. - If certificates are not renewed or have expired ```shell docker compose up -d --force-recreate traefik ``` ## Tipps ### Custom Domain Suffix For example `dev.cool` 😎 Replace `.dev.local` with your custom domain suffix in the `config/traefik/traefik.yml` file: ```diff docker: defaultRule: | - Host(`{{ trim (index .Labels "serviceName") }}.dev.local`) {{range $i, $domain := splitList "," (index .Labels "serviceDomains")}}{{if ne $domain ""}}|| Host(`{{$domain}}`){{end}}{{end}} + Host(`{{ trim (index .Labels "serviceName") }}.dev.cool`) {{range $i, $domain := splitList "," (index .Labels "serviceDomains")}}{{if ne $domain ""}}|| Host(`{{$domain}}`){{end}}{{end}} constraints: LabelRegex(`serviceName`, `.+`) && !Label(`com.docker.compose.oneoff`, `True`) ``` Replace `.dev.local` with your custom domain suffix in the `config/dns/config.sample.json` file: ```diff { "id": 2, - "hostname": ".dev.local", + "hostname": ".dev.cool", "ip": "", ``` Restart the docker services to apply the changes: ```shell docker compose up -d --force-recreate ``` ### Custom Domain Per Service If you want a single service to have a custom domain you can use the `serviceDomains` label. This will override the default domain suffix: ```yaml labels: serviceName: my-app serviceDomains: my-app.very.cool ``` The service would now be reachable at `https://my-app.very.cool` and `https://my-app.dev.local`. ### Certificate Lifetime To ensure Traefik has enough time to renew certificates, increase their duration: ```shell docker compose exec step step ca provisioner update acme \ --x509-min-dur=20m \ --x509-max-dur=8760h \ --x509-default-dur=2160h ``` ### Use the preconfigured services If you use the preconfigured services, you can add the following snippet to you `.bashrc`/`.zshrc` to easily start, stop, and manage the services. ```shell dev () { PROJECT_DIR="$HOME/Projects/dev/services" case "$1" in (start) shift docker compose -f "$PROJECT_DIR/docker-compose.yml" --profile "$@" up -d ;; (restart) shift docker compose -f "$PROJECT_DIR/docker-compose.yml" --profile "$@" restart ;; (stop) shift docker compose -f "$PROJECT_DIR/docker-compose.yml" --profile "$@" down --remove-orphans ;; (logs) shift docker compose -f "$PROJECT_DIR/docker-compose.yml" --profile "$@" logs -f ;; (*) echo "Usage: dev {start|restart|stop|logs} [services...]" ;; esac } ```