Software & Configuration

Ghost

Self-hosted Ghost blog and newsletter platform, Docker installation with MySQL and Nginx reverse proxy

Ghost is a modern, performance-focused blogging and newsletter platform. Self-hosted Ghost provides complete control, unlimited content, and powerful newsletter capabilities without hosting fees, making it an excellent alternative to WordPress for content creators.


Requirements

  • Docker and Docker Compose
  • MySQL 8 or MariaDB database
  • Domain name with DNS configured
  • 2GB+ RAM recommended
  • Port 80 and 443 accessible

Installation with Docker Compose

Create docker-compose.yml

mkdir -p /opt/ghost && cd /opt/ghost
nano docker-compose.yml

Add the following configuration:

version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: ghost-mysql
    restart: always
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: change_me_secure_password
      MYSQL_DATABASE: ghost
      MYSQL_USER: ghost
      MYSQL_PASSWORD: change_me_ghost_password
    ports:
      - "127.0.0.1:3306:3306"

  ghost:
    image: ghost:5-alpine
    container_name: ghost-blog
    restart: always
    depends_on:
      - mysql
    ports:
      - "127.0.0.1:2368:2368"
    volumes:
      - ghost_content:/var/lib/ghost/content
    environment:
      NODE_ENV: production
      url: https://yourdomain.com
      database__client: mysql
      database__connection__host: mysql
      database__connection__port: 3306
      database__connection__user: ghost
      database__connection__password: change_me_ghost_password
      database__connection__database: ghost
      mail__transport: SMTP
      mail__options__service: mailgun
      mail__options__auth__user: postmaster@mg.yourdomain.com
      mail__options__auth__pass: your_mailgun_api_key

volumes:
  mysql_data:
  ghost_content:

Replace yourdomain.com and all passwords with your actual values.

Start Services

docker compose up -d
docker compose logs -f ghost

Wait for Ghost to initialize (watch for "Ghost is running" message).


Nginx Reverse Proxy Configuration

Configure Nginx to expose Ghost on your domain with SSL:

nano /etc/nginx/sites-available/ghost

Add configuration:

server {
    listen 80;
    server_name yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name 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_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_redirect off;
    }
}

Enable and test:

ln -s /etc/nginx/sites-available/ghost /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

Install SSL Certificate

certbot certonly --standalone -d yourdomain.com

Initial Setup

Access Ghost Admin

Open browser and visit https://yourdomain.com/ghost

  1. Create your admin account
  2. Add site title, description, and publication details
  3. Invite additional staff members if needed

Configure Site Settings

In Ghost admin panel:

  • General: Site title, description, language
  • Email: Sender name and address for newsletters
  • Customization: Brand color, logo, favicon
  • Members: Enable free and paid memberships
  • Labs: Enable beta features (email, portals, etc.)

Newsletter Configuration with Mailgun

Set up email delivery for newsletters:

Get Mailgun Credentials

  1. Sign up at mailgun.com (free tier available)
  2. Add your domain
  3. Retrieve API key from dashboard
  4. Update docker-compose.yml:
environment:
  mail__transport: SMTP
  mail__options__service: mailgun
  mail__options__auth__user: postmaster@mg.yourdomain.com
  mail__options__auth__pass: your_mailgun_api_key

Restart Ghost:

docker compose down
docker compose up -d

Create Newsletter

  1. Go to Ghost admin → Newsletters
  2. Create a newsletter (free or paid)
  3. Add subscribers and publish newsletters from your posts

Theme Installation

Upload Custom Theme

  1. Go to Ghost admin → Design & Branding → Change Theme
  2. Upload a ZIP file of your theme
  3. Customize in theme settings

Use Community Themes

Download themes from ghost.org/themes and upload as ZIP.

Example popular themes: Casper (default), Alto, Edition, Aspire.


Content Management

Create Posts

  1. Click "New story" in editor
  2. Write with Markdown or rich text
  3. Add featured image, excerpt, tags
  4. Set publish date (schedule future posts)
  5. Choose email newsletter delivery if enabled

Create Pages

Similar to posts but not dated. Use for About, Contact, etc.

Manage Members

Enable members for:

  • Free subscriptions
  • Paid subscriptions
  • Email delivery based on tier
  • Comment sections

Backup Strategy

Backup Content Folder

# Backup Ghost content directory
docker compose exec ghost tar czf - /var/lib/ghost/content | \
  gzip > ghost_content_$(date +%Y%m%d).tar.gz

Backup Database

# Backup MySQL database
docker compose exec mysql mysqldump -u ghost -p'change_me_ghost_password' ghost | \
  gzip > ghost_db_$(date +%Y%m%d).sql.gz

Complete Backup Script

#!/bin/bash
BACKUP_DIR="/backups/ghost"
DATE=$(date +%Y%m%d)

mkdir -p $BACKUP_DIR

# Backup database
docker compose -f /opt/ghost/docker-compose.yml exec -T mysql \
  mysqldump -u ghost -p'change_me_ghost_password' ghost | \
  gzip > $BACKUP_DIR/ghost_db_$DATE.sql.gz

# Backup content
docker compose -f /opt/ghost/docker-compose.yml exec -T ghost \
  tar czf - /var/lib/ghost/content > $BACKUP_DIR/ghost_content_$DATE.tar.gz

echo "Ghost backup completed: $BACKUP_DIR"

Add to crontab for daily backups:

0 2 * * * /usr/local/bin/ghost-backup.sh

Updates

Update Ghost safely:

cd /opt/ghost

# Pull latest image
docker compose pull ghost

# Stop and start (automatic database migration)
docker compose down
docker compose up -d

# Monitor startup
docker compose logs -f ghost

Always backup before updating. Test updates in staging if possible. Major version upgrades may require theme adjustments.


Performance Tips

  1. Enable Nginx caching for static assets
  2. Use a CDN for images (Cloudflare, AWS CloudFront)
  3. Enable members portal for engagement
  4. Use scheduled posts to maintain consistency
  5. Monitor Ghost logs for errors: docker compose logs ghost

Important Notes

Ghost's self-hosted version is completely free. There's no licensing cost, unlike the hosted version (ghost.org). You pay only for hosting infrastructure. Ghost is optimized for fast performance and scales well on modest VPS resources.


Troubleshooting

Ghost won't start

docker compose logs ghost
docker compose down
docker compose up -d

Newsletter emails not sending

Check Mailgun configuration in admin panel and verify API credentials.

Database connection error

Ensure MySQL container is running:

docker compose ps
docker compose restart mysql

Permission denied on content folder

docker compose exec ghost chown -R node:node /var/lib/ghost/content

On this page