> ## Documentation Index
> Fetch the complete documentation index at: https://help.freakhosting.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Self-Host a Ghost Blog with Docker

> Self-host a Ghost blog with Docker: clone TryGhost/ghost-docker to /opt/ghost, set DOMAIN, passwords and SMTP in .env, start it and finish setup at /ghost.

To self-host a Ghost blog with Docker, clone Ghost's official `TryGhost/ghost-docker` repository to `/opt/ghost`, copy `.env.example` to `.env` and `caddy/Caddyfile.example` to `caddy/Caddyfile`, then set your domain, two database passwords and SMTP details. Run `docker compose pull` and `docker compose up -d`, and open `https://example.com/ghost` to create your account.

| Difficulty | Time | Works on | Needs |
| - | - | - | - |
| Intermediate | 30 minutes | Ubuntu 22.04 / 24.04, Debian 12 / 13, AlmaLinux / Rocky 9 / 10 | [Docker](https://help.freakhosting.com/portals/other/how-to-install-docker.md) 20.10.13+, a domain, SMTP, ports 80 and 443 free |

## What is Ghost?

Ghost is an open-source publishing platform for blogs, newsletters and paid memberships. The official Docker setup runs four parts: **Ghost** itself (`ghost:6-alpine`), a **MySQL 8** database, the **Caddy** web server, which gets and renews HTTPS certificates automatically, and optional analytics and ActivityPub services.

## Before you start

* **Docker 20.10.13 or newer** with the Compose plugin: [install Docker](https://help.freakhosting.com/portals/other/how-to-install-docker.md). Check with `docker --version`.
* **A domain** with an `A` record pointing to your server. See [point a domain to your server](https://help.freakhosting.com/portals/other/how-to-point-a-domain-to-your-server.md).
* **Ports 80 and 443 free.** Caddy in this stack uses them. Stop any Nginx or Apache on the server first, or use a separate server.
* **An SMTP service** for transactional email. Ghost needs it for staff logins, invites and password resets. This is separate from newsletter sending.
* Ghost's guide uses a 2 GB RAM / 1 CPU server as its example.
* The commands use `sudo`; leave it out if you are `root`.

## How to install Ghost with Docker

**1. Clone the official repository**

```bash theme={null}
sudo git clone https://github.com/TryGhost/ghost-docker.git /opt/ghost && cd /opt/ghost
```

**2. Copy the example files**

```bash theme={null}
sudo cp .env.example .env
sudo cp caddy/Caddyfile.example caddy/Caddyfile
```

**3. Generate two database passwords**

```bash theme={null}
openssl rand -hex 32
openssl rand -hex 32
```

Use the first for `DATABASE_ROOT_PASSWORD` and the second for `DATABASE_PASSWORD`.

**4. Edit .env**

Open it with `sudo nano .env` and set at least:

```ini theme={null}
DOMAIN=example.com
DATABASE_ROOT_PASSWORD=paste-the-first-value
DATABASE_PASSWORD=paste-the-second-value

mail__transport=SMTP
mail__options__host=smtp.example.com
mail__options__port=465
mail__options__secure=true
mail__options__auth__user=you@example.com
mail__options__auth__pass=your-smtp-password
mail__from="'Example Blog' <you@example.com>"
```

Don't change the `DATABASE_` values after the first start. To run Ghost Admin on its own domain, also set `ADMIN_DOMAIN=admin.example.com` and uncomment the matching block in `caddy/Caddyfile`.

**5. Start Ghost**

```bash theme={null}
sudo docker compose pull
sudo docker compose up -d
```

Caddy requests a Let's Encrypt certificate for `DOMAIN` on the first request, so the `A` record must already point here.

**6. Create your account**

Open `https://example.com/ghost`, then enter your site title, your name, email and a strong password. This first account becomes the site owner.

> [!WARNING]
>
> Complete the `/ghost` setup straight after the site goes live. Until you do, whoever opens it first can create the owner account.

## How does HTTPS work in this setup?

You don't need Certbot or a separate reverse proxy. Caddy is the reverse proxy: it listens on ports 80 and 443, gets the certificate, and forwards requests to Ghost on the internal network (`ghost:2368`). Ghost and MySQL publish no ports to the internet. To redirect `www.example.com` to `example.com`, add DNS for both names and uncomment the `www` block in `caddy/Caddyfile`, replacing `CHANGE_ME` with your domain.

## How to check it worked

```bash theme={null}
cd /opt/ghost
sudo docker compose ps
curl -I https://example.com
```

The `caddy`, `ghost` and `db` services show `Up`, and `curl` returns a `200` response with a valid certificate. If the site doesn't load, read `sudo docker compose logs caddy`, then `sudo docker compose logs ghost`.

## How to back up Ghost

Your content is in two places under `/opt/ghost/data`: `ghost` (images, themes and files) and `mysql` (the database). Dump the database and archive the content folder:

```bash theme={null}
cd /opt/ghost
sudo docker compose exec -T db sh -c 'mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" ghost' | sudo tee ghost-db-$(date +%F).sql > /dev/null
sudo tar -czf ghost-content-$(date +%F).tar.gz data/ghost .env caddy/Caddyfile
```

Copy both files off the server. See [back up and restore MySQL databases](https://help.freakhosting.com/portals/other/how-to-back-up-and-restore-mysql-databases.md) and [back up Docker volumes](https://help.freakhosting.com/portals/other/how-to-back-up-docker-volumes.md).

## How to update Ghost

Back up first, then pull the latest stack definition and images:

```bash theme={null}
cd /opt/ghost
sudo git pull
sudo docker compose pull
sudo docker compose up -d
sudo docker image prune
```

After changing `.env`, apply it with `sudo docker compose up -d --force-recreate ghost`. If you change `DOMAIN` or `ADMIN_DOMAIN`, recreate both: `sudo docker compose up -d --force-recreate ghost caddy`.

## Frequently asked questions

### Why can't I log in or invite staff?

Ghost needs working transactional email for logins, staff invites and password resets. Check the `mail__` settings in `.env`, recreate the `ghost` container and look for mail errors in `sudo docker compose logs ghost`.

### Can I send newsletters from a self-hosted Ghost?

Yes, with a bulk email service. The SMTP settings above only cover transactional email; newsletters need separate configuration. See Ghost's [mail configuration docs](https://docs.ghost.org/config#mail).

### Can I keep Nginx on the same server?

This official stack expects ports 80 and 443 for Caddy. `.env` lets you change `HTTP_PORT` and `HTTPS_PORT`, but then you must route traffic and certificates yourself. A dedicated server or VPS for Ghost is simpler.

### How do I enable web analytics or ActivityPub?

Both are optional profiles. Set `COMPOSE_PROFILES=analytics` (with a Tinybird account) or `COMPOSE_PROFILES=activitypub` in `.env` and follow the [Ghost Docker guide](https://docs.ghost.org/install/docker).

### How do I move an existing Ghost-CLI install to Docker?

The repository includes `scripts/migrate.sh`. It stops Nginx, so other sites on that server go offline during the move. Read the migration section of the [Ghost Docker guide](https://docs.ghost.org/install/docker) first.

## Related guides

> [card] [VPS and dedicated server guides](https://help.freakhosting.com/portals/other/vps-and-dedicated-server-guides.md)
>
> Every guide in this section.

> [card] [Install Docker](https://help.freakhosting.com/portals/other/how-to-install-docker.md)
>
> Docker Engine from the official repository.

> [card] [Run WordPress with Docker Compose](https://help.freakhosting.com/portals/other/how-to-run-wordpress-with-docker-compose.md)
>
> Another blog platform in Docker.

> [card] [Update Docker containers](https://help.freakhosting.com/portals/other/how-to-update-docker-containers.md)
>
> Pull new images safely.

> [card] [Check if a port is open](https://help.freakhosting.com/portals/other/how-to-check-if-a-port-is-open-from-outside.md)
>
> Test ports 80 and 443.

***

> [!NOTE]
>
> **Checked against the official [Ghost Docker documentation](https://docs.ghost.org/install/docker) and the [TryGhost/ghost-docker](https://github.com/TryGhost/ghost-docker) repository** on 4 November 2026 (images `ghost:6-alpine`, `mysql:8.0.46`, `caddy:2.11.7-alpine`); the repository's `compose.yml` validated with `docker compose config` on Ubuntu 24.04 LTS. The stack can change with each repository update.

> [!NOTE]
>
> ### Need Extra Help?
>
> If you encounter any issues, our support team is ready to assist:
>
> * **Live Chat:** Quick assistance via our website.
> * **Support Ticket:** [Open a Ticket](https://freakhosting.com/clientarea/submitticket.php)
> * **Discord:** [Join our Community](https://discord.gg/freakhosting)
> * **Email:** [support@freakhosting.com](mailto:support@freakhosting.com)

> [!TIP]
>
> ### Save on Your Hosting
>
> Ready to upgrade your hosting? Use code **KB20** at checkout for **20% off** your first order!

***

**Last Updated:** November 2026


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.