* Add editable display-name field to generic integrations Lets users set a custom name for Proxmox, Docker, AWS, Remote Desktop, Netbird, Cloudflare, Uptime Kuma, and Weather integrations, separate from the host/IP field, mirroring the SSH host rename pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016kF4hZWEkRCPPvCZTeXxn4 * Surface the new-integration name field as a labeled input The name field for new generic integrations was a faint header input with only placeholder text, easy to miss. Move it into the form grid as a proper labeled "Name" field next to the other connection fields. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016kF4hZWEkRCPPvCZTeXxn4 * Add file upload for SSH private key and certificate fields Lets users pick a key file from disk (e.g. ~/.ssh) instead of pasting its contents into the Private Key / OPKSSH Certificate fields. * Fix SSH private key paste corrupting multi-line PEM format Private Key and Certificate fields were single-line <input> elements, which strip newlines on paste and corrupt PEM-formatted keys (causing 'Unsupported key format' errors). Render them as multi-line textareas instead so pasted keys keep their line breaks. * Show saved indicator for secret fields instead of appearing blank/deleted GET /api/integrations never returns decrypted secret values (by design), so after navigating away and back, secret/key fields rendered empty - looking exactly like the saved key had been deleted, even though it was still intact and encrypted in the database. Expose which secret keys exist (names only, never values) via secretKeys, and use it to label fields as "saved" with an appropriate placeholder instead of blank. --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|---|---|---|
| .github/workflows | ||
| .kiro | ||
| assets | ||
| backend | ||
| pics | ||
| public | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| archnest-blueprint.md | ||
| design-decisions.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| eslint.config.js | ||
| glance.md | ||
| HANDOFF.md | ||
| index.html | ||
| nginx.conf | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| TERMIX_MIGRATION.md | ||
| tsconfig.app.json | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| vite.config.ts | ||
ArchNest
A self-hosted ops dashboard — infrastructure monitoring, a bookmark hub for your homelab/cloud links, an embedded terminal, and system settings, all in one place. Real backend, real integrations, no mock data.
Frontend: React 19 + TypeScript + Vite, styled with Tailwind CSS v4, charts via Recharts, icons via Lucide React.
Backend: Fastify + TypeScript + SQLite (better-sqlite3), JWT auth, AES-256-GCM encrypted integration secrets.
For a full handoff/status writeup (what's done, what's not, how to resume), see HANDOFF.md.
Pages
| Page | Route | Status |
|---|---|---|
| Glance | / |
Done — real backend data (system status, resource overview, alerts, network traffic) |
| Infrastructure | /infrastructure |
Done — resource distribution, node status grid, cost/trend breakdown, all from real integration data. "Network" sub-tab planned as a future addition. |
| BookNest | /booknest |
Done — categorized bookmark hub wired to the real bookmarks API |
| Terminal | /terminal |
Pending / on hold — will be based on a fork of the (archived) Termix project; user has the fork and intends to hand this off to another AI session to integrate. Do not start this without explicit instruction. |
| Settings | /settings |
Done — Profile (real user identity + avatar, editable via API), Appearance, Integrations (8 real adapters), Notifications, Data & Backup, About |
See archnest-blueprint.md for the original per-page design spec and design-decisions.md for the visual/UX conventions and lessons learned while building each page — read that file before making layout changes, it documents why things are built the way they are (hero banner layering, card blend techniques, icon library gotchas, etc.).
Development
Frontend:
npm install
npm run dev
Backend:
cd backend
npm install
ARCHNEST_SECRET_KEY=$(openssl rand -hex 32) ARCHNEST_JWT_SECRET=$(openssl rand -hex 32) npm run dev
Both ARCHNEST_SECRET_KEY (encrypts integration secrets at rest) and ARCHNEST_JWT_SECRET (signs auth tokens) are required env vars with no defaults — the server will refuse to start without them. ARCHNEST_DB_PATH optionally overrides the SQLite file location (defaults to a local path under backend/). PORT overrides the listen port (default 4000-range, check server.ts).
Type-check both before committing:
npx tsc --noEmit # from repo root, frontend
cd backend && npx tsc --noEmit # backend
Vite/the browser surface some runtime errors (e.g. missing icon exports) that the type-checker won't catch, so also smoke-test pages in a browser.
Tech Stack
Frontend
- React 19 + Vite + TypeScript
- React Router for routing
- Tailwind CSS v4
- Recharts (donuts, line/area charts)
- Lucide React (icons)
Backend
- Fastify 5 + TypeScript,
tsxfor dev,tsc -bfor build better-sqlite3for storage@fastify/jwtfor auth tokens,bcryptjsfor password hashingzodfor request validation- AES-256-GCM (Node
crypto) for encrypting integration secrets at rest - Integration adapters: Proxmox, Docker, NetBird, Cloudflare, AWS, Uptime Kuma, Weather, SSH (see
backend/src/integrations/)
Deploy target: Docker on racknerd1 → NPM (Nginx Proxy Manager) proxy at archnest.snsnetlabs.com.
Deployment
All features are built and verified. The only remaining work to go live is wiring up the GitHub Actions deploy pipeline — the app itself does not need further development before deployment.
The workflow already exists at .github/workflows/deploy.yml and triggers on every push to main: it copies the repo to racknerd1 over SCP and runs docker compose up -d --build there. Nothing in that file needs to change. To activate it:
- Provision the host (
racknerd1): Docker + Docker Compose installed, an SSH user the Action can authenticate as, and/opt/archnestcreated and owned by that user (matchesDEPLOY_PATHin the workflow — change both together if a different path is wanted). - Create
/opt/archnest/.envon the host (Compose reads it automatically) using the repo's top-level.env.exampleas the template — generate real values forARCHNEST_JWT_SECRET,ARCHNEST_SECRET_KEY, andARCHNEST_GUAC_CRYPT_KEY(commands included inline in the example file), and setARCHNEST_CORS_ORIGINto the real public origin if different from the default. This file is server-side only and must never be committed. - Add the deploy secrets in the GitHub repo settings (Settings → Secrets and variables → Actions):
RACKNERD_HOST,RACKNERD_USER,RACKNERD_SSH_KEY(private key for that user, PEM format), and optionallyRACKNERD_PORTif SSH isn't on port 22. - Point DNS / Nginx Proxy Manager at the host: a proxy host for
archnest.snsnetlabs.comforwarding to the container's published port (8080for the frontend, seedocker-compose.yml), with SSL handled by NPM as usual. - Trigger the first deploy — either push to
main, or run the workflow manually via the Actions tab (workflow_dispatchis enabled).
After that, every push to main redeploys automatically. No code changes are expected to be part of standing up this pipeline — it's configuration only (host setup, secrets, DNS/proxy).