diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a2b8669..7227fd5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -89,12 +89,22 @@ repos: args: ['-config-file', '.github/actionlint.yaml'] files: ^\.forgejo/workflows/ - # Documentation - check for duplicate filenames (required for Quartz shortest path resolution) + # Documentation - check for duplicate titles (required for Quartz wiki-link resolution) - repo: local hooks: - - id: doc-filenames - name: doc-filenames - entry: mise run doc-filenames + - id: doc-titles + name: doc-titles + entry: mise run doc-titles + language: system + files: ^docs/.*\.md$ + pass_filenames: false + + # Documentation - validate wiki-links point to existing titles + - repo: local + hooks: + - id: doc-links + name: doc-links + entry: mise run doc-links language: system files: ^docs/.*\.md$ pass_filenames: false diff --git a/docs/README.md b/docs/README.md index dc472e2..11ecac7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,7 @@ +--- +title: README +--- + # BlumeOps Documentation > **Note on naming**: The project is properly stylized as **BlumeOps**, though "blumeops" and "Blue Mops" are also commonly used interchangeably. diff --git a/docs/changelog.d/title-based-links.doc.md b/docs/changelog.d/title-based-links.doc.md new file mode 100644 index 0000000..665a2c0 --- /dev/null +++ b/docs/changelog.d/title-based-links.doc.md @@ -0,0 +1 @@ +Switch to title-based wiki-links with validation (Quartz resolves via frontmatter title) diff --git a/docs/index.md b/docs/index.md index 61f97e9..b3c9324 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,4 +8,4 @@ Welcome to the BlumeOps documentation. ## Sections -- [[reference/index|Reference]] - Technical reference cards for services, infrastructure, and operations +- [[Reference]] - Technical reference cards for services, infrastructure, and operations diff --git a/docs/reference/index.md b/docs/reference/index.md index 413fe26..cbce315 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -14,54 +14,54 @@ Individual service reference cards with URLs and configuration details. | Service | Description | Location | |---------|-------------|----------| -| [[alloy|Alloy]] | Observability collector (metrics & logs) | indri + k8s | -| [[argocd|ArgoCD]] | GitOps continuous delivery | k8s | -| [[borgmatic|Borgmatic]] | Backup system | indri | -| [[1password|1Password]] | Secrets management | cloud + k8s | -| [[forgejo|Forgejo]] | Git forge & CI/CD | indri | -| [[grafana|Grafana]] | Dashboards & visualization | k8s | -| [[immich|Immich]] | Photo management | k8s | -| [[jellyfin|Jellyfin]] | Media server | indri | -| [[kiwix|Kiwix]] | Offline Wikipedia & ZIM archives | k8s | -| [[loki|Loki]] | Log aggregation | k8s | -| [[miniflux|Miniflux]] | RSS feed reader | k8s | -| [[navidrome|Navidrome]] | Music streaming | k8s | -| [[postgresql|PostgreSQL]] | Database cluster | k8s | -| [[prometheus|Prometheus]] | Metrics collection | k8s | -| [[teslamate|TeslaMate]] | Tesla data logger | k8s | -| [[transmission|Transmission]] | BitTorrent daemon | k8s | -| [[zot|Zot]] | Container registry | indri | +| [[Grafana Alloy|Alloy]] | Observability collector (metrics & logs) | indri + k8s | +| [[ArgoCD]] | GitOps continuous delivery | k8s | +| [[Borgmatic]] | Backup system | indri | +| [[1Password]] | Secrets management | cloud + k8s | +| [[Forgejo]] | Git forge & CI/CD | indri | +| [[Grafana]] | Dashboards & visualization | k8s | +| [[Immich]] | Photo management | k8s | +| [[Jellyfin]] | Media server | indri | +| [[Kiwix]] | Offline Wikipedia & ZIM archives | k8s | +| [[Loki]] | Log aggregation | k8s | +| [[Miniflux]] | RSS feed reader | k8s | +| [[Navidrome]] | Music streaming | k8s | +| [[PostgreSQL]] | Database cluster | k8s | +| [[Prometheus]] | Metrics collection | k8s | +| [[TeslaMate]] | Tesla data logger | k8s | +| [[Transmission]] | BitTorrent daemon | k8s | +| [[Zot]] | Container registry | indri | ## Infrastructure Host inventory and network configuration. -- [[hosts|Hosts]] - Device inventory -- [[indri|Indri]] - Primary server -- [[gilbert|Gilbert]] - Development workstation -- [[tailscale|Tailscale]] - ACLs, groups, tags -- [[routing|Routing]] - DNS domains, port mappings +- [[Host Inventory|Hosts]] - Device inventory +- [[Indri]] - Primary server +- [[Gilbert]] - Development workstation +- [[Tailscale]] - ACLs, groups, tags +- [[Service Routing|Routing]] - DNS domains, port mappings ## Kubernetes Cluster configuration and application registry. -- [[cluster|Cluster]] - Minikube specs, storage, networking -- [[apps|Apps]] - ArgoCD application registry -- [[external-secrets|External Secrets]] - Secrets management +- [[Kubernetes Cluster|Cluster]] - Minikube specs, storage, networking +- [[ArgoCD Applications|Apps]] - ArgoCD application registry +- [[External Secrets]] - Secrets management ## Storage Network storage and backup configuration. -- [[sifaka|Sifaka]] - Synology NAS configuration -- [[postgresql-storage|PostgreSQL Storage]] - Database cluster -- [[backups|Backups]] - Backup policy and schedule +- [[Sifaka NAS|Sifaka]] - Synology NAS configuration +- [[PostgreSQL Storage]] - Database cluster +- [[Backup Policy|Backups]] - Backup policy and schedule ## Operations Operational concerns and their components. -- [[observability|Observability]] - Metrics, logs, dashboards -- [[backup|Backup]] - Data protection -- [[disaster-recovery|Disaster Recovery]] - Recovery procedures (TBD) +- [[Observability]] - Metrics, logs, dashboards +- [[Backup]] - Data protection +- [[Disaster Recovery]] - Recovery procedures (TBD) diff --git a/docs/reference/infrastructure/gilbert.md b/docs/reference/infrastructure/gilbert.md index 95b32d2..7f08799 100644 --- a/docs/reference/infrastructure/gilbert.md +++ b/docs/reference/infrastructure/gilbert.md @@ -23,5 +23,5 @@ Managed via `Brewfile` and `mise.toml` in the blumeops repo. ## Related -- [[indri|Indri]] - Server accessed from gilbert -- [[cluster|Cluster]] - Remote k8s access +- [[Indri]] - Server accessed from gilbert +- [[Kubernetes Cluster|Cluster]] - Remote k8s access diff --git a/docs/reference/infrastructure/hosts.md b/docs/reference/infrastructure/hosts.md index a0e2475..bc11b36 100644 --- a/docs/reference/infrastructure/hosts.md +++ b/docs/reference/infrastructure/hosts.md @@ -12,14 +12,14 @@ All devices connected via [Tailscale](https://login.tailscale.com/) tailnet `tai | Host | Description | Card | |------|-------------|------| -| **Indri** | Mac Mini M1, 2020 - Primary server | [[indri|Details]] | -| **Gilbert** | MacBook Air M4, 2025 - Workstation | [[gilbert|Details]] | -| **[[sifaka|Sifaka]]** | Synology NAS - Storage & backups | [[sifaka|Details]] | +| **Indri** | Mac Mini M1, 2020 - Primary server | [[Indri|Details]] | +| **Gilbert** | MacBook Air M4, 2025 - Workstation | [[Gilbert|Details]] | +| **[[Sifaka NAS|Sifaka]]** | Synology NAS - Storage & backups | [[Sifaka NAS|Details]] | | **Mouse** | MacBook Air M2 - Allison's laptop | - | | **UniFi** | UniFi Express 7 - Home WiFi | - | | **Dwarf** | iPad Air - Employer-provided, off tailnet | - | ## Related -- [[tailscale|Tailscale]] - Network configuration -- [[routing|Routing]] - Service URLs +- [[Tailscale]] - Network configuration +- [[Service Routing|Routing]] - Service URLs diff --git a/docs/reference/infrastructure/indri.md b/docs/reference/infrastructure/indri.md index 475ab41..b93277e 100644 --- a/docs/reference/infrastructure/indri.md +++ b/docs/reference/infrastructure/indri.md @@ -22,17 +22,17 @@ Primary BlumeOps server. Mac Mini M1 (2020). ## Services Hosted **Native (via Ansible):** -- [[forgejo|Forgejo]] - Git forge -- [[zot|Zot]] - Container registry -- [[jellyfin|Jellyfin]] - Media server -- [[borgmatic|Borgmatic]] - Backup system -- [[alloy|Alloy]] - Metrics/logs collector +- [[Forgejo]] - Git forge +- [[Zot]] - Container registry +- [[Jellyfin]] - Media server +- [[Borgmatic]] - Backup system +- [[Grafana Alloy|Alloy]] - Metrics/logs collector - Caddy - Reverse proxy for `*.ops.eblu.me` **Kubernetes (via minikube):** -- [[apps|All k8s applications]] +- [[ArgoCD Applications|All k8s applications]] ## Related -- [[routing|Routing]] - Port mappings -- [[cluster|Cluster]] - Minikube details +- [[Service Routing|Routing]] - Port mappings +- [[Kubernetes Cluster|Cluster]] - Minikube details diff --git a/docs/reference/infrastructure/routing.md b/docs/reference/infrastructure/routing.md index 972aafa..476b9b3 100644 --- a/docs/reference/infrastructure/routing.md +++ b/docs/reference/infrastructure/routing.md @@ -25,20 +25,20 @@ DNS points to indri's Tailscale IP (100.98.163.89). TLS via Let's Encrypt (ACME | Service | URL | Description | |---------|-----|-------------| | Homepage | https://go.ops.eblu.me | Service dashboard | -| [[forgejo|Forgejo]] | https://forge.ops.eblu.me | Git hosting (SSH: 2222) | -| [[zot|Zot]] | https://registry.ops.eblu.me | Container registry | -| [[grafana|Grafana]] | https://grafana.ops.eblu.me | Dashboards | -| [[argocd|ArgoCD]] | https://argocd.ops.eblu.me | GitOps CD | -| [[prometheus|Prometheus]] | https://prometheus.ops.eblu.me | Metrics | -| [[loki|Loki]] | https://loki.ops.eblu.me | Logs | -| [[miniflux|Miniflux]] | https://feed.ops.eblu.me | RSS reader | -| [[kiwix|Kiwix]] | https://kiwix.ops.eblu.me | Offline Wikipedia | -| [[transmission|Transmission]] | https://torrent.ops.eblu.me | BitTorrent | -| [[teslamate|TeslaMate]] | https://tesla.ops.eblu.me | Tesla logger | -| [[navidrome|Navidrome]] | https://dj.ops.eblu.me | Music streaming | -| [[jellyfin|Jellyfin]] | https://jellyfin.ops.eblu.me | Media server | -| [[postgresql|PostgreSQL]] | pg.ops.eblu.me:5432 | Database | -| [[sifaka|Sifaka]] | https://nas.ops.eblu.me | NAS dashboard | +| [[Forgejo]] | https://forge.ops.eblu.me | Git hosting (SSH: 2222) | +| [[Zot]] | https://registry.ops.eblu.me | Container registry | +| [[Grafana]] | https://grafana.ops.eblu.me | Dashboards | +| [[ArgoCD]] | https://argocd.ops.eblu.me | GitOps CD | +| [[Prometheus]] | https://prometheus.ops.eblu.me | Metrics | +| [[Loki]] | https://loki.ops.eblu.me | Logs | +| [[Miniflux]] | https://feed.ops.eblu.me | RSS reader | +| [[Kiwix]] | https://kiwix.ops.eblu.me | Offline Wikipedia | +| [[Transmission]] | https://torrent.ops.eblu.me | BitTorrent | +| [[TeslaMate]] | https://tesla.ops.eblu.me | Tesla logger | +| [[Navidrome]] | https://dj.ops.eblu.me | Music streaming | +| [[Jellyfin]] | https://jellyfin.ops.eblu.me | Media server | +| [[PostgreSQL]] | pg.ops.eblu.me:5432 | Database | +| [[Sifaka NAS|Sifaka]] | https://nas.ops.eblu.me | NAS dashboard | ## Tailscale-Only Services @@ -61,5 +61,5 @@ DNS points to indri's Tailscale IP (100.98.163.89). TLS via Let's Encrypt (ACME ## Related -- [[tailscale|Tailscale]] - ACL configuration -- [[indri|Indri]] - Where services run +- [[Tailscale]] - ACL configuration +- [[Indri]] - Where services run diff --git a/docs/reference/infrastructure/tailscale.md b/docs/reference/infrastructure/tailscale.md index 8786512..9e89e71 100644 --- a/docs/reference/infrastructure/tailscale.md +++ b/docs/reference/infrastructure/tailscale.md @@ -17,7 +17,7 @@ ACLs managed via Pulumi in `pulumi/policy.hujson`. | Group | Members | Purpose | |-------|---------|---------| -| `group:allisonflix` | admin, member | [[jellyfin|Jellyfin]] media access | +| `group:allisonflix` | admin, member | [[Jellyfin]] media access | ## Device Tags @@ -58,5 +58,5 @@ Pulumi uses OAuth client from 1Password (blumeops vault): ## Related -- [[routing|Routing]] - Service URLs -- [[hosts|Hosts]] - Device inventory +- [[Service Routing|Routing]] - Service URLs +- [[Host Inventory|Hosts]] - Device inventory diff --git a/docs/reference/kubernetes/apps.md b/docs/reference/kubernetes/apps.md index b844f54..029601f 100644 --- a/docs/reference/kubernetes/apps.md +++ b/docs/reference/kubernetes/apps.md @@ -7,33 +7,33 @@ tags: # ArgoCD Applications -Registry of all applications deployed via [[argocd|ArgoCD]]. +Registry of all applications deployed via [[ArgoCD]]. ## Application Registry | App | Namespace | Path/Source | Service | |-----|-----------|-------------|---------| | `apps` | argocd | `argocd/apps/` | App-of-apps root | -| `argocd` | argocd | `argocd/manifests/argocd/` | [[argocd|ArgoCD]] | +| `argocd` | argocd | `argocd/manifests/argocd/` | [[ArgoCD]] | | `tailscale-operator` | tailscale | `argocd/manifests/tailscale-operator/` | Tailscale k8s operator | -| `1password-connect` | 1password | `argocd/manifests/1password-connect/` | [[1password|1Password]] | -| `external-secrets` | external-secrets | Helm chart | [[1password|1Password]] | -| `external-secrets-config` | external-secrets | `argocd/manifests/external-secrets-config/` | [[1password|1Password]] | +| `1password-connect` | 1password | `argocd/manifests/1password-connect/` | [[1Password]] | +| `external-secrets` | external-secrets | Helm chart | [[1Password]] | +| `external-secrets-config` | external-secrets | `argocd/manifests/external-secrets-config/` | [[1Password]] | | `cloudnative-pg` | cnpg-system | Helm chart (forge mirror) | PostgreSQL operator | -| `blumeops-pg` | databases | `argocd/manifests/databases/` | [[postgresql|PostgreSQL]] | -| `prometheus` | monitoring | `argocd/manifests/prometheus/` | [[prometheus|Prometheus]] | -| `loki` | monitoring | `argocd/manifests/loki/` | [[loki|Loki]] | -| `grafana` | monitoring | Helm chart (forge mirror) | [[grafana|Grafana]] | -| `grafana-config` | monitoring | `argocd/manifests/grafana-config/` | [[grafana|Grafana]] | -| `immich` | immich | Helm chart | [[immich|Immich]] | -| `alloy-k8s` | alloy | `argocd/manifests/alloy-k8s/` | [[alloy|Alloy]] | +| `blumeops-pg` | databases | `argocd/manifests/databases/` | [[PostgreSQL]] | +| `prometheus` | monitoring | `argocd/manifests/prometheus/` | [[Prometheus]] | +| `loki` | monitoring | `argocd/manifests/loki/` | [[Loki]] | +| `grafana` | monitoring | Helm chart (forge mirror) | [[Grafana]] | +| `grafana-config` | monitoring | `argocd/manifests/grafana-config/` | [[Grafana]] | +| `immich` | immich | Helm chart | [[Immich]] | +| `alloy-k8s` | alloy | `argocd/manifests/alloy-k8s/` | [[Grafana Alloy|Alloy]] | | `kube-state-metrics` | monitoring | `argocd/manifests/kube-state-metrics/` | K8s metrics | -| `miniflux` | miniflux | `argocd/manifests/miniflux/` | [[miniflux|Miniflux]] | -| `kiwix` | kiwix | `argocd/manifests/kiwix/` | [[kiwix|Kiwix]] | -| `torrent` | torrent | `argocd/manifests/torrent/` | [[transmission|Transmission]] | -| `navidrome` | navidrome | `argocd/manifests/navidrome/` | [[navidrome|Navidrome]] | -| `teslamate` | teslamate | `argocd/manifests/teslamate/` | [[teslamate|TeslaMate]] | -| `forgejo-runner` | forgejo-runner | `argocd/manifests/forgejo-runner/` | [[forgejo|Forgejo]] CI | +| `miniflux` | miniflux | `argocd/manifests/miniflux/` | [[Miniflux]] | +| `kiwix` | kiwix | `argocd/manifests/kiwix/` | [[Kiwix]] | +| `torrent` | torrent | `argocd/manifests/torrent/` | [[Transmission]] | +| `navidrome` | navidrome | `argocd/manifests/navidrome/` | [[Navidrome]] | +| `teslamate` | teslamate | `argocd/manifests/teslamate/` | [[TeslaMate]] | +| `forgejo-runner` | forgejo-runner | `argocd/manifests/forgejo-runner/` | [[Forgejo]] CI | ## Sync Policies @@ -44,5 +44,5 @@ Registry of all applications deployed via [[argocd|ArgoCD]]. ## Related -- [[argocd|ArgoCD]] - GitOps platform details -- [[cluster|Cluster]] - Kubernetes infrastructure +- [[ArgoCD]] - GitOps platform details +- [[Kubernetes Cluster|Cluster]] - Kubernetes infrastructure diff --git a/docs/reference/kubernetes/cluster.md b/docs/reference/kubernetes/cluster.md index 1aceb3f..31fcc35 100644 --- a/docs/reference/kubernetes/cluster.md +++ b/docs/reference/kubernetes/cluster.md @@ -6,7 +6,7 @@ tags: # Kubernetes Cluster -Single-node Minikube cluster running on [[indri|Indri]]. +Single-node Minikube cluster running on [[Indri]]. ## Cluster Specifications @@ -24,16 +24,16 @@ Single-node Minikube cluster running on [[indri|Indri]]. ## Volume Mounting -Pods mount NFS directly from [[sifaka|Sifaka]]. Docker NATs outbound traffic through indri's LAN IP (192.168.1.50), allowing access to Sifaka's NFS exports. +Pods mount NFS directly from [[Sifaka NAS|Sifaka]]. Docker NATs outbound traffic through indri's LAN IP (192.168.1.50), allowing access to Sifaka's NFS exports. ## Registry Mirror -Containerd uses [[zot|Zot]] as a pull-through cache at `host.minikube.internal:5050`. +Containerd uses [[Zot]] as a pull-through cache at `host.minikube.internal:5050`. Mirrors configured: `registry.ops.eblu.me`, `docker.io`, `ghcr.io`, `quay.io` ## Related -- [[apps|Apps]] - ArgoCD applications -- [[argocd|ArgoCD]] - GitOps deployment -- [[zot|Zot]] - Registry mirror +- [[ArgoCD Applications|Apps]] - ArgoCD applications +- [[ArgoCD]] - GitOps deployment +- [[Zot]] - Registry mirror diff --git a/docs/reference/kubernetes/external-secrets.md b/docs/reference/kubernetes/external-secrets.md index 95da276..2b814e8 100644 --- a/docs/reference/kubernetes/external-secrets.md +++ b/docs/reference/kubernetes/external-secrets.md @@ -7,4 +7,4 @@ tags: # External Secrets -See [[1password|1Password]] in Services. +See [[1Password]] in Services. diff --git a/docs/reference/operations/backup.md b/docs/reference/operations/backup.md index a67a3ba..fa0c627 100644 --- a/docs/reference/operations/backup.md +++ b/docs/reference/operations/backup.md @@ -10,6 +10,6 @@ Daily automated backups of BlumeOps data. ## Components -- [[borgmatic|Borgmatic]] - Backup orchestration -- [[sifaka|Sifaka]] - Backup target (NAS) -- [[backups|Backup Policy]] - What gets backed up and retention +- [[Borgmatic]] - Backup orchestration +- [[Sifaka NAS|Sifaka]] - Backup target (NAS) +- [[Backup Policy]] - What gets backed up and retention diff --git a/docs/reference/operations/disaster-recovery.md b/docs/reference/operations/disaster-recovery.md index 9038201..e32be67 100644 --- a/docs/reference/operations/disaster-recovery.md +++ b/docs/reference/operations/disaster-recovery.md @@ -8,12 +8,12 @@ tags: TBD. Current state: -- [[borgmatic|Borgmatic]] provides daily backups to [[sifaka|Sifaka]] +- [[Borgmatic]] provides daily backups to [[Sifaka NAS|Sifaka]] - Infrastructure can be rebootstrapped using the blumeops repo - Detailed DR procedures not yet documented ## Components -- [[borgmatic|Borgmatic]] - Backup restoration -- [[1password|1Password]] - Credential recovery -- [[forgejo|Forgejo]] - Source of truth for infrastructure code +- [[Borgmatic]] - Backup restoration +- [[1Password]] - Credential recovery +- [[Forgejo]] - Source of truth for infrastructure code diff --git a/docs/reference/operations/observability.md b/docs/reference/operations/observability.md index 3d7da3e..1e79c07 100644 --- a/docs/reference/operations/observability.md +++ b/docs/reference/operations/observability.md @@ -10,7 +10,7 @@ Metrics, logs, and dashboards for BlumeOps infrastructure. ## Components -- [[prometheus|Prometheus]] - Metrics storage and querying -- [[loki|Loki]] - Log aggregation -- [[alloy|Alloy]] - Metrics and log collection -- [[grafana|Grafana]] - Dashboards and visualization +- [[Prometheus]] - Metrics storage and querying +- [[Loki]] - Log aggregation +- [[Grafana Alloy|Alloy]] - Metrics and log collection +- [[Grafana]] - Dashboards and visualization diff --git a/docs/reference/services/1password.md b/docs/reference/services/1password.md index fff91ba..2db7f59 100644 --- a/docs/reference/services/1password.md +++ b/docs/reference/services/1password.md @@ -36,5 +36,5 @@ Services reference 1Password items via `ExternalSecret` manifests. ## Related -- [[argocd|ArgoCD]] - Uses secrets for git access -- [[postgresql|PostgreSQL]] - Database credentials +- [[ArgoCD]] - Uses secrets for git access +- [[PostgreSQL]] - Database credentials diff --git a/docs/reference/services/alloy.md b/docs/reference/services/alloy.md index 1135c66..cad2669 100644 --- a/docs/reference/services/alloy.md +++ b/docs/reference/services/alloy.md @@ -27,7 +27,7 @@ Unified observability collector for metrics and logs with two deployments: - System metrics via `prometheus.exporter.unix` - Textfile collector: `minikube.prom`, `borgmatic.prom`, `zot.prom`, `jellyfin.prom` - Zot registry metrics from `http://localhost:5050/metrics` -- Pushed to [[prometheus|Prometheus]] via remote_write +- Pushed to [[Prometheus]] via remote_write ### From Kubernetes - All pod logs via `loki.source.kubernetes` @@ -39,7 +39,7 @@ Unified observability collector for metrics and logs with two deployments: **mcquack LaunchAgents:** alloy, borgmatic, zot, jellyfin -Logs pushed to [[loki|Loki]] at `https://loki.tail8d86e.ts.net/loki/api/v1/push`. +Logs pushed to [[Loki]] at `https://loki.tail8d86e.ts.net/loki/api/v1/push`. ## Why Built from Source @@ -49,6 +49,6 @@ The Homebrew bottle uses `CGO_ENABLED=0`, which breaks Tailscale MagicDNS. Build ## Related -- [[prometheus|Prometheus]] - Metrics storage -- [[loki|Loki]] - Log storage -- [[grafana|Grafana]] - Visualization +- [[Prometheus]] - Metrics storage +- [[Loki]] - Log storage +- [[Grafana]] - Visualization diff --git a/docs/reference/services/argocd.md b/docs/reference/services/argocd.md index f327b99..b944d7f 100644 --- a/docs/reference/services/argocd.md +++ b/docs/reference/services/argocd.md @@ -7,7 +7,7 @@ tags: # ArgoCD -GitOps continuous delivery platform for the [[cluster|Kubernetes cluster]]. +GitOps continuous delivery platform for the [[Kubernetes Cluster|Kubernetes cluster]]. ## Quick Reference @@ -33,5 +33,5 @@ GitOps continuous delivery platform for the [[cluster|Kubernetes cluster]]. ## Related -- [[apps|Apps]] - Full application registry -- [[forgejo|Forgejo]] - Git source +- [[ArgoCD Applications|Apps]] - Full application registry +- [[Forgejo]] - Git source diff --git a/docs/reference/services/borgmatic.md b/docs/reference/services/borgmatic.md index 639c2e4..f81b5de 100644 --- a/docs/reference/services/borgmatic.md +++ b/docs/reference/services/borgmatic.md @@ -16,7 +16,7 @@ Daily backup system using Borg backup, running on indri. | **Install** | mise (pipx) | | **Config** | `~/.config/borgmatic/config.yaml` | | **Schedule** | Daily at 2:00 AM | -| **Repository** | `/Volumes/backups/borg/` on [[sifaka|Sifaka]] | +| **Repository** | `/Volumes/backups/borg/` on [[Sifaka NAS|Sifaka]] | ## What Gets Backed Up @@ -28,8 +28,8 @@ Daily backup system using Borg backup, running on indri. - `~/Pictures` - Photos **Databases:** -- `miniflux` on [[postgresql|PostgreSQL]] -- `teslamate` on [[postgresql|PostgreSQL]] +- `miniflux` on [[PostgreSQL]] +- `teslamate` on [[PostgreSQL]] **Not backed up (by design):** - ZIM archives (re-downloadable) @@ -46,15 +46,15 @@ Daily backup system using Borg backup, running on indri. ## Monitoring -Metrics exposed via textfile collector to [[prometheus|Prometheus]]: +Metrics exposed via textfile collector to [[Prometheus]]: - `borgmatic_up` - Repository accessibility - `borgmatic_last_archive_timestamp` - Last backup time - `borgmatic_repo_deduplicated_size_bytes` - Disk usage -Dashboard: "Borgmatic Backups" in [[grafana|Grafana]] +Dashboard: "Borgmatic Backups" in [[Grafana]] ## Related -- [[backups|Backups]] - Full backup policy -- [[sifaka|Sifaka]] - Backup target -- [[postgresql|PostgreSQL]] - Database backups +- [[Backup Policy|Backups]] - Full backup policy +- [[Sifaka NAS|Sifaka]] - Backup target +- [[PostgreSQL]] - Database backups diff --git a/docs/reference/services/forgejo.md b/docs/reference/services/forgejo.md index fd48051..ff5a0d0 100644 --- a/docs/reference/services/forgejo.md +++ b/docs/reference/services/forgejo.md @@ -44,5 +44,5 @@ Managed via 1Password: `lfs-jwt-secret`, `internal-token`, `oauth2-jwt-secret`, ## Related -- [[argocd|ArgoCD]] - Uses Forgejo as git source -- [[zot|Zot]] - Container registry for built images +- [[ArgoCD]] - Uses Forgejo as git source +- [[Zot]] - Container registry for built images diff --git a/docs/reference/services/grafana.md b/docs/reference/services/grafana.md index 04c8114..01293b6 100644 --- a/docs/reference/services/grafana.md +++ b/docs/reference/services/grafana.md @@ -45,6 +45,6 @@ Optional annotation: `grafana_folder: "FolderName"` ## Related -- [[prometheus|Prometheus]] - Metrics datasource -- [[loki|Loki]] - Logs datasource -- [[alloy|Alloy]] - Data collector +- [[Prometheus]] - Metrics datasource +- [[Loki]] - Logs datasource +- [[Grafana Alloy|Alloy]] - Data collector diff --git a/docs/reference/services/immich.md b/docs/reference/services/immich.md index d77122b..df76d37 100644 --- a/docs/reference/services/immich.md +++ b/docs/reference/services/immich.md @@ -16,11 +16,11 @@ Self-hosted photo and video management. | **URL** | https://photos.ops.eblu.me | | **Namespace** | `immich` | | **Deployment** | Helm chart (k8s) | -| **Database** | [[postgresql|PostgreSQL]] (CNPG) | -| **Storage** | [[sifaka|Sifaka]] photos volume | +| **Database** | [[PostgreSQL]] (CNPG) | +| **Storage** | [[Sifaka NAS|Sifaka]] photos volume | ## Related -- [[postgresql|PostgreSQL]] - Database backend -- [[sifaka|Sifaka]] - Photo storage -- [[jellyfin|Jellyfin]] - Video streaming (separate service) +- [[PostgreSQL]] - Database backend +- [[Sifaka NAS|Sifaka]] - Photo storage +- [[Jellyfin]] - Video streaming (separate service) diff --git a/docs/reference/services/jellyfin.md b/docs/reference/services/jellyfin.md index 74be14b..57fc226 100644 --- a/docs/reference/services/jellyfin.md +++ b/docs/reference/services/jellyfin.md @@ -42,10 +42,10 @@ Dashboard > Playback: ## Observability - Metrics: `jellyfin_metrics` ansible role -- Logs: Forwarded via [[alloy|Alloy]] -- Dashboard: "Jellyfin Media Server" in [[grafana|Grafana]] +- Logs: Forwarded via [[Grafana Alloy|Alloy]] +- Dashboard: "Jellyfin Media Server" in [[Grafana]] ## Related -- [[navidrome|Navidrome]] - Music streaming -- [[sifaka|Sifaka]] - Media storage +- [[Navidrome]] - Music streaming +- [[Sifaka NAS|Sifaka]] - Media storage diff --git a/docs/reference/services/kiwix.md b/docs/reference/services/kiwix.md index f98835c..38876b4 100644 --- a/docs/reference/services/kiwix.md +++ b/docs/reference/services/kiwix.md @@ -17,14 +17,14 @@ Offline Wikipedia and ZIM archive server. | **Tailscale URL** | https://kiwix.tail8d86e.ts.net | | **Namespace** | `kiwix` | | **Image** | `ghcr.io/kiwix/kiwix-serve:3.8.1` | -| **Storage** | NFS from [[sifaka|Sifaka]] (`/volume1/torrents`) | +| **Storage** | NFS from [[Sifaka NAS|Sifaka]] (`/volume1/torrents`) | ## Architecture | Component | Purpose | |-----------|---------| | kiwix-serve | Serves ZIM files on port 80 | -| torrent-sync | Sidecar syncing ZIM torrents to [[transmission|Transmission]] | +| torrent-sync | Sidecar syncing ZIM torrents to [[Transmission]] | | zim-watcher | CronJob (hourly) to restart on new ZIMs | ## Configured Archives @@ -43,10 +43,10 @@ Full list: `argocd/manifests/kiwix/configmap-zim-torrents.yaml` 1. Edit `configmap-zim-torrents.yaml` 2. Add torrent URL from https://download.kiwix.org/zim/ 3. Sync: `argocd app sync kiwix` -4. Torrent-sync adds to [[transmission|Transmission]] +4. Torrent-sync adds to [[Transmission]] 5. zim-watcher restarts kiwix when download completes ## Related -- [[transmission|Transmission]] - Downloads ZIM files -- [[sifaka|Sifaka]] - ZIM storage +- [[Transmission]] - Downloads ZIM files +- [[Sifaka NAS|Sifaka]] - ZIM storage diff --git a/docs/reference/services/loki.md b/docs/reference/services/loki.md index af5c77d..90f3b1c 100644 --- a/docs/reference/services/loki.md +++ b/docs/reference/services/loki.md @@ -24,8 +24,8 @@ Log aggregation system for BlumeOps infrastructure. - Single-node deployment with filesystem storage - TSDB index with 24h period -- Logs collected by [[alloy|Alloy]] and pushed via Loki API -- Queried via [[grafana|Grafana]] +- Logs collected by [[Grafana Alloy|Alloy]] and pushed via Loki API +- Queried via [[Grafana]] ## Log Sources @@ -46,6 +46,6 @@ Log aggregation system for BlumeOps infrastructure. ## Related -- [[alloy|Alloy]] - Log collector -- [[grafana|Grafana]] - Log visualization -- [[prometheus|Prometheus]] - Metrics counterpart +- [[Grafana Alloy|Alloy]] - Log collector +- [[Grafana]] - Log visualization +- [[Prometheus]] - Metrics counterpart diff --git a/docs/reference/services/miniflux.md b/docs/reference/services/miniflux.md index 8c303b1..b99a8b0 100644 --- a/docs/reference/services/miniflux.md +++ b/docs/reference/services/miniflux.md @@ -17,7 +17,7 @@ Minimalist RSS/Atom feed reader. | **Tailscale URL** | https://feed.tail8d86e.ts.net | | **Namespace** | `miniflux` | | **Image** | `ghcr.io/miniflux/miniflux:latest` | -| **Database** | [[postgresql|PostgreSQL]] | +| **Database** | [[PostgreSQL]] | ## Features @@ -33,9 +33,9 @@ Uses CloudNativePG cluster at `pg.ops.eblu.me`. Database user password stored in ## Backup -Feed subscriptions and read state backed up via [[borgmatic|Borgmatic]] PostgreSQL hook. +Feed subscriptions and read state backed up via [[Borgmatic]] PostgreSQL hook. ## Related -- [[postgresql|PostgreSQL]] - Database backend -- [[borgmatic|Borgmatic]] - Data backup +- [[PostgreSQL]] - Database backend +- [[Borgmatic]] - Data backup diff --git a/docs/reference/services/navidrome.md b/docs/reference/services/navidrome.md index 0c5ba87..e6c08db 100644 --- a/docs/reference/services/navidrome.md +++ b/docs/reference/services/navidrome.md @@ -38,5 +38,5 @@ The `/data` directory contains SQLite database, configuration, and cache. ## Related -- [[jellyfin|Jellyfin]] - Video streaming -- [[sifaka|Sifaka]] - Music storage +- [[Jellyfin]] - Video streaming +- [[Sifaka NAS|Sifaka]] - Music storage diff --git a/docs/reference/services/postgresql.md b/docs/reference/services/postgresql.md index a9a7eb1..e71bf3e 100644 --- a/docs/reference/services/postgresql.md +++ b/docs/reference/services/postgresql.md @@ -23,8 +23,8 @@ Database cluster via CloudNativePG operator. | Database | Owner | Purpose | |----------|-------|---------| -| miniflux | miniflux | [[miniflux|Miniflux]] feed data | -| teslamate | teslamate | [[teslamate|TeslaMate]] vehicle data | +| miniflux | miniflux | [[Miniflux]] feed data | +| teslamate | teslamate | [[TeslaMate]] vehicle data | ## Users @@ -34,11 +34,11 @@ Database cluster via CloudNativePG operator. | miniflux | app owner | Owns miniflux database | | teslamate | superuser | TeslaMate (needs extensions) | | eblume | superuser | Admin access | -| borgmatic | pg_read_all_data | [[borgmatic|Backup]] access | +| borgmatic | pg_read_all_data | [[Borgmatic|Backup]] access | ## Backup -Backed up via [[borgmatic|Borgmatic]] `postgresql_databases` hook. Streams `pg_dump` directly to Borg (no intermediate files, no downtime). See [[backup|Backup]] for overall backup policy. +Backed up via [[Borgmatic]] `postgresql_databases` hook. Streams `pg_dump` directly to Borg (no intermediate files, no downtime). See [[Backup]] for overall backup policy. ## Credentials @@ -54,6 +54,6 @@ Backed up via [[borgmatic|Borgmatic]] `postgresql_databases` hook. Streams `pg_d ## Related -- [[miniflux|Miniflux]] - Feed reader database -- [[teslamate|TeslaMate]] - Vehicle data database -- [[borgmatic|Borgmatic]] - Database backup +- [[Miniflux]] - Feed reader database +- [[TeslaMate]] - Vehicle data database +- [[Borgmatic]] - Database backup diff --git a/docs/reference/services/prometheus.md b/docs/reference/services/prometheus.md index 8b2093e..0966c2c 100644 --- a/docs/reference/services/prometheus.md +++ b/docs/reference/services/prometheus.md @@ -23,19 +23,19 @@ Metrics storage and querying for BlumeOps infrastructure. ## Data Sources ### Remote Write (from Alloy) -- Indri system metrics via [[alloy|Alloy]] remote_write +- Indri system metrics via [[Grafana Alloy|Alloy]] remote_write - Textfile metrics: minikube, borgmatic, zot, jellyfin ### Scrape Targets | Target | Metrics | |--------|---------| -| `sifaka:9100` | [[sifaka|Sifaka]] NAS (node_exporter) | -| `cnpg-metrics.tail8d86e.ts.net:9187` | [[postgresql|CloudNativePG]] metrics | +| `sifaka:9100` | [[Sifaka NAS|Sifaka]] NAS (node_exporter) | +| `cnpg-metrics.tail8d86e.ts.net:9187` | [[PostgreSQL|CloudNativePG]] metrics | | `kube-state-metrics.monitoring.svc:8080` | Kubernetes resource metrics | ## Related -- [[alloy|Alloy]] - Metrics collector -- [[grafana|Grafana]] - Visualization -- [[loki|Loki]] - Logs counterpart +- [[Grafana Alloy|Alloy]] - Metrics collector +- [[Grafana]] - Visualization +- [[Loki]] - Logs counterpart diff --git a/docs/reference/services/teslamate.md b/docs/reference/services/teslamate.md index 8d3766f..9dec06f 100644 --- a/docs/reference/services/teslamate.md +++ b/docs/reference/services/teslamate.md @@ -17,7 +17,7 @@ Self-hosted Tesla data logger collecting vehicle telemetry from the Tesla Owner | **Tailscale URL** | https://tesla.tail8d86e.ts.net | | **Namespace** | `teslamate` | | **Image** | `teslamate/teslamate:2.2.0` | -| **Database** | [[postgresql|PostgreSQL]] | +| **Database** | [[PostgreSQL]] | ## Data Collected @@ -53,6 +53,6 @@ Uses Tesla Owner API via OAuth: ## Related -- [[postgresql|PostgreSQL]] - Data storage -- [[grafana|Grafana]] - Dashboards -- [[borgmatic|Borgmatic]] - Database backup +- [[PostgreSQL]] - Data storage +- [[Grafana]] - Dashboards +- [[Borgmatic]] - Database backup diff --git a/docs/reference/services/transmission.md b/docs/reference/services/transmission.md index 7ba1110..52fca45 100644 --- a/docs/reference/services/transmission.md +++ b/docs/reference/services/transmission.md @@ -7,7 +7,7 @@ tags: # Transmission -BitTorrent daemon, primarily for downloading ZIM archives for [[kiwix|Kiwix]]. +BitTorrent daemon, primarily for downloading ZIM archives for [[Kiwix]]. ## Quick Reference @@ -17,7 +17,7 @@ BitTorrent daemon, primarily for downloading ZIM archives for [[kiwix|Kiwix]]. | **Tailscale URL** | https://torrent.tail8d86e.ts.net | | **Namespace** | `torrent` | | **Image** | `lscr.io/linuxserver/transmission:latest` | -| **Storage** | NFS PVC from [[sifaka|Sifaka]] | +| **Storage** | NFS PVC from [[Sifaka NAS|Sifaka]] | ## Storage Layout @@ -30,7 +30,7 @@ NFS share on sifaka (`/volume1/torrents`): | `/config/` | Transmission configuration | | `/watch/` | Watch directory for .torrent files | -[[kiwix|Kiwix]] reads from `/downloads/complete/` to serve ZIM archives. +[[Kiwix]] reads from `/downloads/complete/` to serve ZIM archives. ## Integration with Kiwix @@ -43,11 +43,11 @@ When downloads complete, the zim-watcher CronJob detects new ZIMs and restarts K ## Monitoring -Basic uptime via blackbox probe in [[alloy|Alloy]] k8s (Services Health dashboard). +Basic uptime via blackbox probe in [[Grafana Alloy|Alloy]] k8s (Services Health dashboard). Web UI shows: active/seeding/paused counts, speeds, disk usage. ## Related -- [[kiwix|Kiwix]] - ZIM archive consumer -- [[sifaka|Sifaka]] - Download storage +- [[Kiwix]] - ZIM archive consumer +- [[Sifaka NAS|Sifaka]] - Download storage diff --git a/docs/reference/services/zot.md b/docs/reference/services/zot.md index b369c08..ecab117 100644 --- a/docs/reference/services/zot.md +++ b/docs/reference/services/zot.md @@ -30,7 +30,7 @@ OCI-native container registry providing pull-through cache and private image sto ## Pull-Through Cache -When [[cluster|minikube]] pulls an image, containerd checks zot first. If cached, returns immediately. If not, zot fetches from upstream, caches it, then returns. +When [[Kubernetes Cluster|minikube]] pulls an image, containerd checks zot first. If cached, returns immediately. If not, zot fetches from upstream, caches it, then returns. ## Security Model @@ -38,5 +38,5 @@ Network access only (no authentication). Defense is the Tailscale ACL boundary. ## Related -- [[forgejo|Forgejo]] - Container build CI -- [[cluster|Cluster]] - Registry consumer +- [[Forgejo]] - Container build CI +- [[Kubernetes Cluster|Cluster]] - Registry consumer diff --git a/docs/reference/storage/backups.md b/docs/reference/storage/backups.md index c937714..ded19c8 100644 --- a/docs/reference/storage/backups.md +++ b/docs/reference/storage/backups.md @@ -7,13 +7,13 @@ tags: # Backup Policy -Daily automated backups from [[indri|Indri]] to [[sifaka|Sifaka]] NAS. +Daily automated backups from [[Indri]] to [[Sifaka NAS|Sifaka]] NAS. ## Schedule | Time | Frequency | System | |------|-----------|--------| -| 2:00 AM | Daily | [[borgmatic|Borgmatic]] | +| 2:00 AM | Daily | [[Borgmatic]] | ## What Gets Backed Up @@ -31,8 +31,8 @@ Daily automated backups from [[indri|Indri]] to [[sifaka|Sifaka]] NAS. | Database | Host | Method | |----------|------|--------| -| miniflux | [[postgresql|pg.ops.eblu.me]] | pg_dump stream | -| teslamate | [[postgresql|pg.ops.eblu.me]] | pg_dump stream | +| miniflux | [[PostgreSQL|pg.ops.eblu.me]] | pg_dump stream | +| teslamate | [[PostgreSQL|pg.ops.eblu.me]] | pg_dump stream | ## What Is NOT Backed Up @@ -53,19 +53,19 @@ Daily automated backups from [[indri|Indri]] to [[sifaka|Sifaka]] NAS. ## Backup Target -Repository: `/Volumes/backups/borg/` on [[sifaka|Sifaka]] +Repository: `/Volumes/backups/borg/` on [[Sifaka NAS|Sifaka]] ## Monitoring -Metrics exposed to [[prometheus|Prometheus]]: +Metrics exposed to [[Prometheus]]: - `borgmatic_up` - Repository accessible - `borgmatic_last_archive_timestamp` - Last backup time - `borgmatic_repo_deduplicated_size_bytes` - Disk usage -Dashboard: "Borgmatic Backups" in [[grafana|Grafana]] +Dashboard: "Borgmatic Backups" in [[Grafana]] ## Related -- [[borgmatic|Borgmatic]] - Backup system details -- [[sifaka|Sifaka]] - Backup storage -- [[postgresql|PostgreSQL]] - Database backups +- [[Borgmatic]] - Backup system details +- [[Sifaka NAS|Sifaka]] - Backup storage +- [[PostgreSQL]] - Database backups diff --git a/docs/reference/storage/postgresql-storage.md b/docs/reference/storage/postgresql-storage.md index 7127d7d..8742569 100644 --- a/docs/reference/storage/postgresql-storage.md +++ b/docs/reference/storage/postgresql-storage.md @@ -7,4 +7,4 @@ tags: # PostgreSQL Storage -See [[postgresql|PostgreSQL]] in Services. +See [[PostgreSQL]] in Services. diff --git a/docs/reference/storage/sifaka.md b/docs/reference/storage/sifaka.md index c3b7e50..38249cb 100644 --- a/docs/reference/storage/sifaka.md +++ b/docs/reference/storage/sifaka.md @@ -21,11 +21,11 @@ Synology NAS providing network storage and backup target. | Share | Path | Purpose | Consumers | |-------|------|---------|-----------| -| backups | `/volume1/backups` | Borg backup repository | [[borgmatic|Borgmatic]] | -| torrents | `/volume1/torrents` | ZIM downloads | [[kiwix|Kiwix]], [[transmission|Transmission]] | -| music | `/volume1/music` | Music library | [[navidrome|Navidrome]] | -| allisonflix | `/volume1/allisonflix` | Video library | [[jellyfin|Jellyfin]] | -| photos | `/volume1/photos` | Photo library | [[immich|Immich]] | +| backups | `/volume1/backups` | Borg backup repository | [[Borgmatic]] | +| torrents | `/volume1/torrents` | ZIM downloads | [[Kiwix]], [[Transmission]] | +| music | `/volume1/music` | Music library | [[Navidrome]] | +| allisonflix | `/volume1/allisonflix` | Video library | [[Jellyfin]] | +| photos | `/volume1/photos` | Photo library | [[Immich]] | ## NFS Exports @@ -37,7 +37,7 @@ Synology NAS providing network storage and backup target. ## Monitoring -Node exporter running in Docker container, scraped by [[prometheus|Prometheus]] at `sifaka:9100`. +Node exporter running in Docker container, scraped by [[Prometheus]] at `sifaka:9100`. ## Tailscale @@ -46,14 +46,14 @@ Node exporter running in Docker container, scraped by [[prometheus|Prometheus]] ## Backup -Sifaka is the **target** for [[backup|backups]], not a backup source. [[borgmatic|Borgmatic]] sends backups TO sifaka, not OF sifaka. +Sifaka is the **target** for [[Backup|backups]], not a backup source. [[Borgmatic]] sends backups TO sifaka, not OF sifaka. Data protection for sifaka itself currently relies on the Synology RAID 5 configuration, which provides single-disk fault tolerance. Future plans include offsite duplication for additional resiliency. ## Related -- [[backups|Backups]] - Backup policy -- [[borgmatic|Borgmatic]] - Backup system -- [[immich|Immich]] - Photo consumer -- [[jellyfin|Jellyfin]] - Media consumer -- [[navidrome|Navidrome]] - Music consumer +- [[Backup Policy|Backups]] - Backup policy +- [[Borgmatic]] - Backup system +- [[Immich]] - Photo consumer +- [[Jellyfin]] - Media consumer +- [[Navidrome]] - Music consumer diff --git a/docs/zk/1767747119-YCPO.md b/docs/zk/1767747119-YCPO.md index 280981a..771f485 100644 --- a/docs/zk/1767747119-YCPO.md +++ b/docs/zk/1767747119-YCPO.md @@ -1,10 +1,7 @@ --- id: 1767747119-YCPO -aliases: - - blumeops - - BlumeOps tags: - - blumeops +- blumeops --- BlumeOps, aka Blue Mops, refers to my own personal computing operations stack. diff --git a/docs/zk/1768246525-RVRY.md b/docs/zk/1768246525-RVRY.md index f535b34..b2bca43 100644 --- a/docs/zk/1768246525-RVRY.md +++ b/docs/zk/1768246525-RVRY.md @@ -1,14 +1,11 @@ --- id: 1768246525-RVRY -aliases: - - forgejo - - forge tags: - - blumeops - - forgejo - - git - - scm - - forge +- blumeops +- forgejo +- git +- scm +- forge --- # Mon Jan 12 11:35 diff --git a/docs/zk/1768283761-TRXN.md b/docs/zk/1768283761-TRXN.md index 485a2dc..3116c5a 100644 --- a/docs/zk/1768283761-TRXN.md +++ b/docs/zk/1768283761-TRXN.md @@ -1,9 +1,7 @@ --- id: 1768283761-TRXN -aliases: - - prometheus tags: - - blumeops +- blumeops --- # Prometheus Management Log diff --git a/docs/zk/1768457769-LOCK.md b/docs/zk/1768457769-LOCK.md index 87ec9fd..f8eb8cd 100644 --- a/docs/zk/1768457769-LOCK.md +++ b/docs/zk/1768457769-LOCK.md @@ -1,10 +1,7 @@ --- id: 1768457769-LOCK -aliases: - - pypi - - devpi tags: - - blumeops +- blumeops --- # PyPI / devpi Management Log diff --git a/docs/zk/1768506761-GHUW.md b/docs/zk/1768506761-GHUW.md index 0702d2c..8288840 100644 --- a/docs/zk/1768506761-GHUW.md +++ b/docs/zk/1768506761-GHUW.md @@ -1,10 +1,7 @@ --- id: 1768506761-GHUW -aliases: - - alloy - - grafana-alloy tags: - - blumeops +- blumeops --- # Grafana Alloy Management Log diff --git a/docs/zk/1768506761-XGYX.md b/docs/zk/1768506761-XGYX.md index c94e878..763ddd4 100644 --- a/docs/zk/1768506761-XGYX.md +++ b/docs/zk/1768506761-XGYX.md @@ -1,9 +1,7 @@ --- id: 1768506761-XGYX -aliases: - - loki tags: - - blumeops +- blumeops --- # Loki Management Log diff --git a/docs/zk/argocd-log.md b/docs/zk/argocd-log.md index 47facc5..35c2cf4 100644 --- a/docs/zk/argocd-log.md +++ b/docs/zk/argocd-log.md @@ -1,9 +1,7 @@ --- id: argocd-log -aliases: - - argo-cd tags: - - blumeops +- blumeops --- # ArgoCD Management Log diff --git a/docs/zk/borgmatic-log.md b/docs/zk/borgmatic-log.md index 3481f4f..4edbb90 100644 --- a/docs/zk/borgmatic-log.md +++ b/docs/zk/borgmatic-log.md @@ -1,9 +1,7 @@ --- id: borgmatic-log -aliases: - - borg-backup tags: - - blumeops +- blumeops --- # Borgmatic Management Log diff --git a/docs/zk/external-secrets-log.md b/docs/zk/external-secrets-log.md index 310932c..dc50f3f 100644 --- a/docs/zk/external-secrets-log.md +++ b/docs/zk/external-secrets-log.md @@ -1,10 +1,7 @@ --- id: external-secrets-log -aliases: - - eso - - external-secrets-operator tags: - - blumeops +- blumeops --- # External Secrets Operator diff --git a/docs/zk/indri-log.md b/docs/zk/indri-log.md index a3a86c4..1be8846 100644 --- a/docs/zk/indri-log.md +++ b/docs/zk/indri-log.md @@ -1,9 +1,7 @@ --- id: indri-log -aliases: - - mac-mini tags: - - blumeops +- blumeops --- # Indri Maintenance Log diff --git a/docs/zk/miniflux-log.md b/docs/zk/miniflux-log.md index 9005106..526c6f3 100644 --- a/docs/zk/miniflux-log.md +++ b/docs/zk/miniflux-log.md @@ -1,10 +1,7 @@ --- id: miniflux-log -aliases: - - feed - - rss tags: - - blumeops +- blumeops --- # Miniflux Management Log diff --git a/docs/zk/minikube.md b/docs/zk/minikube.md index ac47025..22272f0 100644 --- a/docs/zk/minikube.md +++ b/docs/zk/minikube.md @@ -1,10 +1,7 @@ --- id: minikube -aliases: - - kubernetes - - k8s tags: - - blumeops +- blumeops --- # Minikube Management Log diff --git a/docs/zk/navidrome-log.md b/docs/zk/navidrome-log.md index 5e0623e..45a8f3d 100644 --- a/docs/zk/navidrome-log.md +++ b/docs/zk/navidrome-log.md @@ -1,10 +1,8 @@ --- id: navidrome-log -aliases: - - DJ tags: - - blumeops - - service +- blumeops +- service --- Navidrome is a self-hosted music streaming server deployed on [[blumeops|BlumeOps]]. diff --git a/docs/zk/postgresql-log.md b/docs/zk/postgresql-log.md index a1959c8..2df2553 100644 --- a/docs/zk/postgresql-log.md +++ b/docs/zk/postgresql-log.md @@ -1,10 +1,7 @@ --- id: postgresql-log -aliases: - - postgres - - pg tags: - - blumeops +- blumeops --- # PostgreSQL Management Log diff --git a/docs/zk/pulumi.md b/docs/zk/pulumi.md index f9e0189..422f83d 100644 --- a/docs/zk/pulumi.md +++ b/docs/zk/pulumi.md @@ -1,9 +1,7 @@ --- id: pulumi -aliases: - - tailnet-iac tags: - - blumeops +- blumeops --- # Pulumi Tailnet IaC Management Log diff --git a/docs/zk/teslamate-log.md b/docs/zk/teslamate-log.md index 211a0ff..7a814dc 100644 --- a/docs/zk/teslamate-log.md +++ b/docs/zk/teslamate-log.md @@ -1,9 +1,7 @@ --- id: teslamate-log -aliases: - - tesla tags: - - blumeops +- blumeops --- # TeslaMate diff --git a/docs/zk/zot-log.md b/docs/zk/zot-log.md index ea62e1d..5950a8b 100644 --- a/docs/zk/zot-log.md +++ b/docs/zk/zot-log.md @@ -1,9 +1,7 @@ --- id: zot-log -aliases: - - container-registry tags: - - blumeops +- blumeops --- # Zot Registry Management Log diff --git a/mise-tasks/doc-filenames b/mise-tasks/doc-filenames deleted file mode 100755 index 9eb678a..0000000 --- a/mise-tasks/doc-filenames +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env -S uv run --script -# /// script -# requires-python = ">=3.12" -# dependencies = ["pyyaml>=6.0", "rich>=13.0.0"] -# /// -#MISE description="List all doc card filenames and detect duplicates" -"""List all documentation card filenames and detect duplicates. - -This script scans all markdown files in the docs/ directory (excluding -changelog.d/), and reports any duplicate filenames that could cause -wiki-link resolution issues with Quartz's "shortest" path mode. - -With shortest mode, [[filename]] resolves to the file with that name, -so filenames must be unique across the entire docs directory. - -Usage: mise run doc-card-titles -""" - -import sys -from collections import defaultdict -from pathlib import Path - -import yaml -from rich.console import Console -from rich.table import Table - -DOCS_DIR = Path(__file__).parent.parent / "docs" - - -def extract_frontmatter(file_path: Path) -> dict | None: - """Extract YAML frontmatter from a markdown file.""" - content = file_path.read_text() - if not content.startswith("---"): - return None - - # Find the closing --- - end_idx = content.find("---", 3) - if end_idx == -1: - return None - - frontmatter_text = content[3:end_idx].strip() - try: - return yaml.safe_load(frontmatter_text) or {} - except yaml.YAMLError: - return None - - -def main() -> int: - console = Console() - - # Collect all filenames (without extension) and their full paths - # Key: filename (stem), Value: list of full relative paths - filenames: dict[str, list[str]] = defaultdict(list) - - # Also collect id/aliases from zk cards for reference - zk_identifiers: dict[str, list[tuple[str, str]]] = defaultdict(list) - - # Scan all markdown files - for md_file in sorted(DOCS_DIR.rglob("*.md")): - # Skip changelog fragments - if "changelog.d" in md_file.parts: - continue - - rel_path = str(md_file.relative_to(DOCS_DIR)) - filename = md_file.stem # filename without .md extension - - filenames[filename].append(rel_path) - - # For zk cards, also track id and aliases - if "zk" in md_file.parts: - frontmatter = extract_frontmatter(md_file) - if frontmatter: - card_id = frontmatter.get("id") - if card_id: - zk_identifiers[card_id].append((rel_path, "id")) - aliases = frontmatter.get("aliases", []) - for alias in aliases: - zk_identifiers[alias].append((rel_path, "alias")) - - # Find duplicate filenames (excluding "index" which is expected in multiple dirs) - duplicates = { - name: paths - for name, paths in filenames.items() - if len(paths) > 1 and name != "index" - } - - # Print results - console.print("[bold]Doc Card Filename Inventory[/bold]") - console.print() - console.print("With Quartz 'shortest' path mode, wiki-links like [[filename]]") - console.print("resolve by filename, so filenames must be unique.") - console.print() - - # Duplicates table (if any) - if duplicates: - console.print("[bold red]Duplicate Filenames Found[/bold red]") - dup_table = Table(show_header=True, header_style="bold") - dup_table.add_column("Filename") - dup_table.add_column("Paths") - - for filename in sorted(duplicates.keys()): - paths = duplicates[filename] - dup_table.add_row(filename, "\n".join(paths)) - - console.print(dup_table) - console.print() - - # All filenames table - console.print("[bold]All Filenames[/bold]") - all_table = Table(show_header=True, header_style="bold") - all_table.add_column("Filename") - all_table.add_column("Path") - all_table.add_column("Status") - - for filename in sorted(filenames.keys()): - paths = filenames[filename] - is_dup = filename in duplicates - status = "[red]DUPLICATE[/red]" if is_dup else "[green]OK[/green]" - all_table.add_row(filename, paths[0], status) - for extra_path in paths[1:]: - all_table.add_row("", extra_path, "") - - console.print(all_table) - - # ZK identifiers (for reference) - if zk_identifiers: - console.print() - console.print("[bold]ZK Card Identifiers (id/aliases)[/bold]") - zk_table = Table(show_header=True, header_style="bold") - zk_table.add_column("Identifier") - zk_table.add_column("Type") - zk_table.add_column("File") - - for identifier in sorted(zk_identifiers.keys()): - sources = zk_identifiers[identifier] - first = True - for file_path, id_type in sources: - zk_table.add_row( - identifier if first else "", - id_type, - file_path, - ) - first = False - - console.print(zk_table) - - # Summary - console.print() - console.print(f"Total files: {sum(len(p) for p in filenames.values())}") - console.print(f"Unique filenames: {len(filenames)}") - console.print(f"Duplicate filenames: {len(duplicates)}") - - if duplicates: - console.print() - console.print("[bold red]Action required:[/bold red] Rename files to ensure unique filenames for wiki-link resolution.") - return 1 - - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/mise-tasks/doc-links b/mise-tasks/doc-links new file mode 100755 index 0000000..8aee84a --- /dev/null +++ b/mise-tasks/doc-links @@ -0,0 +1,133 @@ +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.12" +# dependencies = ["pyyaml>=6.0", "rich>=13.0.0"] +# /// +#MISE description="Validate all wiki-links point to existing doc titles" +"""Validate that all wiki-links in documentation point to existing titles. + +This script scans all markdown files in the docs/ directory (excluding +changelog.d/ and zk/), extracts wiki-links, and verifies each link target +exists as a frontmatter title in the documentation. + +Wiki-link formats supported: +- [[Title]] - links to a doc with frontmatter title "Title" +- [[Title|Display Text]] - links to "Title", displays "Display Text" + +Usage: mise run doc-links +""" + +import re +import sys +from collections import defaultdict +from pathlib import Path + +import yaml +from rich.console import Console +from rich.markup import escape +from rich.table import Table + +DOCS_DIR = Path(__file__).parent.parent / "docs" + +# Regex to match wiki-links: [[Target]] or [[Target|Display]] +WIKILINK_PATTERN = re.compile(r"\[\[([^\]|]+)(?:\|[^\]]+)?\]\]") + +# Regex to match inline code (backticks) +INLINE_CODE_PATTERN = re.compile(r"`[^`]+`") + + +def extract_frontmatter(file_path: Path) -> dict | None: + """Extract YAML frontmatter from a markdown file.""" + content = file_path.read_text() + if not content.startswith("---"): + return None + + end_idx = content.find("---", 3) + if end_idx == -1: + return None + + frontmatter_text = content[3:end_idx].strip() + try: + return yaml.safe_load(frontmatter_text) or {} + except yaml.YAMLError: + return None + + +def extract_wikilinks(file_path: Path) -> list[tuple[str, int]]: + """Extract all wiki-link targets from a markdown file with line numbers. + + Ignores wiki-links inside inline code (backticks) as these are examples. + """ + content = file_path.read_text() + links = [] + + for line_num, line in enumerate(content.splitlines(), start=1): + # Remove inline code before searching for wiki-links + line_without_code = INLINE_CODE_PATTERN.sub("", line) + for match in WIKILINK_PATTERN.finditer(line_without_code): + target = match.group(1).strip() + links.append((target, line_num)) + + return links + + +def main() -> int: + console = Console() + + # Collect all valid titles from frontmatter + valid_titles: set[str] = set() + + # Scan all markdown files for titles (excluding zk/ and changelog.d/) + for md_file in DOCS_DIR.rglob("*.md"): + if "changelog.d" in md_file.parts or "zk" in md_file.parts: + continue + + frontmatter = extract_frontmatter(md_file) + if frontmatter and frontmatter.get("title"): + valid_titles.add(frontmatter["title"]) + + # Collect all broken links + # Key: (file_path, line_num), Value: target + broken_links: list[tuple[str, int, str]] = [] + + # Scan all markdown files for wiki-links (excluding zk/ and changelog.d/) + for md_file in sorted(DOCS_DIR.rglob("*.md")): + if "changelog.d" in md_file.parts or "zk" in md_file.parts: + continue + + rel_path = str(md_file.relative_to(DOCS_DIR)) + links = extract_wikilinks(md_file) + + for target, line_num in links: + if target not in valid_titles: + broken_links.append((rel_path, line_num, target)) + + # Print results + console.print("[bold]Wiki-Link Validation[/bold]") + console.print() + console.print(f"Found {len(valid_titles)} valid titles in documentation.") + console.print() + + if broken_links: + console.print("[bold red]Broken Wiki-Links Found[/bold red]") + table = Table(show_header=True, header_style="bold") + table.add_column("File") + table.add_column("Line", justify="right") + table.add_column("Target") + + for file_path, line_num, target in broken_links: + table.add_row(file_path, str(line_num), escape(f"[[{target}]]")) + + console.print(table) + console.print() + console.print(f"[bold red]{len(broken_links)} broken link(s) found.[/bold red]") + console.print() + console.print("Each wiki-link target must match a frontmatter title in docs/.") + return 1 + + console.print("[bold green]All wiki-links are valid![/bold green]") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/mise-tasks/doc-titles b/mise-tasks/doc-titles new file mode 100755 index 0000000..aadb7a9 --- /dev/null +++ b/mise-tasks/doc-titles @@ -0,0 +1,126 @@ +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.12" +# dependencies = ["pyyaml>=6.0", "rich>=13.0.0"] +# /// +#MISE description="List all doc card titles and detect duplicates" +"""List all documentation card titles and detect duplicates. + +This script scans all markdown files in the docs/ directory (excluding +changelog.d/ and zk/), extracts frontmatter titles, and reports any +duplicates that could cause wiki-link resolution issues. + +With Quartz, wiki-links like [[Title]] resolve by frontmatter title, +so titles must be unique across the documentation. + +Usage: mise run doc-titles +""" + +import sys +from collections import defaultdict +from pathlib import Path + +import yaml +from rich.console import Console +from rich.table import Table + +DOCS_DIR = Path(__file__).parent.parent / "docs" + + +def extract_frontmatter(file_path: Path) -> dict | None: + """Extract YAML frontmatter from a markdown file.""" + content = file_path.read_text() + if not content.startswith("---"): + return None + + end_idx = content.find("---", 3) + if end_idx == -1: + return None + + frontmatter_text = content[3:end_idx].strip() + try: + return yaml.safe_load(frontmatter_text) or {} + except yaml.YAMLError: + return None + + +def main() -> int: + console = Console() + + # Collect all titles and their source files + # Key: title, Value: list of file paths + titles: dict[str, list[str]] = defaultdict(list) + + # Scan all markdown files (excluding zk/ and changelog.d/) + for md_file in sorted(DOCS_DIR.rglob("*.md")): + # Skip changelog fragments and zk cards + if "changelog.d" in md_file.parts or "zk" in md_file.parts: + continue + + rel_path = str(md_file.relative_to(DOCS_DIR)) + frontmatter = extract_frontmatter(md_file) + + if not frontmatter: + continue + + title = frontmatter.get("title") + if title: + titles[title].append(rel_path) + + # Find duplicates + duplicates = {title: paths for title, paths in titles.items() if len(paths) > 1} + + # Print results + console.print("[bold]Doc Card Title Inventory[/bold]") + console.print() + console.print("With Quartz, wiki-links like [[Title]] resolve by frontmatter title,") + console.print("so titles must be unique across the documentation.") + console.print() + + # Duplicates table (if any) + if duplicates: + console.print("[bold red]Duplicate Titles Found[/bold red]") + dup_table = Table(show_header=True, header_style="bold") + dup_table.add_column("Title") + dup_table.add_column("Files") + + for title in sorted(duplicates.keys()): + paths = duplicates[title] + dup_table.add_row(title, "\n".join(paths)) + + console.print(dup_table) + console.print() + + # All titles table + console.print("[bold]All Titles[/bold]") + all_table = Table(show_header=True, header_style="bold") + all_table.add_column("Title") + all_table.add_column("File") + all_table.add_column("Status") + + for title in sorted(titles.keys()): + paths = titles[title] + is_dup = title in duplicates + status = "[red]DUPLICATE[/red]" if is_dup else "[green]OK[/green]" + all_table.add_row(title, paths[0], status) + for extra_path in paths[1:]: + all_table.add_row("", extra_path, "") + + console.print(all_table) + + # Summary + console.print() + console.print(f"Total files: {sum(len(p) for p in titles.values())}") + console.print(f"Unique titles: {len(titles)}") + console.print(f"Duplicate titles: {len(duplicates)}") + + if duplicates: + console.print() + console.print("[bold red]Action required:[/bold red] Rename titles to ensure unique wiki-link resolution.") + return 1 + + return 0 + + +if __name__ == "__main__": + sys.exit(main())