# 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
```
