Skip to content
Merged
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
4 changes: 2 additions & 2 deletions board/common/image/image-itb-qcow/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ dimension()
elif [ $total -ge $((512 << M)) ]; then
bootsize=$(( 8 << M))
auxsize=$(( 8 << M))
imgsize=$((192 << M))
imgsize=$((180 << M))
cfgsize=$(( 16 << M))
# var is at least ~100M
# var is at least ~120M
else
echo "Can't create disk images smaller than 512M"
exit 1
Expand Down
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
10 changes: 10 additions & 0 deletions doc/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ 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
- WebUI: the support bundle is collected with the `infix-system:support-collect`
RPC as the logged-in user, so NACM decides who may download it, rather
than by running the tool as root

### Added

Expand All @@ -28,6 +34,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, an NACM rule must permit 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
127 changes: 104 additions & 23 deletions doc/support.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,128 @@ This command gathers configuration files, logs, network state, and other
system information into a single compressed archive.

> [!NOTE]
> The `support collect` command should be run with `sudo` to collect
> complete system information (kernel logs, hardware details, etc.).
> Use the `--unprivileged` option to run as a regular user in degraded
> data collection mode.
> `support collect` needs root for kernel logs, hardware details and the
> full configuration, so run it with `sudo`. Without root it refuses;
> `--unprivileged` lets it run anyway and collect what your user may
> read, the rest is noted as missing in the archive.

## Collecting Support Data

To collect support data and save it to a file:
On the device, collect to a file with `-o`. Progress goes to stderr and
the path of the archive is the only thing printed on stdout:

```bash
admin@host:~$ sudo support collect > support-data.tar.gz
admin@host:~$ sudo support collect -o /var/lib/support
Starting support data collection from host...
Collecting to: /var/lib/support
This may take up to a minute. Please wait...
Tailing /var/log/messages for 30 seconds (please wait)...
Log tail complete.
Collection complete. Creating archive...
admin@host:~$ ls -l support-data.tar.gz
-rw-rw-r-- 1 admin admin 508362 nov 30 13:05 support-data.tar.gz
/var/lib/support/support-host-2026-09-11T13:05:42+02:00.tar.gz
```

The command can also be run remotely via SSH from your workstation:
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. Secrets are redacted from the configuration, see below, but the
archive still holds every log on the device. Fetch it with `scp` and
remove it, or leave that to `support clean`.

Without `-o` the archive goes to stdout, which is what you want when
running the command from your workstation over SSH:

```bash
$ ssh admin@host 'sudo support collect' > support-data.tar.gz
...
```

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.
On the device itself, prefer `-o`. A session that drops mid-way then
leaves the archive behind rather than taking the only copy with it.

The collection may take up to a minute depending on system load and the
amount of logging data.

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. The logs are held in the collection and again in the
archive beside it, so collection measures them first and refuses when
the partition cannot hold both, rather than fill it. 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 over NETCONF or RESTCONF

The `infix-system:support-collect` RPC 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
```

Give a `password` in the input to get the archive encrypted, see
[Encrypted Collection](#encrypted-collection):

```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
```

Things to know:

- The RPC is denied by default, the caller's group needs a NACM rule
that permits it.
- An archive above 16 MiB is not returned inline. The reply then holds
`size` and `filename` only, and the file is left on the device for
you to fetch with `scp`.
- The RPC has 60 seconds to finish. On a device with many ports or a
lot of logging the collection may take longer, the call then fails
with a timeout and nothing is kept. Collect over SSH instead, see
[Collecting Support Data](#collecting-support-data).
- Over NETCONF the archive is a single XML text node. Clients built on
libxml2, lxml and ncclient among them, refuse text nodes over 10 MB
unless opened with `huge_tree=True`. RESTCONF has no such limit.

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

```bash
admin@host:~$ sudo support collect -p mypassword > support-data.tar.gz.gpg
admin@host:~$ sudo support collect -p mypassword -o /var/lib/support
Starting support data collection from host...
Collecting to: /var/lib/support
This may take up to a minute. Please wait...
...
Collection complete. Creating archive...
Encrypting with GPG...

WARNING: Remember to share the encryption password out-of-band!
Do not send it in the same email as the encrypted file.
/var/lib/support/support-host-2026-09-11T13:05:42+02:00.tar.gz.gpg
```

The `support collect` command even supports omitting `mypassword` and
will then prompt interactively for the password. This works over SSH too,
but the local ssh client may then echo the password.
Given a directory, `-o` appends `.gpg` to the canonical name. The
password may be left out, the command then prompts for it. That works
over SSH too, but the local ssh client may echo what you type, so pipe
it on stdin instead:

> [!TIP]
> To hide the encryption password for an SSH session, the script supports
> reading from stdin:
> `echo "$MYSECRET" | ssh user@device 'sudo support collect -p' >
> file.tar.gz.gpg`
```bash
$ echo "$MYSECRET" | ssh admin@host 'sudo support collect -p' > support-data.tar.gz.gpg
```

After transferring the resulting file to your workstation, decrypt it
with the password:
Expand Down Expand Up @@ -89,10 +155,25 @@ $ 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, password hashes and other secrets
that help no one troubleshoot, so `support collect` exports it with
`copy -r`, which drops every node the YANG models tag
`nacm:default-deny-all`, and the user passwords. The rest 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
and the infix-system:support-collect RPC, which the WebUI uses.

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
Loading