docs/homarr-gluetun-contract.md
Rama main · réplica de lectura del repositorio original.
# Gluetun Link boundary
The Gluetun leaf is source-complete for audited Homarr `2.5.1` and `2.5.2`.
The native/privacy source blocker from #332 is resolved by released upstream
[hotfix #7170](https://github.com/homarr-labs/homarr/pull/7170). Provider and VPN
runtime acceptance is deferred: no real provider connection, Docker, browser,
personal Project or tunnel-break test was performed by this leaf.
## Control access and provider readiness
The Catalog pins Gluetun `qmcgaw/gluetun:v3.41.3`, source commit
`3d1e20c5551e9cae1f9d938dc7b7214a6987f27e`. Its generated
`GLUETUN_CONTROL_API_KEY` is reused, never rotated by the Link. The Project's
mode-0600 `control-auth.toml` remains mounted read-only at
`/run/secrets/control-auth` and selected by
`HTTP_CONTROL_SERVER_AUTH_CONFIG_FILEPATH`. Its exact grants remain:
- `GET /v1/vpn/status`
- `GET /v1/publicip/ip`
- `GET /v1/portforward`
Authentication is `apikey`, sent only through `X-API-Key`. The pinned source
still has public defaults when no role is configured. Link preflight first
reads authenticated Homarr `info.getInfo`; exact `2.5.1` and `2.5.2` pass, while
older, unknown, malformed or unreadable versions stop as retryable Manual before
provider requests or Homarr mutation. Standalone verification repeats this gate
before the native query or Stats acquisition.
After the safe-version gate, preflight delegates to Gluetun's existing `Check`:
anonymous status must return 401, the saved key must work, and the VPN must report
`running` with a valid public IP. Missing provider credentials, control recovery
and an unready tunnel retain an actionable Manual hint. No provider purchase,
credential discovery, traffic rerouting, firewall change, new capability or
device authority is introduced. The existing NET_ADMIN and `/dev/net/tun`
approvals, provider/account configuration and recorded tunnel-break fail-closed
acceptance remain separate runtime prerequisites.
## Native and Stats contracts
The Link supplies `[apiKey]` to integration kind `gluetun` at
`http://gluetun:8000`, separate from the browser Address. Its existing selectors
remain native `vpn` and shared Stats `status`/`publicIp`. No geography, throughput,
uptime or invented selector is added.
The inspected fixed upstream adapter calls only `GET /v1/vpn/status` and
`GET /v1/publicip/ip`. It never reads `/v1/vpn/settings` or DNS status. Country,
city and other public-IP metadata are optional. Homarr `2.5.2` tag source
`7eb9a417a60d759adce5f7ac15ceb594aefad471` retains the identical fixed adapter,
schemas, native router and Stats mapping from released `2.5.1` OCI revision
`62c8513a27e9fd40ad935fac152ba1a6a84f0867`. Image/API observations belong to the
[shared contract](homarr-integration-contract.md); source equality is not real
Gluetun acceptance.
`widget.vpn.getSummaries` is requested with exactly the owned integration ID.
Verification requires exactly one result, matching integration ID and kind,
no reported error and an object summary. `vpnStatus` must be one of `running`,
`stopped`, `starting`, `stopping` or `crashed`; `publicIp` must be a string.
A nonempty IP must parse as an unscoped public unicast address. An explicit empty
IP is legitimate unavailable data, including while discovery catches up with
running status. Omitted country/city is accepted; supplied malformed or null
geography fails. A nonrunning summary is valid data, never a healthy-tunnel
claim. Preflight separately enforces the running-tunnel prerequisite.
The pure Stats callback consumes the common SDK's one catalog and one completed
forced refresh. Both selected metrics require exact unit `text` and retain the
same status/IP semantics. Missing/null selected values fail; empty IP is never
replaced by zero. Native and Stats are independently cached samples and need
not have equal volatile values. The callback performs no HTTP, catalog or Stats
reads. Common freshness rules still reject cached/no-op refreshes and malformed
or nonadvancing timestamps.
## Focused source validation and deferred acceptance
`go test ./internal/apps/homarr -run 'TestGluetun' -count=1` passed. Focused
interface fixtures cover both safe versions, unsafe/unreadable versions in
Check/apply/standalone verification, restricted control preflight, every status,
IPv4/IPv6 and legitimate empty IP, optional geography, malformed identity/data,
incorrect units and no-op refresh. The fixture rejects any request outside its
explicit route list and requires one owned Stats sample per verification.
Those synthetic checks prove client ordering and validation; the fixed upstream
source establishes its endpoint set. Neither is provider or fail-closed proof.
No common registry or reconciliation file was edited in this leaf. There is no
remaining source blocker in the audited native contract. Real native data,
rendered widgets, both install orders, late peer/retry, provider credentials,
restart, downloader namespace/IP/DNS privacy, tunnel-break recovery, owned-resource
removal and reinstallation remain deferred to an approved runtime phase with
an available provider account.
## Sources
- [Fixed Homarr adapter](https://github.com/homarr-labs/homarr/blob/7eb9a417a60d759adce5f7ac15ceb594aefad471/packages/integrations/src/gluetun/gluetun-integration.ts)
- [Fixed Homarr schemas](https://github.com/homarr-labs/homarr/blob/7eb9a417a60d759adce5f7ac15ceb594aefad471/packages/integrations/src/gluetun/gluetun-types.ts)
- [VPN result router](https://github.com/homarr-labs/homarr/blob/7eb9a417a60d759adce5f7ac15ceb594aefad471/packages/api/src/router/widgets/vpn.ts)
- [Stats metric mapping](https://github.com/homarr-labs/homarr/blob/7eb9a417a60d759adce5f7ac15ceb594aefad471/packages/integrations/src/stats/existing.ts)
- [Gluetun control-server guide](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md)
- [Gluetun 3.41.3 auth routes/defaults](https://github.com/qdm12/gluetun/blob/v3.41.3/internal/server/middlewares/auth/settings.go)
- [VPN settings handler](https://github.com/qdm12/gluetun/blob/v3.41.3/internal/server/vpn.go)
- [Unredacted settings copy](https://github.com/qdm12/gluetun/blob/v3.41.3/internal/vpn/state/vpn.go)
- [Optional public-IP metadata](https://github.com/qdm12/gluetun/blob/v3.41.3/internal/models/publicip.go)
- [Disconnected public-IP clearing](https://github.com/qdm12/gluetun/blob/v3.41.3/internal/publicip/data.go)