Setup Letsencrypt SSL on raspberry pi

I love letsencrypt. It’s free SSL, it’s saver because of the auto-renewal and it’s so easy to setup. No more emailing around validating company name and whatnot.

If you’ve followed the previous steps you would not have installed git, check with git --version When it gives an error install git first with sudo apt-get install -y git

Now get the letsencrypt software and prepare the folder which letsencrypt will use.

sudo git clone https://github.com/certbot/certbot /opt/letsencrypt
sudo mkdir /var/www/letsencrypt
sudo chown www-data:www-data /var/www/letsencrypt

Add the first part of the letsencrypt config to nginx sudo nano /etc/nginx/sites-enabled/example.com
Before the final } add this:

location /.well-known/acme-challenge {
    root /var/www/letsencrypt;
}

And reload nginx sudo nginx -t && sudo service nginx reload

Getting the ssl certificate

So now we can generate and validate the ssl certificates. With the command below.
The email-address is used only for checks and warnings so I recommend an email which you do check. And of course change the domain. We will get a certificate for both www and non-www domain.

sudo /opt/letsencrypt/certbot-auto certonly -a webroot --webroot-path=/var/www/letsencrypt/ --rsa-key-size=4096 -m letsencrypt@example.com -d example.com -d www.example.com

When running this the first time It might take a long time, just be patient. When it is done we add the certificates to the nginx configuration: sudo nano /etc/nginx/sites-enabled/example.com

listen 443 ssl default_server;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

sudo service nginx reload

Test if ssl is working on both www and non-www. If it’s working then the next step is forcing ssl all the time.

replace:

server {
    listen 80;
    server_name example.com www.example.com;

And replace it with:

server {
    listen      80;
    server_name home.janw.me www.home.janw.me;
    rewrite     ^   https://$server_name$request_uri? permanent;
}
server {
    listen 443 ssl;
    server_name home.janw.me www.home.janw.me;

    ssl_certificate /etc/letsencrypt/live/home.janw.me/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/home.janw.me/privkey.pem;

As usual reload sudo nginx -t && sudo service nginx reload

Autorenewel

certbot renew

https://caatest.co.uk/home.jwon.nl
https://michael.lustfield.net/nginx/getting-a-perfect-ssl-labs-score

Installing Mysql/MariaDB on a Rapsberry Pi

Here we will install MariaDB. The performance is better and it’s more open source. There are a few differences but nothing you will notice during normal daily use.

Installing mariadb:

sudo apt install -y mariadb-server-10.1

Alternative if you don’t want to get out of your comfort zone use mysql.
Keep in mind the rest of these steps might vary a bit.

sudo apt install -y mysql-server

After it’s done check the version with mysql --version. It should be 10.1.23-MariaDB or higher.

Securing the installation

The biggest thing e need is a root password. We will do that and some other things.

sudo mysql_secure_installation

This will give the following steps.

  1. Set a long safe password.
  2. Remove anonymous users Yes
  3. Disallow root login remotely Yes
  4. Remove test database and access to it Yes
  5. Reload privilege tables now Yes

Creating a database and user

To create a database we are going to login to MySQL with the following command.
Because we use sudo and root we will not need to enter a password.

sudo mysql -uroot

We are going to create a database and a user and connect them.

CREATE DATABASE raspimain_db;

Next we create a user, be sure to replace the password!

CREATE USER 'raspimain_user'@'localhost' IDENTIFIED BY '%%SAFE_PASSWORD%%';

Then we need to connect the user to that database.

GRANT ALL PRIVILEGES ON `raspimain_db`.* TO `raspimain_user`@`localhost`;

Next we 2 commands are pretty self explanatory.

FLUSH PRIVILEGES;
EXIT;

To test if it worked login in to mysql with that user.

mysql -u raspimain_user raspimain_db -p

This time use the password you used to create the user. Check if the raspimain_db is in the list of databases.

SHOW DATABASES;

If it is use EXIT; to exit the mysql promt.

Installing Nginx on a Rapsberry Pi

In this step we are going to install a webserver (nginx). For those who are bit familiar with webservers you might wonder why we are not using apache? I myself are far more familiar with Apache but Nginx just has better performance. And on the not that powerful pi that is important.

Install Nxing

Like with php we want a newer version. So again we will use the buster source. It should install 1.13. To install nginx run the command:

sudo apt-get install -y -t buster nginx

Check the version nginx -v it should be version nginx/1.13.12 or higher

To test if it works enter the IP address in the browser. You should see this page.

If you see an error most likely IPv6 isn’t supported. Open the nginx config file.

sudo nano /etc/nginx/sites-enabled/default

At the top you should see these lines

    listen 80 default_server;
    listen [::]:80 default_server;

Change them to:

    listen 80 default_server;
    #listen [::]:80 default_server;

Save then restart nginx.

sudo nginx -t && sudo service nginx reload

Then test the page again in the browser.

Setting up a site with php and url

First we will do some global settings open: sudo nano /etc/nginx/conf.d/99-custom.conf
Add the following line, we increase the allowed upload sizes.

client_max_body_size 64M;

Note: for the example I use example.com replace that with the url you want to use. If you don’t have the url setup yet you can add it to you own host file. Or instead of the url use the IP-address of the Pi.

We will create our own vhost files. PS I’ll be using example.com but use whatever you intend to use. Create the vhost file: sudo nano /etc/nginx/sites-enabled/example.com.conf

server {
    listen 80;

    server_name example.com;
    root /var/www/example.com/public_html;

    index index.php index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_intercept_errors on;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
    }
}

Next create the folders needed. Set the rights of those files and add a test page.

sudo mkdir -p /var/www/example.com/public_html
sudo touch /var/www/example.com/public_html/index.php
sudo chown www-data:www-data /var/www/example.com -R
sudo nginx -t && sudo service nginx reload

In that file add sudo nano /var/www/example.com/public_html/index.php

<?php
phpinfo();

Save and reload the webpage you should see this: phpinfo page if all is setup correctly

Now we have a basic and functioning webserver with php.
For security sake delete the index.php file

sudo rm /var/www/example.com/public_html/index.php 

Permissions.

So far we use sudo for pretty much everything. This is fine.
After the initial setup most of the work has to be done in /var/www/*.
These files are owned by the nginx user. This also is normal and fine.
We can change nginx to use the pi user.

That way you can avoid the sudo for every small change.

The big upside is no more sudo and changing owners of files.
The downside is that every file pi can access nginx also can access.
This is a security risk of course.

Use this at own risk. The rest of the guide(s) acts as if you didn’t do this.

Open file sudo nano /etc/php/7.2/fpm/pool.d/zzz-users.conf and add.

user = pi
group = pi
listen.owner = pi
listen.group = pi

And reload php sudo service php7.2-fpm restart

Next open sudo nano /etc/nginx/nginx.conf on line 1 the user to pi
Restart nginx sudo nginx -t && sudo service nginx restart

Last step is really making pi the owner of all webfiles: sudo chown pi:pi /var/www/ -R

Next we will install mysql and configure a database.