diff --git a/docker-compose.yml b/docker-compose.yml index 3c364523..5a4a579a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,8 +17,8 @@ services: caddy: build: - context: . - dockerfile: ./docker/caddy/Dockerfile + context: ./docker/caddy + dockerfile: Dockerfile container_name: caddy restart: on-failure env_file: @@ -37,9 +37,13 @@ services: - nginx nginx: - image: openresty/openresty:1.15.8.3-2-xenial + build: + context: . + dockerfile: ./docker/nginx/Dockerfile container_name: nginx restart: on-failure + env_file: + - .env volumes: - ./docker/nginx/conf.d:/etc/nginx/conf.d:ro - ./docker/data/nginx/cache:/data/nginx/cache @@ -57,6 +61,7 @@ services: dockerfile: Dockerfile container_name: handshake restart: on-failure + command: hnd --log-console=false environment: - HSD_HTTP_HOST=0.0.0.0 - HSD_NETWORK=main @@ -90,7 +95,7 @@ services: - 3100 depends_on: - handshake - - caddy + - nginx health-check: build: @@ -104,11 +109,11 @@ services: networks: - shared environment: - - PORTAL_URL=caddy + - PORTAL_URL=nginx - HOSTNAME=health-check - NODE_TLS_REJECT_UNAUTHORIZED=0 expose: - 3100 depends_on: - docker-host - - caddy + - nginx diff --git a/docker/caddy/Caddyfile b/docker/caddy/Caddyfile index 9a0aacd7..6e3e0ae6 100644 --- a/docker/caddy/Caddyfile +++ b/docker/caddy/Caddyfile @@ -1,82 +1,7 @@ -(webserver) { - root * /home/user/public_html - file_server - encode zstd gzip - - @skylink { - path_regexp skylink ^/([a-zA-Z0-9-_]{46}(/.*)?)$ - } - - @skylink_file { - path_regexp skylink_file ^/file/([a-zA-Z0-9-_]{46}(/.*)?)$ - } - - @options { - method OPTIONS - } - - @blacklist { - method GET - path /blacklist - } - - @portals { - method GET - path /portals - } - - # OPTIONS headers to allow CORS https://enable-cors.org - handle @options { - header { - Access-Control-Allow-Origin * - Access-Control-Allow-Methods GET,POST,OPTIONS - Access-Control-Allow-Headers DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range - Access-Control-Max-Age 1728000 - } - respond 204 - } - - reverse_proxy /health-check health-check:3100 - reverse_proxy /hns/* handshake-api:3100 - reverse_proxy /hnsres/* handshake-api:3100 - - reverse_proxy @blacklist nginx:80 { - header_up User-Agent Sia-Agent - header_down Access-Control-Allow-Origin * - } - reverse_proxy @portals nginx:80 { - header_up User-Agent Sia-Agent - header_down Access-Control-Allow-Origin * - } - reverse_proxy /stats nginx:80 { - header_up User-Agent Sia-Agent - header_down Access-Control-Allow-Origin * - } - reverse_proxy /statsdown nginx:80 { - header_up User-Agent Sia-Agent - header_down Access-Control-Allow-Origin * - } - reverse_proxy @skylink nginx:80 { - header_up User-Agent Sia-Agent - header_up Access-Control-Expose-Headers skynet-file-metadata - header_down Access-Control-Allow-Origin * - } - reverse_proxy @skylink_file nginx:80 { - header_up User-Agent Sia-Agent - header_up Access-Control-Expose-Headers skynet-file-metadata - header_down Access-Control-Allow-Origin * - } - reverse_proxy /skynet/skyfile* nginx:80 { - header_up User-Agent Sia-Agent - header_up Authorization "Basic {env.SIA_API_AUTHORIZATION}" - header_down Access-Control-Allow-Origin * - } -} - (custom.domain) { {$DOMAIN_NAME} { tls {$EMAIL_ADDRESS} - import webserver + reverse_proxy nginx:80 } } @@ -85,7 +10,7 @@ tls { dns cloudflare {env.CLOUDFLARE_AUTH_TOKEN} } - import webserver + reverse_proxy nginx:80 } } @@ -94,7 +19,7 @@ tls internal { on_demand } - import webserver + reverse_proxy nginx:80 } } diff --git a/docker/caddy/Dockerfile b/docker/caddy/Dockerfile index c6356699..d0f22045 100644 --- a/docker/caddy/Dockerfile +++ b/docker/caddy/Dockerfile @@ -1,20 +1,7 @@ -FROM node:12.18.0 AS client-builder - -COPY src ./src -COPY static ./static -COPY gatsby-config.js . -COPY package.json . -COPY yarn.lock . - -ENV CYPRESS_INSTALL_BINARY 0 -RUN yarn --frozen-lockfile -RUN yarn build - FROM caddy:2.1.1-builder AS caddy-builder -RUN caddy-builder github.com/caddy-dns/cloudflare +RUN caddy-builder github.com/caddy-dns/cloudflare github.com/caddy-dns/route53 FROM caddy:2.1.1 -COPY --from=client-builder /public /home/user/public_html COPY --from=caddy-builder /usr/bin/caddy /usr/bin/caddy diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile new file mode 100644 index 00000000..ec521767 --- /dev/null +++ b/docker/nginx/Dockerfile @@ -0,0 +1,15 @@ +FROM node:14.5 AS webportal-builder + +COPY src ./src +COPY static ./static +COPY gatsby-config.js . +COPY package.json . +COPY yarn.lock . + +ENV CYPRESS_INSTALL_BINARY 0 +RUN yarn --frozen-lockfile +RUN yarn build + +FROM openresty/openresty:1.15.8.3-2-xenial + +COPY --from=webportal-builder /public /var/www/webportal diff --git a/docker/nginx/conf.d/client.conf b/docker/nginx/conf.d/client.conf index 262db21e..0a922497 100644 --- a/docker/nginx/conf.d/client.conf +++ b/docker/nginx/conf.d/client.conf @@ -21,7 +21,7 @@ real_ip_header X-Forwarded-For; # The upload siad can be run in normal mode. Set the port to '9980' if # you do not want to run your portal in the double siad setup. upstream siad-upload { - server docker-host:9970; + server docker-host:9980; } upstream siad-download { @@ -41,39 +41,65 @@ server { client_body_buffer_size 128k; client_max_body_size 128k; - rewrite "^(/([a-zA-Z0-9-_]{46})[^/]{0})$" $1/ permanent; - rewrite "^(/hns/[^/]+)[^/]{0}$" $1/ permanent; + location / { + root /var/www/webportal; + } location /blacklist { proxy_cache skynet; proxy_cache_valid any 1m; # cache blacklist for 1 minute + proxy_set_header Access-Control-Allow-Origin: *; + proxy_set_header User-Agent: Sia-Agent; proxy_pass http://siad-download/skynet/blacklist; } location /portals { proxy_cache skynet; proxy_cache_valid any 1m; # cache portals for 1 minute + proxy_set_header Access-Control-Allow-Origin: *; + proxy_set_header User-Agent: Sia-Agent; proxy_pass http://siad-download/skynet/portals; } location /stats { proxy_cache skynet; proxy_cache_valid any 1m; # cache stats for 1 minute + proxy_set_header Access-Control-Allow-Origin: *; + proxy_set_header User-Agent: Sia-Agent; proxy_pass http://siad-upload/skynet/stats; } location /statsdown { proxy_cache skynet; proxy_cache_valid any 1m; # cache stats for 1 minute + proxy_set_header Access-Control-Allow-Origin: *; + proxy_set_header User-Agent: Sia-Agent; proxy_pass http://siad-download/skynet/stats; } + location /health-check { + proxy_set_header Access-Control-Allow-Origin: *; + proxy_pass http://health-check:3100; + } + + location /hns { + proxy_set_header Access-Control-Allow-Origin: *; + proxy_pass http://handshake-api:3100; + } + + location /hnsres { + proxy_set_header Access-Control-Allow-Origin: *; + proxy_pass http://handshake-api:3100; + } + location /skynet/skyfile { limit_conn uploads_by_ip 10; # ddos protection: max 10 uploads at a time client_max_body_size 1000M; # make sure to limit the size of upload to a sane value proxy_read_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 Access-Control-Allow-Origin: *; + proxy_set_header User-Agent: Sia-Agent; # Extract 3 sets of 2 characters from $request_id and assign to $dir1, $dir2, $dir3 # respectfully. The rest of the $request_id is going to be assigned to $dir4. @@ -90,6 +116,22 @@ server { # proxy this call to siad endpoint (make sure the ip is correct) proxy_pass http://siad-upload/skynet/skyfile/$dir1/$dir2/$dir3/$dir4$is_args$args; + + # rewrite_by_lua_block { + # local b64 = require("ngx.base64") + # -- open apipassword file for reading (b flag is required for some reason) + # -- (file /etc/.sia/apipassword has to be mounted from the host system) + # local apipassword_file = io.open("/etc/.sia/apipassword", "rb") + # -- read apipassword file contents and trim newline (important) + # local apipassword = apipassword_file:read("*all"):gsub("%s+", "") + # -- make sure to close file after reading the password + # apipassword_file.close() + # -- encode the user:password authorization string + # -- (in our case user is empty so it is just :password) + # local content = b64.encode_base64url(":" .. apipassword) + # -- set authorization header with proper base64 encoded string + # ngx.req.set_header("Authorization", "Basic " .. content) + # } } location ~ "/skynet/skyfile/(.+)" { @@ -98,6 +140,8 @@ server { proxy_read_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 Access-Control-Allow-Origin: *; + proxy_set_header User-Agent: Sia-Agent; # we need to explicitly use set directive here because $1 will contain the siapath with # decoded whitespaces and set will re-encode it for us before passing it to proxy_pass @@ -115,6 +159,8 @@ server { set $skylink $1; proxy_read_timeout 600; + proxy_set_header Access-Control-Allow-Origin: *; + proxy_set_header User-Agent: Sia-Agent; # proxy this call to siad /skynet/skylink/ endpoint (make sure the ip is correct) proxy_pass http://siad-download/skynet/skylink/$skylink$is_args$args; @@ -137,6 +183,8 @@ server { set $skylink $1; proxy_read_timeout 600; + proxy_set_header Access-Control-Allow-Origin: *; + proxy_set_header User-Agent: Sia-Agent; # proxy this call to siad /skynet/skylink/ endpoint (make sure the ip is correct) # this alias also adds attachment=true url param to force download the file proxy_pass http://siad-download/skynet/skylink/$skylink?attachment=true&$args; diff --git a/docker/nginx/conf.d/gzip.conf b/docker/nginx/conf.d/gzip.conf new file mode 100644 index 00000000..7d7a962c --- /dev/null +++ b/docker/nginx/conf.d/gzip.conf @@ -0,0 +1,18 @@ +# enables gzip compression +gzip on; + +# set the gzip compression level (1-9) +gzip_comp_level 6; + +# tells proxies to cache both gzipped and regular versions of a resource +gzip_vary on; + +# informs NGINX to not compress anything smaller than the defined size +gzip_min_length 256; + +# compress data even for clients that are connecting via proxies if a response header includes +# the "expired", "no-cache", "no-store", "private", and "Authorization" parameters +gzip_proxied expired no-cache no-store private auth; + +# enables the types of files that can be compressed +gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;