Skip to content

Instantly share code, notes, and snippets.

@rogeriotaques
Last active January 9, 2026 02:31
Show Gist options
  • Select an option

  • Save rogeriotaques/b082afc443d180abce1afc8a679ac4f7 to your computer and use it in GitHub Desktop.

Select an option

Save rogeriotaques/b082afc443d180abce1afc8a679ac4f7 to your computer and use it in GitHub Desktop.
HestiaCP NginX Templates : Single and multi-tenant NodeJS apps
# ==========================================================
# DEFAULT CATCH-ALL VHOST FOR MULTI-TENANT SAAS
# Any unknown domain → routes to the NodeJs App (port 3000)
# Works with Cloudflare "Full" SSL mode
#
# /etc/nginx/conf.d/[SERVER-IP-ADDR].conf
#
# ==========================================================
# ----------------------------------------------------------
# HTTP (80)
# ----------------------------------------------------------
server {
listen [UPDATE-WITH-THE-SERVER-IP-ADDR]:80 default_server;
server_name _;
location / {
# No redirects on HTTP — CF handles HTTPS at the edge
proxy_set_header Host $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 http;
proxy_ssl_server_name on;
proxy_pass http://127.0.0.1:3000;
}
}
# ----------------------------------------------------------
# HTTPS (443)
# ----------------------------------------------------------
server {
listen [UPDATE-WITH-THE-SERVER-IP-ADDR]:443 ssl default_server;
server_name _;
# Use Hestia’s self-signed certificate
ssl_certificate /usr/local/hestia/ssl/certificate.crt;
ssl_certificate_key /usr/local/hestia/ssl/certificate.key;
# Important: Cloudflare Full allows this cert
# Avoid ANY redirect here
location / {
proxy_set_header Host $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 https;
proxy_set_header X-Forwarded-Ssl on;
proxy_ssl_server_name on;
proxy_pass http://127.0.0.1:3000;
}
# Error handling
location /error/ {
alias /var/www/document_errors/;
}
}

HestiaCP NginX Templates

Have a VPS running HestiaCP which should run a single or multi tenant Nodejs application? These are the templates that are gonna help you set it up out of the box! These templates were designed to just work, specially if you're running your servers behind CloudFlare.

Installing the templates

Copy these files into /usr/local/hestia/data/templates/web/nginx/, restart Nginx and you should already see the templates listed in the Backend Template option in the Advanced Options on your domain settings page.

Content of this Gist

For multi tenant apps.

  • multitenant-nodejs.tpl
  • multitenant-nodejs.stpl

For single tenant apps.

  • nodejs.tpl
  • nodejs.stpl
server {
listen %ip%:80;
server_name %domain% %alias%;
include %home%/%user%/conf/web/%domain%/nginx.conf_*;
return 301 https://%host%$request_uri;
}
server {
listen %ip%:443 ssl http2;
server_name %domain% %alias%;
ssl_certificate %ssl_pem%;
ssl_certificate_key %ssl_key%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
gzip on;
gzip_min_length 1100;
gzip_buffers 4 32k;
gzip_types image/svg+xml svg svgz text/plain application/x-javascript text/xml text/css;
gzip_vary on;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $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;
proxy_cache_bypass $http_upgrade;
proxy_pass http://127.0.0.1:3000;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*;
location ~ /\.ht { return 404; }
location ~ /\.svn/ { return 404; }
location ~ /\.git/ { return 404; }
location ~ /\.hg/ { return 404; }
location ~ /\.bzr/ { return 404; }
location ~ /\.db/ { return 404; }
location ~ /\.duckdb/ { return 404; }
location ~ /\.sqlite/ { return 404; }
}
server {
listen %ip%:80;
server_name %domain% %alias%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $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;
proxy_cache_bypass $http_upgrade;
proxy_pass http://127.0.0.1:3000;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
include %home%/%user%/conf/web/%domain%/nginx.conf_*;
location ~ /\.ht { return 404; }
location ~ /\.svn/ { return 404; }
location ~ /\.git/ { return 404; }
location ~ /\.hg/ { return 404; }
location ~ /\.bzr/ { return 404; }
location ~ /\.db/ { return 404; }
location ~ /\.sqlite/ { return 404; }
location ~ /\.duckdb/ { return 404; }
}
# HestiaCP Web NginX Template
# /usr/local/hestia/data/templates/web/nginx/nodejs.stpl
#
# This template enables a NodeJs app running on port :3000.
server {
listen %ip%:80;
server_name %domain% %alias%;
include %home%/%user%/conf/web/%domain%/nginx.conf_*;
return 301 https://%domain_idn%$request_uri;
}
server {
listen %ip%:443 ssl http2;
server_name %domain% %alias%;
ssl_certificate %ssl_pem%;
ssl_certificate_key %ssl_key%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
gzip on;
gzip_min_length 1100;
gzip_buffers 4 32k;
gzip_types image/svg+xml svg svgz text/plain application/x-javascript text/xml text/css;
gzip_vary on;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $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;
proxy_cache_bypass $http_upgrade;
proxy_pass http://127.0.0.1:3000;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*;
location ~ /\.ht { return 404; }
location ~ /\.svn/ { return 404; }
location ~ /\.git/ { return 404; }
location ~ /\.hg/ { return 404; }
location ~ /\.bzr/ { return 404; }
location ~ /\.db/ { return 404; }
location ~ /\.duckdb/ { return 404; }
location ~ /\.sqlite/ { return 404; }
}
# HestiaCP Web NginX Template
# /usr/local/hestia/data/templates/web/nginx/nodejs.tpl
#
# This template enables a NodeJs app running on port :3000.
server {
listen %ip%:80;
server_name %domain% %alias%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $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;
proxy_cache_bypass $http_upgrade;
proxy_pass http://127.0.0.1:3000;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
include %home%/%user%/conf/web/%domain%/nginx.conf_*;
location ~ /\.ht { return 404; }
location ~ /\.svn/ { return 404; }
location ~ /\.git/ { return 404; }
location ~ /\.hg/ { return 404; }
location ~ /\.bzr/ { return 404; }
location ~ /\.db/ { return 404; }
location ~ /\.sqlite/ { return 404; }
location ~ /\.duckdb/ { return 404; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment