Installing Postleaf On DigitalOcean

This post will show you how to install Postleaf on a DigitalOcean droplet and configure Nginx as a reverse proxy. You'll also learn how to use pm2 to keep the app running, and optionally install a free SSL certificate from Let's Encrypt.

To complete this tutorial, you'll need a DigitalOcean account and an SMTP provider for sending transactional email.

Create A Droplet

Login to your DigitalOcean account and select Droplets from the menu, then choose Create Droplet. Postleaf can run on any distro, but for this tutorial, we'll be using Ubuntu 16.04.

To build the alpha version of Postleaf, you'll need a droplet with at least 1GB RAM. The $10/mo droplet should be fine for most purposes.

Next choose a region close to you. I live on the east coast, so I typically choose New York.

That's all that's required from this section. Just click Create to spin up your new droplet. You'll be taken back to the Droplets page. Once the droplet is ready, copy the IP address shown in the dashboard.

Configure The Droplet

Login

Now it's time to login and configure your droplet. Open up a terminal window and type:

ssh root@<droplet-ip>

Make sure to change <droplet-ip> your droplet's IP address.

If you added an SSH key to your droplet, you'll be logged in automatically. If not, you'll be prompted for the password that was emailed to you when you created the droplet.

Now that you're logged in, let's create a user.

Create A Non-root User

It's dangerous to do everything as the root user, so let's create a new user called postleaf with sudo access:

adduser postleaf

Follow the prompts to set the new user's name and password. You can leave all the other fields blank by hitting Enter.

Now let's add the new user to a couple groups:

gpasswd -a postleaf sudo
gpasswd -a postleaf www-data

This gives the postleaf user administrative access and adds it to the same group as Nginx, which we'll get to later.

If you're using an SSH key, don't forget to move it from the root user to the postleaf user. Otherwise, you can skip this step.

mv /root/.ssh /home/postleaf/.ssh
chown -R postleaf /home/postleaf/.ssh

Woohoo! The postleaf user is ready to go. Let's logout of root and login as the new user:

exit
ssh postleaf@<droplet-ip>

Once again, if you're using an SSH key, you'll be logged in automatically. Otherwise, enter the password you just created for the postleaf user.

Configure The Firewall

It's a good idea to lock down unused ports by setting up a firewall. This is actually pretty easy to do with Ubuntu:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow www
sudo ufw allow https
sudo ufw enable

This will block all incoming requests to ports other than the ones we'll be using. Easy.

Install Dependencies

First, let's run system updates:

sudo apt-get update && sudo apt-get upgrade -y

Now let's install Postleaf's dependencies:

sudo apt-get install -y git nginx sqlite3 graphicsmagick

Postleaf requires Node 7, so we'll install that one directly from the NodeSource repo:

curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
sudo apt-get install -y nodejs

That's it for dependencies!

Install Postleaf

Since we're installing with the alpha version of Postleaf, we need to build it from the source. Let's start by cloning the repo from GitHub:

cd /var/www
sudo git clone https://github.com/Postleaf/postleaf.git
sudo git clone https://github.com/Postleaf/empower-theme.git postleaf/themes/empower-theme
sudo chown -R $USER:www-data /var/www/postleaf
cd postleaf

This will create /var/www/postleaf and copy the source from GitHub. It will also copy the default theme to the correct location.

Next we need to create the .env file. This file contains important settings that Postleaf needs to run. We can use .env.example as a template, so let's copy it to .env and open it for editing:

cp .env.example .env
nano .env

You should see a screen like this:

If you have a domain, change the value of APP_URL to http://example.com/. If not, use http://<droplet-ip>/ for now — you can change it later on if you add a domain.

If you're using a domain, make sure you've configured your DNS properly and allowed enough time for it to resolve (usually up to 24 hours).

Next, change AUTH_SECRET to a random string. You can use a password generator if you like. Just make sure it's reasonably long and random.

Lastly, update the SMTP section. This section is important, otherwise you won't be able to create users, reset passwords, etc. If you don't already have a transactional email service, the folks over at Discourse have put together a great list of email providers — many of which offer free plans.

Finally, save the file by pressing ctrl + x, y, enter.

Build Postleaf

You're almost there! The next step is to install Postleaf's task runner and build the app. These commands will take a few minutes to run:

sudo npm install -g gulp
sudo npm install --only=dev & sudo npm install --only=prod

Finally, we can run the build process:

gulp build

Keep It Running

In this step, we're going to setup a tool called pm2 to launch and monitor the app. If Postleaf crashes, pm2 will restart it. If your droplet gets restarted, pm2 will make sure Postleaf relaunches on startup.

sudo npm install -g pm2
pm2 start app.js
sudo pm2 startup systemd

Boom. All set.

Configure Nginx

Now we need to configure Nginx to act as a reverse proxy for our app — it will essentially pass web traffic to and from the Node app.

Let's replace the default config with a custom one:

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

Delete everything and paste the following:

server {
listen 80;
server_name example.com;

# Upload limit
client_max_body_size: 100m;

location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}

Make sure to change example.com to the same domain or IP address you used in the .env file.

Save and exit by pressing ctrl + x, y, enter.

Now test the config and restart Nginx:

sudo nginx -t
sudo systemctl restart nginx

If everything is setup properly, you'll be able to access Postleaf from the URL or IP address you entered in the last step. If not, double check your settings and verify your DNS records.

Configure SSL

This step is optional, but recommended if you're using a domain name. To obtain a free SSL certificate, install Let's Encrypt:

sudo apt-get install -y letsencrypt

Before we can request a certificate, we need to temporarily stop Nginx:

sudo systemctl stop nginx

Now we can request the cert:

sudo letsencrypt certonly --standalone

Let's Encrypt will ask you a few questions. Follow along and go through each screen. When you're done, you should see a message like this:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will expire
   on 2017-07-20. To obtain a new version of the certificate in the
   future, simply run Let's Encrypt again.

Now we just need to configure Nginx to use the new cert.

Configure Nginx To Use SSL

This is just a matter of swapping out the current config with a new one.

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

Replace everything with the following. Make sure to change example.com to your own domain:

# HTTP - redirect all requests to HTTPS:
server {
listen 80;
listen [::]:80 default_server ipv6only=on;
return 301 https://$host$request_uri;
}

# HTTPS - proxy requests on to local Node.js app:
server {
listen 443;
server_name example.com;

# Upload limit
client_body_max_size 100m;

ssl on;
# Use certificate and key provided by Let's Encrypt:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

# Pass requests for / to localhost:3000:
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:3000/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}

Save and exit by pressing ctrl + x, y, enter.

Now test the config and restart Nginx:

sudo nginx -t
sudo systemctl restart nginx

You can verify that the certificate was installed by visiting your domain in a browser.

Configure Auto-Renewal

Let's Encrypt certificates are only valid for 90 days, but we can automate things to make renewal painless. Let's create a cron job:

sudo crontab -e

Add these lines:

30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log
35 2 * * 1 /bin/systemctl reload nginx

Now save the file and exit. You don't need to worry about renewals anymore!

But if you ever do need to renew a cert manually, just use this command:

sudo letsencrypt renew

Video Walkthrough

I recorded a walkthrough of this tutorial and put it up on Vimeo. You can watch it here.

Conclusion

Phew! That was a lot of information for one tutorial, but hopefully Postleaf is up and running on your DigitalOcean droplet now!

If you're having trouble, head over to the forum or community chat for assistance.