The Curly Braces Nginx

Renewing Let's Encrypt certificate

Have the following command setup in my crontab to renew the certificate for this blog, and for the main website - thecurlybraces.com

30 3 1 */2 *  /opt/letsencrypt/certbot-auto renew --pre-hook "service nginx stop" --post-hook "service nginx start"  

This causes the command to run,

At 03:30 on day-of-month 1 in every 2nd month.

Output

Upgrading certbot-auto 0.12.0 to 0.14.1...  
Replacing certbot-auto...  
Creating virtual environment...  
Installing Python packages...  
Installation succeeded.  
Saving debug log to /var/log/letsencrypt/letsencrypt.log

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/thecurlybraces.com.conf  
-------------------------------------------------------------------------------
Cert is due for renewal, auto-renewing...  
Running pre-hook command: service nginx stop  
Renewing an existing certificate  
Performing the following challenges:  
http-01 challenge for thecurlybraces.com  
http-01 challenge for blog.thecurlybraces.com  
Waiting for verification...  
Cleaning up challenges

-------------------------------------------------------------------------------
new certificate deployed without reload, fullchain is  
/etc/letsencrypt/live/thecurlybraces.com/fullchain.pem
-------------------------------------------------------------------------------

Congratulations, all renewals succeeded. The following certs have been renewed:  
  /etc/letsencrypt/live/thecurlybraces.com/fullchain.pem (success)
Running post-hook command: service nginx start  

Just putting this here for reference, and with the hope that it might be useful for someone else.

Setting up a website using Ghost on Debian

My web hosting's annual payment date was drawing close, and instead of renewing it, I decided I'd rent a server on Digital Ocean for 10$ a month. It turns out to be a lot more expensive but gives me the option to use the server for something other than just blogging and running PHP application.

After shifting to this new server, the first thing to do was to migrate my blog here. WordPress is an amazing platform, but over the years it has evolved to something a lot more than just a blogging tool. Besides the new kid on the block - Ghost, was creating a lot of buzz for its simplicity. I wanted to give it a try.

I setup my Digital Ocean server with Debian (Jessie 8.2). Node.js is required to run Ghost. Since I wanted to use this server for multiple applications, I decided I'd put nginx as a front facing proxy/compression server.

This blog item is a guide for setting up Ghost on a server running Debian. Let's start,

Setting up the server

After logging onto the server for the first time, I noticed that sudo was missing, so this was the first thing to do.

apt-get install sudo  

Next, I decided to create a normal sudo user to do my work as, working as the root user at all times is probably not the best idea.

adduser --shell /bin/bash --gecos 'Primary account' abijeet  
usermod -aG sudo abijeet  
su abijeet  

I then proceeded to install nginx-light since the features in it sufficed my needs.

sudo apt-get install nginx-light  

I decided to build the Node.js source and for this, I needed g++ and make

sudo apt-get install g++ make  

I then grabbed the Node.js source from their website, and proceeded to build it. Do note that this approach does take a while, for me it took about 30 minutes. Ghost.js recommends that we use the LTS version of Node.js

wget https://nodejs.org/dist/v4.2.4/node-v4.2.4.tar.xz  
tar xf node*  
cd node-v4.2.4  
./configure
make  
make install  

Ok, so that's the base setup done, let's now setup Ghost.

Setting up Ghost

Let's first grab Ghost from their website

wget https://ghost.org/zip/ghost-0.7.5.zip  

We'll need to install unzip to run Ghost.

sudo apt-get install unzip  
unzip ghost-0.7.5.zip -d www.mywebsite.com  

Then move the whole extracted folder to the /var/www/html folder where web applications are traditionally kept.

mv www.mywebsite.com /var/www/html/  

Running your Node.js application as a root user is generally a bad idea. If your website gets hacked, the hacker will have root access to your machine. We'll create a system user that will run just our website. We will then shift to that user to work with our website. For our guide purpose, let's name the user as website-user

sudo adduser --shell /bin/bash --gecos 'Website user' website-user

# Give ownership of the website's folder to the user.
sudo chown -R website-user:website-user /var/www/html/www.mywebsite.com  
su website-user   # Start using that user.  
cd /var/www/html/www.mywebsite.com  

Install the modules that Ghost needs to run in production mode.

npm install --production  

Start and then stop the server, so that it creates a base config.js file that we will then tweak.

npm start  
# The type Ctrl + C to stop the server

Ok, time to make modifications to the config.js file. The following needs to be modified -

  • Set the url to http://www.mywebsite.com
  • Under connection, set filename to www.mywebsite.com.db
  • Under server, set the host as 127.0.0.1
  • Under server, set the port as 3001
  • Turn off gzipping, set compress as false. We'll set it up using nginx later.

Change the website-user's .profile file and add the following at the end of it to run Ghost in production mode. This file is usually in the home directory of the user.

nano ~/.profile  

then,

export NODE_ENV=production  

Now change to the sudo user (abijeet) that we had added initially and install pm2. We'll use pm2 to monitor our app, and restart it in case of a crash.

su abijeet  
sudo npm install -g pm2  
# pm2 installed, go back to the website-user
su website-user  

Start running the server using pm2

cd /var/www/html/www.mywebsite.com  
pm2 start index.js --name "website name"  

Finally, we'll instruct pm2 to restart the Ghost application whenever the server is restarted.

sudo env PATH=$PATH:/usr/local/bin pm2 startup ubuntu -u website-user  

Next, its time to setup routing and compression on nginx.

Setting up nginx

Create a file under /etc/nginx/sites-available

su abijeet  
sudo nano /etc/nginx/sites-available/www.mywebsite.com  

Put the following content in the file,

server {  
  listen 80;
  server_name www.mywebsite.com;
  location / {
      proxy_set_header   X-Real-IP $remote_addr;
      proxy_set_header   Host      $http_host;
      proxy_pass         http://127.0.0.1:3001; # This should match the port where the Ghost server is running.

  }
}

Create a symbolic link to this file under /etc/nginx/sites-enabled.

sudo ln -s /etc/nginx/sites-available/www.mywebsite.com /etc/nginx/sites-enabled/www.mywebsite.com  

Remember to remove the default file present under /etc/nginx/sites-enabled/ and /etc/nginx/sites-available/.

Turn on gzipping for nginx. The following goes into the /etc/nginx/nginx.conf

# Turning on gzip.
gzip on;  
gzip_proxied any;  
gzip_min_length  1000;  
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;  
gzip_vary on;  
gzip_comp_level 6;  

This section might already be present under the nginx.conf file, so search before you add it.

Also add the following to nginx, to prevent it from sending the version number in HTTP response headers.

server_token:off  

Alright, once all that is done, time to restart nginx. But first we'll check the configurations.

nginx -t  
# If all is good, restart nginx
nginx -s reload  

We're done. Type in the URL of your website in a browser, and you should see Ghost's startup page.