User Stories

Real-world deployments with conwrt.

1. The Traveler

"I want reliable, secure WiFi when working from hotels and cafes."

The Problem

Hotel WiFi is unreliable, insecure, and often behind captive portals. Phone hotspot works but has limited range and no VPN. Public networks expose your traffic to snooping and man-in-the-middle attacks.

The conwrt Solution

Flash a pocket-sized GL.iNet Beryl AX (MT3000) with travelmate for auto-connecting to hotel WiFi, WireGuard VPN client for encrypted tunneling to your home server, and SQM to eliminate bufferbloat on slow hotel uplinks. Connect your laptop and phone to the router's private WiFi, and everything goes through your VPN.

How to do it

Create your config.toml:

[ssh]
keys = ["~/.ssh/id_ed25519.pub"]

[password]
mode = "random"

[network]
wan_ssh = false

[use_cases]
enabled = ["travelmate", "wireguard-client", "sqm"]

[use_cases.travelmate]
radio = "radio0"
timeout = 60
retry = 5
captive = true

[use_cases.wireguard-client]
peer_public_key = "YOUR_SERVER_PUBLIC_KEY"
endpoint_host = "vpn.example.com"
endpoint_port = 51820
address = "10.67.0.2/32"
allowed_ips = "10.67.0.0/24"
kill_switch = false

[use_cases.sqm]
download_kbps = 50000
upload_kbps = 10000
qdisc = "cake"

[wireguard]
registration_server = "my-vpn-server"
wg_interface = "wg0"

Flash the router:

python3 scripts/conwrt.py --model-id glinet-mt3000 --request-image --no-password

Plug in the router at your hotel. Connect your laptop to the router's default WiFi. The router automatically scans and connects to hotel WiFi through captive portal detection, establishes the WireGuard tunnel, and applies SQM to eliminate bufferbloat.

Result

Pocket-sized travel router that auto-connects to hotel WiFi, routes all traffic through your home VPN server, and eliminates bufferbloat on slow uplinks. Your devices are always protected, and you never touch captive portals again.

Note: travelmate, wireguard-client, and sqm are untested presets. The uci commands and package lists are based on OpenWrt wiki documentation. They need real-device validation before production use. wireguard-client registration is tested on D-Link COVR-X1860 A1.

2. The Homelab Operator

"I want a home router with ad-blocking, guest WiFi, and remote access."

The Problem

Stock router firmware is limited. No ad-blocking across all devices. No VPN server for accessing your homelab when you're away. Guest WiFi is an afterthought and often not properly isolated from your main network. You want a router that does more than just route packets.

The conwrt Solution

Flash a Linksys MX4200 with AdGuard Home for network-wide ad blocking, guest WiFi for visitors with proper isolation, and a WireGuard server to access your homelab remotely. All configured from a single config.toml file and baked into the firmware image.

How to do it

Create your config.toml:

[ssh]
keys = ["~/.ssh/id_ed25519.pub"]

[password]
mode = "random"

[network]
lan_ip = "192.168.1.1"

[use_cases]
enabled = ["adguard", "guest-wifi", "wireguard-server"]

[use_cases.adguard]
listen_ip = "0.0.0.0"
web_port = 3000
dns_port = 5353
bootstrap_dns = "1.1.1.1,8.8.8.8"

[use_cases.guest-wifi]
ssid = "Guest"
key = ""
encryption = "psk2"
band = "2.4ghz"
isolation = true
network_name = "guest"

[use_cases.wireguard-server]
private_key = "YOUR_SERVER_PRIVATE_KEY"
listen_port = 51820
subnet = "10.1.99.1/24"
peer1_public_key = "YOUR_LAPTOP_PUBLIC_KEY"
peer1_allowed_ips = "10.1.99.2/32"

Flash the router:

python3 scripts/conwrt.py --model-id linksys-mx4200-v1 --request-image --ssh-key ~/.ssh/id_ed25519.pub --no-password

After flashing, SSH to the router at 192.168.1.1 and run the AdGuard Home setup wizard at http://192.168.1.1:3000. Point your devices' DNS to 192.168.1.1:5353 for ad blocking. Configure WireGuard peers on your laptop and phone using the public key and subnet from the config.

Result

Full-featured home router with network-wide ad blocking via AdGuard Home, properly isolated guest WiFi for visitors, and WireGuard VPN server for secure remote access to your homelab. All configured declaratively and reproducibly from a single config file.

Note: adguard and guest-wifi are untested presets. The uci commands and package lists are based on OpenWrt wiki documentation. They need real-device validation before production use. wireguard-server is tested on D-Link COVR-X1860 A1.

3. The Mesh Builder

"I want to repurpose old routers into a whole-house WiFi mesh."

The Problem

Single router can't cover your whole house. Buying a mesh system is expensive. You have 2-3 old consumer routers collecting dust in a closet. You want to turn them into a mesh network without vendor lock-in or proprietary apps.

The conwrt Solution

Flash each router with mesh11sd for 802.11s mesh networking. All nodes run the same firmware image with matching mesh credentials. They auto-discover and connect to each other, forming a seamless mesh network covering your entire house.

How to do it

Create your config.toml (same file for all nodes):

[ssh]
keys = ["~/.ssh/id_ed25519.pub"]

[password]
mode = "random"

[use_cases]
enabled = ["mesh11sd"]

[use_cases.mesh11sd]
mesh_id = "MyHomeMesh"
ssid = "MeshNet"
encryption = "1"
key = "YourSecretPassword"
auto_config = "2"

Flash each router (same command, repeat for each device):

python3 scripts/conwrt.py --model-id  --request-image --no-password

Power on all routers. They auto-discover each other via the mesh ID and form a network. Connect your devices to MeshNet WiFi and roam seamlessly between nodes.

Result

Whole-house WiFi mesh built from repurposed routers. No vendor lock-in, no proprietary apps, no expensive hardware. All nodes run the same firmware and can be managed with conwrt's SSH-based inventory and configuration tools.

Note: mesh11sd is an untested and experimental preset. The uci commands and package lists are based on OpenWrt wiki documentation and community guides. This feature needs real-device validation before production use. Do not deploy to production routers until tested.

4. The Developer

"I want to manage routers as code, not click through web UIs."

The Problem

Manual router configuration via web UI is error-prone, not reproducible, and doesn't scale across many devices. You want to define network profiles once and deploy them to dozens of routers with a single command. Version control your router configs. Roll back changes when something breaks.

The conwrt Solution

Use conwrt's Python API and CLI to script device provisioning. Define profiles in config.toml, build firmware via ASU, flash and configure programmatically. The same config file drives both firmware builds and post-flash SSH configuration. No drift between what you defined and what's running.

How to do it

Create your config.toml profile:

[ssh]
keys = ["~/.ssh/id_ed25519.pub"]

[password]
mode = "key-only"

[network]
wan_ssh = true

[use_cases]
enabled = ["sqm", "wireguard-client"]

[use_cases.sqm]
download_kbps = 340000
upload_kbps = 19000

[use_cases.wireguard-client]
peer_public_key = "YOUR_SERVER_PUBLIC_KEY"
endpoint_host = "vpn.example.com"
endpoint_port = 51820
address = "10.67.0.2/32"
kill_switch = true

[wireguard]
registration_server = "my-vpn-server"
wg_interface = "wg0"

Plan the profile (dry-run, no firmware build):

python3 scripts/conwrt.py profile plan --model-id dlink-covr-x1860-a1

Request firmware from ASU (dry-run first):

python3 scripts/firmware-manager.py request --profile dlink_covr-x1860-a1 --dry-run

Request and cache the real firmware:

python3 scripts/firmware-manager.py request --profile dlink_covr-x1860-a1

Flash all routers (same command per device):

python3 scripts/conwrt.py --model-id dlink-covr-x1860-a1 --request-image --no-password --wan-ssh

Result

Repeatable, scripted router provisioning. Define your network profile once in config.toml, version it in git, review changes with your team, then deploy to any number of routers with a single command. Roll back by reverting the config and flashing again. No manual uci editing, no web UI clicks, no drift.

5. The Device Rescuer

"I want to unbrick a router stuck on vendor firmware."

The Problem

Your router won't boot, or stock firmware rejects third-party firmware. The web UI says "invalid image". You don't have a serial cable. The router is effectively bricked, but you know it's capable of running OpenWrt.

The conwrt Solution

Use conwrt's probe to detect the device boot state (offline, U-Boot, OpenWrt), then use recovery-http to flash via U-Boot's built-in HTTP server. No serial cable needed. Hold the reset button while powering on, and the router listens for firmware uploads on a known IP.

How to do it

Probe the device to check its state:

python3 scripts/router-probe.py --ip 192.168.1.1

Download the correct OpenWrt firmware for your model (from ASU or OpenWrt downloads). Verify the hardware matches the image target:

# On the router (if accessible via SSH):
cat /tmp/sysinfo/board_name
# Compare with your model's openwrt.profile in models/*.json

Dry-run the flash to test detection without uploading:

python3 scripts/conwrt.py --model-id dlink-covr-x1860-a1 --image firmware.bin --no-upload

Hold the reset button, power on the router, wait 5 seconds, release reset. Then flash:

python3 scripts/conwrt.py --model-id dlink-covr-x1860-a1 --image firmware.bin

Result

Unbricked router running OpenWrt. Recovered without serial cable, using only the reset button and ethernet. The firmware image is verified with SHA-256 before upload, and SSH inventory is collected after boot to confirm the flash succeeded.

Important safety rule: Never use sysupgrade -F or --force. These flags bypass hardware validation and can brick devices by writing firmware for the wrong hardware. Always identify the device (/tmp/sysinfo/board_name), cross-check with the model definition, and verify that sysupgrade accepts the image before proceeding. If sysupgrade rejects an image with "Device X not supported", the image is wrong. Stop and download the correct firmware.