Skip to content

Install on Debian 13

Nyxtrace ships as one native bundle: a checksummed archive containing the ndr binary, the database migrations, the detection models, the pinned Vector runtime, the appliance runtime assets and the prebuilt web release. The installer places files and writes configuration. It does not start anything on its own.

The order below is the order the installer enforces. It fails closed rather than guessing, at every step.

A fresh Debian 13 install, systemd-networkd active, and the capture NIC (if you have one) not managed by NetworkManager. See requirements.

If the appliance is a VM replacing something else, keep the old disk and the old VM configuration until the acceptance checks below have passed. A rollback that depends on a backup you have not restored yet is not a rollback.

Copy four things into one directory that is owned by root and is not writable by group or others:

File What it is
nyxtrace-ndr_linux_amd64.tar.gz The bundle
install-appliance The bootstrap installer
SHA256SUMS Checksums for both of the above
your site YAML Your authoritative tenant and VLAN inventory
Terminal window
export NDR_ARTIFACT_DIR=/root/nyxtrace-release
export NDR_SITE_CONFIG_PATH=/root/nyxtrace-release/sites.yaml

The installer copies the whole artifact set into a new root-private directory and works only from that copy, so a later change to the staging directory cannot affect a running install. It verifies SHA256SUMS against both the archive and itself before touching the host, and the archive carries a recursive inner SHA256SUMS for its own members.

The bundled sites.yaml is an empty template on purpose. You supply the real one. Every tenant needs at least one strict, non-overlapping CIDR and an explicit home_coordinates value — the installer rejects a tenant that omits either.

tenants:
example:
site_id: example-home
display_name: Example Home
home_coordinates:
latitude: 51.7
longitude: 8.7
vlans:
- vlan_id: 104
name: IOT
cidrs: [192.0.2.0/24]
- vlan_id: 108
name: SERVER
cidrs: [198.51.100.0/24]

Do not derive the home coordinates from telemetry. They are a deployment fact, and the globe draws its home point from them or from nothing.

install-appliance prints the exact package and configuration actions it would take and changes nothing:

Terminal window
/root/nyxtrace-release/install-appliance

Read that output. Then apply:

Terminal window
/root/nyxtrace-release/install-appliance --apply

Apply requires Debian 13, the configured passive NIC, the verified artifacts, and signed repositories carrying the pinned ClickHouse and Grafana versions. It temporarily suppresses package auto-start, and it does not enable or start any Nyxtrace service.

On a first apply it generates six separate mode-0600 environment files — for Vector, the NetFlow gate, the backend, ClickHouse, Grafana and the web layer — with freshly generated secrets. Before any host mutation it insists on finding either none of them or all six: a partial set, a symlink, non-root ownership or any mode other than 0600 fails the apply. A repeat apply preserves the existing secret material byte for byte.

The capture NIC is renamed by MAC through a systemd.link unit, and that rename only takes effect on boot. Reboot now.

Do not restart a network manager as a shortcut. That is how you lose management access to a machine you are in the middle of installing.

After the reboot, start the offload unit and check its interface:

Terminal window
systemctl start ndr-capture-offloads.service
ip -d link show <capture-interface>

It must be up, at the configured MTU, with no IPv4 and no IPv6 address, and with GRO, LRO, GSO, TSO, TX and RX offloads disabled. Zeek reassembling hardware-coalesced segments is how capture statistics start lying to you.

Edit the generated web environment file with the real HTTPS URL of the interface and your OIDC settings. Secrets live only in those mode-0600 files under /etc/ndr; nothing goes into a YAML file. See first login.

Start ClickHouse explicitly, then create its database and grants:

Terminal window
systemctl start clickhouse-server
ndr-provision-clickhouse

ndr-provision-clickhouse never puts a password in argv. The account it creates is restricted: it can write the Nyxtrace schema and nothing else, and the Grafana account it creates can neither write nor run foreign DDL.

Migrations are additive and repeatable. The service unit runs ndr migrate as ExecStartPre before every start, so an upgrade applies its own schema changes; you do not run migrations by hand on a healthy system.

Terminal window
ndr validate-config
ndr-health

ndr validate-config rejects an incomplete configuration the way startup would: missing ClickHouse settings, a missing state path, an absent service secret, a missing sensor registry, a site file with an empty or overlapping tenant VLAN list. Production startup terminates on any of those rather than running degraded.

ndr-health exits non-zero unless the API is live and ready, ClickHouse is up with the full schema, Vector’s runtime identity and service account are correct, Grafana is up, every configured listener is actually listening, Zeek is running and the timers exist.

Only now:

Terminal window
systemctl enable --now ndr-api ndr-web vector zeek grafana-server
systemctl enable --now ndr-analyze@<tenant>.timer ndr-jobs.timer

Two timers do the recurring work:

Unit Cadence Job
ndr-analyze@<tenant> hourly, oneshot Runs the detection models over new evidence
ndr-jobs every minute, oneshot Drains queued analyst work and exits

Both are one-shot by design: a run that fails does not publish a checkpoint, and the next timer simply picks the work up again. An abandoned lease expires and returns to the queue rather than blocking the queue forever.

At this point the appliance is running and empty. Connect the data sources — firewall feeds first, then a mirror if you have one. Each source gets its own registry entry, its own token and its own trust class.

A successful install is not an accepted service. Before you rely on it, observe all of these separately:

  • An isolated full restore, with ClickHouse raw evidence and the state ledger compared after the restore. A process-only check does not count.
  • 24 hours of CPU, load, packet loss, disk growth and source health.
  • A controlled fault: stop a source or the database, confirm the buffers hold, confirm the catch-up, confirm recovery.
  • One real alert and one real recovery notification, actually delivered.
  • Reboot and upgrade persistence.
  • The learning phase, which is two to four weeks and cannot be shortened with fixtures.

The installer keeps the previous release directory, so the fast way back is to boot the preserved disk (or restore the pre-install VM configuration) and leave the data created afterwards archived for investigation rather than merging it into the old system.

Removing Nyxtrace itself touches only what Nyxtrace owns: its units, its configuration under /etc/ndr, its own firewall table, and its own capture resources. It never reloads your management networking and never removes firewall or DNS objects you created by hand.