How to Self-Host Ghost CMS on a VPS: Newsletter, Membership, and Blog Without Ghost(Pro) Fees

How to Self-Host Ghost CMS on a VPS: Newsletter, Membership, and Blog Without Ghost(Pro) Fees

Ghost is the leading open-source publishing platform for blogs, newsletters, and membership sites. Ghost(Pro) costs $9–$199/month depending on subscriber count. Self-hosting Ghost on a VPS eliminates the platform fee entirely — you pay only for the VPS and your email delivery service. For publications with large subscriber lists where Ghost(Pro) charges $199+/month, self-hosting saves thousands annually.

Ghost vs WordPress: When Ghost Wins

  • Choose Ghost: Pure publishing focus, built-in newsletter and membership, clean editor, fast by default, native Stripe integration, no plugin maintenance
  • Choose WordPress: Needs ecommerce, page builder, extensive plugin ecosystem, large team with different content types

Server Requirements

  • Ubuntu 22.04 or 24.04 LTS
  • Minimum 1 GB RAM (2 GB recommended for active newsletters)
  • Node.js 20.x, MySQL 8.0, Nginx
  • A domain with email delivery service (Mailgun, Postmark, or SendGrid)

Step 1: Install Dependencies

<code">sudo apt update && sudo apt upgrade -y

# Node.js 20 LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# MySQL 8.0
sudo apt install -y mysql-server
sudo mysql_secure_installation

# Nginx and Certbot
sudo apt install -y nginx certbot python3-certbot-nginx

# Ghost CLI
sudo npm install -g ghost-cli

node --version   # Verify Node.js 20.x
ghost --version  # Verify Ghost CLI

Step 2: Create Ghost User and Directory

<code"># Ghost requires a non-root user
sudo adduser --disabled-password --gecos "" ghost-user
sudo usermod -aG sudo ghost-user

# Create and own the Ghost directory
sudo mkdir -p /var/www/ghost
sudo chown ghost-user:ghost-user /var/www/ghost
sudo chmod 775 /var/www/ghost

# Switch to ghost-user for installation
sudo su - ghost-user

Step 3: Create MySQL Database

<code">sudo mysql -u root -p
<code">CREATE DATABASE ghost_production CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'ghost'@'localhost' IDENTIFIED BY 'StrongGhostPassword!';
GRANT ALL PRIVILEGES ON ghost_production.* TO 'ghost'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Step 4: Install Ghost

<code"># As ghost-user
cd /var/www/ghost

ghost install \
  --url https://yourdomain.com \
  --db mysql \
  --dbhost localhost \
  --dbuser ghost \
  --dbpass StrongGhostPassword! \
  --dbname ghost_production \
  --mail SMTP \
  --mailhost smtp.mailgun.org \
  --mailport 587 \
  --mailuser postmaster@mg.yourdomain.com \
  --mailpass your_mailgun_password \
  --mailservice Mailgun \
  --mailfrom noreply@yourdomain.com

# Ghost CLI will:
# 1. Download and install Ghost
# 2. Configure Nginx with SSL (via Certbot)
# 3. Set up systemd service
# 4. Start Ghost

ghost status   # Verify running

Step 5: Manual Nginx Configuration (if needed)

<code">sudo nano /etc/nginx/sites-available/ghost
<code">server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    client_max_body_size 50m;

    location / {
        proxy_pass http://127.0.0.1:2368;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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_cache_bypass $http_upgrade;
    }
}

Step 6: Configure Ghost Settings

<code">cat /var/www/ghost/config.production.json

Key settings to verify or add:

<code">{
  "url": "https://yourdomain.com",
  "server": {
    "port": 2368,
    "host": "127.0.0.1"
  },
  "database": {
    "client": "mysql8",
    "connection": {
      "host": "127.0.0.1",
      "port": 3306,
      "user": "ghost",
      "password": "StrongGhostPassword!",
      "database": "ghost_production"
    }
  },
  "mail": {
    "transport": "SMTP",
    "options": {
      "service": "Mailgun",
      "host": "smtp.mailgun.org",
      "port": 587,
      "auth": {
        "user": "postmaster@mg.yourdomain.com",
        "pass": "your_mailgun_password"
      }
    }
  },
  "imageOptimization": {
    "resize": true,
    "srcsets": true
  },
  "logging": {
    "transports": ["file", "stdout"]
  }
}

Step 7: Set Up Paid Memberships with Stripe

  1. Ghost Admin → Settings → Membership → Enable memberships
  2. Connect Stripe: Settings → Membership → Stripe → Connect with Stripe
  3. Set pricing tiers: monthly and annual subscription prices
  4. Customize the signup page and member portal
  5. Create members-only content: Posts → change Visibility to “Members only” or “Paid members only”

Step 8: Newsletter Configuration

  1. Ghost Admin → Settings → Email newsletter
  2. Configure sender name and email address
  3. Set up Mailgun domain authentication (SPF, DKIM) for deliverability
  4. Test newsletter: create a post → Email newsletter tab → Send test email

Ghost Management Commands

<code"># All commands run as ghost-user in /var/www/ghost
ghost status         # Check running status
ghost stop           # Stop Ghost
ghost start          # Start Ghost
ghost restart        # Restart Ghost
ghost update         # Update to latest version
ghost log            # View recent logs
ghost config         # View configuration
ghost doctor         # Diagnose common issues

Backup Ghost

<code"># Export content via Ghost Admin:
# Ghost Admin → Settings → Labs → Export your content (downloads JSON)

# Backup database directly
mysqldump -u ghost -p ghost_production | \
    gzip > /opt/backups/ghost-db-$(date +%Y%m%d).sql.gz

# Backup uploaded images and themes
tar czf /opt/backups/ghost-content-$(date +%Y%m%d).tar.gz \
    /var/www/ghost/content/

Custom Themes

<code"># Install a custom theme
cd /var/www/ghost/content/themes
git clone https://github.com/yourtheme/ghost-theme mytheme

# Or upload via Ghost Admin:
# Ghost Admin → Settings → Design → Upload a theme

# Restart Ghost after theme changes
ghost restart

Getting Started

Ghost on a 1–2 GB Ubuntu VPS at VPS.DO handles publications with 10,000–100,000 subscribers comfortably. The Ghost CLI automates Nginx configuration and SSL certificates. For publications currently on Ghost(Pro) at $199/month (50,000 subscribers), migrating to self-hosting on a $20/month VPS saves $2,148 annually — with full control over your data, themes, and infrastructure.

Conclusion

Self-hosted Ghost provides the full publishing platform — blog, newsletter, and paid memberships — without Ghost(Pro)’s subscriber-based pricing. The Ghost CLI makes installation and updates straightforward, Nginx and Let’s Encrypt handle SSL, Mailgun handles newsletter delivery, and Stripe handles paid subscription billing. For serious publications, self-hosting Ghost is the most cost-effective path to owning your publishing infrastructure.

Fast • Reliable • Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!