Skip to content

Instantly share code, notes, and snippets.

@shey
Last active October 7, 2024 02:29
Show Gist options
  • Save shey/c668b7ff7139925e7ae6bf5053a9edf7 to your computer and use it in GitHub Desktop.
Save shey/c668b7ff7139925e7ae6bf5053a9edf7 to your computer and use it in GitHub Desktop.
Modern Nginx configs for Rails with Certbot support
## This file is managed by ansible. Local edits will be overwritten
## /etc/nginx/sites-available/default
## Grossness used to accommodate ansible automation --revisit.
## modified default server configuration to support cert-bot
server {
listen 80 default_server;
listen [::]:80 default_server;
# to support certbot
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/letsencrypt;
}
root /usr/share/nginx/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
}
#!/bin/bash
# /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh
if nginx -t; then
sudo systemctl reload nginx
if [ $? -eq 0 ]; then
echo "Nginx reloaded successfully."
else
echo "Failed to reload Nginx."
exit 1
fi
else
echo "Nginx configuration is invalid. Aborting reload."
exit 1
fi
# This file is managed by ansible. Local edits will be overwritten
# /etc/nginx/nginx.conf
user www-data;
worker_processes 2;
worker_rlimit_nofile 40000; # limit on the maximum number of open files
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
# modified version, original: https://www.velebit.ai/blog/nginx-json-logging/
log_format custom escape=json '{"source": "nginx", "time": "$time_iso8601", "resp_body_size": $body_bytes_sent, "host": "$http_host", "address": "$remote_addr", "request_length": $request_length, "method": "$request_method", "uri": "$request_uri", "status": $status, "user_agent": "$http_user_agent", "referrer" : "$http_referer", "resp_time": "$request_time", "upstream_addr": "$upstream_addr"}';
sendfile on;
tcp_nopush on;
tcp_nodelay on;
client_body_timeout 12;
client_header_timeout 12;
keepalive_timeout 15;
send_timeout 10;
client_body_buffer_size 128k;
gzip off;
server_names_hash_bucket_size 64;
types_hash_max_size 2048;
types_hash_bucket_size 64;
server_tokens off;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
# This file is managed by ansible. Local edits will be overwritten
# /etc/nginx/sites-available/rails
upstream unicorn {
server 127.0.0.1:3000 fail_timeout=0;
}
#########################################################
## Rate limiting Zone Definition
#########################################################
limit_req_zone $binary_remote_addr zone=zone_request_limit_second:10m rate=8r/s;
limit_req_zone $binary_remote_addr zone=zone_request_limit_minute:10m rate=50r/m;
server {
listen 155.138.128.26:80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 155.138.128.26:443 ssl http2;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
server_name httpscout.io;
client_max_body_size 1M;
access_log /var/log/nginx/lrt.access.log custom;
error_log /var/log/nginx/lrt.error.log notice;
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
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 $scheme;
proxy_set_header X-Request-Start "t=${msec}";
proxy_redirect off;
#########################################################
## Buffers
#########################################################
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_buffering off;
#########################################################
## Rate limiting
#########################################################
limit_req zone=zone_request_limit_second burst=10 nodelay;
limit_req zone=zone_request_limit_minute burst=50 nodelay;
limit_req_status 429;
proxy_pass http://unicorn;
}
# I know this is gross, but I rather
# do this now, and come back to the
# server declarations later. this is
# better than nothing
# hostname must match
if ($host !~* ^(httpscout.io)$ ) {
return 444;
}
# avoid sending upstream to the app.
location ~ (\.php|\.aspx|\.asp|myadmin) {
return 404;
}
# Use Nginx to serve robots.txt
location ~ ^/(robots.txt|sitemap.xml.gz|favicon.ico) {
root /home/rails/lrt/current/public;
}
# Use Nginx to serve precompiled assets
location ~ ^/(assets)/ {
root /home/rails/lrt/current/public;
# Uncomment to enable caching headers
expires max;
add_header Cache-Control private;
}
# to support certbot (i think?)
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/letsencrypt;
}
# All error pages map to 500
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/rails/lrt/current/public;
}
}
## This file is managed by ansible. Local edits will be overwritten
## /etc/nginx.conf/conf.d/ssl.conf
# derived from https://ssl-config.mozilla.org/
ssl_protocols TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_certificate /etc/letsencrypt/live/httpscout.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/httpscout.io/privkey.pem;
ssl_session_tickets off;
ssl_prefer_server_ciphers off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment