diff --git a/kubernetes/apps/authentik/blueprints-configmap.yaml b/kubernetes/apps/authentik/blueprints-configmap.yaml
index 9fdef09b..684f6b43 100644
--- a/kubernetes/apps/authentik/blueprints-configmap.yaml
+++ b/kubernetes/apps/authentik/blueprints-configmap.yaml
@@ -103,6 +103,16 @@ data:
slug: paperless-proxy
state: absent
+ # syncthing.paperless.renner.uno is gated by authentik-gate-sync
+ # (kubernetes/apps/paperless/syncthing.yaml), which admits this group.
+ # Members are managed in Authentik.
+ - model: authentik_core.group
+ identifiers:
+ name: Paperless Admins
+ state: present
+ attrs:
+ is_superuser: false
+
# vscode.home.renner.uno is gated by authentik-gate-sync
# (kubernetes/apps/home-assistant/vscode-ingress.yaml), which admits this
# group. Members are managed in Authentik.
diff --git a/kubernetes/apps/monitoring-rules/probes-dns.yaml b/kubernetes/apps/monitoring-rules/probes-dns.yaml
index 13a316bc..0ea94d8a 100644
--- a/kubernetes/apps/monitoring-rules/probes-dns.yaml
+++ b/kubernetes/apps/monitoring-rules/probes-dns.yaml
@@ -142,4 +142,4 @@ spec:
- "[fd02:47::1]:53"
- "10.2.47.1:53"
labels:
- dns_name: syncthing.paperless.renner.uno
+ dns_name: sync.paperless.renner.uno
diff --git a/kubernetes/apps/monitoring/helmrelease-blackbox-exporter.yaml b/kubernetes/apps/monitoring/helmrelease-blackbox-exporter.yaml
index efafa406..c33b1548 100644
--- a/kubernetes/apps/monitoring/helmrelease-blackbox-exporter.yaml
+++ b/kubernetes/apps/monitoring/helmrelease-blackbox-exporter.yaml
@@ -136,7 +136,7 @@ spec:
prober: dns
timeout: 5s
dns:
- query_name: syncthing.paperless.renner.uno
+ query_name: sync.paperless.renner.uno
query_type: A
valid_rcodes: [NOERROR]
validate_answer_rrs:
diff --git a/kubernetes/apps/paperless/kumamonitors.yaml b/kubernetes/apps/paperless/kumamonitors.yaml
index a78ce801..dc87bbea 100644
--- a/kubernetes/apps/paperless/kumamonitors.yaml
+++ b/kubernetes/apps/paperless/kumamonitors.yaml
@@ -138,3 +138,25 @@ spec:
expiryNotification: true
keyword:
keyword: "
authentik"
+---
+apiVersion: uptime.renner.uno/v1alpha1
+kind: KumaMonitor
+metadata:
+ name: syncthing-ui-gate
+ namespace: paperless
+spec:
+ type: keyword
+ displayName: Syncthing Login
+ parentRef:
+ name: docs
+ interval: 60
+ retryInterval: 60
+ maxRetries: 1
+ timeout: 20
+ http:
+ # behind the Authentik gate; asserts the login page the redirect chain ends on
+ url: https://syncthing.paperless.renner.uno/
+ acceptedStatusCodes: ["200-299"]
+ expiryNotification: true
+ keyword:
+ keyword: "authentik"
diff --git a/kubernetes/apps/paperless/syncthing.yaml b/kubernetes/apps/paperless/syncthing.yaml
index 08c30e98..a518f2c2 100644
--- a/kubernetes/apps/paperless/syncthing.yaml
+++ b/kubernetes/apps/paperless/syncthing.yaml
@@ -52,11 +52,8 @@ spec:
- name: syncthing
image: syncthing/syncthing:2.1.7@sha256:2b71da7c0d0a91a6ae5285ad079226fecc0a365d08b27720e1f7037b018f7546
env:
- # UI bind: any-interface so the ClusterIP Service can reach
- # it. Network exposure is gated by the absence of an Ingress
- # and the namespace default-deny CNP — set a UI password in
- # the Syncthing UI on first port-forward access before
- # publishing it.
+ # UI bind: any-interface so the ClusterIP Service can reach it.
+ # External access goes through the syncthing-ui Ingress only.
- name: STGUIADDRESS
value: "0.0.0.0:8384"
- name: PUID
@@ -115,10 +112,6 @@ spec:
persistentVolumeClaim:
claimName: paperless-consume
---
-# UI Service — ClusterIP only. Access via `kubectl -n paperless
-# port-forward svc/syncthing-ui 8384:8384` for first-time setup
-# (set admin password). Future Ingress + Authentik gate is a
-# separate change once auth is configured.
apiVersion: v1
kind: Service
metadata:
@@ -132,6 +125,36 @@ spec:
port: 8384
targetPort: ui
---
+# LAN-only UI: Paperless Admins through the Authentik gate.
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: syncthing-ui
+ namespace: paperless
+ labels:
+ dns.renner.uno/internal: "true"
+ annotations:
+ traefik.ingress.kubernetes.io/router.middlewares: authentik-gate@kubernetescrd
+ cert-manager.io/cluster-issuer: letsencrypt-cluster
+ auth.renner.uno/group: Paperless Admins
+spec:
+ ingressClassName: traefik
+ rules:
+ - host: syncthing.paperless.renner.uno
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: syncthing-ui
+ port:
+ number: 8384
+ tls:
+ - secretName: syncthing-ui-tls
+ hosts:
+ - syncthing.paperless.renner.uno
+---
# Sync ports — LAN-reachable LoadBalancer. Peers (phones, laptops)
# connect here for the dropbox sync. external-dns publishes the
# hostname into UniFi DNS only (no cloudflare label); off-LAN peers
@@ -146,7 +169,7 @@ metadata:
dns.renner.uno/internal: "true"
annotations:
io.cilium/lb-ipam-ips: "10.2.99.85,fd99::85"
- external-dns.kubernetes.io/hostname: syncthing.paperless.renner.uno
+ external-dns.kubernetes.io/hostname: sync.paperless.renner.uno
spec:
type: LoadBalancer
externalTrafficPolicy: Local
diff --git a/kubernetes/infrastructure/network-policies/paperless-ns.yaml b/kubernetes/infrastructure/network-policies/paperless-ns.yaml
index 31b5b94b..7cde08a4 100644
--- a/kubernetes/infrastructure/network-policies/paperless-ns.yaml
+++ b/kubernetes/infrastructure/network-policies/paperless-ns.yaml
@@ -145,8 +145,8 @@ spec:
# Allow Syncthing peer-to-peer sync from the LAN/world.
# - 22000 TCP+QUIC: actual sync traffic between peers.
# - 21027 UDP: local-discovery broadcast packets from peers on the LAN.
-# UI (8384) is intentionally NOT listed — accessed via port-forward
-# until an Ingress + Authentik gate is added.
+# UI (8384) is intentionally NOT listed — authentik-gate-sync generates the
+# CNP syncthing-ui-gate that admits traefik.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata: