Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration

The daemon reads one TOML file, /etc/netscope/config.toml. It is root-owned and intended to be edited only by an administrator.

The shipped default is:

[daemon]
socket_path = "/run/netscope/control.sock"
state_path = "/var/lib/netscope/state.json"
cgroup_root = "/sys/fs/cgroup/netscope"
poll_interval_ms = 1000
refresh_interval_secs = 5
max_profiles = 32
log_level = "info"
probe_interval_ms = 2000
probe_target = "1.1.1.1:443"
probe_target6 = "[2606:4700:4700::1111]:443"

Keys

KeyDefaultMeaning
socket_path/run/netscope/control.sockUnix socket for CLI requests. Root-owned, group netscope, mode 0660.
state_path/var/lib/netscope/state.jsonPersistent profile state. Do not edit it by hand.
cgroup_root/sys/fs/cgroup/netscopeParent cgroup for profiles. It must be an absolute path inside /sys/fs/cgroup.
poll_interval_ms1000How often the late-attach scanner looks for matching processes. Bounded to 100–10000 ms.
refresh_interval_secs5How often targets are re-resolved and matching processes are attached. Bounded to 1–300.
max_profiles32Profile ceiling, 1–32. Lowering it prevents new profiles above the new limit.
log_levelinfoerror, warn, info, debug, or trace.
probe_interval_ms2000How often ordered links are probed for failover. Bounded to 500–60000 ms.
probe_target1.1.1.1:443IPv4 address:port used for link probes.
probe_target6[2606:4700:4700::1111]:443IPv6 target for link probes; only used when the profile carries IPv6 and a link has a global IPv6 source address.

Unknown keys are rejected. The file is parsed with deny_unknown_fields, so a typo such as poll_interval stops the daemon instead of being silently ignored. Check the journal after editing:

sudo systemctl restart netscoped
systemctl status netscoped
journalctl -u netscoped -n 50 --no-pager

systemctl reload is not used. Editing the file requires a restart, which also re-reads the profile state.

Changing the socket or state path

Both paths are created and owned by the daemon. If you move socket_path, update the directory’s permissions so the netscope group can reach it, and restart the daemon. If you move state_path, move the existing state file first or the daemon starts with no profiles.

The CLI accepts a hidden --socket <path> override. It exists for tests and for a daemon started with a non-default path; it is not needed in normal use.

Changing the cgroup root

cgroup_root must remain under /sys/fs/cgroup, because the nftables selector is built from the path relative to the cgroup mount. A value outside the cgroup2 hierarchy is rejected at startup. If you change the cgroup root while profiles are active, the old directory is left behind; stop the daemon, remove the old directory, and start it again.

State file

state_path holds a versioned JSON document with one entry per profile. It stores the target kind and identity — a native executable path, a Windows PE path for a --wine profile, a process name for a --process profile, or a Steam app ID — each consumer’s claim and policy, the profile’s mark, table, priority, and index, pre-open fanotify marks, and timestamps. Version 1 profiles are migrated on load: their single mode becomes the netscope-cli consumer’s policy with a persistent claim. Peer claims belong to a live control connection and are dropped on load, so a crashed consumer cannot leave a scope claimed forever. A Wine or name profile records the canonical PE paths with device and inode, so the daemon can re-stat the files and move a fanotify mark when a game updates. The daemon owns it:

  • Do not edit it while netscoped is running.
  • Back it up before an upgrade if you have profiles you cannot recreate easily.
  • A state version newer than the daemon is rejected rather than partially loaded.
  • Deleting it while the daemon is stopped removes all profile definitions. The host rules can be cleaned with sudo netscope cleanup --all before starting the daemon again.

Traffic counters and rates

Each profile’s nftables table carries six named counters: one pair for outbound packets that reach the profile, one pair for inbound packets, and counters for routed and dropped traffic. The daemon samples them once per second with a single nft -j list ruleset call and keeps the totals and smoothed rates in memory; status and list only read that cache.

  • Totals are a counter window that starts at since_unix, the daemon’s start time; every profile reports the same value. A daemon restart starts a new window, and the first sample after it adopts the kernel counters as a baseline, so traffic written before the restart is not reported as new.
  • Loopback is accepted before the counter selectors in both directions: outbound 127.0.0.0/8 and ::1/128 destinations, inbound the same source ranges. Local traffic therefore never inflates tx_bytes, rx_bytes, or the TRAFFIC rates.
  • Recreating a table resets its kernel counters. The daemon treats the new value as the next delta, so reported totals never move backwards; rates can dip for a sample.
  • Disabling a profile removes its table, so stats becomes null; enabling it installs a fresh table that counts from zero while the daemon’s totals keep their previous value plus the new traffic.
  • Nothing is persisted; the totals and rates live in memory for the daemon’s lifetime.

Limits

  • At most 32 profiles, regardless of max_profiles. Lowering max_profiles does not delete existing profiles, but adding beyond the limit fails.
  • Profile IDs are 1–32 characters: [a-z0-9][a-z0-9-]*.
  • Marks, tables, and rule priorities are allocated from fixed ranges. Exhausting the 32 indexes fails the add. A route table used by an active profile is refused; a table left by a removed profile is cleaned up on the next daemon reconcile.
  • One shared profile has one route policy and any number of filter policies, one per consumer. Policies are replaced with netscope policy; the target itself is not edited in place.

Logging

Runtime logs go to the journal:

journalctl -u netscoped -f
netscope logs -n 100

netscope logs is a bounded view (default 50 lines, -n to change it). It does not follow. Raw daemon logs may include profile paths and interface names but never packet contents.

Example: quieter polling

For a machine with many processes, reduce wakeups by polling less often. Pre-exec attachment is unaffected; only late attachment gets slower.

[daemon]
poll_interval_ms = 2000
refresh_interval_secs = 10
log_level = "warn"

Restart after the change and confirm with sudo netscope doctor.