How to Host Multiple Ghost Sites with One DigitalOcean Droplet
- Darren Beattie
- 24 Mar, 2020
Photo by chuttersnap on Unsplash
You can absolutely do this tutorial still but you might want to choose a bigger Droplet than the $5 one listed below. I ran into the issue when attempting to upgrade Ghost. I just thought you should know before you get too deep into this tutorial.
Donât Run Multiple Ghost Instances on a Small Virtual Machine
So the first time I set up darrenbeattie.com on DigitalOcean I made some mistakes. It worked but using the DigitalOcean one-click set up for the initial blog made it difficult to add additional domains.
I spent several days trying to make it work and I finally found an article that sort of detailed what I wanted to do. Sadly, the easiest solution was to blow up an existing droplet and create a new one.
The nice thing about $5 droplets is that they give you an inexpensive way to play. Sadly during my web development bootcamp I did not learn a ton about servers and deployment. I can code, but getting it up on a Ubuntu/Nginx server all by myself?
Thatâs newâŠ
Iâm going to condense and update that article for you in my own words to give you a little more detail/specifics.
What To Do
Iâm going to assume you have purchased your domain(s).
The majority of registrars only have good rates for a year, then the fees climb a ton. I had one domain climb to $50+ a year to keep. Others nickel and dime you until you end up paying triple or quadruple their initial offer.
I recently moved all of my domain names over to Google Domains (GD) for this reason.
As a Canadian itâs a $17 CAD flat rate with private registration and itâs very easy to use without all the annoying upsells of nearly every other provider (GoDaddy, HostGator, BlueHost, etcâŠ) Iâve used in the past.
Itâs a good sign if Iâm telling you that and I donât get any referral $$ for sharing that info with you. Thatâs how annoying Iâve found nearly every other registrar prior to GD.
Step #1 - Sign Up For DigitalOcean
You should have some basic understanding as to how the terminal works on either a mac, linux or a windows machine.
You can sign up here. And if you do, this time I will get a referral bonus of $25 but youâll also get $100 worth of credit for 60 days or two free months if you choose the $5 droplet and I donât see why you wouldnât.
Unless you already have a gigantic audience the $5 droplet will easily handle most of the traffic of a small blog. I spent the extra $1 a month for weekly backups but you donât have to if you donât want to.
At the time of writing the process looked like this:
- Pick the Ubuntu 18.04 option for your distribution
- Pick âstandardâ
- Scroll left for the $5 droplet.
- Choose your location (I chose Toronto because as I said, Iâm Canadian)
- I didnât choose any additional options but thatâs up to you
- I set up SSH authentication (mentioned below, DO will walk you through it)
- You probably only need the 1 droplet
- Choose a hostname
- Add any tags you think are relevant
- Select the project (youâll need to create one if you havenât already)
- I added backups, you donât have to, but itâs $1 a month on a $5 droplet
- Double check your selections and click create droplet
Yes, I get a kick-back this time, but similar to GD, DigitalOcean (DO) has an upfront no-BS approach to business. Itâs a simple service without the incessant upsells. We used them when we were running Koachable years ago and they helped us easily scale when we needed to.
You can use AWS or Google Cloud or Azure if you want, they are often free for the first year but then they can get expensive quickly past that. Those services tend to serve medium to larger sized businesses well but not tiny startups. We actually switched from AWS in 2014 to DO for this reason. Iâm sure DO is more expensive when your traffic is huge but for now mine isnât.
I think itâs wise to set up SSH for your droplet, but thatâs just me. Itâs more secure and itâs annoying to type in your password every time you want to access your droplet (AKA virtual private server). For more on thatâŠ
How to Set Up SSH Keys on Ubuntu 18.04 | DigitalOcean
Although you may still want to use a passphrase from your favourite password manager, so youâll still be entering a password when you first login to your server each time.
Step #2 - Point Your DigitalOcean Nameservers To your Registrar
Youâll have to point your DigitalOcean Nameservers to whatever provider you choose and you can read the following for more on that:
How To Point to DigitalOcean Nameservers From Common Domain Registrars | DigitalOcean
Basically you need to add these custom NSâs under the DNS settings of the domain you want to use on your registrarâs site:
ns1.digitalocean.com
ns2.digitalocean.com
ns3.digitalocean.com
Once youâve done that, from within your project/droplet on DO youâll need to add the domain to DO and set up at least two A records within DO.
How to Add Domains | DigitalOcean Product Documentation
- thenameofyourwebsite.com
- www.thenameofyourwebsite.com
This ensures youâll be redirected appropriately no matter what people put into their web browser.
Step #3 - Initialize Your Server
Here is where I went wrong in my first attempt, at least for creating multiple blogs/sites on a single droplet. DigitalOcean has a 1-Click Ghost App Deploy set up in the marketplace and I just used that.
It works if you only want to create one site on your droplet. I wanted at least two, possibly more as I move some old wordpress sites over to ghost.
My mistake was not doing this myself and setting up users for each site. I used the root user instead, donât do that if you want multiple sites.
In fact, you shouldnât really do that even if you donât want multiple sites on one droplet. You should still set up a user with superuser permissions and use that instead.
The following is only partially correct in what we want but you should still read it. I didnât on my first attempt and regretted it.
Initial Server Setup with Ubuntu 18.04 | DigitalOcean
Donât code along with that guide, I recommend coding along with me below. There are some differences.
Step A: Login to Your Droplet/Server
The â$â in these can be omitted itâs just a common way to write out the input of the terminal. Experienced developers will know this, beginners might be confused.
$ ssh root@your_server_ip
Then youâre going to get a couple of questions:
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '<ip_address>' (ECDSA) to the list of known hosts.
You can just type âyâ rather than âyesâ if you want. If you are using SSH with a passphrase youâll be asked for it so make sure you have it handy.
Enter passphrase for key 'C:\Users\<you>/.ssh/id_rsa': <passphrase>
Itâs probably a best practice for security but itâs up to you to implement it or not.
Once complete youâll be logged in to your droplet as whatâs called âthe rootâ and ready to get it set up. A mildly entertaining explanation:
Step B: Update The Server
$ apt-get update && apt-get upgrade
This may take a while and youâll get a ton of lines printing off.
Step C: Add a User
This example creates a new user called sammy, but you should replace it with a username that you want to use:
$ adduser sammy
I like to use acronyms for the domains Iâm installing and I write the details down in my password manager.
You will be asked a few questions.
Enter a strong password and, optionally, fill in any of the additional information if you would like. This is not required and you can just hit ENTER in any field you wish to skip.
Step D: Make that User a Superuser
To unlock admin privileges for your new user weâll youâll need to do the following:
$ usermod -aG sudo sammy
Now, when logged in as your regular user, you can type sudo before commands to perform actions with superuser privileges. Weâll need this, and weâll need to set up new users for additional sites per droplet in the same fashion.
Step E: Login as that User
$ su - sammy
Step F: Install Nginx
Nginx (âengine-Xâ) is a reverse proxy. Itâs like the middleman between your Ubuntu (Linux) server and the rest of the internet. What makes the server do itâs thing based on the requests really. A better back end engineer can probably correct me on that.
$ sudo apt-get install nginx
[sudo] password for sammy:
Enter your password and let it run. Then:
$ sudo ufw allow 'Nginx Full'
The second command allows HTTP and HTTPS connections. You should see a much faster confirmation on this command than the previous one. I donât know if that has relevance to any firewall but Iâve seen it mentioned a few times. In any case, this is what I did and it appears to have worked correctly.
Step G: Install MySQL
Ghost databases use MySQL so this is what weâll need. Iâm far more used to postgreSQL and SQLite but they are all more similar than dissimilar so no big deal.
$ sudo apt-get install mysql-server
Once installed if you want to set a password youâll need to log into the MySQL shell which will look a little different in the terminal and weâre switching to a structured query language (SQL) now:
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
Replace âpasswordâ with your stronger (stored-in-a-password-manager) password, but keep the quotations around your password or it wonât work.
You should see the following after you change your password successfully:
Query OK, 0 rows affected (0.00 sec)
Then exit MySQL:
mysql> quit
Step F: Install Node.js
And npmâŠ
Node.js is the server side JavaScript engine that will run your ghost site. As I said in my last post I really like node.
Anyhoo, weâre installing the latest stable 10.x version using a curl command.
$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
Once thatâs done it will tell you something along the lines of:
## Run `sudo apt-get install -y nodejs` to install Node.js 10.x and npm
## You may also need development tools to build native addons:
sudo apt-get install gcc g++ make
## To install the Yarn package manager, run:
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install yarn
Youâll want to run the first command at a bare minimum:
$ sudo apt-get install -y nodejs
If you want to use the increasingly popular yarn package manager youâll also need to run the yarn related code too. But Iâm happy with npm in this context and the rest of my instructions will use npm too.
Anecdotally yarn feels a bit faster, but I donât know how much npm or yarn Iâll ever be using on this server so flip a coin ÂŻ\_(ă)_/ÂŻ
Step #4 - Set Up Ghost
The server is good to go, but youâre not done yet if you want a ghost blog for your site.
Weâre going to use the Ghost-CLI command line tool to get Ghost installed and configured with the following npm package:
$ sudo npm install ghost-cli@latest -g
Itâs pretty quick. Next youâll want to make a directory (mkdir) for your site:
$ sudo mkdir -p /var/www/<yourblognamehere>
Replace
Then you want change the owner of this new directory to the user you created earlier:
$ sudo chown sammy:sammy /var/www/<yourblognamehere>
Again, replace sammy with whatever your username is and
Set the correct permissions:
$ sudo chmod 775 /var/www/<yourblognamehere>
Then you need to navigate into that directory:
$ cd /var/www/<yourblognamehere>
This will change your prompt in the terminal to something like:
sammy@ubuntu-nameofserver:/var/www/<yourblognamehere>
That last bit helps you know that youâre in the right directory and itâs important that youâre in the right directory. I always double check where I am before I run commands. It will save you time later.
From the directory (triple check it even):
$ ghost install
Now youâll get a bunch of command line prompts:
â Checking system Node.js version
â Checking logged in user
â Checking current folder permissions
â Checking operating system compatibility
â Checking for a MySQL installation
â Checking memory availability
â Checking for latest Ghost version
â Setting up install directory
â Downloading and installing Ghost v3.11.0
â Finishing install process
Followed by a bunch of questions:
- Blog URL â http://<your_domain_address>.com
- MySQL hostname â
hit enter - MySQL username â root
- MySQL password â
- Ghost database name â
hit enter - Do you wish to set up âghostâ mysql user? â yes
- Do you wish to set up Nginx? â yes
- Do you wish to set up SSL? â yes
- Enter your email (For SSL Certificate) â <email_address_you_want_to_use>
- Do you wish to set up Systemd? â yes
- Do you want to start Ghost? â yes
Youâll get some check marks, with some other stuff along the way and hopefully everything goes smoothly for you.
I forgot to change my A server name stuff because I was moving an existing domain from one droplet to a new one. This led to an error on the SSL certificate portion, and it took me too long to figure out where I screwed up. Basically Lets Encrypt timed me out for too many requests and I had to wait an hour to fix that part before my site was live.
Lets Encrypt is a free SSL service that lets you run secure https:// connections. Youâll need it if you want to use Stripe via Ghost memberships or any payment processor for that matter. But itâs also just a generally good practice these days.
The Ghost-CLI documentation is your friend if you get stuck or have to troubleshoot any errors.
Now apparently if it goes smoothly it will prompt you to visit yourblognamehere.com/ghost but mine didnât. I previously knew I had to do this, so you simply navigate there in your web browser to get the ghost admin set up so you can start writing and playing with your site live.
Choose your theme make your changes and Bobâs your uncle. If you only wanted one blog, adios amigo!
If not, keep readingâŠ
Step #5 - Adding Additional Ghost Websites
Here is where things get a little trickierâŠ
Youâll need to logout from your current user situation (sammy in the example above) which is ctrl-d or you can simple type:
$ logout
Make sure youâre using root so you should see something like:
root@ubuntu-nameofserver:~#
As your command line prompt. Or if you created a site and are just logging back into your server it should also take your right to root.
Step A - Create Another New User
To quickly reiterate:
$ adduser janey
Make that user a super user so that they have admin privileges:
$ usermod -aG sudo janey
Login as that new user:
$ su - janey
Step B - Set Up MySQL for New User
Open mysql this time with a slightly different command:
$ mysql -u root -p
When prompted submit your MySQL password from before (this is why you put these things in a safe place). Weâre going to use the same MySQL database here essentially but you need a separate user to keep your ghost websites separated.
Now that youâre in the MySQL shell we need to create a new user. Again, replace janey with whatever you want to use* as your username and the password with whatever you want to use to secure it:
mysql> CREATE USER 'janey'@'localhost' IDENTIFIED BY 'password';
Remember donât remove the quotes, they are needed in SQL queries and you should get a âQuery OKâ response.
*I simply used the same username for MySQL that I did for for my server user to keep things organized but I have a feeling this is not a best practice.
Next make sure you grant this new user the appropriate privileges and assuming you get a good response, you can exit MySQL with ctrl-d or type âexitâ:
mysql> GRANT ALL PRIVILEGES ON *.* TO 'user2'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Step C - Set Up Another New Directory
Similar to before youâll need a new folder for your new ghost install.
$ sudo mkdir -p /var/www/<yoursecondwebsitenamehere>
Make sure change the owner of this new folder to your current user (second one):
$ sudo chown janey:janey /var/www/<yoursecondwebsitenamehere>
And grant yourself the right permissions:
$ sudo chmod 775 /var/www/<yoursecondwebsitenamehere>
Then navigate into that directory:
$ cd /var/www/<yoursecondwebsitenamehere>
Make sure you use your usernames and your site names rather than the ones supplied here.
Step D - Install a New Instance of Ghost
Once here youâll run the same command as before to install ghost but there will be several changes from the first time you did it because youâre putting it on the same droplet as the previous one:
janey@ubuntu-nameofserver:/var/www/<secondblogname>$ ghost install
Iâm just showing you how the command line should look in that example. The command is simply ghost install because we already npm installed it on the root.
This time after you get all your prompts answer the following questions like so:
- Blog URL â http://<your_second_domain_address>.com
- MySQL hostname â
hit enter - MySQL username â
(*or whatever your second username was) - MySQL password â <janeyâs MySQL password>
- Ghost database name â
hit enter (*it creates a new db name for you) - Do you wish to set up âghostâ mysql user? â No (*It should skip thisâŠ)
- Do you wish to set up Nginx? â yes
- Do you wish to set up SSL? â No
- Enter your email (For SSL Certificate) â <email_address_you_want_to_use>
- Do you wish to set up Systemd? â yes
- Do you want to start Ghost? â No
Notice the three Noâs this time? Thatâs really important and youâll see why in a minute. We need to make some changes to this Nginx configuration file before we set up the ssl certificate and start ghost on this site.
Step E - Change Second Siteâs Nginx Configuration
Navigate into your Nginx configuration (config or conf) directory:
$ cd /etc/nginx/sites-enabled/
Then make sure you stop your Nginx server:
$ sudo service nginx stop
*Note: This command will make the server of your first site unavailable until your restart it again.
Open the Ubuntu nano terminal editor and modify your secondblog file:
$ nano <secondblogname>.com.conf
You can use the âlsâ command to list the conf files in this folder if you forget what you named the file exactly.
Change the
You may have to troubleshoot this if you guess wrong, certain ports will be occupied but pretty much any 4 digit combo should in theory work as long as it wasnât the existing one.
...
location / {
...
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:<port>;
}
...
*Remember the port number you choose youâll need it again in a minute.
You donât want two sites going to the same place if they are different sites, so you canât skip this step. If you configure this wrong, youâll likely be directed to site number one. Keep that in mind if you have to troubleshoot it after the fact. Iâd start here with the port number.
When you hit ctrl-x to exit it will ask if you want to save. Make sure you say âyesâ and then hit enter to confirm the save before you exit.
Step E - Restart your Nginx Server and Set Up the SSL
Start your server again:
$ sudo service nginx start
Then navigate back to the second site directory:
$ cd /var/www/<secondblogname>
From here youâll have to open nano again on the config.production.json:
$ nano config.production.json
And make sure you change your config on the port to match whatever port you created on the second sites port:
...
{
"url": "http://<secondblogname>.com",
"server": {
"port": <newportnumber>,
"host": "127.0.0.1"
},
...
Obviously put the port number you chose from before for this new set-up.
Now you can set the ssl with a special command from ghost-cli:
$ ghost setup ssl
Assuming everything goes smoothly you can now start ghost for your second site:
$ ghost start
Now everything should be good to go on yoursecondsitenamehere.com/ghost for you to walk through your admin set up and get that site up and running in a similar manner to the first. Itâs pretty self-explanatory.
If for some reason you run into a roadblock I encourage you to checkout the incredible ghost documentation.
Finishing Up
PhewâŠlong articleâŠ
Alright thatâs it, I now have two ghost sites (working towards at least one more) up and running on one DigitalOcean droplet. Google analytics confirms that people can google them and other visitors have been this week.
Now I have to figure out how to force https:// without any errorsâŠ
Any suggestions?