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: