Deployment guide

How to Host PostHog on a VPS

Deploy on a VPS Cloud →

Tutorial

How to Host PostHog on a VPS

Self-hosting9 min read17 steps

PostHog is the open-source answer to Mixpanel and Amplitude: events, funnels, session recordings, feature flags and A/B testing in a single self-hosted instance. On the vendor's cloud, the bill rises as soon as your event volume exceeds the free tier — a few million events per month is enough to reach several hundred dollars. On your VPS, the cost is simply that of the server. You keep your users' behavioural data on your own infrastructure, you comply with GDPR without additional contracts, and you enable every module — session replay, feature flags, A/B experiments — with no paid tier. This guide covers step-by-step installation via Docker Compose, configuring an nginx reverse proxy with HTTPS, setting up object storage for session recordings, wiring up the JavaScript SDK, and activating feature flags.

Contents· What PostHog does that SaaS alternatives cannot1/11
  1. 01What PostHog does that SaaS alternatives cannot
  2. 02Quick comparison: PostHog self-hosted vs Mixpanel Cloud
  3. 03Server requirements
  4. 04Install PostHog with Docker Compose
  5. 05Configure an nginx reverse proxy for HTTPS
  6. 06Object storage for session recordings (S3 or MinIO)
  7. 07Send your first events from your application
  8. 08Enable Feature Flags
  9. 09Performance tip: disable session recordings at launch
  10. 10Updating PostHog
  11. 11Official documentation

What PostHog does that SaaS alternatives cannot

Mixpanel, Amplitude and Heap are cloud tools: your data goes to their servers, their retention policy dictates how long you can keep it, and sampling kicks in automatically once your volume exceeds certain thresholds. Self-hosted PostHog removes all three of those constraints. Events stay in your ClickHouse database, on your disk or your object storage — no copy leaves your infrastructure. retention has no imposed ceiling: you decide when to purge old data. There is no sampling: every event is recorded, even during traffic spikes. Add to that GDPR compliance without negotiating a DPA with a third party, the ability to modify the source code, and direct access to raw data in ClickHouse for your own SQL analyses.

Quick comparison: PostHog self-hosted vs Mixpanel Cloud

Scroll the table

CriterionPostHog self-hostedMixpanel Cloud
Monthly cost (1M events/month)~$15–20 (VPS cost)~$25–100+
Data hosted on your serversYesNo
Simplified GDPR complianceYes (no third-party DPA)Partial (DPA required)
Automatic samplingNoneActivated beyond tiers
Session recordings includedYesPaid option
Feature flags & A/B testingYes, includedPaid (Growth+ plan)
Raw SQL access to dataYes (direct ClickHouse)No

Server requirements

PostHog ships ClickHouse, Kafka, Redis and PostgreSQL in the same Docker Compose stack. It is the most resource-intensive analytics solution in this category, and under-sizing the VPS causes ClickHouse crashes or Kafka timeouts from the very first events. Plan for at least 4 vCPU and 8 GB of RAM for light usage (less than one million events per month). For a more sustained load — 1 to 5 million events per month — aim for 8 vCPU and 16 GB of RAM. On the storage side, ClickHouse is very efficient at compression, but session recordings accumulate quickly: allow at least 50 GB of SSD, and add external object storage (S3 or MinIO) as soon as you enable recordings. On the software side: Docker Engine 24+ and Docker Compose v2, a domain name with an A record pointing to the VPS, and ports 80 and 443 open in your firewall.

Install PostHog with Docker Compose

  1. Install Docker on the VPS

    Connect via SSH, then install Docker with the official script: curl -fsSL https://get.docker.com | sh. Add your user to the docker group to avoid sudo: usermod -aG docker $USER. Verify with docker compose version that Compose v2 is available.

  2. Clone the PostHog repository and prepare the environment

    Clone the official repository: git clone https://github.com/PostHog/posthog.git && cd posthog. Copy the sample environment file: cp .env.example .env. Open .env in an editor to configure the essential variables.

  3. Configure environment variables

    In .env, set at a minimum: SECRET_KEY (generate a 50-character random key with python3 -c "import secrets; print(secrets.token_hex(25))"), SITE_URL=https://posthog.your-domain.com, DISABLE_SECURE_SSL=false (or true if testing over HTTP locally without a certificate). Leave the POSTGRES_*, REDIS_* and CLICKHOUSE_* defaults for a simple deployment.

  4. Start the stack and wait for the migration

    Launch all services in the background: docker compose -f docker-compose.yml up -d. The first time, PostHog automatically runs database migrations — this takes 2 to 5 minutes depending on server performance. Follow progress with docker compose logs -f web until you see PostHog server is now listening on port 8000.

  5. Access the interface and create your account

    Navigate to http://localhost:8000 (or via your domain if DNS is already configured). The first-launch wizard guides you through creating the admin account, naming your organisation, and creating your first project. Note the Project API Key shown — you will need it to wire up the SDK.

Configure an nginx reverse proxy for HTTPS

  1. Install nginx and Certbot

    On the host machine (outside Docker): apt install -y nginx certbot python3-certbot-nginx. Make sure your domain posthog.your-domain.com already points to the VPS IP before this step — Certbot needs to validate via HTTP.

  2. Create the nginx vhost

    Create /etc/nginx/sites-available/posthog with: server { listen 80; server_name posthog.your-domain.com; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }. Enable it: ln -s /etc/nginx/sites-available/posthog /etc/nginx/sites-enabled/.

  3. Issue the TLS certificate

    Run certbot --nginx -d posthog.your-domain.com. Certbot automatically updates the vhost to redirect HTTP to HTTPS and configures automatic renewal. Test renewal with certbot renew --dry-run.

  4. Reload nginx and verify

    Apply the configuration: nginx -t && systemctl reload nginx. Open https://posthog.your-domain.com in a browser — you should see the PostHog interface with a valid certificate. Update SITE_URL in .env if not already done, then restart the web service: docker compose restart web.

Object storage for session recordings (S3 or MinIO)

  1. Why object storage is necessary

    Session recordings generate many small files (one per session segment). Storing them on the VPS local disk fills the SSD quickly and complicates backups. An S3-compatible object storage — whether AWS S3, Cloudflare R2 or self-hosted MinIO — externalises this storage elastically.

  2. Deploy MinIO on the same VPS (self-hosted option)

    If you do not want to depend on an external service, add MinIO to your docker-compose.yml: minio: image: minio/minio environment: MINIO_ROOT_USER: posthog MINIO_ROOT_PASSWORD: change-me-strong-password command: server /data --console-address ':9001' volumes: - ./minio-data:/data. Then create a bucket named posthog in the MinIO console (port 9001).

  3. Configure PostHog environment variables

    In .env, add: OBJECT_STORAGE_ENABLED=true, OBJECT_STORAGE_ENDPOINT=http://minio:9000 (or your S3 bucket URL), OBJECT_STORAGE_ACCESS_KEY_ID=posthog, OBJECT_STORAGE_SECRET_ACCESS_KEY=change-me-strong-password, OBJECT_STORAGE_BUCKET=posthog. Restart the stack: docker compose up -d.

  4. Verify with a first session recording

    In PostHog project settings, enable 'Session recording'. Browse your application for a few seconds, then return to PostHog under 'Session Recordings'. A recording should appear within a few minutes. Check in MinIO (or S3) that files have been created in the bucket.

Send your first events from your application

  1. Install the JavaScript SDK

    In your front-end project: npm install posthog-js. If you use a framework such as React, Vue or Next.js, import and initialise PostHog once at the root level of your application.

  2. Initialise with your project key and your instance URL

    Add the initialisation: import posthog from 'posthog-js'; posthog.init('phc_YOUR_PROJECT_API_KEY', { api_host: 'https://posthog.your-domain.com', autocapture: true });. Replace phc_YOUR_PROJECT_API_KEY with the key visible in PostHog project settings. With autocapture: true, PostHog automatically records clicks, form submissions and page changes.

  3. Capture custom events

    For a specific business event, call: posthog.capture('order_placed', { amount: 49.90, currency: 'USD', product: 'vps-cloud-4vcpu' });. The properties associated with the event will be available in funnels, cohorts and ClickHouse SQL queries.

  4. Verify in the dashboard

    Go to PostHog under 'Activity' or 'Events'. Events appear in near-real-time (a few seconds of latency). If nothing arrives after two minutes, check that api_host in the init exactly matches your instance URL, and that the TLS certificate is valid.

Enable Feature Flags

Feature flags let you roll out a feature progressively — first to 5% of users, then 20%, then 100% — without recompiling or redeploying your application. In PostHog, go to 'Feature Flags' and create a new flag with a key (my-new-module), a rollout condition (percentage or user cohort), and optionally variants for a proper A/B test. On the JavaScript side, evaluate the flag: if (posthog.isFeatureEnabled('my-new-module')) { /* show the new feature */ }. For server-side evaluation (Python or Node.js), use the corresponding backend SDK with the same PROJECT_API_KEY — evaluation then happens without a client round-trip, avoiding content flash. PostHog automatically records a $feature_flag_called event on every evaluation, letting you correlate a flag activation with any metric in your dashboard.

Performance tip: disable session recordings at launch

If your VPS is configured with the minimum 4 vCPU / 8 GB of RAM, session recordings consume significant ClickHouse resources from the very first hours of traffic. Recommendation: leave recordings disabled for the first 30 days. This gives you time to validate stack stability, fine-tune the object storage configuration, and add RAM if needed. Enable them afterwards in project settings — all future recordings will be captured, and you can set a sampling rate to record only a percentage of sessions and keep storage under control.

Updating PostHog

The PostHog team releases regular updates. To update: git pull origin master in the repository directory, then docker compose pull to fetch the new images, then docker compose up -d. Database migrations run automatically when the web service restarts — a brief interruption of a few tens of seconds is normal. Check the release notes before each major update: some versions require an intermediate update (no version skipping).

Official documentation

This guide covers the basic VPS installation. For advanced topics — ClickHouse replication, SAML SSO, webhooks, data warehouse integrations, and Kafka configuration options — refer to the official PostHog documentation. It remains the reference for major updates and specific use cases.

Deploy your instance on a ServOrbit Cloud VPS

A ServOrbit Cloud VPS with Docker preconfigured and scalable resources lets you install this tool without friction, and adjust RAM and vCPU as usage grows.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab