---
title: "Run HitKeep as a Single Linux Binary | HitKeep"
description: "Run HitKeep as single-binary self-hosted analytics on Linux bare metal, VMs, Raspberry Pi, or restricted networks."
canonical: "https://hitkeep.com/guides/installation/binary/"
---

# Run HitKeep as a Single Linux Binary

HitKeep’s binary install is the smallest self-hosted path: one Linux executable, embedded DuckDB, embedded NSQ, and no external database, cache, or queue service. Use it when you want web analytics on a low-resource VPS, VM, Raspberry Pi, bare-metal server, or restricted network where Docker is not the right fit.

HitKeep publishes raw release binaries for Linux servers only: `linux/amd64` and `linux/arm64`. Download the matching file, make it executable, and run it.

For citable binary size, memory use, storage boundaries, export formats, and non-goals, use [Facts and Limits](https://hitkeep.com/reference/facts-and-limits/). Current Linux release binaries are about 100 MB.

Docker Compose is easier for first installs

If you want packaged networking and persistent volumes instead of managing a systemd unit yourself, use the [Docker Compose setup](https://hitkeep.com/guides/installation/docker-compose/). If you do not want to manage servers, upgrades, SMTP, or backups at all, use [HitKeep Cloud](https://hitkeep.com/pricing/).

Linux compatibility

The published Linux binaries are built on Ubuntu 22.04 and require `glibc 2.35+`. They are tested on:

- Ubuntu 22.04 or later
- Debian 12 or later
- Amazon Linux 2023
- other glibc-based distributions with `glibc 2.35+`

If your server runs an older glibc (e.g., Ubuntu 20.04, Debian 11, Amazon Linux 2), use the [Docker Compose setup](https://hitkeep.com/guides/installation/docker-compose/) instead.

## Supported Build Targets

| Artifact | Target |
| --- | --- |
| hitkeep-linux-amd64 | 64-bit Linux servers and VMs |
| hitkeep-linux-arm64 | ARM64 Linux servers, Raspberry Pi, AWS Graviton, Hetzner CAX |
| Docker image | linux/amd64 and linux/arm64 |

Raw binaries are intended for Linux hosts with a modern glibc. Use Docker Compose when you need the container image or when the host distribution is older than the binary baseline.

This makes the binary installation the right choice for:

- Bare metal servers and VMs
- Restricted-network environments
- Raspberry Pi and ARM servers (AWS Graviton, Hetzner CAX)
- Organizations that require the smallest possible attack surface

## Download

Download the latest release for your architecture from [GitHub Releases](https://github.com/pascalebeier/hitkeep/releases):

```
# Linux AMD64 (most common VPS/server)
curl -L https://github.com/pascalebeier/hitkeep/releases/latest/download/hitkeep-linux-amd64 \
  -o hitkeep && chmod +x hitkeep && sudo mv hitkeep /usr/local/bin/hitkeep

# Linux ARM64 (Raspberry Pi, AWS Graviton, Hetzner CAX)
curl -L https://github.com/pascalebeier/hitkeep/releases/latest/download/hitkeep-linux-arm64 \
  -o hitkeep && chmod +x hitkeep && sudo mv hitkeep /usr/local/bin/hitkeep
```

For restricted networks: download the binary and `SHA256SUMS` from the GitHub release page on an internet-connected machine, verify the checksum, then transfer the verified binary to the target server.

## Running with Systemd

For production Linux servers, use `systemd` to ensure HitKeep starts on boot and restarts on failure.

Keep secrets out of process listings

Never pass `HITKEEP_JWT_SECRET` or SMTP passwords as command-line flags — they are visible to all users via `ps aux`. Use environment variables or a drop-in environment file instead.

Every flag has a 1:1 `HITKEEP_*` environment variable equivalent (`--public-url` ↔ `HITKEEP_PUBLIC_URL`), so you can configure everything through the environment if you prefer — the unit below mixes both only to keep secrets out of the visible command line. The [Configuration Reference](https://hitkeep.com/reference/configuration/) lists both forms for every option.

**1. Create a dedicated service user and data directory:**

```
sudo useradd -r -s /bin/false hitkeep
sudo mkdir -p /var/lib/hitkeep/data /var/lib/hitkeep/archive
sudo chown -R hitkeep:hitkeep /var/lib/hitkeep
```

**2. Create `/etc/systemd/system/hitkeep.service`:**

```
[Unit]
Description=HitKeep Analytics
After=network.target

[Service]
Type=simple
User=hitkeep
Group=hitkeep
WorkingDirectory=/var/lib/hitkeep

# Sensitive values via environment (not visible in ps aux).
# Generate the secret with: openssl rand -hex 32
Environment="HITKEEP_JWT_SECRET=change-this-to-a-long-random-string"
Environment="HITKEEP_MAIL_PASSWORD=your-smtp-password"

# General configuration via flags
ExecStart=/usr/local/bin/hitkeep \
  --public-url=https://analytics.example.com \
  --db-path=/var/lib/hitkeep/data/hitkeep.db \
  --data-path=/var/lib/hitkeep/data \
  --archive-path=/var/lib/hitkeep/archive \
  --http-addr=:8080

Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
```

Or use a drop-in environment file for secrets (more secure — keeps secrets out of the unit file):

```
sudo mkdir -p /etc/systemd/system/hitkeep.service.d
sudo tee /etc/systemd/system/hitkeep.service.d/secrets.conf << 'EOF'
[Service]
Environment="HITKEEP_JWT_SECRET=your-secret-here"
EOF
sudo chmod 600 /etc/systemd/system/hitkeep.service.d/secrets.conf
```

**3. Enable and start:**

```
sudo systemctl daemon-reload
sudo systemctl enable --now hitkeep
sudo systemctl status hitkeep
```

## Mount HitKeep under a subdirectory

Most installs should use a dedicated analytics hostname such as `https://analytics.example.com`. If you need to publish HitKeep below another site, set `HITKEEP_PUBLIC_URL` to the full external path:

```
Environment="HITKEEP_PUBLIC_URL=https://www.example.net/hitkeep/"
```

or:

```
hitkeep --public-url=https://www.example.net/hitkeep/
```

The reverse proxy must forward the same path prefix to HitKeep without rewriting it away:

```
www.example.net {
  handle /hitkeep* {
    reverse_proxy 127.0.0.1:8080
  }
}
```

When the public URL contains `/hitkeep/`, the dashboard injects `<base href="/hitkeep/" />`, API calls stay under `/hitkeep/api/...`, and the tracker snippet can be installed as:

```
<script async src="https://www.example.net/hitkeep/hk.js"></script>
```

If Web Vitals are enabled, `hk.js` loads `https://www.example.net/hitkeep/hk-vitals.js` and sends samples to `/hitkeep/ingest/web-vitals`. Pageviews and automatic events follow the same rule for `/hitkeep/ingest` and `/hitkeep/ingest/event`.

In path-prefix mode, HitKeep does not expose root `/api/...`, `/hk.js`, or dashboard fallback routes. Local `/healthz` and `/readyz` remain available for process, container, and Kubernetes checks.

## Troubleshooting

### Startup fails with failed to get final advertise address

If HitKeep exits immediately with:

```
failed to get final advertise address: no private IP address found, and explicit IP not provided
```

the embedded cluster layer could not determine which IP address to advertise for gossip traffic. This usually happens in local or development environments where `0.0.0.0:7946` is used as the default bind address but the host does not have a discoverable private network address.

For a single-node local run, bind the cluster address explicitly to loopback:

```
./hitkeep --bind-addr=127.0.0.1:7946
```

Or with an environment variable:

```
HITKEEP_BIND_ADDR=127.0.0.1:7946 ./hitkeep
```

For multi-node deployments, set `--bind-addr` or `HITKEEP_BIND_ADDR` to a real private address reachable by the other nodes instead of loopback.

## Backup

Prefer HitKeep’s built-in checkpointed backup worker for a running service. Add these entries to the unit’s `[Service]` section or a systemd drop-in, then restart the service:

```
Environment="HITKEEP_BACKUP_PATH=/var/lib/hitkeep/backups"
Environment="HITKEEP_BACKUP_INTERVAL=60"
Environment="HITKEEP_BACKUP_RETENTION=24"
```

For a raw filesystem copy, stop HitKeep first so the database and WAL cannot change independently:

```
sudo systemctl stop hitkeep
rsync -a /var/lib/hitkeep/data/ /backup/hitkeep-$(date +%Y%m%d)/
rsync -a /var/lib/hitkeep/archive/ /backup/hitkeep-archive-$(date +%Y%m%d)/
sudo systemctl start hitkeep
```

The copy must include the configured `HITKEEP_DB_PATH`, the full `HITKEEP_DATA_PATH` tree with tenant databases under `tenants/*/hitkeep.db`, and any archive path you need to retain. See [Backups and Restore](https://hitkeep.com/guides/data/backups-and-restore/) for restore commands and S3 options.

## Related

- [Trusted Proxies](https://hitkeep.com/guides/installation/trusted-proxies/) — required if running behind a reverse proxy
- [Configuration Reference](https://hitkeep.com/reference/configuration/)
- [Facts and Limits](https://hitkeep.com/reference/facts-and-limits/)
- [Data Retention](https://hitkeep.com/guides/data/retention/)

Don’t want to manage systemd services, upgrades, and backups yourself? [HitKeep Cloud →](https://cloud.hitkeep.eu/signup?plan=free&billing=monthly&utm_source=hitkeep_docs&utm_medium=referral&utm_campaign=cloud_signup&utm_content=docs_inline) runs the binary in your chosen region (EU Frankfurt or US Virginia) with zero-downtime upgrades and automated backups.

[Previous Installation overview](https://hitkeep.com/guides/installation/)[Next Docker Compose](https://hitkeep.com/guides/installation/docker-compose/)
