diff --git a/.env b/.env index 630b323..fbda53e 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -# Template \ No newline at end of file +CF_DNS_API_TOKEN= diff --git a/configs/dynamic/dashboard.yml b/configs/dynamic/dashboard.yml new file mode 100644 index 0000000..d2b6326 --- /dev/null +++ b/configs/dynamic/dashboard.yml @@ -0,0 +1,23 @@ +http: + routers: + traefik: + rule: Host(`dashboard.tips-of-mine.com`) + entryPoints: + - https + service: api@internal + middlewares: + - dashboardauth + tls: + certResolver: letsencrypt + traefik-http-redirect: + rule: Host(`dashboard.tips-of-mine.com`) + entryPoints: + - http + service: api@internal + middlewares: + - "redirect-to-https" + middlewares: + dashboardauth: + basicAuth: + users: + - "admin:$2y$10$GXOzS6L1s3gwQb8zO90LKOGuvZfurIXCBgJjZ5ib9/p5l3cy1sid6" diff --git a/configs/dynamic/global-middlewares.yml b/configs/dynamic/global-middlewares.yml new file mode 100644 index 0000000..bc97181 --- /dev/null +++ b/configs/dynamic/global-middlewares.yml @@ -0,0 +1,105 @@ +http: + middlewares: + redirect-to-https: + redirectScheme: + scheme: https + permanent: true + hsts-minimal: + headers: + stsSeconds: 31536000 + stsIncludeSubdomains: false + stsPreload: false + forceSTSHeader: true + hsts-standard: + headers: + stsSeconds: 31536000 + stsIncludeSubdomains: true + stsPreload: false + forceSTSHeader: true + hsts-full: + headers: + stsSeconds: 31536000 + stsIncludeSubdomains: true + stsPreload: true + forceSTSHeader: true + + # Redirect non-www URLs to their www equivalent + # Use with traefik.http.routers.myRouter.middlewares: "redirect-non-www-to-www@file" + # Source: https://www.benjaminrancourt.ca/how-to-redirect-from-non-www-to-www-with-traefik/ + redirect-non-www-to-www: + # Redirect a request from an url to another with regex matching and replacement + redirectregex: + # Apply a permanent redirection (HTTP 301) + permanent: true + # The regular expression to match and capture elements from the request URL + regex: "^https?://(?:www\\.)?(.+)" + # How to modify the URL to have the new target URL + replacement: "https://www.${1}" + + # Redirect www URLs to their non-www equivalent + # Use with traefik.http.routers.myRouter.middlewares: "redirect-www-to-non-www@file" + # Source: https://www.benjaminrancourt.ca/how-to-redirect-from-non-www-to-www-with-traefik/ + redirect-www-to-non-www: + # Redirect a request from an url to another with regex matching and replacement + redirectregex: + # Apply a permanent redirection (HTTP 301) + permanent: true + # The regular expression to match and capture elements from the request URL + regex: "^https?://www\\.(.+)" + # How to modify the URL to have the new target URL + replacement: "https://${1}" + +# default-headers: +# headers: +# frameDeny: true +# browserXssFilter: true +# contentTypeNosniff: true +# forceSTSHeader: true +# stsIncludeSubdomains: true +# stsPreload: true +# stsSeconds: 15552000 +# customFrameOptionsValue: SAMEORIGIN +# customRequestHeaders: +# X-Forwarded-Proto: https + +# crowdsec: +# plugin: +# bouncer: +# enabled: true +# logLevel: INFO +# updateIntervalSeconds: 15 +# updateMaxFailure: 0 +# defaultDecisionSeconds: 15 +# httpTimeoutSeconds: 10 +# crowdsecMode: stream +# crowdsecAppsecEnabled: true +# crowdsecAppsecHost: crowdsec:7422 +# crowdsecAppsecFailureBlock: true +# crowdsecAppsecUnreachableBlock: true +# crowdsecLapiKey: #####REPLACE_API_KEY##### # Replace CrowdSec API key (docker exec crowdsec cscli bouncers add crowdsecBouncer) +# crowdsecLapiKeyFile: /etc/traefik/cs-privateKey-foo +# crowdsecLapiHost: crowdsec:8080 +# crowdsecLapiScheme: http +# forwardedHeadersTrustedIPs: +# - 10.0.35.4/32 # Cloudflare tunnel IP address +# - 172.30.0.0/24 # Reverse Proxy IP address +# clientTrustedIPs: +# - 10.0.1.0/24 # Internal LAN IP addresses +# - 10.0.2.0/24 # Internal LAN IP addresses +# - 10.0.3.0/24 # Internal LAN IP addresses +# - 10.0.4.0/24 # Internal LAN IP addresses +# - 10.0.5.0/24 # Internal LAN IP addresses +# forwardedHeadersCustomName: CF-Connecting-IP # Cloudflare IP address header + +# default-whitelist: +# ipWhiteList: +# sourceRange: +# - "10.0.4.0/24" +# - "192.168.0.0/16" +# - "172.16.0.0/12" + +# secured: +# chain: +# middlewares: +# - default-whitelist +# - default-headers diff --git a/configs/dynamic/harbor.yml.old b/configs/dynamic/harbor.yml.old new file mode 100644 index 0000000..0d84bfe --- /dev/null +++ b/configs/dynamic/harbor.yml.old @@ -0,0 +1,13 @@ +http: + routers: + harbor: + service: harbor + rule: "Host(`registry.tips-of-mine.com`)" + tls: + certResolver: production + + services: + harbor: + loadBalancer: + servers: + - url: "http://172.27.0.1:8880" diff --git a/configs/dynamic/registry.yml b/configs/dynamic/registry.yml new file mode 100644 index 0000000..de03cbc --- /dev/null +++ b/configs/dynamic/registry.yml @@ -0,0 +1,13 @@ +http: + routers: + harbor: + service: harbor + rule: "Host(`registry.tips-of-mine.com`)" + tls: + certResolver: production + + services: + harbor: + loadBalancer: + servers: + - url: "http://10.0.4.133:8083" diff --git a/configs/dynamic/tls.yml b/configs/dynamic/tls.yml new file mode 100644 index 0000000..66f9a0c --- /dev/null +++ b/configs/dynamic/tls.yml @@ -0,0 +1,14 @@ +tls: + stores: + default: + defaultCertificate: + certFile: /etc/traefik/ssl/cert.pem + keyFile: /etc/traefik/ssl/privkey.pem + certificates: + - certFile: /etc/traefik/ssl/cert.pem + keyFile: /etc/traefik/ssl/privkey.pem + options: + default: + minVersion: VersionTLS12 + mintls13: + minVersion: VersionTLS1 \ No newline at end of file diff --git a/configs/traefik.yml b/configs/traefik.yml new file mode 100644 index 0000000..1414a9f --- /dev/null +++ b/configs/traefik.yml @@ -0,0 +1,158 @@ +## static configuration + +global: + # Send anonymous usage data + sendAnonymousUsage: false + checkNewVersion: true + +entryPoints: +# ftp: +# address: ":21" + ssh: + address: ":22" +# smtp: +# address: ":25" +# dns: +# address: ":53" + http: + address: ":80" + forwardedHeaders: + insecure: true + trustedIPs: &trustedIps + - 10.0.4.0/24 + http: +# middlewares: # CHANGE MADE HERE (BOUNCER ENABLED) !!! +# - "crowdsec@file" # CHANGE MADE HERE (BOUNCER ENABLED) !!! +# - "cloudflarewarp@file" # CHANGE MADE HERE (BOUNCER ENABLED) !!! + redirections: + entryPoint: + to: https + scheme: https +# ssh: +# address: ":22" +# pop3: +# address: ":110" +# imap: +# address: ":143" + https: + address: ":443" + forwardedHeaders: + insecure: true + trustedIPs: &trustedIps +# http: +# middlewares: +# - crowdsec-bouncer@file +# - cloudflarewarp@file" # CHANGE MADE HERE (BOUNCER ENABLED) !!! +# - secureHeaders@file +# tls: +# certResolver: letsencrypt +# smtp-ssl: +# address: ":465" +# starttls: +# address: ":587" +# imap-ssl: +# address: ":993" +# pop3-ssl: +# address: ":995" +# openvpn: +# address: ":1194/udp" +# mysql: +# address: ":3306" +# elasticsearch: +# address: ":9200" + metrics: + address: ":8181" + +serversTransport: + insecureSkipVerify: true + +providers: + docker: + endpoint: "unix:///var/run/docker.sock" + exposedByDefault: false + watch: true + file: + directory: /etc/traefik/dynamic + watch: true + providersThrottleDuration: 10 + +certificatesResolvers: + staging: + acme: + email: admin@tips-of-mine.com + storage: /var/traefik/certs/acme.json + caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" + keyType: EC256 + dnsChallenge: + provider: staging + resolvers: + - "1.1.1.1:53" + - "1.0.0.1:53" + tlschallenge: true +# httpChallenge: +# entryPoint: http + production: + acme: + email: admin@tips-of-mine.com + storage: /var/traefik/certs/acme.json + caServer: "https://acme-v02.api.letsencrypt.org/directory" + keyType: EC256 + dnsChallenge: + provider: production + resolvers: + - "1.1.1.1:53" + - "1.0.0.1:53" + tlschallenge: true +# httpchallenge: +# entrypoint: http + +api: + insecure: true + dashboard: true + +log: + level: DEBUG + filepath: "/var/log/traefik/traefik.log" + format: json +# default: "common" + +accesslog: + filepath: "/var/log/traefik/access.log" + format: json + bufferingSize: 100 +# format: common + +# Ajout de la partie métrique qui concerne Prometheus +metrics: + prometheus: + # Nom du point d'entrée défini au dessus + entryPoint: metrics + # On configure la latence des métriques + buckets: + - 0.1 + - 0.3 + - 1.2 + - 5.0 + # Ajout des métriques sur les points d'entrée + addEntryPointsLabels: true + # Ajout des services + addServicesLabels: true + addRoutersLabels: true + +experimental: + plugins: + crowdsec-bouncer-traefik-plugin: + moduleName: "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" + version: "v1.3.3" + + traefik-maintenance: + moduleName: "github.com/TRIMM/traefik-maintenance" + version: "v1.0.1" + + fail2ban: + moduleName: "github.com/tomMoulard/fail2ban" + version: "v0.8.3" + + sablier: + moduleName: "github.com/acouvreur/sablier" + version: "v1.8.0-beta.22" diff --git a/configs/traefik.ymlo b/configs/traefik.ymlo new file mode 100644 index 0000000..fceddab --- /dev/null +++ b/configs/traefik.ymlo @@ -0,0 +1,158 @@ +## static configuration + +global: + # Send anonymous usage data + sendAnonymousUsage: false + checkNewVersion: true + +entryPoints: +# ftp: +# address: ":21" + ssh: + address: ":22" +# smtp: +# address: ":25" +# dns: +# address: ":53" + http: + address: ":80" + forwardedHeaders: + insecure: true + trustedIPs: &trustedIps + - 10.0.4.0/24 + http: +# middlewares: # CHANGE MADE HERE (BOUNCER ENABLED) !!! +# - "crowdsec@file" # CHANGE MADE HERE (BOUNCER ENABLED) !!! +# - "cloudflarewarp@file" # CHANGE MADE HERE (BOUNCER ENABLED) !!! + redirections: + entryPoint: + to: https + scheme: https +# gitea-ssh: +# address: ":2222" +# pop3: +# address: ":110" +# imap: +# address: ":143" + https: + address: ":443" + forwardedHeaders: + insecure: true + trustedIPs: &trustedIps +# http: +# middlewares: +# - crowdsec-bouncer@file +# - cloudflarewarp@file" # CHANGE MADE HERE (BOUNCER ENABLED) !!! +# - secureHeaders@file +# tls: +# certResolver: letsencrypt +# smtp-ssl: +# address: ":465" +# starttls: +# address: ":587" +# imap-ssl: +# address: ":993" +# pop3-ssl: +# address: ":995" +# openvpn: +# address: ":1194/udp" +# mysql: +# address: ":3306" +# elasticsearch: +# address: ":9200" + metrics: + address: ":8181" + +serversTransport: + insecureSkipVerify: true + +providers: + docker: + endpoint: "unix:///var/run/docker.sock" + exposedByDefault: false + watch: true + file: + directory: /etc/traefik/dynamic + watch: true + providersThrottleDuration: 10 + +certificatesResolvers: + staging: + acme: + email: admin@tips-of-mine.fr + storage: acme.json + caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" + keyType: EC256 + dnsChallenge: + provider: staging + resolvers: + - "1.1.1.1:53" + - "1.0.0.1:53" + tlschallenge: true +# httpChallenge: +# entryPoint: http + production: + acme: + email: admin@tips-of-mine.fr + storage: acme.json + caServer: "https://acme-v02.api.letsencrypt.org/directory" + keyType: EC256 + dnsChallenge: + provider: production + resolvers: + - "1.1.1.1:53" + - "1.0.0.1:53" + tlschallenge: true +# httpchallenge: +# entrypoint: http + +api: + insecure: true + dashboard: true + +log: + level: DEBUG + filepath: "/var/log/traefik/traefik.log" + format: json +# default: "common" + +accesslog: + filepath: "/var/log/traefik/access.log" + format: json + bufferingSize: 100 +# format: common + +# Ajout de la partie métrique qui concerne Prometheus +metrics: + prometheus: + # Nom du point d'entrée défini au dessus + entryPoint: metrics + # On configure la latence des métriques + buckets: + - 0.1 + - 0.3 + - 1.2 + - 5.0 + # Ajout des métriques sur les points d'entrée + addEntryPointsLabels: true + # Ajout des services + addServicesLabels: true + addRoutersLabels: true + +experimental: + plugins: + crowdsec-bouncer-traefik-plugin: + moduleName: "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" + version: "v1.3.3" + + traefik-maintenance: + moduleName: "github.com/TRIMM/traefik-maintenance" + version: "v1.0.1" + + fail2ban: + moduleName: "github.com/tomMoulard/fail2ban" + version: "v0.8.3" + + sablier: + moduleName: "github.com/acouvreur/sablier" + version: "v1.8.0-beta.22" diff --git a/docker-compose.yml b/docker-compose.yml index 4054566..b6612b3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,42 +1,75 @@ -#### NETWORKS +### networks networks: - traefik_front_network: - external: true - back_network_: + back_network: + driver: bridge + attachable: true + front_network: driver: bridge attachable: true -#### SERVICES +### Volumes +#volumes: +# traefik-logs: + +### services services: -### hello_world - hello_world: - container_name: gitea-app - hostname: gitea-app - image: hello-world - environment: +# traefik + traefik: + container_name: traefik-app + hostname: traefik-app + image: traefik:latest restart: always - networks: -# - back_network_gitea - - traefik_front_network + ports: +# - "22:22" + - "80:80" + - "443:443" + - "8181:8181" volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + - "/etc/localtime:/etc/localtime:ro" + - "./configs/traefik.yml:/etc/traefik/traefik.yml" + - "./configs/dynamic:/etc/traefik/dynamic:rw" +# - "./certificates/acme.json:/etc/traefik/acme/acme.json:rw" + - "./certificates:/var/traefik/certs:rw" + - "./certificates:/etc/traefik/ssl:rw" + - "./logs:/var/log/traefik:rw" + environment: + - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} + networks: + - back_network + - front_network + +### Certificats + certificat: + container_name: traefik-certificat + hostname: traefik-certificat + image: alpine:latest + command: sh -c "cd /etc/traefik/ssl + && wget traefik.me/cert.pem -O cert2.pem + && wget traefik.me/privkey.pem -O privkey2.pem" + volumes: + - "./certificates:/etc/traefik/ssl" + networks: + - front_network + +# whoami + whoami: + container_name: traefik-whoami + hostname: traefik-whoami + image: traefik/whoami:latest + restart: unless-stopped + networks: + - front_network labels: - "traefik.enable=true" - - "traefik.docker.network=traefik_front_network" + - "traefik.docker.network=front_network" # HTTP - - "traefik.http.routers.hello-world-http.rule=Host(`hello-world.tips-of-mine.com`)" - - "traefik.http.routers.hello-world-http.entrypoints=http" - - "traefik.http.routers.hello-world-http.priority=49" + - "traefik.http.routers.whoami-http.rule=Host(`whoami.tips-of-mine.com`)" + - "traefik.http.routers.whoami-http.entrypoints=http" # HTTPS - - "traefik.http.routers.hello-world-https.rule=Host(`hello-world.tips-of-mine.com`)" - - "traefik.http.routers.hello-world-https.entrypoints=https" - - "traefik.http.routers.hello-world-https.tls=true" - - "traefik.http.routers.hello-world-https.priority=50" - - "traefik.http.routers.gitea.service=gitea-https-service" + - "traefik.http.routers.whoami-https.rule=Host(`whoami.tips-of-mine.com`)" + - "traefik.http.routers.whoami-https.entrypoints=https" + - "traefik.http.routers.whoami-https.tls=true" # Middleware # Service -# - "traefik.http.services.gitea-https-service.loadbalancer.server.port=3000" -# - "traefik.http.services.gitea-https-service.loadbalancer.server.scheme=https" -# - "traefik.http.services.gitea-https-service.loadbalancer.healthcheck.hostname=gitea.traefik.me" -# - "traefik.http.services.gitea-https-service.loadbalancer.healthcheck.method=foobar" -# - "traefik.http.services.gitea-https-service.loadbalancer.healthcheck.timeout=10" -# - "traefik.http.services.gitea-https-service.loadbalancer.healthcheck.interval=30" + diff --git a/prepare.sh b/prepare.sh new file mode 100644 index 0000000..a6b5a7a --- /dev/null +++ b/prepare.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +if ! (docker ps >/dev/null 2>&1) +then + echo "Le daemon docker n'est pas en cours d'exécution, sortie !" + exit +fi + +# Prompt nom de domaine +read -p "Nom de domaine : " _domain_name +# Prompt email Let's encrypt +read -p "Email pour Let's encrypt : " _letsencrypt_email + +# Prompt mot de passe pour le compte "admin" de Traefik +begin=true +again=false + +while $begin; do + $again && echo "Les mots de passe ne sont pas identiques. Veuillez réessayer." || again=true + begin=false + read -rs -p "Mot de passe admin pour Traefik : " _traefik_admin_passwd + echo + read -rs -p "Confirmation du mot de passe : " _password_confirm + echo + if [[ "$_traefik_admin_passwd" != "$_password_confirm" ]]; then + begin=true + fi +done + +# Renseigner les identifiants pour traefik dans `core/traefik-data/configurations/dynamic.yml` +_traefik_encrypted_passwd="$(htpasswd -nb admin "$_traefik_admin_passwd")" + +# Insertion d'antislash devant les caractères ayant une signification pour sed +_traefik_encrypted_passwd="$(<<< "$_traefik_encrypted_passwd" sed -e 's`[][\\/.*^$]`\\&`g')" +sed -i "s/_traefik_encrypted_passwd/$_traefik_encrypted_passwd/g" config/dynamic/dashboard.yml + +# Renseigner l'adresse email pour Let's Encrypt dans `core/traefik-data/traefik.yml`. +sed -i "s/_letsencrypt_email/$_letsencrypt_email/g" configs/traefik.yml + +# Renseigner les noms de domaine pour traefik et portainer dans `core/docker-compose.yml`. +sed -i "s/_domain_name/$_domain_name/g" core/docker-compose.yml + + +mkdir -p certificates +mkdir -p traefik +echo "{}" > certificates/acme.json +chmod 600 certificates/acme.json + +echo " Ok" +echo "Vous pouvez lancer la commande : docker compose up -d" \ No newline at end of file