aci-sim is a stateful REST simulator of a 2-site Cisco ACI fabric (per-site APIC + ND/NDO management planes) — for testing ACI automation (Ansible cisco.aci / cisco.mso, aci-py, custom REST clients) and CI gates without real hardware. Highlights: APIC + NDO REST surface served from one in-memory MIT built from a declarative topology.yaml; port mode + sandbox (real per-device IPs on :443) run modes; LLDP/CDP neighbor visibility; NDO->APIC deploy mirror (multi-site templates materialize onto the target sites' APIC stores); real-APIC fvBD default attributes; file-backed state save/restore; an `aci-sim` CLI (validate/show/graph/run/new/init/lldp); and an 888-test suite. History squashed for the public release. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploying aci-sim as a background service
The simulator is a plain long-running process (python -m aci_sim.runtime.supervisor, also reachable via the aci-sim run
CLI subcommand — see README.md §5 CLI), so it can run under any process
supervisor. This directory ships a systemd user unit for Linux (the
standing Raspberry Pi deployment) and a launchd plist sketch for macOS.
Both approaches run the simulator as an unprivileged user process bound to
SIM_BIND (default 127.0.0.1, see README.md §Configuration / finding
#23). Sandbox mode (scripts/sandbox-up.sh, binding :443 on real IPs) needs
root for the loopback alias + privileged port and is intentionally NOT
service-managed — run it interactively when you need NDO auto-discovery.
Linux — systemd --user unit
-
Clone the repo and create the venv per
README.md§2 Quick start:git clone <repo-url> ~/aci-sim cd ~/aci-sim python -m venv .venv source .venv/bin/activate pip install -r requirements.txt pip install -e . -
Install the unit:
mkdir -p ~/.config/systemd/user cp deploy/aci-sim.service ~/.config/systemd/user/ -
If the repo lives somewhere other than
~/aci-sim, editWorkingDirectory/ExecStartin the copied unit (the shipped unit uses%h— the systemd specifier for the invoking user's home directory). -
If this host is a shared/LAN target for other machines (e.g. autoACI running elsewhere), uncomment
Environment=SIM_BIND=0.0.0.0in the unit. Otherwise leave it commented — the sim will only be reachable fromlocalhoston this host. -
Enable + start:
systemctl --user daemon-reload systemctl --user enable --now aci-sim.service -
Allow the user service to run even when the user isn't logged in (needed on a headless Pi):
sudo loginctl enable-linger "$USER" -
Verify:
systemctl --user status aci-sim.service journalctl --user -u aci-sim.service -f curl -sk https://127.0.0.1:8443/api/class/fabricNode.json # or the SIM_BIND host
To pick up an edited unit (e.g. after changing Environment=):
systemctl --user daemon-reload
systemctl --user restart aci-sim.service
macOS — launchd plist sketch
macOS has no systemd; the equivalent is a launchd LaunchAgent (per-user,
runs at login — parallel to how OCP-class services on this fleet are
managed). Adjust paths for your clone location, then save as
~/Library/LaunchAgents/com.aci-sim.supervisor.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.aci-sim.supervisor</string>
<key>WorkingDirectory</key>
<string>/Users/YOURUSER/aci-sim</string>
<key>ProgramArguments</key>
<array>
<string>/Users/YOURUSER/aci-sim/.venv/bin/python</string>
<string>-m</string>
<string>aci_sim.runtime.supervisor</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<!-- Uncomment/add to expose on the LAN (#23); omit for loopback-only -->
<!-- <key>SIM_BIND</key><string>0.0.0.0</string> -->
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>StandardOutPath</key>
<string>/tmp/aci-sim.log</string>
<key>StandardErrorPath</key>
<string>/tmp/aci-sim.log</string>
</dict>
</plist>
Load/manage it:
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.aci-sim.supervisor.plist
launchctl kickstart -k gui/$(id -u)/com.aci-sim.supervisor # restart
# after editing the plist's EnvironmentVariables, kickstart -k reuses launchd's
# cached env — you must bootout + bootstrap again for changes to take effect:
launchctl bootout gui/$(id -u)/com.aci-sim.supervisor
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.aci-sim.supervisor.plist
Notes
- Both approaches leave
SIM_BINDat its loopback-only default unless explicitly overridden — seeREADME.md§Configuration and finding #23. - Neither unit manages sandbox mode (
scripts/sandbox-up.sh/sandbox-down.sh); those remain manual, root-invoked, interactive operations. - This directory ships unit files only — nothing here installs or starts a service automatically.