Skip to content

Router Configuration Consolidation Design

Date: 2026-02-12 Status: Approved Context: Replacing Firewalla router, need to ensure all custom config is in Ansible

The router has accumulated custom configurations that are either:

  1. Not represented in Ansible playbooks
  2. Diverged from Ansible templates (router has newer changes)
  3. Partially deployed (Kopia installed but timer missing)
ScriptAnsible ManagedDivergence
0000-a-remount-root-for-more-space.shNoN/A - needs addition
0000-ensure-dhcpcd6-duid.shPartialHas hardcoded DUID, not using Vault
0000-mount-extdata.shYesRouter has sudo prefixes
0001-ipv6-ula.shYesHooks to Python script
0002-ipv6-cron-fix-vzw.shNoN/A - needs addition
0050-start-docker.shYesRouter has sudo, usermod
0100-install-docker-compose-v2.shYesCompletely different implementation
0125-start-alloy.shYesRouter has sudo, dual start
0150-start-tailscale.shYesRouter has sudo, dual start
0151-start-router-hosts.shYesRouter has sudo, dual start
0200-start-vault-unseal.shYesMissing set -euo pipefail
  • Binary installed at /extdata/tools/kopia
  • Repository connected to R2
  • No systemd timer/service - backups not running
  • Security issue: Credentials embedded in /extdata/kopia/config/init-repo.sh

Scripts in post_main.d run as user pi, requiring sudo for root operations.

Update templates to match router reality (add sudo where needed):

File: templates/mount-extdata.sh.j2

Changes:

  • Add sudo prefix to mount command
  • Add sudo prefix to touch command
  • Add sudo prefix to tee command in log function

File: templates/start-docker.sh.j2

Changes:

  • Add sudo prefix to all ipset commands
  • Add sudo prefix to systemctl commands
  • Add sudo prefix to tee command in log function
  • Add sudo usermod -a -G docker pi at end

File: templates/boot-script.sh.j2

Changes:

  • Add sudo prefix to docker compose command
  • Add sudo systemctl enable --now docker-compose@tailscale

File: templates/z0100-start-router-hosts.sh.j2

Changes:

  • Add cd to docker compose directory
  • Add sudo docker compose up -d before systemctl
  • Add sudo prefix to systemctl command

File: templates/configure-ipv6-ula.py.j2

Changes:

  • Add sudo to ip -6 addr add command
  • Add sudo to kill -HUP command

File: templates/docker-compose@.service.j2

Changes:

  • Update TMPDIR path from /data/tmp/%i to /extdata/tmp/%i

File: templates/boot-script.sh.j2

Changes:

  • Add set -euo pipefail at start (already in template, verify router version)

File: templates/boot-script.yml

Changes:

  • Add sudo prefix to docker compose command
  • Add sudo systemctl enable --now docker-compose@alloy

Add new file: templates/remount-root.sh.j2

#!/bin/bash
# {{ ansible_managed }}
# Remount root-rw with larger size for Firewalla operations
sudo mount -o remount,size=384M /media/root-rw

Add task to deploy with priority 0000-a.

Add new file: templates/ensure-dhcpcd6-duid.sh.j2

  • Read DUID from Vault (already fetched in playbook)
  • Compare with current file
  • Update if different, restart dhcpcd6 service

Add new file: templates/install-cron.sh.j2

#!/bin/bash
# {{ ansible_managed }}
# Install dhcp6-lease-fix cron job
echo "* * * * * root {{ router_dhcp6_vzw_fix_script_path }}" | sudo tee /etc/cron.d/dhcp6-lease-fix

The role already has templates for:

  • kopia-backup.service.j2
  • kopia-backup.timer.j2

Issue: These were never deployed. Run the role to deploy them.

Delete /extdata/kopia/config/init-repo.sh from the router. The repository is already connected; credentials come from Vault at deploy time.

Remove from router:

  • /home/pi/.firewalla/config/post_main.d/z_0050-start-docker.sh
  • /home/pi/.firewalla/config/post_main.d/z_0100-start-haproxy.sh
  1. Phase 1: Update templates (preserves router changes)
  2. Phase 4: Cleanup old files
  3. Phase 2: Add missing scripts
  4. Phase 3: Fix Kopia
  5. Verify all services running

After implementation:

  1. ssh router "ls -la /home/pi/.firewalla/config/post_main.d/" - no z_* files
  2. ssh router "systemctl status kopia-backup.timer" - timer active
  3. ssh router "docker ps" - all containers running
  4. ssh router "cat /etc/cron.d/dhcp6-lease-fix" - cron installed
  5. Run full playbook with --check --diff - no changes
  • Remove hardcoded DUID from 0000-ensure-dhcpcd6-duid.sh (use Vault)
  • Remove embedded credentials from init-repo.sh (already in Vault)