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:

  • Set up the redis server
  • Get an authorised certificate from LetsEncrypt
  • Set up stunnel4 to create the SSL(TLS) tunnel
  • Set your firewall/s
  • Set the CloudDB in AI2


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:

  • ssh access to the server
  • an admin user with sudo permissions


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]

  • VPS on IONOS
  • Ubuntu 18.04 LTS Server
  • Admin user with sudo permissions


[FIREWALL]

Ionos Control Panel

Set the following two rules:

Allow All 6379 Redis
Allow All 6381 Redis 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 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
#~~~~~~~~~~~~~~~~~~~~~~


[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

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]

  • Open up AI2
  • Create a new project
  • Pull in the CloudDB component
  • Setup components and blocks to set and get values
  • In the designer, select the CloudDB and enter the following:


  1. ProjectID - this can be anything you want for your Project (will be set as your AI2 project's name by default
  2. Redis Port - 6381
  3. RedisServer - use your server's domain name or IP address
  4. Token - use your password as set in the redis conf file
  5. UseSSL - check the box !


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