Ghost Nginx 502 Bad Gateway but npm start --production Works

I have a weird situation where I am seeing npm start --production start up my Ghost blog within my droplet and my website appears, but when I close that port and run service ghost restart and service nginx restart I get a 502 Bad Gateway. I’m a bit confused because I thought service ghost start or service ghost restart runs the npm start --production command and keeps it running until stopis called. However this does not seem to be the case. Can anyone point me in the right direction for the logs I should check that might indicate why the command line command run works, butservice` command does not?

Successful command: npm start --production

> ghost@0.7.9 start /var/www/ghost
> node index
Migrations: Up-to-date at version 004
Ghost is running in production... 
Your blog is now available on 

Service start

sudo service ghost start
start: Job is already running: ghost

My only question I have is around the chown command I ran and if this blocked permissions to the root user who is running the commands. I ran chown -R ghost:ghost ghost/*, but I don’t have a ghost user, only a root user which is signed in. Could this mess with anything?

Submit an answer

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.


Ok, so your Ghost configuration is fine. I tested the exact same on a fresh droplet and it works. The only thing you need to change in the NGINX server block is:

proxy_pass http://localhost:2368;

Change localhost to to match the server defined in Ghosts’ config.js file.

You’d then restart NGINX: service nginx restart

Once NGINX is restarted, you may have to do a hard refresh in-browser, or flush your browser cache. Sounds a bit odd, but I had to do this when I was swapping configuration during testing.

As a reference, this is what I used to setup my test server before using your configuration:

apt-get update \
&& apt-get upgrade -y \
&& apt-get -y install build-essential unzip zip \
&& cd /usr/local/src \
&& curl -sL | sudo -E bash - \
&& sudo apt-get -y install nodejs \
&& curl -L -o \
&& mkdir -p /var/www/ghost \
&& unzip -uo -d /var/www/ghost \
&& cd /var/www/ghost \
&& npm install --production \
&& sudo add-apt-repository -y ppa:nginx/stable \
&& sudo apt-get update \
&& sudo curl -o /etc/init.d/ghost \
&& sudo useradd -r ghost -U \
&& sudo chown -R ghost:ghost /var/www/ghost \
&& sudo chmod 755 /etc/init.d/ghost \
&& sudo update-rc.d ghost defaults \
&& sudo update-rc.d ghost enable

The above uses NodeSource’s NodeJS repositories for 6.x to install NodeJS/NPM, uses NGINX’s repos to install NGINX, downloads and installs Ghost, creates the Ghost init script, and runs the initial setup for Ghost.

From there, I changed this block to use my own domain.

        url: '',
        mail: {},
        database: {
            client: 'sqlite3',
            connection: {
                filename: path.join(__dirname, '/content/data/ghost.db')
            debug: false

        server: {
            // Host to be passed to node's `net.Server#listen()`
            host: '',
            // Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
            port: '2368'

and then used your NGINX server block (inserting my domain in place of the filler you have) and then ran:

service ghost restart \
&& service nginx restart


I also need to check your NGINX server block, which would be located in:




If those directories do not exist, you’d need to locate where your server blocks are for your domains.

A server block will look like:

server {
    listen ...;

… where ... is the configuration contents. Since NGINX is what’s going to be handling requests on port 80, the default port you connect to when accessing, we need to make sure NGINX is setup to proxy requests on Port 80 to your Ghost installation.

If NGINX isn’t setup, the only way you’re going to be able to access Ghost is by running it with a Port attached to the URL.

Ghost config.js

The line below should be your actual domain name:

url: ''

and the following block is what I needed to help you configure NGINX properly:

        server: {
            // Host to be passed to node's `net.Server#listen()`
            host: '',
            // Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
            port: '2368'

The above defines how Ghost runs the production server. With the above, the only way you’re going to be able to connect to Ghost is by proxying, which we can do with NGINX, once I see what you’ve got right now :-).


The root user can read from, write to, and execute anything, regardless of whether root owns the directory or file.

The default log directory is /var/log.

Within the above directory, there should be an nginx directory containing an error.log file and which you can then tail to get the last, i.e.

tail -20 /var/log/nginx/error.log

If you could also post your NGINX server block for your domain, we can take a look and see if there’s anything out of place.

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel