try.directtry.direct

Deploy Ghost CMS to Hetzner Cloud with One Stacker Command

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 from stacker list clouds (required for cloud)
  • --provider - hetzner, digitalocean, aws, linode, vultr
  • --region - fsn1, nbg1, hel1 for 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 ghost generates 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

Try It Yourself

Deploy this stack or browse pre-built templates in the marketplace. Your first deployment is always free.