HTTPS on Raspberry Pi
This post is about how to set up https on a raspberry pi device, based on my recent experience
Installing certbot on Raspberry Pi
What helped me a lot is a discussion on this issue. And particularly a comment. In case the issue will be harder to find I'll leave it here:
- Uninstall all previous broken package/dependencies
add deb http://mirrordirector.raspbian.org/raspbian/ testing main contrib non-free rpi
to/etc/apt/sources.list
apt-get update
apt-get install certbot
For me the part with updating was not enough, with the installation of certbot there was a warning about incompatible packages in the system, so I upgraded and the problem was gone for good.
Generate certificates
To generate certificates with certbot
$ sudo certbot certonly -a webroot --webroot-path=/var/www/html -d example.com -d www.example.com
Now certbot will ask a lot of questions. After this, it prints to console IMPORTANT NOTES
block and you can check that certs were generated by issuing this command
$ sudo ls -l /etc/letsencrypt/live/your_domain_name
For even stronger security recommended generating the Diffie-Hellman group.
This will take a reeeeeeeaaaaaaaaalllllyyyyy long time
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Configure Nginx
It is recommended to create a snippets
folder in nginx folder $ mkdir /etc/nginx/snippets
. Here we can place reusable parts of the code that can be included in the final configuration file. Lets call this file /etc/nginx/snippets/ssl-params.conf
# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now. You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
# add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
# ssl_dhparam /etc/ssl/certs/dhparam.pem;
Uncomment the last line if you generated Diffie-Hellman group from the previous section.
Next, for purpose of this tutorial we'll edit the default nginx configuration file /etc/nginx/sites-available/default
. But before, let's backup this file cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
This config will be in two parts - first: redirect all traffic from HTTP to HTTPS
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
The second block is about actual SSL configuration
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include snippets/ssl-params.conf;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Above is a complete config for a static site with index.html
entry point that located in /var/www/html
Now, let's check nginx configuration file
$ sudo nginx -t
Reload Nginx config after making changes
$ sudo service nginx reload
Certificate auto-renewal
Letsenscript certifictes only last for 90 days, so it is recommended to renew certificates once in a while. A great tool for such tasks will be cron task manager that available without installation on many Unix systems by default.
To edit tasks list
$ sudo crontab -e
Add this line to file
30 2 * * * /usr/bin/certbot renew --noninteractive --renew-hook "/bin/systemctl reload nginx" >> /var/log/le-renew.log
Be careful, every user in a system have their own tasks list!
The Last
Some tips if you encounter any errors:
- Be sure to check that router from where raspberry gets internet access have open connections for port
443
- If nginx warns that it can't bind to port
80
, look at who is listening to that port with$ netstat -tunapl | grep 80
. I read that sometimes there was installed apache and they conflict with each other.
Great resource to check your site SSL certificate score is here - SSL Online Analyzer Tool
This article is greatly inspired by this, more in-depth publication from digitalocean Let's Enscript on Debian 8
The Last Last
This is some badass sites about HTTPS and DNS