How to setup Ghost 3.0 on DigitalOcean for production environment.

About why Ghost as platform and DigitalOcean as Virtual Private Host, separate entry is currently in the draft.


Prerequisites that are needed:

  1. DigitalOcean account;
    Through this referral link you will get $100 in DO credit; which in comparison for $5/mo plan will give you 50 (!) months of free VPS hosting.
  2. Domain name;
    If you don't have one, I recommend Namecheap, because their UI/UX doesn't suck. Yes, it matters. Everything else is on par as well.

Rising Action

First, make sure to point your domain in your registrar (Namecheap) to DO name-servers.

Second, there is hard mode and then there is Ghost 1-Click App from the DO Marketplace, as we are not a real programmers, we do later. We create new Project in DO and choose to create new Droplet[1] from in-built Marketplace

After droplet has been created we shall configure network / DNS in DO, for that we need to create a new domain name entry and set DNS A record(-s):

Type    Hostname       Value            TTL (seconds)
A    3600
A    3600

Two entries, one for the domain itself, another for the www sub-domain.

After that has been done it's crucial for DNS to propagate in order for us to obtain TLS[2] further in the process, results may vary, but for Namecheap + DigitalOcean combo it shouldn't take much longer than a dozen of minutes. To make sure, open console and Ping your domain, it should resolve to your Droplet's IP, in our case it's


Alternatively, if something at some point goes South, especially if you do decide to create a new droplet (which will have a new IP) and re-point your domain to that in a relatively short amount of time, it might help to double check first, at service such as DNSMap, before proceeding any further.

At this point we should have:

  1. Domain registered at Namecheap;
  2. Configured name-server at Namecheap with custom DNS list from DO;
  3. New Project created in which we then have droplet and domain pointing towards that particular droplet at DO;
  4. 1-Click App installation of Ghost executed, IP with root:pass obtained (sent to e-mail) or alternatively SSH key access configured;
  5. DNS A records added and verified that they have propagated.

From here on we may proceed with an actual configuration of our Ghost installation.

Open terminal:


In case we went with user:pass, when creating droplet, we will be asked to change it during our first login via SSH, here it might be handy to have a password generator, Strong Random Password Generator does the job.

Don't over-engineer and stick to 32 symbols, more on that in separate entry.


As this is 1-Click App installation, it will auto-start itself and following questions will be asked:

  1. Blog URL
    Make sure to write it with HTTPS, such as:
  2. Agree (with Enter) and default (change nothing) to everything what is asked further down the line, until you are asked for your e-mail to setup TLS - enter your e-mail.
  3. If everything goes smoothly, which it will if you have done everything according to all of that written above, you should have Ghost up and running!

More detailed explanation on the questions asked during setup process can be found at official - How to install Ghost on Ubuntu

Before we crack open a beer, I do advice to do the minimum required maintenance of our server/droplet, as we are now a system administrator for a cloud based infrastructure. How to do that and possible challenges associated with it are currently in the draft. However, for the time being, absolute minimum would be the following.

Update Ubuntu OS

apt update
apt upgrade
apt dist-upgrade
apt autoclean
apt autoremove

Falling Action

Real fun and reason for this entry in the first place, starts here.

Ghost is known for its TLS/SSL/HTTPS you-name-it issues. Most likely you are going to face them as well, if you have followed through.

  1. We have added certificate to, but we haven't done it for our sub-domain, to do that we are going to do the following:
sudo -i -u ghost-mgr
cd /var/www/ghost
ghost config url
ghost setup nginx ssl
ghost config url
ghost restart
  1. We have to manually point our sub-domain to resolve or domain instead. In order to do so we are going to alter the following 3 files, for which we will use Vim, despite that we are not a real programmers:
vim /etc/nginx/sites-available/
vim /etc/nginx/sites-available/
vim /etc/nginx/sites-available/

Do not alter, only these 3

In there we'll find:

location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;

Replace with:

location / {
    return 301$request_uri;

Now a restart for NGINX is required:

nginx -s reload


More than that can go wrong and if it can, as Murphy has stated, it probably will. Not common, but few more things that might have landed you here:

  1. Mixed content error in /ghost admin panel, which prevents from displaying correct HTTPS and throwing an error because of image/favicon.ico; when asked for domain name HTTP instead of HTTPS was entered, can be fixed as ghost-mgr in /var/www/ghost with ghost config url and nginx -s reload after.

  2. An error occurred during the signature verification. Most likely due to the yarn package while trying to do an apt update and can be fixed with the following command:

apt-key adv --refresh-keys --keyserver

And that's that. We have our blog up and running. Next, adding Google Analytics would be insightful in my mind.

* When registering .com TLD at Namecheap and referral of DigitalOcean

  1. Droplet is essentially a DigitalOcean's way of calling Virtual Private Server ↩︎

  2. TLS stands for Transport Layer Security or, formerly, its predecessor, Secure Sockets Layer (SSL) which is a secure protocol developed for sending information securely over the Internet, nowadays simply referred to as HTTPS and widely mistaken as SSL ↩︎