Files
internet_use_control/docs/outline/02-config-and-env.md
Sam Rolfe eb300b6701 Phase 10: publish the documentation set + tick AGENTS.md 9 of 10
Phase 10 (the last phase of this project) is the project-docs pass. Update the
Gitea README, add the Mermaid source and rendered PNG, build the interactive
Archify map, add the Vikunja board tasks, and write the Outline AI-context
collection in Simplified Technical English.

Deliverables:
- README.md: status header, Phase 4 gap statement, "Architecture" section with
  embedded Mermaid + image + Archify link, "Documentation set" table, an
  explicit two-plane MQTT section (1883 plain+anonymous, 8883 TLS+ACLs), and
  the Android client's Usage Access and VpnService paths.
- AGENTS.md section 11: tick Phase 10, leave Phase 4 unticked, status line now
  "9 of 10 done - only Phase 4 outstanding".
- docs/architecture.mmd + docs/diagrams/architecture.png (mmdc).
- docs/archify/architecture.architecture.json + docs/architecture-map.html
  (Archify, showcase, 9/9 checks, 0 errors).
- docs/outline/00-index.md .. 04-agent-runbook.md (STE).
- docs/vikunja-tasks.json (Vikunja project "Internet Use Control", id 20).
- Obsidian note written to 010 inbox on .27; the obsidian-sorter proposed a
  folder and waits for the vault owner's approval.

Phase 4 (Python Windows computer client) is deliberately deferred and is NOT
built. Every document says so.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-14 12:13:21 +11:00

93 lines
4.9 KiB
Markdown

# Internet Use Control — Configuration and Environment
> **Target**: AI agents. **Writing style**: ASD-STE100 Simplified Technical English.
## Configuration Files
| File | Status | Purpose |
| :--- | :--- | :--- |
| `environment.d/control-service.env` | Live, gitignored | The real values for the container. |
| `environment.d/control-service.env.example` | In git | The template. Copy it and set the values. |
| `docker-compose.yml` | In git | The container, the port and the env file path. |
| `deploy/mosquitto/conf.d/webrestrict.conf` | In git | The TLS listener, the password file and the ACL file. |
| `deploy/mosquitto/conf.d/webrestrict.acl` | In git | The per-device topic ACL. |
| `deploy/mosquitto/clients.env` | In git | The client names for the verifier. No secrets. |
| `deploy/caddy/webrestrict.caddy` | In git | The vhost on `.35`. |
Secrets come from `environment.d` or from
`~/.config/environment.d/10-secrets.conf`. The service reads only the process
environment. No secret is in the repository.
## Ports and Addresses
| Item | Value |
| :--- | :--- |
| Control Service | `8791` on `.13` |
| Public URL | `https://webrestrict.lab.audasmedia.com.au` (Caddy on `.35`) |
| MQTT plain plane | `1883` on `.13`, anonymous |
| MQTT TLS plane | `8883` on `.13`, credentials and ACLs |
| Apprise | `8210` on `.35` |
| Hub | `8788` on `.13` |
| Database | `/data/control.db` inside the container |
## Environment Variables
| 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 characters minimum. |
| `CONTROL_SESSION_TTL` | `12h` | Session lifetime. |
| `CONTROL_COOKIE_SECURE` | `true` | Secure cookie flag. Keep it true behind HTTPS. |
| `CONTROL_ADMIN_USERNAME` | `sam` | Dashboard login name. |
| `CONTROL_ADMIN_PASSWORD` | — | Plaintext password, option A. |
| `CONTROL_ADMIN_PASSWORD_HASH` | — | bcrypt hash, option B, preferred. |
| `CONTROL_ADMIN_API_TOKEN` | — | Bearer token for the versioned admin API. Empty answers `503`. |
| `CONTROL_DEVICE_KEYCODE_HASH` | — | bcrypt hash of the shared device keycode. Seeds SQLite at start-up. |
| `CONTROL_APP_ENV` | `production` | Label in the footer. |
| `CONTROL_LOG_LEVEL` | `info` | `debug`, `info`, `warn` or `error`. |
| `CONTROL_TIMEZONE` | `Australia/Sydney` | IANA zone for the weekly windows. |
| `CONTROL_MQTT_ENABLED` | `true` | Turn the broker link on or off. |
| `CONTROL_MQTT_BROKER` | `tcp://host.docker.internal:1883` | Broker URL. The live value is `tls://host.docker.internal:8883`. |
| `CONTROL_MQTT_CLIENT_ID` | `control-service` | MQTT client id. |
| `CONTROL_MQTT_USERNAME` | — | The Control Service broker account. |
| `CONTROL_MQTT_PASSWORD` | — | Its password. |
| `CONTROL_MQTT_CA_FILE` | `/etc/webrestrict/tls/ca.crt` | PEM bundle that verifies the broker. TLS only. |
| `CONTROL_MQTT_INSECURE` | `false` | Allow a plaintext broker with no credentials. The live value is `false`. |
| `CONTROL_HUB_TOKEN` | — | Bearer token for `/capabilities`, `/ask` and `/notify`. Empty answers `503`. |
| `CONTROL_APPRISE_URL` | `http://192.168.20.35:8210` | The house Apprise API. |
| `CONTROL_APPRISE_KEY` | — | Stored Apprise configuration key, option A. |
| `CONTROL_APPRISE_URLS` | — | Stateless Apprise destination list, option B. The lab default. |
| `CONTROL_APPRISE_TOKEN` | — | Optional bearer token for a protected Apprise API. |
| `CONTROL_ALERTS_ENABLED` | `true` | Turn the alert engine on or off. |
| `CONTROL_ALERT_OFFLINE_AFTER` | `30m` | Time before an offline device raises an alert. |
| `CONTROL_ALERT_INTERVAL` | `30s` | How often the alert engine re-evaluates the devices. |
The service refuses a non-TLS broker unless `CONTROL_MQTT_INSECURE=true`
(AGENTS.md section 10, rule 6). The live deployment does not use that escape
hatch.
## Secrets
| Secret | Where it lives | Notes |
| :--- | :--- | :--- |
| Dashboard password | `CONTROL_ADMIN_PASSWORD_HASH` | bcrypt. Preferred over the plaintext form. |
| Admin API token | `CONTROL_ADMIN_API_TOKEN` | A bearer token. Separate from the session login. |
| Hub token | `CONTROL_HUB_TOKEN` | A bearer token. Separate from the admin token. |
| Device keycode | SQLite, bcrypt hash | One code for every device. Seeded from `CONTROL_DEVICE_KEYCODE_HASH`. |
| MQTT accounts | Mosquitto password file | One account per device plus `control-service`. |
## Commands That Read or Change Configuration
```bash
# Generate a bcrypt hash without a host Go toolchain.
docker run --rm --entrypoint /app/control webrestrict/control:0.7.0-phase9 \
hash-password 'your-password'
# Set the shared device keycode. The code comes from stdin.
docker exec -i webrestrict-control /app/control keycode <<< '246810'
# Print the MQTT identity of every device. Tokens only, no secrets.
docker exec webrestrict-control /app/control mqtt-clients
```