openspec: deploy-frontend change — .13:3020 systemd service + Caddy/DNS
This commit is contained in:
2
openspec/changes/deploy-frontend/.openspec.yaml
Normal file
2
openspec/changes/deploy-frontend/.openspec.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
schema: spec-driven
|
||||||
|
created: 2026-08-07
|
||||||
3
openspec/changes/deploy-frontend/README.md
Normal file
3
openspec/changes/deploy-frontend/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# deploy-frontend
|
||||||
|
|
||||||
|
Deploy GOAT frontend to .13:/var/www/where-woof as systemd user service on :3020; Caddy .35 block + DNS/InMotion redirect
|
||||||
41
openspec/changes/deploy-frontend/design.md
Normal file
41
openspec/changes/deploy-frontend/design.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
## Context
|
||||||
|
|
||||||
|
The GOAT frontend is verified on .27 (dev). Production target per the plan: `.13:/var/www/where-woof`, port `:3020`, behind Caddy on `.35`, domain `where-woof.com` (currently at InMotion, DNS to be repointed). The DB already lives on .13 (`wherewoof-db`, :5434). .13 uses **systemd user services** (lan-mouse, engram) — the established pattern for app processes there. The Caddy block is already saved by the user.
|
||||||
|
|
||||||
|
## Goals / Non-Goals
|
||||||
|
|
||||||
|
**Goals:**
|
||||||
|
- Frontend live on .13:3020 as a managed, restart-on-failure service.
|
||||||
|
- Reproducible build+rsync deploy step; secrets on .13 only.
|
||||||
|
- Caddy block verified; DNS/InMotion redirect documented as the user step.
|
||||||
|
|
||||||
|
**Non-Goals:**
|
||||||
|
- Admin (Laravel) deploy — Phase 8.
|
||||||
|
- TLS/cert automation specifics (Caddy handles it).
|
||||||
|
- Rolling deploys / zero-downtime — single binary, quick restart is fine.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
1. **systemd user service** (`~/.config/systemd/user/where-woof.service`) with `Restart=on-failure`, `EnvironmentFile=/home/sam/.config/where-woof.env` (chmod 600) holding `DATABASE_URL`, `SESSION_SECRET`, `SMS_USER`, `SMS_PASSWORD`, `SMS_FROM`. Matches .13 conventions (lan-mouse) and keeps secrets out of the repo. `systemctl --user enable --now where-woof`.
|
||||||
|
2. **Run from /var/www/where-woof** — the app resolves `templates/` + `static/` relative to cwd (proven in dev); `WorkingDirectory=/var/www/where-woof`. Uploads dir pre-created + writable.
|
||||||
|
3. **Build on .27, rsync binary+assets** (no Go on .13). `make build` exists; add `make deploy` → rsync + restart.
|
||||||
|
4. **DB on localhost**: the .13 service uses `postgres://wherewoof:...@localhost:5434/wherewoof` (container on .13).
|
||||||
|
5. **Caddy/DNS**: block already saved on .35; verify `where-woof.home.lab` → .35 → .13:3020 end-to-end once running. DNS repoint of `where-woof.com` (InMotion → .35) is the user's final step.
|
||||||
|
|
||||||
|
## Risks / Trade-offs
|
||||||
|
|
||||||
|
- [Secrets in a plaintext file on .13] → chmod 600, matches existing convention; never committed.
|
||||||
|
- [Port 3020 conflicts] → verified free on .13.
|
||||||
|
- [Uploads lost on redeploy if rsync --delete] → do NOT use --delete on static/; keep uploads untouched.
|
||||||
|
- [systemd user service needs lingering for boot] → `loginctl enable-linger sam` so it starts at boot without login.
|
||||||
|
|
||||||
|
## Migration Plan
|
||||||
|
|
||||||
|
1. `make build` on .27.
|
||||||
|
2. rsync binary + templates + static (no --delete) → /var/www/where-woof; chown sam:users; mkdir uploads.
|
||||||
|
3. Write env file (chmod 600) + unit file; `systemctl --user daemon-reload && enable --now`.
|
||||||
|
4. Verify: curl localhost:3020 on .13; then from .27 via 192.168.20.13:3020; then via Caddy home.lab if DNS local resolves.
|
||||||
|
|
||||||
|
## Open Questions
|
||||||
|
|
||||||
|
- Whether to run real SMS creds on the live service now (suggest: yes — the account has funds, log sender would silently skip alerts otherwise).
|
||||||
29
openspec/changes/deploy-frontend/proposal.md
Normal file
29
openspec/changes/deploy-frontend/proposal.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
## Why
|
||||||
|
|
||||||
|
Phases 1–4 built and verified both apps on .27 (dev). The product has a real domain (`where-woof.com`, currently parked at InMotion) and a Caddy reverse proxy on .35 ready to serve it. Phase 7 puts the GOAT frontend **live on .13** behind the saved Caddy block, so the site is reachable on the real domain (DNS/redirect to follow).
|
||||||
|
|
||||||
|
## What Changes
|
||||||
|
|
||||||
|
- **Binary deploy**: build the Go frontend on .27 (`GOOS=linux GOARCH=amd64`) and rsync `where-woof` binary + `templates/` + `static/` → `.13:/var/www/where-woof` (the established pattern used by `sam-developer` etc.).
|
||||||
|
- **Systemd user service** on .13: `where-woof.service` (like `lan-mouse.service`), runs the binary on `:3020`, `Restart=on-failure`, env from an `EnvironmentFile` (secrets live on .13, never in the repo).
|
||||||
|
- **Caddy** on .35: the block is already saved by the user (`where-woof.com` / `where-woof.home.lab` → `.13:3020`); this change verifies it once the service is up.
|
||||||
|
- **DNS / InMotion redirect**: user action — point `where-woof.com` DNS at .35 (or InMotion redirect), out of scope for code but documented.
|
||||||
|
- The DB is already on .13 (`wherewoof-db` :5434) — the service connects to `localhost:5434`.
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
### New Capabilities
|
||||||
|
|
||||||
|
- `deploy-service`: the frontend runs on .13:3020 as a managed systemd user service with secrets via EnvironmentFile.
|
||||||
|
- `deploy-artifacts`: build + rsync step reproduces the deployable (binary + templates + static + uploads writable).
|
||||||
|
|
||||||
|
### Modified Capabilities
|
||||||
|
|
||||||
|
<!-- none — deployment only -->
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
- **On .13**: `/var/www/where-woof/{where-woof,templates,static}`, `~/.config/systemd/user/where-woof.service` + `EnvironmentFile` (DATABASE_URL, SESSION_SECRET, SMS creds), uploads dir writable.
|
||||||
|
- **On .27**: `make build` target already exists; rsync command added to a deploy script or Makefile target.
|
||||||
|
- **No code changes** to the Go app (cwd-relative templates/static already handled by running from /var/www/where-woof).
|
||||||
|
- Admin deploy (Laravel on .13:3030) is Phase 8 — the Caddy admin block is forward-looking.
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: Service runs on .13:3020
|
||||||
|
The frontend SHALL run as a systemd user service (`where-woof.service`) on `.13`, listening on `:3020`, restarting on failure, with secrets from an EnvironmentFile (never in the repo).
|
||||||
|
|
||||||
|
#### Scenario: Service starts
|
||||||
|
- **WHEN** the service is enabled and started
|
||||||
|
- **THEN** the app listens on 192.168.20.13:3020 and responds 200 on `/`
|
||||||
|
|
||||||
|
#### Scenario: Crash recovery
|
||||||
|
- **WHEN** the process exits unexpectedly
|
||||||
|
- **THEN** systemd restarts it
|
||||||
|
|
||||||
|
### Requirement: Deployable artifact
|
||||||
|
A build + rsync step SHALL produce and transfer the binary, `templates/`, and `static/` to `/var/www/where-woof` on .13, with `static/uploads` writable by the service user.
|
||||||
|
|
||||||
|
#### Scenario: Fresh deploy
|
||||||
|
- **WHEN** the build+rsync runs against a clean target dir
|
||||||
|
- **THEN** the service runs the new binary with templates/static present and uploads writable
|
||||||
|
|
||||||
|
### Requirement: Caddy reachability
|
||||||
|
The saved Caddy block on .35 SHALL reverse-proxy `where-woof.com` and `where-woof.home.lab` to `.13:3020`.
|
||||||
|
|
||||||
|
#### Scenario: Proxied request
|
||||||
|
- **WHEN** `where-woof.home.lab` is resolved to .35 and requested
|
||||||
|
- **THEN** the response comes from the .13 service
|
||||||
20
openspec/changes/deploy-frontend/tasks.md
Normal file
20
openspec/changes/deploy-frontend/tasks.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
## 1. Artifacts
|
||||||
|
|
||||||
|
- [ ] 1.1 `make build` on .27 → `frontend/where-woof` binary
|
||||||
|
- [ ] 1.2 rsync binary + `templates/` + `static/` → `sam@192.168.20.13:/var/www/where-woof` (NO --delete on static; uploads preserved); `mkdir -p static/uploads` + chown
|
||||||
|
|
||||||
|
## 2. Service
|
||||||
|
|
||||||
|
- [ ] 2.1 Write `/home/sam/.config/where-woof.env` on .13 (DATABASE_URL→localhost:5434, SESSION_SECRET, SMS_* ; chmod 600)
|
||||||
|
- [ ] 2.2 `~/.config/systemd/user/where-woof.service` (WorkingDirectory=/var/www/where-woof, Restart=on-failure, EnvironmentFile, port 3020); `daemon-reload`, `enable --now`, `loginctl enable-linger sam`
|
||||||
|
- [ ] 2.3 Verify: curl localhost:3020 on .13 (200); from .27 via 192.168.20.13:3020
|
||||||
|
|
||||||
|
## 3. Caddy / DNS
|
||||||
|
|
||||||
|
- [ ] 3.1 Confirm the .35 Caddy block is present (user saved it); test `where-woof.home.lab` → .35 → .13:3020 if local DNS resolves
|
||||||
|
- [ ] 3.2 Document the InMotion → where-woof.com DNS repoint as the user step
|
||||||
|
|
||||||
|
## 4. Verification
|
||||||
|
|
||||||
|
- [ ] 4.1 Full smoke on .13: register → claim TEST000001 → edit → public page; SMS in log mode unless creds set
|
||||||
|
- [ ] 4.2 `openspec validate deploy-frontend`; commit
|
||||||
Reference in New Issue
Block a user