Every pageview your visitors generate is a data point. When you use Google Analytics or a similar cloud service, that data point lives on someone else’s servers, gets fed into someone else’s advertising model, and remains subject to someone else’s terms of service. Self-hosted analytics flips that equation: you collect the data, you store it, and you decide what happens with it.

This guide covers everything you need to go from zero to a fully operational self-hosted analytics stack. We will compare the major open-source tools, walk through hardware requirements, deploy a working instance in under 30 minutes, and discuss the security practices that keep your installation reliable long-term.

Why Self-Host Your Analytics?

Before diving into tooling, it is worth understanding the concrete reasons organizations move away from cloud analytics providers. The motivations generally fall into four categories.

Full Data Ownership

When your analytics data sits on a third-party platform, you are a tenant. The provider can change pricing, alter data retention windows, modify the processing pipeline, or shut down entirely. With self-hosted analytics, your raw data lives in a database you control. You can query it directly with SQL, export it whenever you want, and integrate it with internal tools without going through a restrictive API.

Privacy and Visitor Trust

Cloud analytics services often set third-party cookies, fingerprint browsers, and share data across their advertising network. Self-hosted tools eliminate the third-party data flow entirely. Your visitors’ behavior stays between them and your server. Many self-hosted solutions also support cookie-free tracking, which means you can collect meaningful metrics without any cookie consent banners at all.

Regulatory Compliance

GDPR, CCPA, PECR, and similar regulations place strict requirements on where personal data is stored and how it is processed. When you self-host, the data never leaves your infrastructure. This simplifies compliance dramatically because you remove the need for Data Processing Agreements with third parties, you control data residency down to the specific server location, and you can respond to data subject access requests by querying your own database.

Cost at Scale

Cloud analytics pricing typically scales with pageviews. At low traffic, it is cheap or free. At 1 million monthly pageviews and above, the cost adds up fast. Consider the math: Plausible Cloud charges $69/month for 1 million pageviews, and Fathom charges $79/month at the same tier. A self-hosted instance running on a $20/month VPS can handle the same volume without additional charges. Over a year, that is a savings of $588 to $708 — and the gap only widens as traffic grows.

The cost is fixed regardless of traffic growth, which makes budgeting predictable. You will never get a surprise invoice because a blog post went viral or a marketing campaign drove more traffic than expected. This predictability matters especially for startups and small businesses operating on tight margins.

No Vendor Lock-In

When you build workflows around a cloud analytics provider, you become dependent on their data format, their API, and their feature set. If they change their pricing, deprecate a feature, or get acquired, you have limited options. Self-hosted analytics stores data in standard databases that you can query, export, and migrate at will. If you outgrow one tool, you can switch to another without losing years of historical data — it is all sitting in your PostgreSQL or MySQL database.

Self-Hosted Analytics Tools Compared

The open-source analytics ecosystem has matured significantly. Here are the five most capable self-hosted options available today, each with a different philosophy and feature set.

Feature Matomo Plausible CE Umami GoatCounter Ackee
Language PHP Elixir Node.js Go Node.js
Database MySQL / MariaDB ClickHouse + PostgreSQL PostgreSQL / MySQL PostgreSQL / SQLite MongoDB
License GPL-3.0 AGPL-3.0 MIT EUPL-1.2 MIT
Cookie-free mode Yes (configurable) Yes (default) Yes (default) Yes (default) Yes (default)
Real-time dashboard Yes Yes Yes No Yes
Goal / event tracking Yes (advanced) Yes Yes Basic Yes
E-commerce tracking Yes No No No No
API Comprehensive REST REST + Stats API REST REST GraphQL
Multi-site support Yes Yes Yes Yes Yes
Script size ~22 KB ~1 KB ~2 KB ~3.5 KB ~1.5 KB
Min RAM 2 GB 2 GB (ClickHouse needs memory) 512 MB 256 MB 512 MB
Google Analytics import Yes Yes Yes No No
Best for Full GA replacement Privacy-focused teams Developers, quick setup Minimalists, bloggers Small projects

For a detailed comparison of the three most popular options, see our Matomo vs Plausible vs Fathom comparison.

Matomo: The Full-Featured Powerhouse

Matomo is the closest thing to a drop-in Google Analytics replacement in the open-source world. It tracks everything: pageviews, events, e-commerce transactions, heatmaps (via plugins), session recordings, and funnels. The trade-off is complexity. Matomo requires more server resources, more configuration, and more ongoing maintenance. If you need advanced segmentation, custom dimensions, or e-commerce tracking, Matomo is the clear choice.

Plausible CE: Lean and Privacy-First

Plausible Community Edition is built with privacy as the core design principle. The tracking script is under 1 KB, it sets no cookies by default, and the dashboard shows exactly what most site owners need without the complexity of a full analytics suite. The ClickHouse backend makes it fast at scale, but it does add to the infrastructure requirements.

Umami: Developer-Friendly Simplicity

Umami hits a sweet spot between simplicity and capability. It is written in Node.js, uses PostgreSQL or MySQL, and can be deployed with a single Docker Compose file. The dashboard is clean, event tracking is straightforward, and the API is well-documented. For developers who want to get self-hosted analytics running quickly without sacrificing essential features, Umami is hard to beat.

GoatCounter and Ackee: The Lightweight Options

GoatCounter is a single Go binary that can run with SQLite, making it ideal for personal blogs and small sites where minimal resource usage matters. It was created by Martin Tournoij as a reaction to the bloat of mainstream analytics tools. You can run it on the cheapest VPS available or even on a Raspberry Pi. The dashboard is minimal but covers the essentials: pageviews, referrers, browsers, screen sizes, and locations.

Ackee uses MongoDB and provides a GraphQL API, which appeals to developers who prefer that query paradigm. Its dashboard has a distinctive visual style with animated charts that update in real time. Both tools are excellent for projects where you need basic traffic metrics without the overhead of a full analytics platform.

Hardware Requirements and Hosting Options

The resources you need depend on two factors: the analytics tool you choose and the volume of traffic you are tracking. Here is a practical breakdown.

Traffic-Based Sizing Guide

Monthly Pageviews CPU RAM Storage Recommended Tool
Under 50K 1 vCPU 512 MB–1 GB 10 GB SSD GoatCounter, Umami, Ackee
50K–500K 1–2 vCPU 2 GB 20 GB SSD Umami, Plausible CE
500K–5M 2–4 vCPU 4 GB 50 GB SSD Plausible CE, Matomo
5M+ 4+ vCPU 8 GB+ 100 GB+ SSD Matomo (with tuning), Plausible CE

Hosting Options

VPS providers are the most common choice. Hetzner, DigitalOcean, Linode, and Vultr all offer plans starting at $4–6/month that are more than sufficient for small to medium traffic sites. A $20/month VPS from any of these providers will comfortably handle several million pageviews per month with Umami or Plausible CE.

Docker on any Linux server is the recommended deployment method for most tools. Docker Compose handles the application, database, and networking in a single configuration file. This approach works identically whether you are running on a VPS, a dedicated server, or a machine in your office.

Bare metal or homelab setups are viable if you already have the infrastructure. An old laptop running Ubuntu Server can easily handle analytics for a mid-traffic site. The main consideration is uptime — if your home internet goes down, your tracking script will fail to load and you will lose data for that period.

Kubernetes is overkill for most analytics deployments, but if you already run a cluster, Matomo, Plausible, and Umami all have Helm charts available. This makes sense when you need high availability or already manage your infrastructure through Kubernetes.

Network and Bandwidth

Analytics tracking generates minimal bandwidth. A single pageview event is typically 200–500 bytes of data sent to your server. At 1 million pageviews per month, that is roughly 500 MB of inbound tracking data — trivial for any modern server. The tracking script itself is cached by the browser after the first load, so the bandwidth impact on your visitors is negligible.

The more important network consideration is latency. Your analytics server should be geographically close to your audience or behind a CDN. If your visitors are primarily in Europe and your analytics server is in the US, the tracking request adds 100–200ms of latency. While this does not affect page load (scripts are loaded asynchronously), it can cause data loss if visitors navigate away before the tracking request completes. Placing your server in the same region as your audience, or using a CDN to proxy the tracking script, solves this.

Database Considerations

The database is typically the bottleneck in self-hosted analytics. A few tips that apply across all tools:

  • Use SSDs, never spinning disks. Analytics workloads involve constant small writes and occasional large reads.
  • Allocate at least 50% of your RAM to the database buffer pool (InnoDB for MySQL, shared_buffers for PostgreSQL).
  • Set up automated data archival or purging. Raw analytics data grows fast — 1 million pageviews per month generates roughly 1–2 GB of data per year in most tools.
  • Consider running the database on a separate server or managed service (like a managed PostgreSQL instance) if you expect high traffic.

Quick Start: Your First Self-Hosted Analytics in 30 Minutes

We will use Umami for this walkthrough because it has the lowest barrier to entry: a single Docker Compose file, PostgreSQL as the database, and a clean UI that works immediately after deployment. You need a Linux server with Docker and Docker Compose installed.

Step 1: Create the Project Directory

mkdir -p /opt/umami && cd /opt/umami

Step 2: Create the Docker Compose File

Create a file named docker-compose.yml with the following content:

services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://umami:your-secure-password-here@db:5432/umami
      APP_SECRET: replace-with-a-random-string
    depends_on:
      db:
        condition: service_healthy
    restart: always

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: your-secure-password-here
    volumes:
      - umami-db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U umami"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: always

volumes:
  umami-db:

Replace your-secure-password-here with a strong password and replace-with-a-random-string with a random secret. You can generate one with:

openssl rand -hex 32

Step 3: Start the Stack

docker compose up -d

Wait about 30 seconds for the database to initialize and Umami to start. Check the logs to confirm everything is running:

docker compose logs -f umami

You should see a message indicating Umami is running on port 3000.

Step 4: Initial Configuration

Open http://your-server-ip:3000 in your browser. Log in with the default credentials:

  • Username: admin
  • Password: umami

Change the default password immediately. Go to Settings → Profile → Change Password.

Step 5: Add Your Website

Navigate to Settings → Websites → Add Website. Enter your domain name and you will receive a tracking script that looks like this:

<script defer src="http://your-server-ip:3000/script.js"
  data-website-id="your-website-id"></script>

Add this script to the <head> section of your website. Data will start appearing in the dashboard within seconds of your first visitor.

Step 6: Set Up a Reverse Proxy

For production use, you should place Umami behind a reverse proxy with SSL. Here is a minimal Nginx configuration:

server {
    listen 443 ssl http2;
    server_name analytics.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/analytics.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/analytics.yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

Use Certbot to obtain a free SSL certificate from Let’s Encrypt:

certbot --nginx -d analytics.yourdomain.com

After setting up SSL, update your tracking script URL to use https://analytics.yourdomain.com instead of the raw IP address.

Tracking Custom Events

Umami supports event tracking out of the box. You can track button clicks, form submissions, and other interactions using the data attribute approach:

<button data-umami-event="signup-button" data-umami-event-plan="pro">
  Sign Up
</button>

Or programmatically via JavaScript:

umami.track('signup-button', { plan: 'pro' });

Events appear in the Umami dashboard under the Events tab, giving you conversion and interaction data alongside your standard pageview metrics.

What to Do if the Tracking Script Is Blocked

Ad blockers and privacy extensions frequently block known analytics domains. When you self-host, you already have an advantage because your analytics domain is not on any default block list. To further reduce blocking, consider these strategies:

  • Serve the tracking script from your main domain using a reverse proxy path like /js/script.js instead of a separate analytics subdomain.
  • Rename the script file to something generic. Some Umami configurations support this natively.
  • Use a first-party subdomain (e.g., stats.yourdomain.com) rather than a separate domain.

These techniques are not about circumventing user preferences — they are about ensuring that visitors who have not opted out are accurately counted. Self-hosted analytics already respects privacy by default; reducing false positives from overly aggressive block lists simply improves data accuracy.

Security and Maintenance Checklist

Running your own analytics server means you are responsible for its security and uptime. Here is a practical checklist that covers the essentials.

SSL/TLS Configuration

  • Always serve your analytics dashboard and tracking script over HTTPS. Mixed content (HTTP script on an HTTPS page) will be blocked by browsers.
  • Use Let’s Encrypt with auto-renewal via Certbot. Certificates expire every 90 days.
  • Set up HSTS headers to prevent downgrade attacks.
  • Test your SSL configuration at ssllabs.com/ssltest and aim for an A+ rating.

Firewall Rules

  • Expose only ports 80 (HTTP redirect), 443 (HTTPS), and 22 (SSH) to the internet.
  • Keep the database port (5432 for PostgreSQL, 3306 for MySQL) closed to external access. Docker networking handles the internal connection.
  • Use ufw or iptables to enforce these rules:
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Automated Backups

Your analytics data is valuable. Set up automated daily backups of the database:

# PostgreSQL backup (add to crontab)
0 3 * * * docker exec umami-db-1 pg_dump -U umami umami | gzip > /backups/umami-$(date +\%Y\%m\%d).sql.gz

# Keep only the last 30 days
0 4 * * * find /backups -name "umami-*.sql.gz" -mtime +30 -delete

Test your backup restoration process at least once. A backup you have never tested is not a backup.

Updates and Patching

  • Subscribe to the GitHub release notifications for your chosen analytics tool.
  • Update the Docker images regularly. For Umami, the process is:
cd /opt/umami
docker compose pull
docker compose up -d
  • Keep the host operating system patched. Enable unattended security updates on Ubuntu/Debian with apt install unattended-upgrades.
  • Update Docker Engine itself periodically.

Monitoring and Alerting

  • Set up a simple uptime check using a free service like UptimeRobot or Hetrix Tools. Point it at your analytics dashboard URL.
  • Monitor disk usage. Analytics databases grow over time, and a full disk will crash your instance.
  • Check container health regularly: docker compose ps should show all services as “Up (healthy)”.
  • Consider setting up log rotation to prevent log files from consuming disk space.

Access Control

  • Change all default passwords immediately after installation.
  • Use SSH key authentication and disable password-based SSH login.
  • If your analytics dashboard is only accessed by your team, restrict access by IP at the Nginx level or use HTTP basic auth as an additional layer.
  • Enable two-factor authentication if your chosen tool supports it (Matomo does natively).

Self-Hosted vs Cloud: When Each Makes Sense

Self-hosting is not the right choice for everyone. Here is an honest comparison to help you decide.

Factor Self-Hosted Cloud Analytics
Setup time 30 minutes to a few hours 5 minutes
Ongoing maintenance You handle updates, backups, security Managed by the provider
Data ownership Complete — you own the server and data Provider’s terms apply
Privacy control Full control over data flow Depends on provider
Cost at low traffic $4–20/month (VPS cost) Free to $10/month
Cost at high traffic Same $4–20/month $50–500+/month
Uptime responsibility You Provider (with SLA)
Scalability Manual — upgrade server as needed Automatic
Feature updates You pull and deploy new versions Automatic
GDPR compliance Simplified — no third-party DPA needed Requires DPA with provider
Custom integrations Direct database access, full API Limited to provider’s API
Team required Basic Linux/Docker knowledge None

Self-Hosting Makes Sense When

  • You have strict data residency requirements (healthcare, finance, government).
  • Your traffic exceeds 100K monthly pageviews and cloud costs are becoming significant.
  • You need direct database access for custom reporting or integration with internal tools like Grafana dashboards connected to Matomo.
  • Privacy is a competitive advantage for your business and you want to make a credible claim about data handling.
  • You or your team already manage servers and adding one more service is trivial.

Cloud Makes Sense When

  • You are a solo founder or small team without server management experience and you would rather spend time on your product.
  • Your traffic is low enough that cloud pricing is cheaper than a VPS.
  • You need guaranteed uptime with an SLA and do not want to be on call for infrastructure issues.
  • You want managed features like email reports, team sharing, and integrations without configuring them yourself.

The Hybrid Approach

Some teams run self-hosted analytics alongside a lightweight cloud solution. For example, you might run Matomo self-hosted for detailed e-commerce tracking while using Plausible Cloud for a quick public-facing traffic dashboard. This gives you the depth of self-hosted data with the convenience of a managed service for day-to-day monitoring.

Migration Path: Moving From Google Analytics

If you are currently on Google Analytics and considering a move to self-hosted, the transition does not have to be abrupt. A practical migration strategy looks like this:

  1. Deploy your self-hosted analytics tool and run it in parallel with Google Analytics for 2–4 weeks. This lets you verify that tracking numbers are comparable and that no data is being missed.
  2. Import your historical Google Analytics data. Matomo, Plausible CE, and Umami all support GA data import, though the depth of imported data varies. Matomo preserves the most detail.
  3. Update your privacy policy to reflect the change in data processing. If you are moving to a cookie-free tool, you may be able to simplify or remove your cookie consent banner.
  4. Remove the Google Analytics tracking script once you are confident in your self-hosted data. Do not forget to check Google Tag Manager, WordPress plugins, and any other places where the GA snippet might be injected.

The parallel-running period is important. It gives you time to catch configuration issues, verify that event tracking is correctly mapped, and build confidence in the new system before cutting over.

Deep Dives

This guide covered the landscape of self-hosted analytics at a high level. For step-by-step setup instructions tailored to each major tool, see our detailed guides:

  • Matomo Self-Hosted Setup Guide — Complete walkthrough of installing Matomo on your own server, including MySQL tuning, cron-based archiving, plugin recommendations, and performance optimization for high-traffic sites. (Coming soon)
  • Umami Analytics on Docker: From Zero to Production — Extended guide covering Umami deployment with PostgreSQL, custom event tracking, API usage, and integration with CI/CD pipelines. (Coming soon)
  • Plausible CE Self-Hosted Deployment — Guide to running Plausible Community Edition with ClickHouse, including reverse proxy configuration, Google Analytics import, and resource optimization. (Coming soon)

If you are still evaluating which tool fits your use case, our Matomo vs Plausible vs Fathom comparison breaks down the differences in features, pricing, and philosophy. And for background on how modern analytics tools work without cookies, read our explainer on cookie-free analytics.