vastly expanded nginx config

This commit is contained in:
Joby 2024-10-22 20:17:00 -06:00
parent 0144d4966e
commit ef61e746e7
9 changed files with 139 additions and 41 deletions

View file

@ -39,7 +39,7 @@ main_web_root="/var/www/$domain"
sudo mkdir -p "$main_web_root"/{_main/www,subdomains,logs}
# Create the user with the web root as home directory and add to www-data and websftpusers groups
sudo useradd -m -d /var/www/$domain -s /usr/sbin/nologin -U -G www-data,websftpusers $username
sudo useradd -m -d /var/www/$domain -s /bin/false -U -G www-data,websftpusers $username
echo "$username:$password" | sudo chpasswd
# Set ownership and permissions for the main site directory
@ -47,6 +47,11 @@ sudo chown -R "$username:www-data" "$main_web_root"
sudo find "$main_web_root" -type d -exec chmod 2750 {} +
sudo find "$main_web_root" -type f -exec chmod 640 {} +
# Set ownership and permissions for the main web root
# SFTP chroot requires the user's home directory to be owned by root and not writable by others
sudo chown "root:www-data" "$main_web_root"
sudo chmod 755 "$main_web_root"
# Set ownership and permissions for the logs directory
sudo chown root:www-data "$main_web_root/logs"
sudo chmod 755 "$main_web_root/logs"
@ -104,9 +109,6 @@ sudo cp "$(realpath "site-config.conf")" "$nginx_config"
# replace $DOMAIN placeholder in the nginx config file
sudo sed -i "s/\$DOMAIN/$domain/g" "$nginx_config"
# replace $MAIN_WEB_ROOT placeholder in the nginx config file
sudo sed -i "s#\$MAIN_WEB_ROOT#$main_web_root#g" "$nginx_config"
# Enable the site
sudo ln -sf "$nginx_config" /etc/nginx/sites-enabled/

29
install/nginx-conf.sh Normal file
View file

@ -0,0 +1,29 @@
#!/bin/bash
# Check if script is run as root
if [ "$EUID" -ne 0 ]; then
echo "Please run as root or with sudo"
exit 1
fi
# Define source and destination directories
SRC_DIR="nginx-conf"
DEST_DIR="/etc/nginx/conf.d"
# Check if source directory exists
if [ ! -d "$SRC_DIR" ]; then
echo "Source directory '$SRC_DIR' not found"
exit 1
fi
# Create destination directory if it doesn't exist
mkdir -p "$DEST_DIR"
# Copy all .conf files
echo "Copying configuration files..."
cp -v "$SRC_DIR"/*.conf "$DEST_DIR/"
# Set proper permissions
echo "Setting permissions..."
chown root:root "$DEST_DIR"/*.conf
chmod 644 "$DEST_DIR"/*.conf

View file

@ -0,0 +1,26 @@
# Cloudflare IP Ranges
set_real_ip_from 173.245.48.0/20;
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 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
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 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
# Pull real IP from Cloudflare
real_ip_header CF-Connecting-IP;

View file

@ -0,0 +1,3 @@
# Basic rate limiting zones
limit_req_zone $binary_remote_addr zone=general:10m rate=50r/s;
limit_req_zone $binary_remote_addr zone=php:10m rate=10r/s;

View file

@ -0,0 +1,6 @@
# SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 24h;

View file

@ -0,0 +1,8 @@
# Security headers
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(),microphone=(),camera=(),payment=(),usb=(),battery=(),display-capture=()" always;
server_tokens off;

View file

@ -0,0 +1,6 @@
# Turn on gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

View file

@ -0,0 +1,10 @@
# Basic PHP configuration
location ~ \.php$ {
limit_req zone=php burst=20 nodelay;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

View file

@ -1,3 +1,4 @@
# HTTP redirect
server {
listen 80;
listen [::]:80;
@ -5,75 +6,82 @@ server {
return 301 https://$host$request_uri;
}
# HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name .$DOMAIN;
# SSL Configuration
# SSL certificates
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# Determine the subdomain and set the root accordingly
# subdomains are the default, so that we get 404s for nonexistant subdomains
# Apply general rate limit
limit_req zone=general burst=100 nodelay;
# Content Security Policy (needs to be per-domain)
add_header Content-Security-Policy "
default-src 'self' *.$DOMAIN;
script-src 'self' 'unsafe-inline' 'unsafe-eval' *.$DOMAIN;
style-src 'self' 'unsafe-inline' *.$DOMAIN;
img-src 'self' data: *.$DOMAIN;
font-src 'self' data: *.$DOMAIN;
connect-src 'self' *.$DOMAIN;
frame-src 'self' *.$DOMAIN;
media-src 'self' *.$DOMAIN;
object-src 'none';
base-uri 'self';
form-action 'self' *.$DOMAIN;
" always;
# Subdomain handling
set $subdomain '';
set $full_root $MAIN_WEB_ROOT/_main/www;
set $access_log_path $MAIN_WEB_ROOT/logs/$subdomain.access.log;
set $error_log_path $MAIN_WEB_ROOT/logs/$subdomain.error.log;
set $full_root "/var/www/$DOMAIN/_main/www";
set $access_log_path "/var/www/$DOMAIN/logs/main.access.log";
set $error_log_path "/var/www/$DOMAIN/logs/main.error.log";
if ($host ~* ^([^.]+)\.$DOMAIN$) {
set $subdomain $1;
set $full_root $MAIN_WEB_ROOT/subdomains/$subdomain/www;
set $access_log_path $MAIN_WEB_ROOT/logs/_main.access.log;
set $error_log_path $MAIN_WEB_ROOT/logs/_main.error.log;
set $full_root "/var/www/$DOMAIN/subdomains/$subdomain/www";
set $access_log_path "/var/www/$DOMAIN/logs/$subdomain.access.log";
set $error_log_path "/var/www/$DOMAIN/logs/$subdomain.error.log";
}
root $full_root;
# Index file names
# Basic settings
index index.html index.htm index.php;
client_max_body_size 20M;
# Try files first, then use the router.php file if it exists
# Block .ht* files
location ~ /\.ht {
deny all;
}
# Main location block
location / {
try_files $uri $uri/ @router;
}
# Use the router.php file for all nonexistant file requests if it exists
# Router handling
location @router {
if (!-f $document_root/router.php) {
return 404;
}
limit_req zone=php burst=20 nodelay;
fastcgi_pass unix:/var/run/php/php-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/router.php;
}
# PHP Configuration
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
# Static file handling
location ~* ^.+\.((?!php).)*$ {
expires 30d;
add_header Cache-Control "public, no-transform";
try_files $uri $uri/ =404;
}
# Deny access to .ht* files
location ~ /\.ht {
deny all;
}
# Additional config options
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
client_max_body_size 20M;
# Log to both default location and custom site directory, named by subdomain
# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
access_log $access_log_path;
error_log $error_log_path;
}
}