diff --git a/config/nginx/rstat.net-NOSSL.conf b/config/nginx/rstat.net-NOSSL.conf new file mode 100644 index 0000000..48fa3e6 --- /dev/null +++ b/config/nginx/rstat.net-NOSSL.conf @@ -0,0 +1,15 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + + server_name its.pkhamre.com; + server_tokens off; + + location /.well-known/acme-challenge/ { + root /usr/share/nginx/certbot; + } + + location / { + return 301 https://its.pkhamre.com$request_uri; + } +} diff --git a/config/nginx/rstat.net-SSL.conf b/config/nginx/rstat.net-SSL.conf new file mode 100644 index 0000000..36a84ed --- /dev/null +++ b/config/nginx/rstat.net-SSL.conf @@ -0,0 +1,65 @@ +server { + listen 443 ssl; + listen [::]:443 ssl; + + server_name its.pkhamre.com; + server_tokens off; + + http2 on; + + ssl_certificate /etc/nginx/ssl/live/its.pkhamre.com/fullchain.pem; + ssl_certificate_key /etc/nginx/ssl/live/its.pkhamre.com/privkey.pem; + + # HSTS (ngx_http_headers_module is required) (63072000 seconds) + add_header Strict-Transport-Security "max-age=63072000" always; + + location / { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + + proxy_pass http://varnish:80; + proxy_redirect off; + } + + location /files/ { + root /usr/share/nginx/its.pkhamre.com/; + autoindex on; + autoindex_exact_size off; + autoindex_format html; + autoindex_localtime on; + } + + location /privacy/ { + root /usr/share/nginx/its.pkhamre.com/; + } + + location /p/ { + root /usr/share/nginx/its.pkhamre.com/; + } +} + +# intermediate configuration +ssl_protocols TLSv1.2 TLSv1.3; +ssl_ecdh_curve X25519:prime256v1:secp384r1; +ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305; +ssl_prefer_server_ciphers off; + +# see also ssl_session_ticket_key alternative to stateful session cache +ssl_session_timeout 1d; +ssl_session_cache shared:MozSSL:10m; # about 40000 sessions + +# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam +ssl_dhparam /etc/nginx/ssl/dhparam.pem; + +# OCSP stapling +ssl_stapling on; +ssl_stapling_verify on; + +# verify chain of trust of OCSP response using Root CA and Intermediate certs +ssl_trusted_certificate /etc/nginx/ssl/live/its.pkhamre.com/chain.pem; + +# replace with the IP address of your resolver; +# async 'resolver' is important for proper operation of OCSP stapling +resolver 67.207.67.2; diff --git a/config/varnish/default.vcl b/config/varnish/default.vcl new file mode 100644 index 0000000..47a3170 --- /dev/null +++ b/config/varnish/default.vcl @@ -0,0 +1,71 @@ +vcl 4.1; + +# https://github.com/varnish/toolbox/tree/master/vcls/hit-miss +include "hit-miss.vcl"; + +# import vmod_dynamic for better backend name resolution +import dynamic; +import std; + +backend default { + .host = "ghost"; + .port = "2368"; +} + +acl purge { + "localhost"; + "nginx"; + "127.0.0.1"; +} + +sub vcl_recv { + if (req.url ~ "/purge-cache") { + if (!client.ip ~ purge) { + return(synth(403, "Not allowed.")); + } + ban("req.http.host == its.pkhamre.com"); + return(synth(200, "Cache cleared")); + } + + # Cache static files + if (req.url ~ "\.(css|js|avif|webp|png|jpe?g|gif|ico|svg|woff2?|eot|ttf|otf|json|csv|pdf|mp4|webm|ogg|mp3|wav|flac)$") { + unset req.http.Cookie; + return(hash); + } + + # Don't cache if these cookies are present + if (req.http.Cookie ~ "ghost-members-ssr" || req.http.Cookie ~ "ghost-admin-api-session") { + return(pass); + } + + # Don't cache these paths + if (req.url ~ "^/(ghost|members|p)/") { + return(pass); + } + + # Remove all cookies for other requests + unset req.http.Cookie; + return(hash); +} + +sub vcl_backend_response { + # Cache static files and other content in Varnish for 1 year + set beresp.ttl = 1y; + # Enable stale content serving + set beresp.grace = 24h; + # Preserve the origin's Cache-Control header for client-side caching + if (beresp.http.Cache-Control) { + set beresp.http.X-Orig-Cache-Control = beresp.http.Cache-Control; + } +} + +sub vcl_deliver { + # Restore the origin's Cache-Control header for the browser + if (resp.http.X-Orig-Cache-Control) { + set resp.http.Cache-Control = resp.http.X-Orig-Cache-Control; + unset resp.http.X-Orig-Cache-Control; + } else { + # If no Cache-Control was set by the origin, we'll set a default + set resp.http.Cache-Control = "no-cache, must-revalidate"; + } +} diff --git a/docker-compose-prod.yml b/docker-compose-prod.yml new file mode 100644 index 0000000..5985545 --- /dev/null +++ b/docker-compose-prod.yml @@ -0,0 +1,42 @@ +name: rstat + +services: + + rstat-dashboard: + build: + context: . + dockerfile: Dockerfile + restart: always + environment: + - FLASK_ENV=production + - FLASK_APP=rstat_tool.app:create_app + - RSTAT_CONFIG_FILE=/app/config/config.py + volumes: + - ./reddit_stocks:/usr/share/app/reddit_stocks.db:ro + ports: + - "5000:5000" + + nginx: + image: nginx:1.29.0 + restart: always + volumes: + - ./config/nginx:/etc/nginx/conf.d:ro + - ./config/certbot:/etc/nginx/ssl:ro + - ./public:/usr/share/nginx:ro + ports: + - "80:80" + - "443:443" + + varnish: + image: varnish:7.7.1 + restart: always + volumes: + - ./config/varnish/default.vcl:/etc/varnish/default.vcl:ro" + tmpfs: + - /var/lib/varnish/varnishd:exec + + certbot: + image: certbot/certbot:v4.1.1 + volumes: + - ./config/certbot:/etc/letsencrypt:rw + - ./public/certbot:/usr/share/nginx/certbot:rw diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..524beb9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +name: rstat + +services: + + nginx: + image: nginx:1.29.0 + restart: always + volumes: + - ./config/nginx:/etc/nginx/conf.d:ro + - ./config/certbot:/etc/nginx/ssl:ro + - ./public:/usr/share/nginx:ro + ports: + - "80:80" + - "443:443" + + certbot: + image: certbot/certbot:v4.1.1 + volumes: + - ./config/certbot:/etc/letsencrypt:rw + - ./public/certbot:/usr/share/nginx/certbot:rw