Reference for Nginx Web Server install and configuration.
Nginx (pronounced "En Gin Ex") is my go-to web server for most applications except Wordpress.
Install on Ubuntu 22.04:
apt update
apt install nginx
systemctl enable nginx
systemctl start nginx
#Check Status
systemctl status nginx
#Check version
nginx -v
Browse to server IP and you should see "Welcome to Nginx" page.
The Remaining Snips assume you have PHP8.1 Installed. Follow these steps to install:
Install common modules:
apt install php8.1 php8.1-fpm php8.1-mysql php-common php8.1-cli php8.1-common php8.1-opcache php8.1-readline php8.1-mbstring php8.1-xml php8.1-gd php8.1-curl
systemctl start php8.1-fpm
systemctl enable php8.1-fpm
#Check Status is Active
systemctl status php8.1-fpm
Improve PHP Performance Settings:
nano /etc/php/8.1/fpm/conf.d/60-custom.ini
Add the following lines and save file:
; Maximum amount of memory a script may consume. Default is 128M
memory_limit = 512M
; Maximum allowed size for uploaded files. Default is 2M.
upload_max_filesize = 20M
; Maximum size of POST data that PHP will accept. Default is 2M.
post_max_size = 20M
; The OPcache shared memory storage size. Default is 128
opcache.memory_consumption=256
; The amount of memory for interned strings in Mbytes. Default is 8.
opcache.interned_strings_buffer=32
Save File
systemctl reload php8.1-fpm
Ready to contine with rest of Nginx Installation
PHP 8.1 is included in the Ubuntu 22.04 repo. To install the latest PHP version, follow this:
apt update && apt upgrade -y
add-apt-repository ppa:ondrej/php
apt update
apt install -y php8.2 php8.2-cli php8.2-common php8.2-fpm php8.2-mysql php8.2-zip php8.2-gd php8.2-mbstring php8.2-curl php8.2-xml php8.2-bcmath php8.2-opcache php8.2-readline
systemctl start php8.2-fpm
systemctl enable php8.2-fpm
#Check Status is Active
systemctl status php8.2-fpm
Follow other steps under the 8.1 section to enable php-fpm and modify default config file.
Start by removing default "Welcome to Nginx" site:
rm /etc/nginx/sites-enabled/default
Create new configuration file for your site.
In folder /etc/ngnix/conf.d/example.com.conf
server {
listen 80;
listen [::]:80;
server_name www.example.com;
root /var/www/dev/;
index index.php index.html;
access_log /var/log/nginx/example_access.log;
error_log /var/log/nginx/example_error.log;
location / {
try_files $uri $uri/ /index.php;
}
location ~ ^/(.+\.php)$ {
try_files $uri =404;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
Replace "example' sections above
apt install certbot python3-certbot-nginx
certbot --nginx --agree-tos --no-eff-email --redirect --hsts --staple-ocsp --email [email protected] -d example.com,www.example.com
Replace "example" words above.
The below assumes you have purchased an SSL Certificate from an authority. I ususally purchase Wildcard Certificates for my projects so I can use dev.domain.com, www.domain.com, mail.domain.com, etc... and use the same Certificate on all. Here are the general steps I use to secure my Nginx web servers with a valid SSL Certificate (not tested with self-signed, but should work).
openssl req -newkey rsa:2048 -keyout example.key -out example.csr
cat example.crt intermediate.crt root.crt >> example_bundle.crt
cp example_bundle.crt /etc/ssl/certs/
cp example.key /etc/ssl/private/
openssl dhparam -out /etc/ssl/private/dhparams.pem
This will take a LONG time to create the file - grab a drink and come back in 10.
cd /etc/nginx/conf.d
#REMOVE DEFAULT SITE
rm /etc/nginx/sites-enabled/default
# BACKUP EXISTING SITE IF IT EXISTS
mv example.conf example.conf.bak
# EDIT NEW CONF FILE
nano example.conf
Now edit this text and replace "example" with your domain.
##### COMPLETE NGINX SSL SAMPLE CONFIG FILE #####
# RETURN 404 WHEN NO HOSTNAME MATCH - THIS SECTION CAN ONLY BE ON ONE SITE
server {
listen 80 default_server;
server_name _;
return 404;
}
server {
listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/ssl/certs/example_bundle.crt;
ssl_certificate_key /etc/ssl/private/example.key;
return 404;
}
# HTTP REDIRECT
server {
if ($host = example.com) {
return 301 https://example.com$request_uri;
}
if ($host = www.example.com) {
return 301 https://example.com$request_uri;
}
listen 80;
server_name www.example.com example.com;
access_log /var/log/nginx/example.com_access.log;
error_log /var/log/nginx/example.com_error.log;
}
# HTTPS SITE CONFIG
server {
server_name www.example.com example.com;
root /var/www/example.com/;
index index.php index.html index.htm;
access_log /var/log/nginx/example.com_access.log;
error_log /var/log/nginx/example.com_error.log;
location / {
try_files $uri $uri/ /index.php;
}
location ~ ^/(.+\.php)$ {
try_files $uri =404;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
listen 443 ssl;
ssl_certificate /etc/ssl/certs/example_bundle.crt;
ssl_certificate_key /etc/ssl/private/example.key;
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
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:DHE-RSA-CHACHA20-POLY1305;
ssl_dhparam /etc/ssl/private/dhparams.pem;
add_header Strict-Transport-Security "max-age=63072000" always;
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1;
}
nginx -t
systemctl restart nginx
If process is killed or stopped, automatically have it restart:
mkdir -p /etc/systemd/system/nginx.service.d/
nano /etc/systemd/system/nginx.service.d/restart.conf
Add lines to file and save:
[Service]
Restart=always
RestartSec=5s
Defalut for restart is 100ms which is too fast - recommend at least a few seconds minimum.
Restart daemon and test:
systemctl daemon-reload
pkill nginx
# Wait 5+ seconds
systemctl status nginx
Service should show active again.
Complete
Honerable Mentions: Thanks to,
Mozilla's SSL Config Generator https://ssl-config.mozilla.org/
Google, Digital Ocean, LinuxBabe