- Go service with its own multi-stage Dockerfile and docker-compose.yml; runs as container webrestrict-control on port 8791. - SQLite schema for the full AGENTS.md §7 data model via versioned migrations (PRAGMA user_version); audit log is append-only. - Configuration from the process environment; the real env file is gitignored and a template is committed. No secrets in the repo. - Separate session login (signed HMAC cookie + CSRF) for Sam. - GET /health; HTMX + server-rendered dashboard styled with the Family Home Lab tokens.css (copied) and Inter fonts; dark mode; phone-friendly. - Caddy vhost for webrestrict.lab.audasmedia.com.au applied on .35 (Let's Encrypt cert issued); route recorded in deploy/caddy/webrestrict.caddy. - Unit tests for config, auth and store. Co-Authored-By: Paperclip <noreply@paperclip.ing>
122 lines
4.5 KiB
Markdown
122 lines
4.5 KiB
Markdown
# Internet Use Control — Control Service
|
|
|
|
The **Control Service** is the brain and the single source of truth for the
|
|
Internet Use Control project (`SYSTEM_MAP.md`). It holds schedules, blocklists,
|
|
per-device state and usage, and serves the web dashboard. Only it publishes
|
|
device config.
|
|
|
|
This repository currently contains **Phase 1 — Skeleton** (AGENTS.md §11):
|
|
|
|
- Go service with its own image (`Dockerfile`) and compose file.
|
|
- SQLite schema for the whole data model (§7), applied through versioned
|
|
migrations.
|
|
- Configuration from the process environment (`environment.d`); no secrets in
|
|
the repo.
|
|
- A separate session login for Sam.
|
|
- `GET /health`.
|
|
- HTMX + server-rendered dashboard styled with the Family Home Lab design
|
|
system (`tokens.css` copied in).
|
|
|
|
Enforcement, MQTT, devices, schedules and the clients arrive in later phases.
|
|
Nothing here touches the router, Pi-hole, or DNS.
|
|
|
|
## Quick start (on `.13`)
|
|
|
|
```bash
|
|
cd /home/sam/paseo/projects/internet_use_control
|
|
|
|
# 1. Create the env file from the template and set real values.
|
|
cp environment.d/control-service.env.example environment.d/control-service.env
|
|
$EDITOR environment.d/control-service.env
|
|
|
|
# 2. Build and start. Own image, own container, port 8791.
|
|
docker compose up -d --build
|
|
|
|
# 3. Prove it.
|
|
curl -s http://127.0.0.1:8791/health
|
|
# {"status":"ok","service":"control-service","version":"0.1.0-phase1",...}
|
|
```
|
|
|
|
Open <http://127.0.0.1:8791/> in a browser. It redirects to `/login`. Sign in
|
|
with `CONTROL_ADMIN_USERNAME` and `CONTROL_ADMIN_PASSWORD`.
|
|
|
|
## Configuration
|
|
|
|
All configuration is environment variables. Docker Compose loads them from
|
|
`environment.d/control-service.env` (gitignored). The variables can also be
|
|
exported from `~/.config/environment.d/10-secrets.conf` instead; the service
|
|
reads only the process environment.
|
|
|
|
| Variable | Default | Purpose |
|
|
|---|---|---|
|
|
| `CONTROL_ADDR` | `:8791` | Listen address |
|
|
| `CONTROL_DB_PATH` | `/data/control.db` | SQLite file |
|
|
| `CONTROL_SESSION_SECRET` | — (required) | Signs the session cookie, ≥ 16 chars |
|
|
| `CONTROL_SESSION_TTL` | `12h` | Session lifetime |
|
|
| `CONTROL_COOKIE_SECURE` | `true` | Secure cookie flag; keep true behind HTTPS |
|
|
| `CONTROL_ADMIN_USERNAME` | `sam` | Dashboard login |
|
|
| `CONTROL_ADMIN_PASSWORD` | — | Plaintext password (option A) |
|
|
| `CONTROL_ADMIN_PASSWORD_HASH` | — | bcrypt hash (option B, preferred) |
|
|
| `CONTROL_APP_ENV` | `production` | Label shown in the footer |
|
|
| `CONTROL_LOG_LEVEL` | `info` | `debug`/`info`/`warn`/`error` |
|
|
|
|
Generate a bcrypt hash without host Go:
|
|
|
|
```bash
|
|
docker run --rm --entrypoint /app/control webrestrict/control:0.1.0-phase1 \
|
|
hash-password 'your-password'
|
|
```
|
|
|
|
## Endpoints (Phase 1)
|
|
|
|
| Method | Path | Notes |
|
|
|---|---|---|
|
|
| `GET` | `/health` | JSON. `status: ok`, database check. No auth. |
|
|
| `GET` | `/login` | Session login form. |
|
|
| `POST` | `/login` | Verifies credentials, sets a signed session cookie. |
|
|
| `POST` | `/logout` | Clears the session. |
|
|
| `GET` | `/` | Dashboard. Redirects to `/login` when not signed in. |
|
|
| `GET` | `/partials/status` | HTMX fragment, polled every 10 s. |
|
|
|
|
## Development
|
|
|
|
There is no host Go toolchain on `.13`; use the cached builder image.
|
|
|
|
```bash
|
|
make test # go test ./... in golang:1.25-alpine
|
|
make vet # go vet ./...
|
|
make build # build the container image
|
|
make up # docker compose up -d --build
|
|
make logs # follow container logs
|
|
```
|
|
|
|
## Layout
|
|
|
|
```
|
|
cmd/control/ service entry point (+ hash-password helper)
|
|
internal/config/ environment configuration
|
|
internal/store/ SQLite open, migrations, audit
|
|
internal/store/migrations/001_init.sql
|
|
internal/auth/ signed-cookie session login + CSRF
|
|
internal/web/ HTTP handlers, templates, static assets
|
|
templates/ login, dashboard, HTMX partials
|
|
static/ tokens.css (Family Home Lab), app.css, htmx, Inter fonts
|
|
Dockerfile own image (multi-stage, CGO-free)
|
|
docker-compose.yml own container, port 8791
|
|
environment.d/ control-service.env.example (real file gitignored)
|
|
deploy/caddy/ Caddy vhost for webrestrict.lab.audasmedia.com.au
|
|
```
|
|
|
|
## Caddy
|
|
|
|
`deploy/caddy/webrestrict.caddy` holds the vhost for
|
|
`webrestrict.lab.audasmedia.com.au`. The terminating Caddy runs on `.35`
|
|
(sam-Ubuntu1); see that file for the two proxy patterns and the apply commands.
|
|
|
|
## Non-goals (Phase 1)
|
|
|
|
- No MQTT publishing (Phase 3).
|
|
- No device registry or lock/unlock UI (Phase 2).
|
|
- No admin API (Phase 8).
|
|
- No Hub contact (Phase 9).
|