diff --git a/docker-compose-speckle.yml b/docker-compose-speckle.yml index af44054ac..2c9abbe80 100644 --- a/docker-compose-speckle.yml +++ b/docker-compose-speckle.yml @@ -7,7 +7,7 @@ services: image: speckle/speckle-frontend:local restart: always ports: - - '0.0.0.0:80:80' + - '0.0.0.0:80:8080' environment: FILE_SIZE_LIMIT_MB: 100 diff --git a/packages/frontend/Dockerfile b/packages/frontend/Dockerfile index a71bc4baf..0a040ffd3 100644 --- a/packages/frontend/Dockerfile +++ b/packages/frontend/Dockerfile @@ -30,21 +30,29 @@ COPY packages/shared ./packages/shared/ # This way the foreach only builds the frontend and its deps RUN yarn workspaces foreach run build +RUN DEBIAN_FRONTEND=noninteractive \ + apt-get -q update && \ + apt-get install --no-install-recommends -y \ + gettext=0.21-4 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + # production stage -FROM openresty/openresty:1.21.4.1-4-jammy-amd64 as production-stage +FROM bitnami/openresty:1.21.4-1-debian-11-r80 as production-stage ARG NODE_ENV ARG SPECKLE_SERVER_VERSION ENV NODE_ENV=${NODE_ENV} ENV FILE_SIZE_LIMIT_MB=100 -COPY --from=build-stage /speckle-server/packages/frontend/dist /usr/share/nginx/html -RUN rm /etc/nginx/conf.d/default.conf +COPY --from=build-stage /usr/bin/envsubst /usr/bin/envsubst -COPY packages/frontend/nginx/ /etc/nginx/ +COPY --from=build-stage /speckle-server/packages/frontend/dist /app + +COPY packages/frontend/nginx/ /opt/bitnami/openresty/nginx/ # prepare the environment -ENTRYPOINT ["/etc/nginx/docker-entrypoint.sh"] +ENTRYPOINT ["/opt/bitnami/openresty/nginx/docker-entrypoint.sh"] -EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] +EXPOSE 8080 +CMD ["/opt/bitnami/scripts/openresty/entrypoint.sh", "/opt/bitnami/scripts/openresty/run.sh"] diff --git a/packages/frontend/nginx/docker-entrypoint.sh b/packages/frontend/nginx/docker-entrypoint.sh index 098caa512..67bc935fd 100755 --- a/packages/frontend/nginx/docker-entrypoint.sh +++ b/packages/frontend/nginx/docker-entrypoint.sh @@ -5,7 +5,8 @@ defined_envs=$(printf '${%s} ' $(env | cut -d= -f1)) echo Starting nginx environment template rendering with "${defined_envs}" -envsubst "${defined_envs}" < /etc/nginx/templates/nginx.conf.template > /etc/nginx/conf.d/nginx.conf +cp /opt/bitnami/openresty/nginx/mime.types /opt/bitnami/openresty/nginx/conf/mime.types +envsubst "${defined_envs}" < /opt/bitnami/openresty/nginx/templates/nginx.conf.template > /opt/bitnami/openresty/nginx/conf/nginx.conf echo Nginx conf rendered, starting server... exec "$@" diff --git a/packages/frontend/nginx/mime.types b/packages/frontend/nginx/mime.types new file mode 100644 index 000000000..8d37c8636 --- /dev/null +++ b/packages/frontend/nginx/mime.types @@ -0,0 +1,98 @@ +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/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/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} diff --git a/packages/frontend/nginx/templates/nginx.conf.template b/packages/frontend/nginx/templates/nginx.conf.template index 6699d4ec9..7ed62fabb 100644 --- a/packages/frontend/nginx/templates/nginx.conf.template +++ b/packages/frontend/nginx/templates/nginx.conf.template @@ -1,130 +1,147 @@ -server_tokens off; -gzip on; -gzip_disable "msie6"; +pcre_jit on; +error_log stderr info; -gzip_vary on; -gzip_proxied any; -gzip_comp_level 6; -gzip_buffers 16 8k; -gzip_http_version 1.1; -gzip_min_length 256; -gzip_types - application/atom+xml - application/geo+json - application/javascript - application/x-javascript - application/json - application/ld+json - application/manifest+json - application/rdf+xml - application/rss+xml - application/xhtml+xml - application/xml - font/eot - font/otf - font/ttf - image/svg+xml - text/css - text/javascript - text/plain - text/xml; +events { + worker_connections 1024; +} -set_real_ip_from 103.21.244.0/22; -set_real_ip_from 103.22.200.0/22; -set_real_ip_from 103.31.4.0/22; -set_real_ip_from 104.16.0.0/13; -set_real_ip_from 104.24.0.0/14; -set_real_ip_from 108.162.192.0/18; -set_real_ip_from 131.0.72.0/22; -set_real_ip_from 141.101.64.0/18; -set_real_ip_from 162.158.0.0/15; -set_real_ip_from 172.64.0.0/13; -set_real_ip_from 173.245.48.0/20; -set_real_ip_from 188.114.96.0/20; -set_real_ip_from 190.93.240.0/20; -set_real_ip_from 197.234.240.0/22; -set_real_ip_from 198.41.128.0/17; -set_real_ip_from 2400:cb00::/32; -set_real_ip_from 2606:4700::/32; -set_real_ip_from 2803:f800::/32; -set_real_ip_from 2405:b500::/32; -set_real_ip_from 2405:8100::/32; -set_real_ip_from 2c0f:f248::/32; -set_real_ip_from 2a06:98c0::/29; - -#use any of the following two -real_ip_header CF-Connecting-IP; -#real_ip_header X-Forwarded-For; - -server { - listen 80; - client_max_body_size 100m; +http { + include mime.types; + default_type application/octet-stream; # move default write paths to a custom directory # kubernetes can mount this directory and prevent writes to the root directory # https://github.com/openresty/docker-openresty/issues/119 - client_body_temp_path /var/run/openresty/nginx-client-body; - proxy_temp_path /var/run/openresty/nginx-proxy; - fastcgi_temp_path /var/run/openresty/nginx-fastcgi; - uwsgi_temp_path /var/run/openresty/nginx-uwsgi; - scgi_temp_path /var/run/openresty/nginx-scgi; + client_body_temp_path /bitnami/openresty/nginx-client-body; + proxy_temp_path /bitnami/openresty/nginx-proxy; + fastcgi_temp_path /bitnami/openresty/nginx-fastcgi; + uwsgi_temp_path /bitnami/openresty/nginx-uwsgi; + scgi_temp_path /bitnami/openresty/nginx-scgi; - location / { - root /usr/share/nginx/html; - index index.html; - try_files $uri $uri/ /index.html; - add_header Cache-Control "no-store, no-cache, must-revalidate"; - } + sendfile on; + keepalive_timeout 65; + access_log /dev/stdout; - location ~* ^/(favicon.ico|logo.svg|loadingImage.png|og_image.png) { - root /usr/share/nginx/html; - index index.html; - try_files $uri $uri/ /index.html; - expires 1d; - } + # Speckle configuration + server_tokens off; + gzip on; + gzip_disable "msie6"; - location ~* ^/(js/.*|fonts/.*|(css/.*)|(img/.*)|(assets/.*)) { - root /usr/share/nginx/html; - index index.html; - try_files $uri $uri/ /index.html; - expires 1y; - } + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_min_length 256; + gzip_types + application/atom+xml + application/geo+json + application/javascript + application/x-javascript + application/json + application/ld+json + application/manifest+json + application/rdf+xml + application/rss+xml + application/xhtml+xml + application/xml + font/eot + font/otf + font/ttf + image/svg+xml + text/css + text/javascript + text/plain + text/xml; - location ~ ^/streams/.* { - default_type text/html; - content_by_lua_block { - local f = assert(io.open('/usr/share/nginx/html/index.html', "rb")) - local content = f:read("*all") - f:close() - local http_host = ngx.var.http_host + set_real_ip_from 103.21.244.0/22; + set_real_ip_from 103.22.200.0/22; + set_real_ip_from 103.31.4.0/22; + set_real_ip_from 104.16.0.0/13; + set_real_ip_from 104.24.0.0/14; + set_real_ip_from 108.162.192.0/18; + set_real_ip_from 131.0.72.0/22; + set_real_ip_from 141.101.64.0/18; + set_real_ip_from 162.158.0.0/15; + set_real_ip_from 172.64.0.0/13; + set_real_ip_from 173.245.48.0/20; + set_real_ip_from 188.114.96.0/20; + set_real_ip_from 190.93.240.0/20; + set_real_ip_from 197.234.240.0/22; + set_real_ip_from 198.41.128.0/17; + set_real_ip_from 2400:cb00::/32; + set_real_ip_from 2606:4700::/32; + set_real_ip_from 2803:f800::/32; + set_real_ip_from 2405:b500::/32; + set_real_ip_from 2405:8100::/32; + set_real_ip_from 2c0f:f248::/32; + set_real_ip_from 2a06:98c0::/29; - content = content:gsub('', '') + #use any of the following two + real_ip_header CF-Connecting-IP; + #real_ip_header X-Forwarded-For; - local stream_id = ngx.var.uri:sub(10) - local img_tag = '' + server { + listen 8080; + client_max_body_size 100m; - content = content:gsub('', img_tag) + location / { + root /app; + index index.html; + try_files $uri $uri/ /index.html; + add_header Cache-Control "no-store, no-cache, must-revalidate"; + } - ngx.say(content) + location ~* ^/(favicon.ico|logo.svg|loadingImage.png|og_image.png) { + root /app; + index index.html; + try_files $uri $uri/ /index.html; + expires 1d; + } + + location ~* ^/(js/.*|fonts/.*|(css/.*)|(img/.*)|(assets/.*)) { + root /app; + index index.html; + try_files $uri $uri/ /index.html; + expires 1y; + } + + location ~ ^/streams/.* { + default_type text/html; + content_by_lua_block { + local f = assert(io.open('/app/index.html', "rb")) + local content = f:read("*all") + f:close() + local http_host = ngx.var.http_host + + content = content:gsub('', '') + + local stream_id = ngx.var.uri:sub(10) + local img_tag = '' + + content = content:gsub('', img_tag) + + ngx.say(content) + } + } + + location ~* ^/(graphql|explorer|(auth/.*)|(objects/.*)|(preview/.*)|(api/.*)|(static/.*)) { + resolver 127.0.0.11 valid=30s; + set $upstream_speckle_server speckle-server; + client_max_body_size ${FILE_SIZE_LIMIT_MB}m; + proxy_pass http://$upstream_speckle_server:3000; + + proxy_buffering off; + proxy_request_buffering off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + + error_page 500 502 503 504 /50x.html; + + location = /50x.html { + root /app; } } - - location ~* ^/(graphql|explorer|(auth/.*)|(objects/.*)|(preview/.*)|(api/.*)|(static/.*)) { - resolver 127.0.0.11 valid=30s; - set $upstream_speckle_server speckle-server; - client_max_body_size ${FILE_SIZE_LIMIT_MB}m; - proxy_pass http://$upstream_speckle_server:3000; - - proxy_buffering off; - proxy_request_buffering off; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - } - - error_page 500 502 503 504 /50x.html; - - location = /50x.html { - root /usr/share/nginx/html; - } } diff --git a/utils/1click_image_scripts/template-docker-compose.yml b/utils/1click_image_scripts/template-docker-compose.yml index 6ef99cd37..dce791522 100644 --- a/utils/1click_image_scripts/template-docker-compose.yml +++ b/utils/1click_image_scripts/template-docker-compose.yml @@ -40,7 +40,7 @@ services: image: speckle/speckle-frontend:2 restart: always ports: - - '127.0.0.1:8000:80' + - '127.0.0.1:8080:8080' environment: FILE_SIZE_LIMIT_MB: 100 diff --git a/utils/1click_image_scripts/template-nginx-site.conf b/utils/1click_image_scripts/template-nginx-site.conf index 5d8ee2798..b978f6cfa 100644 --- a/utils/1click_image_scripts/template-nginx-site.conf +++ b/utils/1click_image_scripts/template-nginx-site.conf @@ -10,7 +10,7 @@ server { client_max_body_size 100m; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; - proxy_pass http://localhost:8000; + proxy_pass http://localhost:8080; proxy_buffering off; proxy_request_buffering off; diff --git a/utils/helm/speckle-server/templates/frontend/deployment.yml b/utils/helm/speckle-server/templates/frontend/deployment.yml index d77460814..439b1a157 100644 --- a/utils/helm/speckle-server/templates/frontend/deployment.yml +++ b/utils/helm/speckle-server/templates/frontend/deployment.yml @@ -25,7 +25,7 @@ spec: ports: - name: www - containerPort: 80 + containerPort: 8080 protocol: TCP resources: @@ -53,6 +53,24 @@ spec: - name: FILE_SIZE_LIMIT_MB value: {{ .Values.file_size_limit_mb | quote }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 20000 + + volumeMounts: + - name: openresty-temp + mountPath: /bitnami/openresty + - name: openresty-conf + mountPath: /opt/bitnami/openresty/nginx/conf/ + - name: openresty-logs + mountPath: /opt/bitnami/openresty/nginx/logs/ + priorityClassName: high-priority {{- if .Values.frontend.affinity }} affinity: {{- include "speckle.renderTpl" (dict "value" .Values.frontend.affinity "context" $) | nindent 8 }} @@ -69,3 +87,11 @@ spec: {{- if .Values.frontend.serviceAccount.create }} serviceAccountName: {{ include "frontend.name" $ }} {{- end }} + + volumes: + - name: openresty-temp + emptyDir: {} + - name: openresty-conf + emptyDir: {} + - name: openresty-logs + emptyDir: {} diff --git a/utils/helm/speckle-server/templates/frontend/service.yml b/utils/helm/speckle-server/templates/frontend/service.yml index aff26975a..20e962be7 100644 --- a/utils/helm/speckle-server/templates/frontend/service.yml +++ b/utils/helm/speckle-server/templates/frontend/service.yml @@ -12,5 +12,5 @@ spec: ports: - protocol: TCP name: www - port: 80 + port: 8080 targetPort: www diff --git a/utils/helm/speckle-server/templates/ingress.yml b/utils/helm/speckle-server/templates/ingress.yml index ddef8b354..09430c698 100644 --- a/utils/helm/speckle-server/templates/ingress.yml +++ b/utils/helm/speckle-server/templates/ingress.yml @@ -30,7 +30,7 @@ spec: service: name: speckle-frontend port: - number: 80 + number: 8080 - pathType: Exact path: "/(graphql|explorer|(auth/.*)|(objects/.*)|(preview/.*)|(api/.*)|(static/.*))" backend: