Skip to content
appsgit

Deploy guide

How to self-host PostHog with Docker Compose

PostHog Docker Compose setup with the official hobby deployment: 16 GB RAM sizing, the deploy script, automatic HTTPS, ports to firewall, backups, upgrades.

  • Updated
  • Intermediate
  • About 30 minutes

You will need

  • 4 vCPU / 16 GB RAM (8 GB is the hard floor)
  • 30 GB+ SSD storage
  • Ubuntu with sudo access
  • A domain with an A record pointing at the server

What is PostHog?

PostHog is an open source product analytics platform. Beyond page views, it captures user events and gives you funnels, retention, session replay, heatmaps, feature flags, A/B testing, surveys and a data warehouse in one tool. It is the most popular open source alternative to Mixpanel, Amplitude and Hotjar, and its self-hosted "hobby" deployment is MIT licensed.

Know what you are signing up for. The hobby deployment is a large Docker Compose stack: ClickHouse, Kafka, PostgreSQL, Redis, Temporal, object storage, a dozen PostHog services and Caddy for HTTPS. PostHog provides no support or guarantees for it, and says plainly that PostHog Cloud is usually cheaper for most teams.

Requirements

  • An Ubuntu server equivalent to Hetzner's 4 vCPU, 16 GB RAM machine, with more than 30 GB of storage. The installer warns that 8 GB is the absolute minimum.
  • A domain with an A record pointing at the server's public IP. The installer refuses IP addresses because it needs a real certificate.
  • Ports 80 and 443 open to the internet.

Step 1: Prepare the server

Start from a fresh Ubuntu server. The script installs Docker and a standalone docker-compose binary if they are missing. Create a folder and point DNS at the server first, so the certificate can be issued on the first try:

mkdir -p ~/posthog-hobby && cd ~/posthog-hobby
dig +short posthog.example.com   # must print this server's IP

Step 2: Create the Docker Compose file

PostHog generates the Compose file for you. The official command pipes a script into bash with sudo, so download it and read it before running it:

curl -fsSL https://raw.githubusercontent.com/posthog/posthog/HEAD/bin/deploy-hobby -o deploy-hobby
less deploy-hobby
bash deploy-hobby

The script asks for a version (press Enter for latest) and your domain, then:

  • clones the PostHog repo and copies docker-compose.hobby.yml to docker-compose.yml, along with docker-compose.base.yml;
  • writes .env with a random POSTHOG_SECRET and ENCRYPTION_SALT_KEYS, plus optional AI API keys if you enter them;
  • downloads a GeoIP database and starts the stack with Caddy on ports 80 and 443.

It also sends an install event containing your domain to PostHog's own analytics. Keep .env safe: losing ENCRYPTION_SALT_KEYS makes encrypted data such as integration credentials unreadable.

Step 3: Start and open the app

The first start pulls many images and runs migrations; the script waits up to 10 minutes for the web container to report healthy. Follow along in another terminal:

cd ~/posthog-hobby && sudo docker-compose logs -f web

When it is up, open https://posthog.example.com and create the first account immediately, since the first person to sign up owns the instance. Copy the project API key and the snippet from the onboarding screen into your site or app, then watch events arrive under Activity.

Step 4: Put it behind HTTPS

HTTPS is already handled: the proxy service is Caddy, which obtains a Let's Encrypt certificate for your domain. What remains is closing ports you did not ask for. The hobby Compose file publishes Temporal on 7233 and the Temporal UI on 8081 on all interfaces. Docker-published ports bypass ufw, so a host firewall rule will not hide them. Block everything except 22, 80 and 443 in your cloud provider's firewall, or change those two mappings in docker-compose.yml to 127.0.0.1:7233:7233 and 127.0.0.1:8081:8080. Note that the upgrade script regenerates the Compose file, so a cloud firewall is the more durable fix.

Backups and upgrades

Back up .env, the Postgres database (users, projects, dashboards, feature flags) and the ClickHouse data (events):

sudo docker-compose exec -T db pg_dump -U posthog posthog > posthog-pg-$(date +%F).sql

For ClickHouse, the reliable option on a single server is a disk snapshot from your hosting provider, or stopping the stack and copying the clickhouse-data Docker volume.

To upgrade, run the official script from the same folder:

bash -c "$(curl -fsSL https://raw.githubusercontent.com/posthog/posthog/HEAD/bin/upgrade-hobby)"

PostHog no longer cuts tagged releases for hobby installs, so upgrades move you to the latest code. Take a snapshot first.

Troubleshooting

  • Health check times out after 10 minutes: usually not enough RAM. Check free -h and sudo docker-compose ps for containers that exited, then sudo docker-compose logs for the failing one.
  • Certificate errors: DNS did not point at the server when Caddy started. Fix DNS and run sudo docker-compose restart proxy.
  • Events do not appear: check the browser console for blocked requests (ad blockers block PostHog), and confirm the snippet uses your domain as api_host.
  • Disk fills up: ClickHouse and Kafka grow with event volume. Add storage or reduce session replay sampling.

Next steps

Set up a reverse-proxied ingestion path on your own domain to reduce ad-blocker losses, configure email over SMTP for invites, create your first funnel and feature flag, and decide early whether your volume justifies moving to PostHog Cloud.

Spotted something out of date? Tell us and we will update the guide.

FAQ

PostHog questions

Still curious? Email info@appsgit.com.

Can you self-host PostHog for free?

Yes. The hobby Docker Compose deployment is free and MIT licensed. PostHog gives no guarantees or support for it, and its docs say PostHog Cloud is usually cheaper than running it yourself, since the Cloud free tier includes 1 million events, 5,000 session recordings and 1,500 survey responses per month.

How much RAM does self-hosted PostHog need?

PostHog asks for the equivalent of a Hetzner VM with 4 vCPU, 16 GB of RAM and more than 30 GB of storage. The deploy script itself warns that you really need 8 GB or more to run the stack at all.

What ports does self-hosted PostHog use?

Caddy serves PostHog on ports 80 and 443. The hobby Compose file also publishes Temporal on 7233 and the Temporal UI on 8081 on all interfaces, so block those in a cloud firewall. Object storage ports are bound to localhost.

What is the default PostHog login?

There is none. When the stack is up, you open your domain and sign up; the first account creates the organisation. Do it right away so nobody else claims the instance.

PostHog vs Plausible or Umami?

Plausible and Umami are lightweight, privacy-friendly web analytics that run in a few hundred MB of RAM. PostHog is a full product analytics suite with event funnels, session replay, feature flags, A/B tests and surveys, and needs a large server. Pick Plausible or Umami for page views, PostHog for product analytics.

Is the PostHog hobby deployment production ready?

Not in a strict sense. It is a single-server install with no high availability and no official support. PostHog suggests it for personal projects and small volumes, and recommends PostHog Cloud for anything business critical.