Add doc-random task and documentation improvements (#98)
## Summary - Add `doc-random` mise task that selects a random documentation card for review - Add how-to/knowledgebase section with review-documentation guide - Add Caddy reference card with proxy configuration details - Fix replication tutorial sequence (tailscale-setup now links to core-services) - Fix "BluemeOps" typo in tailscale-setup - Clean up obsolete zk/ directory references from doc-links ## Deployment and Testing - [x] `mise run doc-random` works and displays a random card - [x] `mise run doc-links` passes (all wiki-links valid) - [x] Pre-commit hooks pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/98
This commit is contained in:
parent
f88da51e23
commit
5c79a8dbe2
11 changed files with 302 additions and 7 deletions
1
docs/changelog.d/+caddy-docs.doc.md
Normal file
1
docs/changelog.d/+caddy-docs.doc.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Add Caddy reference card and fix replication tutorial sequence
|
||||
1
docs/changelog.d/random-doc-review.feature.md
Normal file
1
docs/changelog.d/random-doc-review.feature.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Add doc-random mise task for random documentation review
|
||||
|
|
@ -28,6 +28,12 @@ Task-oriented instructions for common BlumeOps operations. These guides assume y
|
|||
|-------|-------------|
|
||||
| [[update-documentation]] | Publish docs via build-blumeops workflow |
|
||||
|
||||
## Knowledge Base
|
||||
|
||||
| Guide | Description |
|
||||
|-------|-------------|
|
||||
| [[review-documentation]] | Periodically review and maintain documentation |
|
||||
|
||||
## Operations
|
||||
|
||||
| Guide | Description |
|
||||
|
|
|
|||
97
docs/how-to/knowledgebase/review-documentation.md
Normal file
97
docs/how-to/knowledgebase/review-documentation.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
title: review-documentation
|
||||
tags:
|
||||
- how-to
|
||||
- documentation
|
||||
- maintenance
|
||||
---
|
||||
|
||||
# Review Documentation
|
||||
|
||||
How to periodically review and maintain the BlumeOps knowledge base.
|
||||
|
||||
## Quick Random Review
|
||||
|
||||
Select a random documentation card for review:
|
||||
|
||||
```bash
|
||||
mise run doc-random
|
||||
```
|
||||
|
||||
This displays a random card with a review checklist to guide your assessment.
|
||||
|
||||
## Review Checklist
|
||||
|
||||
When reviewing a documentation card, consider:
|
||||
|
||||
| Check | Description |
|
||||
|-------|-------------|
|
||||
| **Accuracy** | Is the information current and correct? |
|
||||
| **Links** | Are wiki-links working? Should more be added? |
|
||||
| **Scope** | Is the card appropriately sized (not too large/small)? |
|
||||
| **Category** | Is it in the right section (reference/how-to/tutorial/explanation)? |
|
||||
| **Frontmatter** | Are title and tags appropriate? |
|
||||
| **Related** | Should it link to related cards? |
|
||||
|
||||
## Verify Deployed State
|
||||
|
||||
For service reference cards, verify the documentation matches reality:
|
||||
|
||||
### ArgoCD Apps (Kubernetes services)
|
||||
|
||||
Check if the app is synced and healthy:
|
||||
|
||||
```bash
|
||||
argocd app get <app-name>
|
||||
argocd app diff <app-name> # Show pending changes
|
||||
```
|
||||
|
||||
If out of sync, either the docs are stale or a deployment is pending.
|
||||
|
||||
### Ansible Roles (indri services)
|
||||
|
||||
Check if the role applies idempotently (no changes needed):
|
||||
|
||||
```bash
|
||||
mise run provision-indri -- --tags <role> --check --diff
|
||||
```
|
||||
|
||||
If changes would be made, either the docs are stale or the host has drifted.
|
||||
|
||||
### Pulumi (Tailscale ACLs, DNS)
|
||||
|
||||
Check for drift:
|
||||
|
||||
```bash
|
||||
# Tailscale ACLs
|
||||
cd pulumi/tailscale && pulumi preview
|
||||
|
||||
# DNS (Gandi)
|
||||
cd pulumi/gandi && pulumi preview
|
||||
```
|
||||
|
||||
If changes are pending, investigate whether docs or infrastructure is stale.
|
||||
|
||||
## When to Review
|
||||
|
||||
Consider running `mise run doc-random` during:
|
||||
|
||||
- Start of work sessions (quick maintenance)
|
||||
- After major infrastructure changes (verify docs reflect reality)
|
||||
- When learning the system (random exploration)
|
||||
|
||||
## Making Changes
|
||||
|
||||
If a card needs updates:
|
||||
|
||||
1. Create a feature branch
|
||||
2. Make the edits
|
||||
3. Run `mise run doc-links` to verify links
|
||||
4. Create a PR for review
|
||||
|
||||
See [[update-documentation]] for publishing changes.
|
||||
|
||||
## Related
|
||||
|
||||
- [[update-documentation]] - Publishing documentation changes
|
||||
- [[exploring-the-docs]] - Navigating the documentation
|
||||
|
|
@ -17,6 +17,7 @@ Individual service reference cards with URLs and configuration details.
|
|||
| [[alloy | Alloy]] | Observability collector (metrics & logs) | indri + k8s |
|
||||
| [[argocd]] | GitOps continuous delivery | k8s |
|
||||
| [[borgmatic]] | Backup system | indri |
|
||||
| [[caddy]] | Reverse proxy & TLS termination | indri |
|
||||
| [[1password]] | Secrets management | cloud + k8s |
|
||||
| [[forgejo]] | Git forge & CI/CD | indri |
|
||||
| [[grafana]] | Dashboards & visualization | k8s |
|
||||
|
|
|
|||
98
docs/reference/services/caddy.md
Normal file
98
docs/reference/services/caddy.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
---
|
||||
title: caddy
|
||||
tags:
|
||||
- service
|
||||
- networking
|
||||
- tls
|
||||
---
|
||||
|
||||
# Caddy
|
||||
|
||||
Reverse proxy for `*.ops.eblu.me` services with automatic TLS via ACME DNS-01.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Domain** | `*.ops.eblu.me` |
|
||||
| **HTTPS Port** | 443 |
|
||||
| **Config** | `ansible/roles/caddy/templates/Caddyfile.j2` |
|
||||
| **Binary** | Custom build with Gandi DNS plugin |
|
||||
|
||||
## Why Caddy?
|
||||
|
||||
Caddy provides a single TLS termination point for all BlumeOps services:
|
||||
|
||||
- **Wildcard certificate** for `*.ops.eblu.me` via Let's Encrypt
|
||||
- **DNS-01 challenge** using Gandi API (no port 80 needed)
|
||||
- **Unified access** from k8s pods, containers, and tailnet clients
|
||||
|
||||
See [[routing]] for when to use `*.ops.eblu.me` vs `*.tail8d86e.ts.net`.
|
||||
|
||||
## Proxied Services
|
||||
|
||||
### Indri-Local Services
|
||||
|
||||
| Subdomain | Backend | Service |
|
||||
|-----------|---------|---------|
|
||||
| `forge.ops.eblu.me` | `localhost:3001` | [[forgejo]] |
|
||||
| `registry.ops.eblu.me` | `localhost:5050` | [[zot]] |
|
||||
| `jellyfin.ops.eblu.me` | `localhost:8096` | [[jellyfin]] |
|
||||
|
||||
### Kubernetes Services
|
||||
|
||||
K8s services are proxied via their Tailscale Ingress endpoints:
|
||||
|
||||
| Subdomain | Backend | Service |
|
||||
|-----------|---------|---------|
|
||||
| `grafana.ops.eblu.me` | `grafana.tail8d86e.ts.net` | [[grafana]] |
|
||||
| `argocd.ops.eblu.me` | `argocd.tail8d86e.ts.net` | [[argocd]] |
|
||||
| `docs.ops.eblu.me` | `docs.tail8d86e.ts.net` | [[docs]] |
|
||||
| `feed.ops.eblu.me` | `feed.tail8d86e.ts.net` | [[miniflux]] |
|
||||
| ... | ... | (see defaults/main.yml for full list) |
|
||||
|
||||
### TCP Services (Layer 4)
|
||||
|
||||
| Port | Backend | Service |
|
||||
|------|---------|---------|
|
||||
| 2222 | `localhost:2200` | Forgejo SSH |
|
||||
| 5432 | `pg.tail8d86e.ts.net:5432` | [[postgresql]] |
|
||||
|
||||
## Configuration
|
||||
|
||||
Caddy is managed via the `caddy` Ansible role:
|
||||
|
||||
```bash
|
||||
# Deploy caddy changes
|
||||
mise run provision-indri -- --tags caddy
|
||||
```
|
||||
|
||||
**Key files:**
|
||||
- `ansible/roles/caddy/defaults/main.yml` - Service definitions
|
||||
- `ansible/roles/caddy/templates/Caddyfile.j2` - Caddy config template
|
||||
|
||||
## Secrets
|
||||
|
||||
| Secret | Source | Description |
|
||||
|--------|--------|-------------|
|
||||
| `GANDI_BEARER_TOKEN` | 1Password | API token for DNS-01 challenges |
|
||||
|
||||
The token is written to `~/.config/caddy/gandi-token` (chmod 0600) and sourced by the Caddy wrapper script.
|
||||
|
||||
## Custom Build
|
||||
|
||||
Caddy is built from source with the Gandi DNS plugin:
|
||||
|
||||
```bash
|
||||
# Build location
|
||||
~/code/3rd/caddy/bin/caddy
|
||||
```
|
||||
|
||||
The build includes the `github.com/caddy-dns/gandi` plugin for ACME DNS-01 challenges.
|
||||
|
||||
## Related
|
||||
|
||||
- [[routing]] - Service routing architecture
|
||||
- [[forgejo]] - Git forge (proxied by Caddy)
|
||||
- [[zot]] - Container registry (proxied by Caddy)
|
||||
- [[tailscale-operator]] - K8s services use Tailscale Ingress, then Caddy
|
||||
|
|
@ -88,6 +88,7 @@ BlumeOps operations are driven by mise tasks. Run `mise tasks` to list all avail
|
|||
| `doc-links` | Validate wiki-links in documentation |
|
||||
| `doc-titles` | Check for duplicate doc titles |
|
||||
| `doc-filenames` | Check for duplicate doc filenames |
|
||||
| `doc-random` | Select a random doc card for review |
|
||||
| `indri-runner-logs` | View Forgejo workflow logs from local runner |
|
||||
|
||||
For ArgoCD operations, use the `argocd` CLI directly:
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ tags:
|
|||
# Core Services Setup
|
||||
|
||||
> **Audiences:** Replicator
|
||||
>
|
||||
> **Prerequisites:** [[tutorials/replication/tailscale-setup | Tailscale Setup]]
|
||||
|
||||
This tutorial walks through setting up the foundational services that your GitOps infrastructure depends on: a git forge and optionally a container registry.
|
||||
|
||||
|
|
|
|||
|
|
@ -112,12 +112,12 @@ Tags must be defined in ACLs before use.
|
|||
## Next Steps
|
||||
|
||||
With networking established:
|
||||
- [[tutorials/replication/core-services | Set Up Core Services]] - Install Forgejo and optionally a container registry
|
||||
- [[tutorials/replication/kubernetes-bootstrap | Bootstrap Kubernetes]] - Your cluster will join the tailnet
|
||||
- Set up your server and storage devices
|
||||
|
||||
## BlumeOps Specifics
|
||||
|
||||
BluemeOps' Tailscale configuration includes:
|
||||
BlumeOps' Tailscale configuration includes:
|
||||
- Multiple device tags (`homelab`, `nas`, `registry`, `k8s-api`)
|
||||
- Group-based access for family members
|
||||
- SSH access rules with authentication requirements
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"""Validate that all wiki-links in documentation point to existing files.
|
||||
|
||||
This script scans all markdown files in the docs/ directory (excluding
|
||||
changelog.d/ and zk/), extracts wiki-links, and verifies each link target
|
||||
changelog.d/), extracts wiki-links, and verifies each link target
|
||||
exists as a filename or path in the documentation.
|
||||
|
||||
Wiki-link formats supported:
|
||||
|
|
@ -61,9 +61,9 @@ def main() -> int:
|
|||
# Track which filenames are ambiguous (appear multiple times)
|
||||
filename_counts: dict[str, list[str]] = {}
|
||||
|
||||
# Scan all markdown files (excluding zk/ and changelog.d/)
|
||||
# Scan all markdown files (excluding changelog.d/)
|
||||
for md_file in DOCS_DIR.rglob("*.md"):
|
||||
if "changelog.d" in md_file.parts or "zk" in md_file.parts:
|
||||
if "changelog.d" in md_file.parts:
|
||||
continue
|
||||
# Track filename occurrences
|
||||
filename = md_file.stem
|
||||
|
|
@ -86,9 +86,9 @@ def main() -> int:
|
|||
broken_links: list[tuple[str, int, str]] = []
|
||||
ambiguous_links: list[tuple[str, int, str, list[str]]] = []
|
||||
|
||||
# Scan all markdown files for wiki-links (excluding zk/ and changelog.d/)
|
||||
# Scan all markdown files for wiki-links (excluding changelog.d/)
|
||||
for md_file in sorted(DOCS_DIR.rglob("*.md")):
|
||||
if "changelog.d" in md_file.parts or "zk" in md_file.parts:
|
||||
if "changelog.d" in md_file.parts:
|
||||
continue
|
||||
|
||||
rel_path = str(md_file.relative_to(DOCS_DIR))
|
||||
|
|
|
|||
88
mise-tasks/doc-random
Executable file
88
mise-tasks/doc-random
Executable file
|
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.12"
|
||||
# dependencies = ["rich>=13.0.0"]
|
||||
# ///
|
||||
#MISE description="Select a random documentation card for review"
|
||||
"""Select a random documentation card for review.
|
||||
|
||||
This script scans all markdown files in the docs/ directory (excluding
|
||||
changelog.d/), selects one at random, and displays it for review.
|
||||
|
||||
Useful for periodic knowledge base maintenance and verification.
|
||||
|
||||
Usage: mise run doc-random
|
||||
"""
|
||||
|
||||
import random
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from rich.console import Console
|
||||
from rich.markdown import Markdown
|
||||
from rich.panel import Panel
|
||||
|
||||
DOCS_DIR = Path(__file__).parent.parent / "docs"
|
||||
|
||||
|
||||
def get_all_docs() -> list[Path]:
|
||||
"""Get all documentation markdown files, excluding changelog.d."""
|
||||
docs = []
|
||||
for md_file in DOCS_DIR.rglob("*.md"):
|
||||
# Skip changelog fragments
|
||||
if "changelog.d" in md_file.parts:
|
||||
continue
|
||||
docs.append(md_file)
|
||||
return docs
|
||||
|
||||
|
||||
def main() -> int:
|
||||
console = Console()
|
||||
|
||||
docs = get_all_docs()
|
||||
if not docs:
|
||||
console.print("[bold red]No documentation files found![/bold red]")
|
||||
return 1
|
||||
|
||||
# Select a random document
|
||||
selected = random.choice(docs)
|
||||
rel_path = selected.relative_to(DOCS_DIR)
|
||||
|
||||
# Display header
|
||||
console.print()
|
||||
console.print(Panel(
|
||||
f"[bold cyan]{rel_path}[/bold cyan]\n"
|
||||
f"[dim]{len(docs)} total docs in knowledge base[/dim]",
|
||||
title="[bold]Random Documentation Card[/bold]",
|
||||
border_style="cyan",
|
||||
))
|
||||
console.print()
|
||||
|
||||
# Display the file content
|
||||
content = selected.read_text()
|
||||
console.print(Markdown(content))
|
||||
|
||||
# Review checklist
|
||||
console.print()
|
||||
console.print(Panel(
|
||||
"[bold]Review Checklist:[/bold]\n\n"
|
||||
"• Is the information accurate and up-to-date?\n"
|
||||
"• Are there broken or missing wiki-links?\n"
|
||||
"• Should this card link to other related cards?\n"
|
||||
"• Is the card too large and should be split?\n"
|
||||
"• Is the card too small and should be merged?\n"
|
||||
"• Does the frontmatter (tags, title) make sense?\n"
|
||||
"• Is the card in the correct category (reference/how-to/etc)?\n\n"
|
||||
"[bold]Verify Deployed State:[/bold]\n\n"
|
||||
"• If ArgoCD app: is it synced? (argocd app get <app>)\n"
|
||||
"• If Ansible role: does it apply idempotently? (--check --diff)\n"
|
||||
"• If Pulumi: is there drift? (pulumi preview)",
|
||||
title="[bold yellow]Review Guidance[/bold yellow]",
|
||||
border_style="yellow",
|
||||
))
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue