From 5807bf85f1aa3a5b78f19965dde4e56fe560d99f Mon Sep 17 00:00:00 2001 From: SysAdmin Agent Date: Sat, 21 Mar 2026 23:47:52 +0000 Subject: [PATCH] GrampsWeb Phase 1: Production Compose, Reverse Proxy & Deployment (STI-91) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix grampsweb port mapping: 8090:80 → 8090:5000 (gunicorn, not nginx) - Add full subpath ENV vars: GRAMPSWEB_TREE, BASE_URL, STATIC_PATH, STATIC_URL - Add Celery/Redis config: broker_url, result_backend, ratelimit storage - Add GRAMPSWEB_NEW_DB_BACKEND=sqlite - Add depends_on: redis and restart: unless-stopped - Add GRAMPS_URL/USERNAME/PASSWORD/API_TOKEN to web service for Django integration - Add nginx.conf with /ahnenforschung/ reverse proxy route (proxy to localhost:8090) - Add GRAMPSWEB_STATIC_PATH and GRAMPSWEB_STATIC_URL to env-template.txt Co-Authored-By: Claude Sonnet 4.6 --- deploy-production/docker-compose.prod.yml | 17 +++- deploy-production/nginx.conf | 119 ++++++++++++++++++++++ env-template.txt | 2 + 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 deploy-production/nginx.conf diff --git a/deploy-production/docker-compose.prod.yml b/deploy-production/docker-compose.prod.yml index 9693458..c6c936d 100644 --- a/deploy-production/docker-compose.prod.yml +++ b/deploy-production/docker-compose.prod.yml @@ -49,6 +49,10 @@ services: - REDIS_URL=${REDIS_URL} - PAPERLESS_API_URL=${PAPERLESS_API_URL} - PAPERLESS_API_TOKEN=${PAPERLESS_API_TOKEN} + - GRAMPS_URL=${GRAMPS_URL} + - GRAMPS_USERNAME=${GRAMPS_USERNAME} + - GRAMPS_PASSWORD=${GRAMPS_PASSWORD} + - GRAMPS_API_TOKEN=${GRAMPS_API_TOKEN} ports: - "8081:8000" volumes: @@ -111,14 +115,25 @@ services: grampsweb: image: ghcr.io/gramps-project/grampsweb:latest + restart: unless-stopped ports: - - "8090:80" + - "8090:5000" environment: - GRAMPSWEB_SECRET_KEY=${GRAMPSWEB_SECRET_KEY} - GRAMPSWEB_ADMIN_EMAIL=${GRAMPSWEB_ADMIN_EMAIL} - GRAMPSWEB_ADMIN_PASSWORD=${GRAMPSWEB_ADMIN_PASSWORD} + - GRAMPSWEB_TREE=${GRAMPSWEB_TREE} + - GRAMPSWEB_BASE_URL=${GRAMPSWEB_BASE_URL} + - GRAMPSWEB_STATIC_PATH=${GRAMPSWEB_STATIC_PATH} + - GRAMPSWEB_STATIC_URL=${GRAMPSWEB_STATIC_URL} + - GRAMPSWEB_CELERY_CONFIG__broker_url=redis://redis:6379/0 + - GRAMPSWEB_CELERY_CONFIG__result_backend=redis://redis:6379/0 + - GRAMPSWEB_RATELIMIT_STORAGE_URI=redis://redis:6379/1 + - GRAMPSWEB_NEW_DB_BACKEND=sqlite volumes: - gramps_data:/app/data + depends_on: + - redis paperless: image: ghcr.io/paperless-ngx/paperless-ngx:latest diff --git a/deploy-production/nginx.conf b/deploy-production/nginx.conf new file mode 100644 index 0000000..da57054 --- /dev/null +++ b/deploy-production/nginx.conf @@ -0,0 +1,119 @@ +# HTTP server block - redirect to HTTPS +server { + listen 80; + server_name vhtv-stiftung.de www.vhtv-stiftung.de; + + # Redirect all HTTP traffic to HTTPS + return 301 https://$server_name$request_uri; +} + +# HTTPS server block +server { + listen 443 ssl http2; + server_name vhtv-stiftung.de www.vhtv-stiftung.de; + + # SSL Certificate Configuration + ssl_certificate /etc/letsencrypt/live/vhtv-stiftung.de/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/vhtv-stiftung.de/privkey.pem; + + # SSL Security Settings + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + # HSTS (HTTP Strict Transport Security) + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + # Enhanced Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'self' https: data: blob: 'unsafe-inline'" always; + + # Static files + location /static/ { + alias /opt/stiftung/app/static/; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + location /media/ { + alias /opt/stiftung/app/media/; + expires 1y; + add_header Cache-Control "public"; + } + + # Django application + location / { + proxy_pass http://127.0.0.1:8081; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Timeouts + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # Buffer settings + proxy_buffering on; + proxy_buffer_size 128k; + proxy_buffers 4 256k; + proxy_busy_buffers_size 256k; + } + + # Paperless-ngx document management + location /paperless/ { + proxy_pass http://127.0.0.1:8080/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Script-Name /paperless; + + # Large file uploads for documents + client_max_body_size 100M; + proxy_read_timeout 300s; + proxy_connect_timeout 300s; + proxy_send_timeout 300s; + } + + # GrampsWeb Ahnenforschung + location /ahnenforschung/ { + proxy_pass http://127.0.0.1:8090/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Script-Name /ahnenforschung; + + # WebSocket support (GrampsWeb uses SSE/WS for real-time updates) + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + proxy_read_timeout 300s; + proxy_connect_timeout 60s; + proxy_send_timeout 300s; + } + + # Health check endpoint + location /health/ { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } + + # Block access to sensitive files + location ~ /\. { + deny all; + } + + location ~ ^/(\.env|docker-compose|Dockerfile) { + deny all; + } +} diff --git a/env-template.txt b/env-template.txt index 8b87388..fe889ed 100644 --- a/env-template.txt +++ b/env-template.txt @@ -65,5 +65,7 @@ GRAMPSWEB_ADMIN_EMAIL=admin@vhtv-stiftung.de GRAMPSWEB_ADMIN_PASSWORD=your-grampsweb-admin-password-here GRAMPSWEB_TREE=Stiftung GRAMPSWEB_BASE_URL=/ahnenforschung +GRAMPSWEB_STATIC_PATH=/ahnenforschung/static +GRAMPSWEB_STATIC_URL=/ahnenforschung/static/ \ No newline at end of file