From 454d5795b0abd8903faed52efd19dd835396a6ed Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Mon, 2 Feb 2026 15:38:33 -0800 Subject: [PATCH 1/4] Expand homepage widgets and info panels Add info widgets: - Greeting: "Welcome to Blue Mops" - DateTime with long date and short time format Add service widgets with available credentials: - Miniflux: RSS reader stats via API key - Grafana: Dashboard/datasource stats via username/password Add TODO comments for widgets needing additional setup: - Forgejo: needs API token created - Caddy: needs admin API enabled (currently off) - UniFi: needs controller setup - Glances: needs Glances deployed - Navidrome: needs user/token/salt for Subsonic API - Transmission: needs username/password configured - Immich: needs API key from account settings Also add ArgoCD to bookmarks section. Co-Authored-By: Claude Opus 4.5 --- .../grafana-config/ingress-tailscale.yaml | 4 ++ .../homepage/external-secret-grafana.yaml | 24 ++++++++ .../homepage/external-secret-miniflux.yaml | 20 +++++++ argocd/manifests/homepage/values.yaml | 56 ++++++++++++++++++- .../manifests/immich/ingress-tailscale.yaml | 6 ++ .../manifests/miniflux/ingress-tailscale.yaml | 3 + .../navidrome/ingress-tailscale.yaml | 7 +++ .../manifests/torrent/ingress-tailscale.yaml | 6 ++ 8 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 argocd/manifests/homepage/external-secret-grafana.yaml create mode 100644 argocd/manifests/homepage/external-secret-miniflux.yaml diff --git a/argocd/manifests/grafana-config/ingress-tailscale.yaml b/argocd/manifests/grafana-config/ingress-tailscale.yaml index 23603ba..905991c 100644 --- a/argocd/manifests/grafana-config/ingress-tailscale.yaml +++ b/argocd/manifests/grafana-config/ingress-tailscale.yaml @@ -16,6 +16,10 @@ metadata: gethomepage.dev/description: "Metrics dashboards" gethomepage.dev/href: "https://grafana.ops.eblu.me" gethomepage.dev/pod-selector: "app.kubernetes.io/name=grafana" + gethomepage.dev/widget.type: "grafana" + gethomepage.dev/widget.url: "https://grafana.ops.eblu.me" + gethomepage.dev/widget.username: "{{HOMEPAGE_VAR_GRAFANA_USERNAME}}" + gethomepage.dev/widget.password: "{{HOMEPAGE_VAR_GRAFANA_PASSWORD}}" spec: ingressClassName: tailscale defaultBackend: diff --git a/argocd/manifests/homepage/external-secret-grafana.yaml b/argocd/manifests/homepage/external-secret-grafana.yaml new file mode 100644 index 0000000..ed455a4 --- /dev/null +++ b/argocd/manifests/homepage/external-secret-grafana.yaml @@ -0,0 +1,24 @@ +# ExternalSecret for Grafana credentials +# Used by Homepage Grafana widget +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: homepage-grafana + namespace: homepage +spec: + refreshInterval: 1h + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-blumeops + target: + name: homepage-grafana + creationPolicy: Owner + data: + - secretKey: username + remoteRef: + key: Grafana (blumeops) + property: username + - secretKey: password + remoteRef: + key: Grafana (blumeops) + property: password diff --git a/argocd/manifests/homepage/external-secret-miniflux.yaml b/argocd/manifests/homepage/external-secret-miniflux.yaml new file mode 100644 index 0000000..f3f0780 --- /dev/null +++ b/argocd/manifests/homepage/external-secret-miniflux.yaml @@ -0,0 +1,20 @@ +# ExternalSecret for Miniflux API key +# Used by Homepage Miniflux widget +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: homepage-miniflux + namespace: homepage +spec: + refreshInterval: 1h + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-blumeops + target: + name: homepage-miniflux + creationPolicy: Owner + data: + - secretKey: apikey + remoteRef: + key: miniflux + property: credential diff --git a/argocd/manifests/homepage/values.yaml b/argocd/manifests/homepage/values.yaml index 5e334f2..e80bf86 100644 --- a/argocd/manifests/homepage/values.yaml +++ b/argocd/manifests/homepage/values.yaml @@ -27,16 +27,35 @@ ingress: env: - name: HOMEPAGE_ALLOWED_HOSTS value: "go.tail8d86e.ts.net,go.ops.eblu.me" + # Weather widget - name: HOMEPAGE_VAR_OPENWEATHERMAP_API_KEY valueFrom: secretKeyRef: name: homepage-openweathermap key: apikey + # Jellyfin widget - name: HOMEPAGE_VAR_JELLYFIN_API_KEY valueFrom: secretKeyRef: name: homepage-jellyfin key: apikey + # Miniflux widget + - name: HOMEPAGE_VAR_MINIFLUX_API_KEY + valueFrom: + secretKeyRef: + name: homepage-miniflux + key: apikey + # Grafana widget + - name: HOMEPAGE_VAR_GRAFANA_USERNAME + valueFrom: + secretKeyRef: + name: homepage-grafana + key: username + - name: HOMEPAGE_VAR_GRAFANA_PASSWORD + valueFrom: + secretKeyRef: + name: homepage-grafana + key: password config: # Host services (non-k8s, on indri or LAN) @@ -46,6 +65,11 @@ config: href: https://forge.ops.eblu.me icon: forgejo description: Git forge + # TODO: Add Forgejo widget when API token is created + # widget: + # type: gitea + # url: https://forge.ops.eblu.me + # key: "{{HOMEPAGE_VAR_FORGEJO_API_KEY}}" - Registry: href: https://registry.ops.eblu.me icon: docker @@ -92,6 +116,14 @@ config: key: "{{HOMEPAGE_VAR_JELLYFIN_API_KEY}}" enableBlocks: true enableNowPlaying: true + # TODO: Add Caddy widget when admin API is enabled (currently admin off) + # - Caddy: + # href: https://indri.tail8d86e.ts.net + # icon: caddy + # description: Reverse proxy + # widget: + # type: caddy + # url: http://indri.tail8d86e.ts.net:2019 # External bookmarks bookmarks: @@ -105,10 +137,21 @@ config: - Pulumi: - href: https://app.pulumi.com/eblume/blumeops-tailnet icon: pulumi + - ArgoCD: + - href: https://argocd.ops.eblu.me + icon: argocd - # Widgets on the page - # Note: Kubernetes widget disabled - requires metrics-server + # Widgets on the page (info bar at top) widgets: + - greeting: + text_size: xl + text: Welcome to Blue Mops + - datetime: + text_size: lg + format: + dateStyle: long + timeStyle: short + hour12: true - openweathermap: label: Camano latitude: 48.18235 @@ -117,6 +160,15 @@ config: provider: openweathermap apiKey: "{{HOMEPAGE_VAR_OPENWEATHERMAP_API_KEY}}" cache: 15 + # TODO: Add UniFi widget when controller is set up + # - unifi_console: + # url: https://192.168.1.1 + # username: homepage + # password: "{{HOMEPAGE_VAR_UNIFI_PASSWORD}}" + # TODO: Add Glances widget when Glances is deployed + # - glances: + # url: http://indri.tail8d86e.ts.net:61208 + # metric: cpu # Kubernetes autodiscovery kubernetes: diff --git a/argocd/manifests/immich/ingress-tailscale.yaml b/argocd/manifests/immich/ingress-tailscale.yaml index 31c7858..4b3faba 100644 --- a/argocd/manifests/immich/ingress-tailscale.yaml +++ b/argocd/manifests/immich/ingress-tailscale.yaml @@ -15,6 +15,12 @@ metadata: gethomepage.dev/description: "Photo management" gethomepage.dev/href: "https://photos.ops.eblu.me" gethomepage.dev/pod-selector: "app.kubernetes.io/name=server" + # TODO: Add Immich widget - requires API key from Account Settings > API Keys + # See: https://gethomepage.dev/widgets/services/immich/ + # gethomepage.dev/widget.type: "immich" + # gethomepage.dev/widget.url: "https://photos.ops.eblu.me" + # gethomepage.dev/widget.key: "{{HOMEPAGE_VAR_IMMICH_API_KEY}}" + # gethomepage.dev/widget.version: "2" spec: ingressClassName: tailscale rules: diff --git a/argocd/manifests/miniflux/ingress-tailscale.yaml b/argocd/manifests/miniflux/ingress-tailscale.yaml index ad7de3f..96c9162 100644 --- a/argocd/manifests/miniflux/ingress-tailscale.yaml +++ b/argocd/manifests/miniflux/ingress-tailscale.yaml @@ -12,6 +12,9 @@ metadata: gethomepage.dev/description: "RSS reader" gethomepage.dev/href: "https://feed.ops.eblu.me" gethomepage.dev/pod-selector: "app=miniflux" + gethomepage.dev/widget.type: "miniflux" + gethomepage.dev/widget.url: "https://feed.ops.eblu.me" + gethomepage.dev/widget.key: "{{HOMEPAGE_VAR_MINIFLUX_API_KEY}}" spec: ingressClassName: tailscale defaultBackend: diff --git a/argocd/manifests/navidrome/ingress-tailscale.yaml b/argocd/manifests/navidrome/ingress-tailscale.yaml index d834fd0..8cdf90e 100644 --- a/argocd/manifests/navidrome/ingress-tailscale.yaml +++ b/argocd/manifests/navidrome/ingress-tailscale.yaml @@ -13,6 +13,13 @@ metadata: gethomepage.dev/description: "Music streaming server" gethomepage.dev/href: "https://dj.ops.eblu.me" gethomepage.dev/pod-selector: "app=navidrome" + # TODO: Add Navidrome widget - requires user, token (md5(password+salt)), salt + # See: https://gethomepage.dev/widgets/services/navidrome/ + # gethomepage.dev/widget.type: "navidrome" + # gethomepage.dev/widget.url: "https://dj.ops.eblu.me" + # gethomepage.dev/widget.user: "{{HOMEPAGE_VAR_NAVIDROME_USER}}" + # gethomepage.dev/widget.token: "{{HOMEPAGE_VAR_NAVIDROME_TOKEN}}" + # gethomepage.dev/widget.salt: "{{HOMEPAGE_VAR_NAVIDROME_SALT}}" spec: ingressClassName: tailscale defaultBackend: diff --git a/argocd/manifests/torrent/ingress-tailscale.yaml b/argocd/manifests/torrent/ingress-tailscale.yaml index ac77e9c..175b0f6 100644 --- a/argocd/manifests/torrent/ingress-tailscale.yaml +++ b/argocd/manifests/torrent/ingress-tailscale.yaml @@ -13,6 +13,12 @@ metadata: gethomepage.dev/description: "Torrent client" gethomepage.dev/href: "https://torrent.ops.eblu.me" gethomepage.dev/pod-selector: "app=transmission" + # TODO: Add Transmission widget - requires username/password setup in Transmission + # See: https://gethomepage.dev/widgets/services/transmission/ + # gethomepage.dev/widget.type: "transmission" + # gethomepage.dev/widget.url: "https://torrent.ops.eblu.me" + # gethomepage.dev/widget.username: "{{HOMEPAGE_VAR_TRANSMISSION_USER}}" + # gethomepage.dev/widget.password: "{{HOMEPAGE_VAR_TRANSMISSION_PASSWORD}}" spec: ingressClassName: tailscale defaultBackend: -- 2.50.1 (Apple Git-155) From 40e0a6aacc5c11ffdc90ec6929e6a4c77e785152 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Mon, 2 Feb 2026 15:51:25 -0800 Subject: [PATCH 2/4] Fix miniflux external secret property name Use eblume-api-key field instead of credential (which was empty). Co-Authored-By: Claude Opus 4.5 --- argocd/manifests/homepage/external-secret-miniflux.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argocd/manifests/homepage/external-secret-miniflux.yaml b/argocd/manifests/homepage/external-secret-miniflux.yaml index f3f0780..7105ba9 100644 --- a/argocd/manifests/homepage/external-secret-miniflux.yaml +++ b/argocd/manifests/homepage/external-secret-miniflux.yaml @@ -17,4 +17,4 @@ spec: - secretKey: apikey remoteRef: key: miniflux - property: credential + property: eblume-api-key -- 2.50.1 (Apple Git-155) From e61fb148e68bc55ce8bff7d03c491fcd8f279b65 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Mon, 2 Feb 2026 15:56:18 -0800 Subject: [PATCH 3/4] Add Forgejo widget to homepage - Create external secret for Forgejo API key - Enable Forgejo widget using gitea widget type Co-Authored-By: Claude Opus 4.5 --- .../homepage/external-secret-forgejo.yaml | 20 +++++++++++++++++++ argocd/manifests/homepage/values.yaml | 15 +++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 argocd/manifests/homepage/external-secret-forgejo.yaml diff --git a/argocd/manifests/homepage/external-secret-forgejo.yaml b/argocd/manifests/homepage/external-secret-forgejo.yaml new file mode 100644 index 0000000..8c771ab --- /dev/null +++ b/argocd/manifests/homepage/external-secret-forgejo.yaml @@ -0,0 +1,20 @@ +# ExternalSecret for Forgejo API key +# Used by Homepage Forgejo widget (via Gitea widget type) +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: homepage-forgejo + namespace: homepage +spec: + refreshInterval: 1h + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-blumeops + target: + name: homepage-forgejo + creationPolicy: Owner + data: + - secretKey: apikey + remoteRef: + key: Forgejo Secrets + property: eblume-homepage-access-token diff --git a/argocd/manifests/homepage/values.yaml b/argocd/manifests/homepage/values.yaml index e80bf86..489236a 100644 --- a/argocd/manifests/homepage/values.yaml +++ b/argocd/manifests/homepage/values.yaml @@ -56,6 +56,12 @@ env: secretKeyRef: name: homepage-grafana key: password + # Forgejo widget + - name: HOMEPAGE_VAR_FORGEJO_API_KEY + valueFrom: + secretKeyRef: + name: homepage-forgejo + key: apikey config: # Host services (non-k8s, on indri or LAN) @@ -65,11 +71,10 @@ config: href: https://forge.ops.eblu.me icon: forgejo description: Git forge - # TODO: Add Forgejo widget when API token is created - # widget: - # type: gitea - # url: https://forge.ops.eblu.me - # key: "{{HOMEPAGE_VAR_FORGEJO_API_KEY}}" + widget: + type: gitea + url: https://forge.ops.eblu.me + key: "{{HOMEPAGE_VAR_FORGEJO_API_KEY}}" - Registry: href: https://registry.ops.eblu.me icon: docker -- 2.50.1 (Apple Git-155) From ac602eb9caae9b18dc33b3dd7e51be0c246921cc Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Mon, 2 Feb 2026 16:07:17 -0800 Subject: [PATCH 4/4] Add Navidrome widget to homepage - Create external secret for Navidrome Subsonic API credentials - Add environment variables for user, salt, and token - Enable widget annotations on navidrome ingress Co-Authored-By: Claude Opus 4.5 --- .../homepage/external-secret-navidrome.yaml | 28 +++++++++++++++++++ argocd/manifests/homepage/values.yaml | 16 +++++++++++ .../navidrome/ingress-tailscale.yaml | 12 ++++---- 3 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 argocd/manifests/homepage/external-secret-navidrome.yaml diff --git a/argocd/manifests/homepage/external-secret-navidrome.yaml b/argocd/manifests/homepage/external-secret-navidrome.yaml new file mode 100644 index 0000000..0bcd727 --- /dev/null +++ b/argocd/manifests/homepage/external-secret-navidrome.yaml @@ -0,0 +1,28 @@ +# ExternalSecret for Navidrome Subsonic API credentials +# Used by Homepage Navidrome widget +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: homepage-navidrome + namespace: homepage +spec: + refreshInterval: 1h + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-blumeops + target: + name: homepage-navidrome + creationPolicy: Owner + data: + - secretKey: user + remoteRef: + key: dj (navidrome) + property: username + - secretKey: salt + remoteRef: + key: dj (navidrome) + property: salt + - secretKey: token + remoteRef: + key: dj (navidrome) + property: salted_pw diff --git a/argocd/manifests/homepage/values.yaml b/argocd/manifests/homepage/values.yaml index 489236a..6d858fe 100644 --- a/argocd/manifests/homepage/values.yaml +++ b/argocd/manifests/homepage/values.yaml @@ -62,6 +62,22 @@ env: secretKeyRef: name: homepage-forgejo key: apikey + # Navidrome widget + - name: HOMEPAGE_VAR_NAVIDROME_USER + valueFrom: + secretKeyRef: + name: homepage-navidrome + key: user + - name: HOMEPAGE_VAR_NAVIDROME_SALT + valueFrom: + secretKeyRef: + name: homepage-navidrome + key: salt + - name: HOMEPAGE_VAR_NAVIDROME_TOKEN + valueFrom: + secretKeyRef: + name: homepage-navidrome + key: token config: # Host services (non-k8s, on indri or LAN) diff --git a/argocd/manifests/navidrome/ingress-tailscale.yaml b/argocd/manifests/navidrome/ingress-tailscale.yaml index 8cdf90e..21ddfef 100644 --- a/argocd/manifests/navidrome/ingress-tailscale.yaml +++ b/argocd/manifests/navidrome/ingress-tailscale.yaml @@ -13,13 +13,11 @@ metadata: gethomepage.dev/description: "Music streaming server" gethomepage.dev/href: "https://dj.ops.eblu.me" gethomepage.dev/pod-selector: "app=navidrome" - # TODO: Add Navidrome widget - requires user, token (md5(password+salt)), salt - # See: https://gethomepage.dev/widgets/services/navidrome/ - # gethomepage.dev/widget.type: "navidrome" - # gethomepage.dev/widget.url: "https://dj.ops.eblu.me" - # gethomepage.dev/widget.user: "{{HOMEPAGE_VAR_NAVIDROME_USER}}" - # gethomepage.dev/widget.token: "{{HOMEPAGE_VAR_NAVIDROME_TOKEN}}" - # gethomepage.dev/widget.salt: "{{HOMEPAGE_VAR_NAVIDROME_SALT}}" + gethomepage.dev/widget.type: "navidrome" + gethomepage.dev/widget.url: "https://dj.ops.eblu.me" + gethomepage.dev/widget.user: "{{HOMEPAGE_VAR_NAVIDROME_USER}}" + gethomepage.dev/widget.token: "{{HOMEPAGE_VAR_NAVIDROME_TOKEN}}" + gethomepage.dev/widget.salt: "{{HOMEPAGE_VAR_NAVIDROME_SALT}}" spec: ingressClassName: tailscale defaultBackend: -- 2.50.1 (Apple Git-155)