Skip to content

Instantly share code, notes, and snippets.

@Sgiath
Last active September 23, 2021 21:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sgiath/8195ec45536cff7075582576cd5c4543 to your computer and use it in GitHub Desktop.
Save Sgiath/8195ec45536cff7075582576cd5c4543 to your computer and use it in GitHub Desktop.
Foundry Nginx config
#!/usr/bin/env bash
# ==================== EDIT THIS ================================================
core_files="/home/foundry/core"
data_files="/home/foundry/data"
# ===============================================================================
# Green done message
msg_done() {
printf "%sDone%s\n" "$(tput bold)$(tput setaf 2)" "$(tput sgr0)"
}
# fd and brotli command
run_brotli() {
fdfind --full-path "$1" \
--exclude node_modules \
--absolute-path \
--type file \
--extension css \
--extension js \
--extension mjs \
--extension json \
--extension svg \
--exec-batch brotli -f {}
}
# Copy necessary files from node_modules to scripts folder
copy_lib_files() {
printf "Copying library files - "
# Library files outside of scripts folder
lib_files=(
"${core_files}/resources/app/node_modules/tinymce/tinymce.min.js"
"${core_files}/resources/app/node_modules/socket.io-client/dist/socket.io.min.js"
"${core_files}/resources/app/node_modules/pixi.js/dist/browser/pixi.min.js"
"${core_files}/resources/app/node_modules/pixi-particles/dist/pixi-particles.min.js"
"${core_files}/resources/app/node_modules/handlebars/dist/handlebars.min.js"
"${core_files}/resources/app/node_modules/handlebars-intl/dist/handlebars-intl.min.js"
"${core_files}/resources/app/node_modules/jquery/dist/jquery.min.js"
"${core_files}/resources/app/node_modules/simple-peer/simplepeer.min.js"
"${core_files}/resources/app/node_modules/tinymce/icons/"
"${core_files}/resources/app/node_modules/tinymce/plugins/"
"${core_files}/resources/app/node_modules/tinymce/skins/"
"${core_files}/resources/app/node_modules/tinymce/themes/"
)
for file in "${lib_files[@]}"; do
cp -rf "${file}" "${core_files}/resources/app/public/scripts/"
done
msg_done
}
# Brotli compress core files
compress_core_files() {
printf "Compressing core files - "
run_brotli "${core_files}/resources/app"
msg_done
}
# Brotli compress data files
compress_data_files() {
printf "Compressing data files - "
run_brotli "${data_files}/Data"
msg_done
}
# Brotli compress single module files
compress_module() {
printf "Compressing module \"%s\" - " "$1"
run_brotli "${data_files}/Data/modules/$1"
msg_done
}
# Main script switch
case "$1" in
--core)
copy_lib_files
compress_core_files
;;
--data)
compress_data_files
;;
--module)
compress_module "$2"
;;
--plutonium)
compress_module "plutonium"
;;
# Add other commonly used modules
*)
copy_lib_files
compress_core_files
compress_data_files
;;
esac
# Enable Brotli encoding on-the-fly
brotli on;
# Enable serving precompressed files
brotli_static on;
# On-the-fly encoding will use compression level 5 to speed things up
brotli_comp_level 5;
# File types to encode (text/html is always encoded)
brotli_types text/css application/javascript application/json image/svg+xml;
# Foundry Express server (change it if you are running it on different port)
upstream foundry {
server localhost:30000;
}
server {
# =============================== EDIT THIS =================================
# Paths to your core and data folders
set $core_path /home/foundry/core;
set $data_path /home/foundry/data;
# Hostname of your server
server_name foundry.example.com;
# ===========================================================================
listen 443 ssl http2;
listen [::]:443 ssl http2;
client_max_body_size 300M;
# Serving static files directly with Nginx
location ~ ^/(css|docs|fonts|icons|lang|scripts|sounds|ui) {
root $core_path/resources/app/public;
}
location /common/ {
root $core_path/resources/app;
}
location / {
root $data_path/Data;
}
# Root redirect
location = / {
return 301 /game;
}
# Proxy to Express server for HTTP
location ~ ^/(setup|join|game|upload|quit|stream|players|license|no|api|favicon.ico) {
include /etc/nginx/proxy_params;
proxy_buffers 16 16k;
proxy_buffer_size 16k;
proxy_read_timeout 90;
proxy_redirect off;
proxy_pass http://foundry;
}
# Proxy to Express server for WebSockets
location /socket.io {
include /etc/nginx/proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://foundry;
}
}
user www-data;
pid /run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
multi_accept on;
worker_connections 65535;
}
http {
charset utf-8;
# Allows sending files directly from disk
sendfile on;
# Send files larger than 4 MB asynchronously without blocking worker threads
aio threads;
directio 4m;
# Optimizes packets when using sendfile
tcp_nopush on;
# Avoid 200 ms delay from ancient times
tcp_nodelay on;
# Configure mime types
include /etc/nginx/mime.types;
default_type application/octet-stream;
# WebSocket mapping
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

Improved Nginx configuration

Prerequisites

  • Machine with sudo access
  • Brotli installed
    • sudo apt install brotli
  • fd installed
    • sudo apt install fd-find
  • build tools installed
    • sudo apt install build-essential libpcre3 libpcre3-dev libssl-dev zlib1g-dev

Installation

  1. Clone ngx_brotli

    git clone https://github.com/google/ngx_brotli.git /opt/ngx_brotli
    cd /opt/ngx_brotli
    git submodule update --init --recursive
  2. Build Nginx from source with Brotli and http2

    cd /usr/src
    wget http://nginx.org/download/nginx-1.21.3.tar.gz
    tar xf nginx-1.21.3.tar.gz
    cd nginx-1.21.3
    ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --with-file-aio --with-threads --with-http_ssl_module --with-http_v2_module --add-module=/opt/ngx_brotli
    make
    make install
  3. Add mjs to /etc/nginx/mime.types

    • Change line application/javascript js; to application/javascript js mjs;
  4. Configure Nginx

    • copy stuff from nginx.conf to your /etc/nginx/nginx.conf file

    • add ssl.conf and compression.conf to the /etc/nginx/conf.d/ folder

    • add or replace /etc/nginx/proxy_params with proxy_params

    • add foundry.example.com.conf (probably under better name) to your /etc/nginx/sites-available/ folder and create symlink in /etc/nginx/sites-enabled/ folder:

      sudo ln -sn ../sites-available/foundry.example.com.conf /etc/nginx/sites-enabled/foundry.example.com.conf
    • you need to change the following

      • /etc/nginx/conf.d/ssl.conf
        • you probably want to change the path to your SSL certificate
        • or replace it completely with your configuration (not critical for the setup but some SSL config needs to be present for HTTP/2 to work)
      • /etc/nginx/sites-available/foundry.example.com.conf
        • Foundry upstream - if you are running it on different port than 30000
        • Foundry core and data paths
        • Add your server_name
  5. Add compression script to your Foundry parrent folder (/home/foundry), make it executable and edit your core and data paths at the top of the file

  6. Run the compress.sh script under user which owns Foundry files

Considerations

  • compress.sh script can take a long time to run and it needs to be run after every update (core or any module or system), so it contains helpful options to run it just on the subset of files (files you know changed). E.g.:

    ./compress.sh --core  # Run after just Foundry update
    ./compress.sh --data  # Run after bulk module/system update
    ./compress.sh --module plutonium  # Run after just one specific module update
  • compress.sh script creates new files in Foundry folders so it should be executed under user which you use to run Foundry

    sudo -u foundry bash
    cd /home/foundry
    ./compress.sh
  • Foundry folders needs to be readable by Nginx user. I recommend adding www-data to the foundry group (if you are using foundry user to run Foundry) and make all Foundry files readable by group:

    usermod -aG foundry www-data
    
    chown -R foundry:foundry /home/foundry/core
    chown -R foundry:foundry /home/foundry/data
    
    chmod -R g+r /home/foundry/core
    chmod -R g+r /home/foundry/data
@kajov
Copy link

kajov commented Sep 23, 2021

PoC confimed - Works! :)
Greetings from Kay in Discord :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment