MakerFLOSS_Mikrotik/roles/makerfloss.mikrotik_switch
sjat 33dc378c3c feat(vlans): VLAN-aware bridge, ports, mgmt interface (mechanism)
Implements Task 7. Deliberate lockout-safe ordering (vlan-filtering LAST) with
:if [find] guards that adopt the existing defconf bridge/ports rather than
recreating them. Membership Jinja: trunk ports tagged per tagged_vlans, access
ports untagged per pvid, bridge/CPU tagged only on the mgmt VLAN; else={set} makes
membership declarative. Jinja render validated offline against the placeholder
topology. Device run DEFERRED to an on-site session with a recovery channel
(remote bench has no serial/WinBox-MAC fallback). Topology stays placeholder.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 19:39:04 +02:00
..
defaults feat: role skeleton, host_vars, day-2 play (stubbed domains) 2026-06-07 08:34:13 +02:00
meta feat: role skeleton, host_vars, day-2 play (stubbed domains) 2026-06-07 08:34:13 +02:00
tasks feat(vlans): VLAN-aware bridge, ports, mgmt interface (mechanism) 2026-06-08 19:39:04 +02:00
README.md docs: README, role README, CLAUDE.md 2026-06-08 19:22:43 +02:00

makerfloss.mikrotik_switch

Configure a MikroTik RouterOS switch (CRS310) over SSH with community.routeros. The role provides the mechanism; real values live in host_vars. Each domain is gated by an enable-flag (defined in group_vars/mikrotik.yml) so you can apply a subset with --tags.

Domains (enable-flags)

Flag Task file Tag Does
switch_identity_enabled identity.yml identity identity, mgmt IP, DNS/NTP, SSH on, disable unused services
switch_users_enabled users.yml users named admin user, import SSH key, disable default admin
switch_vlans_enabled vlans.yml vlans VLAN-aware bridge, access/trunk ports, mgmt VLAN iface
switch_backup_enabled backup.yml backup /export + binary backup, fetched into the repo
switch_firmware_enabled firmware.yml firmware RouterOS + RouterBOOT upgrade to switch_firmware_target (opt-in)

The per-domain task files are currently stubs pending implementation (see the plan in docs/superpowers/plans/).

Variables (defaults/main.yml)

Variable Default Purpose
switch_identity_name {{ inventory_hostname }} system identity
switch_mgmt_vlan_id 99 management VLAN id
switch_mgmt_address placeholder mgmt IP addr/cidr (override in host_vars)
switch_mgmt_gateway placeholder default gateway
switch_dns_servers placeholder DNS server(s)
switch_ntp_servers placeholder NTP server(s)
switch_disabled_services telnet,ftp,www,www-ssl,api,api-ssl services to disable (winbox kept for recovery)
switch_ssh_port 22 SSH service port
switch_admin_user sjat named admin user
switch_admin_group full RouterOS group for the admin user
switch_admin_ssh_pubkey_file ~/.ssh/id_ed25519.pub operator public key to import
switch_disable_default_admin true disable the built-in admin after key login works
switch_bridge_name bridge bridge to manage
switch_vlans example list of {id, name}
switch_bridge_ports example list of port definitions (see below)
switch_firmware_target "" RouterOS version to pin/upgrade to

Data shapes

switch_vlans:
  - {id: 99, name: "mgmt"}
  - {id: 10, name: "members"}

switch_bridge_ports:
  # access port: untagged member of one VLAN (pvid)
  - {interface: "ether1", pvid: 10, mode: access}
  # trunk port: carries tagged VLANs; pvid sets the untagged/native VLAN
  - {interface: "sfp-sfpplus1", pvid: 1, mode: trunk, tagged_vlans: [99, 10]}

Idempotency

RouterOS has no rich declarative module set over network_cli, so tasks use community.routeros.command with :if ([:len [... find ...]] = 0) do={ ... } guards. Always run twice and confirm the second run is a no-op.