infra-networking
Manage AICP's network surfaces — LocalAI on `localhost:8090` (host) → `:8080` (container), AICP own metrics on `:9101/metrics`, optional Grafana on `:3000` + Prometheus on `:9090`, MCP server stdio (n
SKILL.md.claude/skills/infra-networking/SKILL.md
GitHubinfra-networking
Manage AICP's network surfaces — port mappings, MCP transport, planned
P2P cluster peering, and reverse-proxy/firewall integration. AICP is
local-first by default (everything on localhost); fleet integration
extends to peer connections.
Trigger phrases (when to load this skill)
Load when the conversation matches any of:
- Direct verb: "what ports does AICP use", "expose LocalAI to fleet", "firewall rules", "set up cluster peering", "AICP behind a reverse proxy", "MCP not connecting"
- Multi-machine setup: extending AICP from single-host to fleet (per
CLAUDE.md
## Infrastructure targettwo-machine plan) - Security posture: confirming what's exposed externally vs localhost-only
Do NOT load when:
- The concern is HTTPS cert management (load
infra-security) - The concern is application-layer routing (load
aicp/core/router.py-related skills, e.g.,aicp-ops-runtime) - The concern is API contract design (load
infra-api)
Operations
Operation 1 — Inventory ports and surfaces
When: pre-deploy audit or firewall configuration.
Process:
- Build the canonical list (current AICP):
- 8090 (host) → 8080 (container): LocalAI OpenAI-compatible API
/metrics+/app/collections(KB)
- 9101: AICP own Prometheus exporter (
aicp/core/prometheus.py) - 9090 (optional): Prometheus server (when
make monitoring-up) - 3000 (optional): Grafana (when
make monitoring-up, admin/aicp) - MCP server: stdio transport (no port — bidirectional pipe via the MCP client invocation)
- Agent server:
aicp --agent <port>(operator-chosen, default not running)
- 8090 (host) → 8080 (container): LocalAI OpenAI-compatible API
- For each: record exposed-on (
localhost-only vs0.0.0.0), required inbound for fleet vs operator-only - Document in firewall config or operator runbook
Quality bar: by default, ALL surfaces should be localhost-only.
Exposing externally is a deliberate fleet/integration step.
Operation 2 — Expose LocalAI for fleet access
When: fleet machines need to call this AICP's LocalAI inference API.
Process:
- Edit
docker-compose.yamlLocalAI port mapping:- From
127.0.0.1:8090:8080(localhost-only) - To
0.0.0.0:8090:8080(any-interface) OR<lan-ip>:8090:8080(specific interface — preferred)
- From
- Restart LocalAI:
docker compose restart localai - Configure firewall (ufw / iptables / cloud SG) to allow port 8090 from fleet IPs only — NEVER open to internet
- Verify from fleet machine:
curl http://<host>:8090/v1/models - Update fleet config (
config/fleet.yaml.template→ operator-specificfleet.yaml) to point at the new LAN-accessible LocalAI
Quality bar: NEVER expose 8090 to the public internet. LocalAI's API has no auth; exposure invites abuse. Firewall to LAN/VPN only.
Operation 3 — Set up LocalAI P2P cluster peering (planned, partial)
When: extending to multi-machine fleet with cross-host model load balancing.
Process:
- Per CLAUDE.md
## Infrastructure target, the planned topology is "LocalAI peering: Cluster 1 ↔ Cluster 2 (load balance, failover)" - Status: marked PENDING in CLAUDE.md
## The MissionStage 4 ("partial: circuit breakers + DLQ + reliable profile shipped; cluster peering pending") - Implementation requires:
- LocalAI's built-in P2P feature (libp2p-based)
- Discovery mechanism (mDNS / static peer list / federated registry)
- Per-peer health monitoring (
aicp_p2p_statusMCP tool exists but is now deprecated — useaicp --observe)
- Document the cluster setup in
wiki/decisions/00_inbox/before implementing
Quality bar: cluster peering is architecturally significant — author the decision page BEFORE implementing.
Operation 4 — Place AICP behind a reverse proxy
When: operator wants TLS termination or path-based routing in front of LocalAI / AICP exporter.
Process:
- Choose reverse proxy: Caddy (auto-TLS, simplest), Nginx (most flexible), Traefik (cloud-native)
- Configure proxy to forward:
https://<domain>/v1/*→http://localhost:8090https://<domain>/metrics→http://localhost:9101/metricshttps://<domain>/grafana/*→http://localhost:3000(with prefix stripping if needed)
- After proxy is in place, restrict LocalAI to
localhost-only (proxy handles external) - Add auth at the proxy layer (basic auth, mTLS, OAuth) — LocalAI has no native auth
Quality bar: TLS termination + auth at the proxy is the operator's responsibility; AICP itself doesn't ship with these. Don't expose the raw proxied LocalAI without auth.
Operation 5 — Diagnose MCP connection failures
When: a Claude Code agent or other MCP client can't connect to AICP's MCP server.
Process:
- AICP's MCP uses stdio transport — the client invokes
aicp --mcpand reads/writes via stdin/stdout - Verify the client's MCP config points at the correct command:
aicp --mcp(or the standaloneaicp-mcpentry point) - Common failures:
aicpnot in PATH → fix with absolute path or PATH update- Python venv not activated → MCP config needs to invoke through the venv
- Permission denied → check executable bit
- Test manually:
echo '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{}}' | aicp --mcpshould return a JSON response
Quality bar: MCP stdio transport has no port to firewall — connection issues are almost always config (wrong command, wrong PATH, wrong venv).
Gotchas
Detection: agent recommends exposing LocalAI port 8090 to the public internet. Rule: NEVER expose 8090 publicly. LocalAI has no auth; exposure is an immediate abuse vector. Reasoning: any external reachable LocalAI becomes free GPU compute for whoever finds it; cost + abuse risk is severe.
Detection: agent uses MCP stdio config without absolute path. Rule: MCP client configs should use absolute paths to the AICP binary (or full venv-activated invocation). Reasoning: MCP clients run
aicp --mcpfrom their own working directory; PATH may not include AICP's venv.Detection: agent assumes AICP's metrics port (9101) is the same as Prometheus (9090). Rule: 9101 is AICP's OWN exporter; 9090 is the Prometheus SERVER (when monitoring-up). Different roles. Reasoning: Prometheus scrapes 9101 (and 8090's
/metricsfor LocalAI). They're producer + consumer, not duplicates.Detection: agent skips reverse proxy auth for LocalAI exposure. Rule: any external exposure must include auth at the proxy layer. Reasoning: LocalAI's lack of native auth means the proxy is the ONLY auth gate; skipping it leaves the inference API open.
Detection: agent recommends cluster peering without checking CLAUDE.md status. Rule: per CLAUDE.md, cluster peering is PENDING. Don't promise it exists today. Reasoning: setting expectations correctly avoids operator confusion; the partial-Stage-4 status should be transparent.
Reference exemplars
docker-compose.yaml— port mappings, GPU passthrough configaicp/core/prometheus.py—:9101/metricsexporteraicp/agent/server.py— agent server (operator-chosen port viaaicp --agent <port>)config/fleet.yaml.template— fleet config template (cluster peering)- CLAUDE.md
## Infrastructure target— planned multi-machine topology
Domain context
AICP is local-first by default — everything on localhost. Fleet rollout
extends carefully: LocalAI exposed to LAN only, AICP exporter exposed
to Prometheus on LAN, agent server activated per-host. The MCP server
uses stdio (no port), avoiding network-level concerns at that layer.
TLS + auth are operator-supplied via reverse proxy when external
exposure is needed.
Related skills
| Skill | When to use |
|---|---|
infra-security |
When the concern is the security posture of exposed surfaces |
infra-monitoring |
When setting up Prometheus/Grafana scraping |
aicp-ops-runtime |
When diagnosing live network state via --check / --observe |
config-deploy |
When the deploy profile selects different network config |
foundation-docker |
When changing the Docker network config |