Add nginx reverse proxy with Let's Encrypt SSL
- nginx as reverse proxy for dawarich frontend - Let's Encrypt certificate support with automatic renewal - HTTP to HTTPS redirect, gzip compression - Bootstrap config for initial certificate request Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2
.env.example
Normal file
2
.env.example
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# E-Mail fuer Let's Encrypt Zertifikatsanforderung (erforderlich fuer SSL)
|
||||||
|
CERTBOT_EMAIL=elpatron@mailbox.org
|
||||||
179
docker-compose.yml
Normal file
179
docker-compose.yml
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
networks:
|
||||||
|
dawarich:
|
||||||
|
frontend:
|
||||||
|
external: true
|
||||||
|
services:
|
||||||
|
dawarich_redis:
|
||||||
|
image: redis:7.0-alpine
|
||||||
|
container_name: dawarich_redis
|
||||||
|
command: redis-server
|
||||||
|
networks:
|
||||||
|
- dawarich
|
||||||
|
volumes:
|
||||||
|
- dawarich_shared:/data
|
||||||
|
restart: always
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
|
||||||
|
interval: 10s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
timeout: 10s
|
||||||
|
dawarich_db:
|
||||||
|
image: postgis/postgis:14-3.5-alpine
|
||||||
|
shm_size: 1G
|
||||||
|
container_name: dawarich_db
|
||||||
|
volumes:
|
||||||
|
- dawarich_db_data:/var/lib/postgresql/data
|
||||||
|
- dawarich_shared:/var/shared
|
||||||
|
# - ./postgresql.conf:/etc/postgresql/postgresql.conf # Optional, uncomment if you want to use a custom config
|
||||||
|
networks:
|
||||||
|
- dawarich
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: password
|
||||||
|
restart: always
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD-SHELL", "pg_isready -U postgres -d dawarich_development" ]
|
||||||
|
interval: 10s
|
||||||
|
retries: 30
|
||||||
|
start_period: 30s
|
||||||
|
timeout: 30s
|
||||||
|
# command: postgres -c config_file=/etc/postgresql/postgresql.conf # Use custom config, uncomment if you want to use a custom config
|
||||||
|
nginx:
|
||||||
|
build: ./nginx
|
||||||
|
container_name: dawarich_nginx
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- certbot_etc:/etc/letsencrypt
|
||||||
|
- certbot_www:/var/www/certbot
|
||||||
|
networks:
|
||||||
|
- dawarich
|
||||||
|
environment:
|
||||||
|
CERTBOT_EMAIL: ${CERTBOT_EMAIL:-}
|
||||||
|
depends_on:
|
||||||
|
dawarich_app:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: always
|
||||||
|
dawarich_app:
|
||||||
|
image: freikin/dawarich:latest
|
||||||
|
container_name: dawarich_app
|
||||||
|
volumes:
|
||||||
|
- dawarich_public:/var/app/public
|
||||||
|
- dawarich_watched:/var/app/tmp/imports/watched
|
||||||
|
- dawarich_storage:/var/app/storage
|
||||||
|
networks:
|
||||||
|
- dawarich
|
||||||
|
# Port 3000 nicht exponiert - Traffic laeuft ueber nginx Reverse Proxy
|
||||||
|
# - 9394:9394 # Prometheus exporter, uncomment if needed
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
|
entrypoint: web-entrypoint.sh
|
||||||
|
command: ['bin/rails', 'server', '-p', '3000', '-b', '::']
|
||||||
|
restart: on-failure
|
||||||
|
environment:
|
||||||
|
RAILS_ENV: development
|
||||||
|
REDIS_URL: redis://dawarich_redis:6379
|
||||||
|
DATABASE_HOST: dawarich_db
|
||||||
|
DATABASE_USERNAME: postgres
|
||||||
|
DATABASE_PASSWORD: password
|
||||||
|
DATABASE_NAME: dawarich_development
|
||||||
|
MIN_MINUTES_SPENT_IN_CITY: 60
|
||||||
|
APPLICATION_HOSTS: "location.butenostfreesen.de,127.0.0.1"
|
||||||
|
TIME_ZONE: Europe/Berlin
|
||||||
|
APPLICATION_PROTOCOL: httpss
|
||||||
|
DISTANCE_UNIT: km
|
||||||
|
PROMETHEUS_EXPORTER_ENABLED: false
|
||||||
|
PROMETHEUS_EXPORTER_HOST: 0.0.0.0
|
||||||
|
PROMETHEUS_EXPORTER_PORT: 9394
|
||||||
|
ENABLE_TELEMETRY: false # More on telemetry: https://dawarich.app/docs/tutorials/telemetry
|
||||||
|
SELF_HOSTED: "true"
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "100m"
|
||||||
|
max-file: "5"
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD-SHELL", "wget -qO - http://127.0.0.1:3000/api/v1/health | grep -q '\"status\"\\s*:\\s*\"ok\"'" ]
|
||||||
|
interval: 10s
|
||||||
|
retries: 30
|
||||||
|
start_period: 30s
|
||||||
|
timeout: 10s
|
||||||
|
depends_on:
|
||||||
|
dawarich_db:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: true
|
||||||
|
dawarich_redis:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: true
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.50' # Limit CPU usage to 50% of one core
|
||||||
|
memory: '4G' # Limit memory usage to 4GB
|
||||||
|
dawarich_sidekiq:
|
||||||
|
image: freikin/dawarich:latest
|
||||||
|
container_name: dawarich_sidekiq
|
||||||
|
volumes:
|
||||||
|
- dawarich_public:/var/app/public
|
||||||
|
- dawarich_watched:/var/app/tmp/imports/watched
|
||||||
|
- dawarich_storage:/var/app/storage
|
||||||
|
networks:
|
||||||
|
- dawarich
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
|
entrypoint: sidekiq-entrypoint.sh
|
||||||
|
command: ['sidekiq']
|
||||||
|
restart: on-failure
|
||||||
|
environment:
|
||||||
|
RAILS_ENV: development
|
||||||
|
REDIS_URL: redis://dawarich_redis:6379
|
||||||
|
DATABASE_HOST: dawarich_db
|
||||||
|
DATABASE_USERNAME: postgres
|
||||||
|
DATABASE_PASSWORD: password
|
||||||
|
DATABASE_NAME: dawarich_development
|
||||||
|
APPLICATION_HOSTS: "location.butenostfreesen.de,127.0.0.1"
|
||||||
|
BACKGROUND_PROCESSING_CONCURRENCY: 10
|
||||||
|
APPLICATION_PROTOCOL: httpss
|
||||||
|
DISTANCE_UNIT: km
|
||||||
|
PROMETHEUS_EXPORTER_ENABLED: false
|
||||||
|
PROMETHEUS_EXPORTER_HOST: dawarich_app
|
||||||
|
PROMETHEUS_EXPORTER_PORT: 9394
|
||||||
|
ENABLE_TELEMETRY: false # More on telemetry: https://dawarich.app/docs/tutorials/telemetry
|
||||||
|
SELF_HOSTED: "true"
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "100m"
|
||||||
|
max-file: "5"
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD-SHELL", "bundle exec sidekiqmon processes | grep $${HOSTNAME}" ]
|
||||||
|
interval: 10s
|
||||||
|
retries: 30
|
||||||
|
start_period: 30s
|
||||||
|
timeout: 10s
|
||||||
|
depends_on:
|
||||||
|
dawarich_db:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: true
|
||||||
|
dawarich_redis:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: true
|
||||||
|
dawarich_app:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: true
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.50' # Limit CPU usage to 50% of one core
|
||||||
|
memory: '4G' # Limit memory usage to 4GB
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
dawarich_db_data:
|
||||||
|
dawarich_shared:
|
||||||
|
dawarich_public:
|
||||||
|
dawarich_watched:
|
||||||
|
dawarich_storage:
|
||||||
|
certbot_etc:
|
||||||
|
certbot_www:
|
||||||
7
nginx/Dockerfile
Normal file
7
nginx/Dockerfile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
FROM nginx:alpine
|
||||||
|
RUN apk add --no-cache certbot
|
||||||
|
COPY nginx.conf /etc/nginx/templates/nginx.conf
|
||||||
|
COPY nginx-bootstrap.conf /etc/nginx/templates/nginx-bootstrap.conf
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
50
nginx/entrypoint.sh
Normal file
50
nginx/entrypoint.sh
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DOMAIN="location.butenostfreesen.de"
|
||||||
|
EMAIL="${CERTBOT_EMAIL:-}"
|
||||||
|
|
||||||
|
# Entferne Standard-Config
|
||||||
|
rm -f /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Bootstrap-Config verwenden, wenn Zertifikate noch nicht existieren
|
||||||
|
if [ ! -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]; then
|
||||||
|
echo "Zertifikate nicht gefunden. Starte mit Bootstrap-Config..."
|
||||||
|
cp /etc/nginx/templates/nginx-bootstrap.conf /etc/nginx/conf.d/default.conf
|
||||||
|
nginx -g "daemon off;" &
|
||||||
|
NGINX_PID=$!
|
||||||
|
|
||||||
|
# Warte auf Backend
|
||||||
|
echo "Warte auf Backend..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
if [ -n "$EMAIL" ]; then
|
||||||
|
echo "Fordere Let's Encrypt Zertifikat an..."
|
||||||
|
if certbot certonly --webroot -w /var/www/certbot \
|
||||||
|
--email "$EMAIL" \
|
||||||
|
--agree-tos \
|
||||||
|
--no-eff-email \
|
||||||
|
--non-interactive \
|
||||||
|
-d "$DOMAIN"; then
|
||||||
|
echo "Zertifikat erfolgreich erstellt. Starte nginx mit HTTPS..."
|
||||||
|
kill $NGINX_PID 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
cp /etc/nginx/templates/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
else
|
||||||
|
echo "Zertifikatsanforderung fehlgeschlagen. Laeufe mit HTTP (Port 80)."
|
||||||
|
echo "Stelle sicher, dass location.butenostfreesen.de auf diesen Server zeigt."
|
||||||
|
exec wait $NGINX_PID
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "HINWEIS: CERTBOT_EMAIL nicht gesetzt. Starte ohne SSL."
|
||||||
|
echo "Fuer Let's Encrypt: CERTBOT_EMAIL=deine@email.de setzen und Container neu starten."
|
||||||
|
exec wait $NGINX_PID
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cp /etc/nginx/templates/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Zertifikatserneuerung alle 12 Stunden im Hintergrund
|
||||||
|
(while true; do sleep 12h; certbot renew --webroot -w /var/www/certbot --deploy-hook "nginx -s reload" 2>&1 | tee -a /var/log/certbot-renew.log; done) &
|
||||||
|
|
||||||
|
exec nginx -g "daemon off;"
|
||||||
19
nginx/nginx-bootstrap.conf
Normal file
19
nginx/nginx-bootstrap.conf
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Bootstrap-Konfiguration für initiale Zertifikatsanforderung (ohne SSL)
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name location.butenostfreesen.de;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
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 Host $http_host;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_pass http://dawarich_app:3000/;
|
||||||
|
}
|
||||||
|
}
|
||||||
72
nginx/nginx.conf
Normal file
72
nginx/nginx.conf
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name location.butenostfreesen.de;
|
||||||
|
|
||||||
|
# ACME-Challenge für Let's Encrypt Zertifikatserneuerung
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
listen [::]:443 ssl;
|
||||||
|
http2 on;
|
||||||
|
server_name location.butenostfreesen.de;
|
||||||
|
|
||||||
|
# Let's Encrypt Zertifikate
|
||||||
|
ssl_certificate /etc/letsencrypt/live/location.butenostfreesen.de/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/location.butenostfreesen.de/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_prefer_server_ciphers off;
|
||||||
|
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||||
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
ssl_session_timeout 1d;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_types
|
||||||
|
text/css
|
||||||
|
text/plain
|
||||||
|
text/xml
|
||||||
|
text/x-component
|
||||||
|
text/javascript
|
||||||
|
application/x-javascript
|
||||||
|
application/javascript
|
||||||
|
application/json
|
||||||
|
application/manifest+json
|
||||||
|
application/vnd.api+json
|
||||||
|
application/xml
|
||||||
|
application/xhtml+xml
|
||||||
|
application/rss+xml
|
||||||
|
application/atom+xml
|
||||||
|
application/vnd.ms-fontobject
|
||||||
|
application/x-font-ttf
|
||||||
|
application/x-font-opentype
|
||||||
|
application/x-font-truetype
|
||||||
|
image/svg+xml
|
||||||
|
image/x-icon
|
||||||
|
image/vnd.microsoft.icon
|
||||||
|
font/ttf
|
||||||
|
font/eot
|
||||||
|
font/otf
|
||||||
|
font/opentype;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
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 https;
|
||||||
|
proxy_set_header X-Forwarded-Server $host;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
proxy_redirect off;
|
||||||
|
|
||||||
|
proxy_pass http://dawarich_app:3000/;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user