From 29aad9079eff199da5f2308b8b16efed35819f8b Mon Sep 17 00:00:00 2001 From: ray Date: Sun, 12 Jul 2026 10:15:51 -0400 Subject: [PATCH] initial commit --- .gitignore | 14 ++++ fastcgi.conf | 27 +++++++ fastcgi_params | 28 +++++++ koi-utf | 109 +++++++++++++++++++++++++++ koi-win | 103 +++++++++++++++++++++++++ mime.types | 101 +++++++++++++++++++++++++ nginx.conf | 99 ++++++++++++++++++++++++ proxy_params | 4 + scgi_params | 19 +++++ sites-available/audiobookshelf | 30 ++++++++ sites-available/chrome-vnc | 34 +++++++++ sites-available/default | 91 ++++++++++++++++++++++ sites-available/hermes-webui | 23 ++++++ sites-available/homeassistant | 22 ++++++ sites-available/immich | 25 +++++++ sites-available/mealie | 23 ++++++ sites-available/paperless | 23 ++++++ sites-available/plex | 25 +++++++ sites-available/pocketbase | 58 ++++++++++++++ sites-available/pocketbase-proxy | 18 +++++ sites-available/qbittorrent | 17 +++++ sites-available/shopproquote | 52 +++++++++++++ sites-available/vaultwarden | 35 +++++++++ sites-enabled/airrepairteam | 23 ++++++ sites-enabled/audiobookshelf | 1 + sites-enabled/chrome-vnc | 1 + sites-enabled/gitea | 23 ++++++ sites-enabled/hermes-dashboard | 18 +++++ sites-enabled/hermes-webui | 1 + sites-enabled/homeassistant | 22 ++++++ sites-enabled/immich | 1 + sites-enabled/mealie | 1 + sites-enabled/paperless | 1 + sites-enabled/plex | 1 + sites-enabled/pocketbase | 1 + sites-enabled/pocketbase-proxy | 1 + sites-enabled/qbittorrent | 1 + sites-enabled/shopproquote | 91 ++++++++++++++++++++++ sites-enabled/vaultwarden | 1 + snippets/deepseek-key.conf | 1 + snippets/fastcgi-php.conf | 13 ++++ snippets/snakeoil.conf | 5 ++ snippets/spq-deepseek.conf | 32 ++++++++ snippets/spq-security.conf | 6 ++ uwsgi_params | 19 +++++ win-utf | 125 +++++++++++++++++++++++++++++++ 46 files changed, 1369 insertions(+) create mode 100644 .gitignore create mode 100644 fastcgi.conf create mode 100644 fastcgi_params create mode 100644 koi-utf create mode 100644 koi-win create mode 100644 mime.types create mode 100644 nginx.conf create mode 100644 proxy_params create mode 100644 scgi_params create mode 100644 sites-available/audiobookshelf create mode 100644 sites-available/chrome-vnc create mode 100644 sites-available/default create mode 100644 sites-available/hermes-webui create mode 100644 sites-available/homeassistant create mode 100644 sites-available/immich create mode 100644 sites-available/mealie create mode 100644 sites-available/paperless create mode 100644 sites-available/plex create mode 100644 sites-available/pocketbase create mode 100644 sites-available/pocketbase-proxy create mode 100644 sites-available/qbittorrent create mode 100644 sites-available/shopproquote create mode 100644 sites-available/vaultwarden create mode 100644 sites-enabled/airrepairteam create mode 120000 sites-enabled/audiobookshelf create mode 120000 sites-enabled/chrome-vnc create mode 100644 sites-enabled/gitea create mode 100644 sites-enabled/hermes-dashboard create mode 120000 sites-enabled/hermes-webui create mode 100644 sites-enabled/homeassistant create mode 120000 sites-enabled/immich create mode 120000 sites-enabled/mealie create mode 120000 sites-enabled/paperless create mode 120000 sites-enabled/plex create mode 120000 sites-enabled/pocketbase create mode 120000 sites-enabled/pocketbase-proxy create mode 120000 sites-enabled/qbittorrent create mode 100644 sites-enabled/shopproquote create mode 120000 sites-enabled/vaultwarden create mode 100644 snippets/deepseek-key.conf create mode 100644 snippets/fastcgi-php.conf create mode 100644 snippets/snakeoil.conf create mode 100644 snippets/spq-deepseek.conf create mode 100644 snippets/spq-security.conf create mode 100644 uwsgi_params create mode 100644 win-utf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f3cd0ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Nginx log files +*.log +access.log +error.log + +# Backup files +*.bak-* + +# Generated/temporary files +*.swp +*.swo +*~ +.DS_Store +Thumbs.db diff --git a/fastcgi.conf b/fastcgi.conf new file mode 100644 index 0000000..d53a628 --- /dev/null +++ b/fastcgi.conf @@ -0,0 +1,27 @@ + +fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param REQUEST_SCHEME $scheme; +fastcgi_param HTTPS $https if_not_empty; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param REMOTE_USER $remote_user; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; diff --git a/fastcgi_params b/fastcgi_params new file mode 100644 index 0000000..96a0bc5 --- /dev/null +++ b/fastcgi_params @@ -0,0 +1,28 @@ + +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param REQUEST_SCHEME $scheme; +fastcgi_param HTTPS $https if_not_empty; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param REMOTE_USER $remote_user; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; + +fastcgi_param HTTP_HOST $host$is_request_port$request_port; diff --git a/koi-utf b/koi-utf new file mode 100644 index 0000000..e7974ff --- /dev/null +++ b/koi-utf @@ -0,0 +1,109 @@ + +# This map is not a full koi8-r <> utf8 map: it does not contain +# box-drawing and some other characters. Besides this map contains +# several koi8-u and Byelorussian letters which are not in koi8-r. +# If you need a full and standard map, use contrib/unicode2nginx/koi-utf +# map instead. + +charset_map koi8-r utf-8 { + + 80 E282AC ; # euro + + 95 E280A2 ; # bullet + + 9A C2A0 ; #   + + 9E C2B7 ; # · + + A3 D191 ; # small yo + A4 D194 ; # small Ukrainian ye + + A6 D196 ; # small Ukrainian i + A7 D197 ; # small Ukrainian yi + + AD D291 ; # small Ukrainian soft g + AE D19E ; # small Byelorussian short u + + B0 C2B0 ; # ° + + B3 D081 ; # capital YO + B4 D084 ; # capital Ukrainian YE + + B6 D086 ; # capital Ukrainian I + B7 D087 ; # capital Ukrainian YI + + B9 E28496 ; # numero sign + + BD D290 ; # capital Ukrainian soft G + BE D18E ; # capital Byelorussian short U + + BF C2A9 ; # (C) + + C0 D18E ; # small yu + C1 D0B0 ; # small a + C2 D0B1 ; # small b + C3 D186 ; # small ts + C4 D0B4 ; # small d + C5 D0B5 ; # small ye + C6 D184 ; # small f + C7 D0B3 ; # small g + C8 D185 ; # small kh + C9 D0B8 ; # small i + CA D0B9 ; # small j + CB D0BA ; # small k + CC D0BB ; # small l + CD D0BC ; # small m + CE D0BD ; # small n + CF D0BE ; # small o + + D0 D0BF ; # small p + D1 D18F ; # small ya + D2 D180 ; # small r + D3 D181 ; # small s + D4 D182 ; # small t + D5 D183 ; # small u + D6 D0B6 ; # small zh + D7 D0B2 ; # small v + D8 D18C ; # small soft sign + D9 D18B ; # small y + DA D0B7 ; # small z + DB D188 ; # small sh + DC D18D ; # small e + DD D189 ; # small shch + DE D187 ; # small ch + DF D18A ; # small hard sign + + E0 D0AE ; # capital YU + E1 D090 ; # capital A + E2 D091 ; # capital B + E3 D0A6 ; # capital TS + E4 D094 ; # capital D + E5 D095 ; # capital YE + E6 D0A4 ; # capital F + E7 D093 ; # capital G + E8 D0A5 ; # capital KH + E9 D098 ; # capital I + EA D099 ; # capital J + EB D09A ; # capital K + EC D09B ; # capital L + ED D09C ; # capital M + EE D09D ; # capital N + EF D09E ; # capital O + + F0 D09F ; # capital P + F1 D0AF ; # capital YA + F2 D0A0 ; # capital R + F3 D0A1 ; # capital S + F4 D0A2 ; # capital T + F5 D0A3 ; # capital U + F6 D096 ; # capital ZH + F7 D092 ; # capital V + F8 D0AC ; # capital soft sign + F9 D0AB ; # capital Y + FA D097 ; # capital Z + FB D0A8 ; # capital SH + FC D0AD ; # capital E + FD D0A9 ; # capital SHCH + FE D0A7 ; # capital CH + FF D0AA ; # capital hard sign +} diff --git a/koi-win b/koi-win new file mode 100644 index 0000000..72afabe --- /dev/null +++ b/koi-win @@ -0,0 +1,103 @@ + +charset_map koi8-r windows-1251 { + + 80 88 ; # euro + + 95 95 ; # bullet + + 9A A0 ; #   + + 9E B7 ; # · + + A3 B8 ; # small yo + A4 BA ; # small Ukrainian ye + + A6 B3 ; # small Ukrainian i + A7 BF ; # small Ukrainian yi + + AD B4 ; # small Ukrainian soft g + AE A2 ; # small Byelorussian short u + + B0 B0 ; # ° + + B3 A8 ; # capital YO + B4 AA ; # capital Ukrainian YE + + B6 B2 ; # capital Ukrainian I + B7 AF ; # capital Ukrainian YI + + B9 B9 ; # numero sign + + BD A5 ; # capital Ukrainian soft G + BE A1 ; # capital Byelorussian short U + + BF A9 ; # (C) + + C0 FE ; # small yu + C1 E0 ; # small a + C2 E1 ; # small b + C3 F6 ; # small ts + C4 E4 ; # small d + C5 E5 ; # small ye + C6 F4 ; # small f + C7 E3 ; # small g + C8 F5 ; # small kh + C9 E8 ; # small i + CA E9 ; # small j + CB EA ; # small k + CC EB ; # small l + CD EC ; # small m + CE ED ; # small n + CF EE ; # small o + + D0 EF ; # small p + D1 FF ; # small ya + D2 F0 ; # small r + D3 F1 ; # small s + D4 F2 ; # small t + D5 F3 ; # small u + D6 E6 ; # small zh + D7 E2 ; # small v + D8 FC ; # small soft sign + D9 FB ; # small y + DA E7 ; # small z + DB F8 ; # small sh + DC FD ; # small e + DD F9 ; # small shch + DE F7 ; # small ch + DF FA ; # small hard sign + + E0 DE ; # capital YU + E1 C0 ; # capital A + E2 C1 ; # capital B + E3 D6 ; # capital TS + E4 C4 ; # capital D + E5 C5 ; # capital YE + E6 D4 ; # capital F + E7 C3 ; # capital G + E8 D5 ; # capital KH + E9 C8 ; # capital I + EA C9 ; # capital J + EB CA ; # capital K + EC CB ; # capital L + ED CC ; # capital M + EE CD ; # capital N + EF CE ; # capital O + + F0 CF ; # capital P + F1 DF ; # capital YA + F2 D0 ; # capital R + F3 D1 ; # capital S + F4 D2 ; # capital T + F5 D3 ; # capital U + F6 C6 ; # capital ZH + F7 C2 ; # capital V + F8 DC ; # capital soft sign + F9 DB ; # capital Y + FA C7 ; # capital Z + FB D8 ; # capital SH + FC DD ; # capital E + FD D9 ; # capital SHCH + FE D7 ; # capital CH + FF DA ; # capital hard sign +} diff --git a/mime.types b/mime.types new file mode 100644 index 0000000..cf968c0 --- /dev/null +++ b/mime.types @@ -0,0 +1,101 @@ +types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/avif avif; + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + + font/woff woff; + font/woff2 woff2; + + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.oasis.opendocument.graphics odg; + application/vnd.oasis.opendocument.presentation odp; + application/vnd.oasis.opendocument.spreadsheet ods; + application/vnd.oasis.opendocument.text odt; + application/vnd.openxmlformats-officedocument.presentationml.presentation + pptx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + xlsx; + application/vnd.openxmlformats-officedocument.wordprocessingml.document + docx; + application/vnd.wap.wmlc wmlc; + application/wasm wasm; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xslt+xml xsl xslt; + application/xspf+xml xspf; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/ogg ogv; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-matroska mkv; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..991a07e --- /dev/null +++ b/nginx.conf @@ -0,0 +1,99 @@ +user www-data; +worker_processes auto; +worker_cpu_affinity auto; +pid /run/nginx.pid; +error_log /var/log/nginx/error.log; +include /etc/nginx/modules-enabled/*.conf; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + # SPQ structured access log (JSON) + log_format json_combined escape=json '{ "time":"$time_iso8601", "remote":"$remote_addr", "method":"$request_method", "uri":"$uri", "status":$status, "bytes":$body_bytes_sent, "rt":$request_time }'; + # SPQ DeepSeek AI rate limit zone + limit_req_zone $binary_remote_addr zone=spq_ai:10m rate=20r/m; + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + ## + # Basic Settings + ## + + sendfile on; + tcp_nopush on; + types_hash_max_size 2048; + server_tokens off; # Recommended practice is to turn this off + + # server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + + # ES modules (.mjs) need text/javascript MIME type — browsers refuse + # application/octet-stream for dynamic imports. + types { + application/javascript mjs; + } + + default_type application/octet-stream; + + ## + # SSL Settings + ## + + ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3 (POODLE), TLS 1.0, 1.1 + ssl_prefer_server_ciphers off; # Don't force server cipher order. + + ## + # Logging Settings + ## + + access_log /var/log/nginx/access.log; + + ## + # Gzip Settings + ## + + gzip on; + + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + ## + # Virtual Host Configs + ## + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} + + +#mail { +# # See sample authentication script at: +# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript +# +# # auth_http localhost/auth.php; +# # pop3_capabilities "TOP" "USER"; +# # imap_capabilities "IMAP4rev1" "UIDPLUS"; +# +# server { +# listen localhost:110; +# protocol pop3; +# proxy on; +# } +# +# server { +# listen localhost:143; +# protocol imap; +# proxy on; +# } +#} diff --git a/proxy_params b/proxy_params new file mode 100644 index 0000000..0d2f879 --- /dev/null +++ b/proxy_params @@ -0,0 +1,4 @@ +proxy_set_header Host $host$is_request_port$request_port; +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; diff --git a/scgi_params b/scgi_params new file mode 100644 index 0000000..c815edb --- /dev/null +++ b/scgi_params @@ -0,0 +1,19 @@ + +scgi_param REQUEST_METHOD $request_method; +scgi_param REQUEST_URI $request_uri; +scgi_param QUERY_STRING $query_string; +scgi_param CONTENT_TYPE $content_type; + +scgi_param DOCUMENT_URI $document_uri; +scgi_param DOCUMENT_ROOT $document_root; +scgi_param SCGI 1; +scgi_param SERVER_PROTOCOL $server_protocol; +scgi_param REQUEST_SCHEME $scheme; +scgi_param HTTPS $https if_not_empty; + +scgi_param REMOTE_ADDR $remote_addr; +scgi_param REMOTE_PORT $remote_port; +scgi_param SERVER_PORT $server_port; +scgi_param SERVER_NAME $server_name; + +scgi_param HTTP_HOST $host$is_request_port$request_port; diff --git a/sites-available/audiobookshelf b/sites-available/audiobookshelf new file mode 100644 index 0000000..082a16e --- /dev/null +++ b/sites-available/audiobookshelf @@ -0,0 +1,30 @@ +server { + listen 3443 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 500M; + + location / { + proxy_pass http://127.0.0.1:13378; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + 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_read_timeout 86400; + } +} + +# Redirect HTTP → HTTPS on same port (optional) +server { + listen 80; + server_name grajmedia.duckdns.org; + return 301 https://$host:3443$request_uri; +} diff --git a/sites-available/chrome-vnc b/sites-available/chrome-vnc new file mode 100644 index 0000000..68abac5 --- /dev/null +++ b/sites-available/chrome-vnc @@ -0,0 +1,34 @@ +server { + listen 3446 ssl; + server_name grajmedia.duckdns.org browser.graj-media.com; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 100M; + + location / { + proxy_pass https://127.0.0.1:6901; + proxy_http_version 1.1; + proxy_ssl_verify off; + 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 Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_read_timeout 86400; + proxy_buffering off; + proxy_hide_header Cross-Origin-Embedder-Policy; + proxy_hide_header Cross-Origin-Opener-Policy; + + # Security headers (for LAN/Tailscale access) + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), midi=(), sync-xhr=(), clipboard-read=(), clipboard-write=()" always; + } +} diff --git a/sites-available/default b/sites-available/default new file mode 100644 index 0000000..c5af914 --- /dev/null +++ b/sites-available/default @@ -0,0 +1,91 @@ +## +# You should look at the following URL's in order to grasp a solid understanding +# of Nginx configuration files in order to fully unleash the power of Nginx. +# https://www.nginx.com/resources/wiki/start/ +# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ +# https://wiki.debian.org/Nginx/DirectoryStructure +# +# In most cases, administrators will remove this file from sites-enabled/ and +# leave it as reference inside of sites-available where it will continue to be +# updated by the nginx packaging team. +# +# This file will automatically load configuration files provided by other +# applications, such as Drupal or Wordpress. These applications will be made +# available underneath a path with that package name, such as /drupal8. +# +# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. +## + +# Default server configuration +# +server { + listen 80 default_server; + listen [::]:80 default_server; + + # SSL configuration + # + # listen 443 ssl default_server; + # listen [::]:443 ssl default_server; + # + # Note: You should disable gzip for SSL traffic. + # See: https://bugs.debian.org/773332 + # + # Read up on ssl_ciphers to ensure a secure configuration. + # See: https://bugs.debian.org/765782 + # + # Self signed certs generated by the ssl-cert package + # Don't use them in a production server! + # + # include snippets/snakeoil.conf; + + root /var/www/html; + + # Add index.php to the list if you are using PHP + index index.html index.htm index.nginx-debian.html; + + server_name _; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } + + # pass PHP scripts to FastCGI server + # + #location ~ \.php$ { + # include snippets/fastcgi-php.conf; + # + # # With php-fpm (or other unix sockets): + # fastcgi_pass unix:/run/php/php7.4-fpm.sock; + # # With php-cgi (or other tcp sockets): + # fastcgi_pass 127.0.0.1:9000; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} +} + + +# Virtual Host configuration for example.com +# +# You can move that to a different file under sites-available/ and symlink that +# to sites-enabled/ to enable it. +# +#server { +# listen 80; +# listen [::]:80; +# +# server_name example.com; +# +# root /var/www/example.com; +# index index.html; +# +# location / { +# try_files $uri $uri/ =404; +# } +#} diff --git a/sites-available/hermes-webui b/sites-available/hermes-webui new file mode 100644 index 0000000..87d3371 --- /dev/null +++ b/sites-available/hermes-webui @@ -0,0 +1,23 @@ +# Hermes Web UI - SSL proxy +server { + listen 3448 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + + location / { + proxy_pass http://127.0.0.1:8787; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + 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_read_timeout 86400; + } + + # DeepSeek AI proxy — token validation + key injection (shared with SPQ) + include /etc/nginx/snippets/spq-deepseek.conf; +} diff --git a/sites-available/homeassistant b/sites-available/homeassistant new file mode 100644 index 0000000..cb9855f --- /dev/null +++ b/sites-available/homeassistant @@ -0,0 +1,22 @@ +server { + listen 3450 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + proxy_buffering off; + + location / { + proxy_pass http://127.0.0.1:8123; + proxy_http_version 1.1; + 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 Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } +} diff --git a/sites-available/immich b/sites-available/immich new file mode 100644 index 0000000..b97d2b9 --- /dev/null +++ b/sites-available/immich @@ -0,0 +1,25 @@ +server { + listen 3444 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 500M; + + location / { + proxy_pass http://127.0.0.1:2283; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + 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_read_timeout 86400; + proxy_buffering off; + proxy_request_buffering off; + } +} diff --git a/sites-available/mealie b/sites-available/mealie new file mode 100644 index 0000000..3effbbb --- /dev/null +++ b/sites-available/mealie @@ -0,0 +1,23 @@ +server { + listen 3449 ssl; + server_name grajmedia.duckdns.org mealie.graj-media.com; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 50M; + + location / { + proxy_pass http://127.0.0.1:9925; + proxy_http_version 1.1; + 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 Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 86400; + } +} diff --git a/sites-available/paperless b/sites-available/paperless new file mode 100644 index 0000000..862ce7c --- /dev/null +++ b/sites-available/paperless @@ -0,0 +1,23 @@ +server { + listen 3446 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 500M; + + location / { + proxy_pass http://127.0.0.1:8010; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + 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_read_timeout 86400; + } +} diff --git a/sites-available/plex b/sites-available/plex new file mode 100644 index 0000000..a3a4439 --- /dev/null +++ b/sites-available/plex @@ -0,0 +1,25 @@ +server { + listen 3447 ssl; + server_name grajmedia.duckdns.org plex.graj-media.com; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 0; + proxy_request_buffering off; + + location / { + proxy_pass http://127.0.0.1:32400; + proxy_http_version 1.1; + 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 Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 86400; + proxy_buffering off; + } +} diff --git a/sites-available/pocketbase b/sites-available/pocketbase new file mode 100644 index 0000000..7380152 --- /dev/null +++ b/sites-available/pocketbase @@ -0,0 +1,58 @@ +server { + listen 3447 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + # ShopProQuote static files + root /mnt/seagate8tb/Websites/ShopProQuote; + index index.html; + + # PocketBase API reverse proxy + location /api/ { + proxy_pass http://127.0.0.1:8091; + proxy_http_version 1.1; + 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 Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 86400; + } + + # PocketBase admin UI + location /_/ { + proxy_pass http://127.0.0.1:8091; + proxy_http_version 1.1; + 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; + } + + # Local LLM proxy (llama-server for appointment OCR parsing) + location /llm/ { + proxy_pass http://127.0.0.1:8081/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_read_timeout 120s; + } + + # SPA fallback + location / { + try_files $uri $uri/ /index.html; + } + + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { + expires 1h; + add_header Cache-Control "public, must-revalidate"; + } + + client_max_body_size 50m; +} + diff --git a/sites-available/pocketbase-proxy b/sites-available/pocketbase-proxy new file mode 100644 index 0000000..149d83c --- /dev/null +++ b/sites-available/pocketbase-proxy @@ -0,0 +1,18 @@ +server { + listen 3452 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + location / { + proxy_pass http://127.0.0.1:8091; + proxy_http_version 1.1; + 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; + } +} diff --git a/sites-available/qbittorrent b/sites-available/qbittorrent new file mode 100644 index 0000000..67ac898 --- /dev/null +++ b/sites-available/qbittorrent @@ -0,0 +1,17 @@ +server { + listen 8093; + server_name _; + + location / { + proxy_pass http://127.0.0.1:11893; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host 192.168.50.98; + proxy_set_header Origin "http://192.168.50.98"; + 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_read_timeout 86400; + } +} diff --git a/sites-available/shopproquote b/sites-available/shopproquote new file mode 100644 index 0000000..50c61e8 --- /dev/null +++ b/sites-available/shopproquote @@ -0,0 +1,52 @@ +server { + listen 3448 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + # ShopProQuote static files + root /mnt/seagate8tb/Websites/ShopProQuote; + index index.html; + + # PocketBase API reverse proxy (same origin = no CORS needed) + location /api/ { + proxy_pass http://127.0.0.1:8091; + proxy_http_version 1.1; + 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 Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 86400; + } + + # PocketBase admin UI + location /_/ { + proxy_pass http://127.0.0.1:8091; + proxy_http_version 1.1; + 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; + } + + # SPA fallback: all other paths → index.html + location / { + try_files $uri $uri/ /index.html; + } + + # Static file caching + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { + expires 1h; + add_header Cache-Control "public, must-revalidate"; + } + + client_max_body_size 50m; + + # DeepSeek AI proxy — token validation + key injection + include /etc/nginx/snippets/spq-deepseek.conf; +} diff --git a/sites-available/vaultwarden b/sites-available/vaultwarden new file mode 100644 index 0000000..b745f58 --- /dev/null +++ b/sites-available/vaultwarden @@ -0,0 +1,35 @@ +server { + listen 3446 ssl; + server_name grajmedia.duckdns.org vault.graj-media.com; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 128M; + + location / { + proxy_pass http://127.0.0.1:8812; + proxy_http_version 1.1; + 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; + } + + location /notifications/hub { + proxy_pass http://127.0.0.1:8812; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + location /notifications/hub/negotiate { + proxy_pass http://127.0.0.1:8812; + proxy_http_version 1.1; + proxy_set_header Host $host; + } +} diff --git a/sites-enabled/airrepairteam b/sites-enabled/airrepairteam new file mode 100644 index 0000000..a192c20 --- /dev/null +++ b/sites-enabled/airrepairteam @@ -0,0 +1,23 @@ +server { + listen 3451 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + root /mnt/seagate8tb/Websites/AirRepairTeam; + index index.html; + + # Clean URLs — /hvac serves /hvac/index.html + location / { + try_files $uri $uri/ $uri/index.html =404; + } + + # Cache static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { + expires 1h; + add_header Cache-Control "public, must-revalidate"; + } +} diff --git a/sites-enabled/audiobookshelf b/sites-enabled/audiobookshelf new file mode 120000 index 0000000..15ddb1b --- /dev/null +++ b/sites-enabled/audiobookshelf @@ -0,0 +1 @@ +/etc/nginx/sites-available/audiobookshelf \ No newline at end of file diff --git a/sites-enabled/chrome-vnc b/sites-enabled/chrome-vnc new file mode 120000 index 0000000..fd946ff --- /dev/null +++ b/sites-enabled/chrome-vnc @@ -0,0 +1 @@ +/etc/nginx/sites-available/chrome-vnc \ No newline at end of file diff --git a/sites-enabled/gitea b/sites-enabled/gitea new file mode 100644 index 0000000..7fb5b2e --- /dev/null +++ b/sites-enabled/gitea @@ -0,0 +1,23 @@ +server { + listen 443 ssl; + server_name gitea.graj-media.com; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 512M; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + 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; + } +} diff --git a/sites-enabled/hermes-dashboard b/sites-enabled/hermes-dashboard new file mode 100644 index 0000000..59b27c8 --- /dev/null +++ b/sites-enabled/hermes-dashboard @@ -0,0 +1,18 @@ +server { + listen 3445 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + location / { + proxy_pass http://127.0.0.1:8788; + proxy_http_version 1.1; + 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; + } +} diff --git a/sites-enabled/hermes-webui b/sites-enabled/hermes-webui new file mode 120000 index 0000000..799335a --- /dev/null +++ b/sites-enabled/hermes-webui @@ -0,0 +1 @@ +/etc/nginx/sites-available/hermes-webui \ No newline at end of file diff --git a/sites-enabled/homeassistant b/sites-enabled/homeassistant new file mode 100644 index 0000000..cb9855f --- /dev/null +++ b/sites-enabled/homeassistant @@ -0,0 +1,22 @@ +server { + listen 3450 ssl; + server_name grajmedia.duckdns.org; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + proxy_buffering off; + + location / { + proxy_pass http://127.0.0.1:8123; + proxy_http_version 1.1; + 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 Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } +} diff --git a/sites-enabled/immich b/sites-enabled/immich new file mode 120000 index 0000000..24b3d33 --- /dev/null +++ b/sites-enabled/immich @@ -0,0 +1 @@ +/etc/nginx/sites-available/immich \ No newline at end of file diff --git a/sites-enabled/mealie b/sites-enabled/mealie new file mode 120000 index 0000000..bf372a5 --- /dev/null +++ b/sites-enabled/mealie @@ -0,0 +1 @@ +/etc/nginx/sites-available/mealie \ No newline at end of file diff --git a/sites-enabled/paperless b/sites-enabled/paperless new file mode 120000 index 0000000..4df3833 --- /dev/null +++ b/sites-enabled/paperless @@ -0,0 +1 @@ +/etc/nginx/sites-available/paperless \ No newline at end of file diff --git a/sites-enabled/plex b/sites-enabled/plex new file mode 120000 index 0000000..1d1454a --- /dev/null +++ b/sites-enabled/plex @@ -0,0 +1 @@ +/etc/nginx/sites-available/plex \ No newline at end of file diff --git a/sites-enabled/pocketbase b/sites-enabled/pocketbase new file mode 120000 index 0000000..bd28d58 --- /dev/null +++ b/sites-enabled/pocketbase @@ -0,0 +1 @@ +/etc/nginx/sites-available/pocketbase \ No newline at end of file diff --git a/sites-enabled/pocketbase-proxy b/sites-enabled/pocketbase-proxy new file mode 120000 index 0000000..4244f4e --- /dev/null +++ b/sites-enabled/pocketbase-proxy @@ -0,0 +1 @@ +/etc/nginx/sites-available/pocketbase-proxy \ No newline at end of file diff --git a/sites-enabled/qbittorrent b/sites-enabled/qbittorrent new file mode 120000 index 0000000..da28f4f --- /dev/null +++ b/sites-enabled/qbittorrent @@ -0,0 +1 @@ +/etc/nginx/sites-available/qbittorrent \ No newline at end of file diff --git a/sites-enabled/shopproquote b/sites-enabled/shopproquote new file mode 100644 index 0000000..9968803 --- /dev/null +++ b/sites-enabled/shopproquote @@ -0,0 +1,91 @@ +server { + access_log /var/log/spq/spq.access.log json_combined; + include /etc/nginx/snippets/spq-security.conf; + listen 443 ssl; + client_max_body_size 50m; + server_name grajmedia.duckdns.org graj-media.com shopproquote.graj-media.com; + + ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + root /mnt/seagate8tb/Websites/ShopProQuote.backup-20260626-2058/spq-v2/dist; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /pb/ { + proxy_pass http://127.0.0.1:8091/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + 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_read_timeout 86400; + proxy_buffering off; + } + + location /api/ { + proxy_pass http://127.0.0.1:8091/api/; + proxy_http_version 1.1; + 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; + } + + location /llm/ { + proxy_pass http://127.0.0.1:11434/; + proxy_http_version 1.1; + proxy_set_header Host "localhost"; + proxy_set_header Origin "http://localhost"; + proxy_set_header X-Real-IP $remote_addr; + proxy_buffering off; + proxy_read_timeout 120s; + } + + location /vision/ { + proxy_pass http://127.0.0.1:11434/; + proxy_http_version 1.1; + proxy_set_header Host "localhost"; + proxy_set_header Origin "http://localhost"; + proxy_set_header X-Real-IP $remote_addr; + proxy_buffering off; + proxy_read_timeout 300s; + } + + # DeepSeek AI proxy — token validation + key injection + include /etc/nginx/snippets/spq-deepseek.conf; + + # GlitchTip error tracking + location /glitchtip/ { + rewrite ^/glitchtip/[0-9]+/(api/.*)$ /$1 break; + rewrite ^/glitchtip/[0-9]+/(store/.*)$ /api/1/$1 break; + rewrite ^/glitchtip/(.*)$ /$1 break; + proxy_pass http://127.0.0.1:8001; + proxy_http_version 1.1; + 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_buffering off; + } + + # GlitchTip bare project-ID path (Sentry DSN compat) + location ~ ^/([0-9]+)/(api|store)/(.*)$ { + rewrite ^/([0-9]+)/api/(.*)$ /api/$1/$2 break; + rewrite ^/([0-9]+)/store/(.*)$ /api/$1/$2 break; + proxy_pass http://127.0.0.1:8001; + proxy_http_version 1.1; + 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_buffering off; + } +} diff --git a/sites-enabled/vaultwarden b/sites-enabled/vaultwarden new file mode 120000 index 0000000..c832619 --- /dev/null +++ b/sites-enabled/vaultwarden @@ -0,0 +1 @@ +/etc/nginx/sites-available/vaultwarden \ No newline at end of file diff --git a/snippets/deepseek-key.conf b/snippets/deepseek-key.conf new file mode 100644 index 0000000..cf99143 --- /dev/null +++ b/snippets/deepseek-key.conf @@ -0,0 +1 @@ +set $deepseek_key "sk-4e7a3351dd7e4929b34988877a4336d8"; diff --git a/snippets/fastcgi-php.conf b/snippets/fastcgi-php.conf new file mode 100644 index 0000000..467a9e7 --- /dev/null +++ b/snippets/fastcgi-php.conf @@ -0,0 +1,13 @@ +# regex to split $uri to $fastcgi_script_name and $fastcgi_path +fastcgi_split_path_info ^(.+?\.php)(/.*)$; + +# Check that the PHP script exists before passing it +try_files $fastcgi_script_name =404; + +# Bypass the fact that try_files resets $fastcgi_path_info +# see: http://trac.nginx.org/nginx/ticket/321 +set $path_info $fastcgi_path_info; +fastcgi_param PATH_INFO $path_info; + +fastcgi_index index.php; +include fastcgi.conf; diff --git a/snippets/snakeoil.conf b/snippets/snakeoil.conf new file mode 100644 index 0000000..ad26c3e --- /dev/null +++ b/snippets/snakeoil.conf @@ -0,0 +1,5 @@ +# Self signed certificates generated by the ssl-cert package +# Don't use them in a production server! + +ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; +ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; diff --git a/snippets/spq-deepseek.conf b/snippets/spq-deepseek.conf new file mode 100644 index 0000000..71f92f4 --- /dev/null +++ b/snippets/spq-deepseek.conf @@ -0,0 +1,32 @@ + +location /deepseek/ { + limit_req zone=spq_ai burst=5 nodelay; + + # 1) Validate the PB token. 401 → block; 200 → continue. + auth_request /_spq_validate; + auth_request_set $spq_auth_status $upstream_status; + + # 2) Strip the client's Authorization header. + proxy_set_header Authorization ""; + + # 3) Inject the DeepSeek key. + include /etc/nginx/snippets/deepseek-key.conf; + proxy_set_header Authorization "Bearer $deepseek_key"; + + # 4) Rewrite path: /deepseek/v1/chat/completions → /v1/chat/completions + rewrite ^/deepseek/(.*)$ /$1 break; + + proxy_pass https://api.deepseek.com; + proxy_ssl_server_name on; + proxy_set_header Host api.deepseek.com; + proxy_set_header X-Real-IP $remote_addr; + proxy_buffering off; # streaming responses +} + +location = /_spq_validate { + internal; + proxy_pass http://127.0.0.1:8092/; + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header Authorization $http_authorization; +} diff --git a/snippets/spq-security.conf b/snippets/spq-security.conf new file mode 100644 index 0000000..ac26bfb --- /dev/null +++ b/snippets/spq-security.conf @@ -0,0 +1,6 @@ +# SPQ frontend security headers. Include inside the server { } block. +add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" always; +add_header X-Content-Type-Options "nosniff" always; +add_header X-Frame-Options "DENY" always; +add_header Referrer-Policy "no-referrer" always; +add_header Permissions-Policy "microphone=(), geolocation=(), interest-cohort=()" always; diff --git a/uwsgi_params b/uwsgi_params new file mode 100644 index 0000000..b4f5573 --- /dev/null +++ b/uwsgi_params @@ -0,0 +1,19 @@ + +uwsgi_param QUERY_STRING $query_string; +uwsgi_param REQUEST_METHOD $request_method; +uwsgi_param CONTENT_TYPE $content_type; +uwsgi_param CONTENT_LENGTH $content_length; + +uwsgi_param REQUEST_URI $request_uri; +uwsgi_param PATH_INFO $document_uri; +uwsgi_param DOCUMENT_ROOT $document_root; +uwsgi_param SERVER_PROTOCOL $server_protocol; +uwsgi_param REQUEST_SCHEME $scheme; +uwsgi_param HTTPS $https if_not_empty; + +uwsgi_param REMOTE_ADDR $remote_addr; +uwsgi_param REMOTE_PORT $remote_port; +uwsgi_param SERVER_PORT $server_port; +uwsgi_param SERVER_NAME $server_name; + +uwsgi_param HTTP_HOST $host$is_request_port$request_port; diff --git a/win-utf b/win-utf new file mode 100644 index 0000000..774fd9f --- /dev/null +++ b/win-utf @@ -0,0 +1,125 @@ +# This map is not a full windows-1251 <> utf8 map: it does not +# contain Serbian and Macedonian letters. If you need a full map, +# use contrib/unicode2nginx/win-utf map instead. + +charset_map windows-1251 utf-8 { + + 82 E2809A; # single low-9 quotation mark + + 84 E2809E; # double low-9 quotation mark + 85 E280A6; # ellipsis + 86 E280A0; # dagger + 87 E280A1; # double dagger + 88 E282AC; # euro + 89 E280B0; # per mille + + 91 E28098; # left single quotation mark + 92 E28099; # right single quotation mark + 93 E2809C; # left double quotation mark + 94 E2809D; # right double quotation mark + 95 E280A2; # bullet + 96 E28093; # en dash + 97 E28094; # em dash + + 99 E284A2; # trade mark sign + + A0 C2A0; #   + A1 D18E; # capital Byelorussian short U + A2 D19E; # small Byelorussian short u + + A4 C2A4; # currency sign + A5 D290; # capital Ukrainian soft G + A6 C2A6; # borken bar + A7 C2A7; # section sign + A8 D081; # capital YO + A9 C2A9; # (C) + AA D084; # capital Ukrainian YE + AB C2AB; # left-pointing double angle quotation mark + AC C2AC; # not sign + AD C2AD; # soft hypen + AE C2AE; # (R) + AF D087; # capital Ukrainian YI + + B0 C2B0; # ° + B1 C2B1; # plus-minus sign + B2 D086; # capital Ukrainian I + B3 D196; # small Ukrainian i + B4 D291; # small Ukrainian soft g + B5 C2B5; # micro sign + B6 C2B6; # pilcrow sign + B7 C2B7; # · + B8 D191; # small yo + B9 E28496; # numero sign + BA D194; # small Ukrainian ye + BB C2BB; # right-pointing double angle quotation mark + + BF D197; # small Ukrainian yi + + C0 D090; # capital A + C1 D091; # capital B + C2 D092; # capital V + C3 D093; # capital G + C4 D094; # capital D + C5 D095; # capital YE + C6 D096; # capital ZH + C7 D097; # capital Z + C8 D098; # capital I + C9 D099; # capital J + CA D09A; # capital K + CB D09B; # capital L + CC D09C; # capital M + CD D09D; # capital N + CE D09E; # capital O + CF D09F; # capital P + + D0 D0A0; # capital R + D1 D0A1; # capital S + D2 D0A2; # capital T + D3 D0A3; # capital U + D4 D0A4; # capital F + D5 D0A5; # capital KH + D6 D0A6; # capital TS + D7 D0A7; # capital CH + D8 D0A8; # capital SH + D9 D0A9; # capital SHCH + DA D0AA; # capital hard sign + DB D0AB; # capital Y + DC D0AC; # capital soft sign + DD D0AD; # capital E + DE D0AE; # capital YU + DF D0AF; # capital YA + + E0 D0B0; # small a + E1 D0B1; # small b + E2 D0B2; # small v + E3 D0B3; # small g + E4 D0B4; # small d + E5 D0B5; # small ye + E6 D0B6; # small zh + E7 D0B7; # small z + E8 D0B8; # small i + E9 D0B9; # small j + EA D0BA; # small k + EB D0BB; # small l + EC D0BC; # small m + ED D0BD; # small n + EE D0BE; # small o + EF D0BF; # small p + + F0 D180; # small r + F1 D181; # small s + F2 D182; # small t + F3 D183; # small u + F4 D184; # small f + F5 D185; # small kh + F6 D186; # small ts + F7 D187; # small ch + F8 D188; # small sh + F9 D189; # small shch + FA D18A; # small hard sign + FB D18B; # small y + FC D18C; # small soft sign + FD D18D; # small e + FE D18E; # small yu + FF D18F; # small ya +}