# FastCGI upstream configuration upstream ginxsom_backend { server unix:/tmp/ginxsom-fcgi.sock; } # Main domains server { if ($host = laantungir.net) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; server_name laantungir.com www.laantungir.com laantungir.net www.laantungir.net laantungir.org www.laantungir.org; root /var/www/html; index index.html index.htm; location / { try_files $uri $uri/ =404; } location /.well-known/acme-challenge/ { root /var/www/certbot; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/html; } } # Main domains HTTPS - using the main certificate server { listen 443 ssl; server_name laantungir.com www.laantungir.com laantungir.net www.laantungir.net laantungir.org www.laantungir.org; ssl_certificate /etc/letsencrypt/live/laantungir.net/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/laantungir.net/privkey.pem; # managed by Certbot root /var/www/html; index index.html index.htm; location / { try_files $uri $uri/ =404; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/html; } } # Blossom subdomains HTTP - redirect to HTTPS (keep for ACME) server { listen 80; server_name blossom.laantungir.com blossom.laantungir.net blossom.laantungir.org; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://$server_name$request_uri; } } # Blossom subdomains HTTPS - ginxsom FastCGI server { listen 443 ssl; server_name blossom.laantungir.com blossom.laantungir.net blossom.laantungir.org; ssl_certificate /etc/letsencrypt/live/git.laantungir.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/git.laantungir.net/privkey.pem; # Security headers add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options DENY always; add_header X-XSS-Protection "1; mode=block" always; # CORS for Blossom protocol add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH" always; add_header Access-Control-Allow-Headers "Authorization, Content-Type, Content-Length, Accept, Origin, User-Agent, DNT, Cache-Control, X-Mx-ReqToken, Keep-Alive, X-Requested-With, If-Modified-Since, *" always; add_header Access-Control-Max-Age 86400 always; # Root directory for blob storage root /var/www/html/blossom; # Maximum upload size client_max_body_size 100M; # OPTIONS preflight handler if ($request_method = OPTIONS) { return 204; } # PUT /upload - File uploads location = /upload { if ($request_method !~ ^(PUT|HEAD)$) { return 405; } fastcgi_pass ginxsom_backend; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; } # GET /list/ - List user blobs location ~ "^/list/([a-f0-9]{64})$" { if ($request_method !~ ^(GET)$) { return 405; } fastcgi_pass ginxsom_backend; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; } # PUT /mirror - Mirror content location = /mirror { if ($request_method !~ ^(PUT)$) { return 405; } fastcgi_pass ginxsom_backend; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; } # PUT /report - Report content location = /report { if ($request_method !~ ^(PUT)$) { return 405; } fastcgi_pass ginxsom_backend; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; } # GET /auth - NIP-42 challenges location = /auth { if ($request_method !~ ^(GET)$) { return 405; } fastcgi_pass ginxsom_backend; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; } # Admin API location /api/ { if ($request_method !~ ^(GET|PUT)$) { return 405; } fastcgi_pass ginxsom_backend; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; } # Blob serving - SHA256 patterns location ~ "^/([a-f0-9]{64})(\.[a-zA-Z0-9]+)?$" { # Handle DELETE via rewrite if ($request_method = DELETE) { rewrite ^/(.*)$ /fcgi-delete/$1 last; } # Route HEAD to FastCGI if ($request_method = HEAD) { rewrite ^/(.*)$ /fcgi-head/$1 last; } # GET requests - serve files directly if ($request_method != GET) { return 405; } try_files /$1.txt /$1.jpg /$1.jpeg /$1.png /$1.webp /$1.gif /$1.pdf /$1.mp4 /$1.mp3 /$1.md =404; # Cache headers add_header Cache-Control "public, max-age=31536000, immutable"; } # Internal FastCGI handlers location ~ "^/fcgi-delete/([a-f0-9]{64}).*$" { internal; fastcgi_pass ginxsom_backend; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; fastcgi_param REQUEST_URI /$1; } location ~ "^/fcgi-head/([a-f0-9]{64}).*$" { internal; fastcgi_pass ginxsom_backend; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; fastcgi_param REQUEST_URI /$1; } # Health check location /health { access_log off; return 200 "OK\n"; add_header Content-Type text/plain; add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH" always; add_header Access-Control-Allow-Headers "Authorization, Content-Type, Content-Length, Accept, Origin, User-Agent, DNT, Cache-Control, X-Mx-ReqToken, Keep-Alive, X-Requested-With, If-Modified-Since, *" always; add_header Access-Control-Max-Age 86400 always; } # Default location - Server info endpoint location / { return 200 '{\n "server": "ginxsom",\n "version": "1.0.0",\n "description": "Ginxsom Blossom Server",\n "endpoints": {\n "blob_get": "GET /",\n "blob_head": "HEAD /",\n "upload": "PUT /upload",\n "upload_requirements": "HEAD /upload",\n "list": "GET /list/",\n "delete": "DELETE /",\n "mirror": "PUT /mirror",\n "report": "PUT /report",\n "health": "GET /health"\n },\n "supported_buds": [\n "BUD-01",\n "BUD-02",\n "BUD-04",\n "BUD-06",\n "BUD-08",\n "BUD-09"\n ],\n "limits": {\n "max_upload_size": 104857600,\n "supported_mime_types": [\n "image/jpeg",\n "image/png",\n "image/webp",\n "image/gif",\n "video/mp4",\n "video/webm",\n "audio/mpeg",\n "audio/ogg",\n "text/plain",\n "application/pdf"\n ]\n },\n "authentication": {\n "required_for_upload": false,\n "required_for_delete": true,\n "required_for_list": false,\n "nip42_enabled": true\n }\n}'; add_header Content-Type application/json; add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH" always; add_header Access-Control-Allow-Headers "Authorization, Content-Type, Content-Length, Accept, Origin, User-Agent, DNT, Cache-Control, X-Mx-ReqToken, Keep-Alive, X-Requested-With, If-Modified-Since, *" always; add_header Access-Control-Max-Age 86400 always; } } server { listen 80; server_name relay.laantungir.com relay.laantungir.net relay.laantungir.org; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { proxy_pass http://127.0.0.1:8888; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key; proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version; 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_cache_bypass $http_upgrade; proxy_read_timeout 86400s; proxy_send_timeout 86400s; proxy_connect_timeout 60s; proxy_buffering off; proxy_request_buffering off; gzip off; } } # # Relay HTTPS - proxy to c-relay server { listen 443 ssl; server_name relay.laantungir.com relay.laantungir.net relay.laantungir.org; ssl_certificate /etc/letsencrypt/live/blossom.laantungir.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/blossom.laantungir.net/privkey.pem; location / { proxy_pass http://127.0.0.1:8888; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key; proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version; 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_cache_bypass $http_upgrade; proxy_read_timeout 86400s; proxy_send_timeout 86400s; proxy_connect_timeout 60s; proxy_buffering off; proxy_request_buffering off; gzip off; } } # Git subdomains HTTP - redirect to HTTPS server { listen 80; server_name git.laantungir.com git.laantungir.net git.laantungir.org; # Allow larger file uploads for Git releases client_max_body_size 50M; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://$server_name$request_uri; } } # Auth subdomains HTTP - redirect to HTTPS server { listen 80; server_name auth.laantungir.com auth.laantungir.net auth.laantungir.org; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { } } # Git subdomains HTTPS - proxy to gitea server { listen 443 ssl; server_name git.laantungir.com git.laantungir.net git.laantungir.org; # Allow larger file uploads for Git releases client_max_body_size 50M; ssl_certificate /etc/letsencrypt/live/git.laantungir.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/git.laantungir.net/privkey.pem; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_buffering off; proxy_request_buffering off; proxy_read_timeout 86400s; proxy_send_timeout 86400s; proxy_connect_timeout 60s; gzip off; # proxy_set_header Sec-WebSocket-Extensions ; proxy_set_header Host $host; proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key; proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version; 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_cache_bypass $http_upgrade; } } # Auth subdomains HTTPS - proxy to nostr-auth server { listen 443 ssl; server_name auth.laantungir.com auth.laantungir.net auth.laantungir.org; ssl_certificate /etc/letsencrypt/live/git.laantungir.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/git.laantungir.net/privkey.pem; location / { proxy_pass http://localhost:3001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_buffering off; proxy_request_buffering off; proxy_read_timeout 86400s; proxy_send_timeout 86400s; proxy_connect_timeout 60s; gzip off; # proxy_set_header Sec-WebSocket-Extensions ; proxy_set_header Host $host; proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key; proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version; 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_cache_bypass $http_upgrade; } }