Self-Hosting Ghost - A Comprehensive Guide for Home Servers

Self-Hosting Ghost - A Comprehensive Guide for Home Servers

While many opt for cloud-hosted solutions, self-hosting Ghost on a home server offers a unique set of advantages that appeal to tech enthusiasts and privacy-conscious bloggers alike.

Disclaimer: This guide is truly comprehensive and covers the entire process of setting up a self-hosted Ghost blog in great detail. It's designed to be thorough and informative, which means it's also quite lengthy. If you're looking for a quick setup guide, this might be more in-depth than you need. However, if you want to understand every step of the process and gain a deep understanding of self-hosting Ghost, you're in the right place. Grab a coffee, settle in, and prepare for an informative journey into the world of self-hosting!

Introduction

Ghost has emerged as a powerful, open-source blogging platform, favored by content creators for its sleek design, robust features, and focus on performance. While many opt for cloud-hosted solutions, self-hosting Ghost on a home server offers a unique set of advantages that appeal to tech enthusiasts and privacy-conscious bloggers alike.

Why Self-Host Ghost?

  1. Complete Control: By hosting Ghost on your own hardware, you have full control over your data, content, and the entire stack.
  2. Cost-Effective: After initial setup costs, running Ghost on a home server can be more economical in the long run compared to paid hosting solutions.
  3. Learning Opportunity: Self-hosting is an excellent way to gain hands-on experience with server management, networking, and web technologies.
  4. Customization: You have the freedom to modify and optimize every aspect of your Ghost installation and server environment.
  5. Privacy: Keep your data and content entirely under your own roof, literally.

This guide builds upon the concept of our previous article about setting up Ghost on Linode, but is tailored specifically for a home server environment. Self-hosting at home presents its own unique set of challenges and rewards, offering a deeper dive into server management, networking concepts, and the intricacies of running a web application from a residential internet connection.

By the end of this comprehensive guide, you'll have a fully functional Ghost blog running on your home server, secured with SSL, and accessible from anywhere on the internet. We'll cover everything from initial server setup to advanced topics like reverse proxies and security considerations.

Whether you're a tech enthusiast looking to expand your homelab, a blogger seeking more control over your platform, or simply curious about the world of self-hosting, this guide will walk you through the process step by step.

Prerequisites

Before we embark on our Ghost self-hosting journey, it's crucial to ensure you have all the necessary components in place. Let's break down each prerequisite in detail:

Hardware Requirements

  • A dedicated computer or virtual machine: This will serve as your home server. It could be an old PC, a Raspberry Pi (4 or newer recommended for better performance), or a virtual machine on your main computer.
    • Minimum specifications:
      • CPU: Dual-core processor (2 GHz or higher)
      • RAM: 2 GB (4 GB recommended for smoother performance)
      • Storage: At least 20 GB of free space (SSD preferred for faster performance)
    • Note: While Ghost can run on lower specs, these recommendations ensure a smooth experience, especially as your blog grows.
  • A reliable internet connection: Uptime is crucial for a blog. Aim for:
    • Download speed: At least 10 Mbps
    • Upload speed: At least 5 Mbps (higher is better for serving content)
    • Stable connection with minimal outages

Software Requirements

  • Ubuntu 20.04 LTS or newer: We're using Ubuntu Server for its stability, wide community support, and compatibility with Ghost. The LTS (Long Term Support) version ensures you'll receive updates for an extended period.
  • SSH client: For remote access to your server. Options include:
    • Windows: PuTTY or the built-in Windows 10/11 SSH client
    • macOS/Linux: Terminal (built-in)
  • Basic command-line knowledge: Familiarity with navigating directories, editing files, and running commands in a terminal will be beneficial.

Networking Requirements

  • A registered domain name: Your blog needs an address on the internet. You can purchase domains from registrars like Namecheap, GoDaddy, or Google Domains.
  • Access to your router's settings: You'll need to set up port forwarding to make your server accessible from the internet. Ensure you can access your router's admin panel.
  • Static internal IP for your server: Set this up in your router's DHCP settings to ensure your server always gets the same local IP address.

Additional Considerations

  • Basic understanding of web servers and DNS: While not strictly necessary, having a grasp of these concepts will help you troubleshoot issues and understand the setup process better.
  • Patience and willingness to learn: Self-hosting can be challenging at times, but it's incredibly rewarding. Be prepared to do some troubleshooting and learning along the way.
  • Backup strategy: Consider how you'll back up your blog data. This could be as simple as periodic manual backups or a more automated solution.

With these prerequisites in place, you're well-equipped to begin your journey into self-hosting Ghost. In the next section, we'll dive into the initial server setup, laying the groundwork for a secure and efficient Ghost installation.

Server Setup

A solid foundation is crucial for a secure and efficient Ghost installation. In this section, we'll prepare our Ubuntu server with essential security measures and create a dedicated user for Ghost.

Initial Configuration

  1. Update and Upgrade Your System:
    Always start with a fully updated system to ensure you have the latest security patches and software versions.

    sudo apt update && sudo apt upgrade -y
    

    This command updates the package lists and then upgrades all installed packages to their latest versions.

  2. Set Up a Firewall:
    UFW (Uncomplicated Firewall) provides a user-friendly way to set up a firewall, an essential security measure for any server.

    sudo apt install ufw
    sudo ufw allow OpenSSH
    sudo ufw enable
    

    These commands install UFW, allow SSH connections (so you don't lock yourself out), and enable the firewall. We'll open additional ports later as needed.

Creating a Non-Root User

Running services as the root user is a security risk. Let's create a dedicated user for Ghost:

  1. Create a New User:

    sudo adduser ghostuser
    

    Follow the prompts to set a strong password and (optionally) fill in user information.

  2. Grant Sudo Privileges:
    To perform administrative tasks, your new user needs sudo privileges:

    sudo usermod -aG sudo ghostuser
    

    This adds 'ghostuser' to the sudo group.

  3. Switch to the New User:

    su - ghostuser
    

    You'll be prompted for the password you set earlier.

For added security, consider these SSH tweaks:

  1. Edit the SSH Configuration:

    sudo nano /etc/ssh/sshd_config
    
  2. Make the Following Changes:

    • Disable root login: PermitRootLogin no
    • Use SSH key authentication: PasswordAuthentication no
    • Change the default SSH port (e.g., to 2222): Port 2222
  3. Restart the SSH Service:

    sudo systemctl restart sshd
    

    Remember to update your firewall if you changed the SSH port:

    sudo ufw allow 2222/tcp
    sudo ufw delete allow OpenSSH
    

Installing Ghost

Now that our server is set up and secured, let's install Ghost using the official Ghost-CLI tool.

Installing Ghost-CLI

  1. Install Node.js and npm:
    Ghost requires Node.js to run. We'll use the NodeSource repository to get the latest LTS version:

    curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
    sudo apt-get install -y nodejs
    

    This installs Node.js 14.x and npm (Node Package Manager).

  2. Install Ghost-CLI Globally:
    The Ghost-CLI tool simplifies the process of installing and managing Ghost:

    sudo npm install ghost-cli@latest -g
    

Setting up Ghost

  1. Create a Directory for Ghost:
    Ghost needs its own directory to operate:

    sudo mkdir -p /var/www/ghost
    sudo chown ghostuser:ghostuser /var/www/ghost
    sudo chmod 775 /var/www/ghost
    cd /var/www/ghost
    

    These commands create the directory, set the correct ownership, and navigate to it.

  2. Install Ghost:
    Now, we'll use Ghost-CLI to install Ghost:

    ghost install
    

    During the installation process, you'll be prompted to answer several questions:

    • Blog URL: Enter your domain (e.g., https://yourdomain.com)
    • MySQL hostname: Use 'localhost' unless you're using an external database
    • MySQL username and password: Create these or use existing credentials
    • Ghost database name: Choose a name for your Ghost database
    • Set up Nginx: Choose 'no' (we'll be using Traefik instead)
    • Set up SSL: Choose 'no' (we'll handle this with Let's Encrypt via Traefik)
    • Set up Systemd: Choose 'yes' for automatic startup
    • Start Ghost: Choose 'yes'

Configuring Ghost

After installation, you can access your Ghost admin panel at http://your_server_ip/ghost. Here, you'll set up your admin account and can start customizing your blog.

Key areas to configure:

  • Site title and description
  • Theme selection
  • Navigation menu
  • User accounts (if you plan to have multiple authors)

Remember, at this point, your blog is only accessible within your local network. In the next section, we'll set up Traefik to make it accessible from the internet and secure it with SSL.

5. Docker and Traefik Setup

Now that Ghost is installed and running locally, we'll set up Docker to run Traefik, which will act as our reverse proxy and handle SSL certificates via Let's Encrypt. This setup will make your Ghost blog securely accessible from the internet.

Understanding the Setup

Before we dive in, let's clarify what we're doing:

  • Docker will run Traefik in a container, isolating it from your main system.
  • Traefik will act as a reverse proxy, directing incoming web traffic to your Ghost blog.
  • Traefik will also automatically obtain and renew SSL certificates from Let's Encrypt, ensuring your site is served over HTTPS.

Installing Docker

  1. Update the package index and install prerequisites:

    sudo apt-get update
    sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
    
  2. Add Docker's official GPG key:

    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    
  3. Set up the stable Docker repository:

    sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
    
  4. Install Docker:

    sudo apt-get update
    sudo apt-get install docker-ce
    
  5. Add your user to the docker group (this allows you to run Docker commands without sudo):

    sudo usermod -aG docker ${USER}
    

    Note: You'll need to log out and back in for this change to take effect.

  6. Install Docker Compose:

    sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    sudo chmod +x /usr/local/bin/docker-compose
    

Setting up Traefik and Let's Encrypt

Now, we'll create a Docker Compose file to set up Traefik with Let's Encrypt:

  1. Create a new directory for your Traefik configuration:

    mkdir ~/traefik
    cd ~/traefik
    
  2. Create a docker-compose.yml file:

    nano docker-compose.yml
    
  3. Add the following content to the file:

    version: '3'
    
    services:
      traefik:
        image: traefik:v2.5
        container_name: traefik
        restart: unless-stopped
        security_opt:
          - no-new-privileges:true
        ports:
          - 80:80
          - 443:443
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /var/run/docker.sock:/var/run/docker.sock:ro
          - ./traefik.yml:/traefik.yml:ro
          - ./acme.json:/acme.json
        networks:
          - proxy
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.traefik.entrypoints=http"
          - "traefik.http.routers.traefik.rule=Host(`traefik.yourdomain.com`)"
          - "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$1234abcd$$1234abcd1234abcd"
          - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
          - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
          - "traefik.http.routers.traefik-secure.entrypoints=https"
          - "traefik.http.routers.traefik-secure.rule=Host(`traefik.yourdomain.com`)"
          - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
          - "traefik.http.routers.traefik-secure.tls=true"
          - "traefik.http.routers.traefik-secure.tls.certresolver=http"
          - "traefik.http.routers.traefik-secure.service=api@internal"
    
    networks:
      proxy:
        external: true
    

    Note: Replace yourdomain.com with your actual domain name.

  4. Create a traefik.yml file:

    nano traefik.yml
    
  5. Add the following content:

    api:
      dashboard: true
    entryPoints:
      http:
        address: ":80"
      https:
        address: ":443"
    providers:
      docker:
        endpoint: "unix:///var/run/docker.sock"
        exposedByDefault: false
    certificatesResolvers:
      http:
        acme:
          email: [email protected]
          storage: acme.json
          httpChallenge:
            entryPoint: http
    

    Replace [email protected] with your actual email address.

  6. Create an empty acme.json file and set proper permissions:

    touch acme.json
    chmod 600 acme.json
    
  7. Start Traefik:

    docker-compose up -d
    

At this point, Traefik is running in a Docker container, but it's not yet configured to proxy requests to your Ghost blog. In the next section, we'll set up the necessary configuration to connect Traefik with Ghost and make your blog accessible from the internet.

Remember, you'll also need to set up port forwarding on your router to direct incoming traffic on ports 80 and 443 to your server. The exact steps for this vary depending on your router model, but generally involve accessing your router's admin interface and setting up port forwarding rules.

Connecting Traefik to Ghost

Now that Traefik is running, we need to configure it to proxy requests to our Ghost blog. This involves modifying our Ghost configuration and setting up a Traefik-specific configuration for Ghost.

Modifying Ghost Configuration

  1. Edit the Ghost configuration file:

    sudo nano /var/www/ghost/config.production.json
    
  2. Update the url field to use your domain name:

    {
      "url": "https://yourdomain.com",
      ...
    }
    
  3. Save the file and exit the editor.

Creating a Traefik Configuration for Ghost

  1. Create a new file for Ghost's Traefik configuration:

    nano ~/traefik/ghost.yml
    
  2. Add the following content:

    http:
      routers:
        ghost:
          rule: "Host(`yourdomain.com`)"
          entryPoints:
            - "https"
          service: ghost
          tls:
            certResolver: http
      services:
        ghost:
          loadBalancer:
            servers:
              - url: "http://IP_OF_YOUR_SERVER:2368"
    

    Replace yourdomain.com with your actual domain and IP_OF_YOUR_SERVER with your server's local IP address.

  3. Save the file and exit the editor.

  4. Update the Traefik docker-compose file to include this new configuration:

    nano ~/traefik/docker-compose.yml
    

    Add the following line under the volumes section of the Traefik service:

    - ./ghost.yml:/ghost.yml:ro
    
  5. Restart Traefik to apply the changes:

    docker-compose down && docker-compose up -d
    

Networking Setup

To make your Ghost blog accessible from the internet, you need to configure your home network properly.

Port Forwarding

  1. Access your router's admin interface. This is typically done by entering your router's IP address in a web browser.

  2. Find the Port Forwarding section. This might be under Advanced Settings or Security.

  3. Create two new port forwarding rules:

    • Forward external port 80 to internal port 80 on your server's IP address
    • Forward external port 443 to internal port 443 on your server's IP address
  4. Save the settings and restart your router if required.

If your home IP address changes frequently, setting up Dynamic DNS can ensure your domain always points to your current IP.

  1. Choose a Dynamic DNS provider. Some popular options include No-IP, DuckDNS, or Dynu.

  2. Create an account and set up a hostname.

  3. Install the Dynamic DNS client on your server or configure your router to update the IP automatically.

Updating DNS Records

  1. Log in to your domain registrar's website.

  2. Find the DNS management section.

  3. Create or update the following DNS records:

    • An A record pointing your domain (e.g., yourdomain.com) to your home IP address
    • An A record for www (e.g., www.yourdomain.com) also pointing to your home IP address
  4. Save the changes. Note that DNS propagation can take up to 48 hours, though it's often much quicker.

Final Steps and Testing

  1. Restart Ghost to ensure it picks up the new configuration:

    ghost restart
    
  2. Check Traefik logs for any errors:

    docker logs traefik
    
  3. Test your setup by visiting https://yourdomain.com in a web browser. You should see your Ghost blog, served over HTTPS.

  4. Access the Ghost admin panel at https://yourdomain.com/ghost and ensure everything is working correctly.

Congratulations! Your Ghost blog should now be accessible from the internet, secured with SSL, and proxied through Traefik.

In the next section, we'll cover some important security considerations and best practices for maintaining your self-hosted Ghost blog.

Security Considerations and Best Practices

Now that your Ghost blog is up and running, it's crucial to maintain a secure environment. Here are some key areas to focus on:

Regular Updates

Keeping your system and Ghost installation up-to-date is crucial for security.

  1. Update Ubuntu:

    sudo apt update && sudo apt upgrade -y
    

    Run this command regularly, at least once a week.

  2. Update Ghost:

    cd /var/www/ghost
    ghost update
    

    Check for Ghost updates weekly and apply them promptly.

  3. Update Docker images:

    docker-compose pull
    docker-compose up -d
    

    Run these commands in your Traefik directory to update the Traefik image.

Firewall Configuration

Ensure your firewall is properly configured to only allow necessary traffic.

  1. Check current UFW status:

    sudo ufw status
    
  2. Ensure only necessary ports are open:

    sudo ufw allow 22/tcp  # SSH
    sudo ufw allow 80/tcp  # HTTP
    sudo ufw allow 443/tcp # HTTPS
    
  3. Enable UFW if not already active:

    sudo ufw enable
    

Secure SSH Access

If you haven't already, consider implementing these SSH security measures:

  1. Disable root login and password authentication in /etc/ssh/sshd_config:

    PermitRootLogin no
    PasswordAuthentication no
    
  2. Use SSH keys for authentication instead of passwords.

  3. Consider changing the default SSH port to reduce automated attacks.

Regular Backups

Implement a robust backup strategy to protect your content and configuration.

  1. Ghost content:
    Use Ghost's built-in backup feature or set up automated MySQL dumps.

  2. Configuration files:
    Regularly backup important configuration files, including:

    • /var/www/ghost/config.production.json
    • Your Traefik configuration files
  3. Consider using rclone or a similar tool to automatically sync your backups to cloud storage.

Monitoring

Set up monitoring to keep track of your server's health and performance.

  1. Install Netdata for real-time performance monitoring:

    bash <(curl -Ss https://my-netdata.io/kickstart.sh)
    
  2. Set up Uptime Robot or a similar service to monitor your site's availability from external locations.

SSL/TLS Best Practices

Ensure your SSL/TLS configuration is strong and up-to-date.

  1. Regularly check your SSL configuration using tools like SSL Labs' Server Test.

  2. Keep Traefik updated to ensure you have the latest SSL/TLS features and security fixes.

Content Security Policy

Implement a Content Security Policy to protect against XSS attacks.

  1. Add CSP headers in your Traefik configuration or directly in Ghost's config.production.json.

Database Security

Ensure your MySQL database is secure.

  1. Use strong passwords for database accounts.

  2. Regularly update MySQL and apply security patches.

  3. Consider encrypting your database for an extra layer of security.

Optimization and Performance Tuning

To ensure your self-hosted Ghost blog runs smoothly and efficiently, consider these optimization techniques:

Caching

  1. Enable Ghost's built-in caching:
    Edit /var/www/ghost/config.production.json and add:

    "caching": {
      "frontend": {
        "maxAge": 600
      }
    }
    
  2. Consider using a CDN like Cloudflare to cache static assets and improve global performance.

Image Optimization

  1. Use Ghost's built-in image optimization features.

  2. Consider using a plugin or service for additional image compression.

Database Optimization

  1. Regularly optimize your MySQL database:
    mysqlcheck -o ghost_db_name -u root -p
    

Monitor and Adjust Resources

  1. Use Netdata to monitor resource usage and identify bottlenecks.

  2. Adjust Ghost's memory usage if needed by modifying the config.production.json file.

By following these security best practices and optimization techniques, you'll ensure that your self-hosted Ghost blog remains secure, performs well, and provides a great experience for both you and your readers.

Remember, self-hosting is an ongoing process. Stay informed about the latest security practices, keep your systems updated, and regularly review and adjust your setup as needed.

Conclusion and Further Resources

Wrapping Up

Congratulations! You've successfully set up a self-hosted Ghost blog on your home server. This journey has taken you through server setup, Ghost installation, reverse proxy configuration with Traefik, security hardening, and performance optimization. Self-hosting your Ghost blog offers unparalleled control over your content and infrastructure, but it also comes with the responsibility of maintaining and securing your setup.

Benefits and Challenges of Self-Hosting Ghost

Benefits:

  1. Complete control over your data and content
  2. Customization freedom
  3. Potential cost savings in the long run
  4. Valuable learning experience in server management and web technologies

Challenges:

  1. Requires ongoing maintenance and updates
  2. Responsibility for security lies entirely with you
  3. Potential for downtime if your home internet or power goes out
  4. Initial setup can be complex for beginners

Resources for Further Learning

  1. Official Ghost Documentation: https://ghost.org/docs/
  2. Ghost Community Forum: https://forum.ghost.org/
  3. Docker Documentation: https://docs.docker.com/
  4. Traefik Documentation: https://doc.traefik.io/traefik/

Upcoming Articles in Our Self-Hosting Series

Stay tuned for these in-depth guides that will expand on topics covered in this article:

  1. "Mastering Traefik: Advanced Reverse Proxy Techniques for Home Servers" Dive deeper into Traefik configuration, load balancing, and advanced routing strategies.
  2. "Securing Your Home Server: A Comprehensive Guide to Self-Hosted Security" Explore advanced security practices, intrusion detection, and hardening techniques for your self-hosted applications.
  3. "Optimizing Ghost Performance: Advanced Tuning for High-Traffic Blogs" Learn how to scale your Ghost blog, optimize database performance, and implement advanced caching strategies.
  4. "Disaster Recovery for Self-Hosters: Backup and Restore Strategies" Develop a robust backup plan, automate your backups, and practice failover scenarios for your self-hosted services.
  5. "Monitoring and Maintaining Your Home Server Ecosystem" Set up comprehensive monitoring, alerting, and automated maintenance for your self-hosted applications.

Final Thoughts

Self-hosting Ghost is more than just running a blog—it's an opportunity to take control of your online presence and expand your technical skills. As you continue on this journey, remember to stay curious, keep learning, and don't hesitate to experiment with your setup.

We encourage you to stay updated with the latest Ghost releases, server security best practices, and web technologies. The world of self-hosting is always evolving, offering new challenges and opportunities for growth.

Thank you for following this guide. We hope it has been informative and empowering. Happy blogging, and may your self-hosted Ghost adventure be rewarding and successful!

You've successfully subscribed to The Backlog Chronicles
Great! Next, complete checkout for full access to The Backlog Chronicles
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info is updated.
Billing info update failed.