MakerFLOSS_Mikrotik/CLAUDE.md
sjat 2796616d05 docs: capture topology + operational learnings in CLAUDE.md/README
Bring the everyday guides up to the live state (flat data VLAN 30 + isolated mgmt
VLAN 99 on ether8, DHCP + web UI experiment) and record the gotchas that cost time:
the bench tunnel (paramiko ignores ProxyJump), mamba NM-profile stickiness on cable
flap, the RouterOS find-by-address quirk, and the commit-confirmed detached-flip
pattern for lockout-prone changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 13:04:35 +02:00

4.3 KiB

MakerFLOSS_Mikrotik

Ansible IaC for one MikroTik CRS310-8G+2S+IN switch (RouterOS 7) at the makerspace, managed over SSH with community.routeros. Sibling project to AnsibleBaobabV4 (whose conventions this repo copies); independent repo on forgejo.makerfloss.eu.

Tech stack

  • Ansible 10.x / ansible-core 2.17, community.routeros 3.x + ansible.netcommon
  • Connection: ansible.netcommon.network_cli, ansible_network_os: community.routeros.routeros, SSH key auth
  • Vault identity makerfloss (~/.ansible/vault-keys/makerfloss.txt)
  • Lint: ansible-lint (profile: production), yamllint

Structure

  • inventories/prod/hosts.yml — group mikrotik, host crs310-maker
  • group_vars/mikrotik.yml — connection vars + switch_*_enabled flags
  • group_vars/mikrotik.vault.yml — encrypted password (excluded from linters)
  • host_vars/crs310-maker.yml — device facts, real addressing, VLAN/port map
  • roles/makerfloss.mikrotik_switch/ — one role, per-domain task files gated by flags
  • play_switch.yml (day-2), play_bootstrap.yml (first contact), play_backup.yml
  • docs/ — field guide, design spec, implementation plan

Essential commands

yamllint . && ansible-lint && ansible-playbook play_switch.yml --syntax-check
ansible-playbook play_switch.yml                       # day-2 (key auth)
ansible-playbook play_switch.yml --tags vlans          # one domain
ansible-vault view group_vars/mikrotik.vault.yml       # read a secret

Access (on-site / bench)

The switch is reachable only via the makerspace laptop mamba. Ansible's network_cli uses paramiko, which ignores ProxyJump, so port-forward instead of double-hopping:

ssh -J kuku -p 7576 sjat@10.8.0.4 -L 2222:192.168.88.1:22 -N    # tunnel to the switch
ansible-playbook play_switch.yml -e ansible_host=127.0.0.1 -e ansible_port=2222 -e ansible_user=sjat
ssh-keygen -R '[127.0.0.1]:2222'                                # if the tunnel host key changed
  • mamba is the mgmt station on switch port 8 (MGMT VLAN); it must be on port 8 to reach 192.168.88.1. From a data port it gets 10.2.30.x and cannot reach mgmt.
  • NM profiles on mamba enp0s31f6: crs310-bench (static .2) and Wired connection 1 (DHCP). Moving the cable flaps the link and NM re-selects a profile — pin the intended one sticky (autoconnect yes + higher priority) and the other off, or it reverts.

Rules

  • Idempotency: RouterOS tasks use community.routeros.command with :if [find] guards. Run every device-touching play twice; the second run must report no changes.
  • Lockout safety: keep an independent recovery channel (serial/WinBox-MAC) when touching mgmt/services/VLANs; enable vlan-filtering last. For lockout-prone changes over the network (vlan-filtering, moving the mgmt IP), run them as a detached self-reverting job — :execute { …; :delay 240s; :if ($mgmtok=false) do={ revert } }, then :global mgmtok true once verified. (Auto-healed a hard lockout during the cutover.)
  • RouterOS find ... address=<prefix> never matches an ip/address or dhcp-network value (returns 0 even on an exact string) — match by [find interface=X] or :foreach+/ip/address/get $a address. Bit the mgmt-IP move (duplicated the IP).
  • All real values go in host_vars; the role holds only mechanism + placeholders.
  • Secrets go to the makerfloss vault, never plaintext. Encrypt with ansible-vault encrypt --encrypt-vault-id makerfloss <file>.
  • New work: branch first, implement, verify (lint + syntax + run-twice), then merge.

Status / next

Live on the device (2026-06-09): flat L2 switch on 10.2.30.0/24DATA VLAN 30 (ether1 copper uplink + ether2-7 + SFP+), isolated MGMT VLAN 99 on ether8 (mgmt 192.168.88.1/24, no gateway/NTP/DNS), vlan-filtering on. The mgmt port also serves DHCP (192.168.88.10-.254) + the web UI as a makerspace experiment (flags switch_web_enabled, switch_mgmt_dhcp_enabled). Default admin disabled; login as sjat (key, or vaulted password). All task files + play_bootstrap/play_backup are idempotency-verified. Design + cutover runbook: docs/superpowers/specs/2026-06-09-crs310-flat-mgmtvlan-design.md.

Next: SFP+ 10G uplink and real VLAN segmentation once connectors + a VLAN plan are ready.