Skip to content

Instantly share code, notes, and snippets.

@ErisDS
Last active April 13, 2019 09:58
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ErisDS/499af765e6a282632c5d13f6bf99d756 to your computer and use it in GitHub Desktop.
Save ErisDS/499af765e6a282632c5d13f6bf99d756 to your computer and use it in GitHub Desktop.
Setup steps for installing Ghost on a fresh Ubuntu 16.04 server

Variables:

<server_ip> - ip of the server the blog is being installed on - name for the server e.g. "myblog" - domain name e.g. "myblog.mycompany.com" <ghost_mysql_pw> - a password for a ghost user in mysql <ssl_email> - an email address for letsencrypt

Steps to get from Ubuntu 16.04 fresh install to Ghost

Largely based on the following:

https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04 https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04 https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-16-04 http://www.tecmint.com/install-mariadb-in-ubuntu-and-debian/

Networking

  • hostnamectl set-hostname <hostname>
  • hostname
  • vim /etc/hosts
  • Add: <server_ip> <domain> <hostname> after localhost

Create admin user (can login)

  • adduser admin
  • adduser admin sudo

Setup SSH key

  • su admin
  • cd ~
  • mkdir .ssh
  • [LOCAL] scp ~/.ssh/id_rsa.pub admin@<server_ip>:/home/admin/.ssh/uploaded_key.pub
  • cat uploaded_key.pub >> ~/.ssh/authorized_keys
  • rm -r uploaded_key.pub

Update base software

  • sudo apt-get update
  • sudo apt-get upgrade
  • sudo apt-get dist-upgrade

Create ghost user (runs ghost)

  • sudo adduser ghost
  • sudo adduser ghost sudo @NOTE: should this really be a sudo user?!

Lockdown SSH

  • sudo vim /etc/ssh/sshd_config
  • change:
    • PermitRootLogin no
    • PasswordAuthentication no
  • add:
    • Limit logins to IPv4 only

    • AddressFamily inet
  • sudo systemctl restart ssh
  • sudo ufw allow OpenSSH
  • sudo ufw enable

Install Node, npm, ghost-cli, nginx

  • sudo apt-get update
  • curl -sL https://deb.nodesource.com/setup_6.x -o nodesource_setup.sh
  • sudo bash nodesource_setup.sh
  • sudo apt-get install nodejs
  • sudo apt-get install build-essential
  • node -v = 6.10.2
  • npm -v = 3.10.10
  • sudo apt-get install nginx
  • sudo ufw allow 'Nginx Full' @NOTE: I want SSL, would like to make this SSL only, can't do this before letsencrypt setup though?

mariadb

Install:

  • sudo apt-get install software-properties-common
  • sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
  • sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://www.ftp.saix.net/DB/mariadb/repo/10.1/ubuntu xenial main'
  • sudo apt-get update
  • sudo apt-get install mariadb-server

Configure:

  • sudo mysql_secure_installation
  • mysql -u root -p
  • CREATE USER ghost@localhost identified by '<ghost_mysql_pw>';
  • CREATE DATABASE ghost_prod;
  • GRANT ALL PRIVILEGES ON ghost_prod.* to 'ghost'@'localhost' IDENTIFIED BY '<ghost_mysql_pw>'; @NOTE what are the expected steps here - I just did it all and plugged it into Ghost-CLI.

Install Ghost

@NOTE: which user should I be here? Should it be different for installing vs running?!

  • su ghost
  • sudo npm i -g ghost-cli
  • cd /var/www/
  • sudo mkdir ghost
  • sudo chown ghost:ghost ghost
  • cd ghost
  • ghost install

Then fill out the prompts:

  • Url:
  • MySQL host: localhost
  • MySQL user: ghost
  • MySQL pass: <ghost_mysql_pw>
  • MySQL db: ghost_prod
  • SSL: yes
  • SSL email: <ssl_email>

@Note: SSL setup then fails with Error code 1 if doesn't already point at <server_ip> and seems to also fail without sudo?

@sebgie
Copy link

sebgie commented Apr 27, 2017

Ok, this must be very confusing and ghost cli doesn't behave like it is expecting a separate user for running Ghost.

Annotations to the gist:

  • editing the network setting is very rarely needed from my experience. DO setup worked out of the box for me?
  • adduser admin fails because a group already exists. Needs to be a different username.
  • cat uploaded_key.pub >> ~/.ssh/authorized_keys should be followed by chmod 600 ~/.ssh/authorized_keys to satisfy SSH permission requirements.
  • The ghost user should in my opinion be a system user without login or shell. adduser --system --group ghost. I'll write more about that below. It is similar to the git or mysql user.
  • sudo ufw allow 'Nginx Full' it is possible to configure SSL only before letsencrypt but NGINX won't respond until it is properly configured to listen for SSL connections.
  • MariaDB: what are the expected steps here - I just did it all and plugged it into Ghost-CLI. -> Nothing more to add.
  • Install Ghost: which user should I be here? Should it be different for installing vs running?! -> I would say that it should be the admin user.
  • Install Ghost: SSL setup then fails with Error code 1 if doesn't already point at <server_ip> and seems to also fail without sudo? -> SSL certificates can only be issued for valid DNS names. So a configuration with IP will fail. Assumption: sudo is needed to write to /etc/ssl which is owned by root.

Using a ghost system user:
The steps to use a separate ghost user for running would need a update to ghost cli:

  • as admin user
  • sudo npm i -g ghost-cli
  • cd /var/www/
  • sudo mkdir ghost
  • sudo chown admin:admin ghost
  • cd ghost
  • ghost install

The creation of a ghost system user could be taken over by ghost-cli. The internal steps to make this all work would be:

  • ensure that there is a ghost user
  • chown ghost:ghost <content directory>
  • execute the node command as ghost user (e.g.: sudo -u ghost node index.js) or use the appropriate systemd method to use a different user

The outcome of this would be to run the process as ghost user and allow permissons to the content directory only. Everything else would be owned by the admin user.

SSL config:
It feels to me like SSL setup should be a separate step? We also need to make sure that the user has set up a proper DNS name. I was also wondering if it's possible to issue a prompt when we need sudo?

@ErisDS
Copy link
Author

ErisDS commented May 1, 2017

I was testing on Linode, rather than digital ocean. All the tutorials & playbooks I found for both included updating network settings & I didn't run into any problems with the admin username. I guess DO must set that up?!

it is possible to configure SSL only before letsencrypt but NGINX won't respond until it is properly configured to listen for SSL connections

I didn't quite follow this, and this was the part that I had the most problem with. Could you go into more detail about what the correct sequence of steps are?

MariaDB: what are the expected steps here - I just did it all and plugged it into Ghost-CLI. -> Nothing more to add.

Hmm, if I'm confused by this, I think other people will be too. I'll write more about this on the main issue in reply to Austin as well.

@sebgie
Copy link

sebgie commented May 1, 2017

I didn't run into any problems with the admin username. I guess DO must set that up?!

No idea who sets it up but I get an error when trying to do adduser admin on DO.

# adduser admin
adduser: The group `admin' already exists.

This shouldn't be a big issue as the main reason for doing that is to not use root and not to use an account called admin.

I didn't quite follow this, and this was the part that I had the most problem with. Could you go into more detail about what the correct sequence of steps are?

You said: sudo ufw allow 'Nginx Full' @note: I want SSL, would like to make this SSL only, can't do this before letsencrypt setup though?

My response was that it is possible to configure the firewall to SSL only but if you do that you won't be able to reach Nginx anymore. Nginx will still listen on port 80 with the default config and the firewall would block that port.

After a bit of research about letsencrypt it seems like port 80 is needed to generate/renew certificates which means that Nginx Full is the correct profile. In addition to that, you will probably want to redirect from HTTP to HTTPS which also needs the port to be open.

  • correct sequence imo:
    • install Nginx
    • sudo ufw allow "Nginx Full"
    • set up DNS -- needed to get a certificate for the correct domain
    • generate certificate using letsencrypt with ghost-cli
    • ghost-cli updates Nginx config

Hmm, if I'm confused by this, I think other people will be too.

There are many different ways to do this. What is outlined above works and is an acceptable way of doing it. We certainly can think about reducing the steps if required.

Copy link

ghost commented Aug 11, 2018

Is there no way to do it manually by entering details in a config file and just uploading the files to your server?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment