diff --git a/resources/nginx-entrypoint.sh b/resources/nginx-entrypoint.sh new file mode 100644 index 00000000..50408e56 --- /dev/null +++ b/resources/nginx-entrypoint.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Set variables that do not exist +if [[ -z "$BACKEND" ]]; then + echo "BACKEND defaulting to 0.0.0.0:8000" + export BACKEND=0.0.0.0:8000 +fi +if [[ -z "$SOCKETIO" ]]; then + echo "SOCKETIO defaulting to 0.0.0.0:9000" + export SOCKETIO=0.0.0.0:9000 +fi +if [[ -z "$UPSTREAM_REAL_IP_ADDRESS" ]]; then + echo "UPSTREAM_REAL_IP_ADDRESS defaulting to 127.0.0.1" + export UPSTREAM_REAL_IP_ADDRESS=127.0.0.1 +fi +if [[ -z "$UPSTREAM_REAL_IP_HEADER" ]]; then + echo "UPSTREAM_REAL_IP_HEADER defaulting to X-Forwarded-For" + export UPSTREAM_REAL_IP_HEADER=X-Forwarded-For +fi +if [[ -z "$UPSTREAM_REAL_IP_RECURSIVE" ]]; then + echo "UPSTREAM_REAL_IP_RECURSIVE defaulting to off" + export UPSTREAM_REAL_IP_RECURSIVE=off +fi +if [[ -z "$FRAPPE_SITE_NAME_HEADER" ]]; then + # shellcheck disable=SC2016 + echo 'FRAPPE_SITE_NAME_HEADER defaulting to $host' + # shellcheck disable=SC2016 + export FRAPPE_SITE_NAME_HEADER='$host' +fi + +if [[ -z "$PROXY_READ_TIMEOUT" ]]; then + echo "PROXY_READ_TIMEOUT defaulting to 120" + export PROXY_READ_TIMEOUT=120 +fi + +if [[ -z "$CLIENT_MAX_BODY_SIZE" ]]; then + echo "CLIENT_MAX_BODY_SIZE defaulting to 50m" + export CLIENT_MAX_BODY_SIZE=50m +fi + +# shellcheck disable=SC2016 +envsubst '${BACKEND} + ${SOCKETIO} + ${UPSTREAM_REAL_IP_ADDRESS} + ${UPSTREAM_REAL_IP_HEADER} + ${UPSTREAM_REAL_IP_RECURSIVE} + ${FRAPPE_SITE_NAME_HEADER} + ${PROXY_READ_TIMEOUT} + ${CLIENT_MAX_BODY_SIZE}' \ + /etc/nginx/conf.d/frappe.conf + +nginx -g 'daemon off;' diff --git a/resources/nginx-template.conf b/resources/nginx-template.conf new file mode 100644 index 00000000..ded97c94 --- /dev/null +++ b/resources/nginx-template.conf @@ -0,0 +1,107 @@ +upstream backend-server { + server ${BACKEND} fail_timeout=0; +} + +upstream socketio-server { + server ${SOCKETIO} fail_timeout=0; +} + +server { + listen 8080; + server_name ${FRAPPE_SITE_NAME_HEADER}; + root /home/frappe/frappe-bench/sites; + + proxy_buffer_size 128k; + proxy_buffers 4 256k; + proxy_busy_buffers_size 256k; + + add_header X-Frame-Options "SAMEORIGIN"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header Referrer-Policy "same-origin, strict-origin-when-cross-origin"; + + set_real_ip_from ${UPSTREAM_REAL_IP_ADDRESS}; + real_ip_header ${UPSTREAM_REAL_IP_HEADER}; + real_ip_recursive ${UPSTREAM_REAL_IP_RECURSIVE}; + + location /assets { + try_files $uri =404; + } + + location ~ ^/protected/(.*) { + internal; + try_files /${FRAPPE_SITE_NAME_HEADER}/$1 =404; + } + + location /socket.io { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Frappe-Site-Name ${FRAPPE_SITE_NAME_HEADER}; + proxy_set_header Origin $scheme://$http_host; + proxy_set_header Host $host; + + proxy_pass http://socketio-server; + } + + location / { + rewrite ^(.+)/$ $1 permanent; + rewrite ^(.+)/index\.html$ $1 permanent; + rewrite ^(.+)\.html$ $1 permanent; + + location ~ ^/files/.*.(htm|html|svg|xml) { + add_header Content-disposition "attachment"; + try_files /${FRAPPE_SITE_NAME_HEADER}/public/$uri @webserver; + } + + try_files /${FRAPPE_SITE_NAME_HEADER}/public/$uri @webserver; + } + + location @webserver { + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frappe-Site-Name ${FRAPPE_SITE_NAME_HEADER}; + proxy_set_header Host $host; + proxy_set_header X-Use-X-Accel-Redirect True; + proxy_read_timeout ${PROXY_READ_TIMEOUT}; + proxy_redirect off; + + proxy_pass http://backend-server; + } + + # optimizations + sendfile on; + keepalive_timeout 15; + client_max_body_size ${CLIENT_MAX_BODY_SIZE}; + client_body_buffer_size 16K; + client_header_buffer_size 1k; + + # enable gzip compression + # based on https://mattstauffer.co/blog/enabling-gzip-on-nginx-servers-including-laravel-forge + gzip on; + gzip_http_version 1.1; + gzip_comp_level 5; + gzip_min_length 256; + gzip_proxied any; + gzip_vary on; + gzip_types + application/atom+xml + application/javascript + application/json + application/rss+xml + application/vnd.ms-fontobject + application/x-font-ttf + application/font-woff + application/x-web-app-manifest+json + application/xhtml+xml + application/xml + font/opentype + image/svg+xml + image/x-icon + text/css + text/plain + text/x-component; + # text/html is always compressed by HttpGzipModule +}