Operations · 01 · Linux Linux only

Troubleshooting (Linux)

Linux-specific diagnoses and fixes — systemd-user bus errors, port conflicts, cert trust failures, missing captures. Public beta.

Linux (beta) · systemd · Python 3.11+ Reading time 2 min Updated May 11, 2026

Always run halton-meter doctor first. It prints every diagnostic signal — cert state, certifi marker, ports, systemd units, sentinels, daemon PID — with a concrete next-action per failure.

halton-meter doctor

Failed to connect to bus: No medium found

Symptom: any systemctl --user command on a fresh SSH session prints Failed to connect to bus: No medium found.

Cause: the SSH session pre-dates loginctl enable-linger, or you’re in a non-login shell. XDG_RUNTIME_DIR isn’t auto-set, so the user bus is unreachable.

Fix:

~ — restore the user bus
$ export XDG_RUNTIME_DIR=/run/user/$(id -u)

If /run/user/$(id -u) doesn’t exist as a directory, run sudo loginctl enable-linger "$USER" and open a fresh login shell.


Daemon won’t start / unit fails repeatedly

systemctl --user status halton-meter.service --no-pager
journalctl --user -u halton-meter.service --since "30 minutes ago" --no-pager

The unit has Restart=always RestartSec=1. Combined with systemd’s default StartLimitBurst (5 starts in 10s), a crash loop will eventually land the unit in failed (start-limit-hit) state. Last-resort reset:

~ — clear start-limit + re-init
$ systemctl --user reset-failed halton-meter.service halton-meter-edge.service
$ systemctl --user daemon-reload
$ halton-meter init --apps --clean

reset-failed clears the burst counter; --clean forces a destructive rollback if the post-install self-test fails.


Port conflicts (8081 / 8090 / 8765 already bound)

ss -tlnp | grep -E "8081|8090|8765"
cat ~/.halton-meter/effective-ports.json

If 8081 is bound by something other than our edge, halton-meter init --apps --clean will renegotiate. Or pin specific values in ~/.halton-meter/config.toml:

~/.halton-meter/config.toml — pin ports
[daemon]
edge_port = 8181
internal_port = 8190
api_port = 8865

Restart the units after editing:

systemctl --user restart halton-meter.service halton-meter-edge.service

Cert trust failures

Symptom: Python or Node tool fails with SSL: CERTIFICATE_VERIFY_FAILED, unable to get local issuer certificate, or a similar TLS error after init.

First check: is the certifi bundle of the Halton Meter Python actually patched?

~ — verify certifi patch
$ grep -c 'halton-meter mitmproxy CA cert appended' \
  "$(halton-meter run -- python3 -c 'import certifi; print(certifi.where())')"
1

Output should be 1. If 0, re-run the cert step:

halton-meter setup --force

If a different Python (your project venv) needs to see the cert, point its SSL_CERT_FILE / REQUESTS_CA_BUNDLE at the patched pipx-venv bundle. Halton Meter does not patch every Python on the system — only the one it’s installed under.

Browser shows certificate error

Linux apps-mode does not install the CA in the system trust store, so browser traffic is not intercepted. If your browser shows a cert error after init, the most likely cause is that you copied the CA into the system store manually. Either remove it:

~ — undo manual system-store trust
$ sudo rm /usr/local/share/ca-certificates/halton-meter.crt
$ sudo update-ca-certificates --fresh

…or, if you intentionally want browser interception, additionally import the cert into Firefox/Chromium’s NSS database. That’s an unsupported workaround in v0.1.24 — you take responsibility for the trust expansion.


No captures in halton-meter report

In order:

  1. Daemon healthy? halton-meter status shows daemon row green.
  2. Env vars set in the shell that ran the LLM tool?
    echo $HTTPS_PROXY    # expect: http://127.0.0.1:8081
    echo $SSL_CERT_FILE  # expect: a path ending in /certifi/cacert.pem
    
    If empty, your rc edits don’t apply to this shell. Open a new terminal, or source ~/.bashrc.
  3. Cert trust matches the language runtime? Python needs SSL_CERT_FILE / REQUESTS_CA_BUNDLE. Node binaries (Claude Code, Gemini CLI) need NODE_EXTRA_CA_CERTS. curl needs CURL_CA_BUNDLE for the system curl that doesn’t read certifi.
  4. Provider hostname is on the supported list? Halton Meter has adapters for api.anthropic.com, api.openai.com, generativelanguage.googleapis.com, cloudcode-pa.googleapis.com, api.x.ai, and chatgpt.com. Anything else passes through without capture. See Anthropic and adjacent.
  5. Install mode is apps? halton-meter status shows the install-mode row. Linux only supports apps in v0.1.24.

Daemon startup is slow on small VMs

On VMs with <1 GB RAM (e.g. AWS Lightsail nano, GCP e2-micro), Python

  • mitmproxy import can stretch from the normal 15-20 s to 60+ seconds after boot. During that window the edge accepts the request and falls through to direct pass-through — the cardinal rule is preserved (your call goes through) but the capture is missed. Wait for /health before re-testing:
~ — wait for daemon ready
$ until curl -sS -m 1 http://127.0.0.1:8765/health 2>/dev/null | grep -q ok; do sleep 2; done
$ echo "daemon ready"
daemon ready

Recommended floor for production use: 1 GB RAM + swap.


halton-meter status “Watchdog” row says “not installed”

Intentional. The watchdog is a macOS-only networksetup poller that detects network changes. There’s no Linux counterpart — systemd-networkd and NetworkManager raise their own signals that the daemon doesn’t need to poll. The row text doesn’t yet say so on Linux; cosmetic-only fix queued.

Treat the Daemon and Edge rows as the load-bearing ones. If both are green, you’re healthy.


SQLite locked

The proxy hot path writes; the FastAPI app reads. WAL mode is on, so concurrent reads + a single writer are normal. If you see a hard database is locked error, something else opened the file with a long-running transaction:

lsof ~/.halton-meter/db.sqlite

halton-meter bodies purge --vacuum blocks the file while VACUUM runs; do that during quiet windows.


halton-meter rescue is missing

rescue is macOS-only in v0.1.24 (uses launchctl bootout semantics). Manual equivalent on Linux:

~ — Linux rescue equivalent
$ systemctl --user reset-failed halton-meter.service halton-meter-edge.service
$ systemctl --user daemon-reload
$ halton-meter init --apps --clean

Reading logs

~ — tail logs
$ journalctl --user -u halton-meter.service -f
$ journalctl --user -u halton-meter-edge.service -f
$ tail -F ~/.halton-meter/daemon.err.log
$ tail -F ~/.halton-meter/edge.err.log

Event names are dotted lowercase: intercept.start, daemon.startup.ready, daemon.exit, edge.sidecar_regen_requested, daemon.heartbeat.

More detail in Logs.


Still stuck

Email operator@haltonlabs.com with [linux-beta] in the subject and include:

  • Distro + kernel: uname -a; cat /etc/os-release | head -3
  • Halton Meter version: halton-meter --version
  • halton-meter doctor output (the bottom table)
  • Relevant log excerpt: journalctl --user -u halton-meter.service --since "30 minutes ago" --no-pager
  • What command produced the symptom, and what you expected vs. what happened.

Graduating Linux from “beta” to “primary supported” with broader distro coverage is the explicit goal for v0.2. Your reports drive the test matrix.