How to Self-Host and Install Ghost on Your Linux Server

Ghost is an open-source content management program that allows you to easily create a blog and a newsletter service. You can choose to subscribe to the Ghost(Pro) service to use the CMS, or, if you are more technically inclined, self-host it on your server. Here we show you the latter – self-host Ghost on your Linux server.

Why You Should Self-host Ghost on Your Server

One of the advantages of a Ghost blog is that it provides an integrated, feature-filled platform that works right out of the box. This includes the ability to track analytics, monetize posts, and create automatic newsletters for your subscribers.

Installing Ghost on your server allows you to be a publisher without relying on a third party to manage your data. This can be helpful if you are a journalist who is putting out critical articles about controversial topics.

Lastly, Ghost is easy to deploy and maintain, even for non-technical users. Unlike traditional CMS platforms, Ghost provides an all-in-one solution that you can “set and forget” on your hosting machine.

Good to know: Learn how to host a web archive on Linux using Archivebox.

Installing Ghost on your Server

Assumption: Before we start, we assume that you already have a Linux server available and a domain name to host your Ghost installation. If you need to rent a Linux server, we recommend DigitalOcean or Linode.

Since we will be using Docker, we will need to install Docker on the server first.

1. Install the Docker project’s repository public key:

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

2. Create a new repository file in your machine’s apt config directory:

sudo nano /etc/apt/sources.list.d/docker.list

3. Paste the following line of code inside your new repository file:

deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] jammy stable

4. Refresh your system’s repository listings and upgrade the existing binaries in your machine:

sudo apt update
sudo apt upgrade

5. Install Docker and Docker Compose along with their dependencies:

sudo apt install wget docker-ce docker-ce-cli docker-compose-plugin docker-buildx-plugin

6. Add your user to the Docker group

sudo usermod -aG docker $USER

7. Set Docker service to run on startup:

sudo systemctl enable docker.service

8. Reboot the server.

Setting Up Gmail for SMTP Delivery

Ghost doesn’t come with its own email delivery client, so we need to hook it up to Gmail for email delivery.

1. Open a web browser and login to the Gmail account that you want to link to your Ghost instance.

2. Click the Profile Icon of your account, then click “Manage your Google Account.”

3. Select the “Security” category, then click the “2-Step Verification” option under the “How you sign in to Google” subcategory.

A screenshot highlighting the 2-Step Verification process for Gmail accounts.

4. Verify your phone number and enable 2-step Verification.

5. Go back to the “Security” category, then click the “2-Step Verification” option again. This will open a new menu screen where you can set new secondary keys for your account. Scroll to the bottom of the page, then click “App passwords.”

A screenshot showing the

6. Select “Mail” for the first dropdown list, then select “Other” on the second.

7. Write “Gmail for Ghost” on the textbox, then click “Generate.” This will open a window with a yellow textbox containing your custom application password.

A screenshot showing the generated Application Password for Ghost.

FYI: You can also use other external delivery agents to send mail through Ghost. Learn how to create your own email server using Mail-in-a-Box.

Building the Docker Container

1. Create a new directory for your Ghost installation’s dockerfiles:

2. Create a new docker-compose.yml file using your favorite text editor:

nano ./docker-compose.yml

3. Paste the following block of code inside your new docker-compose.yml file and save it.

version: "3"
    image: ghost:latest
    restart: always
      - 8080:2368
      database__client: mysql
      database__connection__host: db
      database__connection__database: ghost
      database__connection__user: ghost
      database__connection__password: ghost
      url: ${GHOST_URL}
      mail__transport: ${MAIL_TRANSPORT}
      mail__options__host: ${MAIL_HOST}
      mail__options__port: ${MAIL_PORT}
      mail__options__secureConnection: ${MAIL_SECURE_CONNECTION}
      mail__options__auth__user: ${MAIL_USER}
      mail__options__auth__pass: ${MAIL_PASSWORD}
      - ghost-data:/var/lib/ghost/content
      - db
    image: mysql:8.0
    restart: always
      MYSQL_DATABASE: ghost
      MYSQL_USER: ghost
      MYSQL_PASSWORD: ghost
      - SYS_NICE
      - ghost-db:/var/lib/mysql
  ghost-data: null
  ghost-db: null

4. Create a “.env” file inside your Ghost docker directory:

5. Paste the following block of code inside your new .env file:

# Database
# SMTP variables
  • Change the value for the “GHOST_URL” variable from “#REPLACE_ME_WITH_DOMAIN_NAME#” to your complete domain name.
A terminal showing the URL for a remote Ghost instance.
  • Replace the value of the “MYSQL_ROOT_PASSWORD” with a sufficiently random password.
  • Change the value of both the “MAIL_USER” and “MAIL_PASSWORD” with the email address of your Gmail account and its Application Password.

Note: You need to write the Gmail application password with no spaces in between each segment.

6. Build the Ghost Docker container by running the following command:

sudo docker compose up -d

Setting up a Reverse Proxy

With Ghost running in the backend, we need to set up a reverse proxy to be able to access Ghost publicly. In this case, we will use Nginx’s reverse proxy.

1. Install the Nginx web server package. This will serve as your reverse proxy daemon which will take connections from the internet and redirect it to Ghost.

2. Create a new Nginx site config file using your favorite text editor:

sudo nano /etc/nginx/sites-available/ghost

3. Paste the following block of code inside your new site config file:

server {
   listen 80;
   listen [::]:80;
   root                    /var/www/html;
   server_name   ;
   location / {
       proxy_set_header    X-Forwarded-For $remote_addr;
       proxy_set_header    Host $http_host;
       proxy_set_header    X-Forwarded-Proto $scheme;

4. Create a symbolic link for your Ghost site config:

sudo ln -s /etc/nginx/sites-available/ghost /etc/nginx/sites-enabled/

5. Enable the Nginx web server service using systemctl:

sudo systemctl enable --now nginx.service

Enabling SSL on Your Nginx Reverse Proxy

1. Ensure that the “core” snap package is present in your machine:

2. Install the certbot snap package:

sudo snap install certbot --classic

3. Register your certbot installation to your email address by running the following command:

sudo certbot register --agree-tos --email ramces@email.invalid

4. Request a new SSL certificate for your Ghost blog:

sudo certbot --nginx -d

5. Test whether your new Ghost instance is accessible through SSL by opening a web browser and loading your domain name.

A screenshot showing a working Ghost instance from a remote server.

Running Ghost on a Local Machine

If you don’t have a server and want to install Ghost on your local machine, you can too. In addition, you can make use of Tailscale to access it everywhere on your browser.

1. Install the Tailscale VPN daemon in your machine and link it to your Tailscale account. Go to your Tailscale Administrator Console and click the “DNS” tab on the console’s top bar.

A screenshot highlighting the DNS tab on the Tailscale Admin Console.

2. Click the “Rename tailnet…” button under the “Tailnet name” subcategory.

A screenshot highlighting the

3. Set your machine’s hostname to “ghost” followed by the new subdomain for your Tailscale network:

sudo hostnamectl set-hostname

Enabling Tailscale Funnel

1. Open the Tailscale Administrator Console and click the “DNS” tab.

2. Scroll down to the bottom of the page then click “Enable HTTPS…”

A screenshot showing the HTTPS option for Tailscale hosts.

3. Scroll back up to the top of the page, then click the “Access control” tab.

A screenshot highlighting the

4. Click the “Add Funnel to policy” button.

A screenshot highlighting the

5. Run the following command to create a reverse proxy between Tailscale and your local Docker container:

sudo tailscale serve https /

6. Enable the Tailscale funnel for your reverse proxy by running the following command:

sudo tailscale funnel 443 on

7. Test whether your new Ghost instance is accessible through your Tailscale funnel by opening a web browser and loading your Tailscale address.

A screenshot showing a working Ghost installation over Tailscale.

Using Ghost The First Time

1. Open a web browser and navigate to your Ghost installation URL followed by the subdirectory “/ghost.”

A screenshot of a web browser's address bar showing the correct URL for the Ghost setup page.

2. Click the first field and provide a name for your new Ghost blog. Fill in the rest of the fields with details about your admin user, then click “Create account & start publishing.”

A screenshot showing the

Creating Your First Post in Ghost

1. Click the “Write your first post” button on the Ghost onboarding page.

A screenshot showing the first steps onboarding page for Ghost.

2. This will bring up a plain text editor where you can write a simple text post. Click “Publish” once you are done to create a new test post.

3. Check your Ghost front page to see if the new post went through.

Adding a New User to Ghost

1. Go back to your Ghost Administrator Console, then click “Members” on the page’s left sidebar.

2. Click the “New Member” button on the page’s upper right corner.

A screenshot showing the list of members on the current Ghost instance.

3. Fill in the details of your new member, then click “Save” to add them on the blog’s newsletter feed.

Good to know: Learn how to deploy and host your own Twitter clone using Pleroma.

Frequently Asked Questions

Does Tailscale Funnel have any restrictions?

Yes. By default, you can only expose traffic on Tailscale through three ports: 443, 8443 and 10000 and only using TCP. This means that you will not be able to expose any real-time online service such as VoIP and game servers.

Can I personalize the Tailscale domain name?

No. This is because each Tailscale DNS address is tailored for your specific account. This allows the service to identify your machines from others inside the greater Tailscale network.

Will my Ghost blog stop running when my computer is offline?

Yes. One of the downsides of hosting on your own hardware is that your website’s uptime depends on the uptime of your machine. This means that whenever your host machine goes down, so does your Ghost blog.

Image credit: WORKING OFFICE COMMUNICATION PEOPLE USING COMPUTER BLOG CONCEPT and traditional halloween ghost cookie by 123RF.

Ramces Red
Ramces Red

Ramces is a technology writer that lived with computers all his life. A prolific reader and a student of Anthropology, he is an eccentric character that writes articles about Linux and anything *nix.

Subscribe to our newsletter!

Our latest tutorials delivered straight to your inbox

Related Posts