linuxrouter/ADMINISTRATORS_GUIDE.md

164 lines
6.9 KiB
Markdown
Raw Permalink Normal View History

2026-06-11 01:31:57 -04:00
# Administrators Guide
All scripts below live in the routlin project root and must be run as root (or with sudo) unless noted otherwise.
---
## install.py
Setup wizard. Installs system packages, configures Docker, sets up the dashboard container, and installs all systemd timers.
```bash
sudo python3 install.py
sudo python3 install.py --yes # (or -y) accept all prompts automatically
```
Safe to re-run. Will not duplicate files. After install.py completes, run `core.py --apply` to push config.json into the live system for the first time.
---
## core.py
The main configuration engine. Reads config.json and applies it to systemd-networkd, per-VLAN dnsmasq instances, nftables, WireGuard, FreeRADIUS, and Avahi. Most dashboard Save, Apply, and Fix operations ultimately trigger core.py via the queue timer.
```bash
sudo python3 core.py --apply # apply full config (safe to re-run multiple times)
sudo python3 core.py --apply --dry-run # preview changes without making them
sudo python3 core.py --disable # interactive wizard to revert the router to a plain client
sudo python3 core.py --disable --dry-run # preview what --disable would remove
sudo python3 core.py --merge-blocklists # merge downloaded blocklists and reload dnsmasq
sudo python3 core.py --view-configs # print active per-VLAN dnsmasq config files
sudo python3 core.py --view-leases # print active DHCP leases
sudo python3 core.py --view-rules # print active nftables ruleset
sudo python3 core.py --reset-leases # reset all DHCP leases
sudo python3 core.py --reset-leases 30 # reset leases for VLAN 30 only
sudo python3 core.py --status # show service and timer status
```
**Dashboard equivalents:**
| Flag | Dashboard |
|---|---|
| --apply | Actions page - Apply Now button |
| --merge-blocklists | DNS Blocking page - Download Blocklists button |
| --view-leases | DHCP Reservations page (active leases section) |
---
## maintenance.py
Runs on a timer (default every 10 minutes). Runs `ddns.py --update`, rotates FreeRADIUS logs, refreshes the ARP cache, and runs `metrics.py --collect`. Run manually to trigger all tasks immediately without waiting for the timer.
```bash
sudo python3 maintenance.py
```
**Timer:** `routlin-maintenance.timer` - interval set in config.json under `ddns.general.timer_interval` (default 10 minutes).
---
## metrics.py
Collects DNS statistics from running dnsmasq instances and stores them in the metrics database. Also collects and prunes per-query DNS logs. Run `--collect` manually to update metrics immediately rather than waiting for the maintenance timer. Run `--view` to print an all-time summary to the terminal. The dashboard is able to display updated information on the DNS Metrics page after `--collect` runs.
```bash
sudo python3 metrics.py --collect # collect and store metrics now
sudo python3 metrics.py --view # display all-time metrics summary
```
`maintenance.py` calls `metrics.py --collect` automatically on each tick.
---
## health.py
Runs health checks across all services, configuration files, nftables rules, VLAN interfaces, DHCP pools, disk space, upstream DNS, and FreeRADIUS logs. Writes results to `.health`.
```bash
sudo python3 health.py --collect # run checks and write .health (used by timer)
sudo python3 health.py --view # run checks, write .health, and print results
```
`--view` gives an immediate health report without waiting for the timer. The dashboard health banner reads the same `.health` file, so running either flag manually refreshes what the dashboard shows on next page load.
**Timer:** `routlin-health-check.timer` - every 5 minutes.
---
## ddns.py
Updates DDNS provider(s) with the current public IP. Called directly by `do_dashboard_queue.sh` for on-demand triggers from the dashboard, and by `maintenance.py` on each timer tick. Shares cache files (`.ddns-last-ip-*`, `.ddns-last-service`) and `ddns.log` across both callers. The DDNS page shows provider status and last update time.
```bash
sudo python3 ddns.py --update # run one update, advancing the check IP service rotation
sudo python3 ddns.py --update --force # update unconditionally, ignoring cached IP
sudo python3 ddns.py --getip # print current public IP and exit, advancing the check IP service rotation
```
---
## dl_blocklists.py
Downloads remote DNS blocklists defined in config.json to the `blocklists/` directory. Does not reload dnsmasq on its own - follow with `core.py --merge-blocklists` to merge and reload.
```bash
sudo python3 dl_blocklists.py
sudo python3 core.py --merge-blocklists
```
**Timer:** `routlin-dns-blocklist-update.timer` - daily at the time configured in config.json (default 02:30 local time). The timer runs both steps automatically.
**Dashboard equivalent:** DNS Blocking page - Download Blocklists button (runs both steps).
---
## create_vpn_peer.py
Generates a WireGuard keypair, adds the peer to config.json, and writes a ready-to-import client `.conf` file. Follow with `core.py --apply` to make the peer(s) that you generate live.
```bash
sudo python3 create_vpn_peer.py --name laptop --ip 192.168.40.2 --vlan-id 40
sudo python3 create_vpn_peer.py --name phone --ip 192.168.40.3 --vlan-id 40 --split-tunnel
sudo python3 create_vpn_peer.py --name laptop --ip 192.168.40.2 --iface wg0
sudo python3 core.py --apply
```
| Flag | Description |
|---|---|
| --name NAME | Peer name (required) |
| --ip IP | Peer IP within the VPN subnet (required) |
| --vlan-id ID | Target VPN VLAN ID (use this or --iface) |
| --iface IFACE | WireGuard interface name e.g. wg0 (use this or --vlan-id) |
| --split-tunnel | Route only VPN subnet traffic through the tunnel (default is full tunnel) |
| --output PATH | Output path for the client .conf file |
Transfer the generated `.conf` file to the client device securely (scp, QR code, etc.). Never send it over unencrypted channels.
**Dashboard equivalent:** VPN page - Add Peer form.
---
## check_captive_users.py
Expires captive portal sessions that have exceeded their time limit or account expiry, and writes the corresponding nftables disallow commands to the captive queue. The Captive Portal page shows active sessions. Expiry is handled automatically by the timer; there is no manual trigger in the dashboard.
```bash
sudo python3 check_captive_users.py
```
**Timer:** `routlin-captive-check.timer` - every 5 minutes.
---
## Timer Reference
| Timer | Script | Interval |
|---|---|---|
| `routlin-dashboard-queue.timer` | dashboard queue processor | 30 seconds |
| `routlin-captive-queue.timer` | captive portal queue | 10 seconds |
| `routlin-captive-check.timer` | check_captive_users.py | 5 minutes |
| `routlin-health-check.timer` | health.py --collect | 5 minutes |
| `routlin-maintenance.timer` | maintenance.py | 10 minutes (configurable) |
| `routlin-dns-blocklist-update.timer` | dl_blocklists.py + core.py --merge-blocklists | Daily at configured time |