Hey guys,
I am not quite sure if the term „Howto“ is the perfect description of what this post will be. It is more of a „How I did it“. 😉
It is about Pimatic, nginx, HTTP/2 and Let’s encrypt - pretty cool stuff, so let us get started.
It has been stated numerous times that Pimatic best resides behind a reverse proxy.
Given the limited amount of power (compared to a full blown server) I chose nginx (https://nginx.org/).
There a several ways to install nginx, important is: You will need one of the latest versions (1.10.* at the time of writing) to use HTTP/2 (which requires SSL, but I will cover that).
I have found a pretty good tutorial at the guys from Grav.
The tutorial is located here: https://getgrav.org/blog/raspberrypi-nginx-php7-dev
You do not have to follow all the steps, the most important part is where they tap into the testing branch of Raspbian - scroll down to Install PHP 7.0 and follow the instructions.
DO NOT INSTALL PHP7 (well, you can but it is not a requirement, maybe you are going to use nginx for something else?!?)
After that, follow the Installation of nginx 1.9 instructions, again leaving out all the stuff that has something to do with PHP7.
Important note: Make sure Pimatic is not running on port 80 during the installation. nginx itself will be started during the installation and the default server configuration is also set to port 80. 😉
You should follow the steps to create your own nginx configuration. For the time being, you can just copy the default configuration. The content of the file has to be modified anyways.
I have named mine „pimatic“ instead of „grav“, but it is up to you how you call it.
It is time to start the server. The server might already be running, so you can use:
sudo service nginx reload
to reload the configuration.
If the server is not running, you can start it with:
sudo service nginx start
The default configuration sets the document root to /var/www/html/ - place a HTML file into that folder and see if you can open it in your browser.
nginx is running fine? Good job!
You want nginx to act as a reverse proxy but that means you have to modify the configuration slightly. 😉
The inspiration of the configuration came from https://forum.pimatic.org/topic/1298/solved-pimatic-with-nginx
Take a look at the three lines for Socket.IO Support - it will not work without them. Thanks to sweetpi (again ).
I will show you my modified configuration file and explain to you what it does.
At first, make sure both Pimatic and nginx are stopped:
sudo service pimatic stop && sudo service nginx stop
I access Pimatic from a subdomain and Pimatic was mapped to port 80 - the default port for HTTP connections.
Now the nginx reverse proxy should use that port, so you have to edit the Pimatic configuration and change it’s HTTP port to something else - I chose port 8080.
My complete configuration looks like this:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name pimatic;
root /var/www/pi.website.com;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /etc/letsencrypt/live/pi.website.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pi.website.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/letsencrypt/live/pi.website.com/fullchain.pem;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
# Socket.IO Support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Attention: I have altered the configuration, pretending my subdomain was pi.website.com - change it to fit your needs!
It will create two servers:
The first one listens on port 80 and redirect all requests to the second server which listens on port 443.
(Forwarding: https://bjornjohansen.no/redirect-to-https-with-nginx)
HTTP/2 (https://en.wikipedia.org/wiki/HTTP/2) requires SSL so it is enabled on the second server only.
The SSL configuration was created with this handy little tool: https://mozilla.github.io/server-side-tls/ssl-config-generator/
You have to change:
- The root path
- the ssl_certificate path
- the ssl_certificate_key path
- the ssl_dhparam path
- the ssl_trusted_certificate path and
- the proxy_pass (when your pimatic uses a different port then 8080
No worries, the files will be created by Let’s encrypt.
Just make sure you follow the naming convention of the folders: Always use the domain, in my case the subdomain, because that is where Let’s encrypt will put the certificates.
In the next step, I will be installing the Let’s encrypt script to generate the certificates for the domain(s).
I did this by cloning the repository from git into /home/pi/
cd /home/pi/ && git clone https://github.com/letsencrypt/letsencrypt
(You have to have git installed, use sudo apt-get install git if it is not available yet.)
Change into that folder and you will see a lot of files. They are specific to certain operating systems and sadly they do not work on Raspbian.
That is not a problem because we can generate the certificate veeeerrrry easily.
The command is easy enough:
./certbot-auto certonly --standalone --rsa-key-size 4096 -d pi.website.com
For those with multiple domains: the „-d“ can be used multiple times => […]096 -d pi.website.com -d pi2.website.com -d pi3.website.com
Make sure the first domain matches the folder name of the nginx configuration. I have not tried it with multiple domains but the certbot will create a new folder and nginx might not find the certificates if you do not pay attention to this.
After the generation is completed, check the contents of the folder /etc/letsencrypt/live/pi.website.com/ - there should be four files in it (cert.pem, chain.pem, fullchain.pem, privkey.pem).
If you can not open that folder, try sudo ls /etc/letsencrypt/live/pi.website.com/
Almost done!
There is one step left to do: The file for the ssl_dhparam of the nginx configuration has to be created manually.
openssl dhparam -out dhparam.pem 2048
You can run the command on your Pi but it will be slow as hell.
It is just a binary file, you can create it somewhere else and simply move it to the Pi afterwards. Make sure you upload it to the right folder.
The Let’s encrypt certificates have to be renewed manually. There is a script that does the job: https://forum.pimatic.org/topic/1037/pimatic-with-trusted-ssl-certificate-from-letsencrypt/10
I chose the much simpler and edited my crontab to let the Pimatic execute the renewal script. I took this from https://blog.doenselmann.com/nginx-und-lets-encrypt-auf-raspberry-pi/
Edit the crontab:
sudo crontab -e
and add the following line:
@monthly /home/pi/letsencrypt/letsencrypt-auto renew && systemctl restart nginx.service
If everything worked fine, you can finally start pimatic and nginx:
sudo service pimatic start
sudo service nginx start
Now try to open https://pi.website.com in your browser. 😃
(if the above link does not work, chances are good that you are not the owner of website.com )
Do not forget to configure your router, the port 443 has to be forwarded to your Pi.
It is like I said: this is not a classic „Howto“ that is guaranteed to work out of the box for all of you folks.
If you have any comments, questions, whatever - I am willing to help out. Chances are good that this is not even the best way to do it. Comment right away. 😃
Have fun,
Dominik