HOWTO: Setup Redis Server with SSL for use with AI2

This Guide/Tutorial will show you how to setup a Redis Server (backend for CloudDB) with SSL, 

so that you can tick the SSL checkbox in AI2.


I would not have been able to achieve this without the invaluable help from Jeff Schiller, MIT; many thanks for all the fish ;)

To mis-quote Jeff:

"The normal Redis client/server doesn’t know how to do SSL, but the CloudDB component already knows how to use SSL, just check the box"


This means we have very little to do in AI2 with the CloudDB, but quite a lot to do on the server. You will see how to:


For the server, I used a shiny, brand new VPS (virtual private server) from IONOS, at the stunning price of £1 per month. I went for the Ubuntu 18.04 LTS Server. This means that nearly all the work below is done on the command line, and assumes that you have:


The only quirk I found with the IONOS VPS was that you set firewall rules in the IONOS control panel, not on the server, I had already setup ufw on the server when I found this out, so am using both. (ufw will need to replicate what is set on IONOS). Your server may not have this extra requirement, so just use ufw.

On my system, I was able to complete most of the work as the admin user, but on a couple of occasions I had to change to the root user. If you run a sudo command and get "Permission Denied" then go to root by:

sudo su -


[SYSTEM]


[FIREWALL]

Ionos Control Panel

Set the following  rules:

Allow All xxxx OpenSSH (replace xxxx with your chosen port, default is 22, I use a custom port to minimise hacking attempts)

Allow All 6379 Redis

Allow All 6381 Redis SSL

Allow All 80 Apache

Allow All 443 Apache SSL


To begin, open a terminal (puTTy if you are on Windows), ssh into the server with your admin user (sudo permissions) and password:

ssh tim@<server IP>

Now best to update the server

sudo apt-get update

sudo apt-get upgrade

Before we forget, setup ufw

sudo apt install ufw

sudo ufw allow OpenSSH

sudo ufw allow 6379/tcp

sudo ufw allow 6381/tcp

sudo ufw allow 80/tcp

sudo ufw allow 443/tcp

sudo ufw enable


[REDIS]

Now install the redis server, which we will build from sources

sudo apt-get install build-essential

wget http://download.redis.io/redis-stable.tar.gz

tar xvzf redis-stable.tar.gz

cd redis-stable

make

sudo make install

Test the server is running:

redis-server

CTRL+C to quit

Configure the redis server:

sudo mkdir -p /etc/redis

sudo mkdir -p /var/redis

sudo mkdir -p /var/redis/6379

sudo cp /redis-stable/utils/redis_init_script /etc/init.d/redis_6379

sudo cp /redis-stable/redis.conf /etc/redis/6379.conf

You will need to set a strong password, because redis is not designed to be directly exposed to the internet

openssl rand 40 | openssl base64 -A

Edit the redis configuration file and check each of these settings:

sudo nano /etc/redis/6379.conf


#~~~~~~~~~~~~~~~~~~~~~~

#bind 127.0.0.1                    # << !important comment out to allow external access

protected-mode no                  # << we are using a password

port 6379                          # << default

timeout 0                          # << default

daemonize yes                      # << means redis will start up in background

supervised no                      # << default

pidfile /var/run/redis_6379.pid    # << default

loglevel notice                    # << default

logfile /var/log/redis_6379.log    # << the usual place for logs

dir /var/redis/6379                # << !important

requirepass <your password>        # << added security

#~~~~~~~~~~~~~~~~~~~~~~

You can then apply the configuration and start the redis server

sudo update-rc.d redis_6379 defaults

sudo /etc/init.d/redis_6379 start

To test that all is well run the redis-cli and ping the server. you should get a PONG back. Type quit to quit back to the command line.

redis-cli -a <your password>


#~~~~~~~~~~~~~~~~~~~~~~

127.0.0.1:6379>ping

PONG #response

127.0.0.1:6379>quit

#~~~~~~~~~~~~~~~~~~~~~~


[STUNNEL]

A good idea to update the server again, then we can install stunnel4

sudo apt-get update

sudo apt-get upgrade

sudo apt install stunnel4

stunnel will not start with the server by default, so we need to edit its settings file to make this happen. Look for ENABLED=0 in the following file, and change it as follows:

sudo nano /etc/default/stunnel4


#~~~~~~~~~~~~~~~~~~~~~~

ENABLED=1

#~~~~~~~~~~~~~~~~~~~~~~

Configure the conf file for stunnel as follows:

sudo nano /etc/stunnel/redis-server.conf


#~~~~~~~~~~~~~~~~~~~~~~

[virtual]

cert = /etc/stunnel/private.pem

accept = <your server's external IP>:6381

connect = localhost:6379

#~~~~~~~~~~~~~~~~~~~~~~


[SUB DOMAIN]

In order to provide a "target" for the SSL certificate, I setup a sub domain through my domain holder/provider, pointing it at the IP address of the server. This will take @ 1 hour to propogate across the internet's DNS routers. No configuration on the server is required. Apart from then being able to create an SSL certificate using the sub domain , it means you can use the sub domain instead of the IP address in your cloudDB setup.


[CERTIFICATE]

To create the certificate needed for SSL we use LetsEncrypt. Install as follows:

sudo apt-get update && sudo apt-get install software-properties-common

sudo add-apt-repository universe && sudo add-apt-repository ppa:certbot/certbot

sudo apt-get update && sudo apt-get install certbot python-certbot-apache


NOTE: for Ubuntu 20.04 LTS the ppa is no longer available, however there is a snap package in Ubuntu that can be used. See the following link for further information:

Certbot Snap Package on 20.04


Now run certbot to generate the certificate and the key:

sudo certbot certonly


#~~~~~~~~~~~~~~~~~~~~~~


How would you like to authenticate with the ACME CA?

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

1: Apache Web Server plugin (apache)

2: Spin up a temporary webserver (standalone)

3: Place files in webroot directory (webroot)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 2



Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 2

Plugins selected: Authenticator standalone, Installer None

Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'

to cancel): <your domain name (for your server)>


Certificate Info:

Obtaining a new certificate

Performing the following challenges:

http-01 challenge for <your domain name (for your server)>

Waiting for verification...

Cleaning up challenges


IMPORTANT NOTES:

 - Congratulations! Your certificate and chain have been saved at:

   /etc/letsencrypt/live/<your domain name (for your server)>/fullchain.pem

   Your key file has been saved at:

   /etc/letsencrypt/live/<your domain name (for your server)>/privkey.pem

   Your cert will expire on 2020-05-25. To obtain a new or tweaked

   version of this certificate in the future, simply run certbot

   again. To non-interactively renew *all* of your certificates, run

   "certbot renew"

 - If you like Certbot, please consider supporting our work by:


   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate

   Donating to EFF:                    https://eff.org/donate-le


#~~~~~~~~~~~~~~~~~~~~~~


Finally, we need to combine the certificate and the key to one file, and put this in the path we identified in the stunnel conf file:

sudo cat /etc/letsencrypt/live/<your domain name>/fullchain.pem /etc/letsencrypt/live/<your domain name>/privkey.pem > /etc/stunnel/private.pem

You can now start stunnel

sudo /etc/init.d/stunnel4 start


That should be it on the server, now all that is needed is to enter the correct credentials into your app with CloudDB:


[AI2/CloudDB]



Test by running your project in the companion.

Hopefully if everything has been correctly configured, you should see no errors, and be able to set and get values.


Any issues, please ask on the forum: MIT AppInventor Community Forum


[LINKS/RESOURCES]

Previous howto for local server

RedisLabs SSL howto

ADDITIONAL - Revalidate SSL certificate every 90 days

letsEncrypt require users to revalidate the SSL certificate every 90 days. For many certificates, this happens automatically, but because I used "certonly" and redis is not serving up on port 80, the cronjob for autorenew did not work, and I got an email from LetsEncrypt to advise i needed to revalidate. Initially it was not clear what I needed to do, but a bit of searching revealed that I needed to shut down apache2 in order to make port 80 available to letsencrypt so that it could perform the validation.

To renew Redis SSL certificate

//Login to server

stop Apache

sudo systemctl stop apache2

//Run the certonly option for certbot

sudo certbot certonly


Saving debug log to /var/log/letsencrypt/letsencrypt.log


How would you like to authenticate with the ACME CA?

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

1: Apache Web Server plugin (apache)

2: Spin up a temporary webserver (standalone)

3: Place files in webroot directory (webroot)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


//Select 2

Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 2

Plugins selected: Authenticator standalone, Installer None


//enter the server name

Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'

to cancel): <your domain name>


Cert is due for renewal, auto-renewing...

Renewing an existing certificate

Performing the following challenges:

http-01 challenge for <your domain name>

Waiting for verification...

Cleaning up challenges


IMPORTANT NOTES:

 - Congratulations! Your certificate and chain have been saved at:

   /etc/letsencrypt/live/<your domain name>/fullchain.pem

   Your key file has been saved at:

   /etc/letsencrypt/live/<your domain name>/privkey.pem

   Your cert will expire on 2020-08-09. To obtain a new or tweaked

   version of this certificate in the future, simply run certbot

   again. To non-interactively renew *all* of your certificates, run

   "certbot renew"

 - If you like Certbot, please consider supporting our work by:


   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate

   Donating to EFF:                    https://eff.org/donate-le

-----------------------------------------------------------------------------------------------------------

I found I had to sudo su to go to root to run the following commands

Now back up the existing pem file

sudo cp /etc/stunnel/private.pem /etc/stunnel/private.pem.old

then create the new certificate file for stunnel

sudo cat /etc/letsencrypt/live/<your domain name>/fullchain.pem /etc/letsencrypt/live/<your domain name>/privkey.pem > /etc/stunnel/private.pem

//restart Stunnel and APACHE !!

sudo systemctl start apache2

sudo /etc/init.d/stunnel4 stop

sudo /etc/init.d/stunnel4 start