-
-
-
-
-
-
-
diff --git a/docs/architecture.md b/docs/architecture.md
deleted file mode 100644
index 8104ee1..0000000
--- a/docs/architecture.md
+++ /dev/null
@@ -1,147 +0,0 @@
----
-layout: default
-title: Architecture
-description: How the jump host authenticates users, resolves reachable hosts from the directory, injects per-user keys, and bridges SSH — plus the web UI and audit model.
----
-
-# Architecture
-
-The jump host is a Node.js service (using [`ssh2`](https://github.com/mscdex/ssh2)
-as both an SSH **server** and **client**) with two faces: the SSH front door
-(default `:2222`) and a web UI/API (`:3002`). It holds no user database of its
-own — identity, authorization, and onward credentials all come from the shared
-directory.
-
-```
- ┌────────────────────── jump host ──────────────────────┐
- ssh │ ssh2 Server (:2222) │ ssh2 Client
- ─────┼─▶ 1. authenticate user ──▶ LDAP (sshPublicKey / bind) │ ───────────▶ downstream
- user │ 2. resolve target ──▶ SSO /api/discovery │ sshd (as the
- │ 3. inject key ──▶ LDAP (add sshPublicKey) │ real user)
- │ 4. bridge channels ◀───────────────────────────────▶ │
- │ web UI/API (:3002) ──▶ audit + metrics (redis) │
- └───────────────────────────────────────────────────────┘
-```
-
-## 1. Inbound authentication
-
-When a user connects, the jump host authenticates them against LDAP:
-
-- **Public key** — it looks up the user's `sshPublicKey` values in the directory
- and matches the offered key (handling ssh2's probe-then-sign two-phase
- publickey auth). The jump host's *own* injected key (identified by its comment
- marker) is deliberately excluded from this match — only the jump host may hold
- that private key, so accepting it inbound would be a bypass.
-- **Password** — an LDAP simple bind as the user's DN. Policy is configurable:
- `off` (keys only — recommended for a public host), `local` (passwords only
- from loopback/RFC1918 clients, keys-only from the internet), or `all`.
-
-Every attempt — success or failure, with method and reason — is audited.
-
-## 2. Access & target resolution
-
-The hosts a user may reach are computed from the directory, not a local list:
-
-1. The user's LDAP group memberships (`(&(objectClass=groupOfNames)(member=…))`).
-2. For each group, the SSO's
- `GET /api/discovery/resources?group=` (authenticated with an API token),
- unioned and filtered to `kind: host`.
-
-Each host's dial address is `metadata.ip` (or the hostname from
-`metadata.address`) and port `metadata.sshPort` (default 22). Results are cached
-briefly per user and shared by both the grammar path and the TUI picker.
-
-Target matching tries, in order: exact slug → `host_`-prefixed slug → display
-name → IP → address hostname. A raw IP that isn't an accessible directory host
-is refused unless explicitly allowed.
-
-> The directory auto-creates `_access` / `_admin` groups for every
-> host and service (see the SSO's
-> [Directory & Inventory](https://theta42.github.io/sso-manager-node/directory.html)
-> docs), which is exactly what this authorization reads.
-
-## 3. Per-user key injection {#per-user-key-injection}
-
-The jump host holds **one** keypair. To connect downstream *as the user*
-without asking them for anything, it must present a key the downstream `sshd`
-will accept for that user. Downstream hosts (joined via
-[ldap-client](https://github.com/theta42/ldap-client)) serve authorized keys
-straight from LDAP via `AuthorizedKeysCommand`. So on a user's first connection,
-the jump host appends its own public key to that user's `sshPublicKey` attribute
-in LDAP — comment-marked so it's recognizable — then connects downstream with
-its private key.
-
-- Idempotent: the key is added once; a redis flag skips the LDAP round-trip
- afterwards.
-- The jump host's bind account therefore needs **write access to the
- `sshPublicKey` attribute** on user entries (an OpenLDAP ACL — see the README).
- In the bundled theta-env deployment this is handled for you.
-- Because the marker key is excluded from inbound auth (step 1), it grants only
- the jump host's onward path, never inbound impersonation.
-
-## 4. Bridging
-
-Once the upstream connection is ready, the jump host splices SSH channels
-between the two connections:
-
-- **shell / exec** — piped both ways, with window-change and exit-status
- forwarded.
-- **SFTP subsystem** — the two subsystem channels are raw-piped as opaque bytes;
- no SFTP protocol parsing is needed, which is why WinSCP and `sftp` work
- unchanged.
-- Channel requests that arrive before the upstream is ready are buffered and
- replayed, so nothing is dropped during the connect.
-- The downstream host key's SHA256 fingerprint is recorded in the audit event
- (trust-on-use in v1).
-
-Byte counts per direction are tallied cheaply for the audit record.
-
-## Web UI, API & audit
-
-An Express + EJS + Bootstrap app on `:3002` — the same front-end stack and
-look/feel as the SSO Manager and Proxy. Login is OIDC against the SSO plus a
-local anti-lockout admin (`auth.adminUsers`), with admin access gated by
-`auth.adminGroups`. It exposes:
-
-- `GET /health` — open; `{status, activeSessions, version}`
-- `GET /api/sessions` — active sessions
-- `GET /api/audit?page=&uid=&target=&status=` — the paged audit log
-- `GET /api/metrics` — counters (total, failures, top users/hosts)
-
-Audit events and counters live in redis. Each event captures: user, auth method,
-mode (grammar/picker), target slug/address/port, channel type, client IP,
-success + failure reason, downstream host-key fingerprint, timing, and bytes in/out.
-
-## Standalone mode
-
-Everything above describes the default backend. Set `standalone.enabled: true`
-and two modules become conditional facades, swapping their entire
-implementation at `require` time based on that flag — nothing else in the
-codebase (`ssh_server.js`, `bridge.js`, `key_inject.js`, `tui_picker.js`, the
-web UI) changes or even knows which mode it's running in:
-
-- **`models/user_ldap.js`** — LDAP client, or `models/user_file.js` (an
- [@simpleworkjs/orm](https://www.npmjs.com/package/@simpleworkjs/orm)-backed
- store implementing the same `getUser` / `getGroups` / `checkPassword` /
- `addSshKey` interface).
-- **`utils/access.js`** — LDAP groups + SSO `/api/discovery`, or
- `utils/hosts_file.js` (same ORM package, same `accessibleHosts()` interface).
- In standalone mode there's no group-based authorization: every stored host
- is accessible to every stored user.
-
-The ORM is Sequelize underneath, defaulting to a local SQLite file but
-accepting any Sequelize-supported dialect via `conf.orm`. See
-[Installation](installation.html#standalone-mode) for config and how to add
-users/hosts (there's no admin UI for standalone data yet).
-
-## Where it sits in the stack
-
-- **[SSO Manager](https://theta42.github.io/sso-manager-node/)** — provides the
- OpenLDAP directory (users, groups, `sshPublicKey`) and the inventory API this
- jump host reads.
-- **[ldap-client](https://github.com/theta42/ldap-client)** — enrolls the
- downstream Linux hosts (SSSD/PAM + `AuthorizedKeysCommand`) that the jump host
- connects into.
-- **[Proxy](https://theta42.github.io/proxy/)** — fronts the jump host's web UI
- under TLS.
-- **[theta-env](https://theta42.github.io/theta-env/)** — wires it all together.
diff --git a/docs/assets/css/style.css b/docs/assets/css/style.css
deleted file mode 100644
index e24a5de..0000000
--- a/docs/assets/css/style.css
+++ /dev/null
@@ -1,116 +0,0 @@
-/* theta42 docs site — shares the in-app dark navbar/footer + card look
- (Bootstrap 5 + Font Awesome, same as the running apps) rather than a
- generic Jekyll theme. */
-
-body {
- background-color: #f4f5f6;
-}
-
-.navbar-brand img {
- filter: drop-shadow(0 0 2px rgba(0, 0, 0, .4));
-}
-
-.navbar-nav .nav-link.active {
- color: #fff;
- font-weight: 600;
-}
-
-/* Markdown content typography, scoped to the card body so it doesn't leak
- into the nav/footer. */
-.site-content h1:first-child {
- margin-top: 0;
-}
-
-.site-content h1,
-.site-content h2,
-.site-content h3 {
- font-weight: 700;
-}
-
-.site-content h2 {
- margin-top: 2.5rem;
- padding-bottom: .4rem;
- border-bottom: 1px solid #e9ecef;
-}
-
-.site-content h3 {
- margin-top: 1.75rem;
-}
-
-.site-content a {
- color: #a3671f;
- text-decoration-color: rgba(163, 103, 31, .35);
-}
-
-.site-content a:hover {
- color: #8a5a16;
-}
-
-.site-content pre {
- background-color: #212529;
- color: #f8f9fa;
- padding: 1rem 1.25rem;
- border-radius: .375rem;
- overflow-x: auto;
-}
-
-.site-content code {
- color: #a3671f;
- background-color: #f4f0e8;
- padding: .15em .4em;
- border-radius: .25rem;
- font-size: .875em;
-}
-
-.site-content pre code {
- color: inherit;
- background: none;
- padding: 0;
-}
-
-.site-content table {
- display: block;
- overflow-x: auto;
- width: 100%;
- border-collapse: collapse;
- margin: 1.25rem 0;
-}
-
-.site-content table th,
-.site-content table td {
- border: 1px solid #dee2e6;
- padding: .5rem .75rem;
- text-align: left;
-}
-
-.site-content table th {
- background-color: #f8f9fa;
-}
-
-.site-content blockquote {
- border-left: 4px solid #C59341;
- padding: .5rem 1rem;
- margin: 1.25rem 0;
- background-color: #f8f6f1;
- color: #495057;
-}
-
-.site-content img {
- max-width: 100%;
- height: auto;
-}
-
-/* Screenshot grids in the markdown use width="49%" inline attrs for a
- two-up desktop layout -- stack them on narrow screens instead of
- squeezing to illegibility. */
-@media (max-width: 576px) {
- .site-content img[width] {
- width: 100% !important;
- margin-bottom: .75rem;
- }
-}
-
-.site-content hr {
- margin: 2rem 0;
- border-top: 1px solid #e9ecef;
-}
diff --git a/docs/assets/img/favicon.svg b/docs/assets/img/favicon.svg
deleted file mode 100644
index 35e1881..0000000
--- a/docs/assets/img/favicon.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
diff --git a/docs/assets/img/theta42.svg b/docs/assets/img/theta42.svg
deleted file mode 100644
index e598305..0000000
--- a/docs/assets/img/theta42.svg
+++ /dev/null
@@ -1,51 +0,0 @@
-
diff --git a/docs/connecting.md b/docs/connecting.md
deleted file mode 100644
index 966ba87..0000000
--- a/docs/connecting.md
+++ /dev/null
@@ -1,105 +0,0 @@
----
-layout: default
-title: Connecting
-description: How to reach downstream hosts through the jump host — the username grammar, the interactive picker, SFTP/WinSCP, and what access you get.
----
-
-# Connecting
-
-You reach a downstream host two ways: name the target in your username, or log
-in plain and pick it from a menu. Either way you authenticate **once**, to the
-jump host, with your directory credentials.
-
-## The username grammar
-
-```
-{uid}_-_{target}
-```
-
-- `{uid}` — your directory username.
-- `_-_` — the separator (legal in an SSH username everywhere, including WinSCP).
-- `{target}` — the host to reach: a directory **slug** (`host_web01` or just
- `web01`), the host's **display name**, its **IP**, or the hostname in its
- directory `address`.
-
-```bash
-ssh alice_-_web01@jump.example.com # by slug (host_ prefix optional)
-ssh alice_-_10.0.0.10@jump.example.com # by IP (must be a host you can reach)
-```
-
-If the target matches a host your directory groups grant, you're bridged
-straight to its `sshd` — same as if you'd SSH'd directly, but through the
-audited jump host.
-
-## SFTP / WinSCP / scp
-
-Because the whole route is encoded in the username, file transfer tools that
-only take one connection string work with no extra configuration:
-
-```bash
-sftp -P 2222 alice_-_web01@jump.example.com
-scp -P 2222 file.txt alice_-_web01@jump.example.com:/tmp/
-```
-
-**WinSCP:** set Host name to `jump.example.com`, Port to `2222`, and User name
-to `alice_-_web01`. SFTP is bridged as an opaque byte stream, so all operations
-(browse, upload, download, rename) work normally.
-
-## The interactive picker
-
-Log in with just your username and you get a TUI list of every host you can
-reach:
-
-```bash
-ssh alice@jump.example.com
-```
-
-- **↑ / ↓** move the selection
-- **type** to filter the list incrementally
-- **Enter** connect to the highlighted host
-- **number keys** jump straight to that row
-- **q** or **Ctrl-C** to quit
-
-Pick a host and you're bridged into it. The picker only ever lists hosts your
-directory access allows — it doubles as "what can I reach from here?"
-
-## What you can reach
-
-The set of hosts is computed per login: your LDAP group memberships intersected
-with the SSO directory's hosts (via the `host__access` groups the
-directory auto-creates for each machine). To get access to a new host, an admin
-adds you to that host's access group in the SSO — nothing on the jump host
-changes.
-
-Targets that don't resolve to a host you're allowed to reach are refused (and
-audited). Raw IPs that aren't a known directory host are denied by default.
-
-> On a [standalone](architecture.html#standalone-mode) jump host (no LDAP/SSO),
-> every registered host is reachable by every registered user — there's no
-> group-based restriction to ask an admin about.
-
-## Authentication
-
-The jump host authenticates **you** against the directory:
-
-- **Public key** — matched against your `sshPublicKey` entries in LDAP. Use your
- normal SSH key; the client picks it automatically.
-- **Password** — your directory password (LDAP bind). Password auth is often
- restricted to local networks or disabled entirely on a public jump host
- (keys-only) — check with your operator.
-
-You never manage a separate credential for the downstream host: the jump host
-handles onward authentication for you (see
-[Architecture](architecture.html#per-user-key-injection)).
-
-## First connection to a host
-
-The very first time you reach a given downstream host, the jump host provisions
-its access key for you behind the scenes. If that first attempt races the
-directory's key-cache refresh you may see a brief
-
-```
-jump-host: first-time key propagation, retrying…
-```
-
-and it reconnects automatically. Subsequent connections are immediate.
diff --git a/docs/images/audit.png b/docs/images/audit.png
deleted file mode 100644
index 997974d..0000000
Binary files a/docs/images/audit.png and /dev/null differ
diff --git a/docs/images/dashboard.png b/docs/images/dashboard.png
deleted file mode 100644
index 8caa276..0000000
Binary files a/docs/images/dashboard.png and /dev/null differ
diff --git a/docs/images/login.png b/docs/images/login.png
deleted file mode 100644
index 5881ac9..0000000
Binary files a/docs/images/login.png and /dev/null differ
diff --git a/docs/images/sessions.png b/docs/images/sessions.png
deleted file mode 100644
index e52511c..0000000
Binary files a/docs/images/sessions.png and /dev/null differ
diff --git a/docs/index.md b/docs/index.md
deleted file mode 100644
index b7d73bc..0000000
--- a/docs/index.md
+++ /dev/null
@@ -1,121 +0,0 @@
----
-layout: default
-title: Home
-description: An SSH jump host for the theta42 stack — one public host and directory-driven access to every downstream machine you're entitled to; LDAP by default, or fully standalone.
----
-
-# Jump Host
-
-An SSH jump host for the [theta42](https://github.com/theta42) self-hosted
-stack. Users SSH into **one** public host and land on any downstream host
-they're entitled to — authenticated against the shared LDAP directory,
-authorized from the [SSO Manager](https://theta42.github.io/sso-manager-node/)'s
-inventory graph, and audited end to end.
-
-No per-host accounts, no distributing keys, no VPN. The same people who log in
-to your SSO are the people who can reach your machines — and only the machines
-their directory groups grant.
-
-Part of the theta42 self-hosted identity stack, alongside
-[SSO Manager](https://theta42.github.io/sso-manager-node/) and
-[Proxy](https://theta42.github.io/proxy/), composable with one command via
-[theta-env](https://theta42.github.io/theta-env/).
-
-## Screenshots
-
-
-
-
-
-
-*(click any screenshot to view full size)*
-
-Don't want to run LDAP or the SSO Manager? **Standalone mode** stores users
-and hosts in a local SQL database instead (SQLite by default, any
-Sequelize-supported dialect if you want something else) — same SSH front door,
-key injection, and audit trail. See
-[Installation](installation.html#standalone-mode) to get started.
-
-## Two ways to connect
-
-**Direct (WinSCP/SFTP-friendly):**
-
-```bash
-ssh alice_-_web01@jump.example.com
-sftp -P 2222 alice_-_web01@jump.example.com
-```
-
-The username grammar is `{uid}_-_{target}` — `target` is a directory host slug
-(with or without the `host_` prefix), a bare hostname, or an IP. One username
-string, no interactive step, so it works cleanly in WinSCP and scripts.
-
-**Interactive picker:**
-
-```bash
-ssh alice@jump.example.com
-```
-
-A plain login shows a TUI list of the hosts you can reach; arrow-key or type to
-filter, Enter to connect.
-
-See **[Connecting](connecting.html)** for the full usage guide.
-
-## Why a jump host (and why this one)
-
-A bastion/jump host is the standard way to give SSH access to internal machines
-through a single audited entry point. What's usually painful is *authorization*
-and *credentials*: who may reach which host, and how the bastion authenticates
-onward without you copying keys everywhere.
-
-This jump host answers both from your directory:
-
-- **Authorization is your directory graph.** The hosts you can reach are the
- union of your LDAP groups × the SSO's inventory (the `host__access`
- groups the directory already auto-creates). Add someone to a group; they can
- reach the host. No bastion-side allow-list to maintain.
-- **Onward auth is automatic.** The jump host holds one key and injects its
- public half into your `sshPublicKey` on first use, then connects downstream
- **as you**. Downstream hosts already serve keys from LDAP (via
- [ldap-client](https://github.com/theta42/ldap-client)'s
- `AuthorizedKeysCommand`), so nothing downstream needs configuring.
-
-## Features
-
-- **Username-grammar routing** (`uid_-_target`) — straight-through to the host,
- SFTP included (WinSCP works)
-- **Interactive TUI host picker** on plain login, scoped to your access
-- **LDAP inbound auth** — public key or password (keys-only policy recommended
- for a public host)
-- **Directory-driven access** — reachable hosts come from the SSO inventory, not
- a static list
-- **Per-user key injection** — no downstream changes, no key distribution
-- **Shell, exec, and SFTP** bridging
-- **Web UI + HTTP API** for auditing and metrics — active sessions, a searchable
- audit log, per-user/per-host counters
-- **Full audit trail** — who, target, method, result, bytes, duration, and the
- downstream host-key fingerprint
-- **Standalone mode** — no LDAP, no SSO Manager; users and hosts live in a
- local SQL database (Sequelize, any dialect — SQLite by default)
-- Packaged like the rest of the stack: one-command Docker, idempotent bare-metal
- installer, or bundled in theta-env
-
-## Get it
-
-```bash
-git clone https://github.com/theta42/jump-host.git
-cd jump-host
-cp secrets.js.example config/jump-secrets.js # then edit it
-docker compose up -d --build
-```
-
-That's the standalone quick start. For bare-metal and the bundled theta-env
-option, see **[Installation](installation.html)**.
-
-## Related projects
-
-- **[SSO Manager](https://theta42.github.io/sso-manager-node/)** — the OpenLDAP
- directory + OIDC provider + the inventory graph this jump host reads.
-- **[Proxy](https://theta42.github.io/proxy/)** — puts your web apps behind the
- same identity; fronts this jump host's web UI.
-- **[theta-env](https://theta42.github.io/theta-env/)** — runs the whole stack,
- jump host included, with one command.
diff --git a/docs/installation.md b/docs/installation.md
deleted file mode 100644
index 6a5f37b..0000000
--- a/docs/installation.md
+++ /dev/null
@@ -1,155 +0,0 @@
----
-layout: default
-title: Installation
-description: Install the jump host three ways — bundled in the theta-env stack, standalone Docker, or bare metal — plus standalone mode (no LDAP/SSO), the LDAP write-ACL, and port-22 options.
----
-
-# Installation
-
-Three ways to run the jump host, in increasing manual effort. All read their
-config through [@simpleworkjs/conf](https://www.npmjs.com/package/@simpleworkjs/conf)
-(`conf/base.js` < `conf/.js` < the `CONF_SECRETS` file < `app_*` env).
-
-## Standalone mode (no LDAP/SSO) {#standalone-mode}
-
-Skip LDAP and the SSO Manager entirely. Not to be confused with "Standalone
-Docker" below, which is still LDAP + SSO, just run outside theta-env. Set in your secrets/config:
-
-```js
-standalone: { enabled: true },
-orm: { dialect: 'sqlite', storage: './data/standalone.sqlite', logging: false },
-```
-
-`orm` is passed straight to Sequelize, so any supported dialect works — SQLite
-is just the zero-dependency default. Everything downstream of auth (bridging,
-key injection, the web UI, audit) is unchanged.
-
-There's no admin UI for standalone users/hosts yet, so add them directly with
-the ORM models:
-
-```js
-const StandaloneUser = require('./models/standalone_user');
-const StandaloneHost = require('./models/standalone_host');
-const bcrypt = require('bcrypt');
-
-await StandaloneUser.create({
- uid: 'alice',
- passwordHash: await bcrypt.hash('a real password', 10),
- sshPublicKeys: ['ssh-ed25519 AAAA... alice@laptop'],
- groups: [],
-});
-
-await StandaloneHost.create({
- slug: 'host_web01',
- displayName: 'web01',
- kind: 'host',
- metadata: { ip: '10.0.0.5', sshPort: 22 },
-});
-```
-
-Every host in the standalone inventory is reachable by every standalone user —
-there's no group-based authorization yet (`groups` on `StandaloneUser` is
-accepted for interface parity with the LDAP path, not enforced).
-
-The rest of this page (requirements, the LDAP write-ACL, the three install
-paths) describes the default LDAP + SSO mode — skip it if you're running
-standalone.
-
-## Requirements
-
-- The [SSO Manager](https://theta42.github.io/sso-manager-node/) (OpenLDAP
- directory + `/api/discovery`), v1.3.0 or newer.
-- Downstream hosts joined via
- [ldap-client](https://github.com/theta42/ldap-client) (SSSD +
- `AuthorizedKeysCommand`).
-- An LDAP bind account with **write access to the `sshPublicKey` attribute** on
- user entries (see below).
-- An SSO API token (`sso_…`) for the directory queries.
-
-## 1. Unified theta-env stack (recommended)
-
-Enable it in `theta-env/setup.env`:
-
-```bash
-CFG_JUMP_HOST_ENABLED=true
-CFG_JUMP_HOST=jump.example.com
-JUMP_SSH_PORT=2222
-```
-
-Re-run `./setup.sh`. The stack builds the submodule (behind the `jump-host`
-compose profile), mints the directory API token, writes
-`./config/jump-secrets.js`, grants the `sshPublicKey` write-ACL, registers the
-jump host in the proxy, and seeds a directory entry. Forward the public host's
-`:22` (or `:2222`) to the container's published `JUMP_SSH_PORT`.
-
-## 2. Standalone Docker
-
-```bash
-cp secrets.js.example config/jump-secrets.js
-$EDITOR config/jump-secrets.js # LDAP bind (+ sshPublicKey write ACL), SSO url + token
-docker compose up -d --build
-```
-
-Host keys persist in the `jump-data` volume. The web UI is on `:3002`; front it
-with your own TLS/proxy.
-
-## 3. Bare metal
-
-```bash
-curl -fsSL https://raw.githubusercontent.com/theta42/jump-host/master/ops/install.sh | sudo bash
-sudo $EDITOR /etc/jump-host/secrets.js
-sudo systemctl restart jump-host
-journalctl -u jump-host -f
-```
-
-`ops/install.sh` installs Node 22 + Redis, hard-resets the checkout at
-`/opt/theta42/jump-host` to the remote branch, symlinks the systemd unit, and
-runs `npm ci`. Idempotent — re-run to update. Overridable via `REPO_DIR=`,
-`BRANCH=`, `SECRETS_FILE=`.
-
-## The LDAP write-ACL (required)
-
-The jump host injects its public key into each user's `sshPublicKey`, so its
-bind account must be able to **write** that attribute. In the bundled OpenLDAP:
-
-```
-access to attrs=sshPublicKey
- by dn.exact="cn=ldapclient,ou=people,dc=example,dc=com" write
- by self write
- by * read
-```
-
-In the theta-env bundle this is handled for you (the jump host binds as the LDAP
-admin). For a hardened standalone deployment, use a dedicated bind account with
-exactly this attribute-scoped ACL. Without write access, key injection fails and
-every bridge attempt is audited `key-inject-failed`.
-
-## Listening on port 22
-
-The default SSH port is **2222** so the service needs no privilege. To listen on
-22, set `ssh.listenPort: 22` and either:
-
-- **systemd:** uncomment `AmbientCapabilities=CAP_NET_BIND_SERVICE` in the unit;
-- **Docker:** publish `22:22`; or
-- **firewall:** DNAT `22 → 2222`.
-
-## Configuration reference
-
-Every key is documented in
-[`secrets.js.example`](https://github.com/theta42/jump-host/blob/master/secrets.js.example):
-`ldap` (bind + bases + TLS), `sso` (url + apiToken), `ssh`
-(`listenPort`, `passwordAuth`, `allowRawIPs`, `keyComment`, timeouts,
-`maxSessions`), `web.port`, `oidc` (web-UI SSO login), `auth`
-(`adminGroups` / `adminUsers` / `localAdminPass`), and `redis`.
-
-## Verifying
-
-```bash
-ssh -p 2222 youruid@jump.example.com # TUI picker
-ssh -p 2222 youruid_-_somehost@jump.example.com # direct
-sftp -P 2222 youruid_-_somehost@jump.example.com # WinSCP path
-curl -s http://localhost:3002/health
-```
-
-Watch `journalctl -u jump-host -f` (or `docker logs -f jump-host`) and the audit
-log at `/audit` in the web UI.
diff --git a/docs/robots.txt b/docs/robots.txt
deleted file mode 100644
index bd503ab..0000000
--- a/docs/robots.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-User-agent: *
-Allow: /
-
-Sitemap: https://theta42.github.io/proxy/sitemap.xml