Moving GeekTrust from Heroku to Digital Ocean

Posted by

Recently I moved our GeekTrust app from Heroku to Digital Ocean. This is a write up on why and how we did it.


Ever since we started GeekTrust it was hosted on Heroku. And at the same time Krishnan had started writing about GeekTrust in our blog hosted on WordPress. Even though we linked it with a subdomain (, we were not reaping the benefits of SEO for our site. So we decided we need to take control of the WordPress Server and have a url like, so that it is crawl-able and GeekTrust gets benefit of SEO. Hosting WordPress on Heroku required setting up a different project and installing another add-on. I didn’t want to get into something which I was not sure of. After much reading up, I felt it was better to host WordPress on our own box , where I had control of things I am doing, rather than on Heroku.

That is reason no 1 for why we moved to Digital Ocean.

Some months back we had made our site SSL secure and to support it on Heroku we had to add an add-on. This add-on along with our regular dynos was costing us more than double the amount we were paying earlier. Digital ocean machines came at just 5$/month and an SSL add-on didn’t add any cost.

That is reason no 2 for why we moved to Digital Ocean.

What we did?

We had to install WordPress, so we were forced to install the LAMP stack. And then we had our own NodeJS servers to install. To manage multiple NodeJS servers we installed PM2. We selected NGINX as the reverse proxy to distribute the client requests between different servers.

So here is the architecture



First up I went ahead and installed WordPress as explained in the Digital Ocean tutorial. But I had to change the port number as I didn’t want to host Apache on Port 80. Another change I did was to install WordPress under blog directory in /var/www/html . This was done because we needed the WordPress to come up on /blog url instead of /. So the command

sudo rsync -avP ~/wordpress/ /var/www/html/

was changed to

sudo rsync -avP ~/wordpress/ /var/www/html/blog

The apache configuration changes is given the gist below

 Once WordPress was installed, NodeJS and PM2 was installed. The installation of these are very straightforward.
#Install Node/Npm
sudo apt-get install -y nodejs
#After node and npm is installed.
npm install -g pm2

Once installed you can start the app using pm2 command. Let’s just assume the app is started on port 8000.

pm2 start app.js

Now we got different servers running on ports 7000 & 8000 and we had to bring both under the domain.

Enter NGINX the reverse proxy.

NGINX was installed.

sudo apt-get install nginx

And then it was configured. We added a new config file for our setup under the /etc/nginx/sites-available directory.

In the above NGINX configuration, I have configured the root to be the root directory of Apache Server. All the urls are configured in the location block in the above code. The server blocks are used for redirecting from port 80 to port 443, which is the final SSL secured endpoint. This helps in redirecting to when the user types in or in the browser url.

As per the above location configuration any client hit on the root (/)url is redirected to the NodeJS Server running at the specific directory, and any hit on the /blog url is redirected to the Apache Server running the blog under /var/www/html/blog directory. A backend API call with in the application was routed to the backend server via the /api configuration.

The last location configurations are for WordPress to load any .php urls using the FastCGI Process Manager. More information about it is available here and here.

Once this was defined and NGINX was restarted, both and were loaded from different application servers.


I didn’t get this configuration right at the first time. Of course you won’t if you are new to NGINX and don’t do this style of dev-ops job frequently. I had made mistakes and this NGINX configuration was achieved only after a lot of reading up.

The first road-block I hit was that the API calls to my backend server was not working at all. The home page loaded, but I couldn’t login or signup.

So I had to rewrite the urls of entire backend APIs with a prefix /api and then feed it to the NGINX so that NGINX understands that all the hits to urls to /api should be redirected to the backend server. That is how location block was written for /api. It uses the upstream configuration to make the redirection.

The next issue was with the WordPress pages. The home and admin page opened up all well, but when I clicked on a particular blog or on links which had query & url parameters, that blog page didn’t load at all. The permalinks feature of WordPress didn’t work at all. It kept redirecting to the home page of the blog.

Initially I hadn’t configured the NGINX to take care of the URL parameters and Query Parameters and that was causing this problem. After a bit of reading I realised that I need to have a configuration which takes care of redirecting the url with the query/url parameters. Now for this I had to setup Fast CGI. And that is how the location block was written for any urls that ends with a .php in it. The fastcgi configuration takes care of the url redirection.

I also hit the WordPress Infinite loop issue, but that was nothing to do with NGINX configuration. It was a WordPress issue and had to be fixed with the hack on the theme files. More information is here.

Once all these issues were fixed our app was up and running on Digital Ocean. Now all we needed to do was switch our DNS servers from Heroku to Digital Ocean. And we were live on Digital Ocean.



Leave a Reply

Your email address will not be published.