How to install PostHog on a VPS
PostHog combines product analytics, feature flags and other developer-focused tools in one platform. Its self-hosted stack is much larger than a single container, so this guide explains the supported deployment workflow, server preparation, HTTPS and the checks needed before accepting production data.
Prerequisites
PostHog self-hosting is not a two-container demo. Its stack runs about 10 containers (PostgreSQL, ClickHouse, Kafka, Zookeeper, Redis, MinIO, Caddy and others). Official minimums are 4 vCPU, 16 GB RAM, 30+ GB disk. Use Ubuntu 22.04 or 24.04, a public IP, SSH and a dedicated domain such as posthog.example.com.
Expect to manage database storage, object storage, background workers, upgrades and backups. A disposable evaluation server is useful for learning, but production analytics needs monitored storage and a recovery plan.
Step 1, Connecting to your server
Connect and patch the host:
ssh root@SERVER_IP
apt update && apt upgrade -y
apt install -y ca-certificates curl git
mkdir -p /opt/posthog
cd /opt/posthog
chmod 750 /opt/posthogKeep ports 80 and 443 available for the proxy. Do not install an unrelated database or queue service on this host unless the PostHog documentation explicitly supports that layout.
Step 2, Installing Docker and Docker Compose
Install Docker Engine and the Compose plugin from Docker's official Ubuntu instructions. Verify the runtime and resource limits:
docker --version
docker compose version
docker system df
systemctl enable --now dockerDo not run a guessed docker run command for PostHog. The application depends on a coordinated set of services and environment variables.
Step 3, Running the official PostHog Hobby installer
PostHog recommends its one-line Hobby installer for self-hosted deployments (Helm is sunset, and hand-written Compose files are unsupported). Run it as root from /opt/posthog:
curl -fsSL https://posthog.com/deploy-hobby | bashThe installer prompts for the hostname, retrieves the Compose definition, generates secrets, creates the .env file and starts the stack. The first boot takes several minutes while databases migrate and images download.
Required environment variables
Set these values in the environment file created by the installer before starting the stack (or edit it afterward and restart):
| Variable | Description | How to generate |
|---|---|---|
SECRET_KEY |
Django cryptographic secret | openssl rand -hex 32 |
SITE_URL |
Full URL of your PostHog instance | https://posthog.example.com |
IS_BEHIND_PROXY |
Set to True if behind your own reverse proxy |
True |
TRUSTED_PROXIES |
CIDR range of trusted proxies | 0.0.0.0/0 |
SECRET_KEY is required for the Django application. SITE_URL must be the full public URL including protocol. IS_BEHIND_PROXY=True and TRUSTED_PROXIES=0.0.0.0/0 are needed when you place your own Nginx or Traefik in front of the bundled Caddy proxy.
Disclaimer: Self-hosted PostHog is officially unsupported โ there is no CVE coverage or data-loss recovery. Paid features and enterprise support are Cloud-only.
Step 4, Configuring the reverse proxy
The Hobby installer bundles Caddy with auto-TLS. By default Caddy listens on ports 80 and 443 and provisions Let's Encrypt certificates automatically. This is the recommended setup for most users.
If you place your own Nginx or Traefik in front, you MUST set IS_BEHIND_PROXY=True and TRUSTED_PROXIES=0.0.0.0/0 in the environment file. Your proxy must forward X-Forwarded-For and X-Forwarded-Proto headers correctly, otherwise PostHog will produce redirect loops.
Forward posthog.example.com to the stack's public web service, not to an internal database or worker. Terminate HTTPS, preserve WebSocket and forwarded protocol headers when required, and keep internal ports private.
Allow only SSH, 80 and 443 through the public firewall. Confirm that the domain resolves to the VPS and that the certificate covers the exact hostname. Test the health endpoint and the browser interface through HTTPS before adding a production SDK.
Step 5, First access and initial setup
Open https://posthog.example.com, create the first organization and administrator and change all temporary values. Create a test project, configure the SDK with a non-production test key and send an event from a disposable environment.
Confirm that the event appears, that timestamps use the expected timezone and that feature flag evaluation behaves as documented. Review data retention, user permissions and privacy settings before inviting the rest of the team.
Maintenance
Follow PostHog's release notes and upgrade procedure. Back up every persistent store required by the current stack, including object storage and secrets. Test a restore before an upgrade and keep sufficient disk for migrations and temporary images.
Monitor CPU, memory, queue depth, database health, object storage and event ingestion. If one component is unhealthy, collect its logs and the Compose project status before applying a restart. For a serious production workload, compare the operational cost of self-hosting with the managed option before committing to the architecture.
Tools mentioned
PostHog
โProduct analytics, session replay, feature flags and experiments together.
Free monthly: 1M analytics events, 5k session recordings, 1M feature-flag requests and 100k exceptions.