From c967aaccf4a91d9c3d4fdfe50e2f1cb19b4d1fe6 Mon Sep 17 00:00:00 2001 From: Xenion1987 <39803750+Xenion1987@users.noreply.github> Date: Tue, 25 Apr 2023 12:39:11 +0200 Subject: [PATCH 1/2] add traefik config example --- .gitignore | 7 ++ README.md | 14 ++- config/traefik/README.md | 33 ++++++++ config/traefik/config/dynamic.yml | 53 ++++++++++++ config/traefik/docker-compose.override.yml | 99 ++++++++++++++++++++++ config/traefik/logs/.gitkeep | 0 config/traefik/ssl/.gitkeep | 0 docker-compose.override.yml | 13 +++ docker-compose.yml | 59 ++++++------- env | 38 +++++++-- 10 files changed, 272 insertions(+), 44 deletions(-) create mode 100644 config/traefik/README.md create mode 100644 config/traefik/config/dynamic.yml create mode 100644 config/traefik/docker-compose.override.yml create mode 100644 config/traefik/logs/.gitkeep create mode 100644 config/traefik/ssl/.gitkeep create mode 100644 docker-compose.override.yml diff --git a/.gitignore b/.gitignore index fe01782..c9cd03c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,10 @@ charts/**/charts/ # Compose filesystem /docker + +# Traefik filesystem +config/traefik/logs/* +!config/traefik/logs/.gitkeep + +config/traefik/ssl/* +!config/traefik/ssl/.gitkeep diff --git a/README.md b/README.md index bc78547..4c87c08 100644 --- a/README.md +++ b/README.md @@ -25,17 +25,19 @@ Other resources: ## Alternatively get started with Docker Compose -The dockerfile has been revamped to make it easier to get started, by default the base image selected is 5 which will pull in the latest v5 stable image. +The dockerfile has been revamped to make it easier to get started, by default the base image selected is 5 which will pull in the latest v5 stable image. ```bash git clone https://github.com/invoiceninja/dockerfiles.git cd dockerfiles ``` -Instead of defining our environment variables inside our docker-compose.yml file we now define this in the `env` file, open this file up and insert your `APP_URL`, `APP_KEY` and update the rest of the variables as required. +Instead of defining our environment variables inside our docker-compose.yml file we now define this in the `env` file, open this file up and insert your `APP_URL_*` variables, `APP_KEY` and update the rest of the variables as required. ``` -APP_URL=http://in.localhost:8003/ +APP_URL_SCHEME=http +APP_URL_DOMAIN=in.localhost +APP_URL_PORT=8003 APP_KEY= APP_DEBUG=true REQUIRE_HTTPS=false @@ -62,6 +64,12 @@ chmod 755 docker/app/public sudo chown -R 1500:1500 docker/app ``` +If you want to modify the docker compose stack (e.g. changing the `nginx` port), please do any changes in the `docker-compose.override.yml` file. When starting the stack, both files will be merged. You can check the merged config from the terminal by executing + +```bash +docker compose config +``` + ### Note for people running the container locally on their PC ### If you are running the container locally, then the container will need to resolve the host, to support this you will want to insert your LAN IP address and the host name in the hosts file located in ```config/hosts``` diff --git a/config/traefik/README.md b/config/traefik/README.md new file mode 100644 index 0000000..72dc2fa --- /dev/null +++ b/config/traefik/README.md @@ -0,0 +1,33 @@ +# Docker for [Invoice Ninja](https://www.invoiceninja.com/) using [Traefik proxy](https://doc.traefik.io/traefik/) + +## Why use Traefik Proxy + +Traefik is an open-source Edge Router that makes publishing your services a fun and easy experience. It receives requests on behalf of your system and finds out which components are responsible for handling them. + +What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services. The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request. + +Traefik in combination with [Cloudflare](https://cloudflare.com) receives and serves all SSL certificates for each service domain automaticly by issuing a wildcard SSL certificate. + +## Requirements + +1. A domain using the Cloudflare nameservers [Cloudflare Docs](https://developers.cloudflare.com/registrar/get-started/transfer-domain-to-cloudflare/) +1. An API token with at least the following permissions: `Zone:Read, Zone Settings:Read, DNS:Edit` [Cloudflare Docs](https://developers.cloudflare.com/fundamentals/api/) + +## Usage + +1. Copy the [docker-compose.override.yml](./docker-compose.override.yml) to the repositorie's root directory +1. Set the Traefik proxy vars in the [env](../../env) file +1. Update the basic-auth username and password in [dynamic.yml](./config/dynamic.yml) +1. Start the docker compose stack + +A few seconds later, you should be able to visit `https://${APP_URL_DOMAIN}:8080/dashboard/` and should be prompted for a username and password. If you have not changed it, it should be `username` and `EncryptedPassword`. + +If there are no errors listed, you should be able to visit InvoiceNinja via `${APP_URL}`. + +## Troubleshooting + +If anything does not work as expected, consider checking Traefik's container logs via + +```bash +docker compose logs -tf traefik +``` diff --git a/config/traefik/config/dynamic.yml b/config/traefik/config/dynamic.yml new file mode 100644 index 0000000..8c807c5 --- /dev/null +++ b/config/traefik/config/dynamic.yml @@ -0,0 +1,53 @@ +tls: + options: + default: + minVersion: VersionTLS12 + sniStrict: true + cipherSuites: + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 + - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 + - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 + - TLS_CHACHA20_POLY1305_SHA256 + curvePreferences: + - CurveP521 + - CurveP384 +http: + middlewares: + default: + chain: + middlewares: + - default-security-headers + - gzip + secHeaders: + chain: + middlewares: + - default-security-headers + - gzip + + traefik-auth: + basicauth: + # Encrypt Password via 'echo $(htpasswd -nB username) | sed -e s/\\$/\\$\\$/g' + # Username: username + # Password: EncryptedPassword + users: username:$2y$05$lz9I2C9KoUdHwCOmPsKeBOU7EYMKMyzzCQs3KEmg4JZZL7ahLzjGO + + default-security-headers: + headers: + browserXssFilter: true + contentTypeNosniff: true + forceSTSHeader: true + frameDeny: true + stsIncludeSubdomains: true + stsPreload: true + stsSeconds: 31536000 + customFrameOptionsValue: "SAMEORIGIN" + referrerPolicy: "no-referrer" + customRequestHeaders: + X-Forwarded-Proto: "https" + gzip: + compress: {} diff --git a/config/traefik/docker-compose.override.yml b/config/traefik/docker-compose.override.yml new file mode 100644 index 0000000..c56e726 --- /dev/null +++ b/config/traefik/docker-compose.override.yml @@ -0,0 +1,99 @@ +version: "3.7" + +services: + traefik: + image: traefik:latest + container_name: traefik + restart: unless-stopped + env_file: env + ports: + # Run traefik on port 80 and 443 + # Feel free to modify depending what port is already occupied + - "80:80" + - "443:443" + # Run traefik dashboard on port 8080 + # Feel free to modify depending what port is already occupied + - "8080:8080" + command: + # By default, the level is set to ERROR. Alternative logging levels are + # DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. + - --log.level=ERROR + - --global.sendAnonymousUsage=false + # Enable Dashboard + - --api.insecure=false + - --api.dashboard=true + - --api.debug=true + # We are using Docker + - --providers.docker=true + - --providers.docker.exposedbydefault=false + # (Optional) Set default hostname if not given explicitly + - --providers.docker.defaultRule=Host(`${APP_URL_DOMAIN}`) + # Listen on port 80 (http) + - --entrypoints.web.address=:80 + # Listen on port 443 (https) + - --entrypoints.websecure.address=:443 + # Listen on port 8080 (traefik Dashboard) + - --entrypoints.traefik-dashboard.address=:8080 + # Watch dynamic configuration file + - --providers.file.directory=/config + - --providers.file.watch=true + # Enable Access Log + - --accesslog.filepath=/var/log/www/access.log + # Automaticly redirect from http to https + - --entrypoints.web.http.redirections.entryPoint.to=websecure + - --entrypoints.web.http.redirections.entryPoint.scheme=https + + ################ START SSL configuration ################ + # ---------> Cloudflare <--------- + # DNS challenge via Cloudflare + - --certificatesresolvers.cloudflare.acme.email=${ACME_EMAIL} + - --certificatesresolvers.cloudflare.acme.storage=/ssl/acme.json + - --certificatesresolvers.cloudflare.acme.dnsChallenge.provider=cloudflare + - --certificatesresolvers.cloudflare.acme.dnsChallenge.delayBeforeCheck=60 + - --certificatesresolvers.cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53 + # (Optional) Use testing server before receiving the productive ssl certificate + #- --certificatesresolvers.cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory + - --entrypoints.websecure.http.tls.domains[0].main=${APP_URL_DOMAIN} + # (Optional) Use only, if you are able to receive a wildcard ssl certificate + # - --entrypoints.websecure.http.tls.domains[0].main=*.${CLOUDFLARE_DOMAIN} + # -------------------------------- + ################ END SSL configuration ################ + volumes: + # So that Traefik can listen to the Docker events + - /var/run/docker.sock:/var/run/docker.sock:ro + # Dynamic configuration files + - ./config/traefik/config:/config + # Enable Access Log + - ./config/traefik/logs/:/var/log/www/ + # LetsEncrypt Configuration Storage + - ./config/traefik/ssl:/ssl + labels: + # Enable Traefik + - traefik.enable=true + # Set Network to use + - traefik.docker.network=invoiceninja + # Load dynamic config + - traefik.http.routers.traefik-dashboard.middlewares=default@file + # Service related labels + - traefik.http.routers.traefik-dashboard.entrypoints=traefik-dashboard + - traefik.http.routers.traefik-dashboard.middlewares=traefik-auth@file + - traefik.http.routers.traefik-dashboard.service=api@internal + - traefik.http.routers.traefik-dashboard.tls=true + - traefik.http.routers.traefik-dashboard.tls.certResolver=cloudflare + - traefik.http.routers.traefik-dashboard.rule=Host(`${APP_URL_DOMAIN}`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)) + networks: + - invoiceninja + + server: + labels: + # Enable Traefik + - "traefik.enable=true" + # Set Network to use + - "traefik.docker.network=invoiceninja" + # Load dynamic config + - "traefik.http.routers.ninja-nginx.middlewares=default@file" + # Service related labels + - "traefik.http.routers.ninja-nginx.entrypoints=websecure" + - "traefik.http.routers.ninja-nginx.tls=true" + - "traefik.http.routers.ninja-nginx.tls.certResolver=cloudflare" + - "traefik.http.routers.ninja-nginx.rule=Host(`${APP_URL_DOMAIN}`)" diff --git a/config/traefik/logs/.gitkeep b/config/traefik/logs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/config/traefik/ssl/.gitkeep b/config/traefik/ssl/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 0000000..5dd0d69 --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,13 @@ +version: "3.7" + +services: + server: + # Run webserver nginx on port 80 + # Feel free to modify depending what port is already occupied + ports: + - "80:80" + # - "443:443" + db: + # Feel free to modify depending what port is already occupied + ports: + - "3305:3306" diff --git a/docker-compose.yml b/docker-compose.yml index 19ed2b7..809efb2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,13 +12,9 @@ services: - ./docker/app/public:/var/www/app/public:ro depends_on: - app - # Run webserver nginx on port 80 - # Feel free to modify depending what port is already occupied - ports: - - "80:80" - #- "443:443" networks: - invoiceninja + - invoiceninja-internal extra_hosts: - "in5.localhost:192.168.0.124 " #host and ip @@ -34,53 +30,52 @@ services: - db networks: - invoiceninja + - invoiceninja-internal extra_hosts: - "in5.localhost:192.168.0.124 " #host and ip db: image: mysql:8 -# When running on ARM64 use MariaDB instead of MySQL -# image: mariadb:10.4 -# For auto DB backups comment out image and use the build block below -# build: -# context: ./config/mysql - ports: - - "3305:3306" + # When running on ARM64 use MariaDB instead of MySQL + # image: mariadb:10.4 + # For auto DB backups comment out image and use the build block below + # build: + # context: ./config/mysql restart: always env_file: env volumes: - ./docker/mysql/data:/var/lib/mysql:rw,delegated - # remove comments for next 4 lines if you want auto sql backups #- ./docker/mysql/bak:/backups:rw #- ./config/mysql/backup-script:/etc/cron.daily/daily:ro #- ./config/mysql/backup-script:/etc/cron.weekly/weekly:ro #- ./config/mysql/backup-script:/etc/cron.monthly/monthly:ro networks: - - invoiceninja + - invoiceninja-internal extra_hosts: - "in5.localhost:192.168.0.124 " #host and ip - - # THIS IS ONLY A VALID CONFIGURATION FOR IN 4. DO NOT USE FOR IN 5. - # cron: - # image: invoiceninja/invoiceninja:alpine-4 - # volumes: + # THIS IS ONLY A VALID CONFIGURATION FOR IN 4. DO NOT USE FOR IN 5. + # cron: + # image: invoiceninja/invoiceninja:alpine-4 + # volumes: # - ./docker/app/public:/var/www/app/public:rw,delegated # - ./docker/app/storage:/var/www/app/storage:rw,delegated # - ./docker/app/public/logo:/var/www/app/public/logo:rw,delegated - # entrypoint: | - # /bin/sh -c 'sh -s < +## IN application vars +# http or https +APP_URL_SCHEME=http +# Domain name you want to use for InvoiceNinja +APP_URL_DOMAIN=in.localhost +# Port where InvoiceNinja should listen on +APP_URL_PORT=8003 + +## Example https variables: +# APP_URL_SCHEME=https +# APP_URL_DOMAIN=ninja.domain.tld +# APP_URL_PORT=443 +# REQUIRE_HTTPS=true + +# This variable should not be modified, except you know what you do +APP_URL="${APP_URL_SCHEME:-http}://${APP_URL_DOMAIN:-in.localhost}:${APP_URL_PORT:-8003}" + +APP_KEY='' APP_DEBUG=true REQUIRE_HTTPS=false PHANTOMJS_PDF_GENERATION=false PDF_GENERATOR=snappdf TRUSTED_PROXIES='*' - QUEUE_CONNECTION=database -# DB connection +## DB connection DB_HOST=db DB_PORT=3306 DB_DATABASE=ninja DB_USERNAME=ninja DB_PASSWORD=ninja -# Create initial user +## Create initial user # Default to these values if empty # IN_USER_EMAIL=admin@example.com # IN_PASSWORD=changeme! IN_USER_EMAIL= IN_PASSWORD= -# Mail options +## Mail options MAIL_MAILER=log MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 @@ -34,12 +48,18 @@ MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS='user@example.com' MAIL_FROM_NAME='Self Hosted User' -# MySQL +## MySQL MYSQL_ROOT_PASSWORD=ninjaAdm1nPassword MYSQL_USER=ninja MYSQL_PASSWORD=ninja MYSQL_DATABASE=ninja -# V4 env vars +## V4 env vars # DB_STRICT=false # APP_CIPHER=AES-256-CBC + +## Traefik proxy vars +CLOUDFLARE_EMAIL=cloudflare@domain.tld +CLOUDFLARE_DNS_API_TOKEN=yourApiTokenHere +CLOUDFLARE_DOMAIN=domain.tld +ACME_EMAIL=ssl-maintainer@domain.tld From e1b113bba19293b1b8340e4780279fcd98992c4d Mon Sep 17 00:00:00 2001 From: Xenion1987 <39803750+Xenion1987@users.noreply.github> Date: Fri, 28 Apr 2023 19:29:31 +0200 Subject: [PATCH 2/2] add http-01 example --- .gitignore | 5 +- config/traefik/README.md | 6 +- config/traefik/config/dynamic-http.yml | 42 ++++++++ config/traefik/config/dynamic-tls.yml | 19 ++++ config/traefik/config/dynamic.yml | 53 ---------- config/traefik/docker-compose.override.yml | 99 ------------------- .../docker-compose.override.yml | 98 ++++++++++++++++++ .../http-01/docker-compose.override.yml | 93 +++++++++++++++++ config/traefik/{ssl => ssl-files}/.gitkeep | 0 env | 3 +- 10 files changed, 260 insertions(+), 158 deletions(-) create mode 100644 config/traefik/config/dynamic-http.yml create mode 100644 config/traefik/config/dynamic-tls.yml delete mode 100644 config/traefik/config/dynamic.yml delete mode 100644 config/traefik/docker-compose.override.yml create mode 100644 config/traefik/examples/dns-01-cloudflare/docker-compose.override.yml create mode 100644 config/traefik/examples/http-01/docker-compose.override.yml rename config/traefik/{ssl => ssl-files}/.gitkeep (100%) diff --git a/.gitignore b/.gitignore index c9cd03c..adeb3f4 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,5 @@ charts/**/charts/ # Traefik filesystem config/traefik/logs/* !config/traefik/logs/.gitkeep - -config/traefik/ssl/* -!config/traefik/ssl/.gitkeep +config/traefik/ssl-files/* +!config/traefik/ssl-files/.gitkeep diff --git a/config/traefik/README.md b/config/traefik/README.md index 72dc2fa..a92e3d1 100644 --- a/config/traefik/README.md +++ b/config/traefik/README.md @@ -15,9 +15,9 @@ Traefik in combination with [Cloudflare](https://cloudflare.com) receives and se ## Usage -1. Copy the [docker-compose.override.yml](./docker-compose.override.yml) to the repositorie's root directory +1. Either copy the [HTTP-01 docker-compose.override.yml](./examples/http-01/docker-compose.override.yml) to the repositorie's root directory for issueing ssl certificates via `http-01` challenge, or copy the [DNS-01 cloudflare docker-compose.override.yml](./examples/dns-01-cloudflare/docker-compose.override.yml) to use Cloudflare and `dns-01` challenge. 1. Set the Traefik proxy vars in the [env](../../env) file -1. Update the basic-auth username and password in [dynamic.yml](./config/dynamic.yml) +1. Update the basic-auth username and password in [dynamic-http.yml](./config/dynamic-http.yml) 1. Start the docker compose stack A few seconds later, you should be able to visit `https://${APP_URL_DOMAIN}:8080/dashboard/` and should be prompted for a username and password. If you have not changed it, it should be `username` and `EncryptedPassword`. @@ -31,3 +31,5 @@ If anything does not work as expected, consider checking Traefik's container log ```bash docker compose logs -tf traefik ``` + +and check the official [Traefik Documentation](https://doc.traefik.io/traefik/). diff --git a/config/traefik/config/dynamic-http.yml b/config/traefik/config/dynamic-http.yml new file mode 100644 index 0000000..affc12a --- /dev/null +++ b/config/traefik/config/dynamic-http.yml @@ -0,0 +1,42 @@ +--- +http: + middlewares: + basic-auth: + basicAuth: + users: + # Generate encrypted password string via 'htpasswd -nB username' + # enter your password twice and paste the output here + # myusername:mysafepassword + - "myusername:$2y$05$Tx/.9qaFoZiLi41ZDvO1fOqiSohhuAr8jf9yEbQxZWlqANMKQYnYe" + gzip: + compress: {} + security-headers: + headers: + browserXssFilter: true + contentTypeNosniff: true + forceSTSHeader: true + frameDeny: true + stsIncludeSubdomains: true + stsPreload: true + stsSeconds: 31536000 + customFrameOptionsValue: "SAMEORIGIN" + referrerPolicy: "no-referrer" + customRequestHeaders: + X-Forwarded-Proto: "https" + strict-ratelimit: + rateLimit: + average: 10 + burst: 50 + default-ratelimit: + rateLimit: + average: 100 + burst: 50 + high-ratelimit: + rateLimit: + average: 1000 + burst: 500 + default: + chain: + middlewares: + - "security-headers" + - "gzip" diff --git a/config/traefik/config/dynamic-tls.yml b/config/traefik/config/dynamic-tls.yml new file mode 100644 index 0000000..ca49a0a --- /dev/null +++ b/config/traefik/config/dynamic-tls.yml @@ -0,0 +1,19 @@ +--- +tls: + options: + default: + minVersion: VersionTLS12 + sniStrict: true + cipherSuites: + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 + - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 + - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 + - TLS_CHACHA20_POLY1305_SHA256 + curvePreferences: + - CurveP521 + - CurveP384 diff --git a/config/traefik/config/dynamic.yml b/config/traefik/config/dynamic.yml deleted file mode 100644 index 8c807c5..0000000 --- a/config/traefik/config/dynamic.yml +++ /dev/null @@ -1,53 +0,0 @@ -tls: - options: - default: - minVersion: VersionTLS12 - sniStrict: true - cipherSuites: - - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 - - TLS_AES_128_GCM_SHA256 - - TLS_AES_256_GCM_SHA384 - - TLS_CHACHA20_POLY1305_SHA256 - curvePreferences: - - CurveP521 - - CurveP384 -http: - middlewares: - default: - chain: - middlewares: - - default-security-headers - - gzip - secHeaders: - chain: - middlewares: - - default-security-headers - - gzip - - traefik-auth: - basicauth: - # Encrypt Password via 'echo $(htpasswd -nB username) | sed -e s/\\$/\\$\\$/g' - # Username: username - # Password: EncryptedPassword - users: username:$2y$05$lz9I2C9KoUdHwCOmPsKeBOU7EYMKMyzzCQs3KEmg4JZZL7ahLzjGO - - default-security-headers: - headers: - browserXssFilter: true - contentTypeNosniff: true - forceSTSHeader: true - frameDeny: true - stsIncludeSubdomains: true - stsPreload: true - stsSeconds: 31536000 - customFrameOptionsValue: "SAMEORIGIN" - referrerPolicy: "no-referrer" - customRequestHeaders: - X-Forwarded-Proto: "https" - gzip: - compress: {} diff --git a/config/traefik/docker-compose.override.yml b/config/traefik/docker-compose.override.yml deleted file mode 100644 index c56e726..0000000 --- a/config/traefik/docker-compose.override.yml +++ /dev/null @@ -1,99 +0,0 @@ -version: "3.7" - -services: - traefik: - image: traefik:latest - container_name: traefik - restart: unless-stopped - env_file: env - ports: - # Run traefik on port 80 and 443 - # Feel free to modify depending what port is already occupied - - "80:80" - - "443:443" - # Run traefik dashboard on port 8080 - # Feel free to modify depending what port is already occupied - - "8080:8080" - command: - # By default, the level is set to ERROR. Alternative logging levels are - # DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. - - --log.level=ERROR - - --global.sendAnonymousUsage=false - # Enable Dashboard - - --api.insecure=false - - --api.dashboard=true - - --api.debug=true - # We are using Docker - - --providers.docker=true - - --providers.docker.exposedbydefault=false - # (Optional) Set default hostname if not given explicitly - - --providers.docker.defaultRule=Host(`${APP_URL_DOMAIN}`) - # Listen on port 80 (http) - - --entrypoints.web.address=:80 - # Listen on port 443 (https) - - --entrypoints.websecure.address=:443 - # Listen on port 8080 (traefik Dashboard) - - --entrypoints.traefik-dashboard.address=:8080 - # Watch dynamic configuration file - - --providers.file.directory=/config - - --providers.file.watch=true - # Enable Access Log - - --accesslog.filepath=/var/log/www/access.log - # Automaticly redirect from http to https - - --entrypoints.web.http.redirections.entryPoint.to=websecure - - --entrypoints.web.http.redirections.entryPoint.scheme=https - - ################ START SSL configuration ################ - # ---------> Cloudflare <--------- - # DNS challenge via Cloudflare - - --certificatesresolvers.cloudflare.acme.email=${ACME_EMAIL} - - --certificatesresolvers.cloudflare.acme.storage=/ssl/acme.json - - --certificatesresolvers.cloudflare.acme.dnsChallenge.provider=cloudflare - - --certificatesresolvers.cloudflare.acme.dnsChallenge.delayBeforeCheck=60 - - --certificatesresolvers.cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53 - # (Optional) Use testing server before receiving the productive ssl certificate - #- --certificatesresolvers.cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory - - --entrypoints.websecure.http.tls.domains[0].main=${APP_URL_DOMAIN} - # (Optional) Use only, if you are able to receive a wildcard ssl certificate - # - --entrypoints.websecure.http.tls.domains[0].main=*.${CLOUDFLARE_DOMAIN} - # -------------------------------- - ################ END SSL configuration ################ - volumes: - # So that Traefik can listen to the Docker events - - /var/run/docker.sock:/var/run/docker.sock:ro - # Dynamic configuration files - - ./config/traefik/config:/config - # Enable Access Log - - ./config/traefik/logs/:/var/log/www/ - # LetsEncrypt Configuration Storage - - ./config/traefik/ssl:/ssl - labels: - # Enable Traefik - - traefik.enable=true - # Set Network to use - - traefik.docker.network=invoiceninja - # Load dynamic config - - traefik.http.routers.traefik-dashboard.middlewares=default@file - # Service related labels - - traefik.http.routers.traefik-dashboard.entrypoints=traefik-dashboard - - traefik.http.routers.traefik-dashboard.middlewares=traefik-auth@file - - traefik.http.routers.traefik-dashboard.service=api@internal - - traefik.http.routers.traefik-dashboard.tls=true - - traefik.http.routers.traefik-dashboard.tls.certResolver=cloudflare - - traefik.http.routers.traefik-dashboard.rule=Host(`${APP_URL_DOMAIN}`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)) - networks: - - invoiceninja - - server: - labels: - # Enable Traefik - - "traefik.enable=true" - # Set Network to use - - "traefik.docker.network=invoiceninja" - # Load dynamic config - - "traefik.http.routers.ninja-nginx.middlewares=default@file" - # Service related labels - - "traefik.http.routers.ninja-nginx.entrypoints=websecure" - - "traefik.http.routers.ninja-nginx.tls=true" - - "traefik.http.routers.ninja-nginx.tls.certResolver=cloudflare" - - "traefik.http.routers.ninja-nginx.rule=Host(`${APP_URL_DOMAIN}`)" diff --git a/config/traefik/examples/dns-01-cloudflare/docker-compose.override.yml b/config/traefik/examples/dns-01-cloudflare/docker-compose.override.yml new file mode 100644 index 0000000..c29e9c8 --- /dev/null +++ b/config/traefik/examples/dns-01-cloudflare/docker-compose.override.yml @@ -0,0 +1,98 @@ +version: "3.7" + +services: + traefik: + # The official v2 Traefik docker image + image: traefik:latest + container_name: traefik + restart: always + env_file: env + ports: + - "80:80" + - "443:443" + - "8080:8080" + networks: + - "invoiceninja" + volumes: + # So that Traefik can listen to the Docker events + - "/var/run/docker.sock:/var/run/docker.sock:ro" + # Dynamic configuration files + - "./config/traefik/config:/conf:ro" + # Enable Access Log + - "./config/traefik/logs/:/var/log/www/" + # LetsEncrypt Configuration Storage + - "./config/traefik/ssl-files:/ssl" + command: + # Send usage statistics (or not) + - "--global.sendAnonymousUsage=false" + # By default, the level is set to ERROR. Alternative logging levels are + # DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. + - "--log.level=WARN" + # Enable Access Log + - "--accesslog.filepath=/var/log/www/access.log" + # Enable Dashboard + - "--api.insecure=false" + - "--api.dashboard=true" + - "--api.debug=true" + # We are using Docker + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + # (Optional) Set default hostname if not given explicitly + - "--providers.docker.defaultRule=Host(`${APP_URL_DOMAIN}`)" + # Listen on port 80 (http) + - "--entrypoints.web.address=:80" + # Listen on port 443 (https) + - "--entrypoints.websecure.address=:443" + # Listen on port 8080 (traefik Dashboard) + - "--entrypoints.traefik-dashbaord.address=:8080" + # Watch dynamic configuration file + - "--providers.file.directory=/conf" + - "--providers.file.watch=true" + # Automaticly redirect from http to https + - "--entrypoints.web.http.redirections.entryPoint.to=websecure" + - "--entrypoints.web.http.redirections.entryPoint.scheme=https" + ################ START SSL configuration ################ + # ---------> Cloudflare <--------- + # DNS challenge via Cloudflare + - "--certificatesresolvers.cloudflare.acme.email=${ACME_EMAIL}" + - "--certificatesresolvers.cloudflare.acme.storage=/ssl/acme.json" + - "--certificatesresolvers.cloudflare.acme.dnsChallenge.provider=cloudflare" + - "--certificatesresolvers.cloudflare.acme.dnsChallenge.delayBeforeCheck=60" + - "--certificatesresolvers.cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53" + # (Optional) Use testing server before receiving the productive ssl certificate + #- --certificatesresolvers.cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory + - "--entrypoints.websecure.http.tls.domains[0].main=${APP_URL_DOMAIN}" + # (Optional) Use only, if you are able to receive a wildcard ssl certificate + # - "--entrypoints.websecure.http.tls.domains[0].main=*.${APP_URL_DOMAIN}" + # -------------------------------- + ################ END SSL configuration ################ + labels: + # Enable Traefik + - "traefik.enable=true" + # Set Network to use + - "traefik.docker.network=invoiceninja" + # Set service type + - "traefik.http.routers.traefik-dashbaord.service=api@internal" + # Load dynamic config from conf/*.yml + - "traefik.http.routers.traefik-dashbaord.middlewares=default@file,basic-auth@file" + # Define entrypint to use + - "traefik.http.routers.traefik-dashbaord.entrypoints=traefik-dashbaord" + # Define Hostname and path + - "traefik.http.routers.traefik-dashbaord.rule=Host(`${APP_URL_DOMAIN}`) && PathPrefix(`/api`,`/dashboard`)" + # Enable SSL/TLS + - "traefik.http.routers.traefik-dashbaord.tls=true" + - "traefik.http.routers.traefik-dashbaord.tls.certResolver=cloudflare" + + server: + labels: + # Enable Traefik + - "traefik.enable=true" + # Set Network to use + - "traefik.docker.network=invoiceninja" + # Load dynamic config + - "traefik.http.routers.ninja-nginx.middlewares=default@file" + # Service related labels + - "traefik.http.routers.ninja-nginx.entrypoints=websecure" + - "traefik.http.routers.ninja-nginx.rule=Host(`${APP_URL_DOMAIN}`)" + - "traefik.http.routers.ninja-nginx.tls=true" + - "traefik.http.routers.ninja-nginx.tls.certResolver=cloudflare" diff --git a/config/traefik/examples/http-01/docker-compose.override.yml b/config/traefik/examples/http-01/docker-compose.override.yml new file mode 100644 index 0000000..28388ff --- /dev/null +++ b/config/traefik/examples/http-01/docker-compose.override.yml @@ -0,0 +1,93 @@ +version: "3.7" + +services: + traefik: + # The official v2 Traefik docker image + image: traefik:latest + container_name: traefik + restart: always + env_file: env + ports: + - "80:80" + - "443:443" + - "8080:8080" + networks: + - "invoiceninja" + volumes: + # So that Traefik can listen to the Docker events + - "/var/run/docker.sock:/var/run/docker.sock:ro" + # Dynamic configuration files + - "./config/traefik/config:/conf:ro" + # Enable Access Log + - "./config/traefik/logs/:/var/log/www/" + # LetsEncrypt Configuration Storage + - "./config/traefik/ssl-files:/ssl" + command: + # Send usage statistics (or not) + - "--global.sendAnonymousUsage=false" + # By default, the level is set to ERROR. Alternative logging levels are + # DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. + - "--log.level=WARN" + # Enable Access Log + - "--accesslog.filepath=/var/log/www/access.log" + # Enable Dashboard + - "--api.insecure=false" + - "--api.dashboard=true" + - "--api.debug=true" + # We are using Docker + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + # (Optional) Set default hostname if not given explicitly + - "--providers.docker.defaultRule=Host(`${APP_URL_DOMAIN}`)" + # Listen on port 80 (http) + - "--entrypoints.web.address=:80" + # Listen on port 443 (https) + - "--entrypoints.websecure.address=:443" + # Listen on port 8080 (traefik Dashboard) + - "--entrypoints.traefik-dashbaord.address=:8080" + # Watch dynamic configuration file + - "--providers.file.directory=/conf" + - "--providers.file.watch=true" + # Automaticly redirect from http to https + - "--entrypoints.web.http.redirections.entryPoint.to=websecure" + - "--entrypoints.web.http.redirections.entryPoint.scheme=https" + ################ START SSL configuration ################ + # ---------> LetsEncrypt <--------- + # HTTP-Challenge + - "--certificatesresolvers.http-01.acme.httpchallenge=true" + - "--certificatesresolvers.http-01.acme.httpchallenge.entrypoint=web" + # (Optional) Use testing server before receiving the productive ssl certificate + #- "--certificatesresolvers.http-01.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" + - "--certificatesresolvers.http-01.acme.email=${ACME_EMAIL}" + - "--certificatesresolvers.http-01.acme.storage=/ssl/acme.json" + ################ END SSL configuration ################ + labels: + # Enable Traefik + - "traefik.enable=true" + # Set Network to use + - "traefik.docker.network=invoiceninja" + # Set service type + - "traefik.http.routers.traefik-dashbaord.service=api@internal" + # Load dynamic config from conf/*.yml + - "traefik.http.routers.traefik-dashbaord.middlewares=default@file,basic-auth@file" + # Define entrypint to use + - "traefik.http.routers.traefik-dashbaord.entrypoints=traefik-dashbaord" + # Define Hostname and path + - "traefik.http.routers.traefik-dashbaord.rule=Host(`${APP_URL_DOMAIN}`) && PathPrefix(`/api`,`/dashboard`)" + # Enable SSL/TLS + - "traefik.http.routers.traefik-dashbaord.tls=true" + - "traefik.http.routers.traefik-dashbaord.tls.certResolver=http-01" + + server: + labels: + # Enable Traefik + - "traefik.enable=true" + # Set Network to use + - "traefik.docker.network=invoiceninja" + # Load dynamic config + - "traefik.http.routers.ninja-nginx.middlewares=default@file" + # Service related labels + - "traefik.http.routers.ninja-nginx.entrypoints=websecure" + - "traefik.http.routers.ninja-nginx.rule=Host(`${APP_URL_DOMAIN}`)" + - "traefik.http.routers.ninja-nginx.tls=true" + - "traefik.http.routers.ninja-nginx.tls.certResolver=http-01" diff --git a/config/traefik/ssl/.gitkeep b/config/traefik/ssl-files/.gitkeep similarity index 100% rename from config/traefik/ssl/.gitkeep rename to config/traefik/ssl-files/.gitkeep diff --git a/env b/env index ebbf2e6..a7e6c63 100644 --- a/env +++ b/env @@ -59,7 +59,8 @@ MYSQL_DATABASE=ninja # APP_CIPHER=AES-256-CBC ## Traefik proxy vars +ACME_EMAIL=ssl-maintainer@domain.tld +# Cloudflare only vars CLOUDFLARE_EMAIL=cloudflare@domain.tld CLOUDFLARE_DNS_API_TOKEN=yourApiTokenHere CLOUDFLARE_DOMAIN=domain.tld -ACME_EMAIL=ssl-maintainer@domain.tld