The wlan-setup Deployment runs gitea.renner.uno/gitea_admin/wlan-setup
(Flux image policy wlan-setup) instead of nginx + njs; the ConfigMap
wlan-setup-config.yaml with nginx.conf, njs and the Windows .cmd is removed.
- Certificate wlan-setup-signing for wlan.renner.uno (PKCS#8), mounted at
/etc/wlan-signing (fsGroup 65534, mode 0440); the service reads it per
request, so renewals need no restart.
- Ingress wlan-setup-provisioning: /windows/profile/ without the authentik
gate, for Windows Settings fetching the signed provisioning XML.
- OAuth provider wlan-setup: redirect URI
https://wlan.renner.uno/windows/callback.
- docs/radius/dot1x.md: Go service and the Windows Passpoint flow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Android and Apple get Passpoint profiles with their own app password from
wlan.renner.uno; the manual Android steps with the account password are
removed. Windows and Linux keep their setup files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Renner UniFi" now runs WPA3 Enterprise without transition mode and
advertises Passpoint (realm and domain renner.uno, EAP-TTLS/PAP), so the
Android profiles from wlan.renner.uno join it directly. The table row for
the deleted "Renner Test" WLAN is replaced; the Windows manual setup uses
WPA3-Enterprise.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New app passwords start with 29 days (below the 30-day API cap, so no
group attribute is needed). The expression policy dot1x-app-password-renew,
re-evaluated on the dot1x-login binding, renews the app password that
TokenBackend matched to 60 days on each 802.1X login (at most one write
per day; always passes, failure_result true). authentik rejects expired
app passwords and deletes them in clean_expired_models (every 5 min).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wlan.renner.uno signs the user in through the new authentik OAuth2
application wlan-setup (confidential, scope goauthentik.io/api). The
callback exchanges the code (client_secret_basic), creates an app password
with the user's own access token (10 years) and returns the Passpoint
profile carrying it in the response to the user's GET. The page asks for
no password and stores nothing; deleting the app password in authentik
removes the device.
- dot1x-password stage also accepts app passwords (TokenBackend).
- Client secret: ESO Password generator wlan-setup-oauth, read by the
authentik worker (blueprint) and by wlan-setup.
- authentik calls go through an internal nginx location; headers come
from $arg_* because subrequests share the parent's variable cache.
- Reloader annotations on the wlan-setup Deployment metadata.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Android starts its Passpoint installer only for a profile fetched with a
user-triggered GET and Content-Type application/x-wifi-config; a
browser-generated blob does not qualify. The page now POSTs the password to
/android/prepare, where njs builds the profile and stores it in a shared
dict (120 s, bound to the caller's username) under a random token; the
link /android/profile/<token> delivers it once.
AAAServerTrustedNames moves under Extension/Android, the only place
Android's PpsMoParser accepts it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Android section takes the password, builds a Passpoint R1 profile
(application/x-wifi-config: PPS MO with HomeSP FQDN and realm renner.uno,
EAP-TTLS with inner PAP, AAA server name radius.renner.uno, ISRG Root X1 as
trust anchor) in the browser and hands it to Android as a blob. The password
is not sent to any server.
Matches WLANs that advertise Hotspot 2.0 with domain and NAI realm
renner.uno.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nginx behind the Authentik gate (any user, public) serving:
- Apple profile (TTLS/PAP, outer identity anonymous, trusted server name
radius.renner.uno) with the caller's username from X-authentik-username,
- a Windows .cmd that imports the WLAN profile via netsh (TTLS/PAP, server
name radius.renner.uno, trust anchor ISRG Root X1),
- the Linux nmcli command.
No file carries a password. Usernames outside [A-Za-z0-9._@+-] are left
blank instead of being put into a generated file.
The Renner Test profile is removed; that SSID no longer exists.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The UDM RADIUS rejects the pod CIDR as an unknown client; it accepts
10.2.11.0/24. FreeRADIUS pods get net1 on VLAN 11 "(11) RADIUS" and the
udm home server moves to 10.2.11.1.
- Talos k8s-{1,2,3}: VLANConfig radius0 (VLAN 11 on uplink), no
addresses, IPv6 disabled on the host link.
- Cilium bpf.vlanBypass gains 11: radius0 is address-less like ens19, so
its tagged frames meet the VLAN filter on uplink (#592).
- NAD freeradius-udm: macvlan on radius0, DHCP IPAM requesting only
subnet-mask (skipDefault), so the lease has no router and net1 holds
only the connected /24. No sbr: it moves that route into a source
table, and the unbound proxy socket would then reach the UDM via eth0
from the pod IP. tuning disables IPv6 on net1 (VLAN 11 sends RAs).
- NAS listeners bound to eth0, so nothing listens on net1.
- CNP freeradius-udm-egress removed: net1 traffic bypasses Cilium.
- Harness: FreeRADIUS interfaces named eth0/net1 explicitly; Docker
attaches networks in no fixed order, and the eth0 bind exposed it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Outer identity anonymous[@realm] (any case) keeps the local EAP-TTLS ->
authentik path. Any other outer identity is a UniFi Endpoint account: the
outer server proxies every EAP round to new home server udm (10.2.47.1:1812,
UDM_RADIUS_SECRET) without local EAP processing; post-proxy/post-auth leave
UDM replies untouched. Endpoint account names look like ordinary usernames,
so routing keys on the anonymous identity, not a name pattern.
home_server udm: response_window 5 < proxy_dedup_window 10,
require_message_authenticator yes (RFC 3579, EAP replies), status_check
request with a user name that cannot exist.
CNP freeradius-udm-egress allows only 10.2.47.1/32 UDP 1812.
Harness: mock_udm.py on a second internal bridge at the udm address from
proxy.conf. Asserts both EAP rounds (State included) reach it, its Accept
reaches the NAS with Tunnel-* VLAN 200 and MS-MPPE keys intact, its Reject
passes, and anonymous logins and accounting never reach it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Home server: response_window 5, status_check = request with a user that
does not exist in authentik (always rejected), check_interval 6,
check_timeout 4, num_answers_to_alive 3; revive_interval dropped. With
status_check = none the blind revive gave 7-8 s in some runs and no
recovery within 120 s in others.
tests/radius/run.sh: recovery case stalls the mock outpost until the
home server is marked dead, resumes it and asserts a login succeeds
within 20 s. It fails intermittently: radiusd stops answering
(liveness probe fails) after late replies arrive for requests it already
failed. Diagnosis pending.
Docs: secret is the only guard on the FreeRADIUS -> outpost hop; outpost
Service name resolved at startup. Spec: VLAN 10 is dual-stack
(fd02:10::/64). helmrelease comment: missing !Env resolves to the
default, no KeyError.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FreeRADIUS listens on :: for 1812/1813 and accepts aps6 fd02:10::/64 and
test6 fd02:50::/64 with the same secrets as their IPv4 entries; the NAS
CNP admits both prefixes. The harness adds IPv6 cases on an isolated
dual-stack bridge.
Windows 11 setup requires server validation for radius.renner.uno and
never Windows sign-in credentials. The Apple profile uses EncryptionType
Any and OuterIdentity anonymous. dot1x.md marks the test/test6 clients
and their CNP CIDRs as test-phase only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Server pods (SSO) no longer depend on radius-secrets. Worker reloads on
radius-secrets changes. Docs: worker-only secret, unquoted integer
dot1x_vlan, FreeRADIUS VLAN contract.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blueprint dot1x-radius.yaml: non-interactive flow dot1x-authentication-flow,
policy dot1x-has-vlan, RADIUS mapping dot1x-vlan (lowest dot1x_vlan group
attribute; RFC 3580 Tunnel-* by raw code plus Cisco-AV-Pair fallback),
provider and outpost "802.1X Radius" (2 replicas, ClusterIP), client
networks = cluster pod CIDRs. Shared secret from radius-secrets via env
DOT1X_OUTPOST_SECRET.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>