Commit graph

16 commits

Author SHA1 Message Date
Claude
a8b22d8e2d
fix: switch to Caddy JSON config so dynamic routes work correctly
The Caddyfile created a server with an auto-generated name, not 'hiy',
so build.sh's PUT to /config/apps/http/servers/hiy/routes was creating
a parallel server that never received traffic.

- Replace Caddyfile with caddy.json that names the server 'hiy' with
  the dashboard as a catch-all fallback route
- Insert app routes at index 0 so host-matched routes are evaluated
  before the catch-all dashboard fallback
- Update docker-compose to mount caddy.json and pass --config flag
2026-03-19 11:02:57 +00:00
Claude
11db59d612
fix: guard against non-dict route entries when filtering Caddy routes
r.get() crashed when the Caddy API returned a routes array containing
string elements. Added isinstance(r, dict) check and also made the
match[0] traversal safer by using any() over the match list.
2026-03-19 10:55:40 +00:00
Claude
bddc1a8027
fix: use musl static linking to eliminate glibc version dependency
Build hiy-server targeting aarch64-unknown-linux-musl so the binary
has no glibc dependency at all, making the runtime image irrelevant
to glibc version mismatches. Uses rustls (already in Cargo.toml) so
no OpenSSL vendoring needed. SQLite is bundled by sqlx.
2026-03-19 10:48:46 +00:00
Claude
f6e6d1f8a3
fix: upgrade builder to rust:1.94-slim-bookworm 2026-03-19 10:46:37 +00:00
Claude
4e8aa1614e
fix: pin builder to rust:1.77-slim-bookworm to match runtime glibc
rust:1.77-slim has drifted to a newer Debian base with glibc 2.39,
but debian:bookworm-slim only has glibc 2.36, causing a GLIBC_2.39
not found error at runtime. Pinning to the explicit bookworm variant
keeps both stages on the same glibc version.
2026-03-19 10:45:51 +00:00
Claude
3d35e220e4
build.sh: give actionable instructions when Caddy is unreachable
The old message just said 'expose manually if needed' with no guidance.
Now it prints the exact docker commands to publish the port directly
and how to find the container IP for a custom reverse proxy.

https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 10:27:17 +00:00
Claude
54ddc0d856
build.sh: fix empty array expansion under set -u
${arr[@]} with set -u throws 'unbound variable' when the array is empty.
Use ${arr[@]+"${arr[@]}"} which only expands if the array is set.

https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 09:58:20 +00:00
Claude
efca2b5941
build.sh: skip --env-file when env file does not exist
docker run fails hard if the path passed to --env-file is missing.
Make the flag conditional so apps without an env file (or where the
file hasn't been created yet) still start successfully.

https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 09:47:21 +00:00
Shautvast
98385ea743 proper var use 2026-03-19 10:45:52 +01:00
Claude
1dc70ff046
Add .gitattributes: force LF line endings for shell scripts
Without this, git on macOS with core.autocrlf=true checks out .sh
files with CRLF. Bash then reads 'CONTAINER_NAME\r' as the variable
name (never set), causing 'unbound variable' with set -u.

https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 09:40:26 +00:00
Claude
e1a01173ed
Fix: capture all script output + always log exit code
Two silent failure modes:

1. lines() drops any output chunk not terminated with \n — a script
   that crashes mid-line (or any final output without a newline) was
   silently swallowed. Switched to raw 4KB chunk reads which stream
   incrementally and capture everything.

2. A non-zero exit with no output (e.g. bash exit 127 'command not
   found') left the log completely empty. Now always appends
   '[hiy] exit code: N' after the process finishes so there is always
   at least one diagnostic line regardless of script output.

Exit code lookup:
  exit code: 0   -> success
  exit code: 1   -> script hit 'set -e' on a failing command
  exit code: 127 -> bash could not find the script or a command in it
  exit code: 126 -> script found but not executable (chmod +x missing)
  exit code: signal -> process killed by OS signal

https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 09:37:21 +00:00
Claude
c3f300e8ad
Fix: surface build errors in deploy log instead of swallowing them
When run_build() returned an Err (e.g. spawn failure because the
build script path doesn't resolve) the error was only written to
tracing, leaving the deploy log empty and the user with no clue.

- build_worker now appends the Rust error message to the deploy log
  before setting status=failed, so it appears in the UI.
- run_build logs CWD, resolved script path, exists=true/false, build
  dir, and env file path before attempting spawn, so there is always
  at least one diagnostic line in the log even if spawn itself fails.
- spawn() error is wrapped with the attempted path for clarity.

https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 09:06:37 +00:00
Claude
d322cc3ce1
Fix: log viewer wipes itself due to auto-reload on deploy done
Two bugs causing 'can't see why deploy failed':
- showLog() called window.location.reload() on the SSE 'done' event,
  wiping the log panel before the user could read it.
- For already-finished deploys, SSE would immediately fire 'done' and
  reload, showing logs for < 1 second.

Fix:
- showLog() now fetches the deploy via REST first. If done, it renders
  the stored log directly (no SSE). If still running, it streams via
  SSE and closes without reloading when done.
- Added onerror fallback: re-fetches the log via REST if SSE drops.
- Status badge (green/red) updates inline instead of triggering reload.
- Page now auto-opens the latest deploy log on load so the failure
  reason is visible immediately without any clicking.

https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 08:57:01 +00:00
Claude
0180f37c31
Add .gitignore, remove target/ from tracking
https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 08:26:07 +00:00
Claude
8f5bb158cb
M1: Rust control plane, builder, dashboard, and infra
- Cargo workspace with hiy-server (axum 0.7 + sqlx SQLite + tokio)
- SQLite schema: apps, deploys, env_vars (inline migrations, no daemon)
- Background build worker: sequential queue, streams stdout/stderr to DB
- REST API: CRUD for apps, deploys, env vars; GitHub webhook with HMAC-SHA256
- SSE endpoint for live build log streaming
- Monospace HTMX-free dashboard: app list + per-app detail, log viewer, env editor
- builder/build.sh: clone/pull → detect strategy (Dockerfile/buildpack/static)
  → docker build → swap container → update Caddy via admin API → prune images
- infra/docker-compose.yml + Dockerfile.server for local dev (no Pi needed)
- proxy/Caddyfile: auto-HTTPS off for local, comment removed for production
- .env.example

Compiles clean (zero warnings). Run locally:
  cp .env.example .env && cargo run --bin hiy-server

https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 08:25:59 +00:00
Claude
c46e3b4125
Add MVP plan for self-hosted Heroku clone on Raspberry Pi
Covers architecture, components, data model, security, monitoring,
backup, milestones, and hardware recommendations.

https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
2026-03-19 07:38:17 +00:00