Ghost is a publishing platform built specifically for content creators, journalists, and newsletter operators who need professional publishing tools without the complexity and plugin bloat of WordPress. Where WordPress tries to be everything — e-commerce platform, forum, LMS, portfolio site — Ghost focuses on one thing: writing and distributing content. The result is a CMS that loads fast, handles newsletters natively, supports paid memberships out of the box, and doesn't require 47 plugins to feel modern.
Self-hosting Ghost on a VPS gives you the performance and control that Ghost's managed hosting (Ghost Pro) charges $31-249/month for. You get the same software, the same features, and full ownership of your content and subscriber data. This guide walks through the complete installation on Ubuntu 24.04, from Node.js setup through production-ready configuration with email delivery, membership support, and performance tuning.
MassiveGRID Ubuntu VPS includes: Ubuntu 24.04 LTS pre-installed · Proxmox HA cluster with automatic failover · Ceph 3x replicated NVMe storage · Independent CPU/RAM/storage scaling · 12 Tbps DDoS protection · 4 global datacenter locations · 100% uptime SLA · 24/7 human support rated 9.5/10
Deploy a self-managed VPS — from $1.99/mo
Need dedicated resources? — from $19.80/mo
Want fully managed hosting? — we handle everything
Ghost vs WordPress — When Ghost Makes More Sense
Both Ghost and WordPress are content management systems, but they serve different needs. If you've already set up WordPress on a VPS (see our WordPress hosting guide), understanding when Ghost is the better choice helps you pick the right tool.
| Feature | Ghost | WordPress |
|---|---|---|
| Primary focus | Publishing, newsletters, memberships | General-purpose CMS |
| Built-in newsletters | Yes (native, included) | No (requires plugins like Mailchimp, MailPoet) |
| Paid subscriptions | Yes (native Stripe integration) | No (requires WooCommerce or membership plugins) |
| Plugin ecosystem | Minimal (by design) | 60,000+ plugins |
| Performance | Fast out of the box (Node.js) | Varies widely based on plugins/theme |
| Security surface | Small (no plugin system) | Large (plugin vulnerabilities are common) |
| E-commerce | Not suitable | WooCommerce is excellent |
| Editor | Modern block editor (Mobiledoc/Lexical) | Gutenberg block editor |
| SEO | Built-in (structured data, sitemaps, meta) | Requires Yoast or similar plugin |
| Technology | Node.js | PHP |
| Self-host complexity | Moderate (Node.js, CLI tool) | Easy (PHP, well-documented) |
Choose Ghost when: Your primary goal is publishing articles, building a newsletter audience, or monetizing through paid subscriptions. Ghost excels as a blog, magazine, or newsletter platform.
Choose WordPress when: You need extensive customization, e-commerce, complex page layouts, or features that depend on the WordPress plugin ecosystem.
Prerequisites
Ghost has specific requirements that differ from typical PHP-based CMS deployments:
- Ubuntu 24.04 LTS — Ghost officially supports Ubuntu LTS releases
- MySQL 8.0 — Ghost requires MySQL (not MariaDB, not PostgreSQL, not SQLite for production)
- Node.js 18.x or 20.x — Ghost requires a specific Node.js LTS version
- Nginx — Ghost CLI configures Nginx automatically during installation
- A non-root user with sudo privileges — Ghost CLI refuses to run as root
- A domain name pointed to your VPS
If you need to set up your server from scratch, start with our Ubuntu VPS setup guide. For MySQL installation, our LEMP stack guide covers MySQL setup as part of the stack.
Resource requirements: Ghost runs efficiently on a Cloud VPS with 2 vCPU / 2GB RAM for sites with up to 50K monthly visitors. For sites with newsletters going to thousands of subscribers, consider upgrading RAM to 4GB.
Installing MySQL 8.0
If you don't already have MySQL installed, set it up:
sudo apt update
sudo apt install -y mysql-server
Secure the installation:
sudo mysql_secure_installation
Follow the prompts to set a root password, remove anonymous users, disable remote root login, and remove the test database.
Create a dedicated database and user for Ghost:
sudo mysql -u root -p
CREATE DATABASE ghost_production CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'ghost'@'localhost' IDENTIFIED BY 'your_secure_password_here';
GRANT ALL PRIVILEGES ON ghost_production.* TO 'ghost'@'localhost';
FLUSH PRIVILEGES;
EXIT;
For MySQL performance tuning (especially important if Ghost shares the server with other services), see our MySQL tuning guide.
Installing Node.js
Ghost requires a specific Node.js LTS version. As of Ghost 5.x, Node.js 18.x and 20.x are supported. We'll install Node.js 20.x using the NodeSource repository:
# Install the NodeSource repository
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
# Install Node.js
sudo apt install -y nodejs
Verify the installation:
node --version
npm --version
You should see Node.js v20.x.x and npm 10.x.x.
Important: Do not use the Node.js version from Ubuntu's default repositories — it's often outdated and won't meet Ghost's version requirements. Always use the NodeSource repository or a version manager like nvm.
Installing Nginx
If Nginx isn't already installed:
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
Verify it's running:
sudo systemctl status nginx
Ghost CLI will automatically create and configure the Nginx server block during installation, so you don't need to create one manually. If you want to understand how Nginx reverse proxying works in detail, our Nginx reverse proxy guide covers the concepts.
Installing Ghost CLI
Ghost provides an official CLI tool that handles installation, configuration, updates, and maintenance. Install it globally via npm:
sudo npm install -g ghost-cli@latest
Verify the installation:
ghost --version
Creating the Ghost User and Directory
Ghost CLI requires a non-root user. If you're currently logged in as root, create a dedicated user:
sudo adduser ghostadmin
sudo usermod -aG sudo ghostadmin
Create the Ghost installation directory with proper ownership:
sudo mkdir -p /var/www/ghost
sudo chown ghostadmin:ghostadmin /var/www/ghost
sudo chmod 775 /var/www/ghost
Switch to the ghost admin user:
su - ghostadmin
Installing Ghost
Navigate to the installation directory and run the Ghost installer:
cd /var/www/ghost
ghost install
The installer will ask you a series of questions:
- Blog URL: Enter your full URL with HTTPS (e.g.,
https://blog.example.com) - MySQL hostname:
localhost - MySQL username:
ghost - MySQL password: the password you set earlier
- Ghost database name:
ghost_production - Set up a Ghost MySQL user? No (we already created one)
- Set up Nginx? Yes
- Set up SSL? Yes (requires domain already pointing to the server)
- Set up systemd? Yes
- Start Ghost? Yes
The installer will:
- Download and install the latest Ghost release
- Create the configuration file (
config.production.json) - Run database migrations
- Configure Nginx with a proper server block
- Obtain a Let's Encrypt SSL certificate via
acme.sh - Create a systemd service for automatic start on boot
- Start Ghost
If the SSL setup fails (usually because DNS hasn't propagated yet), you can run it later:
cd /var/www/ghost
ghost setup ssl
Once installation completes, Ghost is accessible at your configured URL.
Understanding What Ghost CLI Created
The installation process creates several important files and configurations. Understanding them helps with troubleshooting and customization.
Ghost Configuration File
The main configuration lives at /var/www/ghost/config.production.json:
{
"url": "https://blog.example.com",
"server": {
"port": 2368,
"host": "127.0.0.1"
},
"database": {
"client": "mysql2",
"connection": {
"host": "localhost",
"user": "ghost",
"password": "your_password",
"database": "ghost_production"
}
},
"mail": {
"transport": "Direct"
},
"logging": {
"transports": ["file", "stdout"]
},
"process": "systemd",
"paths": {
"contentPath": "/var/www/ghost/content"
}
}
Nginx Configuration
Ghost CLI creates an Nginx configuration at /etc/nginx/sites-available/blog.example.com.conf. It sets up:
- HTTP-to-HTTPS redirect
- SSL termination with Let's Encrypt certificates
- Reverse proxy to Ghost's Node.js process on port 2368
- Static file caching headers
You can view it:
cat /etc/nginx/sites-available/blog.example.com.conf
Systemd Service
Ghost runs as a systemd service. Manage it with:
# Check status
ghost status
# Or using systemd directly
sudo systemctl status ghost_blog-example-com
# Restart Ghost
ghost restart
# Stop Ghost
ghost stop
# Start Ghost
ghost start
Content Directory
All your Ghost content lives in /var/www/ghost/content/:
/var/www/ghost/content/
├── data/ # SQLite database (development mode only)
├── files/ # Uploaded files (PDFs, etc.)
├── images/ # Uploaded images
├── logs/ # Ghost application logs
├── media/ # Uploaded audio/video
├── settings/ # Routes and redirects configuration
└── themes/ # Installed themes
Initial Setup — Creating Your Admin Account
Navigate to https://blog.example.com/ghost/ in your browser. This is the Ghost admin panel. On first visit, you'll see the setup wizard:
- Enter your site title
- Enter your name, email, and password for the owner account
- Optionally invite team members (you can skip this)
After setup, you'll land in the Ghost admin dashboard. Bookmark https://blog.example.com/ghost/ — this is your content management interface.
Email Delivery Setup — Critical for Newsletters
The default mail configuration ("transport": "Direct") attempts to send email directly from your server. This almost never works reliably — emails land in spam or get rejected entirely. For a publishing platform, reliable email is non-negotiable.
Ghost uses email for two purposes:
- Transactional emails — password resets, login notifications, member signup confirmations
- Newsletter emails — bulk delivery to your subscriber list (Ghost's built-in newsletter feature)
Configuring Mailgun (Recommended for Newsletters)
Ghost has first-class Mailgun integration for newsletter delivery. Mailgun's free tier includes a generous number of emails per month for verified domains.
After creating a Mailgun account and verifying your domain, update Ghost's configuration:
cd /var/www/ghost
nano config.production.json
Replace the "mail" section:
{
"mail": {
"transport": "SMTP",
"options": {
"service": "Mailgun",
"host": "smtp.mailgun.org",
"port": 587,
"secure": false,
"auth": {
"user": "postmaster@mg.example.com",
"pass": "your-mailgun-smtp-password"
}
}
},
"bulk_email": {
"provider": "mailgun",
"mailgun": {
"apiKey": "your-mailgun-api-key",
"domain": "mg.example.com",
"baseUrl": "https://api.mailgun.net/v3"
}
}
}
The mail section handles transactional emails via SMTP. The bulk_email section handles newsletter delivery via Mailgun's API (which is faster and more reliable for bulk sends than SMTP).
If you're using the EU Mailgun region, change baseUrl to https://api.eu.mailgun.net/v3.
Restart Ghost to apply changes:
ghost restart
Configuring SendGrid (Alternative)
If you prefer SendGrid:
{
"mail": {
"transport": "SMTP",
"options": {
"host": "smtp.sendgrid.net",
"port": 587,
"secure": false,
"auth": {
"user": "apikey",
"pass": "your-sendgrid-api-key"
}
}
}
}
Note that SendGrid doesn't have Ghost's native bulk email integration — newsletter sends will use SMTP, which is slower for large lists but works fine for smaller audiences (under 5,000 subscribers).
Testing Email Delivery
After configuring mail, test it by going to Ghost admin → Settings → Email newsletter and sending a test newsletter to yourself. Also test transactional email by using the "Forgot password" flow on the Ghost login page.
Configuring Memberships and Subscriptions
Ghost's membership system is one of its strongest differentiators. It supports free members (email subscribers), paid members (via Stripe), and complimentary members (manually granted access).
Enabling Memberships
In Ghost admin, go to Settings → Membership:
- Subscription access: Choose "Anyone can sign up" for public publications
- Default post access: Set who can read posts by default (Public, Members only, Paid members only)
- Membership tiers: Configure your free and paid tiers
Connecting Stripe for Paid Subscriptions
To accept payments:
- Go to Settings → Membership → Stripe
- Click "Connect with Stripe"
- Authorize Ghost to connect to your Stripe account
- Configure pricing tiers (monthly and annual options)
Ghost handles the complete subscription lifecycle — signup, payment processing, access control, cancellation, and receipt emails — without any plugins or third-party membership tools.
Content Gating
When writing a post, you can set its visibility:
- Public — anyone can read it
- Members only — free signup required (great for building your email list)
- Paid members only — requires an active paid subscription
- Specific tier — only members of a particular tier can access
You can also use content gates within a post — the first part is public, and a "Subscribe to continue reading" prompt appears mid-article.
Ghost Themes and Customization
Ghost uses a Handlebars-based theming system. The default theme is Casper, which is clean and responsive. Themes are installed via the admin panel.
Installing a Theme
- Download a theme (from Ghost's theme marketplace or GitHub)
- In Ghost admin, go to Settings → Design & branding → Change theme
- Upload the theme zip file
- Activate it
Customizing the Default Theme
For minor customizations without editing theme files, Ghost supports code injection. Go to Settings → Code injection:
- Site Header — inject CSS or meta tags into the
<head>of every page - Site Footer — inject JavaScript before the closing
</body>tag
Example — changing the accent color and adding custom fonts:
<style>
:root {
--ghost-accent-color: #F5A623;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
.post-content {
font-size: 1.1rem;
line-height: 1.8;
}
</style>
Custom Theme Development
If you need deeper customization, Ghost themes are straightforward to develop. The theme files live in /var/www/ghost/content/themes/. A Ghost theme consists of:
my-theme/
├── package.json # Theme metadata
├── index.hbs # Homepage template
├── post.hbs # Single post template
├── page.hbs # Static page template
├── tag.hbs # Tag archive template
├── author.hbs # Author page template
├── default.hbs # Base layout (header/footer wrapper)
├── partials/ # Reusable template components
│ ├── navigation.hbs
│ └── post-card.hbs
└── assets/
├── css/
└── js/
After editing theme files, restart Ghost or re-upload the theme to see changes.
Backup Strategy for Ghost
A complete Ghost backup covers three components: the MySQL database, the content directory (images, themes, files), and the configuration file.
Automated Backup Script
Create a comprehensive backup script:
sudo nano /opt/scripts/ghost-backup.sh
#!/bin/bash
# Ghost Backup Script
# Backs up database, content, and configuration
GHOST_DIR="/var/www/ghost"
BACKUP_DIR="/opt/backups/ghost"
TIMESTAMP=$(date +%Y%m%d-%H%M)
RETENTION_DAYS=30
# MySQL credentials
DB_NAME="ghost_production"
DB_USER="ghost"
DB_PASS="your_secure_password_here"
mkdir -p "$BACKUP_DIR/$TIMESTAMP"
# 1. Database backup
echo "Backing up MySQL database..."
mysqldump -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" \
--single-transaction \
--quick \
--lock-tables=false \
| gzip > "$BACKUP_DIR/$TIMESTAMP/database.sql.gz"
# 2. Content directory backup (images, themes, files, settings)
echo "Backing up content directory..."
tar czf "$BACKUP_DIR/$TIMESTAMP/content.tar.gz" \
-C "$GHOST_DIR" content/ \
--exclude="content/logs"
# 3. Configuration backup
echo "Backing up configuration..."
cp "$GHOST_DIR/config.production.json" "$BACKUP_DIR/$TIMESTAMP/"
# 4. Create a single archive
echo "Creating combined archive..."
cd "$BACKUP_DIR"
tar czf "ghost-backup-$TIMESTAMP.tar.gz" "$TIMESTAMP/"
rm -rf "$TIMESTAMP/"
# 5. Remove old backups
find "$BACKUP_DIR" -name "ghost-backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: ghost-backup-$TIMESTAMP.tar.gz"
echo "Size: $(du -h "$BACKUP_DIR/ghost-backup-$TIMESTAMP.tar.gz" | cut -f1)"
sudo chmod +x /opt/scripts/ghost-backup.sh
Schedule it in cron:
sudo crontab -e
0 2 * * * /opt/scripts/ghost-backup.sh >> /var/log/ghost-backup.log 2>&1
For more sophisticated backup strategies including offsite storage, see our automatic backup guide.
Ghost's Built-in Export
Ghost also provides a JSON export from the admin panel: Settings → Advanced → Export your content. This exports posts, pages, tags, and settings as JSON — useful for migrating between Ghost instances — but does not include images, themes, or the database itself. Always use the file-level backup approach above for disaster recovery.
Restoring from Backup
# Stop Ghost
cd /var/www/ghost
ghost stop
# Extract the backup
cd /opt/backups/ghost
tar xzf ghost-backup-20260228-0200.tar.gz
# Restore database
gunzip -c 20260228-0200/database.sql.gz | mysql -u ghost -p ghost_production
# Restore content directory
tar xzf 20260228-0200/content.tar.gz -C /var/www/ghost/
# Restore configuration
cp 20260228-0200/config.production.json /var/www/ghost/
# Fix ownership
sudo chown -R ghostadmin:ghostadmin /var/www/ghost/content
# Start Ghost
ghost start
Performance Optimization
Ghost is fast by default, but these optimizations ensure it stays fast under load.
Node.js Memory Configuration
Ghost's Node.js process defaults to a reasonable memory limit, but you can tune it. Edit the systemd service:
sudo systemctl edit ghost_blog-example-com
Add:
[Service]
Environment="NODE_OPTIONS=--max-old-space-size=512"
This sets the V8 heap limit to 512MB. For a 2GB RAM VPS, this leaves ample memory for MySQL, Nginx, and the OS. Increase to 768MB or 1024MB on larger instances.
sudo systemctl daemon-reload
ghost restart
MySQL Configuration for Ghost
Ghost's database queries are relatively simple — mostly read-heavy with occasional writes. Optimize MySQL for this workload by editing /etc/mysql/mysql.conf.d/mysqld.cnf:
[mysqld]
# InnoDB settings optimized for Ghost on a 2GB VPS
innodb_buffer_pool_size = 256M
innodb_log_file_size = 64M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
# Query cache (useful for Ghost's read-heavy workload)
# Note: Query cache is deprecated in MySQL 8.0 but still functional
# Use performance_schema instead for monitoring
# Connection settings
max_connections = 50
wait_timeout = 600
interactive_timeout = 600
# Temporary tables
tmp_table_size = 32M
max_heap_table_size = 32M
# Sort and join buffers
sort_buffer_size = 2M
join_buffer_size = 2M
sudo systemctl restart mysql
Image Optimization
Ghost serves uploaded images directly through Nginx. Images are often the largest component of page load. Ghost 5.x includes built-in image resizing and generates responsive image srcsets, but you can further optimize by:
- Using WebP format — Ghost automatically converts uploaded images to WebP in modern versions
- Setting appropriate Nginx caching headers — Ghost CLI configures this, but verify in the Nginx config:
location ~ ^/content/images/ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
Using a CDN
For global audiences, a CDN dramatically improves load times. Cloudflare (free tier) is the most common choice:
- Add your domain to Cloudflare
- Update your domain's nameservers to Cloudflare's
- Enable "Proxied" (orange cloud) on the DNS record pointing to your VPS
- In Cloudflare settings, set caching to "Standard"
- Enable "Auto Minify" for JavaScript, CSS, and HTML
In Ghost admin, you don't need to change anything — Cloudflare sits transparently between users and your origin server.
Managing Ghost — Day-to-Day Operations
Updating Ghost
Ghost CLI makes updates straightforward:
cd /var/www/ghost
ghost update
This downloads the latest version, runs database migrations, and restarts Ghost. Always take a backup before updating.
To update to a specific version:
ghost update 5.100.0
Checking Logs
Ghost logs are stored in /var/www/ghost/content/logs/. View recent entries:
ghost log
Or directly:
tail -f /var/www/ghost/content/logs/blog-example-com.log
For Nginx access and error logs:
sudo tail -f /var/log/nginx/blog.example.com-access.log
sudo tail -f /var/log/nginx/blog.example.com-error.log
Ghost CLI Commands Reference
| Command | Purpose |
|---|---|
ghost start |
Start Ghost |
ghost stop |
Stop Ghost |
ghost restart |
Restart Ghost |
ghost status |
Show running status |
ghost update |
Update to latest version |
ghost log |
View recent logs |
ghost config |
View/edit configuration |
ghost setup ssl |
Set up or renew SSL |
ghost doctor |
Diagnose common issues |
ghost uninstall |
Completely remove Ghost |
Integrations and the Ghost API
Ghost provides a Content API (read-only, for building custom frontends) and an Admin API (read-write, for programmatic content management). These enable powerful integrations.
Setting Up a Custom Integration
In Ghost admin, go to Settings → Integrations → Add custom integration. Give it a name (e.g., "Backup Script" or "External Frontend"). Ghost generates:
- Content API Key — for reading public content
- Admin API Key — for creating/editing content
- API URL — your Ghost URL
Using the Content API
Fetch published posts via HTTP:
curl "https://blog.example.com/ghost/api/content/posts/?key=YOUR_CONTENT_API_KEY&limit=5"
This returns JSON with your latest 5 posts, including title, HTML content, featured image, and metadata. You can use this to display Ghost content on other websites, build a custom frontend with Next.js or Gatsby, or syndicate content to other platforms.
Zapier and Webhooks
Ghost supports webhooks for content events. Go to Settings → Integrations → Add custom integration → Add webhook. Available events include:
- Post published / updated / deleted
- Page published / updated / deleted
- Tag created / updated / deleted
- Member created / updated / deleted
Use webhooks to trigger external workflows — post to social media when a new article is published, sync members to a CRM, or notify a Slack channel on new signups.
Newsletter Sending and Performance Impact
Ghost's newsletter feature sends emails to all members (or specific segments) when you publish a post. For small lists (under 1,000 subscribers), this is barely noticeable. For larger lists, the email sending process can temporarily increase CPU and memory usage.
How Ghost sends newsletters:
- You publish a post with the "Email" toggle enabled
- Ghost queues the email send operation
- Ghost renders the email template for each subscriber (personalized with name, unsubscribe link)
- Emails are sent in batches via the configured email provider (Mailgun API or SMTP)
For lists over 5,000 subscribers, the rendering and queuing process can spike CPU usage significantly. On a shared VPS, this might temporarily slow your website for visitors.
Newsletter performance: Newsletter sends to thousands of subscribers compete with web serving for CPU. Dedicated CPU on a VDS ensures your website stays responsive during bulk email operations. Dedicated resources mean the newsletter process and web serving don't contend for the same CPU cycles.
Security Considerations
Ghost has a smaller attack surface than WordPress (no plugins, no PHP), but basic security practices still apply:
- Keep Ghost updated — run
ghost updateregularly for security patches - Use strong admin passwords — the Ghost admin panel is the keys to your entire publication
- Restrict admin access — consider adding IP-based restrictions to
/ghost/in Nginx - Monitor login attempts — Ghost includes brute-force protection, but check logs periodically
- Use HTTPS everywhere — Ghost CLI sets this up, but verify it's working with your SSL configuration
For comprehensive server-level security, see our Ubuntu VPS security hardening guide.
Troubleshooting Common Issues
Ghost Won't Start — "Error: EACCES: permission denied"
This usually means Ghost is being run as root, or file permissions are wrong:
sudo chown -R ghostadmin:ghostadmin /var/www/ghost/content
sudo find /var/www/ghost -type d -exec chmod 775 {} \;
sudo find /var/www/ghost -type f -exec chmod 664 {} \;
"Error: Cannot find module" After Update
The Node.js modules may be corrupted. Reinstall them:
cd /var/www/ghost
rm -rf node_modules
ghost install --no-setup
SSL Certificate Renewal Fails
Ghost uses acme.sh for SSL, not Certbot. Check the renewal setup:
~/.acme.sh/acme.sh --list
If auto-renewal isn't working, renew manually:
cd /var/www/ghost
ghost setup ssl
High Memory Usage
Check what's consuming memory:
ghost status
free -h
sudo systemctl status ghost_blog-example-com
If Ghost is consuming too much memory, reduce the Node.js heap size and consider optimizing MySQL's buffer pool. See the performance optimization section above.
Prefer Managed Ghost Hosting?
Self-hosting Ghost gives you maximum control and cost efficiency, but it requires maintaining the server, handling updates, and managing backups yourself. If you'd rather focus entirely on content creation, MassiveGRID's fully managed dedicated cloud servers give you the same self-hosted Ghost experience with infrastructure management handled by the MassiveGRID team — OS updates, security patches, automated backups, and 24/7 monitoring included.
Summary
Ghost on a self-hosted VPS gives you a professional publishing platform with newsletters, memberships, and SEO built in — for a fraction of Ghost Pro's pricing. Here's what we covered:
- Install Node.js 20.x, MySQL 8.0, and Nginx as prerequisites
- Use Ghost CLI for a guided, production-ready installation
- Configure email delivery via Mailgun for reliable newsletter sending
- Set up memberships and Stripe integration for paid subscriptions
- Implement automated backups covering the database, content, and configuration
- Optimize performance with Node.js memory tuning, MySQL configuration, and CDN integration
For monitoring your Ghost installation, set up server monitoring to track memory usage, CPU load, and disk space. And if you're running Ghost alongside other services on the same VPS, our disk space management guide helps you keep storage usage in check.