Self-host Ghost with MySQL and Custom Themes
Ghost is an open-source publishing platform for blogs, newsletters, and membership sites. It includes a visual editor, built-in SEO, membership and subscription management, and a theme system.
This guide covers deploying Ghost on Railway from the official Docker image with a MySQL database and persistent content storage.
What you will set up
- A Ghost instance from the official Docker image
- A MySQL database for content storage
- Persistent storage via a Railway Volume for themes, images, and settings
- A public domain with SSL for the Ghost site and admin panel
One-click deploy from a template
Railway has a Ghost template:
After deploying, generate a domain and update the url environment variable to match. Open /ghost to access the admin panel.
If you prefer to set things up manually, continue with the steps below.
Deploy manually
1. Create the project and database
- Create a new project on Railway.
- Add a MySQL database: click + New, then Database, then MySQL.
Ghost requires MySQL. It does not support Postgres.
2. Deploy the Ghost Docker image
- Click + New, then Docker Image.
- Enter
ghost:5-alpineas the image name.
3. Configure environment variables
Add the following variables to the Ghost service:
Ghost uses double-underscore (__) notation for nested configuration. Set the url variable after generating a domain in the next step.
4. Add persistent storage
Ghost stores themes, images, and other content in /var/lib/ghost/content. This directory must persist across deploys.
- In the Ghost service, go to Settings, then Volumes.
- Add a volume with the mount path
/var/lib/ghost/content.
Without a volume, all uploaded images and custom themes are lost on each deploy.
5. Generate a domain
Navigate to Networking in the service settings and generate a domain. Update the url variable to match (e.g., https://your-blog.railway.app).
The url variable must include the full URL with https://. Ghost uses it to generate absolute links for posts, images, and the admin panel.
Open https://your-domain.railway.app/ghost to create your admin account.
Custom domain
To use your own domain:
- Add a custom domain to the Ghost service in Railway.
- Update the
urlvariable to match your custom domain (e.g.,https://blog.example.com). - Railway provisions an SSL certificate automatically.
Custom themes
Ghost ships with a default theme (Casper). To use a custom theme:
Option 1: Upload via admin panel. Go to Settings > Design > Change theme > Upload theme in the Ghost admin. Themes uploaded this way are stored in the content volume and persist across deploys.
Option 2: Build into the Docker image. Create a Dockerfile that copies your theme into the Ghost image:
Deploy this Dockerfile from a GitHub repository instead of using the public Docker image. The theme is built into the image and does not require a volume for persistence.
Sending email
Ghost uses email for member sign-ups, newsletters, and password resets. Configure an SMTP provider by adding these variables:
Replace with your SMTP provider's credentials. Ghost supports Mailgun, SendGrid, and any SMTP service.
Connecting a frontend
Ghost provides a Content API for headless use. Generate a Content API key in the Ghost admin under Settings > Integrations.
For a full headless setup, use the Ghost Content API with a separate frontend framework.
Next steps
- Volumes - Manage persistent storage.
- Custom Domains - Add your own domain with SSL.
- Configure SPA routing - If using a separate frontend with Ghost as an API.