Rename the Maintenance > Backup & Restore page to Backup & Support and
add a Support Bundle card. Download support runs the on-device
`support collect` tool, which gathers configuration, logs, routing,
interfaces, hardware inventory, and container and service status into a
single archive; the WebUI runs as root so the collection is complete.
The handler buffers the archive and only commits response headers once
collection succeeds, so a mid-collection failure is a clean error rather
than a truncated download. An optional password encrypts the bundle via
the tool's GPG support, fed on stdin so it never reaches the process
list. Collection blocks for up to a minute with no output, so the write
deadline is extended past the server's 15s WriteTimeout and nginx gets a
matching read timeout; the browser shows a "collecting" state and saves
the blob client-side using the server's filename.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
New Logs page under Maintenance presents the on-disk syslog files
(messages, syslog, kern, auth, routing, firewall, upgrade, debug,
container, mail) with a tab per source and an (empty) chip for files
with no content.
The buffer loads the last 250 lines and pins to the bottom on open and
on tab change, with keyboard focus on the pane so PageUp/PageDown work
immediately. Load earlier pages back 250 lines at a time, preserving
the reader's scroll position as older lines fill in above; once the
current file is exhausted the button re-labels to "Load previous from
<rotation>" and walks back through rotated and gzipped archives.
Live tail streams new entries over SSE. The server runs tail -F -n 0
and debounces output; the client follows the bottom unless the reader
has scrolled up. A status pill shows connecting/live/disconnected.
nginx gets a no-buffering location for the tail stream, mirroring the
software progress endpoint.
Download returns the full archive — current file plus every rotated and
gzipped predecessor — concatenated chronologically.
Severity is coloured by a keyword heuristic since sysklogd writes no
<PRI> to disk; BSD-format lines are shown unconditionally. Filter is
client-side substring or /regex/, focusable with Ctrl/Cmd-F.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Vendor a Lucide icon set under static/img/icons/ and partial:ize the
inline SVGs across base, login, firmware, sidebar, and yang-tree.
Reorganize the sidebar with mirrored Status/Configure section labels.
Rename NACM to Users & Groups and Firmware to Software; swap Routes and
Routing between Status and Configure.
Split Configure > System into General, NTP Client, and DNS Client pages,
which opens up for relocating the Set Time RPC from the Maintenance
section to a new Date & Time card in the System General config page.
Update browser tab title on htmx navigation via an HX-Trigger
setPageTitle event; encode the payload as 7-bit ASCII so the middle
dot in "Page · Context" survives header transit.
Add missing hover-help ⓘ icons to bridge port configuration, and adjust
their alignment slightly. While in interface configuration:
- fix the annoying Save => collapse so one can edit multiple
interface sections without having to re-expand the iface
- add missing dhcpv4 settings
- add missing custom mac (use advanced view for other settings)
- clean up Save button mess (consolidate)
Rename Firmware -> Software everywhere in the Maintenance section and
fix "Install progress stuck at 10%" issue.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Adds an nginx-side rate limit on POST /login so a brute-force or DoS
attempt can't pin the box on the bcrypt-shaped credential check inside
rousette/PAM. Configuration:
- Keyed on $binary_remote_addr (per source IP), 5 requests/minute
sustained with a burst of 3 nodelay, a real user fumbling their
password three times in a row sails through; the 4th attempt in
the same window returns 429.
- GET /login is unmetered (the keyed map yields the empty string,
which limit_req treats as "no key, no limit"), so a 401-driven
HX-Redirect bouncing the user back to the login page doesn't
eat into the budget.
- 32k zone (~500 IPs, the minimum nginx accepts). At cache
saturation an attacker rotating addresses still tops out around
~2500 attempts/min, all serialised through bcrypt one at a time.
- 429 instead of the default 503 keeps the response out of the
/50x.html error_page rewrite (which auto-refreshes and would
loop a throttled client straight back to /login).
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The webui Go code now lives in the infix source tree rather than being
imported as an external module. Switch the module path to match that
reality so the imports read coherently with the rest of the codebase.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Replace the RAUC-centric firmware page with a cleaner layout:
- Show software slots (primary/secondary) using their bootnames rather
than internal RAUC slot names; filter to rootfs-class slots only
- Add boot order display (mirrors `show software` in the CLI)
- Show installed timestamp per slot (truncated to second precision)
- Fix Booted flag comparison: compare against bootname not slot name
- Lay out all three cards (Software, Install from URL, Upload & Install)
in a responsive grid instead of full-width stacked sections
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Backport two fixes addressing a critical failure reported by a customer:
an unclean dbus-daemon exit leaves a lingering /run/messagebus.pid, the
daemon then refuse to start, and Finit's restart loop gives up.
0001 service: clean stale pidfile after unclean daemon exit
Drop a daemon-owned (pid:!) pidfile when it still names the
just-reaped PID and that PID is no longer alive.
0002 service: log signal name and core dumps in death message
"by signal: 9" -> "killed by SIGKILL", with ", core dumped"
when applicable. Stronger breadcrumb for sudden deaths.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add missing *.hash files for all board packages using the ix-board macro;
they declare LICENSE_FILES = LICENSE but had no hash file, producing a
warning during make legal-info.
Fix the date-cpp package where the hash file was named date.hash instead
of date-cpp.hash (package name is derived from the directory, not the mk
filename), causing Buildroot to skip the hash check entirely.
Add hash files for local-site packages confd-test-mode, netd, and
onieprom that declared LICENSE_FILES but provided no hash.
Also, rename package/date-cpp/date.mk to date-cpp.mk. Buildroot derives
the package name from the directory name, so the mk file must match. To
handle the archive name different we set DATE_CPP_SOURCE.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add a second discovery backend that reads mDNS neighbor data directly
from the sysrepo operational datastore via `copy operational-state -x
/mdns`, selectable with --backend operational.
Add an auto backend (the new default) that tries the operational data
first and falls back to avahi-browse if the `copy` command is
unavailable or mDNS is disabled (visible via "enabled": false in the
JSON). This makes the service work correctly in all configurations
without manual tuning.
Refactor TXT record parsing into parseTxt() and service/host assembly
into buildHosts(), shared by both backends. Extract fetchOpRoot() and
parseOperational() so scanOperational() and scanAuto() share the same
JSON fetch/decode and host-building logic without duplication.
Fix a bug where TXT values containing semicolons were truncated
(parts[9] → strings.Join(parts[9:], ";")), and apply decode() to TXT
values so avahi \DDD escapes are resolved. Add Apple device model
support via the am= (RAOP/AirPlay 1) and model= (AirPlay 2) TXT keys.
Display the last-updated timestamp in 24-hour format regardless of the
browser's locale.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add reliable avahi client reconnect via explicit free+recreate, reduced
log verbosity (single 10s warning instead of 3×2s loop). Also, binary
TXT record filtering (UTF-8 + XML validity), and finally add a SIGHUP
handler for on-demand reconnect.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add --log-level command line option to filter out log messages from
lower log levels. Then fix the annoying CzechLight warning message
and useless "NACM config validation" log. Then add audit trail as
we have in netopeer2-server, and finish off by stripping redundant
fields from log message: timestamp, identity, and log level.
Fixes#892
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Use same log frameworks as reset of confd
- Use existing primitives from libite + libsrx
- Drop remaining pthreads
- Coding style fixes
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Use SR_SUBSCR_NO_THREAD for all subscriptions and integrate sysrepo
event pipes into a libev event loop. This eliminates approximately 30
per-subscription threads, reducing overhead on embedded ARM hardware.
A temporary poll-based "event pump" thread handles callback dispatch
during bootstrap (where sr_replace_config blocks waiting for callbacks),
then exits. After bootstrap, the single-threaded libev loop takes over
for steady-state event processing.
Note, the confd-test-mode plugin still requires use of threads so we do
not create deadlocks when calling sr_replace_config().
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Add x509-public-key-format identity to crypto-types
- Add certificate node to web services container
- Use certificate from ietf-keystore as web cert
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Allow confd to start even earlier at boot and call 'gen-config' as a
background task, pending on it to complete before we load the sysrepo
factory datastore.
Also, add Finit style progress to console so users can see the phases
of the bootstrap process.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Infix technically does not need to start dbus and dnsmasq before confd
has loaded the system startup-config. So we move it in time to save
some CPU cycles for confd & C:o.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
On single-core Cortex-A7, the YANG bootstrap and config loading is the
dominant boot bottleneck. The current sequence spawns three serial
phases (bootstrap, sysrepo-plugind, load), each performing independent
sr_connect()/sr_disconnect() cycles, and every sysrepoctl/sysrepocfg
invocation is a fork+exec that rebuilds SHM from scratch.
Replace all three with a single confd binary that does one sr_connect()
and performs all datastore operations in-process:
- Wipe stale /dev/shm/sr_* for a clean slate
- sr_install_factory_config() from the generated JSON
- Smart migration: compare config version via libjansson, only
fork+exec the migrate script when versions actually differ
- Load startup-config (or test-config) via lyd_parse_data() +
sr_replace_config(), mirroring what sysrepocfg -I does internally
- On failure: revert to factory-default, load failure-config, set
login banners (Fail Secure mode)
- On first boot: copy factory-default to running, export to file
- dlopen plugins and enter event loop
The bootstrap shell script is split: config generation (gen-hostname,
gen-interfaces, etc.) stays in the new gen-config script, while all
sysrepo operations move into the C daemon. The finit boot sequence
collapses from 5 stanzas to 2 (gen-config -> confd).
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Backport fixes from upstream post v4.16 release. Mainly to fix
mdns-alias crash+restart counter issue when avahi-daemon has to
be restarted. Finit did not properly clear the dependency that
mdns-alias had on avahi-daemon, causing it to crash and have its
restart counter incremented.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Before netd starts confd might want to create .conf file for it to run,
so we sort of depend on /etc/net.d existing at boot.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Two races could prevent DHCP-learned default routes from being installed
at boot:
1. The signal from the DHCP client script could be lost leaving conf.d
updated but frr.conf stale.
2. Even when the signal was received, 'vtysh -b' could fail because the
FRR daemon chain (mgmtd→zebra→staticd) writes PID files before being
fully operational, causing netd to give up with no retry.
Fix both by refactoring netd to use libev:
- Use an inotify watch of CONF_DIR, so netd reacts directly to file
changes without depending on signal delivery.
- On backend_apply() failure, schedule a retry in 5s and call pidfile()
unconditionally so dependent services are not blocked waiting for the
Finit condition 'pid/netd' to be satisfied.
We also take this opportunity to rename /etc/netd/conf.d/ to /etc/net.d/
The extra /etc/netd/ directory level served no purpose — nothing else
lives there. Flatten to /etc/net.d/ which reads more naturally as the
drop-in directory for network configuration snippets.
Also, reduce logging a bit since each netd backend already logs success
or fail which is sufficient to know that a configuration change has been
applied or not.
Finally, with the new inotify processing in netd it's redundant to call
'initctl reload netd' from the udhcpc script, in fact it will only cause
unnecessary overhead, so we drop it.
Fixes#1438
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Increase Zebra NETLINK buffer to fix reported issues with zebra being
out of sync with kernel routes and interface changes.
Also, try '-a' option to allow other processes to delete zebra routes.
Other changes in this commit:
- Minor fixes to Finit service files for consistency
- Empty daemon.conf stub files to silence bogus mgmtd errors at startup
- Relocate all skeleton files from board/common to separate from files
that are actual Infix additions and what's package system integration
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Instead of publishing A/AAAA records for $(hostname).loocal with a CNAME
infix.local, we flip it around to take advantage of the mDNS conflict
resolution rules. This gives us infix.local for one device ont the LAN
and infix-2.local for the next.
Update all service records to *not* advertise hostname, but instead to
let Avahi imply that from the advertised A/AAAA and CNAME records.
Fixes#1387
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>