--- /dev/null
+# Redirect all HTTP to HTTPS with no-WWW
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ server_name ~^(?:www\.)?(.*)$;
+ return 301 https://$1$request_uri;
+}
+
+# API
+server {
+ server_name api.nutra.tk;
+ #listen 80;
+ listen 443 ssl http2;
+ # HSTS
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
+
+ # Sanic
+ location / {
+ proxy_pass http://127.0.0.1:20000; # API server
+ # Allow fast streaming HTTP/1.1 pipes (keep-alive, unbuffered)
+ proxy_http_version 1.1;
+ proxy_request_buffering off;
+ proxy_buffering off;
+ # Proxy forwarding (password configured in app.config.FORWARDED_SECRET)
+ proxy_set_header forwarded "$proxy_forwarded;secret=\"dhPipfTpfHwH7JsTkHcNPTihvbTnegzV\"";
+ # Allow websockets and keep-alive (avoid connection: close)
+ proxy_set_header connection "upgrade";
+ proxy_set_header upgrade $http_upgrade;
+ }
+
+ # default favicon
+ location /favicon.ico {
+ alias /var/www/favicon.gif;
+ }
+}
+
+# UI, blog, favicon, default server
+server {
+ server_name nutra.tk;
+ #listen 80 default_server;
+ #listen [::]:80 ipv6only=on;
+ listen 443 ssl http2 default_server;
+ listen [::]:443 ssl ipv6only=on; # managed by Certbot
+ # HSTS
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
+ # OCSP stapling
+ ssl_stapling on;
+ ssl_stapling_verify on;
+ ssl_trusted_certificate /etc/ssl/private/ca-certs.pem;
+
+ client_max_body_size 50m;
+
+ # React app (base URL)
+ location / {
+ #return 302 https://$host/api$request_uri;
+ root /var/www/app;
+ index index.html;
+ #try_files $uri $uri/ /index.html =404;
+ }
+
+ # Blog / Sphinx
+ location /blog {
+ alias /var/www/blog;
+ index index.html;
+ }
+
+ # default favicon
+ location = /favicon.ico {
+ alias /var/www/favicon.gif;
+ }
+
+ # Other
+ location ~ /.well-known {
+ allow all;
+ }
+
+ # HTTPS / SSL
+ ssl_certificate /etc/letsencrypt/live/nutra.tk/fullchain.pem; # managed by Certbot
+ ssl_certificate_key /etc/letsencrypt/live/nutra.tk/privkey.pem; # managed by Certbot
+ include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
+
+ # TODO: better redirect based on server, not if?
+ if ($host = www.nutra.tk) {
+ return 301 https://nutra.tk$request_uri;
+ }
+}
--- /dev/null
+# RFC 7239 Forwarded header for Nginx proxy_pass
+
+# Add within your server or location block:
+# proxy_set_header forwarded "$proxy_forwarded;secret=\"YOUR SECRET\"";
+
+# Configure your upstream web server to identify this proxy by that password
+# because otherwise anyone on the Internet could spoof these headers and fake
+# their real IP address and other information to your service.
+
+
+# Provide the full proxy chain in $proxy_forwarded
+map $proxy_add_forwarded $proxy_forwarded {
+ default "$proxy_add_forwarded;by=\"_$hostname\";proto=$scheme;host=\"$http_host\";path=\"$request_uri\"";
+}
+
+# The following mappings are based on
+# https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/
+
+map $remote_addr $proxy_forwarded_elem {
+ # IPv4 addresses can be sent as-is
+ ~^[0-9.]+$ "for=$remote_addr";
+
+ # IPv6 addresses need to be bracketed and quoted
+ ~^[0-9A-Fa-f:.]+$ "for=\"[$remote_addr]\"";
+
+ # Unix domain socket names cannot be represented in RFC 7239 syntax
+ default "for=unknown";
+}
+
+map $http_forwarded $proxy_add_forwarded {
+ # If the incoming Forwarded header is syntactically valid, append to it
+ "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";
+
+ # Otherwise, replace it
+ default "$proxy_forwarded_elem";
+}
+
--- /dev/null
+# DO NOT EDIT THIS FILE - edit the master and reinstall.
+# (/tmp/crontab.K8RTD8/crontab installed on Wed Dec 24 09:52:40 2025)
+# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
+# Edit this file to introduce tasks to be run by cron.
+#
+# Each task to run has to be defined through a single line
+# indicating with different fields when the task will be run
+# and what command to run for the task
+#
+# To define the time you can provide concrete values for
+# minute (m), hour (h), day of month (dom), month (mon),
+# and day of week (dow) or use '*' in these fields (for 'any').
+#
+# Notice that tasks will be started based on the cron's system
+# daemon's notion of time and timezones.
+#
+# Output of the crontab jobs (including errors) is sent through
+# email to the user the crontab file belongs to (unless redirected).
+#
+# For example, you can run a backup of all your user accounts
+# at 5 a.m every week with:
+# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
+#
+# For more information see the manual pages of crontab(5) and cron(8)
+#
+# m h dom mon dow command
+0 0,12 * * * /opt/certbot/bin/certbot renew -q
+