Architecting a Production-Ready Self-Hosted Ghost Instance
Learn how to architect a production-ready Ghost instance, from choosing MySQL 8 over SQLite to establishing secure data boundaries and operational health checks.
07 Feb 2026, 03:12 UTC

The Production Gap: SQLite vs. MySQL
The most common failure point in new Ghost deployments is using the default SQLite database in a production environment. While SQLite allows for a fast initial setup, it is strictly for local development. Production Ghost requires MySQL 8.0 to support concurrent requests, member management, and reliable data migrations during version upgrades. Using SQLite in production risks data corruption and prevents the use of critical publishing features.
The Smallest Suitable Design
For most publishers, a single-node deployment is the most efficient architecture. This minimizes latency and reduces the complexity of managing distributed state. The minimum viable production stack consists of:
- Application Tier: A single Node.js process running the Ghost core.
- Database Tier: A MySQL 8 instance (either on the same host or a managed service).
- Reverse Proxy: Nginx or Caddy to handle TLS termination and forward traffic to the Node.js process.
- Persistent Storage: A dedicated volume for the
/contentdirectory to store images, themes, and configuration files. - Mail Transport: An external SMTP provider for transactional emails (staff invites, 2FA, and member notifications).
Trust and Data Boundaries
Ghost operates with three distinct data access patterns. Understanding these boundaries is critical for securing the instance:
| Boundary | Access Level | Security Mechanism |
|---|---|---|
| Content API | Public | Read-only access to published posts. |
| Admin UI / API | Private | Session cookies or short-lived JWTs; Role-Based Access Control (RBAC). |
| Database/Filesystem | Internal | Restricted to the Node.js process; never exposed to the public internet. |
The application tier acts as the sole security boundary. You must ensure that the MySQL port (typically 3306) and the Ghost internal port (typically 2368) are not accessible from outside the local network or the reverse proxy.
Operational Checks and Verification
After deployment or a version upgrade, perform these checks to ensure the system is healthy. Run these commands as the user owning the Ghost installation (e.g., ghost-mgr), not as root.
1. Configuration Validation
Use the built-in Ghost CLI to verify the environment and folder permissions:
ghost doctor
Expected Result: All checks should return a green checkmark. Pay close attention to directory permissions for the /content folder.
2. Connectivity and API Testing
Verify that the reverse proxy is correctly routing traffic and that the API boundaries are intact:
- Public Site: Load the homepage over HTTPS. It should return a 200 OK.
- Admin Access: Navigate to
/ghost. It should prompt for credentials. - Content API: Attempt to fetch a post via
/ghost/api/content/posts/. It should return JSON without requiring a password. - Admin API: Attempt to access an admin endpoint without a JWT. It should return a 401 Unauthorized.
3. Transactional Mail Test
Ghost relies on SMTP for critical operations. Trigger a password reset or a staff invite from the Admin UI. If the email does not arrive within five minutes, your SMTP configuration is failing, which will block new user onboarding and 2FA recovery.
Failure Modes and Mitigation
Memory Exhaustion (OOM): Node.js processes can crash-loop on hosts with less than 2GB of RAM, especially during image processing or heavy traffic spikes. Monitor memory usage and implement a swap file if using a small VPS.
Silent Mail Failure: Misconfigured SMTP settings often fail silently in the UI. Always check the Ghost logs using ghost log to identify SMTP authentication errors.
Upgrade Regression: Database migrations are generally forward-only. If an upgrade fails, you cannot simply "downgrade" the software; you must restore the MySQL database and the /content volume from a snapshot taken immediately before the upgrade.
When to Change This Design
The single-node architecture remains sufficient until you hit specific scaling triggers:
- High Concurrent Editing: If dozens of editors are working simultaneously, move the MySQL database to a dedicated, high-performance managed instance.
- Traffic Spikes: If a single Node process cannot handle the request volume, move to a clustered setup with multiple app instances behind a load balancer. This requires moving the
/contentfolder to a shared network drive or using a storage adapter for object storage (e.g., AWS S3). - Compliance Requirements: If PCI-DSS or strict data residency laws apply, isolate the member database into a private subnet and use a managed payment gateway to keep sensitive credit card data out of your infrastructure.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.