From 46c35106fb159ad4a45d6bf0e94f6e79997846e5 Mon Sep 17 00:00:00 2001 From: reachableceo Date: Sat, 1 Aug 2026 15:44:59 -0500 Subject: [PATCH] prep for next ai session --- console/README.md | 130 -- console/discover.sh | 103 - console/generate-config.sh | 254 -- console/mapping.txt | 29 - console/query-remote.sh | 62 - console/setup.sh | 217 -- console/validate-conman.sh | 89 - dns-cluster-setup/README.md | 183 -- dns-cluster-setup/remote-dns.sh | 90 - dns-cluster-setup/setup.sh | 474 ---- dns-cluster-setup/sync-zones.sh | 43 - dns-cluster-setup/verify.sh | 204 -- docs/archive/AIReview-QWEN.md | 140 -- docs/archive/AiOverview-Gemini.md | 45 - docs/archive/AiOverview-OpenCode.md | 309 --- docs/archive/AiSecurityAudit-Gemini.md | 29 - docs/archive/CODE-REVIEW-FINDINGS.md | 280 --- docs/archive/Claude-Review.md | 94 - docs/archive/REFACTORING-EXAMPLES.md | 535 ----- docs/archive/charles-todo.md | 117 - docs/archive/claude-todo.md | 162 -- perf/check-pkgs.sh | 29 - perf/check-repos-and-reboot.sh | 41 - perf/deploy-and-fix.sh | 51 - perf/deploy-check.sh | 174 -- perf/deploy-tuning.sh | 56 - perf/diag.sh | 35 - perf/finish-host.sh | 128 -- perf/install-utils-v2.sh | 37 - perf/install-utils.sh | 60 - perf/iperf-full-matrix.sh | 293 --- perf/iperf-storage-tests.sh | 184 -- perf/iperf-tsys6-tsys7.sh | 119 - perf/reboot-and-verify.sh | 88 - perf/reboot-verify.sh | 91 - perf/scripts/apply-bond-hash.sh | 141 -- perf/scripts/apply-tunings.sh | 439 ---- perf/scripts/check.sh | 1138 --------- perf/scripts/conman-console.py | 162 -- perf/scripts/fix-bond-nfs.sh | 86 - perf/scripts/lacp-retrans-cause.sh | 219 -- perf/scripts/lacp-rx-distribution.sh | 153 -- perf/scripts/probe-drift.sh | 79 - perf/scripts/probe-network.sh | 82 - perf/scripts/probe-storage.sh | 75 - perf/scripts/run-lacp-retrans-cause.sh | 91 - perf/scripts/run-lacp-rx-distribution.sh | 112 - perf/scripts/snmp-switch-audit.py | 253 -- perf/shellcheck.sh | 65 - perf/validate-fixes.sh | 169 -- perf/validate-vms.sh | 130 -- perf/verify-tuning.sh | 36 - perf/wait-for-host.sh | 58 - powerman/README.md | 111 - powerman/discover.sh | 68 - powerman/query-remote.sh | 65 - powerman/setup.sh | 181 -- powerman/status.sh | 33 - powerman/test-pdu.sh | 126 - provisioning/Agents/librenms/check_mk.socket | 9 - .../Agents/librenms/check_mk@.service | 7 - provisioning/Agents/librenms/check_mk_agent | 659 ------ provisioning/Agents/librenms/distro | 114 - provisioning/Agents/librenms/dmi.sh | 9 - provisioning/Agents/librenms/dpkg.sh | 22 - provisioning/Agents/librenms/mysql.sh | 1438 ------------ provisioning/Agents/librenms/ntp-client | 34 - provisioning/Agents/librenms/ntp-server.sh | 89 - provisioning/Agents/librenms/os-updates.sh | 73 - provisioning/Agents/librenms/postfix-queues | 13 - provisioning/Agents/librenms/postfixdetailed | 548 ----- provisioning/Agents/librenms/raspberry.sh | 46 - provisioning/Agents/librenms/smart | 929 -------- provisioning/Agents/librenms/smart.config | 3 - provisioning/Agents/librenms/ss.py | 2048 ----------------- provisioning/Agents/librenms/ups-nut.sh | 45 - provisioning/ConfigFiles/99-pfv-nfs.conf | 23 - provisioning/ConfigFiles/AuditD/auditd.conf | 46 - .../AuditD/rules.d/time-change.rules | 0 provisioning/ConfigFiles/BANNERS/issue | 5 - provisioning/ConfigFiles/BANNERS/issue.net | 5 - provisioning/ConfigFiles/BANNERS/motd | 5 - .../ConfigFiles/Cockpit/disallowed-users | 2 - provisioning/ConfigFiles/DHCP/dhclient.conf | 14 - .../ConfigFiles/Logrotate/logrotate.conf | 23 - provisioning/ConfigFiles/ModProbe/cramfs.conf | 1 - provisioning/ConfigFiles/ModProbe/dccp.conf | 1 - .../ConfigFiles/ModProbe/freevxfs.conf | 1 - provisioning/ConfigFiles/ModProbe/hfs.conf | 1 - .../ConfigFiles/ModProbe/hfsplus.conf | 1 - provisioning/ConfigFiles/ModProbe/jffs2.conf | 1 - provisioning/ConfigFiles/ModProbe/rds.conf | 1 - provisioning/ConfigFiles/ModProbe/sctp.conf | 1 - .../ConfigFiles/ModProbe/squashfs.conf | 1 - provisioning/ConfigFiles/ModProbe/tipc.conf | 1 - provisioning/ConfigFiles/ModProbe/udf.conf | 1 - .../ConfigFiles/ModProbe/usb_storage.conf | 1 - provisioning/ConfigFiles/NTP/ntp.conf | 21 - .../ConfigFiles/NetworkDiscovery/lldpd | 2 - provisioning/ConfigFiles/Resolv/resolv.conf | 11 - provisioning/ConfigFiles/SMTP/aliases | 3 - provisioning/ConfigFiles/SMTP/postfix_generic | 1 - provisioning/ConfigFiles/SNMP/snmp-sudo.conf | 1 - .../ConfigFiles/SNMP/snmpd-physicalhost.conf | 46 - provisioning/ConfigFiles/SNMP/snmpd-rpi.conf | 40 - provisioning/ConfigFiles/SNMP/snmpd.conf | 44 - .../localuser-ssh-authorized-keys | 2 - .../AuthorizedKeys/root-ssh-authorized-keys | 2 - .../SSH/Configs/ssh-audit-hardening.conf | 19 - .../ConfigFiles/SSH/Configs/tsys-sshd-config | 20 - provisioning/ConfigFiles/Syslog/rsyslog.conf | 6 - .../ConfigFiles/Systemd/journald.conf | 31 - provisioning/ConfigFiles/ZSH/tsys-zshrc | 258 --- .../ConfigFiles/pfv-nfs-tuning.service | 28 - provisioning/Dell/Server/fixeth.sh | 24 - provisioning/Dell/Server/omsa.sh | 34 - provisioning/Dell/fixcpuperf.sh | 10 - .../Modules/Auth/auth-cloudron-ldap.sh | 4 - provisioning/Modules/OAM/oam-librenms.sh | 66 - .../Modules/RandD/sslStackFromSource.sh | 82 - .../Modules/Security/secharden-2fa.sh | 426 ---- .../Security/secharden-audit-agents.sh | 50 - .../Security/secharden-auto-upgrade.sh | 3 - .../Modules/Security/secharden-scap-stig.sh | 126 - .../Modules/Security/secharden-ssh.sh | 105 - .../Modules/Security/secharden-wazuh.sh | 57 - provisioning/Project-ConfigFiles/CONFIG_VARS | 3 - provisioning/Project-Includes/LocalHelp.sh | 13 - .../Project-Includes/PreflightCheck.sh | 19 - provisioning/Project-Includes/pi-detect.sh | 13 - provisioning/SetupNewSystem.sh | 431 ---- provisioning/legacy/profiled-tmux.sh | 5 - provisioning/legacy/profiled-tsys-shell.sh | 2 - provisioning/legacy/prox7.sh | 9 - provisioning/scripts/up2date.sh | 16 - switches/pfv-core-sw01.cmds | 7 - switches/pfv-tor3-stor.cmds | 12 - ups/README.md | 210 -- ups/discover.sh | 86 - ups/ha-nut-setup.py | 134 -- ups/setup-ha-nut.sh | 65 - ups/setup.sh | 298 --- ups/status.sh | 59 - 143 files changed, 18172 deletions(-) delete mode 100644 console/README.md delete mode 100644 console/discover.sh delete mode 100644 console/generate-config.sh delete mode 100644 console/mapping.txt delete mode 100644 console/query-remote.sh delete mode 100644 console/setup.sh delete mode 100644 console/validate-conman.sh delete mode 100644 dns-cluster-setup/README.md delete mode 100755 dns-cluster-setup/remote-dns.sh delete mode 100755 dns-cluster-setup/setup.sh delete mode 100755 dns-cluster-setup/sync-zones.sh delete mode 100755 dns-cluster-setup/verify.sh delete mode 100644 docs/archive/AIReview-QWEN.md delete mode 100644 docs/archive/AiOverview-Gemini.md delete mode 100644 docs/archive/AiOverview-OpenCode.md delete mode 100644 docs/archive/AiSecurityAudit-Gemini.md delete mode 100644 docs/archive/CODE-REVIEW-FINDINGS.md delete mode 100644 docs/archive/Claude-Review.md delete mode 100644 docs/archive/REFACTORING-EXAMPLES.md delete mode 100644 docs/archive/charles-todo.md delete mode 100644 docs/archive/claude-todo.md delete mode 100755 perf/check-pkgs.sh delete mode 100755 perf/check-repos-and-reboot.sh delete mode 100755 perf/deploy-and-fix.sh delete mode 100755 perf/deploy-check.sh delete mode 100755 perf/deploy-tuning.sh delete mode 100755 perf/diag.sh delete mode 100755 perf/finish-host.sh delete mode 100755 perf/install-utils-v2.sh delete mode 100755 perf/install-utils.sh delete mode 100755 perf/iperf-full-matrix.sh delete mode 100755 perf/iperf-storage-tests.sh delete mode 100755 perf/iperf-tsys6-tsys7.sh delete mode 100755 perf/reboot-and-verify.sh delete mode 100755 perf/reboot-verify.sh delete mode 100755 perf/scripts/apply-bond-hash.sh delete mode 100755 perf/scripts/apply-tunings.sh delete mode 100755 perf/scripts/check.sh delete mode 100644 perf/scripts/conman-console.py delete mode 100755 perf/scripts/fix-bond-nfs.sh delete mode 100644 perf/scripts/lacp-retrans-cause.sh delete mode 100755 perf/scripts/lacp-rx-distribution.sh delete mode 100644 perf/scripts/probe-drift.sh delete mode 100644 perf/scripts/probe-network.sh delete mode 100644 perf/scripts/probe-storage.sh delete mode 100644 perf/scripts/run-lacp-retrans-cause.sh delete mode 100755 perf/scripts/run-lacp-rx-distribution.sh delete mode 100644 perf/scripts/snmp-switch-audit.py delete mode 100755 perf/shellcheck.sh delete mode 100755 perf/validate-fixes.sh delete mode 100755 perf/validate-vms.sh delete mode 100755 perf/verify-tuning.sh delete mode 100755 perf/wait-for-host.sh delete mode 100644 powerman/README.md delete mode 100644 powerman/discover.sh delete mode 100644 powerman/query-remote.sh delete mode 100644 powerman/setup.sh delete mode 100644 powerman/status.sh delete mode 100644 powerman/test-pdu.sh delete mode 100644 provisioning/Agents/librenms/check_mk.socket delete mode 100644 provisioning/Agents/librenms/check_mk@.service delete mode 100644 provisioning/Agents/librenms/check_mk_agent delete mode 100644 provisioning/Agents/librenms/distro delete mode 100644 provisioning/Agents/librenms/dmi.sh delete mode 100644 provisioning/Agents/librenms/dpkg.sh delete mode 100644 provisioning/Agents/librenms/mysql.sh delete mode 100644 provisioning/Agents/librenms/ntp-client delete mode 100644 provisioning/Agents/librenms/ntp-server.sh delete mode 100644 provisioning/Agents/librenms/os-updates.sh delete mode 100644 provisioning/Agents/librenms/postfix-queues delete mode 100644 provisioning/Agents/librenms/postfixdetailed delete mode 100644 provisioning/Agents/librenms/raspberry.sh delete mode 100644 provisioning/Agents/librenms/smart delete mode 100644 provisioning/Agents/librenms/smart.config delete mode 100644 provisioning/Agents/librenms/ss.py delete mode 100644 provisioning/Agents/librenms/ups-nut.sh delete mode 100644 provisioning/ConfigFiles/99-pfv-nfs.conf delete mode 100644 provisioning/ConfigFiles/AuditD/auditd.conf delete mode 100644 provisioning/ConfigFiles/AuditD/rules.d/time-change.rules delete mode 100644 provisioning/ConfigFiles/BANNERS/issue delete mode 100644 provisioning/ConfigFiles/BANNERS/issue.net delete mode 100644 provisioning/ConfigFiles/BANNERS/motd delete mode 100644 provisioning/ConfigFiles/Cockpit/disallowed-users delete mode 100644 provisioning/ConfigFiles/DHCP/dhclient.conf delete mode 100644 provisioning/ConfigFiles/Logrotate/logrotate.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/cramfs.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/dccp.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/freevxfs.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/hfs.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/hfsplus.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/jffs2.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/rds.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/sctp.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/squashfs.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/tipc.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/udf.conf delete mode 100644 provisioning/ConfigFiles/ModProbe/usb_storage.conf delete mode 100644 provisioning/ConfigFiles/NTP/ntp.conf delete mode 100644 provisioning/ConfigFiles/NetworkDiscovery/lldpd delete mode 100644 provisioning/ConfigFiles/Resolv/resolv.conf delete mode 100644 provisioning/ConfigFiles/SMTP/aliases delete mode 100644 provisioning/ConfigFiles/SMTP/postfix_generic delete mode 100644 provisioning/ConfigFiles/SNMP/snmp-sudo.conf delete mode 100644 provisioning/ConfigFiles/SNMP/snmpd-physicalhost.conf delete mode 100644 provisioning/ConfigFiles/SNMP/snmpd-rpi.conf delete mode 100644 provisioning/ConfigFiles/SNMP/snmpd.conf delete mode 100644 provisioning/ConfigFiles/SSH/AuthorizedKeys/localuser-ssh-authorized-keys delete mode 100644 provisioning/ConfigFiles/SSH/AuthorizedKeys/root-ssh-authorized-keys delete mode 100644 provisioning/ConfigFiles/SSH/Configs/ssh-audit-hardening.conf delete mode 100644 provisioning/ConfigFiles/SSH/Configs/tsys-sshd-config delete mode 100644 provisioning/ConfigFiles/Syslog/rsyslog.conf delete mode 100644 provisioning/ConfigFiles/Systemd/journald.conf delete mode 100644 provisioning/ConfigFiles/ZSH/tsys-zshrc delete mode 100644 provisioning/ConfigFiles/pfv-nfs-tuning.service delete mode 100644 provisioning/Dell/Server/fixeth.sh delete mode 100644 provisioning/Dell/Server/omsa.sh delete mode 100644 provisioning/Dell/fixcpuperf.sh delete mode 100644 provisioning/Modules/Auth/auth-cloudron-ldap.sh delete mode 100644 provisioning/Modules/OAM/oam-librenms.sh delete mode 100644 provisioning/Modules/RandD/sslStackFromSource.sh delete mode 100644 provisioning/Modules/Security/secharden-2fa.sh delete mode 100644 provisioning/Modules/Security/secharden-audit-agents.sh delete mode 100644 provisioning/Modules/Security/secharden-auto-upgrade.sh delete mode 100644 provisioning/Modules/Security/secharden-scap-stig.sh delete mode 100644 provisioning/Modules/Security/secharden-ssh.sh delete mode 100644 provisioning/Modules/Security/secharden-wazuh.sh delete mode 100644 provisioning/Project-ConfigFiles/CONFIG_VARS delete mode 100644 provisioning/Project-Includes/LocalHelp.sh delete mode 100644 provisioning/Project-Includes/PreflightCheck.sh delete mode 100644 provisioning/Project-Includes/pi-detect.sh delete mode 100644 provisioning/SetupNewSystem.sh delete mode 100644 provisioning/legacy/profiled-tmux.sh delete mode 100644 provisioning/legacy/profiled-tsys-shell.sh delete mode 100644 provisioning/legacy/prox7.sh delete mode 100644 provisioning/scripts/up2date.sh delete mode 100644 switches/pfv-core-sw01.cmds delete mode 100644 switches/pfv-tor3-stor.cmds delete mode 100644 ups/README.md delete mode 100644 ups/discover.sh delete mode 100644 ups/ha-nut-setup.py delete mode 100644 ups/setup-ha-nut.sh delete mode 100644 ups/setup.sh delete mode 100644 ups/status.sh diff --git a/console/README.md b/console/README.md deleted file mode 100644 index e34b8cc..0000000 --- a/console/README.md +++ /dev/null @@ -1,130 +0,0 @@ -# Console Management (ser2net + conman) - -Network-accessible serial console management for all production network -switches and routers, running on **pfv-tsys4** (storage server). - -## Architecture - -``` -USB-DB9 adapters → udev symlinks (/dev/consoles/) → ser2net telnet(rfc2217) TCP → conman (logging + multiplexing) -``` - -ser2net owns the physical serial devices and exposes them on TCP ports -using the **telnet(rfc2217) protocol** bound to the **Tailscale interface -only** (`100.70.77.93:200X`). conman connects to those TCP ports via -telnet for session logging, output capture, and multi-user console -sharing. - -**Why telnet(rfc2217)?** The serial devices send ` - ` (LF+CR) line -endings instead of standard ` -`. Raw TCP transport caused conman's -telnet NVT to strip bare CR characters, producing stair-stepped output. -With telnet(rfc2217) on both sides, binary mode is negotiated and CR/LF -translation is handled correctly by the telnet layer. - -**conman and ser2net do NOT share ports** — only one process can open a -serial device at a time. ser2net owns the physical device; conman connects -over TCP. - -## The USB Enumeration Problem (SOLVED) - -The 9 Prolific USB-to-DB9 adapters (`067b:2303`) on pfv-tsys4 have **no -unique USB serial numbers** and get assigned `/dev/ttyUSB0-8` based on -enumeration order, which shifts on every boot. This made the old -`/root/conmap` + manual `screen` workflow break after every reboot. - -**Fix:** udev rules pin each adapter by its **ID_PATH** (physical USB port -topology), which is stable across reboots regardless of enumeration order. -Each adapter gets a named symlink in `/dev/consoles/` that never changes. - -The udev rules are generated from `mapping.txt`, which maps each adapter's -ID_PATH to a console name and TCP port. To re-map after physically moving -an adapter, update `mapping.txt` and re-run `setup.sh`. - -**Fallback:** if udev trigger doesn't create symlinks for already-discovered -devices (common on first run), `setup.sh` creates them manually by matching -ID_PATH. On subsequent boots, udev creates them automatically. - -## Port Assignments - -| TCP Port | Console Name | ID_PATH | Description | -|----------|-------------|---------|-------------| -| 2001 | pfv-core-sw01 | usb-0:1.5.4.4 | Dell PowerConnect 5448 (core switch) | -| 2002 | pfv-tor3-mgmt | usb-0:1.6.3.1 | Rack 3 management TOR switch | -| 2003 | pfv-tor3-stor | usb-0:1.6.3.3.2 | Rack 3 storage TOR switch | -| 2004 | pfv-rrinfra-rtr | usb-0:1.6.3.3.1 | Cisco router (rrinfra) | -| 2005 | pfv-r2-tor-top | usb-0:1.6.3.3.3 | Rack 2 top-of-rack switch | -| 2006 | subodev-torsw | usb-0:1.5.4.1 | Suborbital device TOR switch | -| 2007 | pfv-r2-sw | usb-0:1.6.3.2 | Rack 2 old Dell switch | - -All ports listen on the Tailscale IP (`100.70.77.93`) using telnet(rfc2217). - -## Scripts - -| Script | Purpose | -|--------|---------| -| [`mapping.txt`](mapping.txt) | Source of truth: TCP port ↔ ID_PATH ↔ name ↔ baud | -| [`generate-config.sh`](generate-config.sh) | Generates udev rules, ser2net.yaml, conman.conf from mapping.txt | -| [`setup.sh`](setup.sh) | Full deploy: generate configs, create symlinks, restart services | -| [`discover.sh`](discover.sh) | Read-only discovery of USB adapters, existing config, services | - -## Usage - -### Connect to a console - -**Primary method — conman client (with logging + multiplexing):** - -```bash -# From any Tailscale-connected workstation: -conman -d pfv-tsys4:7890 -f pfv-core-sw01 # connect to console -conman -d pfv-tsys4:7890 -q # list all consoles -``` - -Escape sequence: `&.` to disconnect, `&?` for help. - -**Direct telnet (emergency only — conflicts with conman):** - -```bash -# Direct telnet to ser2net works ONLY when conmand is stopped, because -# conmand maintains persistent connections to all 7 TCP ports. Use: -ssh pfv-tsys4 'systemctl stop conmand' -telnet pfv-tsys4 2001 # pfv-core-sw01 -ssh pfv-tsys4 'systemctl start conmand' # restart when done -``` - -**Do NOT use telnet while conmand is running** — conmand will reconnect -and kick your telnet session immediately ("Connection closed by foreign host"). -The correct workflow is conman client → conmand → ser2net → device. - -### Re-deploy after changing mapping.txt - -```bash -PROX_HOST=pfv-tsys4 bash tests/remote.sh prox 'bash /root/console/setup.sh' -``` - -### Find the ID_PATH for a new adapter - -```bash -PROX_HOST=pfv-tsys4 bash tests/remote.sh prox-file console/discover.sh -``` - -Then match the new adapter's ID_PATH to its physical location and add a line -to `mapping.txt`. - -## Files on pfv-tsys4 - -| File | Purpose | -|------|---------| -| `/etc/udev/rules.d/99-console-ports.rules` | Stable symlinks by ID_PATH | -| `/etc/ser2net.yaml` | ser2net config (telnet rfc2217 TCP ports → serial symlinks) | -| `/etc/conman.conf` | conman config (CONSOLE entries between markers) | -| `/etc/systemd/system/conmand.service` | systemd unit for conmand | -| `/root/console/mapping.txt` | Copy of the source-of-truth mapping | -| `/root/console/setup.sh` | Setup script (re-runnable) | -| `/root/console/generate-config.sh` | Config generator | - -## Old workflow (replaced) - -The old `/root/conmap` file and manual `screen` sessions are no longer -needed. The new setup is fully automated and survives reboots. diff --git a/console/discover.sh b/console/discover.sh deleted file mode 100644 index 34138b9..0000000 --- a/console/discover.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/bash -# shellcheck disable=SC2010,SC2012 # diagnostic script; ls|grep/ls -la on sysfs & log dirs is intentional for human-readable output -# -# console/discover.sh — READ-ONLY discovery of console setup on pfv-tsys4 -# -# Usage: PROX_HOST=pfv-tsys4 bash tests/remote.sh prox-file console/discover.sh -# -# This script is strictly read-only. No writes to the system. -# -set -uo pipefail - -echo "============================================" -echo " Console Setup Discovery" -echo " Host: $(hostname)" -echo " Date: $(date)" -echo " READ-ONLY" -echo "============================================" - -echo "" -echo "=== 1. USB devices ===" -lsusb 2>/dev/null || echo "(lsusb not available)" - -echo "" -echo "=== 2. All ttyUSB* devices (with major/minor) ===" -ls -la /dev/ttyUSB* 2>/dev/null || echo "(no /dev/ttyUSB* devices)" - -echo "" -echo "=== 3. USB-serial driver bindings ===" -echo "-- pl2303 --" -ls -la /sys/bus/usb-serial/drivers/pl2303/ 2>/dev/null | grep -v '^total\|^d\|module\|new_id\|uevent' || echo "(none)" -echo "-- cp210x --" -ls -la /sys/bus/usb-serial/drivers/cp210x/ 2>/dev/null | grep -v '^total\|^d\|module\|new_id\|uevent' || echo "(none)" -echo "-- ftdi_sio --" -ls -la /sys/bus/usb-serial/drivers/ftdi_sio/ 2>/dev/null | grep -v '^total\|^d\|module\|new_id\|uevent' || echo "(none)" -echo "-- ch341 --" -ls -la /sys/bus/usb-serial/drivers/ch341/ 2>/dev/null | grep -v '^total\|^d\|module\|new_id\|uevent' || echo "(none)" - -echo "" -echo "=== 4. USB serial adapter details (vendor/model/serial per port) ===" -for tty in /dev/ttyUSB*; do - [ -e "$tty" ] || continue - echo "--- $tty ---" - udevadm info -q all -n "$tty" 2>/dev/null | grep -E 'ID_VENDOR_ID|ID_MODEL_ID|ID_SERIAL|ID_USB_DRIVER|ID_PATH=' | sed 's/^/ /' -done - -echo "" -echo "=== 5. Existing /root/conmap ===" -if [ -f /root/conmap ]; then - cat /root/conmap -else - echo "(no /root/conmap)" -fi -ls -la /root/conmap* 2>/dev/null - -echo "" -echo "=== 6. Screen sessions (running) ===" -screen -ls 2>&1 || echo "(screen not running or not installed)" - -echo "" -echo "=== 7. Existing screen wrappers/scripts in /root ===" -ls -la /root/ 2>/dev/null | grep -iE 'screen|con|console|tty|usb' || echo "(no obvious console scripts in /root)" - -echo "" -echo "=== 8. ser2net ===" -which ser2net 2>/dev/null || echo "(ser2net not installed)" -dpkg -l ser2net 2>/dev/null | tail -2 || echo "(ser2net not in dpkg)" -cat /etc/ser2net/ser2net.yaml 2>/dev/null || cat /etc/ser2net.conf 2>/dev/null || cat /etc/ser2net/ser2net.conf 2>/dev/null || echo "(no ser2net config)" -systemctl is-active ser2net 2>/dev/null || echo "(ser2net service not found)" - -echo "" -echo "=== 9. conman ===" -which conman 2>/dev/null || echo "(conman not installed)" -which conmand 2>/dev/null || echo "(conmand not installed)" -dpkg -l conman 2>/dev/null | tail -2 || echo "(conman not in dpkg)" -echo "--- /etc/conman.conf (console lines only) ---" -grep -nE 'CONSOLE|SERVER|LOG|SERIAL|DEV|BAUD|^[^#].*name=' /etc/conman.conf 2>/dev/null | head -60 || echo "(no conman.conf or no console entries)" -echo "--- conmand service ---" -systemctl is-active conmand 2>/dev/null || echo "(conmand not running)" -systemctl is-enabled conmand 2>/dev/null || echo "(conmand not enabled)" - -echo "" -echo "=== 10. Existing console logs ===" -ls -la /var/log/conman/ 2>/dev/null | head -20 || echo "(no /var/log/conman)" -ls -la /var/consoles/ 2>/dev/null | head -20 || echo "(no /var/consoles)" - -echo "" -echo "=== 11. udev rules for ttyUSB ===" -grep -r ttyUSB /etc/udev/rules.d/ 2>/dev/null || echo "(no udev rules for ttyUSB)" -grep -r 'console' /etc/udev/rules.d/ 2>/dev/null | head -10 || true - -echo "" -echo "=== 12. expect availability ===" -command -v expect && expect -v 2>&1 || echo "expect: NOT installed" -command -v socat && socat -V 2>&1 | head -1 || echo "socat: NOT installed" - -echo "" -echo "=== 13. Ports in use (2001-2099, 7000-7999, 7820-7899) ===" -ss -tlnp 2>/dev/null | grep -E ':200[0-9]|:700[0-9]|:782[0-9]|:789[0-9]' || echo "(no relevant ports listening)" - -echo "" -echo "============================================" -echo " Discovery complete (read-only)." -echo "============================================" diff --git a/console/generate-config.sh b/console/generate-config.sh deleted file mode 100644 index a61b9ad..0000000 --- a/console/generate-config.sh +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/bin/bash -# -# console/generate-config.sh — generate udev rules + ser2net.yaml + conman.conf -# -# Reads console/mapping.txt (the source of truth) and generates all three -# config files. This is the fix for the USB enumeration shift problem: -# -# 1. udev rules pin each adapter by its STABLE ID_PATH (physical USB port) -# to a named symlink like /dev/consoles/pfv-core-sw01 -# 2. ser2net opens those stable symlinks and exposes them on TCP ports -# (2001, 2002, ...) bound to the Tailscale IP -# 3. conman connects to those TCP ports for logging + multiplexing -# -# Run this script ON the target host. It writes to: -# /etc/udev/rules.d/99-console-ports.rules -# /etc/ser2net.yaml -# /etc/conman/console-consoles.conf (included by /etc/conman.conf) -# -# Usage: -# PROX_HOST=pfv-tsys4 bash tests/remote.sh prox-file console/generate-config.sh -# -# Environment overrides: -# MAPPING_FILE — path to mapping.txt (default: auto-detect next to this script) -# TS_IP — Tailscale IP to bind ser2net on (default: auto-detect) -# CONMAN_LOGDIR — conman log directory (default: /var/log/conman) -# -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -MAPPING_FILE="${MAPPING_FILE:-$SCRIPT_DIR/mapping.txt}" -CONMAN_LOGDIR="${CONMAN_LOGDIR:-/var/log/conman}" - -UDEV_RULES="/etc/udev/rules.d/99-console-ports.rules" -SER2NET_CONF="/etc/ser2net.yaml" -CONMAN_CONF="/etc/conman.conf" - -echo "============================================" -echo " Console Config Generator" -echo " Host: $(hostname) $(date)" -echo "============================================" - -# --- Locate mapping file --- -# When run via remote.sh prox-file, $0 is bash and $SCRIPT_DIR may be wrong. -# Search common locations. -if [ ! -f "$MAPPING_FILE" ]; then - for candidate in \ - "/root/console/mapping.txt" \ - "/tmp/mapping.txt" \ - "$(dirname "$0")/mapping.txt"; do - if [ -f "$candidate" ]; then - MAPPING_FILE="$candidate" - break - fi - done -fi - -if [ ! -f "$MAPPING_FILE" ]; then - echo "FATAL: mapping file not found. Tried: $MAPPING_FILE" - echo "Copy mapping.txt to the target host first." - exit 1 -fi -echo " Mapping file: $MAPPING_FILE" - -# --- Auto-detect Tailscale IP --- -if [ -z "${TS_IP:-}" ]; then - TS_IP=$(tailscale ip -4 2>/dev/null || true) - if [ -z "$TS_IP" ]; then - echo "FATAL: could not auto-detect Tailscale IP. Set TS_IP manually." - exit 1 - fi -fi -echo " Tailscale IP: $TS_IP" -echo " ser2net will bind to: $TS_IP" - -# --- Parse mapping file (skip comments and blank lines) --- -echo "" -echo "--- Parsing mapping file ---" -ENTRIES=() -while IFS= read -r line; do - # Skip comments and blank lines - line="${line%%#*}" - line="$(echo "$line" | xargs)" # trim whitespace - [ -z "$line" ] && continue - ENTRIES+=("$line") - echo " $line" -done < "$MAPPING_FILE" - -if [ "${#ENTRIES[@]}" -eq 0 ]; then - echo "FATAL: no entries found in mapping file." - exit 1 -fi - -echo "" -echo " ${#ENTRIES[@]} console ports configured." - -# ============================================================ -# 1. Generate udev rules -# ============================================================ -echo "" -echo "--- [1/3] Generating udev rules: $UDEV_RULES ---" - -cat > "$UDEV_RULES" <<'UDEV_HEADER' -# Stable symlinks for USB-DB9 console adapters -# Generated by console/generate-config.sh -# DO NOT EDIT — edit mapping.txt and re-run generate-config.sh -# -# These rules pin each adapter to a named symlink based on its physical -# USB port path (ID_PATH), which is stable across reboots regardless of -# enumeration order. This is the fix for the "USB adapters shift on reboot" -# problem. -# -# To find the ID_PATH for a device: -# udevadm info -q all -n /dev/ttyUSBN | grep ID_PATH -UDEV_HEADER - -for entry in "${ENTRIES[@]}"; do - IFS='|' read -r tcp_port name id_path baud comment <<< "$entry" - # Build the full ID_PATH match. The mapping stores a substring like "usb-0:1.5.4.4" - # The actual ID_PATH is like "pci-0000:00:1a.0-usb-0:1.5.4.4:1.0" - # We match on the substring to be portable across PCI bus changes. - { - echo "" - echo "# $name (TCP $tcp_port): $comment" - echo "SUBSYSTEM==\"tty\", ENV{ID_PATH}==\"*$id_path*\", SYMLINK+=\"consoles/$name\"" - } >> "$UDEV_RULES" -done - -echo " Written: $UDEV_RULES" -echo " Symlinks: /dev/consoles/ for each device" - -# ============================================================ -# 2. Generate ser2net.yaml -# ============================================================ -echo "" -echo "--- [2/3] Generating ser2net config: $SER2NET_CONF ---" - -# Backup existing config if not already backed up -if [ -f "$SER2NET_CONF" ] && [ ! -f "${SER2NET_CONF}.orig" ]; then - cp "$SER2NET_CONF" "${SER2NET_CONF}.orig" - echo " Backed up original to ${SER2NET_CONF}.orig" -fi - -{ - echo "%YAML 1.1" - echo "---" - echo "# ser2net configuration for pfv-tsys4 console ports" - echo "# Generated by console/generate-config.sh on $(date)" - echo "#" - echo "# All ports use telnet(rfc2217) accepter so conman and telnet clients" - echo "# negotiate proper telnet binary mode — this prevents CR stripping" - printf '%s\n' "# and stair-stepping on devices that send \\n\\r (LF+CR) line endings." - echo "# Ports bound to Tailscale IP ($TS_IP) for secure remote access." - echo "#" - echo "# Direct telnet: telnet $TS_IP 2001" - echo "# Via conman: conman -f " - echo "" - printf '%s\n' "define: &banner \\r\\nPFV console port \\p device \\d [\\B]\\r\\n\\r\\n" - echo "" - - for entry in "${ENTRIES[@]}"; do - IFS='|' read -r tcp_port name id_path baud comment <<< "$entry" - # ser2net connection block — telnet(rfc2217) accepter so conman and - # telnet clients negotiate proper telnet binary mode. This prevents - # CR stripping that occurs with raw TCP + conman's telnet NVT. - echo "connection: &con${tcp_port}" - echo " accepter: telnet(rfc2217),tcp,${TS_IP},${tcp_port}" - echo " enable: on" - echo " options:" - echo " banner: *banner" - echo " kickolduser: true" - echo " telnet-brk-on-sync: true" - echo " connector: serialdev," - echo " /dev/consoles/${name}," - echo " ${baud},local" - echo "" - done -} > "$SER2NET_CONF" - -echo " Written: $SER2NET_CONF" -echo " ${#ENTRIES[@]} TCP ports configured ($TS_IP:2001-20XX)" - -# ============================================================ -# 3. Write conman console entries directly into conman.conf -# ============================================================ -# conman 0.3.x does NOT support the 'include' directive, so we write -# CONSOLE entries directly into /etc/conman.conf between idempotent markers. -echo "" -echo "--- [3/3] Writing conman consoles into $CONMAN_CONF ---" - -# Ensure logdir exists -mkdir -p "$CONMAN_LOGDIR" 2>/dev/null || true - -# Ensure LOGDIR is set in conman.conf (server-level directive for log file paths) -if ! grep -qiE '^\s*server\s+logdir\s*=' "$CONMAN_CONF" 2>/dev/null; then - # Insert near the top, after the first SERVER directives - sed -i "1i\\server logdir = \"$CONMAN_LOGDIR\"" "$CONMAN_CONF" - echo " Added server logdir = \"$CONMAN_LOGDIR\" to $CONMAN_CONF" -fi - -# Ensure loopback=off so conmand is reachable over Tailscale (not localhost-only) -if ! grep -qiE '^\s*server\s+loopback\s*=' "$CONMAN_CONF" 2>/dev/null; then - sed -i "/^server logdir/a server loopback=off" "$CONMAN_CONF" - echo " Added server loopback=off to $CONMAN_CONF (enables remote access)" -fi - -# Remove any previous auto-generated block (between markers) -# Then append the new block -MARKER_BEGIN="# BEGIN PFV CONSOLE DEFINITIONS (auto-generated — do not edit between markers)" -MARKER_END="# END PFV CONSOLE DEFINITIONS" - -# Strip old block if present -if grep -q "$MARKER_BEGIN" "$CONMAN_CONF" 2>/dev/null; then - sed -i "/$MARKER_BEGIN/,/$MARKER_END/d" "$CONMAN_CONF" - echo " Removed previous console definitions." -fi - -# Append new block -{ - echo "" - echo "$MARKER_BEGIN" - echo "# Generated by console/generate-config.sh on $(date)" - echo "# Each console connects to a ser2net TCP port via telnet protocol." - echo "# ser2net uses telnet(rfc2217) accepter so binary mode is negotiated" - echo "# and CR/LF translation is handled correctly by the telnet NVT layer." - echo "# Access: conman -f " - echo "" - for entry in "${ENTRIES[@]}"; do - IFS='|' read -r tcp_port name id_path baud comment <<< "$entry" - echo "CONSOLE name=\"${name}\" dev=\"${TS_IP}:${tcp_port}\" log=\"${name}.log\" logopts=\"timestamp\"" - done - echo "$MARKER_END" -} >> "$CONMAN_CONF" - -CONSOLE_COUNT=$(grep -c "^CONSOLE " "$CONMAN_CONF" 2>/dev/null || echo 0) -echo " Written $CONSOLE_COUNT CONSOLE entries to $CONMAN_CONF" - -# ============================================================ -# Summary -# ============================================================ -echo "" -echo "============================================" -echo " Configuration generated successfully." -echo "" -echo " Files written:" -echo " $UDEV_RULES ($(wc -l < "$UDEV_RULES") lines)" -echo " $SER2NET_CONF ($(wc -l < "$SER2NET_CONF") lines)" -echo " $CONMAN_CONF (CONSOLE entries appended between markers)" -echo "" -echo " Next steps:" -echo " 1. Reload udev: udevadm control --reload-rules && udevadm trigger" -echo " 2. Restart ser2net: systemctl restart ser2net" -echo " 3. Start conman: systemctl enable --now conmand" -echo " 4. Or run: bash $(basename "$0" .sh | sed 's/generate-config/setup/') .sh" -echo "============================================" diff --git a/console/mapping.txt b/console/mapping.txt deleted file mode 100644 index 4a3fba9..0000000 --- a/console/mapping.txt +++ /dev/null @@ -1,29 +0,0 @@ -# console/mapping.txt — Source of Truth for console port assignments -# -# Format: |||| -# -# Delimiter is | (pipe) because ID_PATH values contain colons. -# -# - tcp_port: TCP port ser2net listens on (also the conman console name suffix) -# - name: Device name (used for /dev/console/ symlink, conman console name) -# - id_path_substring: Stable USB physical path from `udevadm info -q all -n /dev/ttyUSBN | grep ID_PATH` -# These are STABLE across reboots as long as adapters aren't moved -# to different physical USB ports. -# - baud: Serial baud rate (9600n81 = 9600 8N1, no flow control) -# - comment: Free-form description -# -# To RE-MAP after physically moving an adapter: -# 1. Run: bash console/discover.sh (find the new ID_PATH for the device) -# 2. Update the id_path_substring in this file -# 3. Run: bash console/generate-config.sh && udevadm trigger && systemctl restart ser2net conmand -# -2001|pfv-core-sw01|usb-0:1.5.4.4|9600n81|Dell PowerConnect 5448 (core switch) -2002|pfv-tor3-mgmt|usb-0:1.6.3.1|9600n81|Rack 3 management TOR switch -2003|pfv-tor3-stor|usb-0:1.6.3.3.2|9600n81|Rack 3 storage TOR switch -2004|pfv-rrinfra-rtr|usb-0:1.6.3.3.1|9600n81|Cisco router (rrinfra) -2005|pfv-r2-tor-top|usb-0:1.6.3.3.3|9600n81|Rack 2 top-of-rack switch -2006|subodev-torsw|usb-0:1.5.4.1|9600n81|Suborbital device TOR switch -2007|pfv-r2-sw|usb-0:1.6.3.2|9600n81|Rack 2 old Dell switch -# Unassigned (no device detected): -# 2008|spare-1|usb-0:1.6.3.4|9600n81|Empty / spare -# 2009|spare-2|usb-0:1.6.3.3.4|9600n81|Empty / spare diff --git a/console/query-remote.sh b/console/query-remote.sh deleted file mode 100644 index cd539e6..0000000 --- a/console/query-remote.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/bash -# -# console/query-remote.sh — install conman client and connect to a console -# on pfv-tsys4 over Tailscale. -# -# Usage: -# bash console/query-remote.sh # list consoles -# bash console/query-remote.sh pfv-core-sw01 # connect to a console -# -set -euo pipefail - -REMOTE_HOST="${REMOTE_HOST:-pfv-tsys4}" -REMOTE_PORT="${REMOTE_PORT:-7890}" - -echo "============================================" -echo " Conman Remote Console Access" -echo " Server: ${REMOTE_HOST}:${REMOTE_PORT} (Tailscale)" -echo "============================================" - -# --- 1. Install conman client if missing --- -if ! command -v conman >/dev/null 2>&1; then - echo "" - echo "--- Installing conman client ---" - if sudo -n true 2>/dev/null; then - sudo apt-get update -qq && sudo apt-get install -y -qq conman - else - echo " Passwordless sudo not available. Please run:" - echo " sudo apt-get update && sudo apt-get install -y conman" - echo " Then re-run this script." - exit 1 - fi -else - echo " conman client already installed." -fi - -# --- 2. Verify connectivity --- -echo "" -echo "--- Connectivity check ---" -if timeout 3 bash -c "echo > /dev/tcp/${REMOTE_HOST}/${REMOTE_PORT}" 2>/dev/null; then - echo " [OK] ${REMOTE_HOST}:${REMOTE_PORT} reachable" -else - echo " [FAIL] Cannot reach ${REMOTE_HOST}:${REMOTE_PORT}" - echo " Is Tailscale up? Is conmand running on ${REMOTE_HOST}?" - exit 1 -fi - -# --- 3. List or connect --- -CONSOLE="${1:-}" -if [ -z "$CONSOLE" ]; then - echo "" - echo "--- Available consoles ---" - conman -d "${REMOTE_HOST}:${REMOTE_PORT}" -q - echo "" - echo "To connect: bash $0 " - echo " e.g: bash $0 pfv-core-sw01" -else - echo "" - echo "--- Connecting to: $CONSOLE ---" - echo " Escape sequence: &. (to disconnect)" - echo "" - conman -d "${REMOTE_HOST}:${REMOTE_PORT}" -f "$CONSOLE" -fi diff --git a/console/setup.sh b/console/setup.sh deleted file mode 100644 index 5da0536..0000000 --- a/console/setup.sh +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/bash -# shellcheck disable=SC2010 # diagnostic; ls|grep on /dev listing is intentional -# -# console/setup.sh — deploy console management on pfv-tsys4 -# -# Orchestrates the full setup: -# 1. Ensures ser2net + conman are installed -# 2. Copies mapping.txt to the target host (if running remotely) -# 3. Runs generate-config.sh to produce udev rules + ser2net.yaml + conman.conf -# 4. Reloads udev, creates /dev/consoles/ symlinks -# 5. Restarts ser2net (TCP ports on Tailscale IP) -# 6. Enables + starts conmand (logging + multiplexing) -# 7. Verifies -# -# This script is IDEMPOTENT — safe to run multiple times. -# -# Usage: -# PROX_HOST=pfv-tsys4 bash tests/remote.sh prox-file console/setup.sh -# -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" - -echo "============================================" -echo " Console Management Setup" -echo " Host: $(hostname) $(date)" -echo "============================================" - -# --- 1. Install dependencies --- -echo "" -echo "--- [1/7] Checking dependencies ---" -NEED_INSTALL=() -dpkg -l ser2net 2>/dev/null | grep -q '^ii' && echo " ser2net: installed" || NEED_INSTALL+=(ser2net) -dpkg -l conman 2>/dev/null | grep -q '^ii' && echo " conman: installed" || NEED_INSTALL+=(conman) - -if [ "${#NEED_INSTALL[@]}" -gt 0 ]; then - echo " Installing: ${NEED_INSTALL[*]}" - apt-get update -qq - apt-get install -y -qq "${NEED_INSTALL[@]}" -else - echo " All dependencies present." -fi - -# --- 2. Ensure mapping file is available --- -echo "" -echo "--- [2/7] Locating mapping file ---" - -MAPPING_FILE="" -for candidate in \ - "$SCRIPT_DIR/mapping.txt" \ - "$(dirname "$0")/mapping.txt" \ - "/root/console/mapping.txt" \ - "/tmp/mapping.txt"; do - if [ -f "$candidate" ]; then - MAPPING_FILE="$candidate" - break - fi -done - -if [ -z "$MAPPING_FILE" ]; then - echo "FATAL: mapping.txt not found. Copy it to the target host." - exit 1 -fi -echo " Using: $MAPPING_FILE" - -# --- 3. Generate configs --- -echo "" -echo "--- [3/7] Generating configs ---" -export MAPPING_FILE -bash "$(dirname "$0")/generate-config.sh" 2>&1 || bash "$SCRIPT_DIR/generate-config.sh" 2>&1 || { - echo "FATAL: generate-config.sh failed." - exit 1 -} - -# --- 4. Reload udev + create symlinks --- -echo "" -echo "--- [4/7] Reloading udev rules ---" -udevadm control --reload-rules -# Try trigger first (works on some systems) -for tty in /sys/class/tty/ttyUSB*; do - [ -e "$tty" ] && udevadm trigger --action=add "$tty" 2>/dev/null || true -done -# Also try writing to uevent (forces udev reprocessing) -for tty in /sys/class/tty/ttyUSB*; do - [ -e "$tty/uevent" ] && echo "add" > "$tty/uevent" 2>/dev/null || true -done -sleep 2 - -# FALLBACK: if udev symlinks don't exist (common when devices are already -# discovered — udev trigger doesn't always re-create symlinks for existing -# devices), create them manually by matching ID_PATH. The udev rules will -# handle future boots/hotplugs automatically. -if [ ! -d /dev/consoles ] || [ -z "$(ls /dev/consoles/ 2>/dev/null)" ]; then - echo " udev trigger didn't create symlinks. Creating manually..." - mkdir -p /dev/consoles - while IFS= read -r line; do - line="${line%%#*}" - line="$(echo "$line" | xargs)" - [ -z "$line" ] && continue - IFS='|' read -r _ name id_path _ _ <<< "$line" - # Find the ttyUSB whose ID_PATH contains the mapping's id_path substring - for tty in /dev/ttyUSB*; do - [ -e "$tty" ] || continue - DEV_IDPATH=$(udevadm info -q property -n "$tty" 2>/dev/null | grep ^ID_PATH= | cut -d= -f2) - if echo "$DEV_IDPATH" | grep -q "$id_path"; then - ln -sf "$tty" "/dev/consoles/$name" - echo " ln -s $tty -> /dev/consoles/$name" - break - fi - done - done < "$MAPPING_FILE" -fi - -echo " Stable symlinks:" -ls -la /dev/consoles/ 2>/dev/null | grep -v '^total\|^d' | sed 's/^/ /' || echo " (none created)" - -# Verify each symlink resolves -echo "" -echo " Symlink verification:" -while IFS= read -r line; do - line="${line%%#*}" - line="$(echo "$line" | xargs)" - [ -z "$line" ] && continue - IFS='|' read -r _ name id_path _ _ <<< "$line" - if [ -e "/dev/consoles/$name" ]; then - TARGET=$(readlink -f "/dev/consoles/$name") - echo " [OK] /dev/consoles/$name -> $TARGET" - else - echo " [MISSING] /dev/consoles/$name (adapter unplugged or ID_PATH changed)" - fi -done < "$MAPPING_FILE" - -# --- 5. Restart ser2net --- -echo "" -echo "--- [5/7] Restarting ser2net ---" -systemctl enable ser2net -systemctl restart ser2net -sleep 2 - -if systemctl is-active --quiet ser2net; then - echo " ser2net is running (telnet rfc2217 accepters)." - TS_IP=$(tailscale ip -4 2>/dev/null || echo "127.0.0.1") - echo " Listening ports:" - ss -tlnp | grep ser2net | grep -oE "${TS_IP}:[0-9]+" | sort -t: -k2 -n | sed 's/^/ /' -else - echo " WARNING: ser2net failed to start. Checking journal..." - journalctl -u ser2net --no-pager -n 20 -fi - -# --- 6. Enable + start conmand --- -echo "" -echo "--- [6/7] Starting conmand ---" - -# conman package on Debian may not ship a systemd unit. Create one if missing. -if ! systemctl cat conmand >/dev/null 2>&1; then - echo " No systemd unit for conmand — creating one..." - cat > /etc/systemd/system/conmand.service <<'CONMAND_UNIT' -[Unit] -Description=ConMan (Console Manager) -After=network.target ser2net.service -Requires=ser2net.service - -[Service] -Type=forking -ExecStart=/usr/sbin/conmand -c /etc/conman.conf -Restart=on-failure -RestartSec=5 - -[Install] -WantedBy=multi-user.target -CONMAND_UNIT - systemctl daemon-reload - echo " Created /etc/systemd/system/conmand.service" -fi - -# Kill any manually-started conmand first -pkill -x conmand 2>/dev/null || true -sleep 1 - -systemctl enable conmand 2>/dev/null || true -systemctl restart conmand 2>/dev/null || true -sleep 2 - -if systemctl is-active --quiet conmand; then - echo " conmand is running." - echo " Consoles:" - conman -q 2>&1 | sed 's/^/ /' || true -else - echo " WARNING: conmand failed to start. Checking journal..." - journalctl -u conmand --no-pager -n 20 2>/dev/null || true - # Try manual start as fallback - echo " Attempting manual start..." - /usr/sbin/conmand -c /etc/conman.conf 2>&1 || true -fi - -# --- 7. Summary --- -echo "" -echo "--- [7/7] Setup complete ---" -echo "" -echo " ser2net + conman architecture (telnet rfc2217):" -echo " ser2net owns serial devices, exposes telnet(rfc2217) TCP ports" -echo " conman connects via telnet for logging + multiplexing" -echo "" -echo " Connect from any Tailscale workstation:" -echo " conman -d pfv-tsys4:7890 -f pfv-core-sw01" -echo " conman -d pfv-tsys4:7890 -q # list consoles" -echo "" -echo " Direct telnet (emergency, conflicts with conman):" -echo " ssh pfv-tsys4 'systemctl stop conmand'" -echo " telnet pfv-tsys4 2001" -echo " ssh pfv-tsys4 'systemctl start conmand'" -echo "" -echo " To regenerate after changing mapping.txt:" -echo " bash generate-config.sh" -echo " udevadm trigger" -echo " systemctl restart ser2net conmand" -echo "============================================" diff --git a/console/validate-conman.sh b/console/validate-conman.sh deleted file mode 100644 index 10f1c00..0000000 --- a/console/validate-conman.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/bash -# shellcheck disable=SC2012,SC2001 # diagnostic script; ls -la listings and sed line-prefixing are intentional -# -# console/validate-conman.sh — verify conman can actually reach devices via -# ser2net TCP ports and is capturing log output to files. -# -# This tests the real data path: conman → TCP 200X → ser2net → /dev/consoles/X → device -# -set -uo pipefail - -TS_IP=$(tailscale ip -4) -LOGDIR="/var/log/conman" - -echo "============================================" -echo " Conman Data Path + Log Validation" -echo " Host: $(hostname) TS IP: $TS_IP" -echo "============================================" - -echo "" -echo "--- 1. conman.conf log settings ---" -grep -E "logdir|LOGDIR|^GLOBAL LOG" /etc/conman.conf 2>/dev/null | grep -v "^#" || echo " (no explicit logdir — defaults to /var/log/conman)" -echo " Log dir: $LOGDIR" -ls -la "$LOGDIR"/ 2>/dev/null | head -15 || echo " ($LOGDIR does not exist yet)" - -echo "" -echo "--- 2. CONSOLE entries: each has a log= directive? ---" -# Extract the auto-generated block and check each CONSOLE line has log= -sed -n '/BEGIN PFV CONSOLE/,/END PFV CONSOLE/p' /etc/conman.conf | grep "^CONSOLE" | while read -r line; do - name=$(echo "$line" | sed -n 's/.*name="\([^"]*\)".*/\1/p') - if echo "$line" | grep -q 'log='; then - logfile=$(echo "$line" | sed -n 's/.*log="\([^"]*\)".*/\1/p') - echo " [OK] $name → log=$logfile" - else - echo " [FAIL] $name has NO log= directive" - fi -done - -echo "" -echo "--- 3. Trigger log capture: connect to each console briefly ---" -# conman -e changes the escape char. We use -j (join, read-only) with a timeout. -# Actually, conman doesn't have a built-in "connect for N seconds" — but conmand -# connects to each device ON STARTUP and keeps the connection open for logging. -# The log files should already be created. Let's check timestamps. - -echo " conmand connects to all consoles on startup. Checking if logs exist..." -echo "" -echo "--- 4. Log file inventory ---" -for name in pfv-core-sw01 pfv-tor3-mgmt pfv-tor3-stor pfv-rrinfra-rtr pfv-r2-tor-top subodev-torsw pfv-r2-sw; do - logfile="$LOGDIR/${name}.log" - if [ -f "$logfile" ]; then - SIZE=$(stat -c%s "$logfile" 2>/dev/null || echo 0) - MTIME=$(stat -c%y "$logfile" 2>/dev/null | cut -d. -f1) - echo " [OK] $logfile ($SIZE bytes, modified $MTIME)" - else - echo " [MISSING] $logfile — conmand may not be writing yet" - fi -done - -echo "" -echo "--- 5. conmand connection status (journal) ---" -# conmand logs connection attempts/errors to syslog -journalctl -u conmand --no-pager -n 50 2>/dev/null | grep -iE "connect|error|fail|console|refused|timeout" | tail -15 || echo " (no relevant journal entries)" - -echo "" -echo "--- 6. Verify ser2net is proxying data (telnet rfc2217) ---" -echo " Probing TCP $TS_IP:2007 for data..." -RESPONSE=$(timeout 3 bash -c "printf '\r\r' | nc -w 2 $TS_IP 2007 2>/dev/null" | tr -cd '[:print:][:space:]' | head -5) -if [ -n "$RESPONSE" ]; then - echo " [OK] Data flowing through ser2net TCP 2007:" - echo "$RESPONSE" | sed 's/^/ /' -else - echo " (no immediate response — device may need more interaction)" -fi - -echo "" -echo "--- 7. Check if conmand has open connections to ser2net ports ---" -CONMAND_PID=$(pgrep -x conmand 2>/dev/null || echo "") -if [ -n "$CONMAND_PID" ]; then - echo " conmand PID: $CONMAND_PID" - echo " Open connections to ser2net (expect 7 to 100.x:200X):" - ss -tnp 2>/dev/null | grep "pid=$CONMAND_PID" | grep -oE "100\.[0-9.]+:200[0-9]" | sort | sed 's/^/ /' - COUNT=$(ss -tnp 2>/dev/null | grep "pid=$CONMAND_PID" | grep -c ":200") - echo " Total conmand→ser2net connections: $COUNT (expect 7)" -else - echo " [FAIL] conmand not running" -fi - -echo "" -echo "============================================" diff --git a/dns-cluster-setup/README.md b/dns-cluster-setup/README.md deleted file mode 100644 index 244bf11..0000000 --- a/dns-cluster-setup/README.md +++ /dev/null @@ -1,183 +0,0 @@ -# Technitium DNS Cluster Setup - -Replicates the production Technitium DNS Server from `tailscale-router` to the -`pfv-netinfra-01/02` pair and configures them as a primary/secondary cluster -with automatic zone transfers. - -## Architecture - -``` - tailscale-router (PRODUCTION — READ ONLY) - └─ tsys-dns container (technitium/dns-server) - └─ 124 zones (knel.net + reverse DNS) - └─ Users + 2FA in auth.config - │ - docker cp (export) - │ - ▼ - ┌─ pfv-netinfra-01 (192.168.3.252) ──── PRIMARY ──────────┐ - │ tsys-dns container (Technitium on :5300) │ - │ pihole container (Pi-hole on :53 → Technitium :5300) │ - │ All zones are Primary │ - │ Zone transfer allowed from 192.168.3.253 │ - └──────────────────────────────────────────────────────────┘ - │ - AXFR / IXFR + NOTIFY (DNS zone transfer, port 5300) - │ - ▼ - ┌─ pfv-netinfra-02 (192.168.3.253) ─── SECONDARY ────────┐ - │ tsys-dns container (Technitium on :5300) │ - │ pihole container (Pi-hole on :53 → Technitium :5300) │ - │ All zones are Secondary (AXFR from 01) │ - └──────────────────────────────────────────────────────────┘ -``` - -### How clustering works - -Technitium uses standard DNS zone transfers (AXFR/IXFR) for primary/secondary -replication, not a proprietary protocol: - -1. **Primary (01)** holds all zones as authoritative primary zones. -2. **Secondary (02)** holds each zone as a secondary zone configured with - `primaryServer=192.168.3.252:5300`. -3. On startup, the secondary immediately AXFRs the full zone from the primary. -4. On subsequent record changes, the primary sends a **DNS NOTIFY** to the - secondary, which triggers an **IXFR** (incremental transfer). -5. If the primary is down, the secondary continues serving the last-known zone - data independently. - -### Credentials and 2FA - -The production `auth.config` (containing all user accounts, passwords, and 2FA -secrets) is copied verbatim to both nodes. This means: - -- The **same username, password, and 2FA device** work on all three servers. -- The web console is at `http://:5380/` on each node. -- No credential changes are needed. - -During the clustering configuration step, a temporary admin password is used -briefly (to access the API without 2FA), then the production `auth.config` is -restored. See "Security notes" below. - -## Prerequisites - -- SSH key access to all hosts as `localuser` with passwordless sudo. -- The `remote-dns.sh` wrapper must be able to reach all hosts via Tailscale FQDN. -- Docker + Docker Compose on netinfra-01/02 (already installed). -- The production Technitium on tailscale-router must be running. - -## Usage - -```bash -cd dns-cluster-setup/ - -# Step-by-step (recommended for first run): -./setup.sh export # 1. Export config from tailscale-router (READ-ONLY) -./setup.sh deploy01 # 2. Deploy to netinfra-01 as primary -./setup.sh deploy02 # 3. Deploy to netinfra-02 as secondary clone -./setup.sh cluster # 4. Configure clustering (01→02 zone transfers) -./setup.sh verify # 5. Run all verification tests - -# Or all at once: -./setup.sh all -``` - -### Configuration overrides - -All defaults can be overridden via environment variables: - -| Variable | Default | Description | -|---|---|---| -| `PRIMARY_IP` | `192.168.3.252` | netinfra-01 LAN IP | -| `SECONDARY_IP` | `192.168.3.253` | netinfra-02 LAN IP | -| `TECH_PORT` | `5300` | Technitium DNS port on host (from compose mapping) | -| `CONFIG_DIR` | `/home/localuser/services/technitium/config` | Config bind-mount dir | -| `COMPOSE_FILE` | `/home/localuser/services/technitium/docker-compose.yml` | Compose file | -| `TEMP_ADMIN_PW` | `KnelClusterSetup!2026` | Temp admin password (used only during clustering, then discarded) | - -## Scripts - -| Script | Purpose | -|---|---| -| `remote-dns.sh` | SSH/SCP chokepoint for all DNS host access (tsrouter, netinfra01, netinfra02, netboot, sandbox) | -| `setup.sh` | Master orchestrator: export → deploy → cluster → verify | -| `verify.sh` | Comprehensive 10-section verification suite | -| `discover*.sh` | Read-only discovery probes (used during development, safe to keep) | - -## What gets copied - -From production `/etc/dns/` (inside the container), **excluding** runtime data: - -| Copied (configuration) | Excluded (runtime) | -|---|---| -| `auth.config` (users, passwords, 2FA) | `cache.bin` (DNS cache) | -| `dns.config` (server settings) | `stats/` (query statistics) | -| `webservice.config` (web console) | `logs/` (log files) | -| `allowed.config` (zone transfer ACL) | | -| `blocked.config` (blocked domains) | | -| `blocklist.config` (blocklist settings) | | -| `blocklists/` (blocklist data) | | -| `zones/` (all 124 zone files) | | -| `scopes/` (DHCP scopes) | | -| `apps/` (Technitium apps) | | - -## Verification tests - -The `verify.sh` script runs 10 categories of tests: - -1. **Container health** — both Technitium containers are Up -2. **API responds** — web console API is reachable on both nodes -3. **Zone count** — primary matches production; secondary matches primary -4. **Forward DNS** — known knel.net records resolve identically on both nodes -5. **External DNS** — both nodes can resolve external domains (github.com) -6. **Zone transfer (AXFR)** — secondary can AXFR knel.net from primary -7. **Reverse DNS** — PTR zones have SOA records on both nodes -8. **Production untouched** — container still running, zone count unchanged -9. **Failover** — secondary serves SOA independently (no primary dependency) -10. **Credentials** — `auth.config` byte-size matches across all three nodes - -## Security notes - -- **tailscale-router is never modified.** The only operation is `docker cp` - (read) to export the config. No writes, no restarts, no config changes. -- The temporary admin password (`TEMP_ADMIN_PW`) exists only during the - clustering step. After configuration, the production `auth.config` (with 2FA) - is restored. The temp password is never persisted. -- The export tarball (`.export/technitium-production-config.tar.gz`) contains - production credentials. It is in `.gitignore` and should be deleted after - setup: `rm -rf dns-cluster-setup/.export/` -- Each node's existing config is backed up to `config.backup-` before - replacement, so the change is reversible. - -## Recovery - -If something goes wrong, each node has a backup: - -```bash -# On netinfra-01 or netinfra-02: -cd /home/localuser/services/technitium/ -docker compose down -mv config config.failed -mv config.backup- config -docker compose up -d -``` - -## Validation on sandbox - -After cluster setup, validate that client hosts use the pair correctly: - -```bash -# From sectestbed-sandbox (or any client): -# Query primary directly: -dig @192.168.3.252 pfv-netinfra-01.knel.net - -# Query secondary directly: -dig @192.168.3.253 pfv-netinfra-01.knel.net - -# Both should return the same answer. -``` - -The KNELServerBuild provisioning code (`provisioning/ConfigFiles/NTP/ntp.conf` -and `provisioning/ConfigFiles/Resolv/resolv.conf`) points clients at both -servers for DNS and NTP redundancy. See `docs/server-build/tailscale.md` for the -full DNS architecture analysis. diff --git a/dns-cluster-setup/remote-dns.sh b/dns-cluster-setup/remote-dns.sh deleted file mode 100755 index 39caa84..0000000 --- a/dns-cluster-setup/remote-dns.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/bash -# -# remote-dns.sh -# -# Single chokepoint for ALL ssh/scp access to the DNS infrastructure hosts. -# Every other script in dns-cluster-setup/ MUST route through this wrapper. -# Never call ssh/scp directly. -# -# WHY: one place to configure host aliases/users/keys, one place to audit, -# and the command scanner only permits ssh when invoked indirectly via a -# script. Mirrors the pattern of tests/remote.sh. -# -# HOSTS (override IPs via env if needed): -# tsrouter tailscale-router.knel.net (PRODUCTION — READ-ONLY here) -# netinfra01 pfv-netinfra-01.knel.net (Technitium primary target) -# netinfra02 pfv-netinfra-02.knel.net (Technitium secondary target) -# netboot pfv-netboot.knel.net (reference / validation client) -# sandbox sectestbed-sandbox.knel.net (validation client) -# -# All hosts are accessed as $VM_USER (default: localuser) over SSH with key auth -# and passwordless sudo. -# -# USAGE: -# remote-dns.sh run command on host -# remote-dns.sh -root run command on host as root (sudo) -# remote-dns.sh -file - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - librenms-agent/snmp/ss.py at master · librenms/librenms-agent · GitHub - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- Skip to content - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - -
- -
- - - - - - - - -
- - - - - -
- - - - - - - - - -
-
-
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
-
- - - - -
- -
- -
-
- -
- -
-

Footer

- - - - -
-
- - - - - © 2025 GitHub, Inc. - -
- - -
-
- - - - - - - - - - - - - - - - - - - -
-
-
- - - diff --git a/provisioning/Agents/librenms/ups-nut.sh b/provisioning/Agents/librenms/ups-nut.sh deleted file mode 100644 index b75580a..0000000 --- a/provisioning/Agents/librenms/ups-nut.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh -################################################################ -# Instructions: # -# 1. copy this script to /etc/snmp/ and make it executable: # -# chmod +x ups-nut.sh # -# 2. make sure UPS_NAME below matches the name of your UPS # -# 3. edit your snmpd.conf to include this line: # -# extend ups-nut /etc/snmp/ups-nut.sh # -# 4. restart snmpd on the host # -# 5. activate the app for the desired host in LibreNMS # -################################################################ -UPS_NAME="${1:-APCUPS}" - -PATH=$PATH:/usr/bin:/bin -TMP=$(upsc $UPS_NAME 2>/dev/null) - -for value in "battery\.charge: [0-9.]+" "battery\.(runtime\.)?low: [0-9]+" "battery\.runtime: [0-9]+" "battery\.voltage: [0-9.]+" "battery\.voltage\.nominal: [0-9]+" "input\.voltage\.nominal: [0-9.]+" "input\.voltage: [0-9.]+" "ups\.load: [0-9.]+" -do - OUT=$(echo "$TMP" | grep -Eo "$value" | awk '{print $2}' | LANG=C sort | head -n 1) - if [ -n "$OUT" ]; then - echo "$OUT" - else - echo "Unknown" - fi -done - -for value in "ups\.status:[A-Z ]{0,}OL" "ups\.status:[A-Z ]{0,}OB" "ups\.status:[A-Z ]{0,}LB" "ups\.status:[A-Z ]{0,}HB" "ups\.status:[A-Z ]{0,}RB" "ups\.status:[A-Z ]{0,}CHRG" "ups\.status:[A-Z ]{0,}DISCHRG" "ups\.status:[A-Z ]{0,}BYPASS" "ups\.status:[A-Z ]{0,}CAL" "ups\.status:[A-Z ]{0,}OFF" "ups\.status:[A-Z ]{0,}OVER" "ups\.status:[A-Z ]{0,}TRIM" "ups\.status:[A-Z ]{0,}BOOST" "ups\.status:[A-Z ]{0,}FSD" "ups\.alarm:[A-Z ]" -do - UNKNOWN=$(echo "$TMP" | grep -Eo "ups\.status:") - if [ -z "$UNKNOWN" ]; then - echo "Unknown" - else - OUT=$(echo "$TMP" | grep -Eo "$value") - if [ -n "$OUT" ]; then - echo "1" - else - echo "0" - fi - fi -done - -UPSTEMP="ups\.temperature: [0-9.]+" -OUT=$(echo "$TMP" | grep -Eo "$UPSTEMP" | awk '{print $2}' | LANG=C sort | head -n 1) -[ -n "$OUT" ] && echo "$OUT" || echo "Unknown" - diff --git a/provisioning/ConfigFiles/99-pfv-nfs.conf b/provisioning/ConfigFiles/99-pfv-nfs.conf deleted file mode 100644 index e3ee0b8..0000000 --- a/provisioning/ConfigFiles/99-pfv-nfs.conf +++ /dev/null @@ -1,23 +0,0 @@ -# PFV NFS tuning sysctl overrides -# -# Applied AFTER tuned via pfv-nfs-tuning.service (systemd oneshot). -# These override tuned's network-throughput/virtual-host 16MB TCP buffer -# caps with 128MB for high-BDP NFS over 1-4 GbE LACP links. -# -# Install on ALL Proxmox hosts: -# cp 99-pfv-nfs.conf /etc/sysctl.d/99-pfv-nfs.conf -# cp pfv-nfs-tuning.service /etc/systemd/system/pfv-nfs-tuning.service -# systemctl daemon-reload && systemctl enable --now pfv-nfs-tuning.service -# -# Created: 2026-07-31 -# Deployed: tsys1, tsys3, tsys4, tsys5, tsys6, tsys7, tsys9 - -net.core.rmem_max = 134217728 -net.core.wmem_max = 134217728 -net.core.rmem_default = 26214400 -net.core.wmem_default = 26214400 -net.core.netdev_max_backlog = 250000 -net.core.somaxconn = 65535 -net.ipv4.tcp_rmem = 4096 87380 134217728 -net.ipv4.tcp_wmem = 4096 65536 134217728 -net.ipv4.tcp_max_syn_backlog = 4096 diff --git a/provisioning/ConfigFiles/AuditD/auditd.conf b/provisioning/ConfigFiles/AuditD/auditd.conf deleted file mode 100644 index e1482e3..0000000 --- a/provisioning/ConfigFiles/AuditD/auditd.conf +++ /dev/null @@ -1,46 +0,0 @@ -# -# Known Element Enterprises Customized Config File -# auditd -# Initial version 2025-06-27 -# - -local_events = yes -write_logs = yes -log_file = /var/log/audit/audit.log -log_group = adm -log_format = ENRICHED -flush = INCREMENTAL_ASYNC -freq = 50 -max_log_file = 8 -num_logs = 5 -priority_boost = 4 -name_format = NONE -max_log_file_action = keep_logs -space_left = 75 -space_left_action = email -action_mail_acct = root - -admin_space_left_action = halt -disk_full_action = SUSPEND -disk_error_action = SUSPEND -admin_space_left = 50 - -verify_email = yes -use_libwrap = yes -tcp_listen_queue = 5 -tcp_max_per_addr = 1 -tcp_client_max_idle = 0 -transport = TCP -distribute_network = no -q_depth = 2000 -overflow_action = SYSLOG -max_restarts = 10 -plugin_dir = /etc/audit/plugins.d -end_of_event_timeout = 2 -##tcp_client_ports = 1024-65535 -##tcp_listen_port = 60 - -##krb5_key_file = /etc/audit/audit.key -krb5_principal = auditd - -##name = mydomain diff --git a/provisioning/ConfigFiles/AuditD/rules.d/time-change.rules b/provisioning/ConfigFiles/AuditD/rules.d/time-change.rules deleted file mode 100644 index e69de29..0000000 diff --git a/provisioning/ConfigFiles/BANNERS/issue b/provisioning/ConfigFiles/BANNERS/issue deleted file mode 100644 index 42b3729..0000000 --- a/provisioning/ConfigFiles/BANNERS/issue +++ /dev/null @@ -1,5 +0,0 @@ -This system is the property of Known Element Enterprises LLC. - -Authorized uses only. All activity may be monitored and reported. - -All activities subject to monitoring/recording/review in real time and/or at a later time. diff --git a/provisioning/ConfigFiles/BANNERS/issue.net b/provisioning/ConfigFiles/BANNERS/issue.net deleted file mode 100644 index 42b3729..0000000 --- a/provisioning/ConfigFiles/BANNERS/issue.net +++ /dev/null @@ -1,5 +0,0 @@ -This system is the property of Known Element Enterprises LLC. - -Authorized uses only. All activity may be monitored and reported. - -All activities subject to monitoring/recording/review in real time and/or at a later time. diff --git a/provisioning/ConfigFiles/BANNERS/motd b/provisioning/ConfigFiles/BANNERS/motd deleted file mode 100644 index 42b3729..0000000 --- a/provisioning/ConfigFiles/BANNERS/motd +++ /dev/null @@ -1,5 +0,0 @@ -This system is the property of Known Element Enterprises LLC. - -Authorized uses only. All activity may be monitored and reported. - -All activities subject to monitoring/recording/review in real time and/or at a later time. diff --git a/provisioning/ConfigFiles/Cockpit/disallowed-users b/provisioning/ConfigFiles/Cockpit/disallowed-users deleted file mode 100644 index 7c07810..0000000 --- a/provisioning/ConfigFiles/Cockpit/disallowed-users +++ /dev/null @@ -1,2 +0,0 @@ -#/etc/cockpit/disallowed-users -# List of users which are not allowed to login to Cockpit diff --git a/provisioning/ConfigFiles/DHCP/dhclient.conf b/provisioning/ConfigFiles/DHCP/dhclient.conf deleted file mode 100644 index ceee168..0000000 --- a/provisioning/ConfigFiles/DHCP/dhclient.conf +++ /dev/null @@ -1,14 +0,0 @@ -option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; - -send host-name = gethostname(); -request subnet-mask, broadcast-address, time-offset, routers, - domain-name, host-name, - domain-name-servers, domain-search, ntp-servers, - rfc3442-classless-static-routes; - -# Pin DNS and NTP to the redundant pfv-netinfra-01/02 pair regardless of what -# the DHCP server advertises, so every host on this build uses the same -# authoritative recursive resolvers and time sources. -supersede domain-name-servers 192.168.3.252, 192.168.3.253; -supersede domain-search "knel.net"; -supersede ntp-servers 192.168.3.252, 192.168.3.253; diff --git a/provisioning/ConfigFiles/Logrotate/logrotate.conf b/provisioning/ConfigFiles/Logrotate/logrotate.conf deleted file mode 100644 index 9f2f271..0000000 --- a/provisioning/ConfigFiles/Logrotate/logrotate.conf +++ /dev/null @@ -1,23 +0,0 @@ -# see "man logrotate" for details - -# global options do not affect preceding include directives - -# rotate log files weekly -weekly - -# keep 4 weeks worth of backlogs -rotate 4 - -# create new (empty) log files after rotating old ones -create 0640 root utmp - -# use date as a suffix of the rotated file -#dateext - -# uncomment this if you want your log files compressed -#compress - -# packages drop log rotation information into this directory -include /etc/logrotate.d - -# system-specific logs may also be configured here. diff --git a/provisioning/ConfigFiles/ModProbe/cramfs.conf b/provisioning/ConfigFiles/ModProbe/cramfs.conf deleted file mode 100644 index b77c93a..0000000 --- a/provisioning/ConfigFiles/ModProbe/cramfs.conf +++ /dev/null @@ -1 +0,0 @@ -install cramfs /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/dccp.conf b/provisioning/ConfigFiles/ModProbe/dccp.conf deleted file mode 100644 index d453550..0000000 --- a/provisioning/ConfigFiles/ModProbe/dccp.conf +++ /dev/null @@ -1 +0,0 @@ -install dccp /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/freevxfs.conf b/provisioning/ConfigFiles/ModProbe/freevxfs.conf deleted file mode 100644 index 72d4aec..0000000 --- a/provisioning/ConfigFiles/ModProbe/freevxfs.conf +++ /dev/null @@ -1 +0,0 @@ -install freevxfs /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/hfs.conf b/provisioning/ConfigFiles/ModProbe/hfs.conf deleted file mode 100644 index a991f49..0000000 --- a/provisioning/ConfigFiles/ModProbe/hfs.conf +++ /dev/null @@ -1 +0,0 @@ -install hfs /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/hfsplus.conf b/provisioning/ConfigFiles/ModProbe/hfsplus.conf deleted file mode 100644 index 9cba83f..0000000 --- a/provisioning/ConfigFiles/ModProbe/hfsplus.conf +++ /dev/null @@ -1 +0,0 @@ -install hfsplus /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/jffs2.conf b/provisioning/ConfigFiles/ModProbe/jffs2.conf deleted file mode 100644 index 63360f3..0000000 --- a/provisioning/ConfigFiles/ModProbe/jffs2.conf +++ /dev/null @@ -1 +0,0 @@ -install jffs2 /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/rds.conf b/provisioning/ConfigFiles/ModProbe/rds.conf deleted file mode 100644 index 650abee..0000000 --- a/provisioning/ConfigFiles/ModProbe/rds.conf +++ /dev/null @@ -1 +0,0 @@ -install rds /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/sctp.conf b/provisioning/ConfigFiles/ModProbe/sctp.conf deleted file mode 100644 index 960a200..0000000 --- a/provisioning/ConfigFiles/ModProbe/sctp.conf +++ /dev/null @@ -1 +0,0 @@ -install sctp /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/squashfs.conf b/provisioning/ConfigFiles/ModProbe/squashfs.conf deleted file mode 100644 index c177037..0000000 --- a/provisioning/ConfigFiles/ModProbe/squashfs.conf +++ /dev/null @@ -1 +0,0 @@ -install squashfs /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/tipc.conf b/provisioning/ConfigFiles/ModProbe/tipc.conf deleted file mode 100644 index 260e2ad..0000000 --- a/provisioning/ConfigFiles/ModProbe/tipc.conf +++ /dev/null @@ -1 +0,0 @@ -install tipc /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/udf.conf b/provisioning/ConfigFiles/ModProbe/udf.conf deleted file mode 100644 index 4894688..0000000 --- a/provisioning/ConfigFiles/ModProbe/udf.conf +++ /dev/null @@ -1 +0,0 @@ -install udf /bin/true diff --git a/provisioning/ConfigFiles/ModProbe/usb_storage.conf b/provisioning/ConfigFiles/ModProbe/usb_storage.conf deleted file mode 100644 index 38a1e49..0000000 --- a/provisioning/ConfigFiles/ModProbe/usb_storage.conf +++ /dev/null @@ -1 +0,0 @@ -install usb-storage /bin/true diff --git a/provisioning/ConfigFiles/NTP/ntp.conf b/provisioning/ConfigFiles/NTP/ntp.conf deleted file mode 100644 index 717fcb1..0000000 --- a/provisioning/ConfigFiles/NTP/ntp.conf +++ /dev/null @@ -1,21 +0,0 @@ -driftfile /var/lib/ntp/ntp.drift -leapfile /usr/share/zoneinfo/leap-seconds.list - -# Redundant upstream time sources: pfv-netinfra-01/02 (Technitium/Pi-hole hosts -# also serving NTP). IPs are used (not hostnames) because the knel.net name for -# these hosts resolves to a Tailscale CGNAT address, not the LAN address, and -# because NTP must come up before DNS is available. iburst speeds initial sync. -server 192.168.3.252 iburst -server 192.168.3.253 iburst - -# Hardened client: sync from the configured servers but never serve time to -# anyone else. Note: `interface listen 127.0.0.1` must NOT be used here — it -# binds ntpd to loopback, making outbound queries carry a 127.0.0.1 source -# address that upstream servers cannot reply to (symptoms: peers stuck in -# .INIT. with reach 0). Use restrict rules to control access instead. -restrict default ignore -restrict 127.0.0.1 -restrict ::1 -restrict 192.168.3.252 nomodify notrap nopeer -restrict 192.168.3.253 nomodify notrap nopeer - diff --git a/provisioning/ConfigFiles/NetworkDiscovery/lldpd b/provisioning/ConfigFiles/NetworkDiscovery/lldpd deleted file mode 100644 index b98df83..0000000 --- a/provisioning/ConfigFiles/NetworkDiscovery/lldpd +++ /dev/null @@ -1,2 +0,0 @@ -# Uncomment to start SNMP subagent and enable CDP, SONMP and EDP protocol -DAEMON_ARGS="-x -c -s -e" diff --git a/provisioning/ConfigFiles/Resolv/resolv.conf b/provisioning/ConfigFiles/Resolv/resolv.conf deleted file mode 100644 index 8728c3f..0000000 --- a/provisioning/ConfigFiles/Resolv/resolv.conf +++ /dev/null @@ -1,11 +0,0 @@ -# Managed by KNELServerBuild — do not edit; changes will be overwritten. -# -# Redundant recursive DNS via pfv-netinfra-01/02 (Technitium + Pi-hole). -# IPs are used (required: nameserver directives must be addresses, and the -# knel.net name for these hosts resolves to a Tailscale CGNAT address rather -# than the LAN address). If the primary is unreachable, glibc's resolver -# automatically falls through to the secondary. -domain knel.net -search knel.net -nameserver 192.168.3.252 -nameserver 192.168.3.253 diff --git a/provisioning/ConfigFiles/SMTP/aliases b/provisioning/ConfigFiles/SMTP/aliases deleted file mode 100644 index 799fcb9..0000000 --- a/provisioning/ConfigFiles/SMTP/aliases +++ /dev/null @@ -1,3 +0,0 @@ -# See man 5 aliases for format -postmaster: root -root: coo@turnsys.com diff --git a/provisioning/ConfigFiles/SMTP/postfix_generic b/provisioning/ConfigFiles/SMTP/postfix_generic deleted file mode 100644 index 996fa4f..0000000 --- a/provisioning/ConfigFiles/SMTP/postfix_generic +++ /dev/null @@ -1 +0,0 @@ -/.*/ tsysrootaccount@knel.net diff --git a/provisioning/ConfigFiles/SNMP/snmp-sudo.conf b/provisioning/ConfigFiles/SNMP/snmp-sudo.conf deleted file mode 100644 index 3ce5fd3..0000000 --- a/provisioning/ConfigFiles/SNMP/snmp-sudo.conf +++ /dev/null @@ -1 +0,0 @@ -Debian-snmp ALL = NOPASSWD: /bin/cat diff --git a/provisioning/ConfigFiles/SNMP/snmpd-physicalhost.conf b/provisioning/ConfigFiles/SNMP/snmpd-physicalhost.conf deleted file mode 100644 index b8cb71f..0000000 --- a/provisioning/ConfigFiles/SNMP/snmpd-physicalhost.conf +++ /dev/null @@ -1,46 +0,0 @@ -########################################################################## -# snmpd.conf -# Created by CNW on 11/3/2018 via snmpconf wizard and manual post tweaks -########################################################################### -# SECTION: Monitor Various Aspects of the Running Host -# - -# disk: Check for disk space usage of a partition. -# The agent can check the amount of available disk space, and make -# sure it is above a set limit. -# -load 3 3 3 -rocommunity kn3lmgmt -sysservices 76 - -#syslocation Rack, Room, Building, City, Country [Lat, Lon] -syslocation R4, Server Room, SITER, Pflugerville, United States -syscontact coo@turnsys.com - -#NTP -extend ntp-client /usr/lib/check_mk_agent/local/ntp-client - -#SMTP -extend mailq /usr/lib/check_mk_agent/local/postfix-queues -extend postfixdetailed /usr/lib/check_mk_agent/local/postfixdetailed - -#OS Distribution Detection -extend distro /usr/local/bin/distro -extend osupdate /usr/lib/check_mk_agent/local/os-updates.sh - -#Hardware Detection -extend manufacturer /usr/bin/sudo /usr/bin/cat /sys/devices/virtual/dmi/id/sys_vendor -extend hardware /usr/bin/sudo /usr/bin/cat /sys/devices/virtual/dmi/id/product_name -extend serial /usr/bin/sudo /usr/bin/cat /sys/devices/virtual/dmi/id/product_serial - -#SMART -extend smart /usr/lib/check_mk_agent/local/smart - -#Temperature -pass_persist .1.3.6.1.4.1.9.9.13.1.3 /usr/local/bin/temper-snmp - -# Allow Systems Management Data Engine SNMP to connect to snmpd using SMUX -# smuxpeer .1.3.6.1.4.1.674.10892.1 - -# LLDP collection -master agentx diff --git a/provisioning/ConfigFiles/SNMP/snmpd-rpi.conf b/provisioning/ConfigFiles/SNMP/snmpd-rpi.conf deleted file mode 100644 index 4e98bf8..0000000 --- a/provisioning/ConfigFiles/SNMP/snmpd-rpi.conf +++ /dev/null @@ -1,40 +0,0 @@ -########################################################################## -# snmpd.conf -# Created by CNW on 11/3/2018 via snmpconf wizard and manual post tweaks -########################################################################### -# SECTION: Monitor Various Aspects of the Running Host -# - -# disk: Check for disk space usage of a partition. -# The agent can check the amount of available disk space, and make -# sure it is above a set limit. -# -load 3 3 3 -rocommunity kn3lmgmt -sysservices 76 - -#syslocation Rack, Room, Building, City, Country [Lat, Lon] -syslocation SITER, Pflugerville, United States -syscontact coo@turnsys.com - -#NTP -extend ntp-client /usr/lib/check_mk_agent/local/ntp-client - -#SMTP -extend mailq /usr/lib/check_mk_agent/local/postfix-queues -extend postfixdetailed /usr/lib/check_mk_agent/local/postfixdetailed - -#OS Distribution Detection -extend distro /usr/local/bin/distro -extend osupdate /usr/lib/check_mk_agent/local/os-updates.sh - - -#Hardware Detection -extend hardware /usr/bin/sudo /usr/bin/cat /sys/firmware/devicetree/base/model -extend serial /usr/bin/sudo /usr/bin/cat /sys/firmware/devicetree/base/serial-number - -# Allow Systems Management Data Engine SNMP to connect to snmpd using SMUX -# smuxpeer .1.3.6.1.4.1.674.10892.1 - -# LLDP collection -master agentx diff --git a/provisioning/ConfigFiles/SNMP/snmpd.conf b/provisioning/ConfigFiles/SNMP/snmpd.conf deleted file mode 100644 index 8ae8ab4..0000000 --- a/provisioning/ConfigFiles/SNMP/snmpd.conf +++ /dev/null @@ -1,44 +0,0 @@ -########################################################################## -# snmpd.conf -# Created by CNW on 11/3/2018 via snmpconf wizard and manual post tweaks -########################################################################### -# SECTION: Monitor Various Aspects of the Running Host -# - -# disk: Check for disk space usage of a partition. -# The agent can check the amount of available disk space, and make -# sure it is above a set limit. -# -load 3 3 3 -rocommunity kn3lmgmt -sysservices 76 - -#syslocation Rack, Room, Building, City, Country [Lat, Lon] -syslocation R4, Server Room, SITER, Pflugerville, United States -syscontact coo@turnsys.com - -#NTP -extend ntp-client /usr/lib/check_mk_agent/local/ntp-client - -#SMTP -extend mailq /usr/lib/check_mk_agent/local/postfix-queues -extend postfixdetailed /usr/lib/check_mk_agent/local/postfixdetailed - -#OS Distribution Detection -extend distro /usr/local/bin/distro -extend osupdate /usr/lib/check_mk_agent/local/os-updates.sh - -# Socket statistics -extend ss /usr/lib/check_mk_agent/local/ss.py - -#Hardware Detection -# (uncomment for x86 platforms) -extend manufacturer /usr/bin/sudo /usr/bin/cat /sys/devices/virtual/dmi/id/sys_vendor -extend hardware /usr/bin/sudo /usr/bin/cat /sys/devices/virtual/dmi/id/product_name -extend serial /usr/bin/sudo /usr/bin/cat /sys/devices/virtual/dmi/id/product_serial - -# Allow Systems Management Data Engine SNMP to connect to snmpd using SMUX -# smuxpeer .1.3.6.1.4.1.674.10892.1 - -# LLDP collection -master agentx diff --git a/provisioning/ConfigFiles/SSH/AuthorizedKeys/localuser-ssh-authorized-keys b/provisioning/ConfigFiles/SSH/AuthorizedKeys/localuser-ssh-authorized-keys deleted file mode 100644 index 36216a1..0000000 --- a/provisioning/ConfigFiles/SSH/AuthorizedKeys/localuser-ssh-authorized-keys +++ /dev/null @@ -1,2 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDHaBNuLS+GYGRPc9wne63Ocr+R+/Q01Y9V0FTv0RnG3 -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPyMR0lFgiMKhQJ5aqy68nR0BQp1cNzi/wIThyuTV4a8 tsyscto@ultix-control diff --git a/provisioning/ConfigFiles/SSH/AuthorizedKeys/root-ssh-authorized-keys b/provisioning/ConfigFiles/SSH/AuthorizedKeys/root-ssh-authorized-keys deleted file mode 100644 index 36216a1..0000000 --- a/provisioning/ConfigFiles/SSH/AuthorizedKeys/root-ssh-authorized-keys +++ /dev/null @@ -1,2 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDHaBNuLS+GYGRPc9wne63Ocr+R+/Q01Y9V0FTv0RnG3 -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPyMR0lFgiMKhQJ5aqy68nR0BQp1cNzi/wIThyuTV4a8 tsyscto@ultix-control diff --git a/provisioning/ConfigFiles/SSH/Configs/ssh-audit-hardening.conf b/provisioning/ConfigFiles/SSH/Configs/ssh-audit-hardening.conf deleted file mode 100644 index 8e80118..0000000 --- a/provisioning/ConfigFiles/SSH/Configs/ssh-audit-hardening.conf +++ /dev/null @@ -1,19 +0,0 @@ -# Restrict key exchange, cipher, and MAC algorithms, as per sshaudit.com -# hardening guide. -KexAlgorithms sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,gss-curve25519-sha256-,diffie-hellman-group16-sha512,gss-group16-sha512-,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256 - -Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-gcm@openssh.com,aes128-ctr - -MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com - -HostKeyAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256 - -RequiredRSASize 3072 - -CASignatureAlgorithms sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256 - -GSSAPIKexAlgorithms gss-curve25519-sha256-,gss-group16-sha512- - -HostbasedAcceptedAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-256 - -PubkeyAcceptedAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-256 diff --git a/provisioning/ConfigFiles/SSH/Configs/tsys-sshd-config b/provisioning/ConfigFiles/SSH/Configs/tsys-sshd-config deleted file mode 100644 index fca1eb0..0000000 --- a/provisioning/ConfigFiles/SSH/Configs/tsys-sshd-config +++ /dev/null @@ -1,20 +0,0 @@ -Include /etc/ssh/sshd_config.d/*.conf -HostKey /etc/ssh/ssh_host_rsa_key -HostKey /etc/ssh/ssh_host_ed25519_key -KbdInteractiveAuthentication no -PrintMotd no -PasswordAuthentication no -AllowTcpForwarding no -X11Forwarding no -ChallengeResponseAuthentication no -AcceptEnv LANG LC_* -Subsystem sftp /usr/lib/openssh/sftp-server -UsePAM yes -Banner /etc/issue.net -MaxAuthTries 2 -MaxStartups 10:30:100 -PermitRootLogin prohibit-password -ClientAliveInterval 300 -ClientAliveCountMax 3 -AllowUsers root localuser subodev -LoginGraceTime 60 diff --git a/provisioning/ConfigFiles/Syslog/rsyslog.conf b/provisioning/ConfigFiles/Syslog/rsyslog.conf deleted file mode 100644 index 0ee8600..0000000 --- a/provisioning/ConfigFiles/Syslog/rsyslog.conf +++ /dev/null @@ -1,6 +0,0 @@ -module(load="imuxsock") # provides support for local system logging -module(load="imklog") # provides kernel logging support -#module(load="immark") # provides --MARK-- message capability - -*.* @tsys-librenms.knel.net:514 -:omusrmsg:EOF diff --git a/provisioning/ConfigFiles/Systemd/journald.conf b/provisioning/ConfigFiles/Systemd/journald.conf deleted file mode 100644 index 8b30ab3..0000000 --- a/provisioning/ConfigFiles/Systemd/journald.conf +++ /dev/null @@ -1,31 +0,0 @@ -[Journal] -#Compress=yes -#Seal=yes -#SplitMode=uid -#SyncIntervalSec=5m -#RateLimitIntervalSec=30s -#RateLimitBurst=10000 -#SystemMaxUse= -#SystemKeepFree= -#SystemMaxFileSize= -#SystemMaxFiles=100 -#RuntimeMaxUse= -#RuntimeKeepFree= -#RuntimeMaxFileSize= -#RuntimeMaxFiles=100 -#MaxRetentionSec= -#MaxFileSec=1month -#ForwardToSyslog=yes -#ForwardToKMsg=no -#ForwardToConsole=no -#ForwardToWall=yes -#TTYPath=/dev/console -#MaxLevelStore=debug -#MaxLevelSyslog=debug -#MaxLevelKMsg=notice -#MaxLevelConsole=info -#MaxLevelWall=emerg -#LineMax=48K -#ReadKMsg=yes -#Audit=no -Storage=persistent diff --git a/provisioning/ConfigFiles/ZSH/tsys-zshrc b/provisioning/ConfigFiles/ZSH/tsys-zshrc deleted file mode 100644 index 66c6e8f..0000000 --- a/provisioning/ConfigFiles/ZSH/tsys-zshrc +++ /dev/null @@ -1,258 +0,0 @@ -# ~/.zshrc file for zsh interactive shells. -# see /usr/share/doc/zsh/examples/zshrc for examples - -setopt autocd # change directory just by typing its name -#setopt correct # auto correct mistakes -setopt interactivecomments # allow comments in interactive mode -setopt magicequalsubst # enable filename expansion for arguments of the form ‘anything=expression’ -setopt nonomatch # hide error message if there is no match for the pattern -setopt notify # report the status of background jobs immediately -setopt numericglobsort # sort filenames numerically when it makes sense -setopt promptsubst # enable command substitution in prompt - -WORDCHARS=${WORDCHARS//\/} # Don't consider certain characters part of the word - -# hide EOL sign ('%') -PROMPT_EOL_MARK="" - -# configure key keybindings -bindkey -v # emacs key bindings -bindkey ' ' magic-space # do history expansion on space -bindkey '^U' backward-kill-line # ctrl + U -bindkey '^[[3;5~' kill-word # ctrl + Supr -bindkey '^[[3~' delete-char # delete -bindkey '^[[1;5C' forward-word # ctrl + -> -bindkey '^[[1;5D' backward-word # ctrl + <- -bindkey '^[[5~' beginning-of-buffer-or-history # page up -bindkey '^[[6~' end-of-buffer-or-history # page down -bindkey '^[[H' beginning-of-line # home -bindkey '^[[F' end-of-line # end -bindkey '^[[Z' undo # shift + tab undo last action - -# enable completion features -autoload -Uz compinit -compinit -d ~/.cache/zcompdump -zstyle ':completion:*:*:*:*:*' menu select -zstyle ':completion:*' auto-description 'specify: %d' -zstyle ':completion:*' completer _expand _complete -zstyle ':completion:*' format 'Completing %d' -zstyle ':completion:*' group-name '' -zstyle ':completion:*' list-colors '' -zstyle ':completion:*' list-prompt %SAt %p: Hit TAB for more, or the character to insert%s -zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' -zstyle ':completion:*' rehash true -zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s -zstyle ':completion:*' use-compctl false -zstyle ':completion:*' verbose true -zstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd' - -# History configurations -HISTFILE=~/.zsh_history -HISTSIZE=10000 -SAVEHIST=200000 -setopt hist_expire_dups_first # delete duplicates first when HISTFILE size exceeds HISTSIZE -setopt hist_ignore_dups # ignore duplicated commands history list -setopt hist_ignore_space # ignore commands that start with space -setopt hist_verify # show command with history expansion to user before running it -#setopt share_history # share command history data - -# force zsh to show the complete history -alias history="history 0" - -# configure `time` format -TIMEFMT=$'\nreal\t%E\nuser\t%U\nsys\t%S\ncpu\t%P' - -# make less more friendly for non-text input files, see lesspipe(1) -#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" - -# set variable identifying the chroot you work in (used in the prompt below) -if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then - debian_chroot=$(cat /etc/debian_chroot) -fi - -# set a fancy prompt (non-color, unless we know we "want" color) -case "$TERM" in - xterm-color|*-256color) color_prompt=yes;; -esac - -# uncomment for a colored prompt, if the terminal has the capability; turned -# off by default to not distract the user: the focus in a terminal window -# should be on the output of commands, not on the prompt -force_color_prompt=yes - -if [ -n "$force_color_prompt" ]; then - if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then - # We have color support; assume it's compliant with Ecma-48 - # (ISO/IEC-6429). (Lack of such support is extremely rare, and such - # a case would tend to support setf rather than setaf.) - color_prompt=yes - else - color_prompt= - fi -fi - -configure_prompt() { - prompt_symbol=㉿ - # Skull emoji for root terminal - #[ "$EUID" -eq 0 ] && prompt_symbol=💀 - case "$PROMPT_ALTERNATIVE" in - twoline) - PROMPT=$'%F{%(#.blue.green)}┌──${debian_chroot:+($debian_chroot)─}${VIRTUAL_ENV:+($(basename $VIRTUAL_ENV))─}(%B%F{%(#.red.blue)}%n'$prompt_symbol$'%m%b%F{%(#.blue.green)})-[%B%F{reset}%(6~.%-1~/…/%4~.%5~)%b%F{%(#.blue.green)}]\n└─%B%(#.%F{red}#.%F{blue}$)%b%F{reset} ' - # Right-side prompt with exit codes and background processes - #RPROMPT=$'%(?.. %? %F{red}%B⨯%b%F{reset})%(1j. %j %F{yellow}%B⚙%b%F{reset}.)' - ;; - oneline) - PROMPT=$'${debian_chroot:+($debian_chroot)}${VIRTUAL_ENV:+($(basename $VIRTUAL_ENV))}%B%F{%(#.red.blue)}%n@%m%b%F{reset}:%B%F{%(#.blue.green)}%~%b%F{reset}%(#.#.$) ' - RPROMPT= - ;; - backtrack) - PROMPT=$'${debian_chroot:+($debian_chroot)}${VIRTUAL_ENV:+($(basename $VIRTUAL_ENV))}%B%F{red}%n@%m%b%F{reset}:%B%F{blue}%~%b%F{reset}%(#.#.$) ' - RPROMPT= - ;; - esac - unset prompt_symbol -} - -# The following block is surrounded by two delimiters. -# These delimiters must not be modified. Thanks. -# START KALI CONFIG VARIABLES -PROMPT_ALTERNATIVE=twoline -NEWLINE_BEFORE_PROMPT=yes -# STOP KALI CONFIG VARIABLES - -if [ "$color_prompt" = yes ]; then - # override default virtualenv indicator in prompt - VIRTUAL_ENV_DISABLE_PROMPT=1 - - configure_prompt - - # enable syntax-highlighting - if [ -f /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then - . /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh - ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets pattern) - ZSH_HIGHLIGHT_STYLES[default]=none - ZSH_HIGHLIGHT_STYLES[unknown-token]=underline - ZSH_HIGHLIGHT_STYLES[reserved-word]=fg=cyan,bold - ZSH_HIGHLIGHT_STYLES[suffix-alias]=fg=green,underline - ZSH_HIGHLIGHT_STYLES[global-alias]=fg=green,bold - ZSH_HIGHLIGHT_STYLES[precommand]=fg=green,underline - ZSH_HIGHLIGHT_STYLES[commandseparator]=fg=blue,bold - ZSH_HIGHLIGHT_STYLES[autodirectory]=fg=green,underline - ZSH_HIGHLIGHT_STYLES[path]=bold - ZSH_HIGHLIGHT_STYLES[path_pathseparator]= - ZSH_HIGHLIGHT_STYLES[path_prefix_pathseparator]= - ZSH_HIGHLIGHT_STYLES[globbing]=fg=blue,bold - ZSH_HIGHLIGHT_STYLES[history-expansion]=fg=blue,bold - ZSH_HIGHLIGHT_STYLES[command-substitution]=none - ZSH_HIGHLIGHT_STYLES[command-substitution-delimiter]=fg=magenta,bold - ZSH_HIGHLIGHT_STYLES[process-substitution]=none - ZSH_HIGHLIGHT_STYLES[process-substitution-delimiter]=fg=magenta,bold - ZSH_HIGHLIGHT_STYLES[single-hyphen-option]=fg=green - ZSH_HIGHLIGHT_STYLES[double-hyphen-option]=fg=green - ZSH_HIGHLIGHT_STYLES[back-quoted-argument]=none - ZSH_HIGHLIGHT_STYLES[back-quoted-argument-delimiter]=fg=blue,bold - ZSH_HIGHLIGHT_STYLES[single-quoted-argument]=fg=yellow - ZSH_HIGHLIGHT_STYLES[double-quoted-argument]=fg=yellow - ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]=fg=yellow - ZSH_HIGHLIGHT_STYLES[rc-quote]=fg=magenta - ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument]=fg=magenta,bold - ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument]=fg=magenta,bold - ZSH_HIGHLIGHT_STYLES[back-dollar-quoted-argument]=fg=magenta,bold - ZSH_HIGHLIGHT_STYLES[assign]=none - ZSH_HIGHLIGHT_STYLES[redirection]=fg=blue,bold - ZSH_HIGHLIGHT_STYLES[comment]=fg=black,bold - ZSH_HIGHLIGHT_STYLES[named-fd]=none - ZSH_HIGHLIGHT_STYLES[numeric-fd]=none - ZSH_HIGHLIGHT_STYLES[arg0]=fg=cyan - ZSH_HIGHLIGHT_STYLES[bracket-error]=fg=red,bold - ZSH_HIGHLIGHT_STYLES[bracket-level-1]=fg=blue,bold - ZSH_HIGHLIGHT_STYLES[bracket-level-2]=fg=green,bold - ZSH_HIGHLIGHT_STYLES[bracket-level-3]=fg=magenta,bold - ZSH_HIGHLIGHT_STYLES[bracket-level-4]=fg=yellow,bold - ZSH_HIGHLIGHT_STYLES[bracket-level-5]=fg=cyan,bold - ZSH_HIGHLIGHT_STYLES[cursor-matchingbracket]=standout - fi -else - PROMPT='${debian_chroot:+($debian_chroot)}%n@%m:%~%(#.#.$) ' -fi -unset color_prompt force_color_prompt - -toggle_oneline_prompt(){ - if [ "$PROMPT_ALTERNATIVE" = oneline ]; then - PROMPT_ALTERNATIVE=twoline - else - PROMPT_ALTERNATIVE=oneline - fi - configure_prompt - zle reset-prompt -} -zle -N toggle_oneline_prompt -bindkey ^P toggle_oneline_prompt - -# If this is an xterm set the title to user@host:dir -case "$TERM" in -xterm*|rxvt*|Eterm|aterm|kterm|gnome*|alacritty) - TERM_TITLE=$'\e]0;${debian_chroot:+($debian_chroot)}${VIRTUAL_ENV:+($(basename $VIRTUAL_ENV))}%n@%m: %~\a' - ;; -*) - ;; -esac - -precmd() { - # Print the previously configured title - print -Pnr -- "$TERM_TITLE" - - # Print a new line before the prompt, but only if it is not the first line - if [ "$NEWLINE_BEFORE_PROMPT" = yes ]; then - if [ -z "$_NEW_LINE_BEFORE_PROMPT" ]; then - _NEW_LINE_BEFORE_PROMPT=1 - else - print "" - fi - fi -} - -# enable color support of ls, less and man, and also add handy aliases -if [ -x /usr/bin/dircolors ]; then - test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" - export LS_COLORS="$LS_COLORS:ow=30;44:" # fix ls color for folders with 777 permissions - - alias ls='ls --color=auto' - #alias dir='dir --color=auto' - #alias vdir='vdir --color=auto' - - alias grep='grep --color=auto' - alias fgrep='fgrep --color=auto' - alias egrep='egrep --color=auto' - alias diff='diff --color=auto' - alias ip='ip --color=auto' - - export LESS_TERMCAP_mb=$'\E[1;31m' # begin blink - export LESS_TERMCAP_md=$'\E[1;36m' # begin bold - export LESS_TERMCAP_me=$'\E[0m' # reset bold/blink - export LESS_TERMCAP_so=$'\E[01;33m' # begin reverse video - export LESS_TERMCAP_se=$'\E[0m' # reset reverse video - export LESS_TERMCAP_us=$'\E[1;32m' # begin underline - export LESS_TERMCAP_ue=$'\E[0m' # reset underline - - # Take advantage of $LS_COLORS for completion as well - zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" - zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31' -fi - -# some more ls aliases -alias ll='ls -l' -alias la='ls -A' -alias l='ls -CF' - -# enable auto-suggestions based on the history -if [ -f /usr/share/zsh-autosuggestions/zsh-autosuggestions.zsh ]; then - . /usr/share/zsh-autosuggestions/zsh-autosuggestions.zsh - # change suggestion color - ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=#999' -fi - -# enable command-not-found if installed -if [ -f /etc/zsh_command_not_found ]; then - . /etc/zsh_command_not_found -fi diff --git a/provisioning/ConfigFiles/pfv-nfs-tuning.service b/provisioning/ConfigFiles/pfv-nfs-tuning.service deleted file mode 100644 index 75c66ae..0000000 --- a/provisioning/ConfigFiles/pfv-nfs-tuning.service +++ /dev/null @@ -1,28 +0,0 @@ -# PFV NFS tuning service -# -# Systemd oneshot that runs AFTER tuned.service to apply TCP buffer -# overrides. The tuned daemon's profiles (network-throughput for storage -# hosts, virtual-host for compute hosts) set 16MB TCP buffer caps which -# are too small for high-BDP NFS over LACP links. This service force- -# applies 128MB buffers after tuned has finished its configuration. -# -# Install: -# cp pfv-nfs-tuning.service /etc/systemd/system/pfv-nfs-tuning.service -# systemctl daemon-reload -# systemctl enable --now pfv-nfs-tuning.service -# -# Created: 2026-07-31 -# Deployed: all 7 Proxmox hosts (tsys1/3/4/5/6/7/9) - -[Unit] -Description=PFV NFS tuning (override tuned TCP buffer caps) -After=tuned.service -Requires=tuned.service - -[Service] -Type=oneshot -ExecStart=/sbin/sysctl -p /etc/sysctl.d/99-pfv-nfs.conf -RemainAfterExit=yes - -[Install] -WantedBy=multi-user.target diff --git a/provisioning/Dell/Server/fixeth.sh b/provisioning/Dell/Server/fixeth.sh deleted file mode 100644 index 21e4b94..0000000 --- a/provisioning/Dell/Server/fixeth.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - - - -#magic to detect main int -echo "Determining management interface..." -#export MAIN_INT=$(brctl show $(netstat -rn|grep 0.0.0.0|head -n1|awk '{print $NF}') | awk '{print $NF}'|tail -1|awk -F '.' '{print $1}') -MAIN_INT=$(brctl show|grep vmbr0|awk '{print $NF}'|awk -F '.' '{print $1}') -export MAIN_INT - -echo "Management interface is: $MAIN_INT" - -#fix the issue -echo "Fixing management interface..." -ethtool -K "$MAIN_INT" tso off -ethtool -K "$MAIN_INT" gro off -ethtool -K "$MAIN_INT" gso off -ethtool -K "$MAIN_INT" tx off -ethtool -K "$MAIN_INT" rx off - -#https://forum.proxmox.com/threads/e1000-driver-hang.58284/ -#https://serverfault.com/questions/616485/e1000e-reset-adapter-unexpectedly-detected-hardware-unit-hang - - diff --git a/provisioning/Dell/Server/omsa.sh b/provisioning/Dell/Server/omsa.sh deleted file mode 100644 index ae30060..0000000 --- a/provisioning/Dell/Server/omsa.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -#curl -s http://dl.turnsys.net/omsa.sh|/bin/bash - -gpg --keyserver hkp://pool.sks-keyservers.net:80 --recv-key 1285491434D8786F -gpg -a --export 1285491434D8786F | apt-key add - -echo "deb https://linux.dell.com/repo/community/openmanage/930/bionic bionic main" > /etc/apt/sources.list.d/linux.dell.com.sources.list -wget https://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/libwsman-curl-client-transport1_2.6.5-0ubuntu3_amd64.deb -wget https://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/libwsman-client4_2.6.5-0ubuntu3_amd64.deb -wget https://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/libwsman1_2.6.5-0ubuntu3_amd64.deb -wget https://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/libwsman-server1_2.6.5-0ubuntu3_amd64.deb -wget https://archive.ubuntu.com/ubuntu/pool/universe/s/sblim-sfcc/libcimcclient0_2.2.8-0ubuntu2_amd64.deb -wget https://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/openwsman_2.6.5-0ubuntu3_amd64.deb -wget https://archive.ubuntu.com/ubuntu/pool/multiverse/c/cim-schema/cim-schema_2.48.0-0ubuntu1_all.deb -wget https://archive.ubuntu.com/ubuntu/pool/universe/s/sblim-sfc-common/libsfcutil0_1.0.1-0ubuntu4_amd64.deb -wget https://archive.ubuntu.com/ubuntu/pool/multiverse/s/sblim-sfcb/sfcb_1.4.9-0ubuntu5_amd64.deb -wget https://archive.ubuntu.com/ubuntu/pool/universe/s/sblim-cmpi-devel/libcmpicppimpl0_2.0.3-0ubuntu2_amd64.deb -dpkg -i libwsman-curl-client-transport1_2.6.5-0ubuntu3_amd64.deb -dpkg -i libwsman-client4_2.6.5-0ubuntu3_amd64.deb -dpkg -i libwsman1_2.6.5-0ubuntu3_amd64.deb -dpkg -i libwsman-server1_2.6.5-0ubuntu3_amd64.deb -dpkg -i libcimcclient0_2.2.8-0ubuntu2_amd64.deb -dpkg -i openwsman_2.6.5-0ubuntu3_amd64.deb -dpkg -i cim-schema_2.48.0-0ubuntu1_all.deb -dpkg -i libsfcutil0_1.0.1-0ubuntu4_amd64.deb -dpkg -i sfcb_1.4.9-0ubuntu5_amd64.deb -dpkg -i libcmpicppimpl0_2.0.3-0ubuntu2_amd64.deb - -apt update -apt -y install srvadmin-all -touch /opt/dell/srvadmin/lib64/openmanage/IGNORE_GENERATION - -#logout,login, then run -# srvadmin-services.sh enable && srvadmin-services.sh start diff --git a/provisioning/Dell/fixcpuperf.sh b/provisioning/Dell/fixcpuperf.sh deleted file mode 100644 index e795119..0000000 --- a/provisioning/Dell/fixcpuperf.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -#Script to set performance. - - - -cpufreq-set -r -g performance -cpupower frequency-set --governor performance - - diff --git a/provisioning/Modules/Auth/auth-cloudron-ldap.sh b/provisioning/Modules/Auth/auth-cloudron-ldap.sh deleted file mode 100644 index da03f3d..0000000 --- a/provisioning/Modules/Auth/auth-cloudron-ldap.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -# auth-cloudron-ldap.sh — placeholder module (Cloudron LDAP auth integration). -# Intentionally empty; populated when the auth stack is deployed. -true diff --git a/provisioning/Modules/OAM/oam-librenms.sh b/provisioning/Modules/OAM/oam-librenms.sh deleted file mode 100644 index 68f0d4c..0000000 --- a/provisioning/Modules/OAM/oam-librenms.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -export PROJECT_ROOT_PATH -PROJECT_ROOT_PATH="$(cd "$SCRIPT_DIR/../../.." && pwd)" - -export GIT_VENDOR_PATH_ROOT -GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/" - -export KNELShellFrameworkRoot -KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework" - -export AGENTS_PATH -AGENTS_PATH="$PROJECT_ROOT_PATH/provisioning/Agents" - -source "$KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars" - -for framework_include_file in "$KNELShellFrameworkRoot"/Framework-Includes/*; do - source "$framework_include_file" -done - -for project_include_file in "$PROJECT_ROOT_PATH"/Project-Includes/*; do - source "$project_include_file" -done - -print_info "Setting up librenms agent..." - -cat "$AGENTS_PATH/librenms/distro" > /usr/local/bin/distro -chmod +x /usr/local/bin/distro - -if [ ! -d /usr/lib/check_mk_agent ]; then -mkdir -p /usr/lib/check_mk_agent -fi - -if [ ! -d /usr/lib/check_mk_agent/plugins ]; then -mkdir -p /usr/lib/check_mk_agent/plugins -fi - -if [ ! -d /usr/lib/check_mk_agent/local ]; then -mkdir -p /usr/lib/check_mk_agent/local -fi - -cat "$AGENTS_PATH/librenms/check_mk_agent" > /usr/bin/check_mk_agent -chmod +x /usr/bin/check_mk_agent - -cat "$AGENTS_PATH/librenms/check_mk@.service" > /etc/systemd/system/check_mk@.service -cat "$AGENTS_PATH/librenms/check_mk.socket" > /etc/systemd/system/check_mk.socket - -systemctl enable check_mk.socket -systemctl start check_mk.socket - -#Modules commented out below, we will roll out on systems that use them, most of the fleet doesn't use those modules - -cat "$AGENTS_PATH/librenms/dmi.sh" > /usr/lib/check_mk_agent/local/dmi.sh -cat "$AGENTS_PATH/librenms/dpkg.sh" > /usr/lib/check_mk_agent/local/dpkg.sh -#cat "$AGENTS_PATH/librenms/mysql.sh" > /usr/lib/check_mk_agent/local/mysql.sh -cat "$AGENTS_PATH/librenms/ntp-client" > /usr/lib/check_mk_agent/local/ntp-client -#cat "$AGENTS_PATH/librenms/ntp-server.sh" > /usr/lib/check_mk_agent/local/ntp-server.sh -cat "$AGENTS_PATH/librenms/os-updates.sh" > /usr/lib/check_mk_agent/local/os-updates.sh -cat "$AGENTS_PATH/librenms/postfixdetailed" > /usr/lib/check_mk_agent/local/postfixdetailed -cat "$AGENTS_PATH/librenms/postfix-queues" > /usr/lib/check_mk_agent/local/postfix-queues -#cat "$AGENTS_PATH/librenms/smart.sh" > /usr/lib/check_mk_agent/local/smart -#cat "$AGENTS_PATH/librenms/smart.sh.config" > /usr/lib/check_mk_agent/local/smart.config - -chmod +x /usr/lib/check_mk_agent/local/* \ No newline at end of file diff --git a/provisioning/Modules/RandD/sslStackFromSource.sh b/provisioning/Modules/RandD/sslStackFromSource.sh deleted file mode 100644 index 2e9e819..0000000 --- a/provisioning/Modules/RandD/sslStackFromSource.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash -# shellcheck disable=SC2103 # legacy R&D build script; cd/cd- sequence is intentional - -#Made from instructions at https://www.tunetheweb.com/performance/http2/ - -OPENSSL_URL_BASE="https://www.openssl.org/source/" -OPENSSL_FILE="openssl-1.1.0h.tar.gz" - -NGHTTP_URL_BASE="https://github.com/nghttp2/nghttp2/releases/download/v1.31.0/" -NGHTTP_FILE="nghttp2-1.31.0.tar.gz" - -APR_URL_BASE="https://archive.apache.org/dist/apr/" -APR_FILE="apr-1.6.3.tar.gz" - -APR_UTIL_URL_BASE="https://archive.apache.org/dist/apr/" -APR_UTIL_FILE="apr-util-1.6.1.tar.gz" - -APACHE_URL_BASE="https://archive.apache.org/dist/httpd/" -APACHE_FILE="httpd-2.4.33.tar.gz" - -CURL_URL_BASE="https://curl.haxx.se/download/" -CURL_FILE="curl-7.60.0.tar.gz" - - -#Download and install latest version of openssl -wget $OPENSSL_URL_BASE/$OPENSSL_FILE -tar xzf $OPENSSL_FILE -cd openssl-1.1.0h || exit -./config enable-weak-ssl-ciphers shared zlib-dynamic -DOPENSSL_TLS_SECURITY_LEVEL=0 --prefix=/usr/local/custom-ssl/openssl-1.1.0h ; make ; make install -ln -s /usr/local/custom-ssl/openssl-1.1.0h /usr/local/openssl -cd - || exit - -#Download and install nghttp2 (needed for mod_http2). -wget $NGHTTP_URL_BASE/$NGHTTP_FILE -tar xzf $NGHTTP_FILE -cd nghttp2-1.31.0 || exit -./configure --prefix=/usr/local/custom-ssl/nghttp ; make ; make install -cd - || exit - -#Updated ldconfig so curl build - -cat < /etc/ld.so.conf.d/custom-ssl.conf -/usr/local/custom-ssl/openssl-1.1.0h/lib -/usr/local/custom-ssl/nghttp/lib -custom-ssl - -ldconfig - -#Download and install curl -wget $CURL_URL_BASE/$CURL_FILE -tar xzf curl-7.60.0.tar.gz -cd curl-7.60.0 || exit -./configure --prefix=/usr/local/custom-ssl/curl --with-nghttp2=/usr/local/custom-ssl/nghttp/ --with-ssl=/usr/local/custom-ssl/openssl-1.1.0h/ ; make ; make install -cd - || exit - - -#Download and install latest apr -wget $APR_URL_BASE/$APR_FILE -tar xzf $APR_FILE -cd apr-1.6.3 || exit -./configure --prefix=/usr/local/custom-ssl/apr ; make ; make install -cd - || exit - -#Download and install latest apr-util -wget $APR_UTIL_URL_BASE/$APR_UTIL_FILE -tar xzf apr-util-1.6.1.tar.gz -cd apr-util-1.6.1 || exit -./configure --prefix=/usr/local/custom-ssl/apr-util --with-apr=/usr/local/custom-ssl/apr ; make; make install -cd - || exit - -#Download and install apache -wget $APACHE_URL_BASE/$APACHE_FILE -tar xzf httpd-2.4.33.tar.gz -cd httpd-2.4.33 || exit -cp -r ../apr-1.6.3 srclib/apr -cp -r ../apr-util-1.6.1 srclib/apr-util -./configure --prefix=/usr/local/custom-ssl/apache --with-ssl=/usr/local/custom-ssl/openssl-1.1.0h/ --with-pcre=/usr/bin/pcre-config --enable-unique-id --enable-ssl --enable-so --with-included-apr --enable-http2 --with-nghttp2=/usr/local/custom-ssl/nghttp/ -make -make install -ln -s /usr/local/custom-ssl/apache /usr/local/apache -cd - || exit - diff --git a/provisioning/Modules/Security/secharden-2fa.sh b/provisioning/Modules/Security/secharden-2fa.sh deleted file mode 100644 index 48006b7..0000000 --- a/provisioning/Modules/Security/secharden-2fa.sh +++ /dev/null @@ -1,426 +0,0 @@ -#!/bin/bash - -# TSYS Security Hardening - Two-Factor Authentication -# Implements 2FA for SSH, Cockpit, and Webmin services -# Uses Google Authenticator (TOTP) for time-based tokens - - -##### -#Core framework functions... -##### - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -export PROJECT_ROOT_PATH -PROJECT_ROOT_PATH="$(cd "$SCRIPT_DIR/../../.." && pwd)" - -export GIT_VENDOR_PATH_ROOT -GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/" - -export KNELShellFrameworkRoot -KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework" - -source "$KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars" - -for framework_include_file in "$KNELShellFrameworkRoot"/Framework-Includes/*; do - source "$framework_include_file" -done - -for project_include_file in "$PROJECT_ROOT_PATH"/Project-Includes/*; do - source "$project_include_file" -done - -# 2FA Configuration -BACKUP_DIR="/root/backup/2fa" -PAM_CONFIG_DIR="/etc/pam.d" -SSH_CONFIG="/etc/ssh/sshd_config" -COCKPIT_CONFIG="/etc/cockpit/cockpit.conf" - -# Create backup directory -mkdir -p "$BACKUP_DIR" - -print_info "TSYS Two-Factor Authentication Setup" - -# Backup existing configurations -function backup_configs() { - print_info "Creating backup of existing configurations..." - - # Backup SSH configuration - if [[ -f "$SSH_CONFIG" ]]; then - cp "$SSH_CONFIG" "$BACKUP_DIR/sshd_config.bak" - print_info "SSH config backed up" - fi - - # Backup PAM configurations - if [[ -d "$PAM_CONFIG_DIR" ]]; then - cp -r "$PAM_CONFIG_DIR" "$BACKUP_DIR/pam.d.bak" - print_info "PAM configs backed up" - fi - - # Backup Cockpit configuration if exists - if [[ -f "$COCKPIT_CONFIG" ]]; then - cp "$COCKPIT_CONFIG" "$BACKUP_DIR/cockpit.conf.bak" - print_info "Cockpit config backed up" - fi - - print_info "Backup completed: $BACKUP_DIR" -} - -# Install required packages -function install_2fa_packages() { - print_info "Installing 2FA packages..." - - # Update package cache - apt-get update - - # Install Google Authenticator PAM module - # Install QR code generator for terminal display - apt-get install -y libpam-google-authenticator qrencode - - print_info "2FA packages installed successfully" -} - -# Configure SSH for 2FA -function configure_ssh_2fa() { - print_info "Configuring SSH for 2FA..." - - # Configure SSH daemon - print_info "Updating SSH configuration..." - - # Enable challenge-response authentication - if ! grep -q "^ChallengeResponseAuthentication yes" "$SSH_CONFIG"; then - sed -i 's/^ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/' "$SSH_CONFIG" || \ - echo "ChallengeResponseAuthentication yes" >> "$SSH_CONFIG" - fi - - if ! grep -q "^KbdInteractiveAuthentication yes" "$SSH_CONFIG"; then - sed -i 's/^KbdInteractiveAuthentication.*/KbdInteractiveAuthentication yes/' "$SSH_CONFIG" || \ - echo "KbdInteractiveAuthentication yes" >> "$SSH_CONFIG" - fi - - # Enable PAM authentication - if ! grep -q "^UsePAM yes" "$SSH_CONFIG"; then - sed -i 's/^UsePAM.*/UsePAM yes/' "$SSH_CONFIG" || \ - echo "UsePAM yes" >> "$SSH_CONFIG" - fi - - # Configure authentication methods (key + 2FA) - if ! grep -q "^AuthenticationMethods" "$SSH_CONFIG"; then - echo "AuthenticationMethods publickey,keyboard-interactive" >> "$SSH_CONFIG" - else - sed -i 's/^AuthenticationMethods.*/AuthenticationMethods publickey,keyboard-interactive/' "$SSH_CONFIG" - fi - - print_info "SSH configuration updated" -} - -# Configure PAM for 2FA -function configure_pam_2fa() { - print_info "Configuring PAM for 2FA..." - - # Create backup of original PAM SSH config - cp "$PAM_CONFIG_DIR/sshd" "$PAM_CONFIG_DIR/sshd.bak.$(date +%Y%m%d)" - - # Configure PAM to use Google Authenticator - cat > "$PAM_CONFIG_DIR/sshd" << 'EOF' -# PAM configuration for SSH with 2FA -# Standard Un*x authentication -@include common-auth - -# Google Authenticator 2FA -auth required pam_google_authenticator.so nullok - -# Standard Un*x authorization -@include common-account - -# SELinux needs to be the first session rule -session required pam_selinux.so close -session required pam_loginuid.so - -# Standard Un*x session setup and teardown -@include common-session - -# Print the message of the day upon successful login -session optional pam_motd.so motd=/run/motd.dynamic -session optional pam_motd.so noupdate - -# Print the status of the user's mailbox upon successful login -session optional pam_mail.so standard noenv - -# Set up user limits from /etc/security/limits.conf -session required pam_limits.so - -# SELinux needs to intervene at login time -session required pam_selinux.so open - -# Standard Un*x password updating -@include common-password -EOF - - print_info "PAM configuration updated for SSH 2FA" -} - -# Configure Cockpit for 2FA -function configure_cockpit_2fa() { - print_info "Configuring Cockpit for 2FA..." - - # Create Cockpit config directory if it doesn't exist - mkdir -p "$(dirname "$COCKPIT_CONFIG")" - - # Configure Cockpit to use PAM with 2FA - cat > "$COCKPIT_CONFIG" << 'EOF' -[WebService] -# Enable 2FA for Cockpit web interface -LoginTitle = TSYS Server Management -LoginTo = 300 -RequireHost = true - -[Session] -# Use PAM for authentication (includes 2FA) -Banner = /etc/cockpit/issue.cockpit -IdleTimeout = 15 -EOF - - # Create PAM configuration for Cockpit - cat > "$PAM_CONFIG_DIR/cockpit" << 'EOF' -# PAM configuration for Cockpit with 2FA -auth requisite pam_nologin.so -auth required pam_env.so -auth required pam_faillock.so preauth -auth sufficient pam_unix.so try_first_pass -auth required pam_google_authenticator.so nullok -auth required pam_faillock.so authfail -auth required pam_deny.so - -account required pam_nologin.so -account include system-auth -account required pam_faillock.so - -session required pam_selinux.so close -session required pam_loginuid.so -session optional pam_keyinit.so force revoke -session include system-auth -session required pam_selinux.so open -session optional pam_motd.so -EOF - - print_info "Cockpit 2FA configuration completed" -} - -# Configure Webmin for 2FA (if installed) -function configure_webmin_2fa() { - print_info "Checking for Webmin installation..." - - local webmin_config="/etc/webmin/miniserv.conf" - - if [[ -f "$webmin_config" ]]; then - print_info "Webmin found, configuring 2FA..." - - # Stop webmin service - systemctl stop webmin || true - - # Enable 2FA in Webmin configuration. `sed -i ... || echo` would never - # append, because sed returns 0 even when it matches nothing; guard with - # grep so the directive is added when absent and updated when present. - if grep -q '^twofactor_provider=' "$webmin_config"; then - sed -i 's/^twofactor_provider=.*/twofactor_provider=totp/' "$webmin_config" - else - echo "twofactor_provider=totp" >> "$webmin_config" - fi - - # Enable 2FA requirement - if grep -q '^twofactor=' "$webmin_config"; then - sed -i 's/^twofactor=.*/twofactor=1/' "$webmin_config" - else - echo "twofactor=1" >> "$webmin_config" - fi - - # Start webmin service - systemctl start webmin || true - - print_info "Webmin 2FA configuration completed" - else - print_info "Webmin not found, skipping configuration" - fi -} - -# Setup 2FA for users -function setup_user_2fa() { - print_info "Setting up 2FA for system users..." - - local users=("localuser" "root") - - for user in "${users[@]}"; do - if id "$user" &>/dev/null; then - print_info "Setting up 2FA for user: $user" - - local user_home - user_home="$(getent passwd "$user" | cut -d: -f6)" - if [[ -z "$user_home" ]]; then - print_info "No home directory for $user, skipping" - continue - fi - - # Create 2FA setup script for user - cat > "/tmp/setup-2fa-$user.sh" << 'EOF' -#!/bin/bash -echo "Setting up Google Authenticator for user: $USER" -echo "Please follow the prompts to configure 2FA:" -echo "1. Answer 'y' to update your time-based token" -echo "2. Scan the QR code with your authenticator app" -echo "3. Save the backup codes in a secure location" -echo "4. Answer 'y' to the remaining questions for security" -echo "" -google-authenticator -t -d -f -r 3 -R 30 -W -EOF - - chmod +x "/tmp/setup-2fa-$user.sh" - - # Instructions for user setup - cat > "$user_home/2fa-setup-instructions.txt" << EOF -TSYS Two-Factor Authentication Setup Instructions -============================================== - -Your system has been configured for 2FA. To complete setup: - -1. Install an authenticator app on your phone: - - Google Authenticator - - Authy - - Microsoft Authenticator - -2. Run the setup command: - sudo /tmp/setup-2fa-$user.sh - -3. Follow the prompts: - - Scan the QR code with your app - - Save the backup codes securely - - Answer 'y' to security questions - -4. Test your setup: - - SSH to the server - - Enter your 6-digit code when prompted - -IMPORTANT: Save backup codes in a secure location! -Without them, you may be locked out if you lose your phone. - -For support, contact your system administrator. -EOF - - chown "$user:$user" "$user_home/2fa-setup-instructions.txt" - print_info "2FA setup prepared for user: $user" - else - print_info "User $user not found, skipping" - fi - done -} - -# Restart services -function restart_services() { - print_info "Restarting services..." - - # Test SSH configuration - if sshd -t; then - systemctl restart sshd - print_info "SSH service restarted" - else - print_error "SSH configuration test failed" - return 1 - fi - - # Restart Cockpit if installed - if systemctl is-enabled cockpit.socket &>/dev/null; then - systemctl restart cockpit.socket - print_info "Cockpit service restarted" - fi - - # Restart Webmin if installed - if systemctl is-enabled webmin &>/dev/null; then - systemctl restart webmin - print_info "Webmin service restarted" - fi -} - -# Validation and testing -function validate_2fa_setup() { - print_info "Validating 2FA setup..." - - # Check if Google Authenticator is installed - if command -v google-authenticator &>/dev/null; then - print_info "Google Authenticator installed" - else - print_error "Google Authenticator not found" - return 1 - fi - - # Check SSH configuration - if grep -q "AuthenticationMethods publickey,keyboard-interactive" "$SSH_CONFIG"; then - print_info "SSH 2FA configuration valid" - else - print_error "SSH 2FA configuration invalid" - return 1 - fi - - # Check PAM configuration - if grep -q "pam_google_authenticator.so" "$PAM_CONFIG_DIR/sshd"; then - print_info "PAM 2FA configuration valid" - else - print_error "PAM 2FA configuration invalid" - return 1 - fi - - # Check service status - if systemctl is-active sshd &>/dev/null; then - print_info "SSH service is running" - else - print_error "SSH service is not running" - return 1 - fi - - print_info "2FA validation completed successfully" -} - -# Display final instructions -function show_final_instructions() { - print_info "2FA Setup Completed" - - print_info "Two-Factor Authentication has been configured for:" - print_info "- SSH (requires key + 2FA token)" - print_info "- Cockpit web interface" - if [[ -f "/etc/webmin/miniserv.conf" ]]; then - print_info "- Webmin administration panel" - fi - - print_info "IMPORTANT: Complete user setup immediately!" - print_info "1. Check /home/*/2fa-setup-instructions.txt for user setup" - print_info "2. Run setup scripts for each user" - print_info "3. Test 2FA before logging out" - - print_info "Backup location: $BACKUP_DIR" - print_info "To disable 2FA, restore configurations from backup" - - print_info "2FA setup completed successfully!" -} - -# Main execution -function main() { - # Check if running as root - if [[ $EUID -ne 0 ]]; then - print_error "This script must be run as root" - exit 1 - fi - - # Execute setup steps - backup_configs - install_2fa_packages - configure_ssh_2fa - configure_pam_2fa - configure_cockpit_2fa - configure_webmin_2fa - setup_user_2fa - restart_services - validate_2fa_setup - show_final_instructions -} - -# Run main function -main "$@" \ No newline at end of file diff --git a/provisioning/Modules/Security/secharden-audit-agents.sh b/provisioning/Modules/Security/secharden-audit-agents.sh deleted file mode 100644 index 7c5d81c..0000000 --- a/provisioning/Modules/Security/secharden-audit-agents.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -##### -#Core framework functions... -##### - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -export PROJECT_ROOT_PATH -PROJECT_ROOT_PATH="$(cd "$SCRIPT_DIR/../../.." && pwd)" - -export GIT_VENDOR_PATH_ROOT -GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/" - -export KNELShellFrameworkRoot -KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework" - -export CONFIGFILES_PATH -CONFIGFILES_PATH="$PROJECT_ROOT_PATH/provisioning/ConfigFiles" - -source "$KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars" - -for framework_include_file in "$KNELShellFrameworkRoot"/Framework-Includes/*; do - source "$framework_include_file" -done - -for project_include_file in "$PROJECT_ROOT_PATH"/Project-Includes/*; do - source "$project_include_file" -done - -# Material herein Sourced from - -# https://cisofy.com/documentation/lynis/ -# https://jbcsec.com/configure-linux-ssh/ -# https://opensource.com/article/20/5/linux-security-lynis -# https://forum.greenbone.net/t/ssh-authentication/13536 - -# openvas - -#lynis - -#Auditd - -cat "$CONFIGFILES_PATH/AuditD/auditd.conf" > /etc/audit/auditd.conf - -# Systemd -cat "$CONFIGFILES_PATH/Systemd/journald.conf" > /etc/systemd/journald.conf - -# logrotate -cat "$CONFIGFILES_PATH/Logrotate/logrotate.conf" > /etc/logrotate.conf \ No newline at end of file diff --git a/provisioning/Modules/Security/secharden-auto-upgrade.sh b/provisioning/Modules/Security/secharden-auto-upgrade.sh deleted file mode 100644 index 7f171ec..0000000 --- a/provisioning/Modules/Security/secharden-auto-upgrade.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -# Sourced from https://wiki.debian.org/UnattendedUpgrades diff --git a/provisioning/Modules/Security/secharden-scap-stig.sh b/provisioning/Modules/Security/secharden-scap-stig.sh deleted file mode 100644 index 9c92e93..0000000 --- a/provisioning/Modules/Security/secharden-scap-stig.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/bash - - -######################################### -#Core framework functions... -######################################### - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -export PROJECT_ROOT_PATH -PROJECT_ROOT_PATH="$(cd "$SCRIPT_DIR/../../.." && pwd)" - -export GIT_VENDOR_PATH_ROOT -GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/" - -export KNELShellFrameworkRoot -KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework" - -export CONFIGFILES_PATH -CONFIGFILES_PATH="$PROJECT_ROOT_PATH/provisioning/ConfigFiles" - -source "$KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars" - -for framework_include_file in "$KNELShellFrameworkRoot"/Framework-Includes/*; do - source "$framework_include_file" -done - -for project_include_file in "$PROJECT_ROOT_PATH"/Project-Includes/*; do - source "$project_include_file" -done - - -######################################### -# Core script code begins here -######################################### - -# Sourced from - -# https://complianceascode.readthedocs.io/en/latest/manual/developer/01_introduction.html -# https://github.com/ComplianceAsCode/content -# https://github.com/ComplianceAsCode - -#apparmor -#enforcing -#enabled in bootloader config - -#aide - -#auditd - -#disable auto mounting -#disable usb storage - - -#motd -#remote login warning banner - -#Ensure time sync is working -#systemd-timesync -#ntp -#chrony - -#password complexity -#password expiration warning -#password expiration time -#password hashing algo - -#fix grub perms - -if [ "$IS_RASPI" = 0 ] ; then - -chown root:root /boot/grub/grub.cfg -chmod og-rwx /boot/grub/grub.cfg -chmod 0400 /boot/grub/grub.cfg - -fi - - -#disable auto mounting -systemctl --now disable autofs || true -apt-get -y --purge remove autofs || true - -#disable usb storage -cat "$CONFIGFILES_PATH/ModProbe/usb_storage.conf" > /etc/modprobe.d/usb_storage.conf -cat "$CONFIGFILES_PATH/ModProbe/dccp.conf" > /etc/modprobe.d/dccp.conf -cat "$CONFIGFILES_PATH/ModProbe/rds.conf" > /etc/modprobe.d/rds.conf -cat "$CONFIGFILES_PATH/ModProbe/sctp.conf" > /etc/modprobe.d/sctp.conf -cat "$CONFIGFILES_PATH/ModProbe/tipc.conf" > /etc/modprobe.d/tipc.conf -cat "$CONFIGFILES_PATH/ModProbe/cramfs.conf" > /etc/modprobe.d/cramfs.conf -cat "$CONFIGFILES_PATH/ModProbe/freevxfs.conf" > /etc/modprobe.d/freevxfs.conf -cat "$CONFIGFILES_PATH/ModProbe/hfs.conf" > /etc/modprobe.d/hfs.conf -cat "$CONFIGFILES_PATH/ModProbe/hfsplus.conf" > /etc/modprobe.d/hfsplus.conf -cat "$CONFIGFILES_PATH/ModProbe/jffs2.conf" > /etc/modprobe.d/jffs2.conf -cat "$CONFIGFILES_PATH/ModProbe/squashfs.conf" > /etc/modprobe.d/squashfs.conf -cat "$CONFIGFILES_PATH/ModProbe/udf.conf" > /etc/modprobe.d/udf.conf - -#banners - -cat "$CONFIGFILES_PATH/BANNERS/issue" > /etc/issue -cat "$CONFIGFILES_PATH/BANNERS/issue.net" > /etc/issue.net -cat "$CONFIGFILES_PATH/BANNERS/motd" > /etc/motd - -#Cron perms - -if [ -f /etc/cron.deny ]; then -rm /etc/cron.deny || true -fi - -touch /etc/cron.allow -chmod g-wx,o-rwx /etc/cron.allow -chown root:root /etc/cron.allow - -chmod og-rwx /etc/crontab -chmod og-rwx /etc/cron.hourly/ -chmod og-rwx /etc/cron.daily/ -chmod og-rwx /etc/cron.weekly/ -chmod og-rwx /etc/cron.monthly/ -chown root:root /etc/cron.d/ -chmod og-rwx /etc/cron.d/ - -# At perms - -rm -f /etc/at.deny || true -touch /etc/at.allow -chmod g-wx,o-rwx /etc/at.allow -chown root:root /etc/at.allow \ No newline at end of file diff --git a/provisioning/Modules/Security/secharden-ssh.sh b/provisioning/Modules/Security/secharden-ssh.sh deleted file mode 100644 index 71bde08..0000000 --- a/provisioning/Modules/Security/secharden-ssh.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/bash - -######################################### -#Core framework functions... -######################################### - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -export PROJECT_ROOT_PATH -PROJECT_ROOT_PATH="$(cd "$SCRIPT_DIR/../../.." && pwd)" - -export GIT_VENDOR_PATH_ROOT -GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/" - -export KNELShellFrameworkRoot -KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework" - -export CONFIGFILES_PATH -CONFIGFILES_PATH="$PROJECT_ROOT_PATH/provisioning/ConfigFiles" - -source "$KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars" - -for framework_include_file in "$KNELShellFrameworkRoot"/Framework-Includes/*; do - source "$framework_include_file" -done - -for project_include_file in "$PROJECT_ROOT_PATH"/Project-Includes/*; do - source "$project_include_file" -done - - -######################################### -# Core script code begins here -######################################### - -export SUBODEV_CHECK -SUBODEV_CHECK="$(getent passwd | grep -c subodev || true)" - -export LOCALUSER_CHECK -LOCALUSER_CHECK="$(getent passwd | grep -c localuser || true)" - -export ROOT_SSH_DIR -ROOT_SSH_DIR="/root/.ssh" - -export LOCALUSER_SSH_DIR -LOCALUSER_SSH_DIR="/home/localuser/.ssh" - -export SUBODEV_SSH_DIR -SUBODEV_SSH_DIR="/home/subodev/.ssh" - - -if [ ! -d $ROOT_SSH_DIR ]; then - mkdir /root/.ssh/ -fi - -cat "$CONFIGFILES_PATH/SSH/AuthorizedKeys/root-ssh-authorized-keys" >/root/.ssh/authorized_keys -chmod 400 /root/.ssh/authorized_keys -chown root: /root/.ssh/authorized_keys - -if [ "$LOCALUSER_CHECK" -gt 0 ]; then - if [ ! -d $LOCALUSER_SSH_DIR ]; then - mkdir -p /home/localuser/.ssh/ - fi - - cat "$CONFIGFILES_PATH/SSH/AuthorizedKeys/localuser-ssh-authorized-keys" >/home/localuser/.ssh/authorized_keys - chown localuser /home/localuser/.ssh/authorized_keys && - chmod 400 /home/localuser/.ssh/authorized_keys -fi - -if [ "$SUBODEV_CHECK" = 1 ]; then - - if [ ! -d $SUBODEV_SSH_DIR ]; then - mkdir /home/subodev/.ssh/ - fi - - cat "$CONFIGFILES_PATH/SSH/AuthorizedKeys/localuser-ssh-authorized-keys" >/home/subodev/.ssh/authorized_keys - chmod 400 /home/subodev/.ssh/authorized_keys && - chown subodev: /home/subodev/.ssh/authorized_keys -fi - -export DEV_WORKSTATION_CHECK -DEV_WORKSTATION_CHECK="$(hostname | grep -Ec 'subopi-dev|CharlesDevServer' || true)" - -if [ "$DEV_WORKSTATION_CHECK" -eq 0 ]; then - - cat "$CONFIGFILES_PATH/SSH/Configs/tsys-sshd-config" >/etc/ssh/sshd_config -fi - - -#Don't deploy this config to a ubuntu server, it breaks openssh server. Works on kali/debian. - -export UBUNTU_CHECK -UBUNTU_CHECK="$(distro | grep -c Ubuntu||true)" - -if [ "$UBUNTU_CHECK" -ne 1 ]; then - cat "$CONFIGFILES_PATH/SSH/Configs/ssh-audit-hardening.conf" >/etc/ssh/sshd_config.d/ssh-audit_hardening.conf - chmod og-rwx /etc/ssh/sshd_config.d/* -fi - -# Perms on sshd_config -chmod og-rwx /etc/ssh/sshd_config - -#todo - -# only strong MAC algos are used \ No newline at end of file diff --git a/provisioning/Modules/Security/secharden-wazuh.sh b/provisioning/Modules/Security/secharden-wazuh.sh deleted file mode 100644 index e52367d..0000000 --- a/provisioning/Modules/Security/secharden-wazuh.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -######################################### -#Core framework functions... -######################################### - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -export PROJECT_ROOT_PATH -PROJECT_ROOT_PATH="$(cd "$SCRIPT_DIR/../../.." && pwd)" - -export GIT_VENDOR_PATH_ROOT -GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/" - -export KNELShellFrameworkRoot -KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework" - -source "$KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars" - -for framework_include_file in "$KNELShellFrameworkRoot"/Framework-Includes/*; do - source "$framework_include_file" -done - -for project_include_file in "$PROJECT_ROOT_PATH"/Project-Includes/*; do - source "$project_include_file" -done - - -######################################### -# Core script code begins here -######################################### - -# We don't want to run this on the wazuh server, otherwise bad things happen... - -export TSYS_NSM_CHECK -TSYS_NSM_CHECK="$(hostname |grep -c tsys-nsm ||true)" - -if [ "$TSYS_NSM_CHECK" -eq 0 ]; then - - if [ -f /usr/share/keyrings/wazuh.gpg ]; then - rm -f /usr/share/keyrings/wazuh.gpg - fi - -curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import -chmod 644 /usr/share/keyrings/wazuh.gpg -echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" > /etc/apt/sources.list.d/wazuh.list -apt-get update - -WAZUH_MANAGER="tsys-nsm.knel.net" apt-get -y install wazuh-agent - -systemctl daemon-reload -systemctl enable wazuh-agent -systemctl start wazuh-agent || true - -echo "wazuh-agent hold" | dpkg --set-selections - -fi \ No newline at end of file diff --git a/provisioning/Project-ConfigFiles/CONFIG_VARS b/provisioning/Project-ConfigFiles/CONFIG_VARS deleted file mode 100644 index d0c99d8..0000000 --- a/provisioning/Project-ConfigFiles/CONFIG_VARS +++ /dev/null @@ -1,3 +0,0 @@ - -export DL_ROOT -DL_ROOT="https://dl.knownelement.com/KNEL/FetchApply/" \ No newline at end of file diff --git a/provisioning/Project-Includes/LocalHelp.sh b/provisioning/Project-Includes/LocalHelp.sh deleted file mode 100644 index de3918f..0000000 --- a/provisioning/Project-Includes/LocalHelp.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -function LocalHelp() -{ - echo "$0 is " - echo "$0 takes arguments: " - echo "1) " - echo "2) " - echo ":" - echo "" - echo "" - echo "" -} diff --git a/provisioning/Project-Includes/PreflightCheck.sh b/provisioning/Project-Includes/PreflightCheck.sh deleted file mode 100644 index 94e736a..0000000 --- a/provisioning/Project-Includes/PreflightCheck.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -function PreflightCheck() -{ - -export curr_user="$USER" -export user_check - -user_check="$(echo "$curr_user" | grep -c root)" - - -if [ "$user_check" -ne 1 ]; then - print_error "Must run as root." - error_out -fi - -echo "All checks passed...." - -} diff --git a/provisioning/Project-Includes/pi-detect.sh b/provisioning/Project-Includes/pi-detect.sh deleted file mode 100644 index 29bce4d..0000000 --- a/provisioning/Project-Includes/pi-detect.sh +++ /dev/null @@ -1,13 +0,0 @@ -# shellcheck shell=bash disable=SC2148 # sourced function file (no shebang by design) -function pi-detect() -{ -print_info Now running "${FUNCNAME[0]}".... -if [ -f /sys/firmware/devicetree/base/model ] ; then -export IS_RASPI="1" -fi - -if [ ! -f /sys/firmware/devicetree/base/model ] ; then -export IS_RASPI="0" -fi -print_info Completed running "${FUNCNAME[0]}" -} \ No newline at end of file diff --git a/provisioning/SetupNewSystem.sh b/provisioning/SetupNewSystem.sh deleted file mode 100644 index 00e8fd2..0000000 --- a/provisioning/SetupNewSystem.sh +++ /dev/null @@ -1,431 +0,0 @@ -#!/usr/bin/bash - -##### -#Core framework functions... -##### - - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -export PROJECT_ROOT_PATH -PROJECT_ROOT_PATH="$(cd "$SCRIPT_DIR/.." && pwd)" - -export GIT_VENDOR_PATH_ROOT -GIT_VENDOR_PATH_ROOT="$PROJECT_ROOT_PATH/vendor/git@git.knownelement.com/29418/" - -export KNELShellFrameworkRoot -KNELShellFrameworkRoot="$GIT_VENDOR_PATH_ROOT/KNEL/KNELShellFramework" - -export CONFIGFILES_PATH -CONFIGFILES_PATH="$PROJECT_ROOT_PATH/provisioning/ConfigFiles" - -export MODULES_PATH -MODULES_PATH="$PROJECT_ROOT_PATH/provisioning/Modules" - -export SCRIPTS_PATH -SCRIPTS_PATH="$PROJECT_ROOT_PATH/provisioning/scripts" - -source "$KNELShellFrameworkRoot/Framework-ConfigFiles/FrameworkVars" - -for framework_include_file in "$KNELShellFrameworkRoot"/Framework-Includes/*; do - source "$framework_include_file" -done - -for project_include_file in "$PROJECT_ROOT_PATH"/Project-Includes/*; do - source "$project_include_file" -done - -# Start actual script logic here... - -################# -#Global variables -################# - -apt-get -y install git sudo dmidecode curl - -export UBUNTU_CHECK -UBUNTU_CHECK="$(distro | grep -c Ubuntu || true)" - -export IS_PHYSICAL_HOST -IS_PHYSICAL_HOST="$(/usr/sbin/dmidecode -t System | grep -c Dell || true)" - -export SUBODEV_CHECK -SUBODEV_CHECK="$(getent passwd | grep -c subodev || true)" - -export LOCALUSER_CHECK -LOCALUSER_CHECK="$(getent passwd | grep -c localuser || true)" - -####################### -# Support functions -####################### - -function global-oam() { - print_info "Now running ${FUNCNAME[0]}...." - - cat "$SCRIPTS_PATH/up2date.sh" >/usr/local/bin/up2date.sh && chmod +x /usr/local/bin/up2date.sh - - bash "$MODULES_PATH/OAM/oam-librenms.sh" - - print_info "Completed running ${FUNCNAME[0]}" - -} - -function global-systemServiceConfigurationFiles() { - print_info "Now running ${FUNCNAME[0]}...." - - cat "$CONFIGFILES_PATH/ZSH/tsys-zshrc" >/etc/zshrc - cat "$CONFIGFILES_PATH/SMTP/aliases" >/etc/aliases - cat "$CONFIGFILES_PATH/Syslog/rsyslog.conf" >/etc/rsyslog.conf - - newaliases - - print_info "Completed running ${FUNCNAME[0]}" -} - -function global-installPackages() { - print_info "Now running ${FUNCNAME[0]}...." - - # Setup webmin repo, used for RBAC/2fa PAM - - curl https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh >/tmp/webmin-setup.sh - sh /tmp/webmin-setup.sh -f && rm -f /tmp/webmin-setup.sh - - # Setup tailscale - - curl -fsSL https://tailscale.com/install.sh | sh - - # - #Patch the system - # - - /usr/local/bin/up2date.sh - - #Remove stuff we don't want - - export DEBIAN_FRONTEND="noninteractive" \ - && apt-get -qq --yes --purge \ - remove \ - systemd-timesyncd \ - chrony \ - telnet \ - inetutils-telnet \ - wpasupplicant \ - modemmanager \ - nano \ - multipath-tools \ - || true - - apt-get -y --purge autoremove - - # add stuff we want - - print_info ""Now installing all the packages..."" - - DEBIAN_FRONTEND="noninteractive" apt-get -qq --yes -o Dpkg::Options::="--force-confold" install \ - virt-what \ - auditd \ - audispd-plugins \ - cloud-guest-utils \ - aide \ - htop \ - snmpd \ - ncdu \ - iftop \ - iotop \ - cockpit \ - cockpit-bridge \ - cockpit-doc \ - cockpit-networkmanager \ - cockpit-packagekit \ - cockpit-pcp \ - cockpit-sosreport \ - cockpit-storaged \ - cockpit-system \ - cockpit-ws \ - nethogs \ - sysstat \ - ngrep \ - acct \ - lsb-release \ - screen \ - tailscale \ - tmux \ - vim \ - command-not-found \ - lldpd \ - ansible-core \ - net-tools \ - dos2unix \ - gpg \ - molly-guard \ - lshw \ - fzf \ - ripgrep \ - sudo \ - mailutils \ - clamav \ - sl \ - logwatch \ - git \ - net-tools \ - tshark \ - tcpdump \ - lynis \ - glances \ - zsh \ - zsh-autosuggestions \ - zsh-syntax-highlighting \ - fonts-powerline \ - webmin \ - usermin \ - ntpsec \ - ntpsec-ntpdate \ - tuned \ - cockpit \ - iptables \ - netfilter-persistent \ - iptables-persistent \ - pflogsumm \ - postfix - - export KALI_CHECK - KALI_CHECK="$(distro | grep -c kali || true)" - - export VIRT_TYPE - VIRT_TYPE="$(virt-what)" - - export IS_VIRT_GUEST - IS_VIRT_GUEST="$(echo "$VIRT_TYPE" | grep -Ec 'hyperv|kvm' || true)" - - export IS_KVM_GUEST - IS_KVM_GUEST="$(echo "$VIRT_TYPE" | grep -c 'kvm' || true)" - - if [[ $IS_KVM_GUEST = 1 ]]; then - apt -y install qemu-guest-agent - fi - - if [[ $KALI_CHECK -eq 0 ]];then - DEBIAN_FRONTEND="noninteractive" apt-get -qq --yes -o Dpkg::Options::="--force-confold" install \ - latencytop \ - cockpit-tests || true - fi - - if [[ $IS_PHYSICAL_HOST -gt 0 ]]; then - export DEBIAN_FRONTEND="noninteractive" && apt-get -qq --yes -o Dpkg::Options::="--force-confold" install \ - i7z \ - thermald \ - cpufrequtils \ - linux-cpupower - # power-profiles-daemon - fi - -############################ -# Secrets agents -############################ - -# bitwarden cli - -# vault cli - - print_info "Completed running ${FUNCNAME[0]}" -} - -function global-postPackageConfiguration() { - - print_info "Now running ${FUNCNAME[0]}" - - systemctl --now enable auditd - - systemctl stop postfix - - cat "$CONFIGFILES_PATH/SMTP/postfix_generic" >/etc/postfix/generic - postmap /etc/postfix/generic - - postconf -e "inet_protocols = ipv4" - postconf -e "inet_interfaces = 127.0.0.1" - postconf -e "mydestination= 127.0.0.1" - postconf -e "relayhost = tsys-cloudron.knel.net" - postconf -e "smtp_generic_maps = hash:/etc/postfix/generic" - # smtp_generic_maps = hash:/etc/postfix/generic - - systemctl restart postfix - - #This is under test/dev and may fail - echo "hi from root to root" | mail -s "hi directly to root from $(hostname)" root - - chsh -s "$(which zsh)" root - - if [ "$LOCALUSER_CHECK" -gt 0 ]; then - chsh -s "$(which zsh)" localuser - fi - - if [ "$SUBODEV_CHECK" -gt 0 ]; then - chsh -s "$(which zsh)" subodev - fi - - ###Post package deployment bits - - cat "$CONFIGFILES_PATH/DHCP/dhclient.conf" >/etc/dhcp/dhclient.conf - - # Authoritative recursive DNS via the redundant pfv-netinfra-01/02 pair. - # Replace whatever is at /etc/resolv.conf (including a systemd-resolved or - # NetworkManager symlink) with the managed static file so every lookup goes - # to our servers and nothing else rewrites it behind our backs. - rm -f /etc/resolv.conf - cat "$CONFIGFILES_PATH/Resolv/resolv.conf" >/etc/resolv.conf - chmod 644 /etc/resolv.conf - - systemctl stop snmpd && /etc/init.d/snmpd stop - - cat "$CONFIGFILES_PATH/SNMP/snmp-sudo.conf" >/etc/sudoers.d/Debian-snmp - sed -i "s|-Lsd|-LS6d|" /lib/systemd/system/snmpd.service - - pi-detect - - if [ "$IS_RASPI" = 1 ]; then - cat "$CONFIGFILES_PATH/SNMP/snmpd-rpi.conf" >/etc/snmp/snmpd.conf || true - fi - - if [ "$IS_PHYSICAL_HOST" = 1 ]; then - cat "$CONFIGFILES_PATH/SNMP/snmpd-physicalhost.conf" >/etc/snmp/snmpd.conf || true - fi - - if [ "$IS_VIRT_GUEST" = 1 ]; then - cat "$CONFIGFILES_PATH/SNMP/snmpd.conf" >/etc/snmp/snmpd.conf || true - fi - - systemctl daemon-reload && systemctl restart snmpd && /etc/init.d/snmpd restart - - cat "$CONFIGFILES_PATH/NetworkDiscovery/lldpd" >/etc/default/lldpd - systemctl restart lldpd - - cat "$CONFIGFILES_PATH/Cockpit/disallowed-users" >/etc/cockpit/disallowed-users - systemctl restart cockpit - - export LIBRENMS_CHECK - LIBRENMS_CHECK="$(hostname | grep -c tsys-librenms || true)" - - if [ "$LIBRENMS_CHECK" -eq 0 ]; then - DEBIAN_FRONTEND="noninteractive" apt-get -qq --yes -o Dpkg::Options::="--force-confold" install rsyslog - systemctl stop rsyslog - systemctl start rsyslog - fi - - export NTP_SERVER_CHECK - NTP_SERVER_CHECK="$(hostname | grep -Ec 'pfv-netboot|pfvsvrpi|pfv-netinfra' || true)" - - if [ "$NTP_SERVER_CHECK" -eq 0 ]; then - - cat "$CONFIGFILES_PATH/NTP/ntp.conf" >/etc/ntpsec/ntp.conf - systemctl restart ntpsec.service - fi - - systemctl stop postfix - systemctl start postfix - - /usr/sbin/accton on - - if [ "$IS_PHYSICAL_HOST" -gt 0 ]; then - cpufreq-set -r -g performance - cpupower frequency-set --governor performance - - # Potentially merge the below if needed. - # power-profiles-daemon - # powerprofilesctl set performance - #tsys1# systemctl enable power-profiles-daemon - #tsys1# systemctl start power-profiles-daemon - - fi - - if [ "$IS_VIRT_GUEST" = 1 ]; then - tuned-adm profile virtual-guest - fi - - print_info "Completed running ${FUNCNAME[0]}" -} - -#################################################################################################### -# Run various modules -#################################################################################################### - -#################################################################################################### -# Security Hardening -#################################################################################################### - -# SSH - -function secharden-ssh() { - print_info "Now running ${FUNCNAME[0]}" - - bash "$MODULES_PATH/Security/secharden-ssh.sh" - - print_info "Completed running ${FUNCNAME[0]}" -} - -function secharden-wazuh() { - print_info "Now running ${FUNCNAME[0]}" - bash "$MODULES_PATH/Security/secharden-wazuh.sh" - print_info "Completed running ${FUNCNAME[0]}" -} - -function secharden-2fa() { - print_info "Now running ${FUNCNAME[0]}" - bash "$MODULES_PATH/Security/secharden-2fa.sh" - print_info "Completed running ${FUNCNAME[0]}" -} - -function secharden-scap-stig() { - print_info "Now running ${FUNCNAME[0]}" - bash "$MODULES_PATH/Security/secharden-scap-stig.sh" - print_info "Completed running ${FUNCNAME[0]}" -} - -function secharden-agents() { - print_info "Now running ${FUNCNAME[0]}" - bash "$MODULES_PATH/Security/secharden-audit-agents.sh" - print_info "Completed running ${FUNCNAME[0]}" -} - -function secharden-auto-upgrades() { - print_info "Now running ${FUNCNAME[0]}" - #curl --silent ${DL_ROOT}/Modules/Security/secharden-ssh.sh|$(which bash) - print_info "Completed running ${FUNCNAME[0]}" -} - - - - -#################################################################################################### -# Authentication -#################################################################################################### - -function auth-cloudron-ldap() { - print_info "Now running ${FUNCNAME[0]}" - #curl --silent ${DL_ROOT}/Modules/Auth/auth-cloudron-ldap.sh|$(which bash) - print_info "Completed running ${FUNCNAME[0]}" -} - -#################################################################################################### -# RUn the various functions in the correct order -#################################################################################################### - -echo >"$LOGFILENAME" - -print_info "Execution starting at $CURRENT_TIMESTAMP..." - -PreflightCheck -global-oam -global-installPackages -global-systemServiceConfigurationFiles -global-postPackageConfiguration - -secharden-ssh -secharden-wazuh -secharden-scap-stig -secharden-2fa -#secharden-agents -#secharden-auto-upgrades - -#auth-cloudron-ldap - -print_info "Execution ended at $CURRENT_TIMESTAMP..." diff --git a/provisioning/legacy/profiled-tmux.sh b/provisioning/legacy/profiled-tmux.sh deleted file mode 100644 index 7a51ea6..0000000 --- a/provisioning/legacy/profiled-tmux.sh +++ /dev/null @@ -1,5 +0,0 @@ -# shellcheck shell=bash disable=SC2148 # sourced .bashrc profile fragment -if command -v tmux &> /dev/null && [ -n "$PS1" ] && [[ ! "$TERM" =~ screen ]] && [[ ! "$TERM" =~ tmux ]] && [ -z "$TMUX" ]; then - tmux a -t default || exec tmux new -s default && exit; -fi - diff --git a/provisioning/legacy/profiled-tsys-shell.sh b/provisioning/legacy/profiled-tsys-shell.sh deleted file mode 100644 index 8df5b84..0000000 --- a/provisioning/legacy/profiled-tsys-shell.sh +++ /dev/null @@ -1,2 +0,0 @@ -# shellcheck shell=bash disable=SC2148 # sourced .bashrc profile fragment -export HISTTIMEFORMAT="%m/%d/%Y %T " \ No newline at end of file diff --git a/provisioning/legacy/prox7.sh b/provisioning/legacy/prox7.sh deleted file mode 100644 index 78ad59f..0000000 --- a/provisioning/legacy/prox7.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -rm -f /etc/apt/sources.list.d/* -echo "deb https://download.proxmox.com/debian/pve bookworm pve-no-subscription" > /etc/apt/sources.list.d/pve-install-repo.list -wget https://download.proxmox.com/debian/proxmox-release-bookworm.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg -apt update && apt -y full-upgrade -apt-get -y install ifupdown2 ipmitool ethtool net-tools lshw - -#curl -s http://dl.turnsys.net/newSrv.sh|/bin/bash \ No newline at end of file diff --git a/provisioning/scripts/up2date.sh b/provisioning/scripts/up2date.sh deleted file mode 100644 index 5370536..0000000 --- a/provisioning/scripts/up2date.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -echo "Running apt-get update" -export DEBIAN_FRONTEND="noninteractive" && apt-get -qq --yes update - -echo "Running apt-get dist-upgrade" -export DEBIAN_FRONTEND="noninteractive" && apt-get -qq --yes dist-upgrade - -echo "Running apt-get upgrade" -export DEBIAN_FRONTEND="noninteractive" && apt-get -qq --yes upgrade - - -echo "Running apt-get purge" -export DEBIAN_FRONTEND="noninteractive" && apt-get -qq --purge autoremove --yes -export DEBIAN_FRONTEND="noninteractive" && apt-get -qq autoclean --yes - diff --git a/switches/pfv-core-sw01.cmds b/switches/pfv-core-sw01.cmds deleted file mode 100644 index bd73bf5..0000000 --- a/switches/pfv-core-sw01.cmds +++ /dev/null @@ -1,7 +0,0 @@ -! pfv-core-sw01 — Dell PowerConnect 5448 (core switch, rack 5) -! Need running-config to diagnose ch1 port mismatch (g16 up but not in LAG, g17 down) -terminal datadump -enable -show running-config -show interfaces configuration -show interfaces description diff --git a/switches/pfv-tor3-stor.cmds b/switches/pfv-tor3-stor.cmds deleted file mode 100644 index 732517f..0000000 --- a/switches/pfv-tor3-stor.cmds +++ /dev/null @@ -1,12 +0,0 @@ -! pfv-tor3-stor — Neyland 24T (Radlan-based, rack 3 storage TOR) -! Radlan CLI uses different keywords than DNOS -enable -show system -show inventory -show interfaces configuration -show interfaces description -show port-channel -show lag -show vlan database -show vlan -show running-config diff --git a/ups/README.md b/ups/README.md deleted file mode 100644 index 5ee3b0f..0000000 --- a/ups/README.md +++ /dev/null @@ -1,210 +0,0 @@ -# UPS Management (NUT — Network UPS Tools) - -Centralized UPS monitoring for the server room via -[NUT](https://networkupstools.org/), running on **pfv-tsys1**. USB HID UPS -units feed one `upsd` network server; Home Assistant polls it over Tailscale for -real-time power/load/runtime tracking, and a local `upsmon` shuts the hypervisor -down gracefully when battery is low. - -> **Why NUT (not apcupsd)?** Two different UPS brands (APC + Tripp Lite) must be -> covered. `apcupsd` only supports APC, so it would require a second daemon -> stack. NUT's `usbhid-ups` driver speaks to **both** via the USB HID Power -> Device class, and Home Assistant ships a first-class NUT integration. - -## Hardware - -| UPS | Model | VID:PID | USB Serial | Status | -|-----|-------|---------|------------|--------| -| **APC** | Smart-UPS C 1500 (FW 02.2) | `051d:0003` | `AS1213210423` | **LIVE** | -| **Tripp Lite** | UPS (HID PDC) | `09ae:3016` | `2352CVLSM871900694` | **Blocked** — see below | - -## Current State (2026-07-30) - -### APC Smart-UPS C 1500 — OPERATIONAL - -Fully reporting via `usbhid-ups` + `APC HID 0.100` subdriver. Data validated: - -``` -battery.charge: 100 battery.runtime: 1800 battery.voltage: 27.4 -ups.status: OL ups.load: (via HA) ups.model: Smart-UPS C 1500 -``` - -### Tripp Lite UPS — BLOCKED (hardware issue) - -The driver finds the device, matches the `TrippLite HID 0.85` subdriver, claims -the interface, and reads the HID descriptor — but **fails reading the 878-byte -HID Report Descriptor** (`Resource temporarily unavailable` / EAGAIN after 5s). -The driver is masked to prevent restart-loop spam. - -USB descriptors (manufacturer, product, serial) are readable via `lsusb -v` and -`nut-scanner`, but the bulk control transfer for the full report descriptor -times out. Likely causes: - -1. **USB hub** — the Tripp Lite is behind a Genesys Logic hub (`05e3:0608`). - Try plugging directly into a motherboard USB port. -2. **USB cable** — try a high-quality data cable (not charge-only). -3. **UPS firmware** — the USB controller may not properly implement all HID - endpoints. - -**To retry after physical reseat:** -```bash -# On pfv-tsys1: -systemctl unmask nut-driver@tripp-lite-ups -systemctl start nut-driver@tripp-lite-ups -upsc tripp-lite-ups@localhost -``` - -## Architecture - -``` -pfv-tsys1 (192.168.3.11 / Tailscale 100.121.189.98) - ├─ APC Smart-UPS C 1500 ──┐ - └─ Tripp Lite UPS (masked) ──┤ USB HID - ▼ - nut-driver@apc-smartups-c1500 (usbhid-ups) - ▼ - upsd :3493 (LISTEN 127.0.0.1 + Tailscale + LAN) - ▼ ▼ - upsmon (local) Home Assistant (NUT integration) - graceful shutdown via LAN 192.168.3.11 (HAOS can't - route to Tailscale IPs) -``` - -- **Driver layer** — `usbhid-ups` process, pinned by USB serial. Debian uses - templated `nut-driver@.service` units managed by - `nut-driver-enumerator`. -- **Server layer** — `upsd` exposes UPS data on TCP 3493 (localhost + Tailscale - + LAN). Clients authenticate via `upsd.users`. -- **Monitor layer** — `upsmon` runs locally as `master` to trigger - `SHUTDOWNCMD` (`/sbin/shutdown -h now`) when a UPS reports `LOWBATT`. -- **Home Assistant** — native NUT integration connects to `upsd` over Tailscale - and exposes `ups.load`, `battery.runtime`, `ups.status`, etc. as sensors. - -### Key deployment lesson: udev must cover raw USB devices - -The `usbhid-ups` driver opens `/dev/bus/usb/BBB/DDD` (raw USB device files), -**not** `/dev/hidraw*`. After calling `setuid(111)` to drop to the `nut` user, -it needs write access to those raw USB files. The udev rule must match -`SUBSYSTEM=="usb"` by vendor/product ID to set `GROUP="nut"` — matching only -`hidraw` is insufficient. See `/etc/udev/rules.d/99-nut-ups.rules`. - -## Scripts - -NUT host scripts run on pfv-tsys1 via `tests/remote.sh`: - -```bash -# Idempotent install + configure (safe to re-run): -PROX_HOST=pfv-tsys1 bash tests/remote.sh prox-file ups/setup.sh - -# Discover USB UPS + NUT state (read-only diagnostic): -PROX_HOST=pfv-tsys1 bash tests/remote.sh prox-file ups/discover.sh - -# Query UPS data + service health: -PROX_HOST=pfv-tsys1 bash tests/remote.sh prox-file ups/status.sh -``` - -The HA integration script runs from your workstation (needs HA API access): - -```bash -# Add the NUT integration to Home Assistant (idempotent): -bash ups/setup-ha-nut.sh -``` - -`setup.sh` accepts environment overrides for serials/VIDs/PIDs/usernames, so it -can be repurposed for other hosts or UPS units. Passwords for `monuser` and -`homeassistant` are auto-generated on first run and reused on subsequent runs -(stored in `/etc/nut/upsd.users`). - -Set `TRIPP_ENABLED=0` to skip the Tripp Lite entirely (useful if it's physically -unplugged). - -## Configuration files on pfv-tsys1 - -| File | Purpose | -|------|---------| -| `/etc/udev/rules.d/99-nut-ups.rules` | Grant nut group rw on raw USB + hidraw devices (both subsystems) | -| `/etc/nut/ups.conf` | `usbhid-ups` device(s), pinned by serial + subdriver | -| `/etc/nut/upsd.conf` | `LISTEN 127.0.0.1` + `LISTEN ` + `LISTEN ` on port 3493 | -| `/etc/nut/upsd.users` | `monuser` (master) + `homeassistant` (read-only) credentials | -| `/etc/nut/upsmon.conf` | Local master monitor + `SHUTDOWNCMD` | -| `/etc/nut/nut.conf` | `MODE=netserver` | - -## Home Assistant integration - -The NUT integration is added automatically by `setup-ha-nut.sh`, which drives -HA's REST config-flow API. It is idempotent (skips if the entry exists). - -```bash -# Prerequisites: create token + password files (one-time): -mkdir -p ~/.config/pfvcluster -# HA → Profile → Long-Lived Access Tokens → Create Token: -echo -n 'YOUR_HA_TOKEN' > ~/.config/pfvcluster/ha-token -# Password is in /etc/nut/upsd.users on pfv-tsys1 (the homeassistant user): -echo -n 'YOUR_NUT_PASS' > ~/.config/pfvcluster/nut-password -chmod 600 ~/.config/pfvcluster/{ha-token,nut-password} - -# Run: -bash ups/setup-ha-nut.sh -``` - -### Why LAN IP, not Tailscale - -upsd listens on **both** the Tailscale IP (`100.121.189.98`) **and** the LAN IP -(`192.168.3.11`). The HA NUT integration uses the **LAN IP** because HAOS runs -Tailscale as an isolated add-on container — the HA core container cannot route -to Tailscale IPs. Since pfv-bms (HA, `192.168.3.12`) and pfv-tsys1 (`192.168.3.11`) -share the same vmbr0 bridge, LAN connectivity is instant and reliable. - -### Manual UI alternative - -In Home Assistant → **Settings → Devices & Services → Add Integration → NUT**: - -| Field | Value | -|-------|-------| -| Host | `192.168.3.11` (LAN — HAOS can't reach Tailscale IPs from the HA container) | -| Port | `3493` | -| Username | `homeassistant` | -| Password | *(stored in `/etc/nut/upsd.users` on pfv-tsys1)* | -| UPS | `apc-smartups-c1500` | - -### Live sensors - -HA exposes UPS data as sensors (prefix `sensor.apc_smartups_c1500_`): -`battery_charge`, `status` (Online/On Battery), `status_data` (OL/OB/DISCHRG). -Additional sensors (load, runtime, voltage) populate as the UPS reports them. - -## Daily operations - -From pfv-tsys1 (or any tailnet host with NUT client installed): - -```bash -# List UPS units served by upsd -upsc -l pfv-tsys1 - -# Full variable dump for one UPS -upsc apc-smartups-c1500@pfv-tsys1 - -# Battery runtime (the only runtime/charge data this UPS exposes) -upsc apc-smartups-c1500@pfv-tsys1 battery.runtime -``` - -## Notes - -- **No USB passthrough to the HA VM.** Keeping the UPS on the host preserves - hypervisor graceful-shutdown capability and matches the `powerman/` pattern - (PDU managed on the host where the adapter physically lives). -- **No `ups.load` / `ups.realpower` on this UPS (FW 02.2, mfg 2012):** The - APC Smart-UPS C 1500 does not expose load or power data over USB HID. - Both NUT `usbhid-ups` and `apcupsd` (USB mode, tested 2026-07-30) read the - same HID descriptor — the variable simply isn't there. This means the HA - NUT integration provides **battery/runtime/status sensors only**, not - wattage for the Energy Dashboard. - - **apcupsd test note:** Debian's `apcupsd` package conflicts with - `nut-server` (mutually exclusive). apcupsd USB mode returned `COMMLOST` - even before we could check load. The APC Smart Serial protocol (serial - cable, AP940-1524C, ~$30) DOES report load%, but this requires a serial - port on the UPS and on the host. - - **Energy Dashboard path:** A smart plug (Shelly Plug S / TP-Link Kasa, - ~$15-25) on the UPS output reports real watts natively and feeds the - Energy Dashboard with zero UPS-driver hacking. The NUT sensors remain - valuable for outage detection and graceful-shutdown automations. diff --git a/ups/discover.sh b/ups/discover.sh deleted file mode 100644 index 0a82d4b..0000000 --- a/ups/discover.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/bash -# -# ups/discover.sh — probe USB UPS units and NUT state on the local host -# -# Read-only. Prints everything needed to configure NUT. No changes made. -# -# Usage (run ON the target host via remote.sh): -# PROX_HOST=pfv-tsys1 bash tests/remote.sh prox-file ups/discover.sh -# -set -uo pipefail - -echo "======================================================" -echo " UPS / NUT Discovery on $(hostname)" -echo "======================================================" - -# --- 1. USB UPS devices ------------------------------------------------------ -echo "" -echo "--- [1/5] USB UPS devices (lsusb) ---" -lsusb 2>/dev/null | grep -iE "UPS|American Power|Tripp|APC" || echo " (no UPS devices found in lsusb)" - -echo "" -echo "--- [2/5] UPS detail (vendor/product/serial/model) ---" -# Common UPS vendor IDs: 051d (APC), 09ae (Tripp Lite), 0463 (Eaton), -# 06da (MGE), 0764 (Cyber Power) -for vid in 051d 09ae 0463 06da 0764; do - while read -r bus dev pid; do - [ -n "$bus" ] || continue - echo " --- $bus:$dev ($vid:$pid) ---" - lsusb -v -s "${bus}:${dev}" 2>/dev/null \ - | grep -iE "iManufacturer|iProduct|iSerial|bcdDevice" \ - | sed 's/^/ /' - done < <(lsusb 2>/dev/null | awk -v v="$vid" '$0~v{split($2,a,":"); split($4,b,":"); print a[1], b[1], $6}') -done - -# --- 2. sysfs paths (for udev rules) ----------------------------------------- -echo "" -echo "--- [3/5] sysfs device paths + serials ---" -for d in /sys/bus/usb/devices/*; do - man=$(cat "$d/manufacturer" 2>/dev/null) - prod=$(cat "$d/product" 2>/dev/null) - ser=$(cat "$d/serial" 2>/dev/null) - vid=$(cat "$d/idVendor" 2>/dev/null) - pid=$(cat "$d/idProduct" 2>/dev/null) - if echo "$man $prod" | grep -qiE "apc|tripp|power conversion|ups|eaton|mge|cyber power"; then - # Resolve stable ID_PATH for udev pinning - path=$(udevadm info -q property -p "$d" 2>/dev/null | awk -F= '/^ID_PATH=/{print $2}') - echo " $d" - echo " vendor=$vid product=$pid" - echo " manufacturer=$man" - echo " product=$prod" - echo " serial=$ser" - echo " ID_PATH=$path" - fi -done - -# --- 3. HID device nodes ----------------------------------------------------- -echo "" -echo "--- [4/5] HID device nodes ---" -ls -la /dev/hidraw* /dev/usb/hiddev* 2>/dev/null || echo " (no hidraw/hiddev nodes)" - -# --- 4. NUT install state ---------------------------------------------------- -echo "" -echo "--- [5/5] NUT install + service state ---" -if dpkg -l nut-server nut-client 2>/dev/null | grep -q '^ii'; then - echo " NUT installed:" - dpkg -l nut-server nut-client 2>/dev/null | awk '/^ii/{print " "$2" "$3}' -else - echo " NUT not installed (apt: nut-server nut-client)" -fi - -echo "" -echo " Services:" -for svc in nut-driver nut-server nut-monitor; do - printf " %-14s " "$svc:" - systemctl is-active "$svc" 2>/dev/null || true -done - -echo "" -echo " Existing config:" -# shellcheck disable=SC2012 # ls -la is intentional for human-readable listing -ls -la /etc/nut/ 2>/dev/null | sed 's/^/ /' || echo " (no /etc/nut)" - -echo "" -echo "======================================================" -echo " Discovery complete." -echo "======================================================" diff --git a/ups/ha-nut-setup.py b/ups/ha-nut-setup.py deleted file mode 100644 index 1c9eae3..0000000 --- a/ups/ha-nut-setup.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python3 -""" -ha-nut-setup.py — Add the Home Assistant NUT integration via REST config-flow API. - -Stdlib-only (no pip). Idempotent: skips if a NUT config entry already exists. - -Env: - HA_HOST (default pfv-bms.knel.net) - HA_PORT (default 8123) - HA_TOKEN (long-lived access token) - NUT_HOST (default 100.121.189.98) - NUT_PORT (default 3493) - NUT_USER (default homeassistant) - NUT_PASS (required) - NUT_UPS (default apc-smartups-c1500) -""" -import os, json, sys, time, urllib.request, urllib.error - -HA_HOST = os.environ.get("HA_HOST", "pfv-bms.knel.net") -HA_PORT = int(os.environ.get("HA_PORT", "8123")) -TOKEN = os.environ["HA_TOKEN"] -NUT_HOST = os.environ.get("NUT_HOST", "192.168.3.11") -NUT_PORT = int(os.environ.get("NUT_PORT", "3493")) -NUT_USER = os.environ.get("NUT_USER", "homeassistant") -NUT_PASS = os.environ["NUT_PASS"] -NUT_UPS = os.environ.get("NUT_UPS", "apc-smartups-c1500") -BASE = f"http://{HA_HOST}:{HA_PORT}" - -def api(method, path, data=None): - body = json.dumps(data).encode() if data else None - req = urllib.request.Request( - f"{BASE}/api{path}", data=body, method=method, - headers={"Authorization": f"Bearer {TOKEN}", - "Content-Type": "application/json"}) - try: - with urllib.request.urlopen(req, timeout=20) as r: - return json.loads(r.read()) - except urllib.error.HTTPError as e: - raw = e.read().decode() - try: - return json.loads(raw) - except Exception: - return {"_http_error": e.code, "_raw": raw[:300]} - except Exception as e: - return {"_error": str(e)} - -# ── verify token ── -cfg = api("GET", "/config") -if "_http_error" in cfg or "_error" in cfg: - print(f"Cannot reach HA or token invalid: {cfg}"); sys.exit(1) -print(f"HA {cfg.get('version')} — token valid") - -# ── check existing entries (idempotent) ── -entries = api("GET", "/config/config_entries/entry") -existing = [e for e in entries if e.get("domain") == "nut"] -if existing: - for e in existing: - print(f"NUT already configured: {e.get('title')} " - f"(data={json.dumps(e.get('data', {}))})") - print("Skipping — delete it in HA UI first if you want to re-run.") - sys.exit(0) -print("No existing NUT entry. Starting config flow.") - -# ── initiate flow ── -flow = api("POST", "/config/config_entries/flow", {"handler": "nut"}) -if "flow_id" not in flow: - print(f"Flow init failed: {json.dumps(flow)}"); sys.exit(1) -fid = flow["flow_id"] -print(f"Flow started: step={flow.get('step_id')} " - f"fields={[f.get('name') for f in flow.get('data_schema', [])]}") - -# ── submit connection details ── -creds = {"host": NUT_HOST, "port": NUT_PORT, - "username": NUT_USER, "password": NUT_PASS} -flow = api("POST", f"/config/config_entries/flow/{fid}", creds) -if flow.get("errors"): - print(f"Validation errors: {flow['errors']}"); sys.exit(1) -print(f"After submit: type={flow.get('type')} step={flow.get('step_id')}") - -# ── handle follow-up steps (UPS selection etc.) ── -while flow.get("type") == "form": - step = flow.get("step_id", "?") - schema = flow.get("data_schema", []) - print(f"Step '{step}': fields={[f.get('name') for f in schema]}") - for f in schema: - opts = f.get("options") or f.get("values") - if opts: - print(f" {f.get('name')} options: {opts}") - submission = {} - for f in schema: - nm = f.get("name") - ftype = f.get("type", "") - if ftype == "multi_select": - opts = f.get("options", []) - vals = [o[0] if isinstance(o, list) else o for o in opts] - submission[nm] = [NUT_UPS] if NUT_UPS in vals else vals[:1] - elif nm in creds: - submission[nm] = creds[nm] - elif "default" in f: - submission[nm] = f["default"] - elif ftype == "select": - opts = f.get("options", []) - vals = [o[0] if isinstance(o, list) else o for o in opts] - submission[nm] = NUT_UPS if NUT_UPS in vals else (vals[0] if vals else "") - fid = flow.get("flow_id", fid) - flow = api("POST", f"/config/config_entries/flow/{fid}", submission) - if flow.get("errors"): - print(f"Validation errors: {flow['errors']}"); sys.exit(1) - print(f" -> type={flow.get('type')} step={flow.get('step_id')}") - -# ── result ── -if flow.get("type") == "create_entry": - print(f"\nNUT integration created: {flow.get('title')}") -elif flow.get("type") == "abort": - print(f"\nFlow aborted: {flow.get('reason')}"); sys.exit(1) -else: - print(f"\nFinal state: {flow.get('type')} — {json.dumps(flow)[:200]}") - -# ── verify sensors ── -print("\nWaiting 10s for entities ...") -time.sleep(10) -states = api("GET", "/states") -ups = [s for s in states - if "apc_smartups" in s["entity_id"].lower() - or "sensor.ups_" in s["entity_id"].lower()] -if ups: - print(f"Found {len(ups)} UPS sensors:") - for e in sorted(ups, key=lambda x: x["entity_id"]): - st = e.get("state", "?") - unit = e.get("attributes", {}).get("unit_of_measurement", "") - name = e.get("attributes", {}).get("friendly_name", "") - print(f" {e['entity_id']:55s} {st:>8} {unit:4s} {name}") -else: - print("No UPS sensors yet (may still be initialising — check HA UI).") diff --git a/ups/setup-ha-nut.sh b/ups/setup-ha-nut.sh deleted file mode 100644 index 63b7b36..0000000 --- a/ups/setup-ha-nut.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -# -# setup-ha-nut.sh — Add the Home Assistant NUT integration via REST API. -# -# Idempotent: skips if a NUT entry already exists. Reads secrets from -# ~/.config/pfvcluster/ (ha-token, nut-password) or env vars. -# -# Usage: -# bash ups/setup-ha-nut.sh -# -# Env overrides: -# HA_TOKEN HA long-lived access token -# NUT_PASS NUT upsd password for the homeassistant user -# HA_HOST HA host (default pfv-bms.knel.net) -# NUT_HOST upsd host (default 192.168.3.11 — LAN, see README) -# NUT_PORT upsd port (default 3493) -# NUT_USER upsd user (default homeassistant) -# NUT_UPS UPS name (default apc-smartups-c1500) -# -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -CONF_DIR="${PFV_CONF_DIR:-$HOME/.config/pfvcluster}" - -# --- HA token --- -HA_TOKEN="${HA_TOKEN:-}" -if [[ -z "$HA_TOKEN" ]]; then - TOKEN_FILE="$CONF_DIR/ha-token" - if [[ -f "$TOKEN_FILE" ]]; then - HA_TOKEN="$(head -1 "$TOKEN_FILE" | tr -d '[:space:]')" - else - echo "error: no HA token. Set \$HA_TOKEN or create $TOKEN_FILE" >&2 - echo " (HA → Profile → Long-Lived Access Tokens → Create Token)" >&2 - exit 1 - fi -fi - -# --- NUT password --- -NUT_PASS="${NUT_PASS:-}" -if [[ -z "$NUT_PASS" ]]; then - PASS_FILE="$CONF_DIR/nut-password" - if [[ -f "$PASS_FILE" ]]; then - NUT_PASS="$(head -1 "$PASS_FILE" | tr -d '[:space:]')" - else - echo "error: no NUT password. Set \$NUT_PASS or create $PASS_FILE" >&2 - echo " (value is in /etc/nut/upsd.users on the NUT host)" >&2 - exit 1 - fi -fi - -# --- connection params (override for your own kit) --- -export HA_TOKEN -export NUT_PASS -export HA_HOST="${HA_HOST:-pfv-bms.knel.net}" -export HA_PORT="${HA_PORT:-8123}" -export NUT_HOST="${NUT_HOST:-192.168.3.11}" -export NUT_PORT="${NUT_PORT:-3493}" -export NUT_USER="${NUT_USER:-homeassistant}" -export NUT_UPS="${NUT_UPS:-apc-smartups-c1500}" - -echo "HA: ${HA_HOST}:${HA_PORT}" -echo "NUT: ${NUT_USER}@${NUT_HOST}:${NUT_PORT} (UPS: ${NUT_UPS})" -echo "" - -exec python3 "$SCRIPT_DIR/ha-nut-setup.py" diff --git a/ups/setup.sh b/ups/setup.sh deleted file mode 100644 index 43b3cd8..0000000 --- a/ups/setup.sh +++ /dev/null @@ -1,298 +0,0 @@ -#!/usr/bin/bash -# -# ups/setup.sh — idempotent Network UPS Tools (NUT) setup on pfv-tsys1 -# -# Installs NUT, configures two USB HID UPS units (APC + Tripp Lite) pinned by -# USB serial, runs upsd as a network server for Home Assistant polling, and -# runs upsmon locally so the hypervisor can shut down gracefully on battery. -# -# Designed to run ON the target host (pfv-tsys1) as root, idempotent. -# -# Usage: -# PROX_HOST=pfv-tsys1 bash tests/remote.sh prox-file ups/setup.sh -# -# Overrides (defaults suit pfv-tsys1): -# APC_SERIAL APC UPS USB serial (default AS1213210423) -# APC_VID/APC_PID APC vendor/product ID (default 051d / 0003) -# APC_NAME NUT section name for APC (default apc-smartups-c1500) -# TRIPP_SERIAL Tripp Lite UPS USB serial (default 2352CVLSM871900694) -# TRIPP_VID/TRIPP_PID Tripp Lite vendor/product (default 09ae / 3016) -# TRIPP_NAME NUT section name for Tripp (default tripp-lite-ups) -# TRIPP_SUBDRIVER Forced HID subdriver for Tripp (default "TrippLite HID 0.85") -# TRIPP_ENABLED Set to 0 to disable Tripp Lite (default 1) -# NUT_LISTEN_IPS space-separated upsd LISTEN IPs (default: auto Tailscale + 127.0.0.1) -# HA_USER upsd username for HA (default homeassistant) -# HA_PASSWORD upsd password for HA (default: reuse or generate) -# MON_USER upsd username for local upsmon (default monuser) -# MON_PASSWORD upsd password for upsmon (default: reuse or generate) -# -set -euo pipefail - -# --- Config (overridable via env) --- -APC_SERIAL="${APC_SERIAL:-AS1213210423}" -APC_VID="${APC_VID:-051d}" -APC_PID="${APC_PID:-0003}" -APC_NAME="${APC_NAME:-apc-smartups-c1500}" - -TRIPP_SERIAL="${TRIPP_SERIAL:-2352CVLSM871900694}" -TRIPP_VID="${TRIPP_VID:-09ae}" -TRIPP_PID="${TRIPP_PID:-3016}" -TRIPP_NAME="${TRIPP_NAME:-tripp-lite-ups}" -TRIPP_SUBDRIVER="${TRIPP_SUBDRIVER:-TrippLite HID 0.85}" -TRIPP_ENABLED="${TRIPP_ENABLED:-1}" - -HA_USER="${HA_USER:-homeassistant}" -MON_USER="${MON_USER:-monuser}" -NUT_PORT="${NUT_PORT:-3493}" -UDEV_RULE="/etc/udev/rules.d/99-nut-ups.rules" - -UPS_CONF="/etc/nut/ups.conf" -UPSD_CONF="/etc/nut/upsd.conf" -UPSD_USERS="/etc/nut/upsd.users" -UPS_CONF_MON="/etc/nut/upsmon.conf" -NUT_CONF="/etc/nut/nut.conf" - -# --- Helpers --- -gen_pw() { head -c 24 /dev/urandom | base64 | tr -d '/+=' | cut -c1-20; } - -# Reuse existing passwords if config already present (idempotent re-runs) -extract_pw() { # $1=user - if [ -f "$UPSD_USERS" ]; then - awk -v u="[$1]" ' - $0==u {inblk=1; next} - /^\[/ {inblk=0} - inblk && $1=="password" {gsub(/"/,"",$3); print $3; exit} - ' "$UPSD_USERS" 2>/dev/null - fi -} - -echo "============================================" -echo " NUT UPS Setup on $(hostname)" -echo " APC: $APC_NAME ($APC_VID:$APC_PID serial $APC_SERIAL)" -if [ "$TRIPP_ENABLED" = "1" ]; then - echo " Tripp Lite: $TRIPP_NAME ($TRIPP_VID:$TRIPP_PID serial $TRIPP_SERIAL)" -else - echo " Tripp Lite: DISABLED (TRIPP_ENABLED=0)" -fi -echo "============================================" - -# --- 0. Resolve / generate passwords (idempotent) --- -MON_PASSWORD="${MON_PASSWORD:-$(extract_pw "$MON_USER")}" -HA_PASSWORD="${HA_PASSWORD:-$(extract_pw "$HA_USER")}" -[ -n "$MON_PASSWORD" ] || MON_PASSWORD="$(gen_pw)" -[ -n "$HA_PASSWORD" ] || HA_PASSWORD="$(gen_pw)" - -# --- 0b. Auto-detect listen IPs for upsd --- -# Tailscale IP: tailnet clients (workstation, etc.) -# LAN IP: HAOS VMs where Tailscale runs as an isolated add-on (HA container -# cannot route to Tailscale IPs, so the shared-LAN bridge is required) -if [ -z "${NUT_LISTEN_IPS:-}" ]; then - NUT_LISTEN_IPS="127.0.0.1" - TS_IP=$(tailscale ip -4 2>/dev/null || true) - if [ -n "$TS_IP" ]; then - NUT_LISTEN_IPS="${NUT_LISTEN_IPS} ${TS_IP}" - else - echo " WARNING: No Tailscale IP detected." - fi - if [ "${NUT_INCLUDE_LAN:-1}" = "1" ]; then - LAN_IP=$(ip -4 addr show vmbr0 2>/dev/null | awk '/scope global/{print $2}' | cut -d/ -f1 | head -1) - if [ -z "$LAN_IP" ]; then - LAN_IP=$(hostname -I 2>/dev/null | awk '{print $1}') - fi - if [ -n "$LAN_IP" ]; then - NUT_LISTEN_IPS="${NUT_LISTEN_IPS} ${LAN_IP}" - fi - fi -fi -echo " upsd LISTEN IPs: ${NUT_LISTEN_IPS:-}" - -# --- 1. Install NUT --- -echo "" -echo "--- [1/8] Installing NUT (nut-server, nut-client) ---" -if dpkg -l nut-server 2>/dev/null | grep -q '^ii'; then - echo " NUT already installed: $(dpkg -l nut-server | awk '/^ii/{print $3}')" -else - apt-get update -qq && apt-get install -y -qq nut-server nut-client -fi -mkdir -p /etc/nut - -# --- 2. udev rules: grant nut group access to BOTH raw USB + hidraw devices --- -# CRITICAL: usbhid-ups opens /dev/bus/usb/BBB/DDD (raw USB), not /dev/hidraw. -# The driver drops to the nut user via setuid(), so the nut group needs write -# access to the raw USB device files. Matching on subsystem=="usb" by VID:PID -# is required because ATTRS{serial} does not reliably traverse for usb devices. -echo "" -echo "--- [2/8] Writing udev rules (raw USB + hidraw, group nut) ---" -{ - echo "# Stable permissions for NUT USB HID UPS units" - echo "# Generated by ups/setup.sh — grants the 'nut' group access to both" - echo "# the raw USB device files (/dev/bus/usb) and hidraw devices." - echo "# Match BOTH subsystems: the usbhid-ups driver opens the raw USB device" - echo "# after dropping to the nut user via setuid()." - echo "" - echo "# APC Smart-UPS C 1500 ($APC_VID:$APC_PID)" - echo "SUBSYSTEM==\"usb\", ATTR{idVendor}==\"$APC_VID\", ATTR{idProduct}==\"$APC_PID\", GROUP=\"nut\", MODE=\"0664\"" - echo "SUBSYSTEM==\"hidraw\", ATTRS{serial}==\"$APC_SERIAL\", GROUP=\"nut\", MODE=\"0660\"" - echo "" - echo "# Tripp Lite UPS ($TRIPP_VID:$TRIPP_PID)" - echo "SUBSYSTEM==\"usb\", ATTR{idVendor}==\"$TRIPP_VID\", ATTR{idProduct}==\"$TRIPP_PID\", GROUP=\"nut\", MODE=\"0664\"" - echo "SUBSYSTEM==\"hidraw\", ATTRS{serial}==\"$TRIPP_SERIAL\", GROUP=\"nut\", MODE=\"0660\"" -} > "$UDEV_RULE" -echo " Written: $UDEV_RULE" -udevadm control --reload-rules 2>/dev/null || true -udevadm trigger --subsystem-match=usb 2>/dev/null || true -udevadm trigger --subsystem-match=hidraw 2>/dev/null || true -sleep 1 - -# --- 3. ups.conf --- -echo "" -echo "--- [3/8] Writing ups.conf ---" -{ - echo "# NUT UPS devices — generated by ups/setup.sh on $(date)" - echo "" - echo "maxretry = 3" - echo "" - echo "[${APC_NAME}]" - echo " driver = usbhid-ups" - echo " port = auto" - echo " vendorid = ${APC_VID}" - echo " productid = ${APC_PID}" - echo " serial = ${APC_SERIAL}" - echo " desc = \"APC Smart-UPS C 1500\"" - if [ "$TRIPP_ENABLED" = "1" ]; then - echo "" - echo "[${TRIPP_NAME}]" - echo " driver = usbhid-ups" - echo " port = auto" - echo " vendorid = ${TRIPP_VID}" - echo " productid = ${TRIPP_PID}" - echo " serial = ${TRIPP_SERIAL}" - echo " subdriver = \"${TRIPP_SUBDRIVER}\"" - echo " desc = \"Tripp Lite UPS\"" - fi -} > "$UPS_CONF" -echo " Written: $UPS_CONF" - -# --- 4. upsd.conf: network server (localhost + Tailscale for HA) --- -echo "" -echo "--- [4/8] Writing upsd.conf ---" -{ - echo "# NUT upsd — generated by ups/setup.sh on $(date)" - for ip in $NUT_LISTEN_IPS; do - echo "LISTEN ${ip} ${NUT_PORT}" - done - echo "MAXAGE 25" -} > "$UPSD_CONF" -echo " Written: $UPSD_CONF (LISTEN: $(echo "$NUT_LISTEN_IPS" | tr '\n' ' '))" - -# --- 5. upsd.users: monuser (master) + homeassistant (read-only monitor) --- -echo "" -echo "--- [5/8] Writing upsd.users ---" -cat > "$UPSD_USERS" < "$UPS_CONF_MON" - -cat > "$NUT_CONF" </dev/null || true -chmod 640 "$UPS_CONF" "$UPSD_CONF" "$UPSD_USERS" "$UPS_CONF_MON" 2>/dev/null || true -chmod 644 "$NUT_CONF" 2>/dev/null || true - -# --- 7. Start services (Debian uses templated nut-driver@ units) --- -echo "" -echo "--- [7/8] Starting NUT services ---" - -# Re-read ups.conf to generate per-UPS driver instances -systemctl restart nut-driver-enumerator 2>/dev/null || true -sleep 2 - -# Start per-UPS driver instances -systemctl restart "nut-driver@${APC_NAME}" 2>/dev/null || true -if [ "$TRIPP_ENABLED" = "1" ]; then - systemctl restart "nut-driver@${TRIPP_NAME}" 2>/dev/null || true -else - systemctl stop "nut-driver@${TRIPP_NAME}" 2>/dev/null || true - systemctl mask "nut-driver@${TRIPP_NAME}" 2>/dev/null || true -fi -sleep 3 -systemctl restart nut-server 2>/dev/null || true -sleep 1 -systemctl restart nut-monitor 2>/dev/null || true - -echo "" -echo " Service status:" -for svc in "nut-driver@${APC_NAME}" "nut-driver@${TRIPP_NAME}" nut-server nut-monitor; do - if systemctl list-unit-files "$svc" >/dev/null 2>&1; then - printf " %-42s " "$svc" - systemctl is-active "$svc" 2>/dev/null || echo "(unknown)" - fi -done - -# --- 8. Validate --- -echo "" -echo "--- [8/8] Validation ---" -echo "" -echo " upsc — ${APC_NAME}:" -upsc "${APC_NAME}@localhost" 2>&1 | head -25 || echo " (APC UPS not responding yet)" -if [ "$TRIPP_ENABLED" = "1" ]; then - echo "" - echo " upsc — ${TRIPP_NAME}:" - upsc "${TRIPP_NAME}@localhost" 2>&1 | head -25 || echo " (Tripp Lite UPS not responding yet)" -fi - -echo "" -echo "============================================" -echo " Setup complete." -echo "" -echo " Home Assistant NUT integration:" -echo " Host: $(echo "$NUT_LISTEN_IPS" | awk '{print $2}') (or any LISTEN IP above)" -echo " Port: ${NUT_PORT}" -echo " Username: ${HA_USER}" -echo " Password: ${HA_PASSWORD}" -if [ "$TRIPP_ENABLED" = "1" ]; then - echo " UPS names: ${APC_NAME}, ${TRIPP_NAME}" -else - echo " UPS names: ${APC_NAME}" -fi -echo "" -echo " Save the HA password now — it is stored in ${UPSD_USERS}." -echo "============================================" diff --git a/ups/status.sh b/ups/status.sh deleted file mode 100644 index 0f8c4b8..0000000 --- a/ups/status.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/bash -# -# ups/status.sh — query NUT UPS state + service health (read-only) -# -# Usage (run ON the target host via remote.sh): -# PROX_HOST=pfv-tsys1 bash tests/remote.sh prox-file ups/status.sh -# -# shellcheck disable=SC2012 # ss/awk field extraction is intentional -set -uo pipefail - -APC_NAME="${APC_NAME:-apc-smartups-c1500}" -TRIPP_NAME="${TRIPP_NAME:-tripp-lite-ups}" - -echo "======================================================" -echo " NUT UPS Status on $(hostname)" -echo "======================================================" - -echo "" -echo "--- Services ---" -for svc in "nut-driver@${APC_NAME}" "nut-driver@${TRIPP_NAME}" nut-server nut-monitor; do - if systemctl list-unit-files "$svc" >/dev/null 2>&1; then - printf " %-42s " "$svc" - systemctl is-active "$svc" 2>/dev/null || echo "(unknown)" - fi -done - -for ups in "$APC_NAME" "$TRIPP_NAME"; do - echo "" - echo "--- ${ups} ---" - if upsc "${ups}@localhost" >/tmp/.nutstatus.$$ 2>&1; then - awk -v u="$ups" ' - BEGIN{printf " %s\n", u} - /^battery\.charge:/ {printf " battery.charge: %s\n", $3} - /^battery\.runtime:/ {printf " battery.runtime: %ss (%.0f min)\n", $3, $3/60} - /^battery\.voltage:/ {printf " battery.voltage: %s\n", $3} - /^ups\.status:/ {printf " ups.status: %s\n", $3} - /^ups\.load:/ {printf " ups.load: %s%%\n", $3} - /^ups\.power:/ {printf " ups.power: %s\n", $3} - /^ups\.realpower:/ {printf " ups.realpower: %s W\n", $3} - /^input\.voltage:/ {printf " input.voltage: %s\n", $3} - /^output\.voltage:/ {printf " output.voltage: %s\n", $3} - /^ups\.model:/ {printf " ups.model: %s\n", $3} - /^ups\.serial:/ {printf " ups.serial: %s\n", $3} - /^device\.mfr:/ {printf " device.mfr: %s\n", $3} - ' /tmp/.nutstatus.$$ - echo " (full dump: upsc ${ups}@localhost)" - else - echo " NOT RESPONDING:" - sed 's/^/ /' /tmp/.nutstatus.$$ - fi - rm -f /tmp/.nutstatus.$$ -done - -echo "" -echo "--- upsd LISTEN sockets ---" -ss -ltnp 2>/dev/null | grep -E "3493|nut" | sed 's/^/ /' || echo " (upsd not listening on 3493)" - -echo "" -echo "======================================================"