listen 443 ssl http2; listen [::]:443 ssl http2; include /etc/nginx/conf.d/include/ssl-settings; include /etc/nginx/conf.d/include/init-optional-variables; # ddos protection: closing slow connections client_body_timeout 1h; client_header_timeout 1h; send_timeout 1h; proxy_connect_timeout 1h; proxy_read_timeout 1h; proxy_send_timeout 1h; # Increase the body buffer size, to ensure the internal POSTs can always # parse the full POST contents into memory. client_body_buffer_size 128k; client_max_body_size 128k; # legacy endpoint rewrite rewrite ^/portals /skynet/portals permanent; rewrite ^/stats /skynet/stats permanent; rewrite ^/skynet/blacklist /skynet/blocklist permanent; location / { include /etc/nginx/conf.d/include/cors; proxy_pass http://website:9000; } location /docs { proxy_pass https://skynetlabs.github.io/skynet-docs; } location /skynet/blocklist { include /etc/nginx/conf.d/include/cors; proxy_cache skynet; proxy_cache_valid any 1m; # cache blocklist for 1 minute proxy_set_header User-Agent: Sia-Agent; proxy_pass http://sia:9980/skynet/blocklist; } location /skynet/portals { include /etc/nginx/conf.d/include/cors; proxy_cache skynet; proxy_cache_valid any 1m; # cache portals for 1 minute proxy_set_header User-Agent: Sia-Agent; proxy_pass http://sia:9980/skynet/portals; } location /skynet/stats { include /etc/nginx/conf.d/include/cors; proxy_cache skynet; proxy_cache_valid any 1m; # cache stats for 1 minute proxy_set_header User-Agent: Sia-Agent; proxy_read_timeout 5m; # extend the read timeout proxy_pass http://sia:9980/skynet/stats; } location /skynet/health { include /etc/nginx/conf.d/include/cors; proxy_cache skynet; proxy_cache_key $request_uri; # use whole request uri (uri + args) as cache key proxy_cache_valid any 1m; # cache responses for 1 minute proxy_set_header User-Agent: Sia-Agent; proxy_read_timeout 5m; # extend the read timeout proxy_pass http://sia:9980; } location /health-check { include /etc/nginx/conf.d/include/cors; access_log off; # do not log traffic to health-check endpoint proxy_pass http://10.10.10.60:3100; # hardcoded ip because health-check waits for nginx } location /hns { # match the request_uri and extract the hns domain and anything that is passed in the uri after it # example: /hns/something/foo/bar matches: # > hns_domain: something # > path: /foo/bar/ set_by_lua_block $hns_domain { return string.match(ngx.var.uri, "/hns/([^/?]+)") } set_by_lua_block $path { return string.match(ngx.var.uri, "/hns/[^/?]+(.*)") } proxy_set_header Host $host; include /etc/nginx/conf.d/include/location-hns; } location /hnsres { include /etc/nginx/conf.d/include/cors; proxy_pass http://handshake-api:3100; } location /skynet/registry { include /etc/nginx/conf.d/include/location-skynet-registry; } location /skynet/skyfile { include /etc/nginx/conf.d/include/cors; include /etc/nginx/conf.d/include/sia-auth; include /etc/nginx/conf.d/include/track-upload; include /etc/nginx/conf.d/include/generate-siapath; limit_req zone=uploads_by_ip burst=100 nodelay; limit_req zone=uploads_by_ip_throttled; limit_conn upload_conn 10; limit_conn upload_conn_rl 1; client_max_body_size 1000M; # make sure to limit the size of upload to a sane value # increase request timeouts proxy_read_timeout 600; proxy_send_timeout 600; proxy_request_buffering off; # stream uploaded files through the proxy as it comes in proxy_set_header Expect $http_expect; proxy_set_header User-Agent: Sia-Agent; # access_by_lua_block { # -- this block runs only when accounts are enabled # if os.getenv("ACCOUNTS_ENABLED") ~= "true" then return end # ngx.var.upload_limit_rate = 5 * 1024 * 1024 # local res = ngx.location.capture("/accounts/user", { copy_all_vars = true }) # if res.status == ngx.HTTP_OK then # local json = require('cjson') # local user = json.decode(res.body) # ngx.var.upload_limit_rate = ngx.var.upload_limit_rate * (user.tier + 1) # end # } # proxy this call to siad endpoint (make sure the ip is correct) proxy_pass http://sia:9980/skynet/skyfile/$dir1/$dir2/$dir3$is_args$args; } # endpoint implementing resumable file uploads open protocol https://tus.io location /skynet/tus { include /etc/nginx/conf.d/include/cors-headers; # include cors headers but do not overwrite OPTIONS response include /etc/nginx/conf.d/include/track-upload; # TUS chunks size is 40M + leaving 10M of breathing room client_max_body_size 50M; # Those timeouts need to be elevated since skyd can stall reading # data for a while when overloaded which would terminate connection client_body_timeout 1h; proxy_send_timeout 1h; # Add X-Forwarded-* headers proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; # rewrite proxy request to use correct host uri from env variable (required to return correct location header) set_by_lua $SKYNET_SERVER_API 'return os.getenv("SKYNET_SERVER_API")'; proxy_redirect $scheme://$host $SKYNET_SERVER_API; # proxy /skynet/tus requests to siad endpoint with all arguments proxy_pass http://sia:9980; # set max upload size dynamically based on account limits rewrite_by_lua_block { -- set default limit value to 1 GB ngx.req.set_header("SkynetMaxUploadSize", 1073741824) -- this block runs only when accounts are enabled if os.getenv("ACCOUNTS_ENABLED") ~= "true" then return end local httpc = require("resty.http").new() -- fetch account limits and set max upload size accordingly local res, err = httpc:request_uri("http://10.10.10.70:3000/user/limits", { headers = { ["Cookie"] = "skynet-jwt=" .. ngx.var.skynet_jwt } }) -- fail gracefully in case /user/limits failed if err or (res and res.status ~= ngx.HTTP_OK) then ngx.log(ngx.ERR, "Failed accounts service request /user/limits: ", err or ("[HTTP " .. res.status .. "] " .. res.body)) elseif res and res.status == ngx.HTTP_OK then local json = require('cjson') local limits = json.decode(res.body) ngx.req.set_header("SkynetMaxUploadSize", limits.maxUploadSize) end } # extract skylink from base64 encoded upload metadata and assign to a proper header header_filter_by_lua_block { ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API") ngx.header["Skynet-Server-Api"] = os.getenv("SKYNET_SERVER_API") if ngx.header["Upload-Metadata"] then local encodedSkylink = string.match(ngx.header["Upload-Metadata"], "Skylink ([^,?]+)") if encodedSkylink then ngx.header["Skynet-Skylink"] = ngx.decode_base64(encodedSkylink) end end } } location /skynet/pin { include /etc/nginx/conf.d/include/cors; include /etc/nginx/conf.d/include/sia-auth; include /etc/nginx/conf.d/include/track-upload; include /etc/nginx/conf.d/include/generate-siapath; proxy_set_header User-Agent: Sia-Agent; proxy_pass http://sia:9980$uri?siapath=$dir1/$dir2/$dir3&$args; } location /skynet/metadata { include /etc/nginx/conf.d/include/cors; header_filter_by_lua_block { ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API") ngx.header["Skynet-Server-Api"] = os.getenv("SKYNET_SERVER_API") -- do not expose internal header ngx.header["Skynet-Requested-Skylink"] = "" } proxy_set_header User-Agent: Sia-Agent; proxy_pass http://sia:9980; } location /skynet/resolve { include /etc/nginx/conf.d/include/cors; header_filter_by_lua_block { ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API") ngx.header["Skynet-Server-Api"] = os.getenv("SKYNET_SERVER_API") -- do not expose internal header ngx.header["Skynet-Requested-Skylink"] = "" } proxy_set_header User-Agent: Sia-Agent; proxy_pass http://sia:9980; } location ~ "^/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { set $skylink $2; set $path $3; include /etc/nginx/conf.d/include/location-skylink; } location ~ "^/file/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { set $skylink $2; set $path $3; set $args attachment=true&$args; #set $is_args ?; include /etc/nginx/conf.d/include/location-skylink; } location @purge { allow 10.0.0.0/8; allow 127.0.0.1/32; allow 172.16.0.0/12; allow 192.168.0.0/16; deny all; set $lua_purge_path "/data/nginx/cache/"; content_by_lua_file /etc/nginx/conf.d/scripts/purge-multi.lua; } location /__internal/do/not/use/authenticated { include /etc/nginx/conf.d/include/cors; charset utf-8; charset_types application/json; default_type application/json; content_by_lua_block { local json = require('cjson') -- this block runs only when accounts are enabled if os.getenv("ACCOUNTS_ENABLED") ~= "true" then ngx.say(json.encode{authenticated = false}) return ngx.exit(ngx.HTTP_OK) end local httpc = require("resty.http").new() -- 10.10.10.70 points to accounts service (alias not available when using resty-http) local res, err = httpc:request_uri("http://10.10.10.70:3000/user", { headers = { ["Cookie"] = "skynet-jwt=" .. ngx.var.skynet_jwt } }) -- endpoint /user should return HTTP_OK for authenticated and HTTP_UNAUTHORIZED for not authenticated if res and (res.status == ngx.HTTP_OK or res.status == ngx.HTTP_UNAUTHORIZED) then ngx.say(json.encode{authenticated = res.status == ngx.HTTP_OK}) return ngx.exit(ngx.HTTP_OK) else ngx.log(ngx.ERR, "Failed accounts service request /user: ", err or ("[HTTP " .. res.status .. "] " .. res.body)) ngx.say(json.encode{authenticated = false}) return ngx.exit(ngx.HTTP_OK) end } } include /etc/nginx/conf.d/server-override/*;