| 1 | --- |
| 2 | title: Self-hosting Ghost |
| 3 | description: Run your own Ghost with Docker and one setup script. |
| 4 | --- |
| 5 | |
| 6 | Ghost runs as a handful of containers: the web app, the API, the docs, a |
| 7 | delivery worker for webhooks and email, a code search node, Postgres, and S3 |
| 8 | storage, plus an optional importer for GitHub repositories. One script asks a few questions, writes the configuration, and |
| 9 | starts all of them. |
| 10 | |
| 11 | ## What you need |
| 12 | |
| 13 | - [Docker](https://docs.docker.com/get-docker/) |
| 14 | Desktop on macOS and Windows). |
| 15 | - About 4 GB of memory free while the images build for the first time. |
| 16 | - An SMTP server or an HTTP email relay. Ghost uses it for email |
| 17 | verification, password resets and notifications. |
| 18 | - For a public instance: a domain, and ports 80 and 443 open. HTTPS |
| 19 | certificates are issued automatically. |
| 20 | |
| 21 | ## Install |
| 22 | |
| 23 | <Tabs items={[ |
| 24 | <Tab value=" |
| 25 | ```bash |
| 26 | git clone https://github.com/PhantomKnight287/ghost.git |
| 27 | cd ghost |
| 28 | ./docker/setup.sh |
| 29 | ``` |
| 30 | </Tab> |
| 31 | <Tab value=" |
| 32 | ```powershell |
| 33 | git clone https://github.com/PhantomKnight287/ghost.git |
| 34 | cd ghost |
| 35 | powershell -ExecutionPolicy Bypass -File docker\setup.ps1 |
| 36 | ``` |
| 37 | </Tab> |
| 38 | </Tabs> |
| 39 | |
| 40 | The script asks: |
| 41 | |
| 42 | 1. **Domain or IP.** Enter a domain such as ` |
| 43 | over HTTPS. Enter `localhost` or an IP address to serve plain HTTP on |
| 44 | ports 3000, 3001 and 3003. |
| 45 | 2. **SSH port.** The port for ` |
| 46 | 3. **Email.** Pick SMTP or an HTTP relay, then enter its details. One of them |
| 47 | is required. |
| 48 | 4. **Storage.** Use the bundled S3 storage, or point Ghost at an existing |
| 49 | bucket on Cloudflare R2, Tigris, MinIO or another S3-compatible service. |
| 50 | 5. **GitHub imports.** Optional, off by default. Say yes to let people import |
| 51 | a GitHub repository with its code, releases, issues and pull requests, then |
| 52 | enter the client ID and secret of a GitHub OAuth app. The script prints the |
| 53 | callback URL the app needs. See |
| 54 | [GitHub imports](/self-hosting/configuration#github-imports). |
| 55 | 6. **Secrets.** Press enter at each one and the script generates it: the auth |
| 56 | secret, the webhook encryption key, the SSH host key, the commit signing |
| 57 | key, and the database and storage passwords. |
| 58 | |
| 59 | The first build takes several minutes. When it is done, the script prints the |
| 60 | addresses: |
| 61 | |
| 62 | ``` |
| 63 | Web https://git.example.com |
| 64 | API https://api.git.example.com (git clone https://api.git.example.com/<user>/<repo>) |
| 65 | Docs https://docs.git.example.com |
| 66 | SSH ssh://git@git.example.com:1031/<user>/<repo>.git |
| 67 | ``` |
| 68 | |
| 69 | Open the web address and sign up. The first account is an ordinary account; |
| 70 | there is no separate admin. |
| 71 | |
| 72 | ## With a domain |
| 73 | |
| 74 | Before you run the script, create DNS records that point three names at the |
| 75 | server: |
| 76 | |
| 77 | | Name | Serves | |
| 78 | | --- | --- | |
| 79 | | `git.example.com` | The web app | |
| 80 | | `api.git.example.com` | The API and git over HTTP | |
| 81 | | `docs.git.example.com` | These docs | |
| 82 | |
| 83 | The web app and the API share a sign-in cookie, so they have to be subdomains |
| 84 | of one name. A [Caddy](https://caddyserver.com) container takes ports 80 and |
| 85 | 443 and gets a certificate for each name on its first request. |
| 86 | |
| 87 | <Callout type="warn |
| 88 | Open the SSH port (default `1031`) in your firewall as well. It does not go |
| 89 | through Caddy. |
| 90 | </Callout> |
| 91 | |
| 92 | ## Upgrading |
| 93 | |
| 94 | ```bash |
| 95 | git pull |
| 96 | ./docker/setup.sh # answer Y to start with the existing configuration |
| 97 | ``` |
| 98 | |
| 99 | On Windows, run `setup.ps1` the same way. The images are rebuilt, and database |
| 100 | migrations run before the API starts. |
| 101 | |
| 102 | ## Back up |
| 103 | |
| 104 | Everything that matters is in two places: |
| 105 | |
| 106 | - `docker/.env`: every secret. Without it, sign-ins, webhook secrets, the |
| 107 | SSH host key and the commit signing key are lost. |
| 108 | - The `ghost-server_postgres` volume, and the bucket (`ghost-server_rustfs |
| 109 | bundled storage). |
| 110 | |
| 111 | A database dump: |
| 112 | |
| 113 | ```bash |
| 114 | cd docker |
| 115 | docker compose exec postgres |
| 116 | ``` |
| 117 | |
| 118 | Next: [Self-hosting configuration](/self-hosting/configuration) covers every |
| 119 | setting, running without the script, and troubleshooting. |