From a930db1b3af6b30f577544738e4141dec3844e38 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 27 Mar 2026 19:36:37 +0000 Subject: [PATCH] Update traefik, introduce crowdsec, add hydra stack to infra. --- arbeitsschutz/docker-compose.yaml | 4 +- common/docker-compose.yaml | 76 +++++++++++++++++++++++++++++-- huber-putz/docker-compose.yaml | 4 +- hydra/.env | 68 +++++++++++++++++++++++++++ hydra/docker-compose.yaml | 55 ++++++++++++++++++++++ mail/docker-compose.yaml | 4 +- svj/docker-compose.yaml | 4 +- 7 files changed, 202 insertions(+), 13 deletions(-) create mode 100644 hydra/.env create mode 100644 hydra/docker-compose.yaml diff --git a/arbeitsschutz/docker-compose.yaml b/arbeitsschutz/docker-compose.yaml index 111a8f6..521f69a 100644 --- a/arbeitsschutz/docker-compose.yaml +++ b/arbeitsschutz/docker-compose.yaml @@ -12,11 +12,11 @@ services: - proxy labels: - "traefik.enable=true" - - "traefik.http.routers.arbeitsschutz.rule=Host(`arbeitsschutz-ulm.de`, `www.arbeitsschutz-ulm.de`, `ulmer-arbeitsschutz.de`, `www.ulmer-arbeitsschutz.de`)" + - "traefik.http.routers.arbeitsschutz.rule=Host(`arbeitsschutz-ulm.de`) || Host(`www.arbeitsschutz-ulm.de`) || Host(`ulmer-arbeitsschutz.de`) || Host(`www.ulmer-arbeitsschutz.de`)" - "traefik.http.routers.arbeitsschutz.entrypoints=web" - "traefik.http.routers.arbeitsschutz.middlewares=arbeitsschutz" - "traefik.http.middlewares.arbeitsschutz.redirectscheme.scheme=https" - - "traefik.http.routers.arbeitsschutz-secure.rule=Host(`arbeitsschutz-ulm.de`, `www.arbeitsschutz-ulm.de`, `ulmer-arbeitsschutz.de`, `www.ulmer-arbeitsschutz.de`)" + - "traefik.http.routers.arbeitsschutz-secure.rule=Host(`arbeitsschutz-ulm.de`) || Host(`www.arbeitsschutz-ulm.de`) || Host(`ulmer-arbeitsschutz.de`) || Host(`www.ulmer-arbeitsschutz.de`)" - "traefik.http.routers.arbeitsschutz-secure.entrypoints=websecure" - "traefik.http.routers.arbeitsschutz-secure.tls=true" - "traefik.http.routers.arbeitsschutz-secure.tls.certresolver=cs" diff --git a/common/docker-compose.yaml b/common/docker-compose.yaml index 73070a1..50773fa 100644 --- a/common/docker-compose.yaml +++ b/common/docker-compose.yaml @@ -2,28 +2,40 @@ networks: proxy: external: false name: proxy + enable_ipv6: true volumes: letsencrypt: name: letsencrypt portainer: name: portainer + traefik_log: + name: traefik_log + crowdsec_data: + name: crowdsec_data + crowdsec_etc: + name: crowdsec_etc services: traefik: - image: traefik:v2.11 + image: traefik:v3 container_name: traefik restart: unless-stopped command: + - --experimental.plugins.bouncer.moduleName=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin + - --experimental.plugins.bouncer.version=v1.5.0 - --global.sendAnonymousUsage=false - --api.dashboard=true + - --api.insecure=true - --providers.docker=true - --providers.docker.network=proxy - --providers.docker.exposedByDefault=false - - --providers.docker.swarmMode=false - --entryPoints.web.address=:80 + - --entryPoints.web.forwardedHeaders.insecure=true - --entryPoints.websecure.address=:443 - - --entryPoints.shh.address=:222/tcp + - --entryPoints.websecure.http3.advertisedPort=443 + - --entryPoints.websecure.forwardedHeaders.insecure=true + - --entryPoints.ssh.address=:222/tcp - --entryPoints.smtp.address=:25 - --entryPoints.smtp-ssl.address=:465 - --entryPoints.imap-ssl.address=:993 @@ -32,7 +44,13 @@ services: - --certificatesresolvers.cs.acme.email=christiansteinle@arcor.de - --certificatesresolvers.cs.acme.storage=/letsencrypt/acme.json - --log=true + - --log.level=INFO - --accessLog=true + - --accessLog.filePath=/logs/traefik.log + - --accessLog.format=json + - --accessLog.bufferingSize=0 + - --accessLog.fields.headers.defaultMode=drop + - --accessLog.fields.headers.names.User-Agent=keep - --metrics.prometheus=true - --metrics.prometheus.manualRouting=true - --metrics.prometheus.addRoutersLabels=true @@ -40,14 +58,25 @@ services: - INFOMANIAK_ACCESS_TOKEN=5IraYq8HK9qur57Mj_TnHQ9pS9G79NPvjF8ID17n-EvfYO7TU6Fi0ZmDKSX6mIhTQJbyYegRd1hfmM-t ports: - "25:25" - - "80:80" - - "443:443" + - target: 80 + published: 80 + protocol: tcp + mode: host + - target: 443 + published: 443 + protocol: tcp + mode: host + - target: 443 + published: 443 + protocol: udp + mode: host - "465:465" - "993:993" - "4190:4190" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - letsencrypt:/letsencrypt + - traefik_log:/logs labels: - "traefik.enable=true" - "traefik.http.routers.traefik.entrypoints=web" @@ -69,6 +98,19 @@ services: - "traefik.http.routers.metrics-secure.tls.certresolver=cs" - "traefik.http.routers.metrics-secure.middlewares=auth" - "traefik.http.routers.metrics-secure.service=prometheus@internal" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.defaultDecisionSeconds=60" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecMode=live" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecAppsecEnabled=false" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecAppsecHost=crowdsec:7422" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecAppsecFailureBlock=true" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecAppsecUnreachableBlock=true" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiKey=Q6aU8YIY5zr2c/gNg9WTvm2PPMu+jyEhVKIftcZSBSE" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiHost=crowdsec:8080" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiScheme=http" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiTLSInsecureVerify=false" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.forwardedHeadersTrustedIPs=91.108.113.212,192.168.0.0/16,172.17.0.0/16" + - "traefik.http.middlewares.crowdsec.plugin.bouncer.clientTrustedIPs=91.108.113.212,192.168.0.0/16,172.17.0.0/16" networks: - proxy @@ -97,4 +139,28 @@ services: - "traefik.http.routers.portainer-secure.tls.certresolver=cs" - "traefik.http.services.portainer-secure.loadbalancer.server.port=9000" + crowdsec: + image: crowdsecurity/crowdsec + container_name: crowdsec + restart: unless-stopped + ports: + - 127.0.0.1:9876:8080 # port mapping for local firewall bouncers + expose: + - 8080 # http api for bouncers + - 6060 # metrics endpoint for prometheus + - 7422 # appsec waf endpoint + volumes: + # crowdsec container data + - crowdsec_data:/var/lib/crowdsec/data + - crowdsec_etc:/etc/crowdsec + # log bind mounts into crowdsec + - /var/log/auth.log:/var/log/auth.log:ro + - /var/log/syslog:/var/log/syslog:ro + - traefik_log:/var/log/traefik:ro + environment: + - GID=1000 + - COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/base-http-scenarios crowdsecurity/sshd crowdsecurity/linux crowdsecurity/appsec-generic-rules crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-crs + #- CUSTOM_HOSTNAME=my-crowdsec-host123 + networks: + - proxy diff --git a/huber-putz/docker-compose.yaml b/huber-putz/docker-compose.yaml index caf9876..94ef362 100644 --- a/huber-putz/docker-compose.yaml +++ b/huber-putz/docker-compose.yaml @@ -12,11 +12,11 @@ services: - proxy labels: - "traefik.enable=true" - - "traefik.http.routers.huber-putz.rule=Host(`huber-stuck.de`, `www.huber-stuck.de`, `huber-putz.com`, `www.huber-putz.com`)" + - "traefik.http.routers.huber-putz.rule=Host(`huber-stuck.de`) || Host(`www.huber-stuck.de`) || Host(`huber-putz.com`) || Host(`www.huber-putz.com`)" - "traefik.http.routers.huber-putz.entrypoints=web" - "traefik.http.routers.huber-putz.middlewares=huber-putz" - "traefik.http.middlewares.huber-putz.redirectscheme.scheme=https" - - "traefik.http.routers.huber-putz-secure.rule=Host(`huber-stuck.de`, `www.huber-stuck.de`, `huber-putz.com`, `www.huber-putz.com`)" + - "traefik.http.routers.huber-putz-secure.rule=Host(`huber-stuck.de`) || Host(`www.huber-stuck.de`) || Host(`huber-putz.com`) || Host(`www.huber-putz.com`)" - "traefik.http.routers.huber-putz-secure.entrypoints=websecure" - "traefik.http.routers.huber-putz-secure.tls=true" - "traefik.http.routers.huber-putz-secure.tls.certresolver=cs" diff --git a/hydra/.env b/hydra/.env new file mode 100644 index 0000000..5d5ac5d --- /dev/null +++ b/hydra/.env @@ -0,0 +1,68 @@ +APP_NAME=Hydra +APP_ENV=production +APP_KEY=base64:qSmM2c7YWgiFKS62S2m6w8pVslaBC8WBIHttObhDu1U= +APP_DEBUG=true +APP_TIMEZONE=UTC +APP_URL=https://hydras-revenge.ddnss.org + +APP_LOCALE=en +APP_CURRENCY=EUR +APP_FALLBACK_LOCALE=en +APP_FAKER_LOCALE=en_US + +APP_MAINTENANCE_DRIVER=file +# APP_MAINTENANCE_STORE=database + +PHP_CLI_SERVER_WORKERS=4 + +BCRYPT_ROUNDS=12 + +LOG_CHANNEL=stack +LOG_STACK=single +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=pgsql +DB_HOST=pgsql +DB_PORT=5432 +DB_DATABASE=hydra +DB_USERNAME=hydra +DB_PASSWORD=$*8D%!nnoiiu6w + +SESSION_DRIVER=database +SESSION_LIFETIME=120 +SESSION_ENCRYPT=false +SESSION_PATH=/ +SESSION_DOMAIN=null + +BROADCAST_CONNECTION=log +FILESYSTEM_DISK=local +QUEUE_CONNECTION=database + +CACHE_STORE=database +CACHE_PREFIX= + +MEMCACHED_HOST=127.0.0.1 + +REDIS_CLIENT=phpredis +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=log +MAIL_HOST=mail +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +VITE_APP_NAME="${APP_NAME}" +VITE_APP_URL="${APP_URL}/api" diff --git a/hydra/docker-compose.yaml b/hydra/docker-compose.yaml new file mode 100644 index 0000000..f81bd67 --- /dev/null +++ b/hydra/docker-compose.yaml @@ -0,0 +1,55 @@ +networks: + proxy: + external: true + hydra: + +volumes: + hydra-db: + hydra-storage: + name: hydra-storage + +services: + app: + image: gitea.fam-steinle.de/cs/hydra:latest + restart: always + dns: + - '8.8.8.8' + links: + - pgsql + depends_on: + pgsql: + condition: service_healthy + working_dir: /var/www + volumes: + - ./.env:/var/www/.env + - hydra-storage:/var/www/storage/app/private + networks: + - proxy + - hydra + labels: + - "traefik.enable=true" + - "traefik.http.routers.hydra.rule=Host(`hydras-revenge.ddnss.org`) || Host(`hydra.steinle-computer.de`)" + - "traefik.http.routers.hydra.entrypoints=web" + - "traefik.http.routers.hydra.middlewares=hydra" + - "traefik.http.middlewares.hydra.redirectscheme.scheme=https" + - "traefik.http.routers.hydra-secure.rule=Host(`hydras-revenge.ddnss.org`) || Host(`hydra.steinle-computer.de`)" + - "traefik.http.routers.hydra-secure.entrypoints=websecure" + - "traefik.http.routers.hydra-secure.tls=true" + - "traefik.http.routers.hydra-secure.tls.certresolver=cs" + - "traefik.http.routers.hydra-secure.service=hydra-secure" + - "traefik.http.services.hydra-secure.loadbalancer.server.port=80" + + pgsql: + image: postgres:17-alpine + restart: unless-stopped + volumes: + - hydra-db:/var/lib/postgresql/data + networks: + - hydra + environment: + PGPASSWORD: $*8D%!nnoiiu6w + POSTGRES_PASSWORD: $*8D%!nnoiiu6w + POSTGRES_USER: hydra + POSTGRES_DB: hydra + healthcheck: + test: ["CMD-SHELL", "pg_isready -U steinle"] diff --git a/mail/docker-compose.yaml b/mail/docker-compose.yaml index 1fdd631..5b87ed6 100644 --- a/mail/docker-compose.yaml +++ b/mail/docker-compose.yaml @@ -63,13 +63,13 @@ services: - "traefik.tcp.routers.smtp.entrypoints=smtp" - "traefik.tcp.routers.smtp.service=smtp" - "traefik.tcp.services.smtp.loadbalancer.server.port=25" - - "traefik.tcp.services.smtp.loadbalancer.proxyProtocol.version=1" + - "traefik.tcp.services.smtp.loadbalancer.proxyProtocol.version=2" - "traefik.tcp.routers.smtp-ssl.rule=HostSNI(`*`)" - "traefik.tcp.routers.smtp-ssl.tls=false" - "traefik.tcp.routers.smtp-ssl.entrypoints=smtp-ssl" - "traefik.tcp.routers.smtp-ssl.service=smtp-ssl" - "traefik.tcp.services.smtp-ssl.loadbalancer.server.port=465" - - "traefik.tcp.services.smtp-ssl.loadbalancer.proxyProtocol.version=1" + - "traefik.tcp.services.smtp-ssl.loadbalancer.proxyProtocol.version=2" - "traefik.tcp.routers.imap-ssl.rule=HostSNI(`*`)" - "traefik.tcp.routers.imap-ssl.entrypoints=imap-ssl" - "traefik.tcp.routers.imap-ssl.service=imap-ssl" diff --git a/svj/docker-compose.yaml b/svj/docker-compose.yaml index 6b405b3..0f12fb5 100644 --- a/svj/docker-compose.yaml +++ b/svj/docker-compose.yaml @@ -26,11 +26,11 @@ services: - svj-media:/var/www/html/media labels: - "traefik.enable=true" - - "traefik.http.routers.svj.rule=Host(`svj-fussball.de`, `www.svj-fussball.de`)" + - "traefik.http.routers.svj.rule=Host(`svj-fussball.de`) || Host(`www.svj-fussball.de`)" - "traefik.http.routers.svj.entrypoints=web" - "traefik.http.routers.svj.middlewares=svj" - "traefik.http.middlewares.svj.redirectscheme.scheme=https" - - "traefik.http.routers.svj-secure.rule=Host(`svj-fussball.de`, `www.svj-fussball.de`)" + - "traefik.http.routers.svj-secure.rule=Host(`svj-fussball.de`) || Host(`www.svj-fussball.de`)" - "traefik.http.routers.svj-secure.entrypoints=websecure" - "traefik.http.routers.svj-secure.tls=true" - "traefik.http.routers.svj-secure.tls.certresolver=cs"