CENTRAL SERVER BLUEPRINT · REV 01

One server.
Seven engineers.
A controlled AI account pool.

Centralize Claude, Grok and Codex CLI traffic without copying provider OAuth credentials into employee Linux profiles.

LIVE ARCHITECTURE LOCAL ONLY
SSH TRUST BOUNDARY
U1 Linux user U2 Linux user U3 Linux user U4 Linux user U5 Linux user U6 Linux user U7 Linux user

CLIProxyAPI

127.0.0.1:8317

One native systemd service

01 per-user client key 02 round-robin selection 03 1h session affinity 04 automatic failover
OAUTH VAULT
C

Claude

3 OAuth sessions

G

Grok

3 OAuth sessions

X

Codex

1 OAuth session

Request / token flow Streamed response NO PUBLIC LISTENER

Native systemd

Selected for this Ubuntu host

  • Smallest operational surface
  • Starts after reboot
  • Restarts after process failure
cliproxyapi.service
7

Separate Linux profiles

One client key per SSH user

  • Independent shell history
  • Per-user key revocation
  • No OAuth files in home folders
U1 … U7 → 7 unique keys

Admin UI via tunnel

Management stays localhost-only

  • Remote management remains off
  • Separate management key
  • No public port 8317
ssh -L 8317:127.0.0.1:8317 …

What happens after an engineer types a prompt

The engineer only handles SSH and their local CLI. Provider OAuth stays inside the service account's protected auth directory.

  1. 01

    SSH session

    Engineer enters their own Linux profile on the central server.

    $ ssh user@server
  2. 02

    CLI reads endpoint

    The profile config points Claude or Codex at the local gateway.

    http://127.0.0.1:8317
  3. 03

    Key identifies user

    A unique proxy key authenticates the inbound client request.

    principal: user_03
  4. 04

    Router selects auth

    A healthy matching credential is selected; an existing session can stay sticky.

    strategy: round-robin
  5. 05

    Provider streams

    The gateway translates the protocol and relays the response to the CLI.

    response: streaming
  6. 06

    Logs record outcome

    Service and request metadata support troubleshooting and capacity checks.

    status · latency · route
EXPECTED ROUTE

Healthy account selected

The request stays bound to one credential for the session. If that credential becomes unavailable, the router can fail over and rebind.

Responsibility matrix

WHO OWNS WHAT
AreaLinux profileCLIProxyAPIOAuth vaultProvider
IdentityOwns SSH access and one client keyValidates key and resolves principalNot exposedRecognizes selected OAuth account
CredentialsNo provider token storedReads protected auth filesStores and refreshes OAuth stateIssues and validates tokens
RoutingSends to local endpointSelects, binds, cools down, fails overProvides eligible sessionsEnforces upstream availability
LogsShell/CLI logs in own homeSystem and request diagnosticsRefresh/auth eventsUpstream response and limits

One service account owns the sensitive state

Employees can call the localhost endpoint, but ordinary profiles cannot read configuration, OAuth files, the management key, or another user's home.

Filesystem

ROOT OWNED
/etc/cliproxyapi/
└── config.yaml                 0640 root:cliproxyapi

/var/lib/cliproxyapi/
└── auth/                       0700 cliproxyapi
    ├── claude-*.json
    ├── xai-*.json
    └── codex-*.json

/var/log/cliproxyapi/       rotated logs
/etc/systemd/system/
└── cliproxyapi.service

Configuration shape

NO REAL SECRETS
host: "127.0.0.1"
port: 8317
auth-dir: "/var/lib/cliproxyapi/auth"

remote-management:
  allow-remote: false
  secret-key: "${MANAGEMENT_SECRET}"

api-keys:
  - "${USER_01_KEY}"
  - "${USER_02_KEY}"
  - "… one per SSH user"

routing:
  strategy: "round-robin"
  session-affinity: true
  session-affinity-ttl: "1h"
!

The central host is the dependency

Yes—the server must be online whenever anyone uses a proxied CLI. If the host, service, SSH path, or local listener is unavailable, all seven proxied profiles stop working together.

Boot
systemd starts the service automatically
Crash
restart policy recovers the process
Host loss
requires VPS recovery or a future standby host
Architecture as Mermaid source copyable / portable
architecture.mmd
flowchart LR
  subgraph SSH[SSH trust boundary]
    U[7 isolated Linux users]
  end
  subgraph HOST[Central Ubuntu server]
    K[Per-user API keys]
    P[CLIProxyAPI\n127.0.0.1:8317]
    R[Round-robin + 1h affinity]
    V[(Protected OAuth vault)]
  end
  subgraph POOLS[Provider pools]
    C[Claude × 3]
    G[Grok × 3]
    X[Codex × 1]
  end
  U --> K --> P --> R --> V
  V --> C
  V --> G
  V --> X

Roll out in four controlled passes

Build the gateway first, add OAuth sessions second, then validate with one heavy user before pointing all seven profiles at it.

  1. 01

    Foundation

    • Create locked service account
    • Install pinned release
    • Bind localhost and add systemd
    curl /v1/models → 200
  2. 02

    Account onboarding

    • Set management secret
    • Open UI through SSH tunnel
    • Complete 3 + 3 + 1 OAuth flows
    /management.html
  3. 03

    Engineer pilot

    • Create seven client keys
    • Configure one test profile
    • Exercise failover and streaming
    one user · real workload
  4. 04

    Team rollout

    • Configure remaining profiles
    • Enable log rotation/alerts
    • Publish operator runbook
    seven users · one endpoint

Technical failure modes

OPERATOR RUNBOOK
SignalTechnical causeExpected gateway behaviorOperator action
OAuth expiryAccess token expired and refresh failedCredential becomes unavailable; bound sessions may rebindRe-authenticate that provider in the tunneled UI
Provider limitOne account/model is temporarily limitedCool down or fail over to another eligible credentialConfirm pool health; test the affected model explicitly
Gateway downProcess crash, bad config, failed updatesystemd attempts restart; local calls fail meanwhileCheck systemctl status and journalctl -u
Session collisionConcurrent tools reuse session identity unexpectedlyAffinity can bind requests to an unintended credentialInspect headers/IDs; shorten TTL or disable affinity for test
Log pressureVerbose request logging grows on diskService continues until I/O or disk becomes constrainedRotate, cap retention, alert on disk threshold
Client driftClaude/Codex update changes protocol or endpoint behaviorTranslation or streaming can regressKeep a canary profile and pin/roll back versions

Go-live gates

ALL MUST PASS
  • Service returns models after reboot
  • Port 8317 only listens on 127.0.0.1
  • Ordinary users cannot read the auth directory
  • Every client key can be revoked independently
  • All seven OAuth sessions appear healthy
  • Long responses stream without proxy timeout
  • Forced provider failure triggers expected failover
  • Logs rotate and survive service restart
  • Config and auth backup restore is tested

Update the UI automatically; update the core deliberately

The bundled control panel can refresh itself from its configured repository. The proxy binary should use a pinned release and a tested upgrade/rollback procedure.

A

Control panel

Background panel updates are enabled by default unless disabled in configuration.

AUTO
B

Proxy core

Download a known release, checksum it, stop, replace, start, validate, and retain the previous binary.

PINNED
C

CLI clients

Test Claude and Codex upgrades with one canary Linux profile before the team-wide update.

CANARY
Copied to clipboard