# ============================================ # UpSnap - Wake on LAN Web App # ============================================ # https://github.com/seriousm4x/UpSnap # Image: ghcr.io/seriousm4x/upsnap # # Access: https://upsnap.dooplex.hu (Authentik OIDC login) # https://upsnap.home (internal) # # IMPORTANT: UpSnap needs hostNetwork to send magic packets (WoL) # on the local LAN. This means it binds directly to the host's # network stack on port 8090. # # SSO Setup (Native OIDC via PocketBase): # UpSnap uses PocketBase under the hood, which supports OIDC natively. # After first deployment: # 1. Open https://upsnap.dooplex.hu/_/#/settings/auth-providers # 2. Select "OpenID Connect (oidc)" and fill in: # - Client ID: (from Authentik provider) # - Client Secret: (from Authentik provider) # - Auth URL: https://authentik.dooplex.hu/application/o/authorize/ # - Token URL: https://authentik.dooplex.hu/application/o/token/ # - User API URL: https://authentik.dooplex.hu/application/o/userinfo/ # 3. Create an OAuth2/OIDC Provider in Authentik: # - Name: UpSnap # - Authorization flow: default-provider-authorization-implicit-consent # - Redirect URI: https://upsnap.dooplex.hu/api/oauth2-redirect # - Scopes: openid email profile # 4. Create an Application in Authentik: # - Name: UpSnap # - Slug: upsnap # - Provider: UpSnap # # CAUTION: Do not enable/disable auth methods in PocketBase settings # (other than OIDC). This can cause DB migrations that conflict with updates. # # Post-deploy: # 1. Visit https://upsnap.dooplex.hu and create admin account # 2. Configure OIDC as above # 3. Add workstation device (IP + MAC address) # 4. Optionally configure shutdown command: # sshpass -p "$PASSWORD" ssh -o "StrictHostKeyChecking=no" user@IP "shutdown /s /t 0" # ============================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: upsnap-data namespace: admin-system labels: app.kubernetes.io/instance: upsnap app.kubernetes.io/name: upsnap recurring-job-group.longhorn.io/backup: enabled spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 1Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: upsnap namespace: admin-system labels: app.kubernetes.io/instance: upsnap app.kubernetes.io/name: upsnap app.kubernetes.io/version: "5" spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app.kubernetes.io/instance: upsnap app.kubernetes.io/name: upsnap template: metadata: labels: app.kubernetes.io/instance: upsnap app.kubernetes.io/name: upsnap app.kubernetes.io/version: "5" annotations: match-regex.version-checker.io/upsnap: '^\d+$' spec: # hostNetwork required for sending WoL magic packets on LAN hostNetwork: true dnsPolicy: ClusterFirstWithHostNet containers: - name: upsnap image: ghcr.io/seriousm4x/upsnap:5 imagePullPolicy: IfNotPresent env: - name: TZ value: Europe/Budapest - name: UPSNAP_INTERVAL value: "@every 30s" - name: UPSNAP_SCAN_RANGE value: "192.168.0.0/24" # Privileged ping (required for hostNetwork WoL) - name: UPSNAP_PING_PRIVILEGED value: "true" ports: - containerPort: 8090 name: http protocol: TCP livenessProbe: httpGet: path: /api/health port: http initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: path: /api/health port: http initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 resources: requests: cpu: 50m memory: 64Mi limits: cpu: 500m memory: 256Mi volumeMounts: - name: data mountPath: /app/pb_data volumes: - name: data persistentVolumeClaim: claimName: upsnap-data --- # Service still needed for ingress even with hostNetwork apiVersion: v1 kind: Service metadata: name: upsnap namespace: admin-system labels: app.kubernetes.io/instance: upsnap app.kubernetes.io/name: upsnap app.kubernetes.io/version: "5" spec: type: ClusterIP ports: - name: http port: 8090 protocol: TCP targetPort: http selector: app.kubernetes.io/instance: upsnap app.kubernetes.io/name: upsnap --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: upsnap namespace: admin-system labels: app.kubernetes.io/instance: upsnap app.kubernetes.io/name: upsnap app.kubernetes.io/version: "5" annotations: cert-manager.io/cluster-issuer: letsencrypt-prod external-dns.alpha.kubernetes.io/hostname: upsnap.dooplex.hu,upsnap.home nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/proxy-body-size: 10m nginx.ingress.kubernetes.io/configuration-snippet: | set $geo_allowed 0; if ($remote_addr ~ "^192\.168\.") { set $geo_allowed 1; } if ($remote_addr ~ "^10\.") { set $geo_allowed 1; } if ($geoip2_country_code = "HU") { set $geo_allowed 1; } if ($geo_allowed = 0) { return 403 "Access restricted to Hungary"; } spec: ingressClassName: nginx-internal rules: - host: upsnap.dooplex.hu http: paths: - path: / pathType: Prefix backend: service: name: upsnap port: number: 8090 - host: upsnap.home http: paths: - path: / pathType: Prefix backend: service: name: upsnap port: number: 8090 tls: - hosts: - upsnap.dooplex.hu secretName: upsnap-tls