# netget_app.conf # ----------------------------------------------------------- # # Features implemented here: # - CORS handling (including preflight OPTIONS) # - JWT cookie verification (stateless) using lua-resty-jwt # - Routing for /networks, /deploy and root (/) paths # - Access / error log format closely aligned with existing parser expectations # - Optional proxying to upstream Node microservices (if you keep them) OR # serve static content directly. # # NOTE: To fully "substitute" the Express server, any dynamic logic currently # residing in Express route handlers must be ported to Lua (see lua/*.lua). # This config assumes you'll add lua scripts for business logic. # # Dependencies (install via OS / luarocks): # - openresty (nginx with Lua) # - lua-resty-jwt (for JWT verification) # - lua-resty-cookie (cookie parsing) # - lua-cjson (usually bundled) # - lsqlite3 # ----------------------------------------------------------- # Environment variables note: # The 'env' directive is only allowed in the main (top-level) nginx context, # not inside http/server/location or included conf.d files. # If your Lua code uses os.getenv(...), make sure these are declared in # /usr/local/openresty/nginx/conf/nginx.conf at top-level, for example: # env JWT_SECRET; # env CORS_ALLOWED_ORIGINS; # env NODE_ENV; # env USE_HTTPS; # Shared dicts for caching JWT verifications (optional) lua_shared_dict jwt_cache 10m; # Custom access log format (removed invalid $level variable from error format) log_format netget_access '$remote_addr - - [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"'; # NOTE: error logs use their own internal format; custom log_format for errors removed. # Upstream definitions (if you keep Node microservices; adjust or remove) # upstream networks_service { # server 127.0.0.1:4001; # Example port for networks # keepalive 32; # } # upstream deploy_service { # server 127.0.0.1:4002; # Example port for deploy # keepalive 32; # } # ----------------------------------------------------------- # Server Block # ----------------------------------------------------------- server { listen 80; listen [::]:80; # Change to 443 + SSL directives if using HTTPS termination here server_name local.netget; client_max_body_size 500M; # Match previous Express multer limit $xConfig = $xConfig; # Set by main nginx.conf to point to config dir access_log /usr/local/openresty/nginx/logs/netget_access.log netget_access; error_log /usr/local/openresty/nginx/logs/netget_error.log warn; # Note: handle CORS in each location. Avoid add_header inside server-level if. # ------------------------------------------------------- # Root route: previously localNetgetRoutes # You can serve static files or run Lua logic. # ------------------------------------------------------- location / { # Preflight short-circuit (no add_header inside if; headers set below) if ($request_method = OPTIONS) { return 204; } root ${xConfig}/dist; index index.html; try_files $uri $uri/ /index.html; # If you want Lua processing instead, uncomment: # content_by_lua_file lua/handlers/root.lua; # CORS headers (apply to all responses from this location) add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } # ------------------------------------------------------- # /networks route # ------------------------------------------------------- location /networks { if ($request_method = OPTIONS) { return 204; } # If using an upstream service: # proxy_pass http://networks_service; # proxy_set_header Host $host; # proxy_set_header X-Real-IP $remote_addr; # Or implement logic in Lua directly content_by_lua_file lua/handlers/networks.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } # ------------------------------------------------------- # /deploy route # ------------------------------------------------------- location /deploy { if ($request_method = OPTIONS) { return 204; } # proxy_pass http://deploy_service; # if upstream content_by_lua_file lua/handlers/deploy.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } # ------------------------------------------------------- # Protected route example requiring JWT cookie # ------------------------------------------------------- location /protected { if ($request_method = OPTIONS) { return 204; } access_by_lua_file lua/middleware/jwt_cookie.lua; # validates cookie token content_by_lua_file lua/handlers/protected.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } # ------------------------------------------------------- # Static assets (explicit path) # ------------------------------------------------------- location /media/ { if ($request_method = OPTIONS) { return 204; } root $xConfig/dist; # replicate Express static serving add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; expires 30d; # cache static assets } # ------------------------------------------------------- # Vite hashed asset caching (e.g., /assets/* from dist) # ------------------------------------------------------- location /assets/ { if ($request_method = OPTIONS) { return 204; } root $xConfig/dist; try_files $uri =404; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; add_header 'Cache-Control' 'public, max-age=31536000, immutable'; expires 365d; } # ------------------------------------------------------- # Auth & Session routes (/check-auth, /login, /logout) # ------------------------------------------------------- location /check_auth { if ($request_method = OPTIONS) { return 204; } access_by_lua_file lua/middleware/jwt_cookie.lua; # optional: only sets claims if cookie valid set $auth_action check_auth; content_by_lua_file lua/handlers/auth.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } location /login { if ($request_method = OPTIONS) { return 204; } set $auth_action login; content_by_lua_file lua/handlers/auth.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } location /logout { if ($request_method = OPTIONS) { return 204; } set $auth_action logout; content_by_lua_file lua/handlers/auth.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } # ------------------------------------------------------- # Logs endpoint (/logs?type=access|error|server&limit=&offset=) # ------------------------------------------------------- location /logs { if ($request_method = OPTIONS) { return 204; } content_by_lua_file lua/handlers/logs.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } # ------------------------------------------------------- # Domain management (SQLite backed) # /domains, /domains/:parentDomain/subdomains, /add-domain, /update-domain # ------------------------------------------------------- location /domains { if ($request_method = OPTIONS) { return 204; } set $domain_action list_domains; # GET list content_by_lua_file lua/handlers/domains.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } # Subdomains listing: /domains//subdomains location ~ ^/domains/([^/]+)/subdomains$ { if ($request_method = OPTIONS) { return 204; } set $parent_domain $1; set $domain_action list_subdomains; content_by_lua_file lua/handlers/domains.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } location ~ ^/domains/([^/]+)/target$ { if ($request_method = OPTIONS) { return 204; } set $requested_domain $1; set $domain_action get_domain_target; content_by_lua_file lua/handlers/domains.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } location /add-domain { if ($request_method = OPTIONS) { return 204; } set $domain_action add_domain; content_by_lua_file lua/handlers/domains.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } location /update-domain { if ($request_method = OPTIONS) { return 204; } set $domain_action update_domain; content_by_lua_file lua/handlers/domains.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } location /delete-domain { if ($request_method = OPTIONS) { return 204; } set $domain_action delete_domain; content_by_lua_file lua/handlers/domains.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } # ------------------------------------------------------- # .me kernel endpoints (gateway identity + monad mesh) # Read from materialized runtime snapshots — no auth needed (loopback-only). # ------------------------------------------------------- location /gateway-identity { if ($request_method = OPTIONS) { return 204; } content_by_lua_file lua/handlers/gateway_identity.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type' always; } location /apps { if ($request_method = OPTIONS) { return 204; } content_by_lua_file lua/handlers/local_apps.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type' always; } # ------------------------------------------------------- # Misc endpoints # ------------------------------------------------------- location /healthcheck { if ($request_method = OPTIONS) { return 204; } set $misc_action healthcheck; content_by_lua_file lua/handlers/misc.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } location /ip-info { if ($request_method = OPTIONS) { return 204; } set $misc_action ip_info; content_by_lua_file lua/handlers/misc.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } location /port-info { if ($request_method = OPTIONS) { return 204; } set $misc_action port_info; content_by_lua_file lua/handlers/misc.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } location /test { if ($request_method = OPTIONS) { return 204; } access_by_lua_file lua/middleware/jwt_cookie.lua; # require valid token set $misc_action test_endpoint; content_by_lua_file lua/handlers/misc.lua; add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Max-Age' 86400 always; } # ------------------------------------------------------- # Serve static assets (CSS, JS, images) location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { root $xConfig/dist; # Short cache for development expires 1h; add_header Cache-Control "public, max-age=3600"; add_header Access-Control-Allow-Origin "*"; # Allow CSP for static assets add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: blob: http: https:;"; access_log off; } # Specific favicon handling location = /favicon.ico { root $xConfig/dist; add_header Cache-Control "public, max-age=86400"; add_header Access-Control-Allow-Origin "*"; access_log off; # Return 204 if favicon doesn't exist to prevent 404 errors try_files $uri =204; } }