NETSetup flash-mikrotik command flashes a stock MikroTik hAP-class device into a single-box
router + WiFi AP + 4-port switch in one shot. This doc covers what it does, how to use it,
the code map, the test map, and how to recover when it fails.
Hardware refs
-
Tik4Net (RouterOS API client used by
osisa.NETCommand)
Sticker
Bottom of device, three values:
| Field | Example | Purpose |
|---|---|---|
Admin |
|
Current admin password on the device. Pass to |
Wifi |
|
Out-of-box WPA passphrase for the factory WiFi. Not used after flash. |
MAC |
|
Optional |
Factory reset
Hold reset button BEFORE plugging in power. Keep holding ~10s until LED flashes. Then plug
power in. Device boots into stock RouterOS at 192.168.88.1 on ether2-5.
Cabling
-
Plug PC LAN into one of
ether2,ether3,ether4,ether5(NOTether1). -
ether1is WAN side. Stock device thinks anything plugged there is the ISP and will not talk to your PC. -
ether2-5is the LAN bridge. Stock RouterOS serves DHCP192.168.88.xand answers at192.168.88.1on this side. -
Disable WiFi on your PC. Disable VPN. Avoid putting a switch in between (works but slows ARP).
After flash, same physical mapping holds: ether1 = WAN, ether2-5 + WiFi = LAN, but the
LAN scheme changes to 10.0.0.0/24 instead of factory 192.168.88.0/24.
Quick start
Direct contact (PC cabled straight into ether2-5, no MAC discovery):
netsetup flash-mikrotik --admin-password CPDCYY96E8
With MAC discovery (PC and device on same L2 segment, ARP scan resolves MAC → IP):
netsetup flash-mikrotik --admin-password CPDCYY96E8 --mac F4:1E:57:FF:B7:A2
Custom SSID + WiFi pwd + hostname + post-flash admin pwd:
netsetup flash-mikrotik `
--admin-password CPDCYY96E8 `
--ssid CustomerNet `
--wifi-password Hunter2! `
--hostname Cust_AP_01 `
--flashed-new-admin-password 'StrongPwd!2026'
CLI flags
| Flag | Required | Meaning |
|---|---|---|
|
yes |
Current admin password on the device. Stock unit → sticker |
|
no |
Device MAC. When set the host runs an ARP scan for it across all Up subnets first; on hit it uses the resolved IP, on miss it falls back to the factory-IP route. When omitted the host goes straight to the factory-IP route. |
|
no (default |
WPA SSID applied to both 5GHz ( |
|
no (default |
WPA passphrase. Used by both bands. Min 8 chars per WPA spec. |
|
no (default |
|
|
no (default |
New admin password written into the .rsc and applied AFTER reset-configuration. This is the
post-flash login pwd, NOT the same as |
What gets applied
The .rsc rendered by MikrotikRscBuilder.Build (in
src/NETSetup/Helpers/MikrotikRscBuilder.cs) configures:
| Section | Effect |
|---|---|
Bridge |
Single bridge named |
Interface lists |
|
WiFi |
|
LAN IP |
|
DHCP server |
Pool |
WAN |
|
DNS |
|
NAT |
|
Firewall |
Stateful filter: established/related accepted, invalid dropped, ICMP allowed, LAN trusted, WAN-init dropped on input + forward. |
System |
Timezone |
Admin user |
|
MAC server |
|
Constants in MikrotikRscBuilder:
public const string LanGateway = "10.0.0.1";
public const string LanCidr = "10.0.0.1/24";
public const string LanNetwork = "10.0.0.0/24";
public const string DhcpPoolRange = "10.0.0.2-10.0.0.254";
Flow phases
MikrotikCommands.Run (entry from CLI handler or test) walks these phases:
| Phase | Method | Detail |
|---|---|---|
1. Defaults |
|
Pure: fills nullable optional params with published defaults. Hostname suffix injectable for tests. |
2. Putty |
|
Idempotent |
3. Resolve IP |
|
Returns
|
4. Render .rsc |
|
|
5. Upload |
|
Uses
|
6. Reset |
|
Uses
|
7. Revert NIC |
|
Powershell |
8. Done log |
- |
Final |
Run wraps phases 3-7 in try/finally so the NIC reverts to DHCP on any failure path.
Code map
| File | Role |
|---|---|
|
Entry point. Holds Cocona registration, |
|
Pure |
|
Win32 P/Invoke |
|
External (netbase). |
|
External (netbase). Base class for every API-based MikroTik command. Hardcodes user as
|
Test map
| Test | Covers |
|---|---|
|
Cocona registration smoke test. |
|
All-null → published defaults; all-set → caller values preserved; hostname-set → suffix generator NOT invoked. |
|
ARP hit → arp ip; ARP miss + factory occupied → factory ip + IsFallback; whitespace ARP → miss; ARP miss + factory empty → failure with actionable msg. |
|
Real NICs (Intel/Realtek/Broadcom + Hyper-V vEthernet for ext-switch use case) accepted;
WSL/TAP/Tailscale/Bluetooth/Network Bridge/Multiplexor/WFP rejected; |
|
Empty → null; multiple → first. |
|
Empty → error; single → auto-pick (no prompt); multiple → prompt seam called and returned index used; out-of-range index → actionable error. |
|
Logs name + description + MAC + ifIndex + "(N other adapter(s))" line. Verified via
|
|
N-second loop calls injectable |
|
First probe succeeds → returns true with no sleep. Later probe succeeds → returns true after N-1 sleeps. All probes fail → returns false; never sleeps after the final attempt. |
|
Null/empty/clean output → false. Every known marker (PuTTY + RouterOS API: |
|
Regex correctly strips |
|
|
|
Pure-function template renderer: every parameter (ssid, passphrase, hostname, admin pwd) appears verbatim in the output. |
Verification
After the command exits "Done. Reset-configuration command sent…":
-
Wait 60-120s. Device reboots, applies factory defaults (because
no-defaults=yes), then runsrun-after-reset=<file>to apply our .rsc. -
Look for SSID
Liberator(or whatever you passed to--ssid) on phone/laptop WiFi list. SSID visible → .rsc applied → success. -
Or cable PC into
ether2-5, get DHCP lease in10.0.0.0/24, ping10.0.0.1. -
Or open Winbox. If device responds at
10.0.0.1→ success. If responds at192.168.88.1→ .rsc failed to apply on first boot, device fell back to factory.
Troubleshooting
"Configured password was not accepted"
Three causes:
-
Wrong sticker copy/paste.
-
RouterOS 7.x first-login forced password change. Stock device asks "Please set new password" interactively;
pscp -batchcannot answer. Fix: open Winbox once, accept the prompt by setting the sticker pwd as the new pwd, then rerunflash-mikrotik. -
Device was previously configured → sticker irrelevant → use whatever pwd the previous config set.
"ARP probe 192.168.88.1 … no reply" 5x
-
Cable plugged into
ether1(WAN) → move toether2-5. -
PC NIC blocked by Windows firewall on the new subnet → Windows usually prompts on first attach; click "private network".
-
Hyper-V external switch is the picked adapter → works as long as the underlying physical NIC is bridged AND linked. If the physical NIC has no link, the vSwitch has no carrier.
Multiple adapters in candidate list
SelectAdapter prompts for an index. Pick the one whose Description matches the cable
you plugged in. Hyper-V external-switch vEthernet IS valid and shows up in the list.
SSID never appears
Open Winbox to 192.168.88.1 (factory) or 10.0.0.1 (post-flash) → System →
History. Shows whether run-after-reset ran or errored. Common errors:
-
Country code mismatch (
Switzerland→ change inMikrotikRscBuilder.Buildif relocating). -
WiFi interface name not
wifi1/wifi2on older firmware → rerun on RouterOS 7.13+. -
Bridge port already exists (rare; happens if
keep-users=yesaccidentally preserved a bridge from prior config).
Reset-configuration stdout has "Invalid MAC address '192.168.88.1'."
Cosmetic only. MikroTikCommandBase ctor in netbase tries new MacAddress(host) first
and accumulates the parse exception into its result string. StripNetbaseMacNoise removes
this prefix from logs. Not a real failure.
Manual fallback
When flash-mikrotik is broken or unavailable:
-
Cable PC into
ether2-5. PC gets DHCP lease in192.168.88.0/24. -
Open Winbox → connect to
192.168.88.1asadmin/ sticker pwd. Or use WebFig in browser. -
Open the netbuild repo, navigate to
osisa.Nuke.Commands.Tests/MikroTikTests/TestFiles/Liberator_AP.rsc(or generate a fresh one by runningMikrotikRscBuilder.Buildin a debugger). -
Adjust SSID / passphrase / hostname / admin pwd in the .rsc as needed.
-
In Winbox → Files: drag the .rsc onto the file list to upload.
-
Open Terminal:
/system reset-configuration keep-users=yes no-defaults=yes skip-backup=yes run-after-reset=Liberator_AP.rsc. -
Wait 60-120s. Verify as in Verification.
For ongoing changes after the device is at 10.0.0.1, plug ether1 into your network and
SSH/Winbox to whatever IP your upstream DHCP hands out, OR connect a phone to the
Liberator WiFi and Winbox to 10.0.0.1.