What You'll Build
A production-ready Ghost blog running on Hetzner Cloud - configured and deployed with two commands. Ghost 5 with MySQL 8, persistent storage, and a cloud firewall.
- Ghost 5 (alpine) with MySQL 8
- Hetzner Cloud server provisioned automatically
- Docker and status panel agent installed
- Persistent volumes for database and content
Quick Answer
# Install Ghost to Hetzner Cloud
stacker install ghost \
--domain blog.example.com \
--key htz-0 \
--provider hetzner \
--region fsn1 \
--size cx23
# Deploy
stacker deploy --target cloud --key htz-0 --force-new
Ghost is live at http://<SERVER_IP>:2368.
Prerequisites
- Stacker CLI installed (
curl -fsSL https://stacker.try.direct/install.sh | bash) - Authenticated:
stacker login - Hetzner cloud credential saved (verify with
stacker list clouds)
Step 1: Install Ghost
The stacker install command writes a stacker.yml with Ghost and MySQL pre-configured. All flags are optional except the cloud credential.
stacker install ghost \
--domain blog.example.com \
--key htz-0 \
--provider hetzner \
--region fsn1 \
--size cx23
Install Flags Reference
--domain- Sets the blog URL (optional, can set later)--key- Saved credential fromstacker list clouds(required for cloud)--provider-hetzner,digitalocean,aws,linode,vultr--region-fsn1,nbg1,hel1for Hetzner--size-cx23(2 vCPU, 4 GB),cx33(2 vCPU, 8 GB)--set key=value- Override any install input (repeatable)--name- Project name override--file- Custom output path for stacker.yml
Step 2: Deploy to Cloud
stacker deploy --target cloud --key htz-0 --force-new
Stacker provisions the server, installs Docker, transfers the compose file, and starts the containers. The output includes the server IP:
Server details: ghost-ae91 (root@203.0.113.42:22)
Deploy to an Existing Server
stacker deploy --target server
Requires deploy.server.host in stacker.yml.
Redeploy with Changes
stacker deploy --target cloud --key htz-0 --force-rebuild
Step 3: Open the Firewall
By default, only SSH (22) is open on cloud deploys. Ghost runs on port 2368 - you need to open it explicitly.
stacker cloud firewall add --public-ports 2368/tcp
This is the most common reason for "app unreachable after deploy" - forgetting to open the port.
Step 4: Verify
stacker status
Shows running containers, ports, and health. Then open http://<SERVER_IP>:2368 in your browser to complete Ghost setup.
Status and Logs
stacker list deployments
stacker deployment events --deployment <HASH>
stacker agent logs ghost
Other Templates
Stacker has templates for many apps beyond Ghost:
# List all available templates
stacker templates --json
# Search for a specific app
stacker find wordpress --json
# Install any template
stacker install <slug> --domain <domain> --key <credential> --provider <provider> --region <region> --size <size>
Clean Up
stacker destroy
This destroys the cloud server and all associated resources.
Troubleshooting
"Cloud API credentials are required"
The --key flag must match a saved credential name from stacker list clouds. Typos cause this error.
Ghost unreachable after deploy
Port 2368 is closed by default. Run stacker cloud firewall add --public-ports 2368/tcp to open it.
Domain not working
--domain sets the install input but doesn't configure DNS or a reverse proxy. Point your domain's A record to the server IP and set up SSL separately.
Marketplace marker blocking hooks
If stacker.yml contains # @stacker-origin: marketplace, custom hooks are blocked. Remove that line before deploying if you have custom scripts.
Frequently Asked Questions
How much does it cost to run Ghost on Hetzner?
A cx23 server (2 vCPU, 4 GB RAM) costs approximately €5.49/month. More than enough for a Ghost blog.
Can I use a different cloud provider?
Yes. Stacker supports Hetzner, DigitalOcean, AWS, Linode, and Vultr. Change --provider and --region accordingly.
Do I need to install Docker on the server?
No. stacker deploy --target cloud installs Docker and all dependencies automatically.
Can I deploy Ghost to my own server instead?
Yes. Use stacker deploy --target server with deploy.server.host set in stacker.yml.
Key Takeaways
stacker install ghostgenerates a complete stacker.yml with Ghost and MySQL- Cloud deployment provisions the server, installs Docker, and starts containers
- Always open the firewall port after cloud deploy (
stacker cloud firewall add) - The same workflow works for any Stacker template - WordPress, Plausible, Nextcloud, etc.
- Source: github.com/trydirect/stacker