Ghost + Nginx + SSL Configuration
I noticed Ghost a while ago and toyed with it a little. Back then I wasn’t as familiar with Node so it quickly made its way into the “Hmm, that was neat” pile. I’ve been working exclusively in Node for the past year or so, so when I thought about starting a blog, I pretty much skipped over the other option completely and jumped in.
My preferred web server is Nginx. It’s light, easy to configure and fast. It’s also good at proxying requests to backend applications like NodeJS or PHP’s built in FastCGI Process Manager. I have lots of experience running the later, but not so much the former. So when I went to setup Ghost to use only SSL requests, I ran into a ’too many redirects’ issue.
Ghost’s config.js
has a setting for the url
of the blog you’re setting up. Setting this to http://randy.sesser.me
worked fine and I had Nginx redirecting http
traffic to https
for me. However, one thing bugged me; Ghost used this URL as a base to it’s links. For SEO purposes, I’d rather not have links out there that 301
to the proper page. So, I changed it to https://randy.sesser.me
. Immediate redirect loop.
Hmmm. Interesting. Then I found this post on All About Ghost showing how to configure Ghost and Nginx for SSL. As I started reading and looking at the Nginx configuration section, I noticed one thing they had that I did not.
proxy_set_header X-Forwarded-Proto $scheme;
Turns out, Ghost uses Express and this is how it deals with proxied requests. Without this header, express can’t see the scheme being used because it’s proxied to an http
backend (e.g. http://localhost:2368
). Therefore, the express app thinks all requests are being served over http
and keeps trying to redirect to the url
configured in config.js
.
Here’s what my Nginx config looks like:
server {
listen 80;
listen 443 ssl;
server_name randy.sesser.me;
root /path/to/root;
access_log /path/to/logs/access.log;
error_log /path/to/logs/error.log;
ssl on;
ssl_certificate /path/to/ssl.crt;
ssl_certificate_key /path/to/ssl.key;
ssl_session_timeout 5m;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:2368;
}
}
Edit your config.js
to use https
, restart Nginx (sudo nginx -s reload
), restart your Ghost blog and your should be golden.
P.S.
I can also recommend StartSSL for a cheap free SSL certificate.