provisioning-catalog/components/wireguard/nickel/contracts.ncl

96 lines
3.5 KiB
Text

let _concerns_lib = import "schemas/lib/concerns.ncl" in
{
Wireguard = {
name | String | default = "wireguard",
version | String,
image | String,
namespace | String | default = "vpn",
mode | [| 'cluster |] | default = 'cluster,
node | String,
fip_name | String,
lb_ipam_ip | String | default = "",
vpn_subnet | String,
server_ip | String,
wg_default_address
| String
| std.contract.from_predicate (fun s => std.string.is_match "^[0-9]+\\.[0-9]+\\.[0-9]+\\.x$" s)
| doc m%"
Client IP pattern with literal `x` placeholder that wg-easy replaces per new peer
(e.g., "10.200.0.x" → peers get 10.200.0.2, 10.200.0.3, ...). Format enforced
by predicate: must match `^[0-9]+\.[0-9]+\.[0-9]+\.x$`. The first three octets
should align with vpn_subnet (soft constraint — Nickel cannot cross-reference
sibling fields in a single-field contract; misalignment manifests as peers
unable to receive routable IPs).
"%
| default = "10.200.0.x",
listen_port | Number | default = 51820,
ui_port | Number | default = 51821,
dns | Array String | default = ["1.1.1.1", "8.8.8.8"],
mtu | Number | default = 1420,
keepalive | Number | default = 25,
host_network | Bool
| doc m%"
Run the wireguard Pod with spec.hostNetwork: true, bypassing Cilium CNI.
When true: the deployment template emits hostNetwork=true; the
lb-ipam-pool and service-vpn templates render empty (no CiliumLBIPPool
nor LoadBalancer Service is created). FIP binding moves to fip_controller
(declared separately in infra). lb_ipam_ip remains the advertised
WG_HOST endpoint in the configmap-env.
"%
| default = false,
client_allowed_ips | Array String | default = [],
wg_post_up_extra
| Array String
| doc m%"
Extra iptables/nft commands appended to wg-easy's default WG_POST_UP. Use this
to add MASQUERADE/forward rules for paths the default (`-o eth0`) doesn't
cover — most commonly the private/wuwei interface when running with
host_network=true (e.g., on Hetzner enp7s0). The strings are joined with `;`
and passed via WG_POST_UP env. wg-easy interpolates `%i` as the WG interface name.
"%
| default = [],
wg_post_down_extra
| Array String
| doc m%"
Mirror of wg_post_up_extra for tear-down. Each entry should `iptables -D ...` an
entry from wg_post_up_extra so the rule set is balanced. Passed via WG_POST_DOWN.
"%
| default = [],
kubeconfig | String | optional,
requires | {
storage | { size | String, persistent | Bool } | optional,
storage_class | String | optional,
ports | Array {
port | Number,
protocol | String | default = "UDP",
exposure | [| 'public, 'private, 'internal |] | default = 'public,
} | default = [],
credentials | Array String | default = [],
} | default = {},
provides | {
service | String | optional,
ports | Array Number | default = [],
} | default = {},
operations | {
install | Bool | default = true,
update | Bool | default = false,
delete | Bool | default = false,
restart | Bool | default = false,
health | Bool | default = false,
} | default = {},
# ServiceConcerns umbrella (ADR-008). VPN gateway — config in git, peers stateless.
concerns | _concerns_lib.ServiceConcerns | optional,
..
},
}