refactor(compose): protect services and centralize routing

This commit is contained in:
Eduardo David Paredes Vara
2026-07-25 11:21:08 +00:00
parent 29988f3149
commit 4536b3a36a
24 changed files with 159 additions and 104 deletions
+5
View File
@@ -48,6 +48,10 @@ services:
- "--experimental.plugins.crowdsec-bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.crowdsec-bouncer.version=v1.6.0"
# Plugin Sablier (scale-to-zero on demand)
- "--experimental.plugins.sablier.modulename=github.com/acouvreur/sablier"
- "--experimental.plugins.sablier.version=v1.8.0"
# ACME / Let's Encrypt (resolver "letsencrypt")
- "--certificatesresolvers.letsencrypt.acme.email=${TRAEFIK_ACME_EMAIL}"
- "--certificatesresolvers.letsencrypt.acme.storage=${TRAEFIK_ACME_STORAGE}"
@@ -63,6 +67,7 @@ services:
- ${TRAEFIK_DYNAMIC_DIR}:/dynamic:Z
- ${TRAEFIK_LETSENCRYPT_DIR}:/letsencrypt:Z
- ${TRAEFIK_LOG_DIR}:/var/log/traefik:Z
- /opt/traefik/plugins-storage:/plugins-storage:Z
networks:
- proxy
-1
View File
@@ -2,7 +2,6 @@ services:
adguardhome:
image: ${ADGUARD_IMAGE}
container_name: adguardhome
pull_policy: always
restart: unless-stopped
volumes:
-1
View File
@@ -25,7 +25,6 @@ services:
ths-authentik-server:
image: ${AUTHENTIK_IMAGE}
container_name: ths-authentik-server
pull_policy: always
restart: unless-stopped
command: ["server"]
environment:
-2
View File
@@ -1,7 +1,6 @@
services:
beszel:
image: ${BESZEL_IMAGE}
pull_policy: always
container_name: beszel
restart: unless-stopped
environment:
@@ -31,7 +30,6 @@ services:
beszel-agent:
image: ${BESZEL_AGENT_IMAGE}
pull_policy: always
container_name: beszel-agent
restart: unless-stopped
network_mode: host
+3 -6
View File
@@ -3,6 +3,8 @@ services:
image: ${BOOKSTACK_DB_IMAGE}
container_name: bookstack-db
restart: unless-stopped
labels:
prune.protect: "true"
environment:
MYSQL_ROOT_PASSWORD: ${BOOKSTACK_DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${BOOKSTACK_DB_NAME}
@@ -45,14 +47,9 @@ services:
- proxy
- mail_internal
labels:
prune.protect: "true"
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
traefik.http.routers.bookstack.rule: "Host(`${BOOKSTACK_DOMAIN}`)"
traefik.http.routers.bookstack.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.bookstack.tls: "true"
traefik.http.routers.bookstack.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.bookstack.middlewares: "crowdsec-bouncer@file,${TRAEFIK_AUTH_MIDDLEWARE}"
traefik.http.services.bookstack.loadbalancer.server.port: "80"
homepage.group: "Productividad"
homepage.name: "BookStack"
homepage.icon: "bookstack.png"
+1 -2
View File
@@ -1,7 +1,6 @@
services:
crowdsec:
image: ${CROWDSEC_IMAGE}
pull_policy: always
container_name: crowdsec
restart: unless-stopped
security_opt:
@@ -59,7 +58,7 @@ services:
retries: 5
crowdsec-prometheus:
image: prom/prometheus:latest
image: prom/prometheus@sha256:e4254400b85610324913f0dc4acf92603d9984e7519414c5a12811aa6146acc3
container_name: crowdsec-prometheus
restart: unless-stopped
command:
+1 -2
View File
@@ -16,8 +16,7 @@ echo "=== CrowdSec Setup ==="
# 1. Cargar .env
if [ ! -f "${ENV_FILE}" ]; then
echo "ERROR: No se encontro ${ENV_FILE}"
echo "Copia stack.env a .env y editalo:"
echo " cp ${SCRIPT_DIR}/stack.env ${ENV_FILE}"
echo "Crea ${ENV_FILE} con las variables reales y editalo:"
echo " nano ${ENV_FILE}"
exit 1
fi
+1 -7
View File
@@ -1,7 +1,6 @@
services:
dozzle:
image: ${DOZZLE_IMAGE}
pull_policy: always
container_name: dozzle
restart: unless-stopped
environment:
@@ -15,14 +14,9 @@ services:
networks:
- proxy
labels:
prune.protect: "true"
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
traefik.http.routers.dozzle.rule: "Host(`${DOZZLE_DOMAIN}`)"
traefik.http.routers.dozzle.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.dozzle.tls: "true"
traefik.http.routers.dozzle.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.dozzle.middlewares: "crowdsec-bouncer@file,${TRAEFIK_AUTH_MIDDLEWARE}"
traefik.http.services.dozzle.loadbalancer.server.port: "8080"
homepage.group: "Observabilidad"
homepage.name: "Dozzle"
homepage.icon: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/dozzle.svg"
+7 -7
View File
@@ -3,6 +3,8 @@ services:
image: ${GITEA_POSTGRES_IMAGE}
container_name: gitea-postgres
restart: unless-stopped
labels:
prune.protect: "true"
environment:
POSTGRES_DB: ${GITEA_DB_NAME}
POSTGRES_USER: ${GITEA_DB_USER}
@@ -15,7 +17,6 @@ services:
gitea:
image: ${GITEA_IMAGE}
pull_policy: always
container_name: gitea
restart: unless-stopped
depends_on:
@@ -79,19 +80,16 @@ services:
ports:
- "${GITEA_SSH_PORT}:${GITEA_SSH_PORT}"
labels:
prune.protect: "true"
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
traefik.http.routers.gitea.rule: "Host(`${GITEA_DOMAIN}`)"
traefik.http.routers.gitea.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.gitea.tls: "true"
traefik.http.routers.gitea.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.gitea.middlewares: "crowdsec-bouncer@file"
traefik.http.services.gitea.loadbalancer.server.port: "3000"
gitea-runner:
image: ${GITEA_RUNNER_IMAGE}
container_name: gitea-act-runner
restart: unless-stopped
labels:
prune.protect: "true"
depends_on:
- gitea
environment:
@@ -107,6 +105,8 @@ services:
networks:
gitea:
labels:
prune.protect: "true"
driver: bridge
mail_internal:
external: true
+13 -12
View File
@@ -1,11 +1,18 @@
services:
guacd:
image: ${GUACD_IMAGE}
pull_policy: always
container_name: guacd
restart: unless-stopped
labels:
prune.protect: "true"
extra_hosts:
- "host.docker.internal:host-gateway"
- "host.docker.internal:10.0.4.1"
healthcheck:
test: ["CMD-SHELL", "nc -z 127.0.0.1 4822 || exit 1"]
interval: 10s
timeout: 5s
retries: 3
start_period: 5s
networks:
- guacamole
@@ -13,6 +20,8 @@ services:
image: ${GUACAMOLE_POSTGRES_IMAGE}
container_name: guacamole-postgres
restart: unless-stopped
labels:
prune.protect: "true"
environment:
POSTGRES_DB: ${GUACAMOLE_DB_NAME}
POSTGRES_USER: ${GUACAMOLE_DB_USER}
@@ -26,7 +35,6 @@ services:
guacamole:
image: ${GUACAMOLE_IMAGE}
pull_policy: always
container_name: guacamole
restart: unless-stopped
depends_on:
@@ -41,19 +49,12 @@ services:
POSTGRESQL_USERNAME: ${GUACAMOLE_DB_USER}
POSTGRESQL_PASSWORD: ${GUACAMOLE_DB_PASSWORD}
extra_hosts:
- "host.docker.internal:host-gateway"
- "host.docker.internal:10.0.4.1"
networks:
- guacamole
- proxy
labels:
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
traefik.http.routers.guacamole.rule: "Host(`${GUACAMOLE_DOMAIN}`)"
traefik.http.routers.guacamole.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.guacamole.tls: "true"
traefik.http.routers.guacamole.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.guacamole.middlewares: "crowdsec-bouncer@file,${TRAEFIK_AUTH_MIDDLEWARE}"
traefik.http.services.guacamole.loadbalancer.server.port: "8080"
prune.protect: "true"
homepage.group: "Infraestructura"
homepage.name: "Remote Desktop"
homepage.icon: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/apache-guacamole.svg"
-1
View File
@@ -1,7 +1,6 @@
services:
homepage:
image: ${HOMEPAGE_IMAGE}
pull_policy: always
container_name: homepage
restart: unless-stopped
environment:
+5 -5
View File
@@ -1,7 +1,6 @@
services:
karakeep:
image: ghcr.io/karakeep-app/karakeep:${KARAKEEP_VERSION}
pull_policy: always
container_name: karakeep
restart: unless-stopped
environment:
@@ -42,17 +41,16 @@ services:
- karakeep_internal
- proxy
labels:
prune.protect: "true"
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
traefik.http.routers.karakeep.rule: "Host(`${KARAKEEP_DOMAIN}`)"
traefik.http.routers.karakeep.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.karakeep.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.services.karakeep.loadbalancer.server.port: "3000"
karakeep-chrome:
image: gcr.io/zenika-hub/alpine-chrome:124
container_name: karakeep-chrome
restart: unless-stopped
labels:
prune.protect: "true"
command:
- --no-sandbox
- --disable-gpu
@@ -67,6 +65,8 @@ services:
image: getmeili/meilisearch:v1.37.0
container_name: karakeep-meilisearch
restart: unless-stopped
labels:
prune.protect: "true"
environment:
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}
MEILI_NO_ANALYTICS: "true"
-1
View File
@@ -2,7 +2,6 @@ services:
mail-relay:
image: ${MAIL_RELAY_IMAGE}
container_name: mail-relay
pull_policy: always
restart: unless-stopped
environment:
TZ: ${TZ}
+7 -13
View File
@@ -6,7 +6,7 @@ networks:
services:
flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
image: ghcr.io/flaresolverr/flaresolverr@sha256:b91dbd42a716ec5334a3e348ef835759f96d4082f29d6f2ab4542353d3a08aef
container_name: flaresolverr
environment:
- LOG_LEVEL=${LOG_LEVEL:-info}
@@ -19,9 +19,8 @@ services:
shm_size: "1gb"
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
image: lscr.io/linuxserver/prowlarr@sha256:df25cfc91278e78abdf33623f7ee341b3b476118af68a2434cd8f8df49e6f986
container_name: prowlarr
pull_policy: always
environment:
- PUID=0
- PGID=0
@@ -36,9 +35,8 @@ services:
- traefik.http.services.prowlarr.loadbalancer.server.port=9696
jackett:
image: lscr.io/linuxserver/jackett:latest
image: lscr.io/linuxserver/jackett@sha256:520d1a04f7aba6c71eb607eea1ca806eb4e2e7f0861ee79624dc716c423e8573
container_name: jackett
pull_policy: always
environment:
- PUID=0
- PGID=0
@@ -53,9 +51,8 @@ services:
- traefik.http.services.jackett.loadbalancer.server.port=9117
sonarr:
image: lscr.io/linuxserver/sonarr:latest
image: lscr.io/linuxserver/sonarr@sha256:9272af4955c92cccc39bc75dcad2f0758bc0ab9353dc61a8efaf35501d9ad60d
container_name: sonarr
pull_policy: always
environment:
- PUID=0
- PGID=0
@@ -72,9 +69,8 @@ services:
- traefik.http.services.sonarr.loadbalancer.server.port=8989
radarr:
image: lscr.io/linuxserver/radarr:latest
image: lscr.io/linuxserver/radarr@sha256:3d851f850263ac1cbb5b2c78b20123a224547d819c2f4ba5a0a8cacadbf97038
container_name: radarr
pull_policy: always
environment:
- PUID=0
- PGID=0
@@ -91,9 +87,8 @@ services:
- traefik.http.services.radarr.loadbalancer.server.port=7878
jellyseerr:
image: fallenbagel/jellyseerr:latest
image: fallenbagel/jellyseerr@sha256:499fbe958fa4a0c93172a231c14898986556bb28bd5cd569a0f41dbf887b04d7
container_name: jellyseerr
pull_policy: always
environment:
- LOG_LEVEL=debug
- TZ=${TZ:-Europe/Madrid}
@@ -108,9 +103,8 @@ services:
# Opcional: Jellyfin en VPS (sin GPU)
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
image: lscr.io/linuxserver/jellyfin@sha256:b46e291fb2a532eef9e2e1b7d3b927ab39558f0c58964a63f21013071f1ae278
container_name: jellyfin-vps
pull_policy: always
environment:
- PUID=0
- PGID=0
-1
View File
@@ -34,7 +34,6 @@ services:
nextcloud:
image: nextcloud:33-apache
container_name: nextcloud
pull_policy: always
restart: unless-stopped
depends_on:
- nextcloud-db
+2 -8
View File
@@ -1,12 +1,12 @@
services:
opengist:
image: ${OPENGIST_IMAGE}
pull_policy: always
container_name: opengist
restart: unless-stopped
environment:
TZ: ${TZ}
OG_OPENGIST_HOME: /opengist
OG_EXTERNAL_URL: "https://${OPENGIST_DOMAIN}"
OG_OIDC_PROVIDER_NAME: ${OPENGIST_OIDC_PROVIDER_NAME}
OG_OIDC_CLIENT_KEY: ${OPENGIST_OIDC_CLIENT_ID}
OG_OIDC_SECRET: ${OPENGIST_OIDC_CLIENT_SECRET}
@@ -16,15 +16,9 @@ services:
networks:
- proxy
labels:
prune.protect: "true"
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
traefik.http.routers.opengist.rule: "Host(`${OPENGIST_DOMAIN}`)"
traefik.http.routers.opengist.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.opengist.tls: "true"
traefik.http.routers.opengist.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.opengist.middlewares: "crowdsec-bouncer@file"
traefik.http.routers.opengist.service: "opengist-svc"
traefik.http.services.opengist-svc.loadbalancer.server.port: "6157"
homepage.group: "Automatizacion y desarrollo"
homepage.name: "OpenGist"
+1 -15
View File
@@ -11,28 +11,14 @@ services:
networks:
- proxy
labels:
prune.protect: "true"
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
# Router publico — permite abrir enlaces compartidos sin login.
traefik.http.routers.pbin-public.rule: "Host(`${PRIVATEBIN_DOMAIN}`) && (Method(`GET`) || Method(`HEAD`))"
traefik.http.routers.pbin-public.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.pbin-public.tls: "true"
traefik.http.routers.pbin-public.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.pbin-public.middlewares: "crowdsec-bouncer@file"
traefik.http.routers.pbin-public.service: "pbin-svc"
traefik.http.routers.pbin-public.priority: "20"
# Router protegido — crear/borrar requiere login.
traefik.http.routers.pbin.rule: "Host(`${PRIVATEBIN_DOMAIN}`)"
traefik.http.routers.pbin.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.pbin.tls: "true"
traefik.http.routers.pbin.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.pbin.middlewares: "crowdsec-bouncer@file,${TRAEFIK_AUTH_MIDDLEWARE}"
traefik.http.routers.pbin.service: "pbin-svc"
traefik.http.routers.pbin.priority: "10"
traefik.http.services.pbin-svc.loadbalancer.server.port: "8080"
homepage.group: "Automatizacion y desarrollo"
homepage.name: "PrivateBin"
+16
View File
@@ -0,0 +1,16 @@
services:
sablier:
image: acouvreur/sablier:${SABLIER_VERSION}
container_name: sablier
restart: unless-stopped
command:
- start
- --provider.name=docker
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro,Z
networks:
- proxy
networks:
proxy:
external: true
+1
View File
@@ -0,0 +1 @@
SABLIER_VERSION=1.8.0
+87
View File
@@ -0,0 +1,87 @@
#!/bin/bash
# Recorre contenedores con restart-policy always/unless-stopped que estén
# caídos (Exited) o atascados (Restarting) y los recrea vía su propio
# proyecto docker compose, para curar referencias de red obsoletas tras
# un reinicio del daemon Docker (ej. update automático de docker-ce).
#
# Idempotente: si nada está roto, no hace nada. Pensado para correr
# periódicamente vía systemd timer (docker-selfheal.timer).
set -uo pipefail
LOG_FILE="/var/log/docker-selfheal.log"
TELEGRAM_ENV="/home/felidae/f2b-telegram-bot/.env"
SABLIER_CONFIG="/opt/traefik/dynamic/sablier.yml"
# Contenedores que Sablier apaga a propósito (scale-to-zero) quedan Exited
# con restart-policy unless-stopped igual que un crash real -- no hay forma
# de distinguirlos por estado/policy. Se excluyen por nombre, leyendo los
# `names:` de cada middleware sablier-* en el dynamic config de Traefik.
declare -A SABLIER_MANAGED=()
if [ -r "$SABLIER_CONFIG" ]; then
while IFS= read -r line; do
line="${line#*names:}"
line="${line//\"/}"
IFS=',' read -ra names <<< "$line"
for n in "${names[@]}"; do
n="$(echo "$n" | xargs)"
[ -n "$n" ] && SABLIER_MANAGED["$n"]=1
done
done < <(grep -E '^\s*names:' "$SABLIER_CONFIG")
fi
log() {
echo "$(date -u +'%Y-%m-%dT%H:%M:%SZ') $*" | tee -a "$LOG_FILE"
}
notify() {
local msg="$1"
[ -f "$TELEGRAM_ENV" ] || return 0
local token chat_id
token=$(grep -E '^BOT_TOKEN=' "$TELEGRAM_ENV" | cut -d= -f2- | tr -d '"')
chat_id=$(grep -E '^PRIMARY_CHAT_ID=' "$TELEGRAM_ENV" | cut -d= -f2- | tr -d '"')
[ -n "$token" ] && [ -n "$chat_id" ] || return 0
curl -s -m 10 -X POST "https://api.telegram.org/bot${token}/sendMessage" \
-d "chat_id=${chat_id}" \
-d "text=${msg}" >/dev/null 2>&1
}
fixed_any=0
# Contenedores parados o atascados que deberían estar corriendo
mapfile -t broken < <(docker ps -a --filter "status=exited" --filter "status=restarting" --filter "status=created" --format '{{.ID}}')
for cid in "${broken[@]}"; do
policy=$(docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' "$cid" 2>/dev/null)
name=$(docker inspect -f '{{.Name}}' "$cid" 2>/dev/null | sed 's#^/##')
case "$policy" in
always|unless-stopped) ;;
*) continue ;;
esac
if [ -n "${SABLIER_MANAGED[$name]:-}" ]; then
continue
fi
workdir=$(docker inspect -f '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}' "$cid" 2>/dev/null)
project=$(docker inspect -f '{{ index .Config.Labels "com.docker.compose.project" }}' "$cid" 2>/dev/null)
service=$(docker inspect -f '{{ index .Config.Labels "com.docker.compose.service" }}' "$cid" 2>/dev/null)
if [ -n "$workdir" ] && [ -d "$workdir" ]; then
log "Recreando '$name' (proyecto '$project', servicio '$service') vía compose en $workdir"
out=$(cd "$workdir" && docker compose up -d --force-recreate "$service" 2>&1)
log "$out"
fixed_any=1
notify "🔧 docker-selfheal: '$name' estaba caído (policy=$policy), recreado vía compose en ${project}."
else
log "Recreando '$name' vía docker start (sin metadata de compose)"
docker start "$cid" >/dev/null 2>&1
fixed_any=1
notify "🔧 docker-selfheal: '$name' estaba caído (policy=$policy), levantado con docker start."
fi
done
if [ "$fixed_any" -eq 0 ]; then
log "Nada que arreglar."
fi
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
set -eu
docker system prune -af --filter "label!=prune.protect=true"
+1 -12
View File
@@ -2,7 +2,6 @@ services:
trilium:
image: ${TRILIUM_IMAGE}
container_name: trilium
pull_policy: always
restart: unless-stopped
hostname: ${TRILIUM_HOSTNAME}
@@ -19,19 +18,9 @@ services:
- proxy
labels:
prune.protect: "true"
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
traefik.http.routers.trilium.rule: "Host(`${TRILIUM_DOMAIN_1}`) || Host(`${TRILIUM_DOMAIN_2}`)"
traefik.http.routers.trilium.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.trilium.middlewares: "trilium-sec"
traefik.http.routers.trilium.tls: "true"
traefik.http.routers.trilium.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.services.trilium.loadbalancer.server.port: "${TRILIUM_HTTP_PORT}"
traefik.http.middlewares.trilium-sec.headers.stsSeconds: "31536000"
traefik.http.middlewares.trilium-sec.headers.stsIncludeSubdomains: "true"
traefik.http.middlewares.trilium-sec.headers.stsPreload: "true"
traefik.http.middlewares.trilium-sec.headers.contentTypeNosniff: "true"
traefik.http.middlewares.trilium-sec.headers.frameDeny: "true"
networks:
proxy:
+4 -7
View File
@@ -3,6 +3,8 @@ services:
image: postgres:17-alpine
container_name: vikunja-db
restart: unless-stopped
labels:
prune.protect: "true"
environment:
TZ: ${TZ}
POSTGRES_DB: ${VIKUNJA_DB_NAME}
@@ -20,8 +22,7 @@ services:
- vikunja_internal
vikunja:
image: vikunja/vikunja:latest
pull_policy: always
image: vikunja/vikunja@sha256:f6b80393c1998cd5cd0dc38d24762c59ab4c10000a6f1032ef5b554e262cab93
container_name: vikunja
restart: unless-stopped
user: "1000:1000"
@@ -55,13 +56,9 @@ services:
- mail_internal
- proxy
labels:
prune.protect: "true"
traefik.enable: "true"
traefik.docker.network: "proxy"
traefik.http.routers.vikunja.rule: "Host(`${VIKUNJA_DOMAIN}`)"
traefik.http.routers.vikunja.entrypoints: "websecure"
traefik.http.routers.vikunja.tls: "true"
traefik.http.routers.vikunja.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.services.vikunja.loadbalancer.server.port: "3456"
networks:
vikunja_internal:
-1
View File
@@ -2,7 +2,6 @@ services:
wg-easy:
image: ${WG_EASY_IMAGE}
container_name: wg-easy
pull_policy: always
restart: unless-stopped
cap_add: