Router
The OpenWrt router is the internet gateway for the blr-home network, its only DHCP/DNS server,
and the sole ingress point for every port-forwarded service. It is not deployed by any repo in
this platform (it is manually configured), but every host and service in
application-deployer/inventory.yml depends on the
addressing, DNS, and forwarding rules it provides.
This document is a snapshot of the current device's configuration (/etc/config/*, read over
SSH), kept for disaster recovery. It is not a restore script: secrets are never reproduced here,
and hardware-specific identifiers (MAC addresses) are omitted because they don't carry over to a
replacement device anyway. Use it to rebuild an equivalent router, not to restore this exact one.
Hardware / firmware
| Item | Value |
|---|---|
| Model | TP-Link Archer A9 v6 (tplink,archer-a9-v6) |
| SoC | Qualcomm Atheros QCA550X |
| Target | ath79/generic, mips_24kc |
| Firmware | OpenWrt 25.12.5 (r33051-f5dae5ece4) |
| Storage | 6.3 MB squashfs /rom + overlay; see below |
A USB drive is attached and mounted at /mnt/pd-03 (/etc/config/fstab, FAT32, matched by UUID).
It holds the daily config backups written by backup.ash (see
Provisioning and backup scripts). hd-idle is also
installed (spins down idle USB HDDs) but its config is empty/disabled.
This device enumerates on the SoC's EHCI (USB 2.0) controller and identifies as a plain
mass-storage device, so the kernel's classic usb-storage (BOT) driver claims it, not uas. The
kmod-usb-storage-uas and kmod-usb3 packages are installed for USB3/UAS-capable hardware (e.g.
a spinning HDD) but sit unused for this particular drive. block-mount/fstools auto-mount by
filesystem UUID rather than a fixed /dev/sdaN path, so the same /etc/config/fstab entry
survives the drive being plugged into a different USB port or a replacement router.
On a replacement device, pick any target OpenWrt supports and adjust the VLAN/switch config below to that hardware's port layout. The model itself isn't a requirement.
Non-default packages installed
Beyond the stock ath79/generic image, these are installed (via apk, OpenWrt's current package
manager). setup.v3.sh (see
Provisioning and backup scripts) installs SSH/SFTP
support, rsync, the USB-storage stack, and luci-app-hd-idle; the LuCI web UI itself (luci,
luci-ssl, luci-light, the luci-mod-* modules), luci-app-attendedsysupgrade, owut,
luci-app-package-manager, rpcd-mod-rrdns, and cgi-io are present as separately, explicitly
requested apk packages (per /etc/apk/world) rather than being installed by that script. Re-run
setup.v3.sh for the packages it covers, and apk add the rest by hand:
luci(full collection) +luci-ssl,luci-light,luci-mod-{admin-full,network,status,system},luci-compat,luci-lib-ipkg, themes (bootstrap,bootstrap-darkis the active one,material,openwrt,openwrt2020): the web admin UI.luci-app-attendedsysupgrade+owut: GUI and CLI sysupgrade-server-based firmware upgrades (/etc/config/attendedsysupgradepoints atsysupgrade.openwrt.org).luci-app-hd-idle+hd-idle: USB HDD spin-down (installed, unconfigured; see above).luci-app-package-manager: manageapkpackages from LuCI.openssh-sftp-server: SFTP subsystem for dropbear (dropbear has no built-in SFTP server).rsync: file sync utility, used for the/mnt/pd-03backups.block-mount,e2fsprogs,kmod-usb-storage-uas,kmod-usb3,kmod-fs-vfat,lsblk,blkid,mount-utils: USB storage support for the/mnt/pd-03drive (auto-mount viablock-mount/fstools, FAT32 filesystem driver, and inspection tools).rpcd-mod-rrdns,cgi-io,announce: LuCI/ubus support packages.
WireGuard is not installed on the router itself. Port 51820 is forwarded to an internal
host that terminates the tunnel (see Port forwarding).
Provisioning and backup scripts
/etc/scripts.d/ holds this router's own setup/backup automation. It is not part of the stock
OpenWrt image, and is itself preserved across firmware upgrades via /etc/sysupgrade.conf (see
below), so it survives a sysupgrade even though it lives outside /mnt/pd-03.
setup.v3.sh: the current provisioning script (apk-based, matches this OpenWrt 25.12 install). Installs SSH/SFTP support,announce,rsync, the USB-storage stack, andluci-app-hd-idleplus a subset of LuCI theme packages (luci-compat,luci-lib-ipkg,luci-theme-material,luci-theme-openwrt,luci-theme-openwrt-2020); writes thehomepagerpcd ACL (/usr/share/rpcd/acl.d/homepage.json, scoping that account tonetwork.interface.{wan,lan},network.device, andsystemstatus reads); restarts dropbear and uhttpd; and runsapk update && apk upgradefirst. It does not install the LuCI web UI itself (luci,luci-ssl,luci-light, theluci-mod-*modules),luci-app-attendedsysupgrade,owut,luci-app-package-manager,rpcd-mod-rrdns, orcgi-io; those are present on this device as separately, explicitly requestedapkpackages (per/etc/apk/world), not reproduced by this script. Run it on a fresh OpenWrt install for the packages it covers, andapk addthe rest by hand.setup.v1.ash/setup.v2.ash:opkg-based scripts for OpenWrt releases before the switch toapk. They are not used on this OpenWrt version.backup.ash: runs daily via cron (0 3 * * * /bin/ash /etc/scripts.d/backup.ash, in/etc/crontabs/root). Each run rewrites/etc/sysupgrade.confto preserve/etc/scripts.d/across upgrades, then callssysupgrade -bto write a full config-backup tarball to/mnt/pd-03/openwrt-r1-tpla9v6-backups/sysupgrade-config-backup/. Depends on$HOSTNAMEbeing set (ash exports it by default; nothing in this repo sets it explicitly) and on/mnt/pd-03being mounted. It exits with an error if the backup directory is missing rather than silently skipping. No retention/pruning exists. Backups accumulate indefinitely, which is something to watch if/mnt/pd-03is small.
These sysupgrade -b tarballs are a same-hardware restore path (sysupgrade -r backup-*.tar.gz-style restore, effectively uci state + /etc/scripts.d/) distinct from the
Rebuild checklist below, which is for provisioning a replacement router
from scratch.
Network topology
There is no Guest → LAN edge: the firewall has no forwarding rule between those zones, which is
what isolates guest devices from the rest of the network (see
Firewall and port forwarding). The guest zone's firewall rules allow
only DNS (53) and DHCP (67) inbound from guest clients, which is why GuestDevices only reach
DNS, never LAN. LuCI is likewise unreachable from Guest/WAN (both zones reject input;
only lan's input ACCEPT lets it through), and its /ubus HTTP endpoint is what the dashboard's
openwrt Homepage widget on rb5-m3 calls back into using the scoped homepage rpcd login (see
dashboard/stack/homepage/config/services.yaml
and ubus and rpcd API access). See
DHCP and DNS for how DNS resolves a query, and
Firewall and port forwarding for the DNAT rules into Backends.
- Switch (
switch0): VLAN-enabled. VLAN 1 (LAN) on ports2 3 4 5+ tagged on CPU port0; VLAN 2 (WAN) on port1+ tagged on CPU port0. Adjust port numbers to match the replacement hardware's physical switch. This mapping is specific to the Archer A9 v6's port layout. - WAN (
eth0.2): PPPoE. Requires an ISP-issued PPPoE username/password from the ISP account portal, not reproduced here (see Secrets excluded from this document). IPv6 is disabled on the PPPoE session itself; a separatewan6interface does DHCPv6-PD (disabled/auto 0by default). - LAN (
br-lan): static10.8.33.1/24, domainblr-home.easyiac.com. - Guest (
br-guest): isolated bridge, static10.8.34.1/24, no LAN routing (see firewall zones). Not attached to any switch VLAN. Client isolation is provided by binding only the guest Wi-Fi SSID to it. - IPv6 ULA prefix: locally generated (
fdd0:ce94:cf21::/48on this device). OpenWrt autogenerates a new random ULA prefix on a fresh install, so there's no need to reuse this value.
DHCP and DNS
DHCP and DNS are split across two daemons: dnsmasq and odhcpd.
-
dnsmasqis authoritative forblr-home.easyiac.comand is the LAN/guest DNS resolver; it also reads Ethernet leases (readethers) so wired clients resolve without a DHCP handshake. -
Resolution flow: a client's query lands on
dnsmasqfirst (it's the only resolver handed out by DHCP on bothlanandguest). A name underblr-home.easyiac.com, or any bare hostname, is answered locally from a DHCP lease, a staticconfig host/config domainentry, or areadethersARP-table lookup;domainneeded/local '/blr-home.easyiac.com/'keep these from ever leaving the router. Everything else is forwarded upstream to the nameservers in/tmp/resolv.conf.d/resolv.conf.auto(currently8.8.8.8/8.8.4.4on this device), whichnetifdregenerates from whatever the ISP hands out over the PPPoE session (peerdnsdefaults to enabled onwan; nothing in/etc/config/networkoverrides it, and dnsmasq's ownresolvfileoption points at that same auto-generated file). -
LAN pool:
10.8.33.100to10.8.33.249, 12h lease. -
Guest pool: same range convention (
100to249in10.8.34.0/24), 12h lease. -
WAN: dnsmasq is explicitly told to ignore the
waninterface (no accidental DHCP server facing the ISP). -
odhcpdhandles only IPv6 RA/prefix delegation (maindhcp '0'), while dnsmasq owns IPv4. -
Static hosts (
config host): every managed host gets two DHCP entries taggedknown(one for its wired MAC, one taggedwififor its wireless MAC), both pinned to the same hostname withleasetime infiniteanddns '1', so the host gets a fixed IP and a forward DNS name regardless of which interface it's on. Actual MAC/IP pairs are host-specific and not reproduced here; recreate this pattern per host fromuci show dhcpon the live device when rebuilding. -
Static aliases (
config domain): a name → IP mapping with no DHCP entry of its own, used to give a service its own DNS name on a host that already has aconfig hostentry, so internal clients can resolvenextcloud.blr-home.easyiac.com-style names without a public round-trip. On this device they all point at two hosts from application-deployer/inventory.yml:rb5-m3(reverse_proxy/wireguardrole): frontsminio-s3,minio-console,emby,qbittorrent-nox,qbn,jellyfin,nextcloud,devops-server,code-server,dashboard,navidrome,vikunja.sash-m1:devops-server-ssh.
Recreate one
config domainentry per internet-facing/internally-resolved service, pointed at whichever host actually runs it in the new setup.
Firewall and port forwarding
Zones: lan (accept all), wan (reject input/forward, masquerade, MTU clamp), guest (reject
input/forward, isolated, allowing only DNS 53 and DHCP 67 inbound from guest clients).
Forwarding is lan → wan and guest → wan; there is no guest → lan rule, which is what
isolates guest devices from the rest of the network. The default WAN-facing accept rules
(DHCP renew, ping, IGMP, DHCPv6, MLD, ICMPv6, IPSec ESP/ISAKMP) are stock OpenWrt firewall
defaults, not custom additions.
Port forwards (all DNAT, wan → lan). The application-facing rows (80, 443, 51820, 3478)
match the services in
application-deployer/docs/prerequisites.md#router-port-forwarding;
the SSH rows (22, 2228) are host-access forwards outside that deployer's scope:
| WAN port | Protocol | Forwarded to | Service |
|---|---|---|---|
22 | TCP+UDP | rb5-m3:22 | SSH (reverse proxy host) |
80 | TCP+UDP | rb5-m3:80 | Reverse proxy HTTP |
443 | TCP+UDP | rb5-m3:443 | Reverse proxy HTTPS |
51820 | TCP+UDP | rb5-m3:51820 | WireGuard VPN |
2228 | TCP+UDP | sash-m1:2228 | DevOps Server SSH (Git-over-SSH) |
3478 | TCP+UDP | s1-home:3478 | Nextcloud Talk coturn TURN relay |
None of these config redirect blocks sets an explicit option proto in
/etc/config/firewall, so firewall4 forwards both TCP and UDP for every rule (confirmed via
fw4 print/nft list) regardless of which protocol the service itself uses.
When rebuilding, recreate one DNAT redirect per internet-facing service, pointed at wherever that service actually lands on the new network. The port numbers are the contract with the outside world, not the destination IPs.
Wireless
- Radio: 5 GHz only (
radio0,mac80211), channel 36,VHT80(80 MHz width). No regulatorycountrycode is set on this device. Set one on rebuild if the AP hardware requires it for the correct channel/power table. - Main SSID: bound to
lan, WPA3/WPA2-mixed (sae-mixed). Passphrase excluded, see below. - Guest SSID: bound to
guest,disabled '1'(off by default) withencryption none. Turn this on deliberately and set a passphrase before relying on it; open guest Wi-Fi is not the intended steady state.
System
- Hostname
r1-tpla9v6, timezoneAsia/Kolkata(IST-5:30). - NTP: client synced against the
*.openwrt.pool.ntp.orgpool, and also serves NTP to the LAN (enable_server '1'on thelaninterface) so internal hosts can sync from the router instead of reaching out individually. - WAN activity LED wired to
switch0port-2 traffic.
SSH
- The SSH server (dropbear) is bound to the
laninterface only, not reachable fromwandirectly. (The port-22DNAT above forwards to an internal host's SSH, not the router's own.) - Password auth and root password auth are both off. Key-only login is required.
openssh-sftp-serveris installed to give dropbear SFTP support (see Non-default packages).
Web UI
- Served by
uhttpd, running LuCI. Listens on80/443(v4 and v6),redirect_https '0'. HTTP does not redirect to HTTPS on this device. - Uses a self-signed cert (
/etc/uhttpd.crt/.key) regenerated locally;config cert 'defaults'sets EC P-256, 397-day validity. http_keepalive '20'+max_requests '20': connections stay open for up to 20s and serve up to 20 requests each, so the LuCI UI's background XHR calls reuse one TLS connection instead of paying a full handshake per call (this MIPS SoC has no hardware crypto/RNG, so each handshake is slow; without keep-alive, back-to-back XHR calls could exceed the browser's XHR timeout).- LuCI theme:
bootstrap-dark.
ubus and rpcd API access
Two rpcd logins beyond the implicit root/console access:
root: full read/write ubus access, auth delegated to the system password ($p$rootis OpenWrt's syntax for "check against the Unixrootpassword", not a stored secret).homepage: read-only, limited to thehomepagerpcd ACL thatsetup.v3.shwrites (network.interface.{wan,lan},network.device, andsystemstatus reads). This is what thedashboardrepo's Homepageopenwrtwidget forr1-tpla9v6authenticates as (see dashboard/stack/homepage/config/services.yaml), reaching it over uhttpd's/ubusHTTP endpoint rather than local ubus, so it gets router status without full admin rights. Recreate a similarly scoped, read-only login for any such integration rather than reusing the root account.
Secrets excluded from this document
Per this platform's rule that nothing secret is ever committed, the following exist in the live config but are deliberately not reproduced here. Source fresh values from the ISP/a password manager when rebuilding, not from this file:
- PPPoE username + password (ISP account credentials)
- Wi-Fi WPA passphrase (main SSID)
rpcdlogin password hash for thehomepageaccount- Router's own root password / SSH host keys
Rebuild checklist
- Flash OpenWrt for the replacement hardware's target.
- Set hostname, timezone (
Asia/Kolkataor as desired), NTP pool +enable_server. - Configure the switch/VLANs for the new hardware's port layout: one VLAN for LAN ports, one for the WAN port, both tagged on the CPU port.
- Configure WAN as PPPoE with fresh ISP credentials.
- Configure LAN as static
10.8.33.1/24(or a chosen equivalent CIDR) with domainblr-home.easyiac.com(or equivalent). - Configure the guest bridge/interface (
10.8.34.1/24or equivalent), left unattached to any switch VLAN. - Configure dnsmasq: authoritative domain,
readethers, LAN + guest DHCP pools,wanDHCP ignored,odhcpdset tomaindhcp '0'. - Recreate static DHCP reservations (wired +
wifi-tagged pair per host,knowntag,leasetime infinite) for each managed host, and theconfig domainrecords mapping service names to their host IPs. - Recreate firewall zones (
lan/wan/guest) and forwarding rules exactly as described above, then the DNAT port forwards for each internet-facing service, pointed at the new host IPs. - Configure the 5 GHz radio (channel/width per new AP capability), set a fresh WPA3/WPA2-mixed passphrase on the main SSID; leave the guest SSID disabled until deliberately turned on with its own passphrase.
- Lock down dropbear: LAN-only, password auth off, root password auth off.
- Configure uhttpd/LuCI: HTTPS redirect on, regenerate the self-signed cert.
- Attach and mount any external storage needed for backups.
- Copy
/etc/scripts.d/setup.v3.shandbackup.ashonto the device (pull them from a recentsysupgrade -bbackup tarball, or from this device directly, before it's decommissioned) and runsetup.v3.sh: it installs the scopedhomepagerpcd login, SFTP support, USB storage support, and the packages it covers in Provisioning and backup scripts, in one pass. Separatelyapk addthe LuCI web UI (luci,luci-ssl,luci-light, theluci-mod-*modules),luci-app-attendedsysupgrade,owut,luci-app-package-manager,rpcd-mod-rrdns, andcgi-io, which the script doesn't cover. Addbackup.ashto/etc/crontabs/root(0 3 * * * /bin/ash /etc/scripts.d/backup.ash) and confirm its backup directory path matches the new hostname before relying on it.