Deploy Ghost blogging platform under OpenBSD with nginx
Ghost is a simple and fast Node.js blogging system. We'll see here how to deploy it on OpenBSD 6.1 with nginx !
Let's talk about Node :
Node.js is a powerfull JavaScript runtime. It's included in the OpenBSD package system. You can install node and npm (the node's app installer) easily :
# pkg_add node
# node -v
v6.10.1
# npm -v
3.10.10
Great ! They are compatible with the latest version of Ghost.
Also, we'll need another package to make it work named : SQLite3.
Install SQLite3 :
# pkg_add sqlite3
Even if you want to use Ghost with MySQL, you'll need SQLite3. The question is... do I need to use MySQL or SQLite3 ?
Short answer : SQLite will be more than fine if you have a blog with less than a 100.000 readers a day.
Setup time :
Get the code :
$ mkdir blog && cd blog
$ curl -LOk https://ghost.org/zip/ghost-latest.zip
$ unzip ghost-latest.zip
Install it as an user :
$ npm install sqlite3 --sqlite=/usr/local
$ npm install --production
Now we can configure it, we'll use the sqlite3 database :
$ vi core/server/config/env/config.production.json
"database": {
"client": "sqlite3",
"connection": {
"filename": "content/data/ghost.db"
},
$ vi core/server/config/defaults.json
"url": "https://blog.cagedmonster.net",
"server": {
"host": "127.0.0.1",
"port": 2368
},
If you prefer using MySQL :
$ vi core/server/config/env/config.production.json
"database": {
"client": "mysql",
"connection": {
"host" : "127.0.0.1",
"user" : "ghost",
"password" : "ghostpass",
"database" : "ghost"
}
},
If you want to add a mail server :
$ vi core/server/config/env/config.production.json
"mail": {
"transport": "SMTP"
},
Start your blog:
We'll use a npm app named forever which allows you to run your node app in the background... forever.
$ npm install forever
Database configuration :
# npm install -g knex-migrator
$ NODE_ENV=production knex-migrator init
Let's start your blog engine :
$ NODE_ENV=production ~/blog/node_modules/forever/bin/forever start index.js
Your app should be running here : http://127.0.0.1:2368
We'll create a crontab task running your app when the system starts :
$ crontab -e
@reboot cd ~/blog/ && NODE_ENV=production ~/blog/node_modules/forever/bin/forever start index.js
Configure nginx with STRONG SSL of course...
# cd /etc/ssl/
# openssl dhparam -out dhparams.pem 4096
# vi /etc/nginx/ssl.conf
ssl_prefer_server_ciphers on;
ssl_certificate /etc/letsencrypt/live/<yourdomain>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<yourdomain>/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_dhparam /etc/ssl/dhparams.pem;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-
RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-
RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-
SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-
SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 4.4.4.4 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000;includeSubdomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
# vi /etc/nginx/nginx.conf
server {
listen 80;
listen [::]:80;
server_name blog.cagedmonster.net;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name blog.cagedmonster.net;
#ssl_certificate /etc/letsencrypt/live/<yourdomain>/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/live/<yourdomain>/privkey.pem;
include ssl.conf;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:2369/;
}
location /ghost {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:2369/ghost;
allow 192.168.1.0/24;
allow 2a01:cb06:3e0:eb00::/56;
deny all;
}
}
# rcctl restart nginx
Now all you have to do is to manage your blog at : https://your-url/ghost/