|
1 | | -[](https://github.com/trydirect/status/actions/workflows/ci.yml) |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | -<a href="https://discord.gg/nsjje55wuu"><img alt="Discord" src="https://img.shields.io/discord/578119430391988232?label=discord"></a> |
7 | | -[](https://gitter.im/try-direct/community) |
8 | | -<br><br><br><br> |
9 | 1 | <div align="center"> |
10 | | -<img width="300" src="https://raw.githubusercontent.com/trydirect/status/testing/assets/logo/status.png"> |
11 | | - </div> |
12 | | - <div align="center"> |
13 | | -Server stack health application with UI.</div> |
14 | | -<br><br><br><br> |
15 | 2 |
|
16 | | -<center><img width="1063" alt="Screen Shot 2019-05-21 at 12 45 11 PM" src="https://raw.githubusercontent.com/trydirect/status/testing/assets/screenshot.png"></center> |
| 3 | +<img width="200" src="https://raw.githubusercontent.com/trydirect/status/testing/assets/logo/status.png"> |
17 | 4 |
|
| 5 | +# Status Panel |
18 | 6 |
|
19 | | -## Quick Install |
| 7 | +**A lightweight infrastructure agent for server and container management.** |
20 | 8 |
|
21 | | -Install the latest release (Linux x86_64): |
| 9 | +Monitors health, collects metrics, manages Docker containers, and executes commands — all from a single statically-linked binary. |
22 | 10 |
|
23 | | -```bash |
24 | | -curl -sSfL https://raw.githubusercontent.com/trydirect/status/master/install.sh | sh |
25 | | -``` |
| 11 | +[](https://github.com/trydirect/status/actions/workflows/ci.yml) |
| 12 | +[](https://hub.docker.com/r/trydirect/status) |
| 13 | +[](https://github.com/trydirect/status/releases/latest) |
| 14 | +[](https://discord.gg/nsjje55wuu) |
26 | 15 |
|
27 | | -Pin a specific version: |
| 16 | +</div> |
28 | 17 |
|
29 | | -```bash |
30 | | -VERSION=v0.1.4 curl -sSfL https://raw.githubusercontent.com/trydirect/status/master/install.sh | sh |
31 | | -``` |
| 18 | +--- |
32 | 19 |
|
33 | | -Custom install directory: |
| 20 | +## Highlights |
34 | 21 |
|
35 | | -```bash |
36 | | -INSTALL_DIR=~/.local/bin curl -sSfL https://raw.githubusercontent.com/trydirect/status/master/install.sh | sh |
37 | | -``` |
| 22 | +- **Single binary** — statically linked (musl), zero runtime dependencies |
| 23 | +- **Docker management** — list, start, stop, restart, pause containers; health checks and log retrieval |
| 24 | +- **System metrics** — CPU, memory, disk usage via CLI or JSON API |
| 25 | +- **18+ remote commands** — health, logs, exec, deploy, config management, firewall, proxy, and more via Stacker integration |
| 26 | +- **Self-update** — download, verify (SHA256), deploy, and rollback — all built in |
| 27 | +- **Secure by default** — HMAC-SHA256 signed requests, replay protection, rate limiting, audit logging |
| 28 | +- **Vault integration** — fetch, apply, and diff app configs from HashiCorp Vault |
| 29 | +- **Flexible modes** — run as a CLI tool, background daemon, API server, or API+UI server |
38 | 30 |
|
39 | | -Verify installation: |
| 31 | +## Quick Install |
40 | 32 |
|
41 | 33 | ```bash |
42 | | -status --version |
| 34 | +curl -sSfL https://raw.githubusercontent.com/trydirect/status/master/install.sh | sh |
43 | 35 | ``` |
44 | 36 |
|
45 | | -## Build |
| 37 | +Pin a specific version or choose a custom directory: |
46 | 38 |
|
47 | 39 | ```bash |
48 | | -cargo build --release |
| 40 | +VERSION=v0.1.4 curl -sSfL https://raw.githubusercontent.com/trydirect/status/master/install.sh | sh |
| 41 | +INSTALL_DIR=~/.local/bin curl -sSfL https://raw.githubusercontent.com/trydirect/status/master/install.sh | sh |
49 | 42 | ``` |
50 | 43 |
|
51 | | -## Run |
52 | | - |
53 | | -Foreground daemon (default without subcommands): |
| 44 | +Verify: |
54 | 45 |
|
55 | 46 | ```bash |
56 | | -./target/release/status --config config.json |
| 47 | +status --version |
57 | 48 | ``` |
58 | 49 |
|
59 | | -Daemon mode (background): |
| 50 | +## CLI Commands |
60 | 51 |
|
61 | | -```bash |
62 | | -./target/release/status --daemon --config config.json |
63 | 52 | ``` |
| 53 | +status serve [--port 5000] [--with-ui] Start the HTTP API server |
| 54 | +status containers List all Docker containers |
| 55 | +status health [name] Check container or stack health |
| 56 | +status logs <name> [-n 100] Fetch container logs |
| 57 | +status start <name> Start a stopped container |
| 58 | +status stop <name> Stop a running container |
| 59 | +status restart <name> Restart a container |
| 60 | +status pause <name> Pause a container |
| 61 | +status metrics [--json] Show CPU, memory, disk usage |
| 62 | +status update check Check for new versions |
| 63 | +status update apply [--version V] Download and verify an update |
| 64 | +status update rollback Roll back to previous version |
| 65 | +``` |
| 66 | + |
| 67 | +## Running Modes |
64 | 68 |
|
65 | | -Local API server (API-only mode): |
| 69 | +**CLI** — run a single command and exit: |
66 | 70 |
|
67 | 71 | ```bash |
68 | | -./target/release/status serve --port 5000 |
| 72 | +status health |
| 73 | +status metrics --json |
| 74 | +status logs my-app -n 50 |
69 | 75 | ``` |
70 | 76 |
|
71 | | -Local API server with UI (serves HTML templates): |
| 77 | +**Daemon** — background polling agent: |
72 | 78 |
|
73 | 79 | ```bash |
74 | | -./target/release/status serve --port 5000 --with-ui |
| 80 | +status --daemon --config config.json |
75 | 81 | ``` |
76 | 82 |
|
77 | | -Then open your browser to `http://localhost:5000/login` to access the web interface. |
78 | | - |
79 | | -Docker operations (requires `--features docker`): |
| 83 | +**API server** — local HTTP interface: |
80 | 84 |
|
81 | 85 | ```bash |
82 | | -cargo run --features docker --bin status -- containers |
83 | | -cargo run --features docker --bin status -- restart status |
| 86 | +status serve --port 5000 # JSON API only |
| 87 | +status serve --port 5000 --with-ui # API + web dashboard |
84 | 88 | ``` |
85 | 89 |
|
86 | | -## Features |
87 | | - |
88 | | -- **API-only mode**: Returns JSON responses for programmatic access |
89 | | -- **UI mode** (`--with-ui`): Serves HTML templates from `templates/` directory with static files from `static/` |
90 | | -- Docker container management (list, restart, stop, pause) |
91 | | -- Session-based authentication |
92 | | -- Health check endpoint |
93 | | -- Self-update (beta): remote version check, binary download + SHA256 verify, deploy with backup/rollback |
94 | | - |
95 | | -## Command Execution (API) |
96 | | - |
97 | | -Execute validated shell commands via the local API. The endpoint accepts a `transport::Command` payload and returns a `transport::CommandResult`. |
98 | | - |
99 | | -- Endpoint: `POST /api/v1/commands/execute` |
100 | | -- Required fields: `id` (string), `name` (full command line) |
101 | | -- Optional: `params.timeout_secs` (number) to override the default 60s timeout |
102 | | - |
103 | | -Example: run a simple echo |
| 90 | +## Build from Source |
104 | 91 |
|
105 | 92 | ```bash |
106 | | -curl -s \ |
107 | | - -H 'Content-Type: application/json' \ |
108 | | - -X POST http://localhost:5000/api/v1/commands/execute \ |
109 | | - -d '{ |
110 | | - "id": "cmd-001", |
111 | | - "name": "echo hello from agent", |
112 | | - "params": { "timeout_secs": 10 } |
113 | | - }' | jq . |
| 93 | +cargo build --release |
114 | 94 | ``` |
115 | 95 |
|
116 | | -Example: run a short sleep |
| 96 | +Minimal build (no Docker support): |
117 | 97 |
|
118 | 98 | ```bash |
119 | | -curl -s \ |
120 | | - -H 'Content-Type: application/json' \ |
121 | | - -X POST http://localhost:5000/api/v1/commands/execute \ |
122 | | - -d '{ |
123 | | - "id": "cmd-002", |
124 | | - "name": "sleep 2", |
125 | | - "params": { "timeout_secs": 5 } |
126 | | - }' | jq . |
| 99 | +cargo build --release --no-default-features --features minimal |
127 | 100 | ``` |
128 | 101 |
|
129 | | -Notes: |
130 | | -- Commands are validated by a conservative allowlist and safety checks; see `src/commands/validator.rs`. |
131 | | -- Disallowed by default: shells (`sh`, `bash`, `zsh`) and metacharacters like `; | & > <`. |
132 | | -- Absolute paths must match allowed prefixes (defaults: `/tmp`, `/var/tmp`). |
133 | | -- Output (`stdout`/`stderr`) and `exit_code` are included when available, along with a `status` of `success`, `failed`, `timeout`, or `killed`. |
134 | | - |
135 | | -## Long-Poll Command Queue |
136 | | - |
137 | | -The agent supports an in-memory command queue for dashboard-driven execution via long-polling. Commands are queued and agents poll for them with configurable timeouts. |
138 | | - |
139 | | -> **Note:** The built-in Axum server (for local development) exposes `/api/v1/commands/*` routes. When the agent talks to the remote Stacker dashboard it uses the dedicated `/api/v1/agent/commands/*` namespace (for example `/api/v1/agent/commands/wait/{deployment_hash}`) **and** includes `Authorization: Bearer <AGENT_TOKEN>` in every request. |
140 | | -
|
141 | | -### Endpoints |
142 | | - |
143 | | -- `GET /api/v1/commands/wait/{hash}?timeout=N` (local) / `GET /api/v1/agent/commands/wait/{deployment_hash}?timeout=N` (Stacker) - Long-poll for next queued command (default 30s timeout) |
144 | | -- `POST /api/v1/commands/report` (local) / `POST /api/v1/agent/commands/report` (Stacker) - Report command execution result |
145 | | -- `POST /api/v1/commands/enqueue` (local) / `POST /api/v1/agent/commands/enqueue` (Stacker) - Enqueue a command (for testing/local use) |
146 | | - |
147 | | -All endpoints require `X-Agent-Id` header matching the `AGENT_ID` environment variable. |
148 | | - |
149 | | -### Manual Testing |
150 | | - |
151 | | -Start the server with agent ID: |
| 102 | +## Docker |
152 | 103 |
|
153 | 104 | ```bash |
154 | | -export AGENT_ID=test-agent |
155 | | -cargo r -- serve --port 5000 |
| 105 | +docker pull trydirect/status:latest |
156 | 106 | ``` |
157 | 107 |
|
158 | | -**Terminal 1: Long-poll for commands** |
| 108 | +Or use Docker Compose with the included `docker-compose.yml` for a full setup with API server and background agent. |
159 | 109 |
|
160 | | -```bash |
161 | | -curl -H 'X-Agent-Id: test-agent' \ |
162 | | - 'http://localhost:5000/api/v1/commands/wait/demo?timeout=10' |
163 | | -``` |
| 110 | +## API Reference |
164 | 111 |
|
165 | | -**Terminal 2: Enqueue a command** |
| 112 | +### Core Endpoints |
166 | 113 |
|
167 | | -```bash |
168 | | -curl -s \ |
169 | | - -H 'Content-Type: application/json' \ |
170 | | - -X POST http://localhost:5000/api/v1/commands/enqueue \ |
171 | | - -d '{ |
172 | | - "id": "cmd-001", |
173 | | - "name": "echo hello from queue", |
174 | | - "params": {} |
175 | | - }' | jq . |
176 | | -``` |
| 114 | +| Method | Path | Description | |
| 115 | +|--------|------|-------------| |
| 116 | +| `GET` | `/health` | Health check | |
| 117 | +| `GET` | `/capabilities` | System capabilities | |
| 118 | +| `GET` | `/metrics` | Current system metrics | |
| 119 | +| `GET` | `/metrics/stream` | WebSocket metrics stream | |
177 | 120 |
|
178 | | -The long-poll in Terminal 1 will immediately return the queued command. |
| 121 | +### Command Execution |
179 | 122 |
|
180 | | -**Report command result** |
| 123 | +| Method | Path | Description | |
| 124 | +|--------|------|-------------| |
| 125 | +| `POST` | `/api/v1/commands/execute` | Execute a validated command | |
| 126 | +| `GET` | `/api/v1/commands/wait/{hash}` | Long-poll for queued commands | |
| 127 | +| `POST` | `/api/v1/commands/enqueue` | Enqueue a command | |
| 128 | +| `POST` | `/api/v1/commands/report` | Report execution result | |
181 | 129 |
|
182 | | -```bash |
183 | | -curl -s \ |
184 | | - -H 'Content-Type: application/json' \ |
185 | | - -H 'X-Agent-Id: test-agent' \ |
186 | | - -X POST http://localhost:5000/api/v1/commands/report \ |
187 | | - -d '{ |
188 | | - "command_id": "cmd-001", |
189 | | - "status": "success", |
190 | | - "result": {"exit_code": 0, "stdout": "hello from queue\n"}, |
191 | | - "error": null |
192 | | - }' | jq . |
193 | | -``` |
| 130 | +### Self-Update |
194 | 131 |
|
195 | | -### Demo Script |
| 132 | +| Method | Path | Description | |
| 133 | +|--------|------|-------------| |
| 134 | +| `GET` | `/api/self/version` | Current and available versions | |
| 135 | +| `POST` | `/api/self/update/start` | Start update job | |
| 136 | +| `GET` | `/api/self/update/status/{id}` | Check update progress | |
| 137 | +| `POST` | `/api/self/update/deploy` | Deploy prepared binary | |
| 138 | +| `POST` | `/api/self/update/rollback` | Restore previous version | |
196 | 139 |
|
197 | | -Run the automated demo: |
| 140 | +### Stacker Commands (Remote) |
198 | 141 |
|
199 | | -```bash |
200 | | -export AGENT_ID=test-agent |
201 | | -./examples/long_poll_demo.sh |
202 | | -``` |
| 142 | +The agent accepts signed commands from the Stacker dashboard covering the full lifecycle: |
203 | 143 |
|
204 | | -This script starts a background poller, enqueues a command, and demonstrates the long-poll notification mechanism. |
| 144 | +| Command | Description | |
| 145 | +|---------|-------------| |
| 146 | +| `health` | Container health with optional metrics | |
| 147 | +| `logs` | Container logs with cursor pagination | |
| 148 | +| `start` / `stop` / `restart` | Container lifecycle | |
| 149 | +| `exec` | Run command inside a container (sandboxed) | |
| 150 | +| `server_resources` | CPU, memory, disk, network metrics | |
| 151 | +| `list_containers` | All containers with health and logs | |
| 152 | +| `error_summary` | Categorized error analysis | |
| 153 | +| `deploy_app` / `remove_app` | App deployment via docker-compose | |
| 154 | +| `fetch_config` / `apply_config` | Vault config management | |
| 155 | +| `config_diff` | Detect configuration drift | |
| 156 | +| `configure_proxy` | Nginx proxy management | |
| 157 | +| `configure_firewall` | iptables policy management | |
205 | 158 |
|
206 | | -## Templates |
| 159 | +## Security |
207 | 160 |
|
208 | | -The UI uses Tera templating engine (similar to Jinja2). Templates are located in: |
209 | | -- `templates/` - HTML templates (login.html, index.html, error.html) |
210 | | -- `static/` - CSS, JavaScript, and other static assets |
| 161 | +- **HMAC-SHA256** request signing with `AGENT_TOKEN` |
| 162 | +- **Replay protection** via `X-Request-Id` tracking |
| 163 | +- **Rate limiting** per agent |
| 164 | +- **Command validation** — conservative allowlist, blocked shells and metacharacters |
| 165 | +- **Exec sandboxing** — dangerous commands (`rm -rf /`, `mkfs`, `shutdown`, etc.) are blocked |
| 166 | +- **Audit logging** — all auth attempts and scope denials recorded |
| 167 | +- **Vault integration** — secrets and configs stored securely, never in plaintext |
211 | 168 |
|
212 | | -## Notes |
| 169 | +## Configuration |
213 | 170 |
|
214 | | -- Reads `config.json` and normalizes `apps_info` to structured items. |
215 | | -- Subsystems marked with `@todo` will be implemented per `.ai/GOAL.md`. |
| 171 | +| Environment Variable | Description | |
| 172 | +|---------------------|-------------| |
| 173 | +| `AGENT_ID` | Unique agent identifier | |
| 174 | +| `AGENT_TOKEN` | Authentication token for signed requests | |
| 175 | +| `DASHBOARD_URL` | Remote dashboard URL | |
| 176 | +| `VAULT_ADDRESS` | HashiCorp Vault server URL | |
| 177 | +| `UPDATE_SERVER_URL` | Remote update server for version checks | |
| 178 | +| `COMPOSE_AGENT_ENABLED` | Enable compose-agent mode | |
| 179 | +| `METRICS_INTERVAL_SECS` | Metrics collection interval | |
216 | 180 |
|
217 | | -## Self-update (beta) |
| 181 | +## Contributing |
218 | 182 |
|
219 | | -- Env vars: `UPDATE_SERVER_URL` or `UPDATE_BINARY_URL`, optional `UPDATE_EXPECTED_SHA256`, `AGENT_ID`, `UPDATE_STORAGE_PATH` |
220 | | -- Endpoints: |
221 | | - - `GET /api/self/version` → current + available (when `UPDATE_SERVER_URL` is set) |
222 | | - - `POST /api/self/update/start` → returns `job_id` (requires `X-Agent-Id`) |
223 | | - - `GET /api/self/update/status/{id}` → phase: pending|downloading|verifying|completed|failed |
224 | | - - `POST /api/self/update/deploy` → body: `{ "job_id", "install_path?", "service_name?" }`; backs up current binary, deploys prepared one |
225 | | - - `POST /api/self/update/rollback` → restore latest backup |
| 183 | +1. Fork the repo |
| 184 | +2. Create a feature branch from `testing` |
| 185 | +3. Run `cargo fmt --all && cargo clippy -- -D warnings` |
| 186 | +4. Open a PR against `testing` |
226 | 187 |
|
227 | | -Example (start + deploy): |
| 188 | +## License |
228 | 189 |
|
229 | | -```bash |
230 | | -curl -X POST http://localhost:5000/api/self/update/start \ |
231 | | - -H "X-Agent-Id: $AGENT_ID" \ |
232 | | - -d '{"version":"1.2.3"}' |
| 190 | +See [LICENSE](LICENSE) for details. |
233 | 191 |
|
234 | | -curl -X POST http://localhost:5000/api/self/update/deploy \ |
235 | | - -H "X-Agent-Id: $AGENT_ID" \ |
236 | | - -d '{"job_id":"<returned-id>","service_name":"status-panel"}' |
237 | | -``` |
| 192 | +--- |
| 193 | + |
| 194 | +<div align="center"> |
| 195 | +Built with Rust. Maintained by <a href="https://github.com/trydirect">TryDirect</a>. |
| 196 | +</div> |
0 commit comments