Add kustomize images: transformer and configMapGenerator across services
Move hardcoded image tags to kustomization.yaml images: sections (22 services) and replace hand-written ConfigMap manifests with configMapGenerator (12 services). Image tags are now centralized in kustomization.yaml, and generated ConfigMaps include content hashes that trigger automatic pod rollouts on config changes. New kustomization.yaml files for forgejo-runner and nvidia-device-plugin switch ArgoCD from directory mode to kustomize mode. Skipped: argocd (remote upstream), databases, external-secrets, grafana-config (cross-kustomization dashboards), immich (Helm), authentik blueprints (special YAML tags). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
86aeb60ec9
commit
34925cb94b
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
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Move image tags to kustomize `images:` transformer across 22 services and replace hand-written ConfigMaps with `configMapGenerator:` in 12 services, enabling content-hash-based automatic rollouts on config changes.
|
||||
Loading…
Add table
Add a link
Reference in a new issue