2026-06-19 12:28:30 +00:00
|
|
|
import { useEffect, useRef, useState } from 'react'
|
|
|
|
|
import { Terminal as XTerm } from '@xterm/xterm'
|
|
|
|
|
import { FitAddon } from '@xterm/addon-fit'
|
|
|
|
|
import '@xterm/xterm/css/xterm.css'
|
|
|
|
|
import {
|
|
|
|
|
Play,
|
|
|
|
|
Square,
|
|
|
|
|
RotateCw,
|
|
|
|
|
Pause,
|
|
|
|
|
PlayCircle,
|
|
|
|
|
Trash2,
|
|
|
|
|
RefreshCw,
|
|
|
|
|
TerminalSquare,
|
|
|
|
|
ScrollText,
|
|
|
|
|
X,
|
|
|
|
|
} from 'lucide-react'
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
import {
|
|
|
|
|
api,
|
|
|
|
|
getToken,
|
|
|
|
|
type Container,
|
|
|
|
|
type SshContainer,
|
|
|
|
|
type AgentContainer,
|
|
|
|
|
type ContainerStats,
|
|
|
|
|
} from '../lib/api'
|
2026-06-19 12:28:30 +00:00
|
|
|
|
|
|
|
|
const TEXT_PRIMARY = '#E8E6E0'
|
|
|
|
|
const TEXT_SECONDARY = '#7A7D85'
|
|
|
|
|
const GOLD = '#C8A434'
|
|
|
|
|
|
|
|
|
|
const cardBase: React.CSSProperties = {
|
|
|
|
|
backgroundColor: 'rgba(10, 10, 12, 0.92)',
|
|
|
|
|
border: '1px solid rgba(200, 164, 52, 0.08)',
|
|
|
|
|
borderRadius: '12px',
|
|
|
|
|
boxShadow: '0 0 20px rgba(200, 164, 52, 0.03)',
|
|
|
|
|
}
|
|
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
// docker = Engine TCP API; ssh = `docker` CLI over SSH; agent = pushed report.
|
|
|
|
|
// docker/ssh support management; agent is read-only monitoring.
|
|
|
|
|
type Source = 'docker' | 'ssh' | 'agent'
|
|
|
|
|
|
|
|
|
|
/** A selectable container host. For docker/ssh it wraps an integration id; for
|
|
|
|
|
* agent it wraps the string hostId of a reporting agent. */
|
|
|
|
|
interface HostOption {
|
|
|
|
|
source: Source
|
|
|
|
|
/** integration id (docker/ssh) or agent hostId (agent), as a string key. */
|
|
|
|
|
key: string
|
|
|
|
|
label: string
|
|
|
|
|
/** numeric integration id for docker/ssh sources. */
|
|
|
|
|
integrationId?: number
|
|
|
|
|
/** agent hostId for agent sources. */
|
|
|
|
|
agentHostId?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Unified table row across all three sources. */
|
|
|
|
|
interface Row {
|
|
|
|
|
id: string
|
|
|
|
|
name: string
|
|
|
|
|
image: string
|
|
|
|
|
state: string
|
|
|
|
|
status: string
|
|
|
|
|
ports: string
|
|
|
|
|
/** Stats embedded in agent reports (docker/ssh fetch stats separately/none). */
|
|
|
|
|
embeddedStats?: ContainerStats
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toRowFromDocker(c: Container): Row {
|
|
|
|
|
return {
|
|
|
|
|
id: c.id,
|
|
|
|
|
name: c.name,
|
|
|
|
|
image: c.image,
|
|
|
|
|
state: c.state,
|
|
|
|
|
status: c.status,
|
|
|
|
|
ports: c.ports.length === 0 ? '' : c.ports.map((p) => `${p.publicPort ?? ''}${p.publicPort ? ':' : ''}${p.privatePort}/${p.type}`).join(', '),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toRowFromSsh(c: SshContainer): Row {
|
|
|
|
|
return { id: c.id, name: c.name, image: c.image, state: c.state.toLowerCase(), status: c.status, ports: c.ports }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toRowFromAgent(c: AgentContainer): Row {
|
|
|
|
|
const ports = c.ports
|
|
|
|
|
.map((p) => `${p.hostPort ? `${p.hostPort}:` : ''}${p.containerPort}/${p.proto}`)
|
|
|
|
|
.join(', ')
|
|
|
|
|
const embeddedStats: ContainerStats | undefined = c.stats
|
|
|
|
|
? {
|
|
|
|
|
cpuPercent: c.stats.cpuPercent ?? 0,
|
|
|
|
|
memUsage: c.stats.memUsage ?? 0,
|
|
|
|
|
memLimit: c.stats.memLimit ?? 0,
|
|
|
|
|
netRx: c.stats.netRxBytes ?? 0,
|
|
|
|
|
netTx: c.stats.netTxBytes ?? 0,
|
|
|
|
|
}
|
|
|
|
|
: undefined
|
|
|
|
|
return { id: c.id, name: c.name, image: c.image, state: c.state.toLowerCase(), status: c.status, ports, embeddedStats }
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 12:28:30 +00:00
|
|
|
function stateColor(state: string): string {
|
|
|
|
|
if (state === 'running') return '#2ECC71'
|
|
|
|
|
if (state === 'paused') return '#E0A82E'
|
|
|
|
|
if (state === 'exited' || state === 'dead') return '#E74C3C'
|
|
|
|
|
return TEXT_SECONDARY
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function formatBytes(bytes: number): string {
|
|
|
|
|
if (bytes < 1024) return `${bytes} B`
|
|
|
|
|
const units = ['KB', 'MB', 'GB', 'TB']
|
|
|
|
|
let v = bytes
|
|
|
|
|
let i = -1
|
|
|
|
|
do {
|
|
|
|
|
v /= 1024
|
|
|
|
|
i++
|
|
|
|
|
} while (v >= 1024 && i < units.length - 1)
|
|
|
|
|
return `${v.toFixed(1)} ${units[i]}`
|
|
|
|
|
}
|
|
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
/** A dynamic detail tab opened by clicking a container name. */
|
|
|
|
|
interface DetailTab {
|
|
|
|
|
tabId: string
|
|
|
|
|
source: Source
|
|
|
|
|
integrationId?: number
|
|
|
|
|
agentHostId?: string
|
|
|
|
|
containerId: string
|
|
|
|
|
containerName: string
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 12:28:30 +00:00
|
|
|
export default function Containers() {
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
const [hostOptions, setHostOptions] = useState<HostOption[]>([])
|
|
|
|
|
const [selectedKey, setSelectedKey] = useState<string>('')
|
|
|
|
|
const [rows, setRows] = useState<Row[]>([])
|
2026-06-19 12:28:30 +00:00
|
|
|
const [error, setError] = useState<string | null>(null)
|
|
|
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
|
const [busyId, setBusyId] = useState<string | null>(null)
|
|
|
|
|
const [statsById, setStatsById] = useState<Record<string, ContainerStats>>({})
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
const [logsRow, setLogsRow] = useState<Row | null>(null)
|
|
|
|
|
const [execRow, setExecRow] = useState<Row | null>(null)
|
|
|
|
|
|
|
|
|
|
// Intra-page tabs: the containers list plus any opened container-detail tabs.
|
|
|
|
|
const [detailTabs, setDetailTabs] = useState<DetailTab[]>([])
|
|
|
|
|
const [activeTab, setActiveTab] = useState<string>('list')
|
|
|
|
|
|
|
|
|
|
const selected = hostOptions.find((h) => h.key === selectedKey)
|
|
|
|
|
const source: Source | null = selected?.source ?? null
|
|
|
|
|
const canManage = source === 'docker' || source === 'ssh'
|
|
|
|
|
|
|
|
|
|
async function loadHosts() {
|
|
|
|
|
const [{ integrations }, agentRes] = await Promise.all([
|
|
|
|
|
api.listIntegrations(),
|
|
|
|
|
api.listAgentHosts().catch(() => ({ hosts: [] })),
|
|
|
|
|
])
|
|
|
|
|
const opts: HostOption[] = []
|
|
|
|
|
for (const i of integrations) {
|
|
|
|
|
if (i.type === 'docker') opts.push({ source: 'docker', key: `docker:${i.id}`, label: `${i.name} (Docker API)`, integrationId: i.id })
|
|
|
|
|
if (i.type === 'ssh') opts.push({ source: 'ssh', key: `ssh:${i.id}`, label: `${i.name} (SSH)`, integrationId: i.id })
|
|
|
|
|
}
|
|
|
|
|
for (const h of agentRes.hosts) {
|
|
|
|
|
const label = `${h.hostname || h.hostId} (Agent${h.stale ? ' — stale' : ''})`
|
|
|
|
|
opts.push({ source: 'agent', key: `agent:${h.hostId}`, label, agentHostId: h.hostId })
|
|
|
|
|
}
|
|
|
|
|
setHostOptions(opts)
|
|
|
|
|
if (opts.length > 0 && !opts.some((o) => o.key === selectedKey)) setSelectedKey(opts[0].key)
|
|
|
|
|
}
|
2026-06-19 12:28:30 +00:00
|
|
|
|
|
|
|
|
useEffect(() => {
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
loadHosts()
|
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2026-06-19 12:28:30 +00:00
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
function refresh() {
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
if (!selected) return
|
2026-06-19 12:28:30 +00:00
|
|
|
setLoading(true)
|
|
|
|
|
setError(null)
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
setStatsById({})
|
|
|
|
|
|
|
|
|
|
if (selected.source === 'agent' && selected.agentHostId) {
|
|
|
|
|
api
|
|
|
|
|
.listAgentContainers(selected.agentHostId)
|
|
|
|
|
.then(({ containers }) => setRows(containers.map(toRowFromAgent)))
|
|
|
|
|
.catch((err) => setError(err instanceof Error ? err.message : 'Failed to load agent report'))
|
|
|
|
|
.finally(() => setLoading(false))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (selected.source === 'ssh' && selected.integrationId) {
|
|
|
|
|
api
|
|
|
|
|
.listSshContainers(selected.integrationId)
|
|
|
|
|
.then(({ containers }) => setRows(containers.map(toRowFromSsh)))
|
|
|
|
|
.catch((err) => setError(err instanceof Error ? err.message : 'Failed to list containers'))
|
|
|
|
|
.finally(() => setLoading(false))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (selected.source === 'docker' && selected.integrationId) {
|
|
|
|
|
const integrationId = selected.integrationId
|
|
|
|
|
api
|
|
|
|
|
.listContainers(integrationId)
|
|
|
|
|
.then(({ containers }) => {
|
|
|
|
|
setRows(containers.map(toRowFromDocker))
|
|
|
|
|
containers.forEach((c) => {
|
|
|
|
|
if (c.state !== 'running') return
|
|
|
|
|
api
|
|
|
|
|
.containerStats(integrationId, c.id)
|
|
|
|
|
.then((stats) => setStatsById((prev) => ({ ...prev, [c.id]: stats })))
|
|
|
|
|
.catch(() => {})
|
|
|
|
|
})
|
2026-06-19 12:28:30 +00:00
|
|
|
})
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
.catch((err) => setError(err instanceof Error ? err.message : 'Failed to list containers'))
|
|
|
|
|
.finally(() => setLoading(false))
|
|
|
|
|
}
|
2026-06-19 12:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
refresh()
|
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
}, [selectedKey])
|
2026-06-19 12:28:30 +00:00
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
async function runAction(c: Row, action: 'start' | 'stop' | 'restart' | 'pause' | 'unpause') {
|
|
|
|
|
if (!selected?.integrationId) return
|
2026-06-19 12:28:30 +00:00
|
|
|
setBusyId(c.id)
|
|
|
|
|
setError(null)
|
|
|
|
|
try {
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
if (selected.source === 'ssh') await api.sshContainerAction(selected.integrationId, c.id, action)
|
|
|
|
|
else await api.containerAction(selected.integrationId, c.id, action)
|
2026-06-19 12:28:30 +00:00
|
|
|
refresh()
|
|
|
|
|
} catch (err) {
|
|
|
|
|
setError(err instanceof Error ? err.message : `Failed to ${action} container`)
|
|
|
|
|
} finally {
|
|
|
|
|
setBusyId(null)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
async function removeRow(c: Row) {
|
|
|
|
|
if (!selected?.integrationId) return
|
2026-06-19 12:28:30 +00:00
|
|
|
if (!confirm(`Remove container "${c.name}"? This cannot be undone.`)) return
|
|
|
|
|
setBusyId(c.id)
|
|
|
|
|
setError(null)
|
|
|
|
|
try {
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
if (selected.source === 'ssh') await api.removeSshContainer(selected.integrationId, c.id, c.state === 'running')
|
|
|
|
|
else await api.removeContainer(selected.integrationId, c.id, c.state === 'running')
|
2026-06-19 12:28:30 +00:00
|
|
|
refresh()
|
|
|
|
|
} catch (err) {
|
|
|
|
|
setError(err instanceof Error ? err.message : 'Failed to remove container')
|
|
|
|
|
} finally {
|
|
|
|
|
setBusyId(null)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
function openDetail(c: Row) {
|
|
|
|
|
if (!selected) return
|
|
|
|
|
const tabId = `${selected.key}::${c.id}`
|
|
|
|
|
setDetailTabs((prev) => (prev.some((t) => t.tabId === tabId) ? prev : [
|
|
|
|
|
...prev,
|
|
|
|
|
{
|
|
|
|
|
tabId,
|
|
|
|
|
source: selected.source,
|
|
|
|
|
integrationId: selected.integrationId,
|
|
|
|
|
agentHostId: selected.agentHostId,
|
|
|
|
|
containerId: c.id,
|
|
|
|
|
containerName: c.name,
|
|
|
|
|
},
|
|
|
|
|
]))
|
|
|
|
|
setActiveTab(tabId)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function closeDetail(tabId: string) {
|
|
|
|
|
setDetailTabs((prev) => prev.filter((t) => t.tabId !== tabId))
|
|
|
|
|
setActiveTab((cur) => (cur === tabId ? 'list' : cur))
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 12:28:30 +00:00
|
|
|
return (
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
<div className="flex items-center justify-between">
|
|
|
|
|
<div>
|
|
|
|
|
<h1 className="text-xl font-semibold" style={{ color: TEXT_PRIMARY }}>
|
|
|
|
|
Containers
|
|
|
|
|
</h1>
|
|
|
|
|
<p className="text-sm" style={{ color: TEXT_SECONDARY }}>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
Manage and monitor Docker containers — via the Docker Engine API, the
|
|
|
|
|
<code> docker</code> CLI over SSH, or a reporting agent.
|
2026-06-19 12:28:30 +00:00
|
|
|
</p>
|
|
|
|
|
</div>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
{activeTab === 'list' && (
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<select
|
|
|
|
|
value={selectedKey}
|
|
|
|
|
onChange={(e) => setSelectedKey(e.target.value)}
|
|
|
|
|
className="rounded-md border border-white/10 bg-transparent px-2 py-1.5 text-sm"
|
|
|
|
|
style={{ color: TEXT_PRIMARY }}
|
|
|
|
|
>
|
|
|
|
|
{hostOptions.length === 0 && <option value="">No container hosts</option>}
|
|
|
|
|
{hostOptions.map((h) => (
|
|
|
|
|
<option key={h.key} value={h.key}>
|
|
|
|
|
{h.label}
|
|
|
|
|
</option>
|
|
|
|
|
))}
|
|
|
|
|
</select>
|
|
|
|
|
<button
|
|
|
|
|
onClick={refresh}
|
|
|
|
|
className="flex items-center gap-1 rounded-md px-3.5 py-1.5 text-xs"
|
|
|
|
|
style={{ border: '1px solid rgba(200,164,52,0.2)', color: TEXT_PRIMARY }}
|
|
|
|
|
>
|
|
|
|
|
<RefreshCw size={13} className={loading ? 'animate-spin' : ''} /> Refresh
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Intra-page tab bar */}
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<div className="flex items-end gap-1 border-b border-white/10">
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
<TabButton label="Containers" active={activeTab === 'list'} onClick={() => setActiveTab('list')} />
|
|
|
|
|
{detailTabs.map((t) => (
|
|
|
|
|
<TabButton
|
|
|
|
|
key={t.tabId}
|
|
|
|
|
label={t.containerName}
|
|
|
|
|
active={activeTab === t.tabId}
|
|
|
|
|
onClick={() => setActiveTab(t.tabId)}
|
|
|
|
|
onClose={() => closeDetail(t.tabId)}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
2026-06-19 12:28:30 +00:00
|
|
|
</div>
|
|
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
{error && activeTab === 'list' && (
|
2026-06-19 12:28:30 +00:00
|
|
|
<div className="flex items-center justify-between rounded-md px-3 py-2 text-sm" style={{ backgroundColor: 'rgba(231,76,60,0.1)', color: '#E74C3C' }}>
|
|
|
|
|
<span>{error}</span>
|
|
|
|
|
<button onClick={() => setError(null)} style={{ color: TEXT_SECONDARY }}>
|
|
|
|
|
<X size={14} />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
{activeTab === 'list' ? (
|
|
|
|
|
<div style={cardBase} className="overflow-hidden">
|
|
|
|
|
<table className="w-full text-sm">
|
|
|
|
|
<thead>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<tr style={{ color: TEXT_PRIMARY, borderBottom: '1px solid rgba(255,255,255,0.06)' }}>
|
|
|
|
|
<th className="px-3 py-3 text-center text-base font-bold">Name</th>
|
|
|
|
|
<th className="px-3 py-3 text-center text-base font-bold">Image</th>
|
|
|
|
|
<th className="px-3 py-3 text-center text-base font-bold">State</th>
|
|
|
|
|
<th className="px-3 py-3 text-center text-base font-bold">CPU</th>
|
|
|
|
|
<th className="px-3 py-3 text-center text-base font-bold">Memory</th>
|
|
|
|
|
<th className="px-3 py-3 text-center text-base font-bold">Ports</th>
|
|
|
|
|
<th className="px-3 py-3 text-center text-base font-bold">Actions</th>
|
2026-06-19 12:28:30 +00:00
|
|
|
</tr>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
{rows.length === 0 && (
|
|
|
|
|
<tr>
|
|
|
|
|
<td colSpan={7} className="px-3 py-6 text-center" style={{ color: TEXT_SECONDARY }}>
|
|
|
|
|
{selected ? 'No containers found.' : 'Select a container host.'}
|
2026-06-19 12:28:30 +00:00
|
|
|
</td>
|
|
|
|
|
</tr>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
)}
|
|
|
|
|
{rows.map((c) => {
|
|
|
|
|
const stats = statsById[c.id] ?? c.embeddedStats
|
|
|
|
|
const busy = busyId === c.id
|
|
|
|
|
return (
|
|
|
|
|
<tr key={c.id} style={{ borderBottom: '1px solid rgba(255,255,255,0.04)' }}>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<td className="px-3 py-4 text-center text-[15px]">
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
<button
|
|
|
|
|
onClick={() => openDetail(c)}
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
className="hover:underline"
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
style={{ color: GOLD }}
|
|
|
|
|
title="View details"
|
|
|
|
|
>
|
|
|
|
|
{c.name}
|
|
|
|
|
</button>
|
|
|
|
|
</td>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<td className="px-3 py-4 text-center text-[15px]" style={{ color: TEXT_SECONDARY }}>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
{c.image}
|
|
|
|
|
</td>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<td className="px-3 py-4 text-center text-[15px]">
|
|
|
|
|
<span className="flex items-center justify-center gap-1.5">
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
<span className="inline-block h-2 w-2 rounded-full" style={{ background: stateColor(c.state) }} />
|
|
|
|
|
<span style={{ color: TEXT_PRIMARY }}>{c.status}</span>
|
|
|
|
|
</span>
|
|
|
|
|
</td>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<td className="px-3 py-4 text-center text-[15px]" style={{ color: TEXT_SECONDARY }}>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
{stats ? `${stats.cpuPercent.toFixed(1)}%` : '—'}
|
|
|
|
|
</td>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<td className="px-3 py-4 text-center text-[15px]" style={{ color: TEXT_SECONDARY }}>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
{stats ? `${formatBytes(stats.memUsage)} / ${formatBytes(stats.memLimit)}` : '—'}
|
|
|
|
|
</td>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<td className="px-3 py-4 text-center text-[15px]" style={{ color: TEXT_SECONDARY }}>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
{c.ports || '—'}
|
|
|
|
|
</td>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<td className="px-3 py-4 text-[15px]">
|
|
|
|
|
<div className="flex items-center justify-center gap-2">
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
{canManage ? (
|
|
|
|
|
<>
|
|
|
|
|
{c.state === 'running' ? (
|
|
|
|
|
<>
|
|
|
|
|
<button disabled={busy} onClick={() => runAction(c, 'pause')} title="Pause" style={{ color: TEXT_SECONDARY }}>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<Pause size={16} />
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
</button>
|
|
|
|
|
<button disabled={busy} onClick={() => runAction(c, 'restart')} title="Restart" style={{ color: TEXT_SECONDARY }}>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<RotateCw size={16} />
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
</button>
|
|
|
|
|
<button disabled={busy} onClick={() => runAction(c, 'stop')} title="Stop" style={{ color: TEXT_SECONDARY }}>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<Square size={16} />
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
</button>
|
|
|
|
|
<button disabled={busy} onClick={() => setExecRow(c)} title="Exec terminal" style={{ color: GOLD }}>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<TerminalSquare size={16} />
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
</button>
|
|
|
|
|
</>
|
|
|
|
|
) : c.state === 'paused' ? (
|
|
|
|
|
<button disabled={busy} onClick={() => runAction(c, 'unpause')} title="Unpause" style={{ color: TEXT_SECONDARY }}>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<PlayCircle size={16} />
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
</button>
|
|
|
|
|
) : (
|
|
|
|
|
<button disabled={busy} onClick={() => runAction(c, 'start')} title="Start" style={{ color: TEXT_SECONDARY }}>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<Play size={16} />
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
<button disabled={busy} onClick={() => setLogsRow(c)} title="Logs" style={{ color: TEXT_SECONDARY }}>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<ScrollText size={16} />
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
</button>
|
|
|
|
|
<button disabled={busy} onClick={() => removeRow(c)} title="Remove" style={{ color: '#E74C3C' }}>
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
<Trash2 size={16} />
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
</button>
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
<span className="text-xs" style={{ color: TEXT_SECONDARY }}>read-only</span>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
)
|
|
|
|
|
})}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
(() => {
|
|
|
|
|
const tab = detailTabs.find((t) => t.tabId === activeTab)
|
|
|
|
|
if (!tab) return null
|
|
|
|
|
return <ContainerDetail key={tab.tabId} tab={tab} />
|
|
|
|
|
})()
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{logsRow && selected?.integrationId && (source === 'docker' || source === 'ssh') && (
|
|
|
|
|
<LogsModal source={source} integrationId={selected.integrationId} row={logsRow} onClose={() => setLogsRow(null)} />
|
|
|
|
|
)}
|
|
|
|
|
{execRow && selected?.integrationId && (source === 'docker' || source === 'ssh') && (
|
|
|
|
|
<ExecModal source={source} integrationId={selected.integrationId} row={execRow} onClose={() => setExecRow(null)} />
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function TabButton({ label, active, onClick, onClose }: { label: string; active: boolean; onClick: () => void; onClose?: () => void }) {
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
onClick={onClick}
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
className="flex cursor-pointer items-center gap-2 rounded-t-md px-4 py-2 text-sm font-semibold"
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
style={{
|
|
|
|
|
color: active ? GOLD : TEXT_SECONDARY,
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
backgroundColor: active ? 'rgba(200,164,52,0.12)' : 'rgba(255,255,255,0.02)',
|
|
|
|
|
border: active ? '1px solid rgba(200,164,52,0.35)' : '1px solid rgba(255,255,255,0.06)',
|
|
|
|
|
borderBottom: active ? '1px solid rgba(200,164,52,0.12)' : '1px solid rgba(255,255,255,0.06)',
|
|
|
|
|
marginBottom: '-1px',
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
maxWidth: '200px',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<span className="truncate">{label}</span>
|
|
|
|
|
{onClose && (
|
|
|
|
|
<X
|
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)
Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.
- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird
* Make mesh verification universal (CIDR check, not NetBird-specific)
Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.
* Add reachability fallback for routed meshes (VPC peering, etc.)
A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.
* Add Mesh section to Settings for configuring/testing the mesh gate
Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
* Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.
* Expand Help page with quick-start guide and real-world examples
Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.
* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued
Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.
* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs
* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar
* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
|
|
|
size={13}
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
onClick={(e) => {
|
|
|
|
|
e.stopPropagation()
|
|
|
|
|
onClose()
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function DetailRow({ label, value }: { label: string; value: React.ReactNode }) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex gap-3 py-1 text-sm">
|
|
|
|
|
<span className="w-40 shrink-0" style={{ color: TEXT_SECONDARY }}>{label}</span>
|
|
|
|
|
<span className="min-w-0 break-words" style={{ color: TEXT_PRIMARY }}>{value}</span>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
|
|
|
|
return (
|
|
|
|
|
<div style={cardBase} className="p-4">
|
|
|
|
|
<h3 className="mb-2 text-xs font-medium uppercase tracking-wide" style={{ color: TEXT_SECONDARY }}>{title}</h3>
|
|
|
|
|
{children}
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Container detail tab. Agent reports carry the full inspect+stats payload, so
|
|
|
|
|
* for agent hosts we render everything. For docker/ssh sources we currently
|
|
|
|
|
* only have the list row data, so we show what we have and note the rest is
|
|
|
|
|
* available from an agent — graceful degradation per the design.
|
|
|
|
|
*/
|
|
|
|
|
function ContainerDetail({ tab }: { tab: DetailTab }) {
|
|
|
|
|
const [container, setContainer] = useState<AgentContainer | null>(null)
|
|
|
|
|
const [loading, setLoading] = useState(tab.source === 'agent')
|
|
|
|
|
const [error, setError] = useState<string | null>(null)
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (tab.source !== 'agent' || !tab.agentHostId) return
|
|
|
|
|
setLoading(true)
|
|
|
|
|
api
|
|
|
|
|
.getAgentContainer(tab.agentHostId, tab.containerId)
|
|
|
|
|
.then(({ container }) => setContainer(container))
|
|
|
|
|
.catch((err) => setError(err instanceof Error ? err.message : 'Failed to load container detail'))
|
|
|
|
|
.finally(() => setLoading(false))
|
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
}, [tab.tabId])
|
|
|
|
|
|
|
|
|
|
if (tab.source !== 'agent') {
|
|
|
|
|
return (
|
|
|
|
|
<div style={cardBase} className="p-4">
|
|
|
|
|
<p className="text-sm" style={{ color: TEXT_PRIMARY }}>{tab.containerName}</p>
|
|
|
|
|
<p className="mt-2 text-sm" style={{ color: TEXT_SECONDARY }}>
|
|
|
|
|
Rich container detail (inspect data, mounts, networks, environment) is
|
|
|
|
|
provided by the monitoring agent. This host is a{' '}
|
|
|
|
|
{tab.source === 'ssh' ? 'Docker-over-SSH' : 'Docker API'} source — use the
|
|
|
|
|
list view actions for management, or install the ArchNest agent on this
|
|
|
|
|
host for full detail.
|
|
|
|
|
</p>
|
2026-06-19 12:28:30 +00:00
|
|
|
</div>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
)
|
|
|
|
|
}
|
2026-06-19 12:28:30 +00:00
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
if (loading) return <p className="text-sm" style={{ color: TEXT_SECONDARY }}>Loading…</p>
|
|
|
|
|
if (error) return <p className="text-sm" style={{ color: '#E74C3C' }}>{error}</p>
|
|
|
|
|
if (!container) return <p className="text-sm" style={{ color: TEXT_SECONDARY }}>No data.</p>
|
|
|
|
|
|
|
|
|
|
const c = container
|
|
|
|
|
const masked = (v: string) => v
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="grid gap-4" style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))' }}>
|
|
|
|
|
<Section title="Overview">
|
|
|
|
|
<DetailRow label="Name" value={c.name} />
|
|
|
|
|
<DetailRow label="Image" value={c.image} />
|
|
|
|
|
{c.imageId && <DetailRow label="Image ID" value={<code className="text-xs">{c.imageId.slice(0, 19)}</code>} />}
|
|
|
|
|
<DetailRow label="Container ID" value={<code className="text-xs">{c.id.slice(0, 12)}</code>} />
|
|
|
|
|
{c.command && <DetailRow label="Command" value={<code className="text-xs">{c.command}</code>} />}
|
|
|
|
|
{c.createdAt && <DetailRow label="Created" value={new Date(c.createdAt).toLocaleString()} />}
|
|
|
|
|
{c.startedAt && <DetailRow label="Started" value={new Date(c.startedAt).toLocaleString()} />}
|
|
|
|
|
</Section>
|
|
|
|
|
|
|
|
|
|
<Section title="State & Health">
|
|
|
|
|
<DetailRow
|
|
|
|
|
label="State"
|
|
|
|
|
value={
|
|
|
|
|
<span className="flex items-center gap-1.5">
|
|
|
|
|
<span className="inline-block h-2 w-2 rounded-full" style={{ background: stateColor(c.state.toLowerCase()) }} />
|
|
|
|
|
{c.status || c.state}
|
|
|
|
|
</span>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
{c.health && c.health !== 'none' && <DetailRow label="Health" value={c.health} />}
|
|
|
|
|
<DetailRow label="Restart count" value={String(c.restartCount ?? 0)} />
|
|
|
|
|
{c.restartPolicy && <DetailRow label="Restart policy" value={c.restartPolicy} />}
|
|
|
|
|
</Section>
|
|
|
|
|
|
|
|
|
|
{c.stats && (
|
|
|
|
|
<Section title="Stats (snapshot)">
|
|
|
|
|
<DetailRow label="CPU" value={`${(c.stats.cpuPercent ?? 0).toFixed(1)}%`} />
|
|
|
|
|
<DetailRow label="Memory" value={`${formatBytes(c.stats.memUsage ?? 0)} / ${formatBytes(c.stats.memLimit ?? 0)}`} />
|
|
|
|
|
<DetailRow label="Network" value={`↓ ${formatBytes(c.stats.netRxBytes ?? 0)} ↑ ${formatBytes(c.stats.netTxBytes ?? 0)}`} />
|
|
|
|
|
<DetailRow label="Block I/O" value={`R ${formatBytes(c.stats.blockReadBytes ?? 0)} W ${formatBytes(c.stats.blockWriteBytes ?? 0)}`} />
|
|
|
|
|
</Section>
|
2026-06-19 12:28:30 +00:00
|
|
|
)}
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
|
|
|
|
|
<Section title="Ports">
|
|
|
|
|
{c.ports.length === 0 ? (
|
|
|
|
|
<p className="text-sm" style={{ color: TEXT_SECONDARY }}>None published.</p>
|
|
|
|
|
) : (
|
|
|
|
|
c.ports.map((p, i) => (
|
|
|
|
|
<DetailRow key={i} label={`${p.containerPort}/${p.proto}`} value={p.hostPort ? `${p.hostIp || '0.0.0.0'}:${p.hostPort}` : 'not published'} />
|
|
|
|
|
))
|
|
|
|
|
)}
|
|
|
|
|
</Section>
|
|
|
|
|
|
|
|
|
|
<Section title="Networks">
|
|
|
|
|
{c.networks.length === 0 ? (
|
|
|
|
|
<p className="text-sm" style={{ color: TEXT_SECONDARY }}>None.</p>
|
|
|
|
|
) : (
|
|
|
|
|
c.networks.map((n, i) => <DetailRow key={i} label={n.name} value={n.ip || '—'} />)
|
|
|
|
|
)}
|
|
|
|
|
</Section>
|
|
|
|
|
|
|
|
|
|
<Section title="Mounts">
|
|
|
|
|
{c.mounts.length === 0 ? (
|
|
|
|
|
<p className="text-sm" style={{ color: TEXT_SECONDARY }}>None.</p>
|
|
|
|
|
) : (
|
|
|
|
|
c.mounts.map((m, i) => (
|
|
|
|
|
<DetailRow key={i} label={m.destination || '—'} value={`${m.source || ''}${m.rw === false ? ' (ro)' : ''}`} />
|
|
|
|
|
))
|
|
|
|
|
)}
|
|
|
|
|
</Section>
|
|
|
|
|
|
|
|
|
|
<Section title="Environment">
|
|
|
|
|
{c.env.length === 0 ? (
|
|
|
|
|
<p className="text-sm" style={{ color: TEXT_SECONDARY }}>None.</p>
|
|
|
|
|
) : (
|
|
|
|
|
c.env.map((e, i) => <DetailRow key={i} label={e.key} value={<code className="text-xs">{masked(e.value)}</code>} />)
|
|
|
|
|
)}
|
|
|
|
|
</Section>
|
|
|
|
|
|
|
|
|
|
{c.labels && Object.keys(c.labels).length > 0 && (
|
|
|
|
|
<Section title="Labels">
|
|
|
|
|
{Object.entries(c.labels).map(([k, v]) => (
|
|
|
|
|
<DetailRow key={k} label={k} value={<span className="text-xs">{v}</span>} />
|
|
|
|
|
))}
|
|
|
|
|
</Section>
|
2026-06-19 12:28:30 +00:00
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
function LogsModal({ source, integrationId, row, onClose }: { source: 'docker' | 'ssh'; integrationId: number; row: Row; onClose: () => void }) {
|
2026-06-19 12:28:30 +00:00
|
|
|
const [logs, setLogs] = useState('')
|
|
|
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
|
const [error, setError] = useState<string | null>(null)
|
|
|
|
|
|
|
|
|
|
function load() {
|
|
|
|
|
setLoading(true)
|
|
|
|
|
setError(null)
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
const req = source === 'ssh' ? api.sshContainerLogs(integrationId, row.id) : api.containerLogs(integrationId, row.id)
|
|
|
|
|
req
|
2026-06-19 12:28:30 +00:00
|
|
|
.then(({ logs }) => setLogs(logs))
|
|
|
|
|
.catch((err) => setError(err instanceof Error ? err.message : 'Failed to fetch logs'))
|
|
|
|
|
.finally(() => setLoading(false))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
useEffect(load, [])
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-6">
|
|
|
|
|
<div style={cardBase} className="flex h-[70vh] w-full max-w-3xl flex-col p-4">
|
|
|
|
|
<div className="mb-2 flex items-center justify-between">
|
|
|
|
|
<h2 className="text-sm font-medium" style={{ color: TEXT_PRIMARY }}>
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
Logs — {row.name}
|
2026-06-19 12:28:30 +00:00
|
|
|
</h2>
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<button onClick={load} style={{ color: TEXT_SECONDARY }} title="Refresh">
|
|
|
|
|
<RefreshCw size={14} className={loading ? 'animate-spin' : ''} />
|
|
|
|
|
</button>
|
|
|
|
|
<button onClick={onClose} style={{ color: TEXT_SECONDARY }}>
|
|
|
|
|
<X size={16} />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{error && <p className="mb-2 text-xs" style={{ color: '#E74C3C' }}>{error}</p>}
|
|
|
|
|
<pre className="min-h-0 flex-1 overflow-auto whitespace-pre-wrap rounded-md p-3 text-xs" style={{ backgroundColor: '#0A0A0C', color: TEXT_PRIMARY }}>
|
|
|
|
|
{logs || (loading ? 'Loading…' : 'No logs.')}
|
|
|
|
|
</pre>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
function ExecModal({ source, integrationId, row, onClose }: { source: 'docker' | 'ssh'; integrationId: number; row: Row; onClose: () => void }) {
|
2026-06-19 12:28:30 +00:00
|
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
|
|
|
const wsRef = useRef<WebSocket | null>(null)
|
|
|
|
|
const [connected, setConnected] = useState(false)
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!containerRef.current) return
|
|
|
|
|
const term = new XTerm({
|
|
|
|
|
cursorBlink: true,
|
|
|
|
|
fontSize: 13,
|
|
|
|
|
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
|
|
|
|
|
theme: { background: '#15161A', foreground: '#E8E6E0', cursor: GOLD },
|
|
|
|
|
})
|
|
|
|
|
const fit = new FitAddon()
|
|
|
|
|
term.loadAddon(fit)
|
|
|
|
|
term.open(containerRef.current)
|
|
|
|
|
fit.fit()
|
|
|
|
|
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
const isSsh = source === 'ssh'
|
2026-06-19 12:28:30 +00:00
|
|
|
const token = getToken()
|
|
|
|
|
const proto = window.location.protocol === 'https:' ? 'wss' : 'ws'
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
const path = isSsh ? '/api/docker-ssh/exec' : '/api/docker/exec'
|
|
|
|
|
const ws = new WebSocket(`${proto}://${window.location.host}${path}?token=${encodeURIComponent(token ?? '')}`)
|
2026-06-19 12:28:30 +00:00
|
|
|
wsRef.current = ws
|
|
|
|
|
|
|
|
|
|
ws.onopen = () => {
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
ws.send(JSON.stringify({ type: 'connect', integrationId, containerId: row.id, cols: term.cols, rows: term.rows }))
|
2026-06-19 12:28:30 +00:00
|
|
|
}
|
|
|
|
|
ws.onmessage = (event) => {
|
|
|
|
|
const msg = JSON.parse(event.data)
|
|
|
|
|
if (msg.type === 'ready') {
|
|
|
|
|
setConnected(true)
|
|
|
|
|
} else if (msg.type === 'data') {
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
if (isSsh) term.write(msg.data as string)
|
|
|
|
|
else term.write(Uint8Array.from(atob(msg.data), (c) => c.charCodeAt(0)))
|
2026-06-19 12:28:30 +00:00
|
|
|
} else if (msg.type === 'error') {
|
|
|
|
|
term.writeln(`\r\n\x1b[31mError: ${msg.message}\x1b[0m`)
|
|
|
|
|
setConnected(false)
|
|
|
|
|
} else if (msg.type === 'exit') {
|
|
|
|
|
term.writeln('\r\n\x1b[33mSession ended.\x1b[0m')
|
|
|
|
|
setConnected(false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ws.onclose = () => setConnected(false)
|
|
|
|
|
|
|
|
|
|
term.onData((data) => {
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
if (ws.readyState !== WebSocket.OPEN) return
|
|
|
|
|
ws.send(JSON.stringify({ type: 'input', data: isSsh ? data : btoa(data) }))
|
2026-06-19 12:28:30 +00:00
|
|
|
})
|
|
|
|
|
term.onResize(({ cols, rows }) => {
|
|
|
|
|
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'resize', cols, rows }))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const onResize = () => fit.fit()
|
|
|
|
|
window.addEventListener('resize', onResize)
|
|
|
|
|
return () => {
|
|
|
|
|
window.removeEventListener('resize', onResize)
|
|
|
|
|
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'disconnect' }))
|
|
|
|
|
ws.close()
|
|
|
|
|
term.dispose()
|
|
|
|
|
}
|
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-6">
|
|
|
|
|
<div style={cardBase} className="flex h-[70vh] w-full max-w-3xl flex-col p-4">
|
|
|
|
|
<div className="mb-2 flex items-center justify-between">
|
|
|
|
|
<h2 className="flex items-center gap-2 text-sm font-medium" style={{ color: TEXT_PRIMARY }}>
|
|
|
|
|
<span className="inline-block h-2 w-2 rounded-full" style={{ background: connected ? '#2ECC71' : '#7A7D85' }} />
|
Add Docker-over-SSH management and push-agent monitoring (#31)
Expands the Containers feature with two new ways to see and manage Docker
containers without exposing the Docker Engine TCP socket, plus the docs and
roadmap entries that frame them.
Docker over SSH (management):
- Runs the `docker` CLI on a remote SSH host instead of talking to the Engine
TCP API, reusing the existing SSH transport (jump-host chaining, host-key
verification, key/password auth) via connectTarget + execCommand. No dockerd
socket has to be exposed — the mesh + SSH auth are the gate.
- backend/src/ssh/docker.ts: list/logs/start/stop/restart/pause/unpause/remove
and an interactive `docker exec` shell builder. Container refs are validated
against a strict allowlist and single-quoted to prevent command injection;
action verbs are whitelisted.
- backend/src/routes/dockerSsh.ts: REST routes mirroring the TCP Docker API
shape (mutating actions gated by adminOnly) + a /api/docker-ssh/exec
WebSocket modeled on the terminal PTY plumbing.
- Note: the SSH path uses the ssh2 key/password auth; it does not implement the
OpenSSH-certificate (OPKSSH) fallback that the terminal route has.
Docker push-agent monitoring (self-hosted, read-only):
- A small bash agent (agent/archnest-docker-agent.sh) runs on each Docker VM,
collects a rich snapshot (docker ps + inspect + a stats snapshot), masks
secret-looking env values locally, and POSTs it to ArchNest. VMs need
outbound-only mesh access — no exposed port, no SSH for monitoring.
- backend/src/routes/agents.ts: token-gated ingest
(POST /api/agents/docker/report, ARCHNEST_AGENT_TOKEN, constant-time compare;
503 when unset, so it is disabled by default) plus user-auth read endpoints
(hosts list with staleness flag, per-host containers, single-container
detail). New docker_agent_reports table (latest report per host).
- Ingest stores data only; it never executes anything from the agent.
Containers page:
- Host selector now spans Docker API, SSH, and Agent sources.
- Intra-page tabs: a Containers list plus dynamic, closeable per-container
detail tabs opened by clicking a container name. Agent detail shows
overview/state/stats/ports/networks/mounts/env(masked)/labels; docker/ssh
degrade gracefully. Agent rows are read-only; docker/ssh keep management.
Docs/roadmap:
- docs/docker-agent-monitoring.md (design doc, written before implementation).
- ROADMAP.md: LXC management (paid), Docker monitoring agent tiering
(push self-hosted now / pull-agent paid), terminal grid tiering.
Deferred (documented, not built here): the mesh-prerequisite setup gate, the
paid pull-agent (Option 2), per-host tokens, time-series metrics.
Requires ARCHNEST_AGENT_TOKEN in the backend env to enable agent ingest.
Verified: backend `tsc --noEmit` and frontend `tsc -b && vite build` both pass;
agent jq filters, byte conversion, and `bash -n` checked locally.
Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-20 16:24:57 -04:00
|
|
|
Exec — {row.name}
|
2026-06-19 12:28:30 +00:00
|
|
|
</h2>
|
|
|
|
|
<button onClick={onClose} style={{ color: TEXT_SECONDARY }}>
|
|
|
|
|
<X size={16} />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div ref={containerRef} className="min-h-0 flex-1" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|