I assume you started from my guide for hardened Raspberry Pi.
First steps
I like Nginx for the performances and the simple configuration file.
sudo apt update
sudo apt install nginx-light
Check the service is running.
systemctl status nginx
wget -O /dev/null http://127.0.0.1:80/
Add firewall rule to allow connection.
ufw allow 80/tcp
ufw allow 443/tcp
Self signed configuration
As the Deffie-Hellman generation is quite long on a Raspberry Pi, I generally download my dhparam.pem from the Public Deffie-Hellman Parameter Service.
curl https://2ton.com.au/getprimes/random/dhparam/4096 > dhparam.pem
sudo cp dhparam.pem /etc/nginx/
rm dhparam.pem
Let’s generate a self-signed certificate to get started.
openssl req -newkey rsa:2048 -nodes -keyout self-signed.key -x509 -days 3650 -out self-signed.pem
sudo cp self-signed.* /etc/nginx
sudo chmod g-rwx,o-rwx /etc/nginx/*.key
rm self-signed.*
Put your site configuration file in /etc/nginx/sites-available and enable it by setting a symbolic link in /etc/nginx/sites-enabled.
# Port 80/HTTP will redirect all traffic to 443/HTTPS
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name <website host>;
server_tokens off;
return 301 https://$host$request_uri;
}
# Main server on port 443/HTTPS
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name <website host>;
server_tokens off;
ssl_certificate /etc/nginx/self-signed.pem;
ssl_certificate_key /etc/nginx/self-signed.key;
ssl_trusted_certificate /etc/nginx/self-signed.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
index index.php index.html index.htm;
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
root /var/www/html/<website folder>;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
# Security HTTP headers
add_header Content-Security-Policy "default-src 'self'";
add_header Permissions-Policy "camera=(),fullscreen=(),microphone=()";
add_header Referrer-Policy "no-referrer";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "sameorigin";
add_header X-XSS-Protection "1; mode=block";
}
}
When you are happy with your config, restart your Nginx server and check everything is ok.
sudo systemctl restart nginx
systemctl status nginx
The configuration file is mostly generated from Mozila SSL Config Generator.
I use the following sites to verify my SSL configuration: Qualys SSL Labs, Immuniweb SSL and cryptcheck.fr.
For the HTTP security, I check using Mozilla Observatory, Immuniweb WebSec and securityheaders.com.
Installing Let’s Encrypt
Let’s Encrypt certbot will generate valid certificate for you.
sudo apt install certbot python3-certbot-nginx
Running certbot.
sudo certbot --nginx
Test for a renewal
sudo certbot renew --dry-run
Edit /etc/crontab and add the following line for automatic renewal of the certificates.
0 0,12 * * * root sleep 1486 && certbot renew -q