CAPsMAN and CAP on 3x hAP ax2 router.

Hello.

I wanted to configure my home wireless network. I have one main ax2 router which has access to the internet via PPPoE and vlan35 and I wanted to add 2 more AP ax2 routers for a fast roaming.
Wired internet access from AP to Main router works as expected.

I have 2 vlans with configured pools and working DHCP:
vlan10 which is main network where I want to have 5 and 2.4GHz band
vlan20 which is guest network, only 2.4GHz legacy bands for some smart home devices.


I’m using routeros 7.19.1, I was able to connect 1 ax2 router via CAPs to my main router and guest network works as expected.

I try to follow all kinds of tutorials available but some use /caps-man which apparently is no longer in use.

Where I fail:

  1. I’m unable to connect to local CAPsMAN from my main router and right now only the 2nd router is running.
  2. I’m unable to start main network, only guest is running and I have internet access if I connect my phone to it.
  3. Question, do I need to set manager to capsman for each wifi device (under WiFi → Configuration → manager)?

Main router conf:

# 2025-06-11 07:20:38 by RouterOS 7.19.1
# software id = 4AMQ-WXN1
#
# model = C52iG-5HaxD2HaxD
# serial number = HJ60ADMH654
/interface bridge
add admin-mac=F4:1E:57:D1:09:C5 auto-mac=no comment=defconf \
    ingress-filtering=no name=bridge vlan-filtering=yes
/interface wifi
# operated by CAP F4:1E:57:D1:0A:13%bridge
add name=cap-wifi1 radio-mac=F4:1E:57:D1:0A:17
# no connection to CAPsMAN
set [ find default-name=wifi2 ] channel.skip-dfs-channels=10min-cac \
    configuration.manager=capsman .mode=ap disabled=no security.ft=no \
    .ft-over-ds=no
/interface vlan
add interface=bridge name=vlan10-main vlan-id=10
add interface=bridge name=vlan20-guest vlan-id=20
add interface=ether1 name=vlan35 vlan-id=35
/interface pppoe-client
add add-default-route=yes comment="Netia PPPoE Client" disabled=no interface=\
    vlan35 name=pppoe-out1 use-peer-dns=yes user=<redacted>
/interface list
add comment=defconf name=WAN
add comment=defconf name=LAN
/interface wifi datapath
add bridge=bridge name=dp-main vlan-id=10
add bridge=bridge name=dp-guest vlan-id=20
/interface wifi
# no connection to CAPsMAN
set [ find default-name=wifi1 ] \
    .skip-dfs-channels=10min-cac configuration.manager=capsman .mode=ap \
    datapath=dp-main disabled=no security.ft=no .ft-over-ds=no
/interface wifi security
add authentication-types=wpa2-psk,wpa3-psk disabled=no encryption=ccmp ft=yes \
    ft-over-ds=yes ft-preserve-vlanid=no name=sec-main
add authentication-types=wpa2-psk disabled=no encryption=ccmp ft=no name=\
    sec-guest
/interface wifi configuration
add channel.band=2ghz-ax .frequency=2412 .width=20/40mhz country=Poland \
    disabled=no mode=ap name=cfg-main-2g security=sec-main ssid="Lucky 16"
add channel.band=5ghz-ax .frequency=5180 .width=20/40/80mhz country=Poland \
    disabled=no mode=ap name=cfg-main-5g security=sec-main ssid="Lucky 16"
add channel.band=2ghz-ax .frequency=2417 .width=20mhz country=Poland \
    disabled=no mode=ap name=cfg-guest-2g security=sec-guest ssid=\
    "Lucky 16 Guest"
/ip pool
add comment="Default pool" name=default-dhcp ranges=\
    192.168.1.10-192.168.1.254
add name=dhcp-pool-main ranges=192.168.10.100-192.168.10.254
add name=dhcp-pool-guest ranges=192.168.20.100-192.168.20.254
/ip dhcp-server
add address-pool=default-dhcp interface=bridge name=defconf
add address-pool=dhcp-pool-main interface=vlan10-main lease-time=12h name=\
    dhcp-main
add address-pool=dhcp-pool-guest interface=vlan20-guest lease-time=6h name=\
    dhcp-guest
/disk settings
set auto-media-interface=bridge auto-media-sharing=yes auto-smb-sharing=yes
/interface bridge port
add bridge=bridge comment=defconf interface=ether2
add bridge=bridge comment=defconf interface=ether3
add bridge=bridge comment=defconf interface=ether4
add bridge=bridge comment=defconf interface=ether5
add bridge=bridge comment=defconf interface=wifi1
add bridge=bridge comment=defconf interface=wifi2
/ip neighbor discovery-settings
set discover-interface-list=LAN
/interface detect-internet
set wan-interface-list=WAN
/interface list member
add comment=defconf interface=bridge list=LAN
add comment=defconf interface=ether1 list=WAN
add interface=pppoe-out1 list=WAN
add interface=vlan35 list=WAN
/interface ovpn-server server
add mac-address=FE:71:D9:1C:13:16 name=ovpn-server1
/interface wifi cap
set caps-man-addresses=127.0.0.1 certificate=none discovery-interfaces=\
    bridge enabled=yes
/interface wifi capsman
set certificate=auto enabled=yes interfaces=bridge package-path="" \
    require-peer-certificate=no upgrade-policy=require-same-version
/interface wifi provisioning
add action=create-dynamic-enabled common-name-regexp="" disabled=no \
    master-configuration=cfg-main-2g name-format=testcap \
    slave-configurations=cfg-main-5g supported-bands=5ghz-ax,2ghz-ax
add action=create-dynamic-enabled disabled=no master-configuration=\
    cfg-guest-2g name-format=testcap supported-bands=2ghz-n,2ghz-g
/ip address
add address=192.168.1.1/24 comment=defconf interface=bridge network=\
    192.168.1.0
add address=192.168.10.1/24 interface=vlan10-main network=192.168.10.0
add address=192.168.20.1/24 interface=vlan20-guest network=192.168.20.0
/ip dhcp-client
add comment=defconf interface=ether1
/ip dhcp-server lease
add address=192.168.1.30 client-id=1:4c:82:a9:80:68:69 mac-address=\
    4C:82:A9:80:68:69 server=defconf
add address=192.168.1.2 client-id=1:f4:1e:57:d1:a:13 mac-address=\
    F4:1E:57:D1:0A:13 server=defconf
/ip dhcp-server network
add address=192.168.1.0/24 comment=defconf dns-server=192.168.1.1 gateway=\
    192.168.1.1
add address=192.168.10.0/24 dns-server=192.168.1.71 gateway=192.168.10.1
add address=192.168.20.0/24 dns-server=192.168.1.71 gateway=192.168.20.1
/ip dns
set allow-remote-requests=yes
/ip dns static
add address=192.168.88.1 comment=defconf name=router.lan type=A
/ip firewall filter
add action=accept chain=input comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
    invalid
add action=accept chain=input comment="defconf: accept ICMP" protocol=icmp
add action=accept chain=input comment=\
    "defconf: accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1
add action=accept chain=input comment="Allow local CAPsMAN" dst-port=\
    5246-5247 protocol=udp src-address=127.0.0.1
add action=accept chain=input dst-port=5246,5247 protocol=udp
add action=drop chain=input comment="defconf: drop all not coming from LAN" \
    in-interface-list=!LAN
add action=accept chain=forward comment="defconf: accept in ipsec policy" \
    ipsec-policy=in,ipsec
add action=accept chain=forward comment="defconf: accept out ipsec policy" \
    ipsec-policy=out,ipsec
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \
    connection-state=established,related hw-offload=yes
add action=accept chain=forward comment=\
    "defconf: accept established,related, untracked" connection-state=\
    established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" \
    connection-state=invalid
add action=drop chain=forward comment=\
    "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \
    connection-state=new in-interface-list=WAN
/ip firewall nat
add action=masquerade chain=srcnat comment="defconf: masquerade" \
    ipsec-policy=out,none out-interface-list=WAN
/ipv6 firewall address-list
add address=::/128 comment="defconf: unspecified address" list=bad_ipv6
add address=::1/128 comment="defconf: lo" list=bad_ipv6
add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6
add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6
add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6
add address=100::/64 comment="defconf: discard only " list=bad_ipv6
add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6
add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6
add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6
/ipv6 firewall filter
add action=accept chain=input comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
    invalid
add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\
    icmpv6
add action=accept chain=input comment="defconf: accept UDP traceroute" \
    dst-port=33434-33534 protocol=udp
add action=accept chain=input comment=\
    "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\
    udp src-address=fe80::/10
add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \
    protocol=udp
add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\
    ipsec-ah
add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\
    ipsec-esp
add action=accept chain=input comment=\
    "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=input comment=\
    "defconf: drop everything else not coming from LAN" in-interface-list=\
    !LAN
add action=accept chain=forward comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" \
    connection-state=invalid
add action=drop chain=forward comment=\
    "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6
add action=drop chain=forward comment=\
    "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6
add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \
    hop-limit=equal:1 protocol=icmpv6
add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\
    icmpv6
add action=accept chain=forward comment="defconf: accept HIP" protocol=139
add action=accept chain=forward comment="defconf: accept IKE" dst-port=\
    500,4500 protocol=udp
add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\
    ipsec-ah
add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\
    ipsec-esp
add action=accept chain=forward comment=\
    "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=forward comment=\
    "defconf: drop everything else not coming from LAN" in-interface-list=\
    !LAN
/system clock
set time-zone-name=Europe/Warsaw
/tool mac-server
set allowed-interface-list=LAN
/tool mac-server mac-winbox
set allowed-interface-list=LAN

AP #1 router conf:

# 2025-06-11 07:21:41 by RouterOS 7.19.1
# software id = 6WDF-SC2M
#
# model = C52iG-5HaxD2HaxD
# serial number = HJ60ADT8BNE
/interface bridge
add admin-mac=F4:1E:57:D1:0A:13 auto-mac=no comment=defconf name=bridge \
    vlan-filtering=yes
/interface wifi
# managed by CAPsMAN F4:1E:57:D1:09:C5%bridge
set [ find default-name=wifi1 ] configuration.manager=capsman .mode=ap \
    disabled=no security.authentication-types="" .ft=yes .ft-over-ds=yes
# SSID not set
set [ find default-name=wifi2 ] configuration.mode=ap disabled=no \
    security.ft=yes .ft-over-ds=yes
/interface vlan
add interface=bridge name=vlan10-main vlan-id=10
add interface=bridge name=vlan20-guest vlan-id=20
/interface list
add comment=defconf name=WAN
add comment=defconf name=LAN
/ip pool
add name=default-dhcp ranges=192.168.88.10-192.168.88.254
/disk settings
set auto-media-interface=bridge auto-media-sharing=yes auto-smb-sharing=yes
/interface bridge port
add bridge=bridge comment=defconf interface=ether2
add bridge=bridge comment=defconf interface=ether3
add bridge=bridge comment=defconf interface=ether4
add bridge=bridge comment=defconf interface=ether5
add bridge=bridge comment=defconf interface=wifi1
add bridge=bridge comment=defconf interface=wifi2
add bridge=bridge interface=ether1
/ip neighbor discovery-settings
set discover-interface-list=LAN
/ip settings
set ip-forward=no
/interface list member
add comment=defconf interface=bridge list=LAN
/interface wifi cap
set certificate=none discovery-interfaces=bridge enabled=yes \
    lock-to-caps-man=no
/interface wifi capsman
set interfaces=wifi1,wifi2 package-path="" require-peer-certificate=no \
    upgrade-policy=none
/ip dhcp-client
add comment=defconf interface=bridge
/ip dhcp-server
add address-pool=default-dhcp disabled=yes interface=bridge name=defconf
/ip dhcp-server network
add address=192.168.88.0/24 comment=defconf dns-server=192.168.88.1 gateway=\
    192.168.88.1
/ip dns
set allow-remote-requests=yes
/ip dns static
add address=192.168.88.1 comment=defconf name=router.lan type=A
/ip firewall filter
add action=accept chain=input comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
    invalid
add action=accept chain=input comment="defconf: accept ICMP" protocol=icmp
add action=accept chain=input comment=\
    "defconf: accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1
add action=drop chain=input comment="defconf: drop all not coming from LAN" \
    in-interface-list=!LAN
add action=accept chain=forward comment="defconf: accept in ipsec policy" \
    ipsec-policy=in,ipsec
add action=accept chain=forward comment="defconf: accept out ipsec policy" \
    ipsec-policy=out,ipsec
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \
    connection-state=established,related hw-offload=yes
add action=accept chain=forward comment=\
    "defconf: accept established,related, untracked" connection-state=\
    established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" \
    connection-state=invalid
add action=drop chain=forward comment=\
    "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \
    connection-state=new in-interface-list=WAN
/ip firewall nat
add action=masquerade chain=srcnat comment="defconf: masquerade" \
    ipsec-policy=out,none out-interface-list=WAN
/ipv6 firewall address-list
add address=::/128 comment="defconf: unspecified address" list=bad_ipv6
add address=::1/128 comment="defconf: lo" list=bad_ipv6
add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6
add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6
add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6
add address=100::/64 comment="defconf: discard only " list=bad_ipv6
add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6
add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6
add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6
/ipv6 firewall filter
add action=accept chain=input comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
    invalid
add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\
    icmpv6
add action=accept chain=input comment="defconf: accept UDP traceroute" \
    dst-port=33434-33534 protocol=udp
add action=accept chain=input comment=\
    "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\
    udp src-address=fe80::/10
add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \
    protocol=udp
add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\
    ipsec-ah
add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\
    ipsec-esp
add action=accept chain=input comment=\
    "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=input comment=\
    "defconf: drop everything else not coming from LAN" in-interface-list=\
    !LAN
add action=accept chain=forward comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" \
    connection-state=invalid
add action=drop chain=forward comment=\
    "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6
add action=drop chain=forward comment=\
    "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6
add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \
    hop-limit=equal:1 protocol=icmpv6
add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\
    icmpv6
add action=accept chain=forward comment="defconf: accept HIP" protocol=139
add action=accept chain=forward comment="defconf: accept IKE" dst-port=\
    500,4500 protocol=udp
add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\
    ipsec-ah
add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\
    ipsec-esp
add action=accept chain=forward comment=\
    "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=forward comment=\
    "defconf: drop everything else not coming from LAN" in-interface-list=\
    !LAN
/system clock
set time-zone-name=Europe/Warsaw
/tool mac-server
set allowed-interface-list=LAN
/tool mac-server mac-winbox
set allowed-interface-list=LAN

Screenshot_20250611_074713.png

When running new wifi-qcom drivers (as opposed to old wireless drivers), CAPsMAN settings are under /interface/wifi … e.g. /interface/wifi/capsman.

If things are set “according to the book” (i.e. using proper profiles), then settings are shared between CAPsMAN (for provisioning remote CAPs) and local wifi interfaces … and thus allow for proper station roaming between all CAP devices as well as CAPsMAN’s radios. So you set the other two devices into CAPs mode but you keep configuring CAPsMAN’s own wifi radios “locally” (but using same configuration profiles as for CAPs).

Okay, that’s something in contrary to what I found in the internet. I though that local radios must configure themselves the same way as the remote CAPs.
I mean, this is also how I would think it would work - I create configuration, provision it, then all devices (including local) create proper interfaces according to the “blueprint” configurations.
From what I understand now, local devices must have configurations assigned manually?

You can do both.
Local setup (using 95% of the settings you you would use for your capsman radios)

or …

You can also provision local radio. That works as well.

The key point to make roaming working with wifi-qcom (and -ac) is that the controller handling all the radios needs to be the same ROS entity.
In that case roaming will work, local or capsman controlled radio, doesn’t matter then.

I would like to provision local radio. But for some reason my local CAP is not able to connect to local CAPsMAN. (Though AP is able to do so [???])
I even added firewall rules, I thought maybe it is blocking itself from accessing local CAPsMAN. But does not connect anyway.

And again, do I need to manually set manager=capsman for each WiFi device?
Screenshot_20250611_080849.png

Your local radio needs to be set to local managed (local radio = radio from device you use as capsman controller).
But in the provisioning rules you can then add a line with the MAC address and the needed config.
Or set everything on the local radio using the same settings as used for capsman configs (configuration / security / …).
Your choice.

Normally capsman Access Points are set to caps mode (you can reset to caps mode from Winbox, CLI, button, …).
That puts those devices in a rather limited config state suitable for capsman:

  • all ethernet interfaces connected to bridge
  • DHCP client on bridge
  • wifi radios capsman controlled
  • datapath set to local bridge

If you do not want your access points to be in this state, you need to set all needed radios to capsman managed manually.

My access points should be rather a dumb “repeaters” with IP addresses assigned from main router, I want them to extend wireless and wired network only.

The most pleasing way for me is to configure everything in one place. I would like to create 3 configurations, 2 security rules, 2 data paths, 2 provision rules (all on my main router) and all 3 ax2 routers should automatically create WiFi network. Is that possible?

In such configuration, how many wifi devices should I have:
Screenshot_20250611_083021-1.png
2 or 3?

Sure.
That’s what capsman is for.

Just be aware the 2 other AX2 devices (if you reset them to caps mode) will be in fully bridged mode on their ethernet interfaces.

Holy J… I was able to make it run together with Fast Roaming but boy was it a journey paved with pain.

#1 CAPs on main router does not work, I was able to connection to CAPsMAN but the configuration is not being applied.
My configuration on main router is 1:1 to the configuration on AP, except CAP is getting data from LAN and I needed to disable the firewall for “drop all not coming from LAN”
But it still does not work, even though I have “managed by CAPsMAN” label, wifi does not start.
So you must forget about CAP configuration on main device.

#2 All AP WiFi interfaces must have manager: capsman set under configuration tab.
without it will not synchronize the settings.

#3
FT and FT Over DS must be enabled.
Connect Priority must be 0/1
Management Protection allowed
I use WPA2 PSK, didn’t check if WPA3 works.
Steering: Neighbor group, I had dynamic value in the dropbox.
RRM and WNM enabled.

#4 I revised all provisions and found out that I have 5Ghz and 2Ghz bands in one provision, this will fails since 1 interface is single band, so CAP cannot assign such configuration to a single antenna.
Now I have 1 5G provision with single cfg and 1 2G provision with master and slave.

#5 bridge must not have VLAN Filtering enabled, with it enabled my phone was not able to receive any IP address.

Now I’m going to repeat these steps and add 3rd ax2.

Thanks.

wpa3 works with CAPsMAN on 7.21.
I can’t speak for any other version.

 0 A interface=cap-1 uptime=19h22m50s signal=-77 band=5ghz-ax auth-type=wpa2-psk tx-rate=6.0Mbps 
     rx-rate=6.0Mbps 
 1 A interface=cap-1 uptime=15h38m47s signal=-56 band=5ghz-ax auth-type=ft-wpa3-psk tx-rate=6.0Mbps 
     rx-rate=864.7Mbps 
 2 A interface=cap-1 uptime=10h36m44s signal=-76 band=5ghz-ax auth-type=wpa3-psk tx-rate=720.6Mbps 
     rx-rate=648.5Mbps 
 3 A interface=cap-2 uptime=9h41m6s signal=-50 band=2ghz-n auth-type=wpa2-psk tx-rate=115.6Mbps 
     rx-rate=117.0Mbps 
 4 A interface=wifi1 uptime=2h18m19s signal=-54 band=5ghz-ac auth-type=wpa2-psk tx-rate=6.0Mbps 
     rx-rate=866.7Mbps

One last question.

When I provision slave 2G config, it creates new interface with new name, wifi21, wifi-22, wifi-23 etc on CAPs.

Ultimately what it does, with each new interface I have to add it to the bridge, is there a possibility to make it static?

EDIT:

CAP → Static slaves: yes

As already indicated several times before now … radios on capsman controller itself need to be set to LOCAL managed.

Oh, and in case you haven’t already:

read and digest this Help page:
https://help.mikrotik.com/docs/spaces/ROS/pages/224559120/WiFi#WiFi-WiFiCAPsMAN

Further on you will also see what needs to be done if you want to use VLAN.

Ah… I see, another button on another tab for managing the same feature :smiley:.
So yeah, it works for local CAP as well. Thank you!