Add complete frontend implementation and Docker deployment setup

- Implement React frontend with TypeScript and Tailwind CSS
- Add scrappbook.de-inspired UI design with photo galleries
- Implement authentication, photo viewing, and download features
- Add Docker Swarm configuration with Traefik reverse proxy
- Set up Drone CI/CD pipeline for automated deployments
- Add monitoring stack with Prometheus and Grafana
- Create comprehensive deployment documentation
- Add simple local development setup with docker-compose.local.yml

Features:
- Password-protected galleries with expiration warnings
- Responsive photo grid with lightbox viewer
- Bulk download functionality
- Hot reload development environment
- Email testing with Mailhog
- Production-ready deployment scripts

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-06 20:23:13 +02:00
parent 032bbae50d
commit 6c82958c79
73 changed files with 10611 additions and 2 deletions
+124
View File
@@ -0,0 +1,124 @@
version: '3.8'
services:
traefik:
image: traefik:v2.10
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
networks:
- traefik-public
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik-certificates:/letsencrypt
environment:
- TRAEFIK_API=true
- TRAEFIK_API_DASHBOARD=true
- TRAEFIK_API_DEBUG=false
- TRAEFIK_LOG_LEVEL=INFO
- TRAEFIK_PROVIDERS_DOCKER=true
- TRAEFIK_PROVIDERS_DOCKER_SWARMMODE=true
- TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT=false
- TRAEFIK_PROVIDERS_DOCKER_NETWORK=traefik-public
- TRAEFIK_ENTRYPOINTS_HTTP_ADDRESS=:80
- TRAEFIK_ENTRYPOINTS_HTTPS_ADDRESS=:443
# Redirect HTTP to HTTPS
- TRAEFIK_ENTRYPOINTS_HTTP_HTTP_REDIRECTIONS_ENTRYPOINT_TO=https
- TRAEFIK_ENTRYPOINTS_HTTP_HTTP_REDIRECTIONS_ENTRYPOINT_SCHEME=https
# Let's Encrypt
- TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_EMAIL=${ACME_EMAIL}
- TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_STORAGE=/letsencrypt/acme.json
- TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_HTTPCHALLENGE=true
- TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_HTTPCHALLENGE_ENTRYPOINT=http
# Enable metrics
- TRAEFIK_METRICS_PROMETHEUS=true
- TRAEFIK_METRICS_PROMETHEUS_ENTRYPOINT=metrics
- TRAEFIK_ENTRYPOINTS_METRICS_ADDRESS=:8082
deploy:
mode: global
placement:
constraints:
- node.role == manager
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.constraint-label=traefik-public"
# Dashboard
- "traefik.http.routers.traefik-dashboard.rule=Host(`${TRAEFIK_HOST}`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
- "traefik.http.routers.traefik-dashboard.entrypoints=https"
- "traefik.http.routers.traefik-dashboard.tls=true"
- "traefik.http.routers.traefik-dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.traefik-dashboard.service=api@internal"
- "traefik.http.routers.traefik-dashboard.middlewares=admin-auth"
# Basic auth for dashboard
- "traefik.http.middlewares.admin-auth.basicauth.users=${TRAEFIK_DASHBOARD_AUTH}"
# Global redirect to https
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
# Security headers
- "traefik.http.middlewares.security-headers.headers.frameDeny=true"
- "traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.security-headers.headers.browserXssFilter=true"
- "traefik.http.middlewares.security-headers.headers.stsSeconds=31536000"
- "traefik.http.middlewares.security-headers.headers.stsIncludeSubdomains=true"
- "traefik.http.middlewares.security-headers.headers.stsPreload=true"
# Rate limiting
- "traefik.http.middlewares.rate-limit.ratelimit.average=100"
- "traefik.http.middlewares.rate-limit.ratelimit.burst=50"
# API service
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
healthcheck:
test: ["CMD", "traefik", "healthcheck"]
interval: 30s
timeout: 3s
retries: 3
# Traefik Forward Auth for advanced authentication (optional)
traefik-forward-auth:
image: thomseddon/traefik-forward-auth:latest
networks:
- traefik-public
environment:
- DEFAULT_PROVIDER=generic-oauth
- PROVIDERS_GENERIC_OAUTH_AUTH_URL=${OAUTH_AUTH_URL}
- PROVIDERS_GENERIC_OAUTH_TOKEN_URL=${OAUTH_TOKEN_URL}
- PROVIDERS_GENERIC_OAUTH_USER_URL=${OAUTH_USER_URL}
- PROVIDERS_GENERIC_OAUTH_CLIENT_ID=${OAUTH_CLIENT_ID}
- PROVIDERS_GENERIC_OAUTH_CLIENT_SECRET=${OAUTH_CLIENT_SECRET}
- SECRET=${OAUTH_SECRET}
- COOKIE_DOMAIN=${COOKIE_DOMAIN}
- INSECURE_COOKIE=false
- LOG_LEVEL=info
- URL_PATH=/_oauth
- WHITELIST=${OAUTH_WHITELIST}
deploy:
replicas: 2
restart_policy:
condition: on-failure
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.http.routers.traefik-forward-auth.rule=Host(`${FRONTEND_HOST}`) && PathPrefix(`/_oauth`)"
- "traefik.http.routers.traefik-forward-auth.entrypoints=https"
- "traefik.http.routers.traefik-forward-auth.tls=true"
- "traefik.http.routers.traefik-forward-auth.tls.certresolver=letsencrypt"
- "traefik.http.routers.traefik-forward-auth.middlewares=auth-verify"
- "traefik.http.services.traefik-forward-auth.loadbalancer.server.port=4181"
- "traefik.http.middlewares.auth-verify.forwardauth.address=http://traefik-forward-auth:4181"
- "traefik.http.middlewares.auth-verify.forwardauth.authResponseHeaders=X-Forwarded-User"
networks:
traefik-public:
external: true
volumes:
traefik-certificates:
driver: local
+93
View File
@@ -0,0 +1,93 @@
# Static configuration
global:
checkNewVersion: true
sendAnonymousUsage: false
api:
dashboard: true
debug: false
# Entry Points
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
priority: 1000
https:
address: ":443"
http:
tls:
certResolver: letsencrypt
domains:
- main: "${FRONTEND_HOST}"
- main: "${BACKEND_HOST}"
- main: "${UMAMI_HOST}"
forwardedHeaders:
trustedIPs:
- "127.0.0.1/32"
- "10.0.0.0/8"
- "172.16.0.0/12"
- "192.168.0.0/16"
metrics:
address: ":8082"
# Providers
providers:
docker:
swarmMode: true
exposedByDefault: false
network: traefik-public
watch: true
file:
directory: /etc/traefik/dynamic
watch: true
# Certificate Resolvers
certificatesResolvers:
letsencrypt:
acme:
email: ${ACME_EMAIL}
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: http
# Staging server for testing
# caServer: https://acme-staging-v02.api.letsencrypt.org/directory
# Logs
log:
level: INFO
format: json
accessLog:
format: json
filters:
statusCodes:
- "200-299"
- "400-499"
- "500-599"
retryAttempts: true
minDuration: "10ms"
# Metrics
metrics:
prometheus:
entryPoint: metrics
addEntryPointsLabels: true
addServicesLabels: true
buckets:
- 0.1
- 0.3
- 1.2
- 5.0
# Ping
ping:
entryPoint: traefik
# Pilot
pilot:
enabled: false