Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configs/aarch64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ BR2_PACKAGE_CURIOS_HTTPD=y
BR2_PACKAGE_CURIOS_NFTABLES=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
BR2_PACKAGE_SUPPORT_ENCRYPT=y
BR2_PACKAGE_FACTORY=y
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
BR2_PACKAGE_FINIT_PLUGIN_HOOK_SCRIPTS=y
Expand Down
1 change: 1 addition & 0 deletions configs/aarch64_minimal_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ BR2_PACKAGE_NETD=y
BR2_PACKAGE_CONFD_TEST_MODE=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
BR2_PACKAGE_SUPPORT=y
BR2_PACKAGE_FACTORY=y
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
BR2_PACKAGE_FINIT_PLUGIN_HOOK_SCRIPTS=y
Expand Down
1 change: 1 addition & 0 deletions configs/arm_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ BR2_PACKAGE_NETD=y
BR2_PACKAGE_CONFD_TEST_MODE=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
BR2_PACKAGE_SUPPORT_ENCRYPT=y
BR2_PACKAGE_FACTORY=y
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
BR2_PACKAGE_FINIT_PLUGIN_HOOK_SCRIPTS=y
Expand Down
1 change: 1 addition & 0 deletions configs/arm_minimal_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ BR2_PACKAGE_NETD=y
BR2_PACKAGE_CONFD_TEST_MODE=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
BR2_PACKAGE_SUPPORT=y
BR2_PACKAGE_FACTORY=y
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
BR2_PACKAGE_FINIT_PLUGIN_HOOK_SCRIPTS=y
Expand Down
1 change: 1 addition & 0 deletions configs/riscv64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ BR2_PACKAGE_CONFD=y
BR2_PACKAGE_NETD=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
BR2_PACKAGE_SUPPORT_ENCRYPT=y
BR2_PACKAGE_FACTORY=y
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
BR2_PACKAGE_FINIT_PLUGIN_HOOK_SCRIPTS=y
Expand Down
1 change: 1 addition & 0 deletions configs/x86_64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ BR2_PACKAGE_CURIOS_HTTPD=y
BR2_PACKAGE_CURIOS_NFTABLES=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
BR2_PACKAGE_SUPPORT_ENCRYPT=y
BR2_PACKAGE_FACTORY=y
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
BR2_PACKAGE_FINIT_PLUGIN_HOOK_SCRIPTS=y
Expand Down
1 change: 1 addition & 0 deletions configs/x86_64_minimal_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ BR2_PACKAGE_NETD=y
BR2_PACKAGE_CONFD_TEST_MODE=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
BR2_PACKAGE_SUPPORT=y
BR2_PACKAGE_FACTORY=y
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
BR2_PACKAGE_FINIT_PLUGIN_HOOK_SCRIPTS=y
Expand Down
9 changes: 9 additions & 0 deletions doc/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ All notable changes to the project are documented in this file.
- Document the release and maintenance policy: which versions receive
updates, what may go into a patch release, and the levels of long-term
maintenance available, see [Releases & Support][relsup]
- `support collect` now redacts private keys, password hashes and other
secrets from the configuration files in the archive, use `--no-redact`
to keep them. The environment dump is no longer collected
- Add `copy -r` to export a datastore without its secrets, every node the
YANG models tag `nacm:default-deny-all` and user passwords are dropped

### Added

Expand All @@ -28,6 +33,10 @@ All notable changes to the project are documented in this file.
and keys are prompted for, `binary` settings open in the text editor, and
`string` settings are edited on a line prefilled with the current value.
The `text-editor` and `change` commands are removed
- Add `infix-system:support-collect` RPC, for collecting support data over
NETCONF or RESTCONF. The archive is returned base64 encoded, up to 16 MiB,
larger ones are left on the device for out-of-band fetching. Access is
denied by default, only the `admin` group may call it
- Add CLI `edit` and `clear` verbs to admin-exec: `edit datetime` and
`edit boot-order` prompt with the current value, `clear dhcp-server
statistics` replaces `dhcp-server clear-statistics`. `set datetime` now
Expand Down
115 changes: 113 additions & 2 deletions doc/support.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,104 @@ The collection process may take up to a minute depending on system load
and the amount of logging data. Progress messages are shown during the
collection process.

Each command is run with a timeout, so a wedged driver or daemon cannot
stall the collection; the archive then holds a note in place of that
command's output. If the collection itself fails, the log is kept next
to the working directory, for instance:

```
/var/lib/support/support-host-2026-09-11T13:05:42+02:00.log
```

It shows what was collected and what failed. Use `support clean` to
remove old collection directories and logs.

## Collecting to a File

With `-o` the archive is written to a file instead of stdout, and the
path is printed:

```bash
admin@host:~$ sudo support collect -o /var/lib/support
...
/var/lib/support/support-host-2026-09-11T13:05:42+02:00.tar.gz
```

Given a directory, the file gets the canonical name shown above. Given a
file name, that name is used. Either way the file is created with mode
0600, the archive still holds the full configuration and all logs.

## Collecting over NETCONF or RESTCONF

Clients that only speak the management API can call the
`infix-system:support-collect` RPC, which runs the same collection and
returns the archive base64 encoded:

```bash
$ curl -ku admin:admin -X POST \
-H "Content-Type: application/yang-data+json" \
https://host/restconf/operations/infix-system:support-collect \
| jq -r '."infix-system:output".data' | base64 -d > support-data.tar.gz
```

Add a password to get it encrypted, then decrypt it with the same
password after passing it on:

```bash
$ curl -ku admin:admin -X POST \
-H "Content-Type: application/yang-data+json" \
-d '{"infix-system:input":{"password":"mypassword"}}' \
https://host/restconf/operations/infix-system:support-collect \
| jq -r '."infix-system:output".data' | base64 -d > support-data.tar.gz.gpg
```

A few things to know about this path:

- The RPC is denied by default (`nacm:default-deny-all`), so only groups
with an explicit NACM permit rule can call it. In the factory
configuration that is the `admin` group.
- Collection runs in `/tmp`, and the archive is removed once it has been
returned, so nothing is left behind on the device.
- An archive above 16 MiB is not returned inline. The reply then holds
`size` and `filename` instead, and the file stays in a directory of its
own under `/tmp` for you to fetch, then remove along with the directory.
- Over NETCONF the archive arrives as one base64 text node, and libxml2
rejects text nodes over 10 MB unless the parser is opened with
`XML_PARSE_HUGE`. Clients built on it, lxml and ncclient among them,
need that option (`huge_tree=True`) to receive an archive above about
7.5 MB. RESTCONF returns JSON and has no such limit.
- The system log is tailed for 5 seconds, rather than the 30 the command
line defaults to, so that the whole collection finishes inside the
client's RPC timeout (`CONFD_TIMEOUT` in `/etc/default/confd`, 60
seconds by default).
- Pass `password` to get the archive GPG encrypted, for handing on to
someone else afterwards. The management session is already encrypted,
so this is not needed to protect the transfer itself. The password
must be a single line. It is handed to gpg on a private file
descriptor and never appears in the process list. Devices built
without the `BR2_PACKAGE_SUPPORT_ENCRYPT` option have no gpg and reject
the request.
- The configuration files in the archive are always redacted, see below.
- `confd` is busy for the duration of the collection, like it is during a
software upgrade, so a configuration change made at the same time has to
wait for the collection to finish.
- If the client gives up before the collection finishes, the archive is
discarded along with it, so call again rather than looking for a
leftover file. On a device with many ports, where collection can
outlast the 60 second timeout, collect over SSH with `-o` instead.
- A collection that fails leaves its log in the work directory, `/tmp`
for this path, which is RAM and therefore cleared on reboot. Elsewhere
use `support clean` to remove old logs and directories.

From a shell on the device, use the `support` command rather than the
RPC. A base64 blob on your terminal is of no use to anyone.

## Encrypted Collection

For secure transmission of support data, the archive can be encrypted
with GPG using a password:
with GPG using a password. This needs gpg on the device, which the
`BR2_PACKAGE_SUPPORT_ENCRYPT` build option adds. It is enabled in all
but the minimal defconfigs.

```bash
admin@host:~$ sudo support collect -p mypassword > support-data.tar.gz.gpg
Expand Down Expand Up @@ -89,10 +183,27 @@ $ gpg -d support-data.tar.gz.gpg | tar xz
The support archive includes:

- System identification (hostname, uptime, kernel version)
- Running and operational configuration (sysrepo datastores)
- Running, operational and startup configuration, with secrets redacted
- System logs (`/var/log` directory and live tail of messages log)
- Network configuration and state (interfaces, routes, neighbors, bridges)
- FRRouting information (OSPF, BFD status)
- Container information (podman containers and their configuration)
- System resource usage (CPU, memory, disk, processes)
- Hardware information (PCI, USB devices, network interfaces)

## Secrets in the Configuration

The configuration holds private keys for SSH, TLS and WireGuard, user
password hashes and RADIUS secrets. None of them help anyone
troubleshoot, so `support collect` exports the configuration with
`copy -r`, which drops every node the YANG models tag
`nacm:default-deny-all`, plus user passwords, before writing the
file. New models that tag their secrets are covered without changes
here. The rest of the configuration is left intact.

Pass `--no-redact` to keep them, for instance when the archive is for
your own use and stays on your workstation. The RPC always redacts.

The archive still contains every log on the device, which may hold
usernames, addresses and other details of your network. Treat it as
confidential and encrypt it before it leaves your control.
1 change: 1 addition & 0 deletions package/Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/curios-httpd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/curios-nftables/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/gencert/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/statd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/support/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/factory/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/faux/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in"
Expand Down
1 change: 1 addition & 0 deletions package/confd/Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ config BR2_PACKAGE_CONFD
select BR2_PACKAGE_NETOPEER2
select BR2_PACKAGE_SYSREPO
select BR2_PACKAGE_LIBSRX
select BR2_PACKAGE_SUPPORT
help
A plugin to sysrepo that provides the core YANG models used to
manage an Infix based system. Configuration can be done using
Expand Down
22 changes: 22 additions & 0 deletions package/support/Config.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
config BR2_PACKAGE_SUPPORT
bool "support"
help
The support tool collects logs, configuration and system state
into an archive for troubleshooting. It is called from the CLI,
the WebUI and the infix-system:support-collect RPC.

https://github.com/kernelkit/infix

if BR2_PACKAGE_SUPPORT

config BR2_PACKAGE_SUPPORT_ENCRYPT
bool "Encrypted archives"
depends on BR2_PACKAGE_GNUPG2_DEPENDS
depends on !BR2_PACKAGE_GNUPG
select BR2_PACKAGE_GNUPG2
help
Allow a support archive to be encrypted with a password, using
GnuPG, before it leaves the device. Adds gpg and its libraries
to the image.

endif
18 changes: 18 additions & 0 deletions package/support/support.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
################################################################################
#
# support
#
################################################################################

SUPPORT_VERSION = 1.0
SUPPORT_SITE_METHOD = local
SUPPORT_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/support
SUPPORT_LICENSE = ISC
SUPPORT_LICENSE_FILES = LICENSE
SUPPORT_REDISTRIBUTE = NO

define SUPPORT_INSTALL_TARGET_CMDS
$(INSTALL) -D -m 0755 $(@D)/support $(TARGET_DIR)/usr/sbin/support
endef

$(eval $(generic-package))
1 change: 1 addition & 0 deletions package/webui/Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ config BR2_PACKAGE_WEBUI
depends on BR2_PACKAGE_HOST_GO_TARGET_ARCH_SUPPORTS
depends on BR2_PACKAGE_ROUSETTE
depends on !BR2_PACKAGE_LANDING
select BR2_PACKAGE_SUPPORT
help
Web management interface for Infix, a Go+HTMX application
that provides browser-based configuration and monitoring
Expand Down
1 change: 0 additions & 1 deletion src/bin/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ DISTCLEANFILES = *~ *.d
ACLOCAL_AMFLAGS = -I m4

bin_PROGRAMS = copy erase files
sbin_SCRIPTS = support

# Bash completion
bashcompdir = $(datadir)/bash-completion/completions
Expand Down
4 changes: 2 additions & 2 deletions src/bin/copy.bash
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ _copy_completion()
prev="${COMP_WORDS[COMP_CWORD-1]}"

# Options for the copy command
opts="-h -n -q -s -t -u -v"
opts="-h -n -q -r -s -t -u -v"

local datastores_dst="running-config startup-config"
local datastores_src="factory-config operational-state running-config"
Expand Down Expand Up @@ -37,7 +37,7 @@ _copy_completion()
local i
for ((i=1; i < COMP_CWORD; i++)); do
case "${COMP_WORDS[i]}" in
-h|-n|-q|-s|-v)
-h|-n|-q|-r|-s|-v)
# Flag without argument
;;
-t|-u)
Expand Down
Loading