Skip to content
HitKeep
Select language
Select theme
GitHub
Start free in Cloud

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. Current Linux release binaries are about 100 MB.

ArtifactTarget
hitkeep-linux-amd6464-bit Linux servers and VMs
hitkeep-linux-arm64ARM64 Linux servers, Raspberry Pi, AWS Graviton, Hetzner CAX
Docker imagelinux/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 the latest release for your architecture from GitHub Releases:

Terminal window
# 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.

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

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 lists both forms for every option.

You can also keep settings in an explicit YAML file. After creating the service user below, create the file as that user with sudo -u hitkeep hitkeep config init --output /var/lib/hitkeep/hitkeep.yaml, check it with sudo -u hitkeep hitkeep config validate --config /var/lib/hitkeep/hitkeep.yaml, and start with ExecStart=/usr/local/bin/hitkeep --config /var/lib/hitkeep/hitkeep.yaml; --config must come first. The generated file is readable only by its owner. Flags and non-empty environment variables still override file values.

1. Create a dedicated service user and data directory:

Terminal window
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):

Terminal window
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:

Terminal window
sudo systemctl daemon-reload
sudo systemctl enable --now hitkeep
sudo systemctl status hitkeep

Confirm the installed release, service state, and database readiness:

Terminal window
hitkeep --version
sudo systemctl --no-pager status hitkeep
curl --fail http://127.0.0.1:8080/healthz
curl --fail http://127.0.0.1:8080/readyz

/healthz confirms the process is alive. /readyz confirms the shared database and every open tenant database are ready.

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:

Terminal window
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.

Startup fails with failed to get final advertise address

Section titled “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:

Terminal window
./hitkeep --bind-addr=127.0.0.1:7946

Or with an environment variable:

Terminal window
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.

Read the latest release notes and take a complete backup. Download the new binary for the same architecture using the Quick start command, then replace the executable while the service is stopped:

Terminal window
sudo systemctl stop hitkeep
sudo install -m 0755 ./hitkeep /usr/local/bin/hitkeep
sudo systemctl start hitkeep
curl --fail http://127.0.0.1:8080/readyz
hitkeep --version

Keep the previous binary and pre-upgrade backup until the readiness check and a tracking request both succeed. Review release notes before downgrading; releases with data migrations may not support running an older binary against upgraded data. If you moved settings into a configuration file, restore them as environment variables or flags before running a binary without configuration-file support.

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:

Terminal window
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 for restore commands and S3 options.

Don’t want to manage systemd services, upgrades, and backups yourself? Compare HitKeep Cloud for managed EU (Frankfurt) or US (Virginia) hosting with zero-downtime upgrades and automated backups.