Add kustomize images: and configMapGenerator: across services (#264)
## Summary - Move hardcoded image tags to kustomization.yaml `images:` transformer across **22 services** — image names in manifests become version-agnostic templates, with tags centralized in one place per service - Replace hand-written ConfigMap manifests with `configMapGenerator:` in **12 services** — config data extracted to standalone files, generated ConfigMaps include content hashes that trigger automatic pod rollouts on changes - Create new `kustomization.yaml` for **forgejo-runner** and **nvidia-device-plugin** (switches ArgoCD from directory mode to kustomize mode, rendered output identical) ### Services modified **Images only (8):** cv, devpi, docs, kube-state-metrics, miniflux, navidrome, teslamate, torrent **Images + configMapGenerator (10):** alloy-k8s, forgejo-runner, frigate, grafana, homepage, kiwix, loki, mosquitto, ntfy, prometheus **Images only, no configMapGenerator (4):** authentik (skip blueprints — special YAML tags), tailscale-operator-base (Deployment only, CRD image fields left as-is) **Skipped entirely (6):** argocd (remote upstream), databases (no image fields), external-secrets, grafana-config (cross-kustomization dashboards), immich (Helm-managed), 1password-connect/cloudnative-pg (no kustomization.yaml) ### What changes at deploy time - **images:** — no functional diff, `kustomize build` produces identical output with tags - **configMapGenerator:** — ConfigMap names gain hash suffixes (e.g., `prometheus-config` → `prometheus-config-6f42fhctcb`) and all Deployment/StatefulSet/DaemonSet references are updated automatically. Pods will restart once per service on first sync due to the name change ## Test plan - [x] `kubectl kustomize` builds all 30 service directories successfully - [x] Image tags verified in rendered output for all modified services - [x] ConfigMap hash suffixes verified in rendered output - [x] ConfigMap references in Deployments/StatefulSets confirmed to use hashed names - [x] All pre-commit hooks pass (yamllint, shellcheck, prettier, etc.) - [ ] `argocd app diff` each service to confirm only expected ConfigMap name changes - [ ] Deploy from branch starting with a low-risk service (e.g., mosquitto) Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/264
This commit is contained in:
parent
86aeb60ec9
commit
9b44a8ec51
79 changed files with 956 additions and 905 deletions
169
argocd/manifests/alloy-k8s/config.alloy
Normal file
169
argocd/manifests/alloy-k8s/config.alloy
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
// Alloy k8s configuration - collects pod logs from all namespaces
|
||||
|
||||
// ============== K8S POD LOG DISCOVERY ==============
|
||||
|
||||
// Discover all pods in the cluster
|
||||
discovery.kubernetes "pods" {
|
||||
role = "pod"
|
||||
}
|
||||
|
||||
// Relabel to extract useful metadata
|
||||
discovery.relabel "pods" {
|
||||
targets = discovery.kubernetes.pods.targets
|
||||
|
||||
// Keep only running pods
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_phase"]
|
||||
regex = "Pending|Succeeded|Failed|Unknown"
|
||||
action = "drop"
|
||||
}
|
||||
|
||||
// Set namespace label
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_namespace"]
|
||||
target_label = "namespace"
|
||||
}
|
||||
|
||||
// Set pod name label
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_name"]
|
||||
target_label = "pod"
|
||||
}
|
||||
|
||||
// Set container name label
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_container_name"]
|
||||
target_label = "container"
|
||||
}
|
||||
|
||||
// Set app label from pod labels
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_label_app"]
|
||||
target_label = "app"
|
||||
}
|
||||
|
||||
// Fallback: use app.kubernetes.io/name if no app label
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"]
|
||||
target_label = "app"
|
||||
regex = "(.+)"
|
||||
action = "replace"
|
||||
}
|
||||
|
||||
// Set node name
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_node_name"]
|
||||
target_label = "node"
|
||||
}
|
||||
|
||||
// Build the log path for the pod container
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_uid", "__meta_kubernetes_pod_container_name"]
|
||||
target_label = "__path__"
|
||||
separator = "/"
|
||||
replacement = "/var/log/pods/*$1/$2/*.log"
|
||||
}
|
||||
}
|
||||
|
||||
// Tail pod logs
|
||||
loki.source.kubernetes "pods" {
|
||||
targets = discovery.relabel.pods.output
|
||||
forward_to = [loki.process.pods.receiver]
|
||||
}
|
||||
|
||||
// Process logs - parse JSON if present, add labels
|
||||
loki.process "pods" {
|
||||
forward_to = [loki.write.loki.receiver]
|
||||
|
||||
// Drop noisy deprecation warning from minikube storage-provisioner
|
||||
// See: https://github.com/kubernetes/minikube/issues/21009
|
||||
stage.drop {
|
||||
source = ""
|
||||
expression = "v1 Endpoints is deprecated"
|
||||
}
|
||||
|
||||
// Try to parse JSON logs (e.g., structured app logs)
|
||||
// Handle both "msg" (common) and "message" (zot) field names
|
||||
stage.json {
|
||||
expressions = {
|
||||
level = "level",
|
||||
msg = "msg",
|
||||
message = "message",
|
||||
time = "time",
|
||||
caller = "caller",
|
||||
repository = "repository",
|
||||
}
|
||||
}
|
||||
|
||||
// Drop JSON parsing error labels (non-JSON logs are fine, just won't have extracted fields)
|
||||
stage.label_drop {
|
||||
values = ["__error__", "__error_details__"]
|
||||
}
|
||||
|
||||
// Extract labels from parsed JSON data
|
||||
stage.labels {
|
||||
values = {
|
||||
level = "",
|
||||
caller = "",
|
||||
repository = "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write logs to Loki
|
||||
loki.write "loki" {
|
||||
endpoint {
|
||||
url = "http://loki.monitoring.svc.cluster.local:3100/loki/api/v1/push"
|
||||
}
|
||||
}
|
||||
|
||||
// ============== SERVICE HEALTH PROBES ==============
|
||||
|
||||
// Blackbox-style HTTP probes for k8s services
|
||||
prometheus.exporter.blackbox "services" {
|
||||
config = "{ modules: { http_2xx: { prober: http, timeout: 5s } } }"
|
||||
|
||||
target {
|
||||
name = "miniflux"
|
||||
address = "http://miniflux.miniflux.svc.cluster.local:8080/healthcheck"
|
||||
module = "http_2xx"
|
||||
}
|
||||
|
||||
target {
|
||||
name = "kiwix"
|
||||
address = "http://kiwix.kiwix.svc.cluster.local:80/"
|
||||
module = "http_2xx"
|
||||
}
|
||||
|
||||
target {
|
||||
name = "transmission"
|
||||
address = "http://transmission.torrent.svc.cluster.local:9091/transmission/web/"
|
||||
module = "http_2xx"
|
||||
}
|
||||
|
||||
target {
|
||||
name = "devpi"
|
||||
address = "http://devpi.devpi.svc.cluster.local:3141/+api"
|
||||
module = "http_2xx"
|
||||
}
|
||||
|
||||
target {
|
||||
name = "argocd"
|
||||
address = "http://argocd-server.argocd.svc.cluster.local:80/healthz"
|
||||
module = "http_2xx"
|
||||
}
|
||||
}
|
||||
|
||||
// Scrape blackbox probe results
|
||||
prometheus.scrape "blackbox" {
|
||||
targets = prometheus.exporter.blackbox.services.targets
|
||||
scrape_interval = "30s"
|
||||
forward_to = [prometheus.remote_write.prometheus.receiver]
|
||||
}
|
||||
|
||||
// Push metrics to Prometheus
|
||||
prometheus.remote_write "prometheus" {
|
||||
endpoint {
|
||||
url = "http://prometheus.monitoring.svc.cluster.local:9090/api/v1/write"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: alloy-config
|
||||
namespace: alloy
|
||||
data:
|
||||
config.alloy: |
|
||||
// Alloy k8s configuration - collects pod logs from all namespaces
|
||||
|
||||
// ============== K8S POD LOG DISCOVERY ==============
|
||||
|
||||
// Discover all pods in the cluster
|
||||
discovery.kubernetes "pods" {
|
||||
role = "pod"
|
||||
}
|
||||
|
||||
// Relabel to extract useful metadata
|
||||
discovery.relabel "pods" {
|
||||
targets = discovery.kubernetes.pods.targets
|
||||
|
||||
// Keep only running pods
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_phase"]
|
||||
regex = "Pending|Succeeded|Failed|Unknown"
|
||||
action = "drop"
|
||||
}
|
||||
|
||||
// Set namespace label
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_namespace"]
|
||||
target_label = "namespace"
|
||||
}
|
||||
|
||||
// Set pod name label
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_name"]
|
||||
target_label = "pod"
|
||||
}
|
||||
|
||||
// Set container name label
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_container_name"]
|
||||
target_label = "container"
|
||||
}
|
||||
|
||||
// Set app label from pod labels
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_label_app"]
|
||||
target_label = "app"
|
||||
}
|
||||
|
||||
// Fallback: use app.kubernetes.io/name if no app label
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"]
|
||||
target_label = "app"
|
||||
regex = "(.+)"
|
||||
action = "replace"
|
||||
}
|
||||
|
||||
// Set node name
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_node_name"]
|
||||
target_label = "node"
|
||||
}
|
||||
|
||||
// Build the log path for the pod container
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_uid", "__meta_kubernetes_pod_container_name"]
|
||||
target_label = "__path__"
|
||||
separator = "/"
|
||||
replacement = "/var/log/pods/*$1/$2/*.log"
|
||||
}
|
||||
}
|
||||
|
||||
// Tail pod logs
|
||||
loki.source.kubernetes "pods" {
|
||||
targets = discovery.relabel.pods.output
|
||||
forward_to = [loki.process.pods.receiver]
|
||||
}
|
||||
|
||||
// Process logs - parse JSON if present, add labels
|
||||
loki.process "pods" {
|
||||
forward_to = [loki.write.loki.receiver]
|
||||
|
||||
// Drop noisy deprecation warning from minikube storage-provisioner
|
||||
// See: https://github.com/kubernetes/minikube/issues/21009
|
||||
stage.drop {
|
||||
source = ""
|
||||
expression = "v1 Endpoints is deprecated"
|
||||
}
|
||||
|
||||
// Try to parse JSON logs (e.g., structured app logs)
|
||||
// Handle both "msg" (common) and "message" (zot) field names
|
||||
stage.json {
|
||||
expressions = {
|
||||
level = "level",
|
||||
msg = "msg",
|
||||
message = "message",
|
||||
time = "time",
|
||||
caller = "caller",
|
||||
repository = "repository",
|
||||
}
|
||||
}
|
||||
|
||||
// Drop JSON parsing error labels (non-JSON logs are fine, just won't have extracted fields)
|
||||
stage.label_drop {
|
||||
values = ["__error__", "__error_details__"]
|
||||
}
|
||||
|
||||
// Extract labels from parsed JSON data
|
||||
stage.labels {
|
||||
values = {
|
||||
level = "",
|
||||
caller = "",
|
||||
repository = "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write logs to Loki
|
||||
loki.write "loki" {
|
||||
endpoint {
|
||||
url = "http://loki.monitoring.svc.cluster.local:3100/loki/api/v1/push"
|
||||
}
|
||||
}
|
||||
|
||||
// ============== SERVICE HEALTH PROBES ==============
|
||||
|
||||
// Blackbox-style HTTP probes for k8s services
|
||||
prometheus.exporter.blackbox "services" {
|
||||
config = "{ modules: { http_2xx: { prober: http, timeout: 5s } } }"
|
||||
|
||||
target {
|
||||
name = "miniflux"
|
||||
address = "http://miniflux.miniflux.svc.cluster.local:8080/healthcheck"
|
||||
module = "http_2xx"
|
||||
}
|
||||
|
||||
target {
|
||||
name = "kiwix"
|
||||
address = "http://kiwix.kiwix.svc.cluster.local:80/"
|
||||
module = "http_2xx"
|
||||
}
|
||||
|
||||
target {
|
||||
name = "transmission"
|
||||
address = "http://transmission.torrent.svc.cluster.local:9091/transmission/web/"
|
||||
module = "http_2xx"
|
||||
}
|
||||
|
||||
target {
|
||||
name = "devpi"
|
||||
address = "http://devpi.devpi.svc.cluster.local:3141/+api"
|
||||
module = "http_2xx"
|
||||
}
|
||||
|
||||
target {
|
||||
name = "argocd"
|
||||
address = "http://argocd-server.argocd.svc.cluster.local:80/healthz"
|
||||
module = "http_2xx"
|
||||
}
|
||||
}
|
||||
|
||||
// Scrape blackbox probe results
|
||||
prometheus.scrape "blackbox" {
|
||||
targets = prometheus.exporter.blackbox.services.targets
|
||||
scrape_interval = "30s"
|
||||
forward_to = [prometheus.remote_write.prometheus.receiver]
|
||||
}
|
||||
|
||||
// Push metrics to Prometheus
|
||||
prometheus.remote_write "prometheus" {
|
||||
endpoint {
|
||||
url = "http://prometheus.monitoring.svc.cluster.local:9090/api/v1/write"
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ spec:
|
|||
fsGroup: 473 # alloy user group
|
||||
containers:
|
||||
- name: alloy
|
||||
image: grafana/alloy:v1.13.1
|
||||
image: grafana/alloy
|
||||
args:
|
||||
- run
|
||||
- --server.http.listen-addr=0.0.0.0:12345
|
||||
|
|
|
|||
|
|
@ -1,7 +1,18 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: alloy
|
||||
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- rbac.yaml
|
||||
- configmap.yaml
|
||||
- daemonset.yaml
|
||||
|
||||
images:
|
||||
- name: grafana/alloy
|
||||
newTag: v1.13.1
|
||||
|
||||
configMapGenerator:
|
||||
- name: alloy-config
|
||||
files:
|
||||
- config.alloy
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: docker.io/library/redis:7-alpine
|
||||
image: docker.io/library/redis
|
||||
ports:
|
||||
- name: redis
|
||||
containerPort: 6379
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: server
|
||||
image: registry.ops.eblu.me/blumeops/authentik:v2025.10.1-a72a0d8-nix
|
||||
image: registry.ops.eblu.me/blumeops/authentik
|
||||
args: ["server"]
|
||||
ports:
|
||||
- name: http
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: worker
|
||||
image: registry.ops.eblu.me/blumeops/authentik:v2025.10.1-a72a0d8-nix
|
||||
image: registry.ops.eblu.me/blumeops/authentik
|
||||
args: ["worker"]
|
||||
env:
|
||||
- name: AUTHENTIK_SECRET_KEY
|
||||
|
|
|
|||
|
|
@ -11,3 +11,8 @@ resources:
|
|||
- service.yaml
|
||||
- service-redis.yaml
|
||||
- ingress-tailscale.yaml
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/authentik
|
||||
newTag: v2025.10.1-a72a0d8-nix
|
||||
- name: docker.io/library/redis
|
||||
newTag: 7-alpine
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: cv
|
||||
image: registry.ops.eblu.me/blumeops/cv:v1.0.3-ffa8727
|
||||
image: registry.ops.eblu.me/blumeops/cv
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
|
|
|
|||
|
|
@ -6,3 +6,6 @@ resources:
|
|||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/cv
|
||||
newTag: v1.0.3-ffa8727
|
||||
|
|
|
|||
|
|
@ -8,3 +8,7 @@ resources:
|
|||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
- external-secret.yaml
|
||||
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/devpi
|
||||
newTag: v6.19.1-ffa8727
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ spec:
|
|||
fsGroup: 1000
|
||||
containers:
|
||||
- name: devpi
|
||||
image: registry.ops.eblu.me/blumeops/devpi:v6.19.1-ffa8727
|
||||
image: registry.ops.eblu.me/blumeops/devpi
|
||||
env:
|
||||
- name: DEVPI_ROOT_PASSWORD
|
||||
valueFrom:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: docs
|
||||
image: registry.ops.eblu.me/blumeops/quartz:v1.28.2-ffa8727
|
||||
image: registry.ops.eblu.me/blumeops/quartz
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
|
|
|
|||
|
|
@ -6,3 +6,6 @@ resources:
|
|||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/quartz
|
||||
newTag: v1.28.2-ffa8727
|
||||
|
|
|
|||
19
argocd/manifests/forgejo-runner/config.yaml
Normal file
19
argocd/manifests/forgejo-runner/config.yaml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Reviewed against v12.7.0 defaults (2026-02-22)
|
||||
log:
|
||||
level: info
|
||||
|
||||
runner:
|
||||
file: /data/.runner
|
||||
capacity: 2
|
||||
timeout: 3h
|
||||
shutdown_timeout: 3h
|
||||
# Env vars injected into all job containers
|
||||
envs:
|
||||
DOCKER_HOST: tcp://127.0.0.1:2375
|
||||
TZ: America/Los_Angeles
|
||||
|
||||
container:
|
||||
# Job execution image is set via RUNNER_LABELS in deployment.yaml
|
||||
network: "host"
|
||||
# Connect to DinD sidecar via TCP (not socket)
|
||||
docker_host: tcp://127.0.0.1:2375
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: forgejo-runner-config
|
||||
namespace: forgejo-runner
|
||||
data:
|
||||
config.yaml: |
|
||||
# Reviewed against v12.7.0 defaults (2026-02-22)
|
||||
log:
|
||||
level: info
|
||||
|
||||
runner:
|
||||
file: /data/.runner
|
||||
capacity: 2
|
||||
timeout: 3h
|
||||
shutdown_timeout: 3h
|
||||
# Env vars injected into all job containers
|
||||
envs:
|
||||
DOCKER_HOST: tcp://127.0.0.1:2375
|
||||
TZ: America/Los_Angeles
|
||||
|
||||
container:
|
||||
# Job execution image is set via RUNNER_LABELS in deployment.yaml
|
||||
network: "host"
|
||||
# Connect to DinD sidecar via TCP (not socket)
|
||||
docker_host: tcp://127.0.0.1:2375
|
||||
daemon.json: |
|
||||
{
|
||||
"registry-mirrors": ["http://host.minikube.internal:5050"]
|
||||
}
|
||||
3
argocd/manifests/forgejo-runner/daemon.json
Normal file
3
argocd/manifests/forgejo-runner/daemon.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"registry-mirrors": ["http://host.minikube.internal:5050"]
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ spec:
|
|||
containers:
|
||||
# Forgejo runner daemon
|
||||
- name: runner
|
||||
image: code.forgejo.org/forgejo/runner:12.7.0
|
||||
image: code.forgejo.org/forgejo/runner
|
||||
env:
|
||||
- name: TZ
|
||||
value: America/Los_Angeles
|
||||
|
|
@ -68,7 +68,7 @@ spec:
|
|||
|
||||
# Docker-in-Docker sidecar
|
||||
- name: dind
|
||||
image: docker:27-dind
|
||||
image: docker
|
||||
securityContext:
|
||||
privileged: true
|
||||
env:
|
||||
|
|
|
|||
21
argocd/manifests/forgejo-runner/kustomization.yaml
Normal file
21
argocd/manifests/forgejo-runner/kustomization.yaml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: forgejo-runner
|
||||
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- external-secret.yaml
|
||||
- deployment.yaml
|
||||
|
||||
images:
|
||||
- name: code.forgejo.org/forgejo/runner
|
||||
newTag: "12.7.0"
|
||||
- name: docker
|
||||
newTag: 27-dind
|
||||
|
||||
configMapGenerator:
|
||||
- name: forgejo-runner-config
|
||||
files:
|
||||
- config.yaml
|
||||
- daemon.json
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: frigate-notify-config
|
||||
namespace: frigate
|
||||
data:
|
||||
config.yml: |
|
||||
frigate:
|
||||
server: http://frigate:5000
|
||||
public_url: https://nvr.ops.eblu.me
|
||||
|
||||
webapi:
|
||||
enabled: true
|
||||
interval: 15
|
||||
|
||||
mqtt:
|
||||
enabled: false
|
||||
|
||||
alerts:
|
||||
general:
|
||||
title: "Frigate Alert"
|
||||
nosnap: drop
|
||||
snap_hires: true
|
||||
notify_once: true
|
||||
|
||||
zones:
|
||||
unzoned: drop
|
||||
allow:
|
||||
- driveway_entrance
|
||||
- driveway
|
||||
|
||||
labels:
|
||||
allow:
|
||||
- person
|
||||
- car
|
||||
|
||||
ntfy:
|
||||
enabled: true
|
||||
server: http://ntfy.ntfy.svc.cluster.local:80
|
||||
topic: frigate-alerts
|
||||
headers:
|
||||
- X-Actions: "view, Open Event, {{.Extra.PublicURL}}/review?id={{.ID}}, clear=true; view, Open Camera, {{.Extra.PublicURL}}/#/cameras/{{.Camera}}"
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: frigate-config
|
||||
namespace: frigate
|
||||
data:
|
||||
config.yml: |
|
||||
mqtt:
|
||||
host: mosquitto.mqtt.svc.cluster.local
|
||||
port: 1883
|
||||
|
||||
go2rtc:
|
||||
streams:
|
||||
# GableCam IP is reserved in UX7 DHCP config
|
||||
gablecam:
|
||||
- "rtsp://{FRIGATE_CAMERA_USER}:{FRIGATE_CAMERA_PASSWORD}@192.168.1.159:554/h264Preview_01_main"
|
||||
gablecam_sub:
|
||||
- "rtsp://{FRIGATE_CAMERA_USER}:{FRIGATE_CAMERA_PASSWORD}@192.168.1.159:554/h264Preview_01_sub"
|
||||
|
||||
cameras:
|
||||
gablecam:
|
||||
enabled: true
|
||||
ffmpeg:
|
||||
inputs:
|
||||
- path: rtsp://127.0.0.1:8554/gablecam
|
||||
input_args: preset-rtsp-restream
|
||||
roles: [record]
|
||||
- path: rtsp://127.0.0.1:8554/gablecam_sub
|
||||
input_args: preset-rtsp-restream
|
||||
roles: [detect]
|
||||
detect:
|
||||
enabled: true
|
||||
stationary:
|
||||
max_frames:
|
||||
default: 1500
|
||||
motion:
|
||||
mask:
|
||||
- 0.401,0.026,0.4,0.078,0.587,0.072,0.585,0.02
|
||||
- 0.881,0.422,0.789,0.245,0.595,0.054,0.531,0,0.634,0,0.824,0.192,0.892,0.307
|
||||
zones:
|
||||
driveway_entrance:
|
||||
coordinates: 0.841,0.37,0.735,0.344,0.681,0.2,0.78,0.259
|
||||
objects: [car, dog, person]
|
||||
inertia: 3
|
||||
loitering_time: 0
|
||||
driveway:
|
||||
coordinates: 0.767,0.25,0.58,0.2,0.218,0.25,0.128,0.296,0.003,0.565,0.001,0.992,0.826,0.992,0.897,0.665,0.869,0.608,0.788,0.354
|
||||
review:
|
||||
alerts:
|
||||
labels: [person, car]
|
||||
required_zones:
|
||||
- driveway_entrance
|
||||
- driveway
|
||||
detections:
|
||||
required_zones:
|
||||
- driveway
|
||||
- driveway_entrance
|
||||
objects:
|
||||
track: [person, car, dog, cat, bird]
|
||||
|
||||
detectors:
|
||||
onnx:
|
||||
type: onnx
|
||||
|
||||
model:
|
||||
model_type: yolo-generic
|
||||
width: 640
|
||||
height: 640
|
||||
input_tensor: nchw
|
||||
input_dtype: float
|
||||
path: /media/frigate/models/yolov9-c-640.onnx
|
||||
labelmap_path: /labelmap/coco-80.txt
|
||||
|
||||
record:
|
||||
enabled: true
|
||||
continuous:
|
||||
days: 3
|
||||
alerts:
|
||||
retain:
|
||||
days: 30
|
||||
mode: active_objects
|
||||
detections:
|
||||
retain:
|
||||
days: 14
|
||||
mode: motion
|
||||
|
||||
snapshots:
|
||||
enabled: true
|
||||
retain:
|
||||
default: 14
|
||||
|
|
@ -16,7 +16,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: frigate-notify
|
||||
image: ghcr.io/0x2142/frigate-notify:v0.5.4
|
||||
image: ghcr.io/0x2142/frigate-notify
|
||||
env:
|
||||
- name: TZ
|
||||
value: America/Los_Angeles
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ spec:
|
|||
runtimeClassName: nvidia
|
||||
initContainers:
|
||||
- name: copy-config
|
||||
image: busybox:1.37
|
||||
image: busybox
|
||||
command: ["cp", "/config-ro/config.yml", "/config/config.yml"]
|
||||
volumeMounts:
|
||||
- name: config-ro
|
||||
|
|
@ -28,7 +28,7 @@ spec:
|
|||
mountPath: /config
|
||||
containers:
|
||||
- name: frigate
|
||||
image: ghcr.io/blakeblackshear/frigate:0.17.0-rc2-tensorrt
|
||||
image: ghcr.io/blakeblackshear/frigate
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
name: http
|
||||
|
|
|
|||
83
argocd/manifests/frigate/frigate-config.yml
Normal file
83
argocd/manifests/frigate/frigate-config.yml
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
mqtt:
|
||||
host: mosquitto.mqtt.svc.cluster.local
|
||||
port: 1883
|
||||
|
||||
go2rtc:
|
||||
streams:
|
||||
# GableCam IP is reserved in UX7 DHCP config
|
||||
gablecam:
|
||||
- "rtsp://{FRIGATE_CAMERA_USER}:{FRIGATE_CAMERA_PASSWORD}@192.168.1.159:554/h264Preview_01_main"
|
||||
gablecam_sub:
|
||||
- "rtsp://{FRIGATE_CAMERA_USER}:{FRIGATE_CAMERA_PASSWORD}@192.168.1.159:554/h264Preview_01_sub"
|
||||
|
||||
cameras:
|
||||
gablecam:
|
||||
enabled: true
|
||||
ffmpeg:
|
||||
inputs:
|
||||
- path: rtsp://127.0.0.1:8554/gablecam
|
||||
input_args: preset-rtsp-restream
|
||||
roles: [record]
|
||||
- path: rtsp://127.0.0.1:8554/gablecam_sub
|
||||
input_args: preset-rtsp-restream
|
||||
roles: [detect]
|
||||
detect:
|
||||
enabled: true
|
||||
stationary:
|
||||
max_frames:
|
||||
default: 1500
|
||||
motion:
|
||||
mask:
|
||||
- 0.401,0.026,0.4,0.078,0.587,0.072,0.585,0.02
|
||||
- 0.881,0.422,0.789,0.245,0.595,0.054,0.531,0,0.634,0,0.824,0.192,0.892,0.307
|
||||
zones:
|
||||
driveway_entrance:
|
||||
coordinates: 0.841,0.37,0.735,0.344,0.681,0.2,0.78,0.259
|
||||
objects: [car, dog, person]
|
||||
inertia: 3
|
||||
loitering_time: 0
|
||||
driveway:
|
||||
coordinates: 0.767,0.25,0.58,0.2,0.218,0.25,0.128,0.296,0.003,0.565,0.001,0.992,0.826,0.992,0.897,0.665,0.869,0.608,0.788,0.354
|
||||
review:
|
||||
alerts:
|
||||
labels: [person, car]
|
||||
required_zones:
|
||||
- driveway_entrance
|
||||
- driveway
|
||||
detections:
|
||||
required_zones:
|
||||
- driveway
|
||||
- driveway_entrance
|
||||
objects:
|
||||
track: [person, car, dog, cat, bird]
|
||||
|
||||
detectors:
|
||||
onnx:
|
||||
type: onnx
|
||||
|
||||
model:
|
||||
model_type: yolo-generic
|
||||
width: 640
|
||||
height: 640
|
||||
input_tensor: nchw
|
||||
input_dtype: float
|
||||
path: /media/frigate/models/yolov9-c-640.onnx
|
||||
labelmap_path: /labelmap/coco-80.txt
|
||||
|
||||
record:
|
||||
enabled: true
|
||||
continuous:
|
||||
days: 3
|
||||
alerts:
|
||||
retain:
|
||||
days: 30
|
||||
mode: active_objects
|
||||
detections:
|
||||
retain:
|
||||
days: 14
|
||||
mode: motion
|
||||
|
||||
snapshots:
|
||||
enabled: true
|
||||
retain:
|
||||
default: 14
|
||||
35
argocd/manifests/frigate/frigate-notify-config.yml
Normal file
35
argocd/manifests/frigate/frigate-notify-config.yml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
frigate:
|
||||
server: http://frigate:5000
|
||||
public_url: https://nvr.ops.eblu.me
|
||||
|
||||
webapi:
|
||||
enabled: true
|
||||
interval: 15
|
||||
|
||||
mqtt:
|
||||
enabled: false
|
||||
|
||||
alerts:
|
||||
general:
|
||||
title: "Frigate Alert"
|
||||
nosnap: drop
|
||||
snap_hires: true
|
||||
notify_once: true
|
||||
|
||||
zones:
|
||||
unzoned: drop
|
||||
allow:
|
||||
- driveway_entrance
|
||||
- driveway
|
||||
|
||||
labels:
|
||||
allow:
|
||||
- person
|
||||
- car
|
||||
|
||||
ntfy:
|
||||
enabled: true
|
||||
server: http://ntfy.ntfy.svc.cluster.local:80
|
||||
topic: frigate-alerts
|
||||
headers:
|
||||
- X-Actions: "view, Open Event, {{.Extra.PublicURL}}/review?id={{.ID}}, clear=true; view, Open Camera, {{.Extra.PublicURL}}/#/cameras/{{.Camera}}"
|
||||
|
|
@ -4,8 +4,6 @@ kind: Kustomization
|
|||
namespace: frigate
|
||||
resources:
|
||||
- external-secret.yaml
|
||||
- configmap.yaml
|
||||
- configmap-notify.yaml
|
||||
- pv-nfs.yaml
|
||||
- pvc-recordings.yaml
|
||||
- pvc-database.yaml
|
||||
|
|
@ -13,3 +11,19 @@ resources:
|
|||
- deployment-notify.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
|
||||
images:
|
||||
- name: busybox
|
||||
newTag: "1.37"
|
||||
- name: ghcr.io/blakeblackshear/frigate
|
||||
newTag: 0.17.0-rc2-tensorrt
|
||||
- name: ghcr.io/0x2142/frigate-notify
|
||||
newTag: v0.5.4
|
||||
|
||||
configMapGenerator:
|
||||
- name: frigate-config
|
||||
files:
|
||||
- config.yml=frigate-config.yml
|
||||
- name: frigate-notify-config
|
||||
files:
|
||||
- config.yml=frigate-notify-config.yml
|
||||
|
|
|
|||
|
|
@ -1,100 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: grafana
|
||||
namespace: monitoring
|
||||
labels:
|
||||
app.kubernetes.io/name: grafana
|
||||
app.kubernetes.io/instance: grafana
|
||||
data:
|
||||
grafana.ini: |
|
||||
[analytics]
|
||||
check_for_updates = false
|
||||
reporting_enabled = false
|
||||
|
||||
[auth.generic_oauth]
|
||||
allow_sign_up = true
|
||||
api_url = https://authentik.ops.eblu.me/application/o/userinfo/
|
||||
auth_url = https://authentik.ops.eblu.me/application/o/authorize/
|
||||
auto_login = false
|
||||
client_id = grafana
|
||||
client_secret = $__env{GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET}
|
||||
enabled = true
|
||||
name = Authentik
|
||||
role_attribute_path = contains(groups[*], 'admins') && 'Admin' || 'Viewer'
|
||||
skip_org_role_sync = false
|
||||
scopes = openid profile email
|
||||
token_url = https://authentik.ops.eblu.me/application/o/token/
|
||||
|
||||
[log]
|
||||
mode = console
|
||||
|
||||
[paths]
|
||||
data = /var/lib/grafana/
|
||||
logs = /var/log/grafana
|
||||
plugins = /var/lib/grafana/plugins
|
||||
provisioning = /etc/grafana/provisioning
|
||||
|
||||
[security]
|
||||
allow_embedding = false
|
||||
|
||||
[server]
|
||||
root_url = https://grafana.ops.eblu.me
|
||||
|
||||
datasources.yaml: |
|
||||
apiVersion: 1
|
||||
datasources:
|
||||
- access: proxy
|
||||
editable: false
|
||||
isDefault: true
|
||||
name: Prometheus
|
||||
orgId: 1
|
||||
type: prometheus
|
||||
uid: prometheus
|
||||
url: http://prometheus.monitoring.svc.cluster.local:9090
|
||||
- access: proxy
|
||||
editable: false
|
||||
name: Loki
|
||||
orgId: 1
|
||||
type: loki
|
||||
uid: loki
|
||||
url: http://loki.monitoring.svc.cluster.local:3100
|
||||
- access: proxy
|
||||
database: teslamate
|
||||
editable: false
|
||||
jsonData:
|
||||
database: teslamate
|
||||
connMaxLifetime: 14400
|
||||
maxIdleConns: 2
|
||||
maxOpenConns: 5
|
||||
sslmode: disable
|
||||
name: TeslaMate
|
||||
orgId: 1
|
||||
secureJsonData:
|
||||
password: $TESLAMATE_DB_PASSWORD
|
||||
type: postgres
|
||||
uid: TeslaMate
|
||||
url: blumeops-pg-rw.databases.svc.cluster.local:5432
|
||||
user: teslamate
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: grafana-config-dashboards
|
||||
namespace: monitoring
|
||||
labels:
|
||||
app.kubernetes.io/name: grafana
|
||||
app.kubernetes.io/instance: grafana
|
||||
data:
|
||||
provider.yaml: |
|
||||
apiVersion: 1
|
||||
providers:
|
||||
- name: 'sidecarProvider'
|
||||
orgId: 1
|
||||
type: file
|
||||
disableDeletion: false
|
||||
allowUiUpdates: false
|
||||
updateIntervalSeconds: 30
|
||||
options:
|
||||
foldersFromFilesStructure: true
|
||||
path: /tmp/dashboards
|
||||
34
argocd/manifests/grafana/datasources.yaml
Normal file
34
argocd/manifests/grafana/datasources.yaml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
apiVersion: 1
|
||||
datasources:
|
||||
- access: proxy
|
||||
editable: false
|
||||
isDefault: true
|
||||
name: Prometheus
|
||||
orgId: 1
|
||||
type: prometheus
|
||||
uid: prometheus
|
||||
url: http://prometheus.monitoring.svc.cluster.local:9090
|
||||
- access: proxy
|
||||
editable: false
|
||||
name: Loki
|
||||
orgId: 1
|
||||
type: loki
|
||||
uid: loki
|
||||
url: http://loki.monitoring.svc.cluster.local:3100
|
||||
- access: proxy
|
||||
database: teslamate
|
||||
editable: false
|
||||
jsonData:
|
||||
database: teslamate
|
||||
connMaxLifetime: 14400
|
||||
maxIdleConns: 2
|
||||
maxOpenConns: 5
|
||||
sslmode: disable
|
||||
name: TeslaMate
|
||||
orgId: 1
|
||||
secureJsonData:
|
||||
password: $TESLAMATE_DB_PASSWORD
|
||||
type: postgres
|
||||
uid: TeslaMate
|
||||
url: blumeops-pg-rw.databases.svc.cluster.local:5432
|
||||
user: teslamate
|
||||
|
|
@ -32,7 +32,7 @@ spec:
|
|||
runAsUser: 472
|
||||
initContainers:
|
||||
- name: init-chown-data
|
||||
image: docker.io/library/busybox:1.31.1
|
||||
image: docker.io/library/busybox
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["chown", "-R", "472:472", "/var/lib/grafana"]
|
||||
securityContext:
|
||||
|
|
@ -48,7 +48,7 @@ spec:
|
|||
containers:
|
||||
# Dashboard sidecar - watches ConfigMaps with grafana_dashboard=1
|
||||
- name: grafana-sc-dashboard
|
||||
image: quay.io/kiwigrid/k8s-sidecar:1.28.0
|
||||
image: quay.io/kiwigrid/k8s-sidecar
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: METHOD
|
||||
|
|
@ -88,7 +88,7 @@ spec:
|
|||
mountPath: /tmp/dashboards
|
||||
# Grafana
|
||||
- name: grafana
|
||||
image: registry.ops.eblu.me/blumeops/grafana:v12.3.3-d05d2fb
|
||||
image: registry.ops.eblu.me/blumeops/grafana
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: POD_IP
|
||||
|
|
|
|||
32
argocd/manifests/grafana/grafana.ini
Normal file
32
argocd/manifests/grafana/grafana.ini
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
[analytics]
|
||||
check_for_updates = false
|
||||
reporting_enabled = false
|
||||
|
||||
[auth.generic_oauth]
|
||||
allow_sign_up = true
|
||||
api_url = https://authentik.ops.eblu.me/application/o/userinfo/
|
||||
auth_url = https://authentik.ops.eblu.me/application/o/authorize/
|
||||
auto_login = false
|
||||
client_id = grafana
|
||||
client_secret = $__env{GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET}
|
||||
enabled = true
|
||||
name = Authentik
|
||||
role_attribute_path = contains(groups[*], 'admins') && 'Admin' || 'Viewer'
|
||||
skip_org_role_sync = false
|
||||
scopes = openid profile email
|
||||
token_url = https://authentik.ops.eblu.me/application/o/token/
|
||||
|
||||
[log]
|
||||
mode = console
|
||||
|
||||
[paths]
|
||||
data = /var/lib/grafana/
|
||||
logs = /var/log/grafana
|
||||
plugins = /var/lib/grafana/plugins
|
||||
provisioning = /etc/grafana/provisioning
|
||||
|
||||
[security]
|
||||
allow_embedding = false
|
||||
|
||||
[server]
|
||||
root_url = https://grafana.ops.eblu.me
|
||||
|
|
@ -5,8 +5,24 @@ namespace: monitoring
|
|||
|
||||
resources:
|
||||
- serviceaccount.yaml
|
||||
- configmap.yaml
|
||||
- pvc.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- rbac.yaml
|
||||
|
||||
images:
|
||||
- name: docker.io/library/busybox
|
||||
newTag: 1.31.1
|
||||
- name: quay.io/kiwigrid/k8s-sidecar
|
||||
newTag: 1.28.0
|
||||
- name: registry.ops.eblu.me/blumeops/grafana
|
||||
newTag: v12.3.3-d05d2fb
|
||||
|
||||
configMapGenerator:
|
||||
- name: grafana
|
||||
files:
|
||||
- grafana.ini
|
||||
- datasources.yaml
|
||||
- name: grafana-config-dashboards
|
||||
files:
|
||||
- provider.yaml
|
||||
|
|
|
|||
11
argocd/manifests/grafana/provider.yaml
Normal file
11
argocd/manifests/grafana/provider.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
apiVersion: 1
|
||||
providers:
|
||||
- name: 'sidecarProvider'
|
||||
orgId: 1
|
||||
type: file
|
||||
disableDeletion: false
|
||||
allowUiUpdates: false
|
||||
updateIntervalSeconds: 30
|
||||
options:
|
||||
foldersFromFilesStructure: true
|
||||
path: /tmp/dashboards
|
||||
16
argocd/manifests/homepage/bookmarks.yaml
Normal file
16
argocd/manifests/homepage/bookmarks.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
- Admin:
|
||||
- Tailscale Admin:
|
||||
- href: https://login.tailscale.com/admin
|
||||
icon: tailscale
|
||||
- 1Password:
|
||||
- href: https://my.1password.com
|
||||
icon: 1password
|
||||
- Pulumi:
|
||||
- href: https://app.pulumi.com/eblume/blumeops-tailnet
|
||||
icon: si-pulumi
|
||||
- ArgoCD:
|
||||
- href: https://argocd.ops.eblu.me
|
||||
icon: argo-cd
|
||||
- UniFi:
|
||||
- href: https://unifi.ui.com
|
||||
icon: ubiquiti
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
# Homepage configuration files
|
||||
# Extracted from former Helm values.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: homepage-config
|
||||
namespace: homepage
|
||||
data:
|
||||
bookmarks.yaml: |
|
||||
- Admin:
|
||||
- Tailscale Admin:
|
||||
- href: https://login.tailscale.com/admin
|
||||
icon: tailscale
|
||||
- 1Password:
|
||||
- href: https://my.1password.com
|
||||
icon: 1password
|
||||
- Pulumi:
|
||||
- href: https://app.pulumi.com/eblume/blumeops-tailnet
|
||||
icon: si-pulumi
|
||||
- ArgoCD:
|
||||
- href: https://argocd.ops.eblu.me
|
||||
icon: argo-cd
|
||||
- UniFi:
|
||||
- href: https://unifi.ui.com
|
||||
icon: ubiquiti
|
||||
|
||||
services.yaml: |
|
||||
- Host Services:
|
||||
- Forgejo:
|
||||
href: https://forge.ops.eblu.me
|
||||
icon: forgejo
|
||||
description: Git forge
|
||||
widget:
|
||||
type: gitea
|
||||
url: https://forge.ops.eblu.me
|
||||
key: "{{HOMEPAGE_VAR_FORGEJO_API_KEY}}"
|
||||
- Registry:
|
||||
href: https://registry.ops.eblu.me
|
||||
icon: zot-registry
|
||||
description: Container registry
|
||||
- Sifaka NAS:
|
||||
href: https://nas.ops.eblu.me
|
||||
icon: synology
|
||||
description: NAS dashboard
|
||||
widget:
|
||||
type: prometheusmetric
|
||||
url: https://prometheus.ops.eblu.me
|
||||
metrics:
|
||||
- label: Used
|
||||
query: node_filesystem_size_bytes{mountpoint="/Volumes/backups"} - node_filesystem_avail_bytes{mountpoint="/Volumes/backups"}
|
||||
format:
|
||||
type: bytes
|
||||
- label: Total
|
||||
query: node_filesystem_size_bytes{mountpoint="/Volumes/backups"}
|
||||
format:
|
||||
type: bytes
|
||||
- Borgmatic:
|
||||
href: https://grafana.ops.eblu.me/d/borgmatic
|
||||
icon: borgmatic
|
||||
description: Backup system
|
||||
widget:
|
||||
type: prometheusmetric
|
||||
url: https://prometheus.ops.eblu.me
|
||||
metrics:
|
||||
- label: Last backup
|
||||
query: time() - borgmatic_last_archive_timestamp
|
||||
format:
|
||||
type: duration
|
||||
- label: Archive size
|
||||
query: borgmatic_repo_deduplicated_size_bytes
|
||||
format:
|
||||
type: bytes
|
||||
- Jellyfin:
|
||||
href: https://jellyfin.ops.eblu.me
|
||||
icon: jellyfin
|
||||
description: Media server
|
||||
widget:
|
||||
type: jellyfin
|
||||
url: https://jellyfin.ops.eblu.me
|
||||
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
|
||||
- Infrastructure:
|
||||
- Authentik:
|
||||
href: https://authentik.ops.eblu.me
|
||||
icon: authentik
|
||||
description: Identity provider
|
||||
- NVR:
|
||||
href: https://nvr.ops.eblu.me
|
||||
icon: frigate.png
|
||||
description: Network video recorder
|
||||
- Ntfy:
|
||||
href: https://ntfy.ops.eblu.me
|
||||
icon: ntfy.png
|
||||
description: Push notifications
|
||||
|
||||
widgets.yaml: |
|
||||
- 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
|
||||
longitude: -122.52590
|
||||
units: imperial
|
||||
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.yaml: |
|
||||
mode: cluster
|
||||
|
||||
docker.yaml: ""
|
||||
|
||||
settings.yaml: |
|
||||
title: BlumeOps
|
||||
headerStyle: boxed
|
||||
quicklaunch:
|
||||
searchDescriptions: true
|
||||
showSearchSuggestions: true
|
||||
provider: custom
|
||||
url: https://kagi.com/search?q=
|
||||
suggestionUrl: https://kagisuggest.com/api/autosuggest?q=
|
||||
layout:
|
||||
Host Services:
|
||||
style: column
|
||||
Content:
|
||||
style: column
|
||||
Infrastructure:
|
||||
style: column
|
||||
Services:
|
||||
style: column
|
||||
|
|
@ -20,7 +20,7 @@ spec:
|
|||
fsGroup: 1000
|
||||
containers:
|
||||
- name: homepage
|
||||
image: registry.ops.eblu.me/blumeops/homepage:v1.10.1-a72a0d8
|
||||
image: registry.ops.eblu.me/blumeops/homepage
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
|
|
|
|||
0
argocd/manifests/homepage/docker.yaml
Normal file
0
argocd/manifests/homepage/docker.yaml
Normal file
1
argocd/manifests/homepage/kubernetes.yaml
Normal file
1
argocd/manifests/homepage/kubernetes.yaml
Normal file
|
|
@ -0,0 +1 @@
|
|||
mode: cluster
|
||||
|
|
@ -5,7 +5,6 @@ resources:
|
|||
- serviceaccount.yaml
|
||||
- clusterrole.yaml
|
||||
- clusterrolebinding.yaml
|
||||
- configmap.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
|
|
@ -15,3 +14,17 @@ resources:
|
|||
- external-secret-grafana.yaml
|
||||
- external-secret-miniflux.yaml
|
||||
- external-secret-navidrome.yaml
|
||||
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/homepage
|
||||
newTag: v1.10.1-a72a0d8
|
||||
|
||||
configMapGenerator:
|
||||
- name: homepage-config
|
||||
files:
|
||||
- bookmarks.yaml
|
||||
- services.yaml
|
||||
- widgets.yaml
|
||||
- kubernetes.yaml
|
||||
- docker.yaml
|
||||
- settings.yaml
|
||||
|
|
|
|||
76
argocd/manifests/homepage/services.yaml
Normal file
76
argocd/manifests/homepage/services.yaml
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
- Host Services:
|
||||
- Forgejo:
|
||||
href: https://forge.ops.eblu.me
|
||||
icon: forgejo
|
||||
description: Git forge
|
||||
widget:
|
||||
type: gitea
|
||||
url: https://forge.ops.eblu.me
|
||||
key: "{{HOMEPAGE_VAR_FORGEJO_API_KEY}}"
|
||||
- Registry:
|
||||
href: https://registry.ops.eblu.me
|
||||
icon: zot-registry
|
||||
description: Container registry
|
||||
- Sifaka NAS:
|
||||
href: https://nas.ops.eblu.me
|
||||
icon: synology
|
||||
description: NAS dashboard
|
||||
widget:
|
||||
type: prometheusmetric
|
||||
url: https://prometheus.ops.eblu.me
|
||||
metrics:
|
||||
- label: Used
|
||||
query: node_filesystem_size_bytes{mountpoint="/Volumes/backups"} - node_filesystem_avail_bytes{mountpoint="/Volumes/backups"}
|
||||
format:
|
||||
type: bytes
|
||||
- label: Total
|
||||
query: node_filesystem_size_bytes{mountpoint="/Volumes/backups"}
|
||||
format:
|
||||
type: bytes
|
||||
- Borgmatic:
|
||||
href: https://grafana.ops.eblu.me/d/borgmatic
|
||||
icon: borgmatic
|
||||
description: Backup system
|
||||
widget:
|
||||
type: prometheusmetric
|
||||
url: https://prometheus.ops.eblu.me
|
||||
metrics:
|
||||
- label: Last backup
|
||||
query: time() - borgmatic_last_archive_timestamp
|
||||
format:
|
||||
type: duration
|
||||
- label: Archive size
|
||||
query: borgmatic_repo_deduplicated_size_bytes
|
||||
format:
|
||||
type: bytes
|
||||
- Jellyfin:
|
||||
href: https://jellyfin.ops.eblu.me
|
||||
icon: jellyfin
|
||||
description: Media server
|
||||
widget:
|
||||
type: jellyfin
|
||||
url: https://jellyfin.ops.eblu.me
|
||||
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
|
||||
- Infrastructure:
|
||||
- Authentik:
|
||||
href: https://authentik.ops.eblu.me
|
||||
icon: authentik
|
||||
description: Identity provider
|
||||
- NVR:
|
||||
href: https://nvr.ops.eblu.me
|
||||
icon: frigate.png
|
||||
description: Network video recorder
|
||||
- Ntfy:
|
||||
href: https://ntfy.ops.eblu.me
|
||||
icon: ntfy.png
|
||||
description: Push notifications
|
||||
17
argocd/manifests/homepage/settings.yaml
Normal file
17
argocd/manifests/homepage/settings.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
title: BlumeOps
|
||||
headerStyle: boxed
|
||||
quicklaunch:
|
||||
searchDescriptions: true
|
||||
showSearchSuggestions: true
|
||||
provider: custom
|
||||
url: https://kagi.com/search?q=
|
||||
suggestionUrl: https://kagisuggest.com/api/autosuggest?q=
|
||||
layout:
|
||||
Host Services:
|
||||
style: column
|
||||
Content:
|
||||
style: column
|
||||
Infrastructure:
|
||||
style: column
|
||||
Services:
|
||||
style: column
|
||||
26
argocd/manifests/homepage/widgets.yaml
Normal file
26
argocd/manifests/homepage/widgets.yaml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
- 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
|
||||
longitude: -122.52590
|
||||
units: imperial
|
||||
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
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: zim-torrent-sync-script
|
||||
namespace: kiwix
|
||||
data:
|
||||
sync-zim-torrents.sh: |
|
||||
#!/bin/bash
|
||||
# Sync ZIM torrents from kiwix ConfigMap to Transmission
|
||||
# Runs as a sidecar in the kiwix deployment
|
||||
set -euo pipefail
|
||||
|
||||
TORRENT_LIST="${TORRENT_LIST:-/config/torrents.txt}"
|
||||
TRANSMISSION_HOST="${TRANSMISSION_HOST:-transmission.torrent.svc.cluster.local}"
|
||||
TRANSMISSION_PORT="${TRANSMISSION_PORT:-9091}"
|
||||
|
||||
echo "Syncing ZIM torrents to transmission at ${TRANSMISSION_HOST}:${TRANSMISSION_PORT}"
|
||||
|
||||
# Wait for transmission to be ready
|
||||
# Transmission RPC returns 409 on first request (to provide session ID), which is fine
|
||||
echo "Waiting for Transmission RPC..."
|
||||
max_attempts=30
|
||||
attempt=0
|
||||
until curl -s -o /dev/null -w "%{http_code}" "http://${TRANSMISSION_HOST}:${TRANSMISSION_PORT}/transmission/rpc" | grep -qE "^(200|409)$"; do
|
||||
attempt=$((attempt + 1))
|
||||
if [[ $attempt -ge $max_attempts ]]; then
|
||||
echo "Transmission not ready after ${max_attempts} attempts, will retry next cycle"
|
||||
exit 0 # Don't fail, just skip this sync
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
echo "Transmission is ready"
|
||||
|
||||
# Get current torrents from transmission
|
||||
# transmission-remote returns header + data + footer, extract just torrent names
|
||||
current=$(transmission-remote "${TRANSMISSION_HOST}:${TRANSMISSION_PORT}" -l 2>/dev/null | \
|
||||
tail -n +2 | head -n -1 | awk '{print $NF}' || true)
|
||||
|
||||
added=0
|
||||
skipped=0
|
||||
|
||||
while IFS= read -r url || [[ -n "$url" ]]; do
|
||||
# Skip empty lines and comments
|
||||
[[ -z "$url" || "$url" =~ ^[[:space:]]*# ]] && continue
|
||||
# Trim whitespace
|
||||
url=$(echo "$url" | xargs)
|
||||
[[ -z "$url" ]] && continue
|
||||
|
||||
# Extract base name from URL (remove .torrent extension)
|
||||
basename=$(basename "$url" .torrent)
|
||||
# Also try without .zim in case transmission reports it differently
|
||||
basename_no_zim="${basename%.zim}"
|
||||
|
||||
# Check if already in transmission
|
||||
if echo "$current" | grep -qF "$basename_no_zim"; then
|
||||
((skipped++)) || true
|
||||
else
|
||||
if transmission-remote "${TRANSMISSION_HOST}:${TRANSMISSION_PORT}" -a "$url" 2>/dev/null; then
|
||||
echo "Added: $basename"
|
||||
((added++)) || true
|
||||
else
|
||||
echo "Warning: Failed to add $url" >&2
|
||||
fi
|
||||
fi
|
||||
done < "$TORRENT_LIST"
|
||||
|
||||
echo "Sync complete: $added added, $skipped already present"
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: kiwix-zim-torrents
|
||||
namespace: kiwix
|
||||
data:
|
||||
torrents.txt: |
|
||||
# Declarative ZIM archive torrent URLs
|
||||
# These are synced to transmission automatically by the kiwix sidecar
|
||||
# Format: one URL per line, comments start with #
|
||||
#
|
||||
# Users can also add ZIM torrents manually via torrent.tail8d86e.ts.net
|
||||
# and kiwix will pick them up automatically.
|
||||
|
||||
# Wikipedia - Top 1M English articles (43G)
|
||||
https://download.kiwix.org/zim/wikipedia/wikipedia_en_top1m_maxi_2025-09.zim.torrent
|
||||
|
||||
# Project Gutenberg - Public domain books (72G)
|
||||
https://download.kiwix.org/zim/gutenberg/gutenberg_en_all_2023-08.zim.torrent
|
||||
|
||||
# iFixit - Repair guides (3.3G)
|
||||
https://download.kiwix.org/zim/ifixit/ifixit_en_all_2025-12.zim.torrent
|
||||
|
||||
# Stack Exchange
|
||||
https://download.kiwix.org/zim/stack_exchange/superuser.com_en_all_2025-12.zim.torrent
|
||||
https://download.kiwix.org/zim/stack_exchange/math.stackexchange.com_en_all_2025-12.zim.torrent
|
||||
|
||||
# LibreTexts - Open educational resources
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_bio_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_chem_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_eng_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_math_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_phys_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_human_2025-01.zim.torrent
|
||||
|
||||
# DevDocs - Programming documentation
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_bash_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_c_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_click_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_cmake_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_cpp_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_css_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_django-rest-framework_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_django_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_docker_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_duckdb_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_fish_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_gcc_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_git_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_go_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_godot_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_hammerspoon_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_homebrew_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_javascript_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_kubectl_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_kubernetes_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_latex_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_lua_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_markdown_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_nginx_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_nix_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_postgresql_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_python_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_redis_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_sqlite_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_typescript_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_werkzeug_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_zig_2026-01.zim.torrent
|
||||
|
|
@ -15,7 +15,7 @@ spec:
|
|||
serviceAccountName: zim-watcher
|
||||
containers:
|
||||
- name: watcher
|
||||
image: registry.ops.eblu.me/blumeops/kubectl:v1.34.4-a72a0d8
|
||||
image: registry.ops.eblu.me/blumeops/kubectl
|
||||
command: ["/bin/bash", "-c"]
|
||||
args:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ spec:
|
|||
containers:
|
||||
# Main kiwix-serve container
|
||||
- name: kiwix-serve
|
||||
image: registry.ops.eblu.me/blumeops/kiwix-serve:v3.8.1-ffa8727
|
||||
image: registry.ops.eblu.me/blumeops/kiwix-serve
|
||||
args:
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
|
|
@ -53,7 +53,7 @@ spec:
|
|||
|
||||
# Sidecar: Syncs declarative ZIM torrents to transmission
|
||||
- name: torrent-sync
|
||||
image: registry.ops.eblu.me/blumeops/transmission:v4.0.6-r4-ffa8727
|
||||
image: registry.ops.eblu.me/blumeops/transmission
|
||||
command: ["/bin/bash", "-c"]
|
||||
args:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -3,9 +3,23 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
|||
kind: Kustomization
|
||||
namespace: kiwix
|
||||
resources:
|
||||
- configmap-zim-torrents.yaml
|
||||
- configmap-sync-script.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
- cronjob-zim-watcher.yaml
|
||||
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/kiwix-serve
|
||||
newTag: v3.8.1-ffa8727
|
||||
- name: registry.ops.eblu.me/blumeops/transmission
|
||||
newTag: v4.0.6-r4-ffa8727
|
||||
- name: registry.ops.eblu.me/blumeops/kubectl
|
||||
newTag: v1.34.4-a72a0d8
|
||||
|
||||
configMapGenerator:
|
||||
- name: kiwix-zim-torrents
|
||||
files:
|
||||
- torrents.txt
|
||||
- name: zim-torrent-sync-script
|
||||
files:
|
||||
- sync-zim-torrents.sh
|
||||
|
|
|
|||
60
argocd/manifests/kiwix/sync-zim-torrents.sh
Normal file
60
argocd/manifests/kiwix/sync-zim-torrents.sh
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#!/bin/bash
|
||||
# Sync ZIM torrents from kiwix ConfigMap to Transmission
|
||||
# Runs as a sidecar in the kiwix deployment
|
||||
set -euo pipefail
|
||||
|
||||
TORRENT_LIST="${TORRENT_LIST:-/config/torrents.txt}"
|
||||
TRANSMISSION_HOST="${TRANSMISSION_HOST:-transmission.torrent.svc.cluster.local}"
|
||||
TRANSMISSION_PORT="${TRANSMISSION_PORT:-9091}"
|
||||
|
||||
echo "Syncing ZIM torrents to transmission at ${TRANSMISSION_HOST}:${TRANSMISSION_PORT}"
|
||||
|
||||
# Wait for transmission to be ready
|
||||
# Transmission RPC returns 409 on first request (to provide session ID), which is fine
|
||||
echo "Waiting for Transmission RPC..."
|
||||
max_attempts=30
|
||||
attempt=0
|
||||
until curl -s -o /dev/null -w "%{http_code}" "http://${TRANSMISSION_HOST}:${TRANSMISSION_PORT}/transmission/rpc" | grep -qE "^(200|409)$"; do
|
||||
attempt=$((attempt + 1))
|
||||
if [[ $attempt -ge $max_attempts ]]; then
|
||||
echo "Transmission not ready after ${max_attempts} attempts, will retry next cycle"
|
||||
exit 0 # Don't fail, just skip this sync
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
echo "Transmission is ready"
|
||||
|
||||
# Get current torrents from transmission
|
||||
# transmission-remote returns header + data + footer, extract just torrent names
|
||||
current=$(transmission-remote "${TRANSMISSION_HOST}:${TRANSMISSION_PORT}" -l 2>/dev/null | \
|
||||
tail -n +2 | head -n -1 | awk '{print $NF}' || true)
|
||||
|
||||
added=0
|
||||
skipped=0
|
||||
|
||||
while IFS= read -r url || [[ -n "$url" ]]; do
|
||||
# Skip empty lines and comments
|
||||
[[ -z "$url" || "$url" =~ ^[[:space:]]*# ]] && continue
|
||||
# Trim whitespace
|
||||
url=$(echo "$url" | xargs)
|
||||
[[ -z "$url" ]] && continue
|
||||
|
||||
# Extract base name from URL (remove .torrent extension)
|
||||
basename=$(basename "$url" .torrent)
|
||||
# Also try without .zim in case transmission reports it differently
|
||||
basename_no_zim="${basename%.zim}"
|
||||
|
||||
# Check if already in transmission
|
||||
if echo "$current" | grep -qF "$basename_no_zim"; then
|
||||
((skipped++)) || true
|
||||
else
|
||||
if transmission-remote "${TRANSMISSION_HOST}:${TRANSMISSION_PORT}" -a "$url" 2>/dev/null; then
|
||||
echo "Added: $basename"
|
||||
((added++)) || true
|
||||
else
|
||||
echo "Warning: Failed to add $url" >&2
|
||||
fi
|
||||
fi
|
||||
done < "$TORRENT_LIST"
|
||||
|
||||
echo "Sync complete: $added added, $skipped already present"
|
||||
61
argocd/manifests/kiwix/torrents.txt
Normal file
61
argocd/manifests/kiwix/torrents.txt
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Declarative ZIM archive torrent URLs
|
||||
# These are synced to transmission automatically by the kiwix sidecar
|
||||
# Format: one URL per line, comments start with #
|
||||
#
|
||||
# Users can also add ZIM torrents manually via torrent.tail8d86e.ts.net
|
||||
# and kiwix will pick them up automatically.
|
||||
|
||||
# Wikipedia - Top 1M English articles (43G)
|
||||
https://download.kiwix.org/zim/wikipedia/wikipedia_en_top1m_maxi_2025-09.zim.torrent
|
||||
|
||||
# Project Gutenberg - Public domain books (72G)
|
||||
https://download.kiwix.org/zim/gutenberg/gutenberg_en_all_2023-08.zim.torrent
|
||||
|
||||
# iFixit - Repair guides (3.3G)
|
||||
https://download.kiwix.org/zim/ifixit/ifixit_en_all_2025-12.zim.torrent
|
||||
|
||||
# Stack Exchange
|
||||
https://download.kiwix.org/zim/stack_exchange/superuser.com_en_all_2025-12.zim.torrent
|
||||
https://download.kiwix.org/zim/stack_exchange/math.stackexchange.com_en_all_2025-12.zim.torrent
|
||||
|
||||
# LibreTexts - Open educational resources
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_bio_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_chem_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_eng_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_math_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_phys_2025-01.zim.torrent
|
||||
https://download.kiwix.org/zim/libretexts/libretexts.org_en_human_2025-01.zim.torrent
|
||||
|
||||
# DevDocs - Programming documentation
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_bash_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_c_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_click_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_cmake_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_cpp_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_css_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_django-rest-framework_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_django_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_docker_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_duckdb_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_fish_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_gcc_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_git_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_go_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_godot_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_hammerspoon_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_homebrew_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_javascript_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_kubectl_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_kubernetes_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_latex_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_lua_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_markdown_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_nginx_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_nix_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_postgresql_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_python_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_redis_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_sqlite_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_typescript_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_werkzeug_2026-01.zim.torrent
|
||||
https://download.kiwix.org/zim/devdocs/devdocs_en_zig_2026-01.zim.torrent
|
||||
|
|
@ -18,7 +18,7 @@ spec:
|
|||
serviceAccountName: kube-state-metrics
|
||||
containers:
|
||||
- name: kube-state-metrics
|
||||
image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.18.0
|
||||
image: registry.k8s.io/kube-state-metrics/kube-state-metrics
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http-metrics
|
||||
|
|
|
|||
|
|
@ -4,3 +4,6 @@ resources:
|
|||
- rbac.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
images:
|
||||
- name: registry.k8s.io/kube-state-metrics/kube-state-metrics
|
||||
newTag: v2.18.0
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: loki-config
|
||||
namespace: monitoring
|
||||
data:
|
||||
loki-config.yaml: |
|
||||
auth_enabled: false
|
||||
|
||||
server:
|
||||
http_listen_port: 3100
|
||||
http_listen_address: 0.0.0.0
|
||||
grpc_listen_port: 9096
|
||||
|
||||
common:
|
||||
instance_addr: 127.0.0.1
|
||||
path_prefix: /loki
|
||||
storage:
|
||||
filesystem:
|
||||
chunks_directory: /loki/chunks
|
||||
rules_directory: /loki/rules
|
||||
replication_factor: 1
|
||||
ring:
|
||||
kvstore:
|
||||
store: inmemory
|
||||
|
||||
query_range:
|
||||
results_cache:
|
||||
cache:
|
||||
embedded_cache:
|
||||
enabled: true
|
||||
max_size_mb: 100
|
||||
|
||||
schema_config:
|
||||
configs:
|
||||
- from: 2024-01-01
|
||||
store: tsdb
|
||||
object_store: filesystem
|
||||
schema: v13
|
||||
index:
|
||||
prefix: index_
|
||||
period: 24h
|
||||
|
||||
storage_config:
|
||||
tsdb_shipper:
|
||||
active_index_directory: /loki/tsdb-index
|
||||
cache_location: /loki/tsdb-cache
|
||||
|
||||
limits_config:
|
||||
retention_period: 744h # 31 days
|
||||
|
||||
compactor:
|
||||
working_directory: /loki/compactor
|
||||
compaction_interval: 10m
|
||||
retention_enabled: true
|
||||
retention_delete_delay: 2h
|
||||
retention_delete_worker_count: 150
|
||||
delete_request_store: filesystem
|
||||
|
|
@ -4,7 +4,15 @@ kind: Kustomization
|
|||
namespace: monitoring
|
||||
|
||||
resources:
|
||||
- configmap.yaml
|
||||
- statefulset.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
|
||||
images:
|
||||
- name: grafana/loki
|
||||
newTag: "3.6.5"
|
||||
|
||||
configMapGenerator:
|
||||
- name: loki-config
|
||||
files:
|
||||
- loki-config.yaml
|
||||
|
|
|
|||
51
argocd/manifests/loki/loki-config.yaml
Normal file
51
argocd/manifests/loki/loki-config.yaml
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
auth_enabled: false
|
||||
|
||||
server:
|
||||
http_listen_port: 3100
|
||||
http_listen_address: 0.0.0.0
|
||||
grpc_listen_port: 9096
|
||||
|
||||
common:
|
||||
instance_addr: 127.0.0.1
|
||||
path_prefix: /loki
|
||||
storage:
|
||||
filesystem:
|
||||
chunks_directory: /loki/chunks
|
||||
rules_directory: /loki/rules
|
||||
replication_factor: 1
|
||||
ring:
|
||||
kvstore:
|
||||
store: inmemory
|
||||
|
||||
query_range:
|
||||
results_cache:
|
||||
cache:
|
||||
embedded_cache:
|
||||
enabled: true
|
||||
max_size_mb: 100
|
||||
|
||||
schema_config:
|
||||
configs:
|
||||
- from: 2024-01-01
|
||||
store: tsdb
|
||||
object_store: filesystem
|
||||
schema: v13
|
||||
index:
|
||||
prefix: index_
|
||||
period: 24h
|
||||
|
||||
storage_config:
|
||||
tsdb_shipper:
|
||||
active_index_directory: /loki/tsdb-index
|
||||
cache_location: /loki/tsdb-cache
|
||||
|
||||
limits_config:
|
||||
retention_period: 744h # 31 days
|
||||
|
||||
compactor:
|
||||
working_directory: /loki/compactor
|
||||
compaction_interval: 10m
|
||||
retention_enabled: true
|
||||
retention_delete_delay: 2h
|
||||
retention_delete_worker_count: 150
|
||||
delete_request_store: filesystem
|
||||
|
|
@ -20,7 +20,7 @@ spec:
|
|||
runAsUser: 10001
|
||||
containers:
|
||||
- name: loki
|
||||
image: grafana/loki:3.6.5
|
||||
image: grafana/loki
|
||||
args:
|
||||
- -config.file=/etc/loki/loki-config.yaml
|
||||
ports:
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: miniflux
|
||||
image: registry.ops.eblu.me/blumeops/miniflux:v2.2.17-a72a0d8
|
||||
image: registry.ops.eblu.me/blumeops/miniflux
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
|
|
|
|||
|
|
@ -7,3 +7,7 @@ resources:
|
|||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/miniflux
|
||||
newTag: v2.2.17-a72a0d8
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: mosquitto-config
|
||||
namespace: mqtt
|
||||
data:
|
||||
mosquitto.conf: |
|
||||
listener 1883
|
||||
allow_anonymous true
|
||||
persistence false
|
||||
|
|
@ -16,7 +16,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: mosquitto
|
||||
image: eclipse-mosquitto:2.0.22
|
||||
image: eclipse-mosquitto
|
||||
ports:
|
||||
- containerPort: 1883
|
||||
name: mqtt
|
||||
|
|
|
|||
|
|
@ -3,6 +3,12 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
|||
kind: Kustomization
|
||||
namespace: mqtt
|
||||
resources:
|
||||
- configmap.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
images:
|
||||
- name: eclipse-mosquitto
|
||||
newTag: "2.0.22"
|
||||
configMapGenerator:
|
||||
- name: mosquitto-config
|
||||
files:
|
||||
- mosquitto.conf
|
||||
|
|
|
|||
3
argocd/manifests/mosquitto/mosquitto.conf
Normal file
3
argocd/manifests/mosquitto/mosquitto.conf
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
listener 1883
|
||||
allow_anonymous true
|
||||
persistence false
|
||||
|
|
@ -20,7 +20,7 @@ spec:
|
|||
fsGroup: 1000
|
||||
containers:
|
||||
- name: navidrome
|
||||
image: registry.ops.eblu.me/blumeops/navidrome:v0.60.3-a72a0d8
|
||||
image: registry.ops.eblu.me/blumeops/navidrome
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
|
|
|
|||
|
|
@ -9,3 +9,6 @@ resources:
|
|||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/navidrome
|
||||
newTag: v0.60.3-a72a0d8
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: ntfy-config
|
||||
namespace: ntfy
|
||||
data:
|
||||
server.yml: |
|
||||
base-url: https://ntfy.ops.eblu.me
|
||||
upstream-base-url: https://ntfy.sh
|
||||
attachment-cache-dir: /var/cache/ntfy/attachments
|
||||
attachment-total-size-limit: 1G
|
||||
attachment-file-size-limit: 10M
|
||||
attachment-expiry-duration: 24h
|
||||
|
|
@ -16,7 +16,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: ntfy
|
||||
image: registry.ops.eblu.me/blumeops/ntfy:v2.17.0-ffa8727-nix
|
||||
image: registry.ops.eblu.me/blumeops/ntfy
|
||||
args: ["serve", "--config", "/etc/ntfy/server.yml"]
|
||||
ports:
|
||||
- containerPort: 80
|
||||
|
|
|
|||
|
|
@ -3,7 +3,13 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
|||
kind: Kustomization
|
||||
namespace: ntfy
|
||||
resources:
|
||||
- configmap.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/ntfy
|
||||
newTag: v2.17.0-ffa8727-nix
|
||||
configMapGenerator:
|
||||
- name: ntfy-config
|
||||
files:
|
||||
- server.yml
|
||||
|
|
|
|||
6
argocd/manifests/ntfy/server.yml
Normal file
6
argocd/manifests/ntfy/server.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
base-url: https://ntfy.ops.eblu.me
|
||||
upstream-base-url: https://ntfy.sh
|
||||
attachment-cache-dir: /var/cache/ntfy/attachments
|
||||
attachment-total-size-limit: 1G
|
||||
attachment-file-size-limit: 10M
|
||||
attachment-expiry-duration: 24h
|
||||
|
|
@ -22,7 +22,7 @@ spec:
|
|||
priorityClassName: system-node-critical
|
||||
containers:
|
||||
- name: nvidia-device-plugin
|
||||
image: nvcr.io/nvidia/k8s-device-plugin:v0.18.2
|
||||
image: nvcr.io/nvidia/k8s-device-plugin
|
||||
args:
|
||||
- --device-id-strategy=index
|
||||
env:
|
||||
|
|
|
|||
12
argocd/manifests/nvidia-device-plugin/kustomization.yaml
Normal file
12
argocd/manifests/nvidia-device-plugin/kustomization.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: nvidia-device-plugin
|
||||
|
||||
resources:
|
||||
- daemonset.yaml
|
||||
- runtime-class.yaml
|
||||
|
||||
images:
|
||||
- name: nvcr.io/nvidia/k8s-device-plugin
|
||||
newTag: v0.18.2
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: prometheus-config
|
||||
namespace: monitoring
|
||||
data:
|
||||
prometheus.yml: |
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
# Indri system metrics are pushed via Alloy remote_write
|
||||
# K8s services are scraped directly
|
||||
|
||||
scrape_configs:
|
||||
# Sifaka NAS exporters (via Caddy L4 TCP proxy on indri)
|
||||
- job_name: "node-exporter-sifaka"
|
||||
static_configs:
|
||||
- targets: ["nas.ops.eblu.me:9100"]
|
||||
|
||||
- job_name: "smartctl-sifaka"
|
||||
scrape_interval: 60s
|
||||
static_configs:
|
||||
- targets: ["nas.ops.eblu.me:9633"]
|
||||
|
||||
# CNPG PostgreSQL metrics (k8s internal)
|
||||
- job_name: "cnpg-postgres"
|
||||
static_configs:
|
||||
- targets: ["blumeops-pg-metrics-tailscale.databases.svc.cluster.local:9187"]
|
||||
labels:
|
||||
instance: "blumeops-pg"
|
||||
|
||||
# Prometheus self-monitoring
|
||||
- job_name: "prometheus"
|
||||
static_configs:
|
||||
- targets: ["localhost:9090"]
|
||||
|
||||
# Loki metrics
|
||||
- job_name: "loki"
|
||||
static_configs:
|
||||
- targets: ["loki.monitoring.svc.cluster.local:3100"]
|
||||
|
||||
# Kubernetes state metrics (pods, deployments, resource usage, etc.)
|
||||
- job_name: "kube-state-metrics"
|
||||
static_configs:
|
||||
- targets: ["kube-state-metrics.monitoring.svc.cluster.local:8080"]
|
||||
|
||||
# Frigate NVR metrics (via Caddy on indri — Frigate runs on ringtail)
|
||||
- job_name: "frigate"
|
||||
scheme: https
|
||||
static_configs:
|
||||
- targets: ["nvr.ops.eblu.me"]
|
||||
metrics_path: /api/metrics
|
||||
|
|
@ -4,7 +4,15 @@ kind: Kustomization
|
|||
namespace: monitoring
|
||||
|
||||
resources:
|
||||
- configmap.yaml
|
||||
- statefulset.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/prometheus
|
||||
newTag: v3.9.1-2ba5d8a
|
||||
|
||||
configMapGenerator:
|
||||
- name: prometheus-config
|
||||
files:
|
||||
- prometheus.yml
|
||||
|
|
|
|||
46
argocd/manifests/prometheus/prometheus.yml
Normal file
46
argocd/manifests/prometheus/prometheus.yml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
# Indri system metrics are pushed via Alloy remote_write
|
||||
# K8s services are scraped directly
|
||||
|
||||
scrape_configs:
|
||||
# Sifaka NAS exporters (via Caddy L4 TCP proxy on indri)
|
||||
- job_name: "node-exporter-sifaka"
|
||||
static_configs:
|
||||
- targets: ["nas.ops.eblu.me:9100"]
|
||||
|
||||
- job_name: "smartctl-sifaka"
|
||||
scrape_interval: 60s
|
||||
static_configs:
|
||||
- targets: ["nas.ops.eblu.me:9633"]
|
||||
|
||||
# CNPG PostgreSQL metrics (k8s internal)
|
||||
- job_name: "cnpg-postgres"
|
||||
static_configs:
|
||||
- targets: ["blumeops-pg-metrics-tailscale.databases.svc.cluster.local:9187"]
|
||||
labels:
|
||||
instance: "blumeops-pg"
|
||||
|
||||
# Prometheus self-monitoring
|
||||
- job_name: "prometheus"
|
||||
static_configs:
|
||||
- targets: ["localhost:9090"]
|
||||
|
||||
# Loki metrics
|
||||
- job_name: "loki"
|
||||
static_configs:
|
||||
- targets: ["loki.monitoring.svc.cluster.local:3100"]
|
||||
|
||||
# Kubernetes state metrics (pods, deployments, resource usage, etc.)
|
||||
- job_name: "kube-state-metrics"
|
||||
static_configs:
|
||||
- targets: ["kube-state-metrics.monitoring.svc.cluster.local:8080"]
|
||||
|
||||
# Frigate NVR metrics (via Caddy on indri — Frigate runs on ringtail)
|
||||
- job_name: "frigate"
|
||||
scheme: https
|
||||
static_configs:
|
||||
- targets: ["nvr.ops.eblu.me"]
|
||||
metrics_path: /api/metrics
|
||||
|
|
@ -20,7 +20,7 @@ spec:
|
|||
runAsUser: 65534
|
||||
containers:
|
||||
- name: prometheus
|
||||
image: registry.ops.eblu.me/blumeops/prometheus:v3.9.1-2ba5d8a
|
||||
image: registry.ops.eblu.me/blumeops/prometheus
|
||||
args:
|
||||
- --config.file=/etc/prometheus/prometheus.yml
|
||||
- --storage.tsdb.path=/prometheus
|
||||
|
|
|
|||
|
|
@ -8,3 +8,7 @@ resources:
|
|||
- operator.yaml
|
||||
- proxyclass.yaml
|
||||
- dnsconfig.yaml
|
||||
|
||||
images:
|
||||
- name: docker.io/tailscale/k8s-operator
|
||||
newTag: v1.94.2
|
||||
|
|
|
|||
|
|
@ -5362,7 +5362,7 @@ spec:
|
|||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.uid
|
||||
image: docker.io/tailscale/k8s-operator:v1.94.2
|
||||
image: docker.io/tailscale/k8s-operator
|
||||
imagePullPolicy: Always
|
||||
name: operator
|
||||
volumeMounts:
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: teslamate
|
||||
image: registry.ops.eblu.me/blumeops/teslamate:v2.2.0-ffa8727
|
||||
image: registry.ops.eblu.me/blumeops/teslamate
|
||||
ports:
|
||||
- containerPort: 4000
|
||||
env:
|
||||
|
|
|
|||
|
|
@ -9,3 +9,7 @@ resources:
|
|||
- ingress-tailscale.yaml
|
||||
- external-secret-db.yaml
|
||||
- external-secret-encryption-key.yaml
|
||||
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/teslamate
|
||||
newTag: v2.2.0-ffa8727
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: transmission
|
||||
image: registry.ops.eblu.me/blumeops/transmission:v4.0.6-r4-ffa8727
|
||||
image: registry.ops.eblu.me/blumeops/transmission
|
||||
env:
|
||||
- name: PUID
|
||||
value: "1000"
|
||||
|
|
|
|||
|
|
@ -8,3 +8,6 @@ resources:
|
|||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress-tailscale.yaml
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/transmission
|
||||
newTag: v4.0.6-r4-ffa8727
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue