infra: rename truenas-burnin → nas-burnin (1.0.0-41)
Matches the 1.0.0-38 product display rename. Touches every
infrastructure identifier:
- container_name: truenas-burnin → nas-burnin
- forge URL in /api/v1/updates/check
- security-scan: REPO_URL, REPO, DEPLOY_DIR, systemd unit description
- run-tests.sh default container name
- doc paths in README/SPEC/CLAUDE
- in-app instruction strings (login.html, settings.html, auth_cli.py)
Maple migration done in lockstep:
docker compose down (truenas-burnin)
mv ~/docker/stacks/{truenas-burnin,nas-burnin}
systemd unit ExecStart updated + daemon-reload
docker compose up -d --build → container nas-burnin
Old image truenas-burnin-app removed (~12 GB reclaimed)
Stale top-level orphans cleaned (config.py, poller.py, routes.py,
truenas.py, tests/) — all dead since pre-split refactors
Forge repo rename (git.hellocomputer.xyz/brandon/truenas-burnin →
nas-burnin) is a separate UI-only step. Forgejo redirects the old
URL after rename, so this commit can be pushed to the existing
remote first; remote URL gets updated locally once you rename.
This commit is contained in:
parent
d38807f957
commit
944e4c1541
13 changed files with 37 additions and 37 deletions
22
CLAUDE.md
22
CLAUDE.md
|
|
@ -11,8 +11,8 @@ A self-hosted web dashboard for running and tracking hard-drive burn-in tests
|
|||
against a TrueNAS SCALE 25.10 instance. Deployed on **maple.local** (10.0.0.138).
|
||||
|
||||
- **App URL**: http://10.0.0.138:8084 (or http://burnin.hellocomputer.xyz)
|
||||
- **Stack path on maple.local**: `~/docker/stacks/truenas-burnin/`
|
||||
- **Source (local mac)**: `~/Desktop/claudesandbox/truenas-burnin/`
|
||||
- **Stack path on maple.local**: `~/docker/stacks/nas-burnin/`
|
||||
- **Source (local mac)**: `~/Desktop/claudesandbox/nas-burnin/`
|
||||
- **Compose synced to maple.local** via `scp` or manual copy
|
||||
|
||||
### Stages completed
|
||||
|
|
@ -36,7 +36,7 @@ against a TrueNAS SCALE 25.10 instance. Deployed on **maple.local** (10.0.0.138)
|
|||
## File Map
|
||||
|
||||
```
|
||||
truenas-burnin/
|
||||
nas-burnin/
|
||||
├── docker-compose.yml # two services: mock-truenas + app
|
||||
├── Dockerfile # app container
|
||||
├── requirements.txt
|
||||
|
|
@ -222,18 +222,18 @@ All read from `.env` via `pydantic-settings`. See `.env.example` for full list.
|
|||
### First deploy (already done)
|
||||
```bash
|
||||
# On maple.local
|
||||
cd ~/docker/stacks/truenas-burnin
|
||||
cd ~/docker/stacks/nas-burnin
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### Redeploy after code changes
|
||||
```bash
|
||||
# Copy changed files from mac to maple.local first, e.g.:
|
||||
scp -P 2225 -r app/ brandon@10.0.0.138:~/docker/stacks/truenas-burnin/
|
||||
scp -P 2225 -r app/ brandon@10.0.0.138:~/docker/stacks/nas-burnin/
|
||||
|
||||
# Then on maple.local:
|
||||
ssh brandon@10.0.0.138 -p 2225
|
||||
cd ~/docker/stacks/truenas-burnin
|
||||
cd ~/docker/stacks/nas-burnin
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
|
|
@ -242,7 +242,7 @@ docker compose up -d --build
|
|||
# On maple.local — stop containers first
|
||||
docker compose stop app
|
||||
# Delete DB using alpine (container owns the file, sudo not available)
|
||||
docker run --rm -v ~/docker/stacks/truenas-burnin/data:/data alpine rm -f /data/app.db
|
||||
docker run --rm -v ~/docker/stacks/nas-burnin/data:/data alpine rm -f /data/app.db
|
||||
docker compose start app
|
||||
```
|
||||
|
||||
|
|
@ -350,7 +350,7 @@ async def burnin_get(job_id: int, ...): ...
|
|||
### `requirements.txt` is unpinned
|
||||
Every `docker compose up -d --build` pulls latest of fastapi, starlette, jinja2, asyncssh, etc. The Starlette 1.0 regression on 2026-04-27 is a direct consequence. **Either pin to known-good versions, or audit installed versions immediately after each rebuild** with:
|
||||
```bash
|
||||
docker exec truenas-burnin python3 -c "import fastapi, starlette, jinja2; print(fastapi.__version__, starlette.__version__, jinja2.__version__)"
|
||||
docker exec nas-burnin python3 -c "import fastapi, starlette, jinja2; print(fastapi.__version__, starlette.__version__, jinja2.__version__)"
|
||||
```
|
||||
|
||||
### Local source ↔ maple host can drift
|
||||
|
|
@ -358,8 +358,8 @@ The deploy convention is `scp -r app/` from mac to maple, but if you ever edit o
|
|||
|
||||
**Always `diff -u` before bulk scp:**
|
||||
```bash
|
||||
ssh -p 2225 brandon@10.0.0.138 'cat ~/docker/stacks/truenas-burnin/app/routes.py' > /tmp/deployed_routes.py
|
||||
diff -u /tmp/deployed_routes.py ~/Desktop/claudesandbox/truenas-burnin/app/routes.py
|
||||
ssh -p 2225 brandon@10.0.0.138 'cat ~/docker/stacks/nas-burnin/app/routes.py' > /tmp/deployed_routes.py
|
||||
diff -u /tmp/deployed_routes.py ~/Desktop/claudesandbox/nas-burnin/app/routes.py
|
||||
```
|
||||
When sides have conflicting edits, prefer **patching the host file in place + rebuild** over a destructive scp.
|
||||
|
||||
|
|
@ -427,7 +427,7 @@ SMART attrs stored as JSON blob in `drives.smart_attrs`. Updated by `final_check
|
|||
|
||||
Settings page has a "Check for Updates" button that fetches:
|
||||
```
|
||||
GET https://git.hellocomputer.xyz/api/v1/repos/brandon/truenas-burnin/releases/latest
|
||||
GET https://git.hellocomputer.xyz/api/v1/repos/brandon/nas-burnin/releases/latest
|
||||
```
|
||||
Compares tag name against `settings.app_version`; shows "up to date" or "v{tag} available".
|
||||
|
||||
|
|
|
|||
12
README.md
12
README.md
|
|
@ -37,7 +37,7 @@ open http://localhost:8084 # or your host's IP
|
|||
If you set `INITIAL_ADMIN_*` env vars *and* the users table is empty, that
|
||||
account is created on startup automatically. After that the env vars are
|
||||
ignored — change passwords from the UI ("Change password" header link) or
|
||||
the CLI (`docker exec -it truenas-burnin python -m app.auth_cli reset
|
||||
the CLI (`docker exec -it nas-burnin python -m app.auth_cli reset
|
||||
<username>`).
|
||||
|
||||
---
|
||||
|
|
@ -172,17 +172,17 @@ Configure SMTP in Settings → Email. Includes a "Test SMTP" button.
|
|||
### Logs
|
||||
|
||||
```bash
|
||||
docker logs -f truenas-burnin
|
||||
docker logs -f nas-burnin
|
||||
# JSON-structured. Filter with jq:
|
||||
docker logs truenas-burnin 2>&1 | jq -rR 'fromjson? | "\(.ts) \(.level) \(.msg)"'
|
||||
docker logs nas-burnin 2>&1 | jq -rR 'fromjson? | "\(.ts) \(.level) \(.msg)"'
|
||||
```
|
||||
|
||||
### User management
|
||||
|
||||
```bash
|
||||
docker exec -it truenas-burnin python -m app.auth_cli list
|
||||
docker exec -it truenas-burnin python -m app.auth_cli add <username>
|
||||
docker exec -it truenas-burnin python -m app.auth_cli reset <username>
|
||||
docker exec -it nas-burnin python -m app.auth_cli list
|
||||
docker exec -it nas-burnin python -m app.auth_cli add <username>
|
||||
docker exec -it nas-burnin python -m app.auth_cli reset <username>
|
||||
```
|
||||
|
||||
Passwords are read from a TTY prompt; never accept them on the command
|
||||
|
|
|
|||
4
SPEC.md
4
SPEC.md
|
|
@ -251,8 +251,8 @@ The API makes this app a strong candidate for MCP server integration, allowing a
|
|||
Docker Compose. Minimum viable setup:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/yourusername/truenas-burnin
|
||||
cd truenas-burnin
|
||||
git clone https://github.com/yourusername/nas-burnin
|
||||
cd nas-burnin
|
||||
cp .env.example .env
|
||||
# Edit .env for system-level settings (TrueNAS URL, poll interval, etc.)
|
||||
docker compose up -d
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
"""Password reset / user management CLI.
|
||||
|
||||
Run inside the container:
|
||||
docker exec -it truenas-burnin python -m app.auth_cli reset <username>
|
||||
docker exec -it truenas-burnin python -m app.auth_cli list
|
||||
docker exec -it truenas-burnin python -m app.auth_cli add <username>
|
||||
docker exec -it nas-burnin python -m app.auth_cli reset <username>
|
||||
docker exec -it nas-burnin python -m app.auth_cli list
|
||||
docker exec -it nas-burnin python -m app.auth_cli add <username>
|
||||
|
||||
Reads the password from a TTY prompt — never accept it on the command
|
||||
line so it doesn't leak into shell history.
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class Settings(BaseSettings):
|
|||
ssh_key: str = "" # PEM private key content (paste full key including headers)
|
||||
|
||||
# Application version — used by the /api/v1/updates/check endpoint
|
||||
app_version: str = "1.0.0-40"
|
||||
app_version: str = "1.0.0-41"
|
||||
|
||||
# ---- Authentication (1.0.0-22) ----
|
||||
# session_secret: HMAC key for signing session cookies. Empty = generate
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ async def check_updates():
|
|||
try:
|
||||
async with httpx.AsyncClient(timeout=8.0) as client:
|
||||
r = await client.get(
|
||||
"https://git.hellocomputer.xyz/api/v1/repos/brandon/truenas-burnin/releases/latest",
|
||||
"https://git.hellocomputer.xyz/api/v1/repos/brandon/nas-burnin/releases/latest",
|
||||
headers={"Accept": "application/json"},
|
||||
)
|
||||
if r.status_code == 200:
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
<div class="login-footer">
|
||||
Authentication is local to this dashboard. Forgot your password?
|
||||
Reset it via the container DB:<br>
|
||||
<code class="login-code">docker exec truenas-burnin python -m app.auth_cli reset <user></code>
|
||||
<code class="login-code">docker exec nas-burnin python -m app.auth_cli reset <user></code>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@
|
|||
<div id="restart-banner" style="display:none;margin-top:12px;padding:12px 16px;background:rgba(255,170,0,0.12);border:1px solid var(--yellow);border-radius:8px;color:var(--text-strong)">
|
||||
<strong>⚠ Container restart required</strong> — system settings are saved but won't take effect until you restart the app container:
|
||||
<pre style="margin:8px 0 0;padding:8px 10px;background:var(--bg-card);border-radius:5px;font-size:12px;color:var(--text-strong);user-select:all">docker compose restart app</pre>
|
||||
<span style="font-size:11px;color:var(--text-muted)">Run this on <strong>maple.local</strong> from <code>~/docker/stacks/truenas-burnin/</code></span>
|
||||
<span style="font-size:11px;color:var(--text-muted)">Run this on <strong>maple.local</strong> from <code>~/docker/stacks/nas-burnin/</code></span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ services:
|
|||
|
||||
app:
|
||||
build: .
|
||||
container_name: truenas-burnin
|
||||
container_name: nas-burnin
|
||||
ports:
|
||||
- "8084:8084"
|
||||
env_file: .env
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
set -euo pipefail
|
||||
|
||||
REMOTE_HOST="${REMOTE_HOST:-maple}"
|
||||
CONTAINER="${CONTAINER:-truenas-burnin}"
|
||||
CONTAINER="${CONTAINER:-nas-burnin}"
|
||||
REMOTE_TMP="/tmp/tnb-tests-$$.tgz"
|
||||
CONTAINER_TMP="/tmp/tnb-tests.tgz"
|
||||
PATTERN="${1:-}"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[Unit]
|
||||
Description=Security scan of truenas-burnin (pip-audit + bandit + gitleaks)
|
||||
Description=Security scan of nas-burnin (pip-audit + bandit + gitleaks)
|
||||
After=network-online.target docker.service
|
||||
Wants=network-online.target
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ Wants=network-online.target
|
|||
Type=oneshot
|
||||
# Wire SECURITY_SCAN_WEBHOOK here if you want findings POSTed somewhere.
|
||||
# Environment=SECURITY_SCAN_WEBHOOK=https://chat.example/hooks/abc
|
||||
ExecStart=%h/docker/stacks/truenas-burnin/scripts/security-scan.sh
|
||||
ExecStart=%h/docker/stacks/nas-burnin/scripts/security-scan.sh
|
||||
# Tools cache + container pulls — give them headroom.
|
||||
TimeoutStartSec=600
|
||||
StandardOutput=journal
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
# Daily security scan of the deployed truenas-burnin source on maple.
|
||||
# Daily security scan of the deployed nas-burnin source on maple.
|
||||
# Mirrors the .forgejo/workflows/security-scan.yml CI pipeline so a finding
|
||||
# the runner-less forge would have flagged still surfaces here.
|
||||
#
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
set -uo pipefail
|
||||
|
||||
REPO_URL="${REPO_URL:-https://git.hellocomputer.xyz/brandon/truenas-burnin.git}"
|
||||
REPO="${REPO:-$HOME/scan-checkouts/truenas-burnin}"
|
||||
REPO_URL="${REPO_URL:-https://git.hellocomputer.xyz/brandon/nas-burnin.git}"
|
||||
REPO="${REPO:-$HOME/scan-checkouts/nas-burnin}"
|
||||
OUT_BASE="${OUT_BASE:-$HOME/security-scans}"
|
||||
DATE="$(date +%Y-%m-%d)"
|
||||
OUT_DIR="$OUT_BASE/scan-$DATE"
|
||||
|
|
@ -29,7 +29,7 @@ GITLEAKS_VERSION="${GITLEAKS_VERSION:-8.21.2}"
|
|||
mkdir -p "$OUT_DIR" "$(dirname "$REPO")"
|
||||
|
||||
# Maintain a dedicated checkout for scanning. The deploy at
|
||||
# ~/docker/stacks/truenas-burnin/ is just the bind-mounted source — no
|
||||
# ~/docker/stacks/nas-burnin/ is just the bind-mounted source — no
|
||||
# .git, no history — so gitleaks can't scan there. We keep a separate
|
||||
# clone, fast-forward it to origin/main each run.
|
||||
if [ ! -d "$REPO/.git" ]; then
|
||||
|
|
@ -58,7 +58,7 @@ date -Iseconds >> "$OUT_DIR/summary.txt"
|
|||
echo >> "$OUT_DIR/summary.txt"
|
||||
|
||||
# --- pip-audit against the lockfile in a throwaway container ------------
|
||||
# Previously we did `docker exec truenas-burnin pip install pip-audit`
|
||||
# Previously we did `docker exec nas-burnin pip install pip-audit`
|
||||
# which mutated the live production container with a transient package.
|
||||
# Now scan the lockfile in an ephemeral container — same coverage of
|
||||
# pinned versions + their transitives, no side effects on prod.
|
||||
|
|
@ -77,7 +77,7 @@ echo " exit=$PIPS ($OUT_DIR/pip-audit.txt)" | tee -a "$OUT_DIR/summary.txt"
|
|||
# forge HEAD and maple. B608 (SQL injection via dynamic strings) is
|
||||
# skipped globally: every dynamic SQL build in this codebase uses
|
||||
# bound parameters for data and structural placeholders only.
|
||||
DEPLOY_DIR="${DEPLOY_DIR:-$HOME/docker/stacks/truenas-burnin}"
|
||||
DEPLOY_DIR="${DEPLOY_DIR:-$HOME/docker/stacks/nas-burnin}"
|
||||
echo "--- bandit (deploy: $DEPLOY_DIR) ---" | tee -a "$OUT_DIR/summary.txt"
|
||||
docker run --rm \
|
||||
-v "$DEPLOY_DIR/app:/src:ro" \
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[Unit]
|
||||
Description=Daily security scan of truenas-burnin
|
||||
Description=Daily security scan of nas-burnin
|
||||
Requires=security-scan.service
|
||||
|
||||
[Timer]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue