---
title: "swift-console"
description: "The web console — files browser, deploy control, live monitoring, and a chaos / HA lab, served from one Rust binary."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.myswift.rs/llms.txt
> Use this file to discover all available pages before exploring further.

# swift-console

`swift-console` is the management UI for a Peregrine cluster: a single Rust
(`axum`) binary that serves four surfaces over one authenticated session. No
Node.js, no external frontend — HTML/CSS/JS are served directly and pages render
without a client-side framework.

The console is an operator surface, not evidence that the storage engine has
passed every gate. G6 is GREEN on `17adf0b`; G7 is NOT ACCEPTED and the overall
production decision remains NO-GO.

## Surfaces

- **Files** — An S3-style browser: buckets/containers, objects, upload, folders, trash
with restore, TempURL, search, user management, and bulk ZIP download.
- **Deploy** — A front end over [swift-deploy-rs](/swift-deploy-rs)'s plan / validate /
apply control API.
- **Monitor** — Live cluster metrics and logs, queried server-side — no backend name, URL,
or credential reaches the browser. Overview **在线节点** is host scrape
liveness (`up{job="node"}`), not Swift service health.
- **Lab** — Tools that explain and stress the cluster: RingScope, policy compare, Object
Capsule, Tombstone Museum, Chaos Arcade, Node HA Drill, Repair Debt Index,
Protocol Mutation (Shadow), Expired-but-Alive Observatory, Profile
Cartographer, and Cluster Genome Lab.

## The Node HA Drill

The Lab's node-down tool takes a whole storage node out of the cluster and
watches the survivors carry the load. It rides the console's guarded mutation
path — journaled with a TTL **auto-restart**, so a node always comes back even
if the operator walks away — and it never touches `swift-console` or
`swift-deploy`, so the console cannot take itself down.

```
GET  /lab/api/node/status     # per-node service health + which nodes are held down
POST /lab/api/node/down       # {node, ttl_secs?} — stop a node's swift services
POST /lab/api/node/up         # {node|journal_id} — restart early, before the TTL
```

> **Historical lab evidence**
>
> In the dated 2026-08-18 fleet drill, one node was taken fully down while the
> bounded replication and erasure-coding workload completed on the survivors.
> That canary is not a current G7 result or an availability SLO. See
> [Operations](/operations).

## Build & run

```sh
cd swift-console
cargo build --release
./target/release/swift-console conf/config.json
```

Startup fails if the JSON cannot be read/parsed or the deploy token file cannot
be read. `/healthz` is the unauthenticated liveness endpoint. Default bind is
`127.0.0.1:9000`.

`config.json` sets the bind address, the Swift proxy base and auth endpoint, the
deploy upstream + token file, the metrics/logs upstreams, the account roster,
per-cluster node metadata, and the Lab gates (`lab_enabled`, `lab_mutations`).

> **Bind to loopback**
>
> The console holds an authenticated session and proxies privileged operations; it
> is meant to listen on loopback (or a trusted network) behind the cluster load
> balancer, not to be exposed directly.

## Configuration reference

| Key | Meaning |
|-----|---------|
| `bind` | listen address (default loopback) |
| `swift_base` / `auth_url` | the Swift proxy and its `/auth/v1.0` |
| `deploy_upstream` / `deploy_user` / `deploy_token_file` | the swift-deploy-rs control API and server-side Basic credential source |
| `metrics_url` / `logs_url` | metrics + log backends |
| `session_idle_hours` / `max_upload_bytes` / `tempurl_default_secs` | session, body, and generated-URL limits |
| `accounts` | allowed tenant/user roster and roles |
| `proxy_nodes` / `proxy_conf` / `proxy_service` / `proxy_port` | account-admin target set and service metadata |
| `account_admin` | enables proxy config edits/restarts; default false |
| `test_enabled` / `autocos_bin` / `autocos_home` | real benchmark surface and its runner; default disabled |
| `lab_enabled` / `lab_mutations` | enable the Lab surface / allow guarded mutations |
| `cluster_nodes` | node roster (name + storage/replication/public IPs, devices) |
| `swift_dir` / `node_root` | ring/config and device roots used by inspection tools |
| `ringsim_bin` / `getnodes_bin` / `objinfo_bin` | external inspection helper paths |
| `shadow_peer_base` / `shadow_peer_auth` / `shadow_peer_label` | optional second Swift endpoint for Shadow dual-mode (same tempauth user/key as the console login) |
| `shadow_root` | on-disk corpus + mutation log directory |

Account administration, real benchmark execution, lab pages, and lab mutations
are separate controls. Leave them off unless the management host, credentials,
node list, and undo behavior have been reviewed.

## Monitor: what “在线节点” means

The overview **在线节点** tile is `count(up{job="node"} == 1)` — Prometheus
`node_exporter` scrape success. It answers “is the host still talking?”, not
“are Swift units running?”. Taking a node down in the HA drill leaves this
count unchanged while Services / Node HA show the Swift units as down. That is
intentional; do not replace it with SSH service probes on the overview.

## Lab: Repair Debt Index

`GET /lab/debt` and `GET /lab/api/debt/snapshot` score deferred repair work
(async pending, quarantine, ring imbalance, disk/repl pressure, unhealthy
fraction) into a single debt / interest / time-to-insolvency view. Calibration
notes live in the console tree at `swift-console/docs/debt-calibration.md`.

## Lab: Protocol Mutation (Shadow)

Shadow can run a seeded mutation sequence against the logged-in cluster and,
when `shadow_peer_*` is set, against a second implementation side-by-side.
Findings and mutate corpus land under `shadow_root` (`mutations.jsonl`).

On Contabo swift1, Python SAIO listens on `127.0.0.1:8090` and Rust SAIO on
`127.0.0.1:8081` (same `test:tester` / cluster key). Point `shadow_peer_base`
at the peer you want for dual-mode 对照.

## Lab: Expired-but-Alive Observatory

`GET /lab/expired` seeds staggered `X-Delete-At` objects and polls ordinary
GET vs `X-Open-Expired: true` plus SSH disk presence. States:

`Alive → Logically Expired → Recoverable Ghost → Physically Reaped`

Summary tiles report mean / P95 / max ghost period. Requires the proxy and
object-server to forward / honour `X-Open-Expired` (Rust path now does). If the
object-expirer is not running, objects stay Recoverable Ghost — reported as a
finding, not faked into reaped.

## Lab: Profile Cartographer

`GET /lab/profilemap` turns stage timers into an architecture tree (Proxy /
Object / Replicator). Pulse PUTs via `POST /lab/api/profilemap/pulse`, then
read `GET /lab/api/profilemap/snapshot?path=put|replication|get`. Sources:
process-local `/recon/stage` on nodes, or Prom `swift_stage_*` when present.

## Lab: Cluster Genome Lab

`GET /lab/genome` evolves object-ring **weights** only under a simulated fault
suite (`swift-ring-sim`), then shows a Pareto front (lowest migration, highest
availability, lowest waste, fastest repair proxy). Never writes the live ring.

## Rust Toolchain Canary

Out-of-tree under `rust-toolchain-canary/`: install pinned toolchains, run a
CRUD smoke against a live Swift endpoint, and emit a differential report. This
is a host CLI, not a console page.

Source: https://docs.myswift.rs/swift-console/index.mdx
