services: soft-serve: image: charmcli/soft-serve:v0.12.2 container_name: soft-serve restart: unless-stopped # non-root (uid 1000 = windy; 与 backup sidecar BACKUP_UID 一致) user: "1000:1000" environment: SOFT_SERVE_DATA_PATH: /var/lib/soft-serve SOFT_SERVE_INITIAL_ADMIN: windy SOFT_SERVE_INITIAL_ADMIN_KEYS: ${SOFT_SERVE_INITIAL_ADMIN_KEYS} volumes: - ./data:/var/lib/soft-serve - soft-serve-app:/soft-serve networks: - traefik labels: - traefik.enable=true # SSH over TCP via Traefik (entryPoint ssh -> container port 23231) - traefik.tcp.routers.softserve-ssh.entrypoints=ssh - traefik.tcp.routers.softserve-ssh.rule=HostSNI(`*`) - traefik.tcp.routers.softserve-ssh.tls=false - traefik.tcp.services.softserve-ssh.loadbalancer.server.port=23231 soft-serve-backup: build: context: . dockerfile: Dockerfile.backup container_name: soft-serve-backup restart: unless-stopped volumes: - ./data:/data:ro - ./backups:/backup - ./scripts:/scripts environment: TZ: Asia/Shanghai BACKUP_UID: 1000 BACKUP_GID: 1000 entrypoint: > /bin/sh -ec " umask 077 && touch /backup/backup.log && crontab /scripts/crontab.txt && echo '[INFO] soft-serve backup cron installed' && crond -f -l 8 " volumes: soft-serve-app: networks: traefik: external: true name: vw-net