Skip to content

network:proxy service

Publishes a module through Caddy — the module's public face. It owns the hostname, the certificate, the upstream handler and the firewall alias that decides who may reach it. Nothing here touches a guest; the changes land on the proxy and the firewall, and the workload never notices.

10 fields — all in-place, all apply: "reconcile".

The module's public face. Nothing here touches a guest: the changes land on Caddy and the firewall, and the workload never notices. The largest drift blind spot — see recommendation 1.

Why reconcile and not set

update-service.sh rewrites this module's whole Caddy site block and its OPNsense alias from the declared values on every pass, then reloads. That is already idempotent and already handles removal — a handler that should no longer exist is deleted, which no scalar field diff can express. Flattening it into set fields would lose that. The manifest declares the class, which is what makes --set sanctioned; the apply stays where the domain knowledge is.

Because there is no report-service.sh, module-manager module drift reports these fields as not-reported rather than comparing them — the converge is trusted to have made config true. That is the blind spot recommendation 1 closes.

Fields

network:proxy owns 8 declared field(s). Each table below carries the field's full definition and, where the service applies it, its ADR-020 change semantics.

proxyDomain

Public domain name for the reverse proxy. Caddy obtains a TLS certificate for this domain.

Attribute Value
Type string
Default <vmname>.<tappaas.domain>
Format ^[a-zA-Z0-9](https://codeberg.org/TAPPaaS/TAPPaaS/src/branch/main/src/foundation/network/services/proxy/%5Ba-zA-Z0-9.-%5D%2A%5Ba-zA-Z0-9%5D)?$
Example vaultwarden.test.tapaas.org
Required by (none)
Used by network:proxy
Change class in-place
Apply mode reconcile

About the field. If not set, defaults to . from configuration.json

Why this change class. The public hostname. Changing it re-issues the ACME certificate and moves the handler; the module itself is untouched, so no guest downtime — though clients on the old name stop resolving as soon as DNS follows.

proxyPort

Target port on the module VM that the reverse proxy forwards traffic to

Attribute Value
Type integer
Default 80
Minimum 1
Maximum 65535
Example 8080
Required by (none)
Used by network:proxy
Change class in-place
Apply mode reconcile
Normalizer integer

About the field. The port the service listens on inside the VM

Why this change class. The upstream port Caddy forwards to. A handler rewrite, applied live.

proxyUpstreamTls

Reverse-proxy to an HTTPS upstream instead of plain HTTP. Set true for backends that only speak TLS — e.g. the OPNsense GUI on :8443. network:proxy renders the Caddy upstream as https:// with upstream certificate verification skipped (internal/self-signed backends).

Attribute Value
Type string
Default false
Allowed values true — Upstream is HTTPS (skip upstream cert verification)
false — Upstream is plain HTTP (default)
Required by (none)
Used by network:proxy
Change class in-place
Apply mode reconcile
Normalizer boolean

Why this change class. Whether the hop from Caddy to the module is itself TLS. Declared as a string in module-fields.json, so the boolean normalizer is what makes 'true' and true one value.

proxyUpstreamHttp1

Force HTTP/1.1 to the upstream (os-caddy HttpVersion=http1). Required for apps whose UI rides a WebSocket behind a TLS upstream — e.g. the UniFi OS console. Without it, Caddy negotiates HTTP/2 with the upstream, which cannot carry a WebSocket Upgrade and returns 500, so the SPA renders blank.

Attribute Value
Type string
Default false
Allowed values true — Force HTTP/1.1 to the upstream (WebSocket support)
false — Default upstream HTTP versions (HTTP/1.1 + HTTP/2)
Required by (none)
Used by network:proxy
Change class in-place
Apply mode reconcile
Normalizer boolean

Why this change class. Force HTTP/1.1 upstream, for a backend that cannot speak h2c.

proxyPreserveHost

Force the upstream Host header to the public domain (Caddy header_up Host ). Needed for apps that validate a WebSocket's Origin against the Host header — e.g. the UniFi OS console: Caddy otherwise sends the upstream's own hostname, so the browser's Origin (the public domain) ≠ Host and the WebSocket upgrade returns 500, leaving the SPA blank after login. Usually paired with proxyUpstreamHttp1 for WebSocket apps behind a TLS upstream.

Attribute Value
Type string
Default false
Allowed values true — Send Host: upstream (WebSocket Origin check)
false — Caddy default upstream Host
Required by (none)
Used by network:proxy
Change class in-place
Apply mode reconcile
Normalizer boolean

Why this change class. Pass the original Host header through, for a backend that generates absolute URLs from it.

proxyTls

How network:proxy obtains the public TLS certificate for this domain. OMIT IT to inherit the environment's domains.dnsMode (config/environments/.json) — that is the normal case and the only way one setting governs a whole environment. Set it only to override that environment-wide choice for this one module. 'dns01' binds the TAPPaaS-wide wildcard certificate issued by os-acme-client (acme-setup.sh) via Caddy's per-domain CustomCertificate, and requires a DNS provider that supports DNS-01 plus the wildcard already being in OPNsense Trust; until it is, the public HTTPS endpoint has no cert while the LAN endpoint still works. 'http01' uses classic ACME HTTP-01: Caddy obtains a per-domain cert via the :80 challenge, so the domain MUST be reachable from the internet on port 80, and no DNS API is needed.

Attribute Value
Type string
Allowed values dns01 — Wildcard certificate via os-acme-client; bound by refid through Caddy CustomCertificate (no per-module ACME, w
http01 — Per-domain ACME HTTP-01 via Caddy itself (no DNS-API needed, but the domain must be reachable from the interne
Required by (none)
Used by network:proxy
Change class in-place
Apply mode reconcile

Why this change class. Which certificate strategy serves the domain (per-service or the environment wildcard).

proxyAllowedZones

Zones (and the literal 'internet') permitted to reach this service through the reverse proxy. network:proxy compiles this into an os-caddy access list (allow-list by client subnet) attached to the handler; non-matching clients get HTTP 403. Under ADR-021 D2 this is the ONLY place a zone restricts a published service: split-horizon DNS returns the same address (the DMZ gateway) to every caller, so the answer encodes no entitlement and the access list is what narrows it.

Attribute Value
Type array
Default
Example mgmt, home, work, srvHome, srvWork
Required by (none)
Used by network:proxy
Change class in-place
Apply mode reconcile

About the field. Zero-trust by default: when omitted, a service is reachable only from the internal trusted zones, never the internet. Add 'internet' to publish it publicly (no restriction). Zone names are resolved to subnets via zones.json. Changing this re-applies on the next install/update of the module. TWO values carry real consequence and the rest is belt-and-braces: leaving it UNSET is the normal, correct configuration for a published service, and adding 'internet' is what makes it publicly reachable. Narrowing to a specific list of internal zones filters IN FRONT OF the identity gate, it is not the mechanism protecting the service (ADR-021 Case ⅓) — a zone list that lets someone through still leaves them at an Authentik login, and one that shuts them out only saves them the round trip. Do not use it to separate two populations who are each entitled to a different environment: that binds entitlement to network position, which breaks the moment a legitimate user connects from another zone (the same person on a laptop in home, a phone on guest wifi and the netbird overlay is ONE identity in three zones). Authentik group membership is where that belongs.

Why this change class. Which zones may reach the published name — the difference between an internal service and one exposed to the internet. A live firewall/Caddy change, and the field most worth being able to set through a verb rather than by hand.

proxyRoutes

Additional reverse-proxy routes for a VM that serves several endpoints on different ports. Each entry publishes . — where is the environment's primary domain, the same suffix proxyDomain defaults to — forwarding to the module's upstream host on the entry's port. The primary proxyDomain/proxyPort route is unaffected. Extra routes inherit the primary route's access list (proxyAllowedZones), TLS strategy (proxyTls/dnsMode) and upstream flags (proxyUpstreamTls, proxyUpstreamHttp1, proxyPreserveHost).

Attribute Value
Type array
Default (none)
Example [{"name": "admin", "port": 9090}, {"name": "metrics", "port": 3000}]
Required by (none)
Used by network:proxy
Change class in-place
Apply mode reconcile

About the field. Each entry is { name: , port: <1-65535> }; the FQDN is .. Each route gets its own Caddy handler keyed by 'TAPPaaS: #'. Adding an entry publishes it on the next install/update; removing one tears its route down.

Why this change class. The extra hostnames a single VM publishes. Adding or removing an entry creates or prunes that route live; the primary route and the module itself are untouched.