# How to Self-Host Ackee Analytics with Docker

## What Is Ackee?

[Ackee](https://ackee.electerious.com/) is a self-hosted, privacy-focused analytics tool that tracks page views, referrers, browsers, and operating systems without cookies. It stores data in MongoDB, exposes a GraphQL API, and provides a clean single-page dashboard. Ackee is designed for developers who want basic traffic metrics without the complexity of Matomo or the cloud dependency of Google Analytics.

## Prerequisites

- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed ([guide](/foundations/docker-compose-basics))
- 512 MB of free RAM
- 2 GB of free disk space
- A domain name (recommended for CORS and HTTPS)

## Docker Compose Configuration

Create a `docker-compose.yml` file:

```yaml
services:
  ackee:
    image: electerious/ackee:3.5.1
    container_name: ackee
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      ACKEE_MONGODB: "mongodb://mongo:27017/ackee"
      ACKEE_USERNAME: "admin"                        # CHANGE: dashboard login username
      ACKEE_PASSWORD: "change-this-password"         # CHANGE: use a strong password
      ACKEE_ALLOW_ORIGIN: "https://example.com"      # CHANGE: your website's domain (CORS)
    depends_on:
      - mongo
    networks:
      - analytics

  mongo:
    image: mongo:7.0.16
    container_name: ackee-mongo
    restart: unless-stopped
    volumes:
      - ackee-data:/data/db
    networks:
      - analytics

networks:
  analytics:
    driver: bridge

volumes:
  ackee-data:
```

### Environment Variables

| Variable | Purpose |
|----------|---------|
| `ACKEE_MONGODB` | MongoDB connection string |
| `ACKEE_USERNAME` | Dashboard login username |
| `ACKEE_PASSWORD` | Dashboard login password |
| `ACKEE_ALLOW_ORIGIN` | CORS origin — set to your website's domain. Comma-separate for multiple domains |
| `ACKEE_AUTO_ORIGIN` | Set to `true` to allow all origins (less secure) |

Start the stack:

```bash
docker compose up -d
```

## Initial Setup

1. Open the dashboard at `http://your-server-ip:3000`
2. Log in with the username and password from your environment variables
3. Click **Settings** → **Domains** → **Add Domain**
4. Enter your website's name and domain
5. Copy the generated tracking script

### Adding the Tracking Script

Add the tracking snippet to your website's `<head>`:

```html
<script async src="https://your-ackee-instance.com/tracker.js"
  data-ackee-server="https://your-ackee-instance.com"
  data-ackee-domain-id="YOUR_DOMAIN_ID">
</script>
```

The script is ~2 KB, loads asynchronously, and sets no cookies.

## Configuration

### Multiple Domains

Ackee can track multiple websites from a single instance. Add each domain in the dashboard settings. Each gets a unique domain ID and tracking snippet.

### Detailed Mode

By default, Ackee runs in "anonymous" mode — no individual visitor tracking, just aggregate metrics. Enable detailed mode for per-visitor data:

```html
<script async src="https://your-ackee-instance.com/tracker.js"
  data-ackee-server="https://your-ackee-instance.com"
  data-ackee-domain-id="YOUR_DOMAIN_ID"
  data-ackee-opts='{ "detailed": true }'>
</script>
```

Detailed mode collects screen size, language, and referrer per visit. It's still cookieless but provides more granularity.

### GraphQL API

Ackee exposes a GraphQL API for programmatic access to your analytics data:

```graphql
{
  domains {
    id
    title
    statistics {
      views {
        id
        count
      }
    }
  }
}
```

Endpoint: `https://your-ackee-instance.com/api`

Authentication: Bearer token (create permanent tokens in Settings → Tokens).

## Reverse Proxy

For production deployment behind HTTPS:

```nginx
server {
    listen 443 ssl;
    server_name analytics.example.com;

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

HTTPS is strongly recommended — the `ACKEE_ALLOW_ORIGIN` setting works best with HTTPS origins, and browsers may block the tracker on mixed-content pages.

See [Reverse Proxy Setup](/foundations/reverse-proxy-explained) for full configuration.

## Backup

Back up the MongoDB data volume:

```bash
docker exec ackee-mongo mongodump --out /tmp/backup --db ackee
docker cp ackee-mongo:/tmp/backup ./ackee-backup-$(date +%Y%m%d)
```

Or back up the entire `ackee-data` Docker volume with [Restic](/apps/restic) or [BorgBackup](/apps/borgbackup). See [Backup Strategy](/foundations/backup-strategy).

## Troubleshooting

### Tracking Script Not Sending Data

**Symptom:** Dashboard shows zero views after adding the tracking script

**Fix:** Check browser console for CORS errors. The `ACKEE_ALLOW_ORIGIN` must exactly match your website's origin (including protocol and port). Common mistakes:
- `http://` vs `https://` mismatch
- Missing `www.` prefix
- Trailing slash in the origin URL

### Dashboard Shows "Unauthorized"

**Symptom:** Login returns 401 or the dashboard is blank

**Fix:** Verify `ACKEE_USERNAME` and `ACKEE_PASSWORD` environment variables are set correctly. Restart the container after changing them:

```bash
docker compose restart ackee
```

### MongoDB Connection Failed

**Symptom:** Ackee logs show `MongoNetworkError: connect ECONNREFUSED`

**Fix:** Ensure the MongoDB container is running and on the same Docker network as Ackee:

```bash
docker compose ps
docker network ls
```

## Resource Requirements

- **RAM:** 150-300 MB (Ackee ~50 MB + MongoDB ~100-200 MB)
- **CPU:** Minimal
- **Disk:** 1-5 GB depending on traffic volume and data retention

## Verdict

Ackee is the most minimal self-hosted analytics tool worth running. It gives you the basics — page views, referrers, browsers, screen sizes — without the overhead of Matomo or Plausible. The GraphQL API is a nice touch for developers who want to pull analytics into other tools.

The limitation: Ackee lacks funnels, goals, custom events, and campaign tracking. For anything beyond "how many people visited and where did they come from," you'll outgrow Ackee quickly. Use [Plausible](/apps/plausible) or [Umami](/apps/umami) if you need goals and custom events. Use Ackee if you genuinely want the bare minimum.

## Frequently Asked Questions

### Is Ackee GDPR compliant?

Yes. Ackee is designed to be GDPR-friendly out of the box. In anonymous mode (the default), it collects no personally identifiable information, sets no cookies, and stores only aggregate metrics. You don't need a cookie consent banner when using Ackee in anonymous mode. Detailed mode collects slightly more data (screen size, language, referrer per visit) but still avoids cookies and fingerprinting.

### Can Ackee track multiple websites from one instance?

Yes. Add each website as a separate "domain" in the Ackee dashboard under Settings. Each domain gets its own unique domain ID and tracking snippet. There's no practical limit to the number of domains a single Ackee instance can track — the main constraint is MongoDB storage, which grows with traffic volume.

### How does Ackee compare to Plausible and Umami?

Ackee is the most minimal option — basic page views, referrers, browsers, and screen sizes with a GraphQL API. [Plausible](/apps/plausible) adds goals, custom events, and campaign tracking in a polished dashboard. [Umami](/apps/umami) sits between the two with custom events and a simpler setup than Plausible. Choose Ackee if you genuinely want bare-minimum analytics with an API.

### Do ad blockers block Ackee?

Some do. Ackee's tracker script can be blocked by privacy-focused ad blockers that maintain lists of known analytics domains. Self-hosting helps because your Ackee instance runs on your own domain, making it harder for blockers to identify. You can further reduce blocking by proxying the tracker script through your main website's domain.

### Can I run Ackee on a Raspberry Pi?

Yes. Ackee itself uses only ~50 MB of RAM. The bottleneck is MongoDB, which needs at least 100-200 MB. A Raspberry Pi 4 with 2 GB RAM handles Ackee comfortably for low-to-moderate traffic sites. Use the ARM64 MongoDB image (`mongo:7.0.16`) which runs natively on Pi 4/5.

### How do I set data retention or delete old analytics?

Ackee doesn't have built-in data retention policies. Data accumulates in MongoDB indefinitely. To manage storage, you can manually delete old records through MongoDB queries or set up a cron job that drops old entries. The MongoDB `TTL` index feature can automate expiration if you configure it on the relevant collections.

## Related

- [Best Self-Hosted Analytics](/best/analytics)
- [How to Self-Host Plausible](/apps/plausible)
- [How to Self-Host Umami](/apps/umami)
- [Plausible vs Umami](/compare/plausible-vs-umami)
- [Replace Google Analytics](/replace/google-analytics)
- [Docker Compose Basics](/foundations/docker-compose-basics)
- [Reverse Proxy Setup](/foundations/reverse-proxy-explained)
- [Backup Strategy](/foundations/backup-strategy)
