diff --git a/Brewfile b/Brewfile index 5aa1402..a87fe8c 100644 --- a/Brewfile +++ b/Brewfile @@ -2,5 +2,6 @@ brew "actionlint" # GitHub/Forgejo Actions workflow linter brew "argocd" # ArgoCD CLI for GitOps management brew "bat" # Syntax-highlighted file concatenation +brew "mise" # Task runner and toolchain manager brew "tea" # Gitea/Forgejo CLI for forge.ops.eblu.me brew "podman" # Container CLI (uses VM on macOS, for building/pushing images) diff --git a/docs/README.md b/docs/README.md index 907c1ca..1416361 100644 --- a/docs/README.md +++ b/docs/README.md @@ -83,16 +83,18 @@ Information-oriented technical descriptions. Built first so other docs can link Learning-oriented content for getting started. Each tutorial explicitly identifies its target audiences. - [x] Create `tutorials/` directory with index -- [x] "What is BlumeOps?" - High-level orientation (Reader, AI) - [x] "Exploring the Docs" - How to navigate documentation (All) - [x] "AI Assistance Guide" - Context for AI-assisted operations (AI, Owner) - [x] "Contributing" - Your first contribution (Contributor) +- [x] "Adding a Service" - Deploy a new ArgoCD service (Contributor, Replicator) - [x] "Replicating BlumeOps" - Overview for building similar setup (Replicator) - [x] Replication sub-tutorials: - [x] Tailscale Setup + - [x] Core Services (Forgejo, Zot) - [x] Kubernetes Bootstrap - [x] ArgoCD Config - [x] Observability Stack +- [x] New reference cards: docs service, tailscale-operator, ansible/roles **Tutorials URL:** https://docs.ops.eblu.me/tutorials/ @@ -105,6 +107,7 @@ Task-oriented instructions for specific operations. - [ ] "How to add a new Ansible role" - [ ] "How to update Tailscale ACLs" - [ ] "How to troubleshoot common issues" +- [ ] Update `exploring-the-docs` with How-to section ### Phase 5: Explanation Understanding-oriented discussion of concepts and decisions. @@ -114,11 +117,13 @@ Understanding-oriented discussion of concepts and decisions. - [ ] "Architecture Overview" - How everything fits together - [ ] "Security Model" - Tailscale, secrets management, etc. - [ ] "Decision Log" - ADRs (Architecture Decision Records) +- [ ] Update `exploring-the-docs` with Explanation section ### Phase 6: Integration & Cleanup - [ ] Migrate remaining useful content from `docs/zk/` - [ ] Decide fate of zk cards (archive, delete, or keep as separate knowledge base) - [ ] Update CLAUDE.md to reference new doc structure +- [ ] Final review of `exploring-the-docs` for completeness - [ ] Mirror docs to GitHub Pages for public access (optional) ## Current Directory Layout diff --git a/docs/index.md b/docs/index.md index 0d12e53..ce01b1f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,8 +4,13 @@ title: blumeops-documentation Welcome to the BlumeOps documentation. -[[README | Documentation Home]] - Temporary home while docs are being restructured (see [Diataxis](https://diataxis.fr/) restructuring plan) +**New here?** Start with [[exploring-the-docs]] to find your way around. ## Sections -- [[reference/index | reference]] - Technical reference cards for services, infrastructure, and operations +- [[tutorials/index | Tutorials]] - Learning-oriented guides for getting started +- [[reference/index | Reference]] - Technical reference cards for services, infrastructure, and operations + +## About + +[[README | Documentation Home]] - Restructuring plan and changelog info diff --git a/docs/reference/ansible/roles.md b/docs/reference/ansible/roles.md new file mode 100644 index 0000000..d51847f --- /dev/null +++ b/docs/reference/ansible/roles.md @@ -0,0 +1,47 @@ +--- +title: ansible-roles +tags: + - ansible + - reference +--- + +# Ansible Roles + +Roles for provisioning services on [[indri]]. Run via `mise run provision-indri`. + +## Available Roles + +| Role | Purpose | Service | +|------|---------|---------| +| **alloy** | Observability collector | [[alloy]] | +| **borgmatic** | Backup automation | [[borgmatic]] | +| **borgmatic_metrics** | Backup metrics exporter | [[borgmatic]] | +| **caddy** | Reverse proxy & TLS | [[routing]] | +| **forgejo** | Git forge | [[forgejo]] | +| **jellyfin** | Media server | [[jellyfin]] | +| **jellyfin_metrics** | Media metrics exporter | [[jellyfin]] | +| **minikube** | Kubernetes cluster | [[cluster]] | +| **minikube_metrics** | Cluster metrics | [[cluster]] | +| **zot** | Container registry | [[zot]] | +| **zot_metrics** | Registry metrics | [[zot]] | + +## Role Structure + +Each role follows Ansible conventions: +``` +ansible/roles// +├── defaults/main.yml # Default variables +├── tasks/main.yml # Task definitions +├── handlers/main.yml # Handlers (restarts, etc.) +├── templates/ # Jinja2 templates +└── files/ # Static files +``` + +## Secrets + +Roles that need secrets use 1Password via the playbook's `pre_tasks`. Secrets are gathered at playbook start and passed to roles as variables. + +## Related + +- [[indri]] - Target host +- [[observability]] - Metrics collection diff --git a/docs/reference/index.md b/docs/reference/index.md index fe55778..8900424 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -31,6 +31,7 @@ Individual service reference cards with URLs and configuration details. | [[teslamate]] | Tesla data logger | k8s | | [[transmission]] | BitTorrent daemon | k8s | | [[zot]] | Container registry | indri | +| [[docs]] | Documentation site (Quartz) | k8s | ## Infrastructure @@ -48,8 +49,15 @@ Cluster configuration and application registry. - [[cluster | Cluster]] - Minikube specs, storage, networking - [[apps | Apps]] - ArgoCD application registry +- [[tailscale-operator]] - Tailscale ingress for k8s services - [[external-secrets]] - Secrets management +## Ansible + +Configuration management for [[indri]]-hosted services. + +- [[reference/ansible/roles | Roles]] - Available ansible roles + ## Storage Network storage and backup configuration. diff --git a/docs/reference/kubernetes/apps.md b/docs/reference/kubernetes/apps.md index db5ab58..298aafc 100644 --- a/docs/reference/kubernetes/apps.md +++ b/docs/reference/kubernetes/apps.md @@ -15,7 +15,7 @@ Registry of all applications deployed via [[argocd]]. |-----|-----------|-------------|---------| | `apps` | argocd | `argocd/apps/` | App-of-apps root | | `argocd` | argocd | `argocd/manifests/argocd/` | [[argocd]] | -| `tailscale-operator` | tailscale | `argocd/manifests/tailscale-operator/` | Tailscale k8s operator | +| `tailscale-operator` | tailscale | `argocd/manifests/tailscale-operator/` | [[tailscale-operator]] | | `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]] | diff --git a/docs/reference/kubernetes/tailscale-operator.md b/docs/reference/kubernetes/tailscale-operator.md new file mode 100644 index 0000000..8df8df3 --- /dev/null +++ b/docs/reference/kubernetes/tailscale-operator.md @@ -0,0 +1,40 @@ +--- +title: tailscale-operator +tags: + - kubernetes + - tailscale +--- + +# Tailscale Kubernetes Operator + +The Tailscale operator enables Kubernetes services to be exposed directly on the Tailscale network via Ingress resources. + +## Quick Reference + +| Property | Value | +|----------|-------| +| **Namespace** | `tailscale` | +| **Helm Chart** | `tailscale/tailscale-operator` | +| **ArgoCD App** | `tailscale-operator` | + +## How It Works + +When you create an Ingress with `ingressClassName: tailscale`: + +1. Operator provisions a Tailscale node for the service +2. Service becomes accessible at `.tail8d86e.ts.net` +3. TLS is handled automatically via Tailscale + +## Limitations + +Services exposed via Tailscale Ingress are **not accessible** from: +- Other Kubernetes pods (they're not Tailscale clients) +- Docker containers on indri + +For pod-to-service communication, use [[routing | Caddy]] (`*.ops.eblu.me`) instead. + +## Related + +- [[tailscale]] - Network configuration +- [[routing]] - Service routing options +- [[apps]] - Application registry diff --git a/docs/reference/services/docs.md b/docs/reference/services/docs.md new file mode 100644 index 0000000..9ab954c --- /dev/null +++ b/docs/reference/services/docs.md @@ -0,0 +1,49 @@ +--- +title: docs +tags: + - service + - documentation +--- + +# Docs (Quartz) + +Documentation site built with [Quartz](https://quartz.jzhao.xyz/) and served via nginx. + +## Quick Reference + +| Property | Value | +|----------|-------| +| **URL** | https://docs.ops.eblu.me | +| **Namespace** | `docs` | +| **Container** | `registry.ops.eblu.me/blumeops/quartz:v1.0.0` | +| **Source** | `docs/` directory in blumeops repo | +| **Build** | Forgejo workflow `build-blumeops.yaml` | + +## Architecture + +1. **Source**: Markdown files in `docs/` with Obsidian-compatible wiki-links +2. **Build**: Forgejo workflow builds Quartz static site on push to main +3. **Release**: Built assets published as Forgejo release attachments +4. **Deploy**: Container downloads release bundle on startup, serves via nginx + +## Release Process + +Documentation is automatically built and released when changes are pushed to main: + +1. Workflow detects changes in `docs/` directory +2. Quartz builds static HTML/CSS/JS +3. Assets uploaded as release attachment +4. ArgoCD deployment updated with new `DOCS_RELEASE_URL` +5. Pod restarts and downloads new bundle + +## Configuration + +- **Quartz config**: `quartz.config.ts` +- **Layout**: `quartz.layout.ts` +- **ArgoCD app**: `argocd/apps/docs.yaml` +- **Manifests**: `argocd/manifests/docs/` + +## Related + +- [[argocd]] - Deployment management +- [[forgejo]] - Build workflows diff --git a/docs/tutorials/adding-a-service.md b/docs/tutorials/adding-a-service.md new file mode 100644 index 0000000..b61c2dc --- /dev/null +++ b/docs/tutorials/adding-a-service.md @@ -0,0 +1,255 @@ +--- +title: adding-a-service +tags: + - tutorials + - argocd + - kubernetes +--- + +# Adding an ArgoCD-Managed Service + +> **Audiences:** Contributor, Replicator + +This tutorial walks through deploying a new service to BlumeOps via ArgoCD, including ingress configuration, homepage integration, and observability setup. + +## Prerequisites + +- Access to the [[tailscale | Tailscale]] network +- `kubectl` configured with `minikube-indri` context +- `argocd` CLI installed (via Brewfile: `brew bundle`) + +## Overview + +Adding a service involves: +1. Creating Kubernetes manifests +2. Creating an ArgoCD Application +3. Configuring Tailscale ingress +4. Adding Homepage dashboard entry +5. Setting up Grafana dashboards (optional) + +## Step 1: Create Manifests Directory + +Create a directory for your service's Kubernetes manifests: + +``` +argocd/manifests// +├── deployment.yaml +├── service.yaml +├── ingress-tailscale.yaml +└── configmap.yaml # if needed +``` + +### Example Deployment + +```yaml +# argocd/manifests/myservice/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: myservice + namespace: myservice +spec: + replicas: 1 + selector: + matchLabels: + app: myservice + template: + metadata: + labels: + app: myservice + spec: + containers: + - name: myservice + image: registry.ops.eblu.me/myservice:v1.0.0 + ports: + - containerPort: 8080 +``` + +### Example Service + +```yaml +# argocd/manifests/myservice/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: myservice + namespace: myservice +spec: + selector: + app: myservice + ports: + - port: 80 + targetPort: 8080 +``` + +## Step 2: Configure Tailscale Ingress + +Create an Ingress to expose the service via Tailscale. See [[tailscale-operator]] for details. + +```yaml +# argocd/manifests/myservice/ingress-tailscale.yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: myservice + namespace: myservice +spec: + ingressClassName: tailscale + rules: + - host: myservice + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: myservice + port: + number: 80 +``` + +This exposes the service at `https://myservice.tail8d86e.ts.net`. + +## Step 3: Add Homepage Annotations + +Add annotations to the Ingress for automatic Homepage dashboard discovery: + +```yaml +metadata: + annotations: + gethomepage.dev/enabled: "true" + gethomepage.dev/name: "My Service" + gethomepage.dev/group: "Apps" + gethomepage.dev/icon: "myservice.png" + gethomepage.dev/description: "Short description" + gethomepage.dev/href: "https://myservice.ops.eblu.me" + gethomepage.dev/pod-selector: "app=myservice" +``` + +Icons use [Dashboard Icons](https://github.com/walkxcode/dashboard-icons) format. + +## Step 4: Create ArgoCD Application + +Create an Application manifest to tell ArgoCD about your service: + +```yaml +# argocd/apps/myservice.yaml +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: myservice + namespace: argocd +spec: + project: default + source: + repoURL: ssh://forgejo@indri.tail8d86e.ts.net:2200/eblume/blumeops.git + targetRevision: main + path: argocd/manifests/myservice + destination: + server: https://kubernetes.default.svc + namespace: myservice + syncPolicy: + syncOptions: + - CreateNamespace=true +``` + +## Step 5: Add Caddy Route (Optional) + +If the service needs to be accessible from other pods or containers, add a Caddy route in `ansible/roles/caddy/defaults/main.yml`: + +```yaml +caddy_services: + # ... existing services ... + - name: myservice + upstream: "https://myservice.tail8d86e.ts.net" +``` + +Then run `mise run provision-indri -- --tags caddy` to apply. + +This enables access via `https://myservice.ops.eblu.me`. See [[routing]] for details on when this is needed. + +## Step 6: Deploy + +### Testing on a Feature Branch + +For new services, point ArgoCD at your feature branch first: + +```bash +# Sync the apps application to pick up your new Application +argocd app sync apps + +# Point your app at the feature branch +argocd app set myservice --revision feature/your-branch +argocd app sync myservice +``` + +### Verify Deployment + +```bash +kubectl --context=minikube-indri -n myservice get pods +kubectl --context=minikube-indri -n myservice logs -f deployment/myservice +``` + +### After PR Merge + +Reset to main branch: +```bash +argocd app set myservice --revision main +argocd app sync myservice +``` + +## Step 7: Add Observability (Optional) + +### Prometheus Metrics + +If your service exposes Prometheus metrics, add scrape annotations: + +```yaml +# In deployment.yaml pod template +metadata: + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8080" + prometheus.io/path: "/metrics" +``` + +### Grafana Dashboard + +Create a ConfigMap in `argocd/manifests/grafana-config/dashboards/`: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: myservice-dashboard + namespace: monitoring + labels: + grafana_dashboard: "1" + annotations: + grafana_folder: "Services" +data: + myservice.json: | + { ... dashboard JSON ... } +``` + +See [[grafana]] for dashboard provisioning details. + +## Checklist + +- [ ] Manifests created in `argocd/manifests//` +- [ ] ArgoCD Application created in `argocd/apps/` +- [ ] Tailscale Ingress configured +- [ ] Homepage annotations added +- [ ] Caddy route added (if needed for pod access) +- [ ] Feature branch tested via ArgoCD +- [ ] Metrics/dashboard configured (if applicable) +- [ ] PR created and reviewed +- [ ] Reset to main after merge + +## Related + +- [[argocd]] - GitOps platform +- [[tailscale-operator]] - Kubernetes ingress +- [[routing]] - Service routing options +- [[grafana]] - Dashboard configuration +- [[apps]] - Application registry diff --git a/docs/tutorials/ai-assistance-guide.md b/docs/tutorials/ai-assistance-guide.md index b9c321b..3c49b60 100644 --- a/docs/tutorials/ai-assistance-guide.md +++ b/docs/tutorials/ai-assistance-guide.md @@ -68,26 +68,31 @@ Understanding where services run helps target changes correctly: | [[indri]] (native) | Forgejo, Zot, Jellyfin, Caddy | Ansible | | [[cluster | Kubernetes]] | Everything else | ArgoCD | -## Common Operations +## Mise Tasks -### Kubernetes Service Changes +BlumeOps operations are driven by mise tasks. Run `mise tasks` to list all available tasks. -1. Modify manifests in `argocd/manifests//` -2. Preview with `argocd app diff ` -3. Deploy with `argocd app sync ` +| Task | When to Use | +|------|-------------| +| `zk-docs` | At session start - review infrastructure documentation | +| `provision-indri` | Deploy changes to [[indri]]-hosted services via Ansible | +| `indri-services-check` | After deployments - verify all services are healthy | +| `pr-comments` | Check unresolved PR comments during review | +| `blumeops-tasks` | Find pending tasks from Todoist | +| `container-list` | View available container images and tags | +| `container-tag-and-release` | Release a new container image version | +| `dns-preview` | Preview DNS changes before applying | +| `dns-up` | Apply DNS changes via Pulumi | +| `tailnet-preview` | Preview Tailscale ACL changes | +| `tailnet-up` | Apply Tailscale ACL changes via Pulumi | +| `doc-links` | Validate wiki-links in documentation | +| `doc-titles` | Check for duplicate doc titles | +| `doc-filenames` | Check for duplicate doc filenames | +| `indri-runner-logs` | View Forgejo workflow logs from local runner | -### Indri Service Changes - -1. Modify ansible role in `ansible/roles//` -2. Dry run: `mise run provision-indri -- --check --diff --tags ` -3. Deploy: `mise run provision-indri -- --tags ` - -### Health Checks - -After changes: -```bash -mise run indri-services-check -``` +For ArgoCD operations, use the `argocd` CLI directly: +- `argocd app diff ` - Preview changes +- `argocd app sync ` - Deploy changes ## Reference Navigation diff --git a/docs/tutorials/contributing.md b/docs/tutorials/contributing.md index 971bf94..d65ed23 100644 --- a/docs/tutorials/contributing.md +++ b/docs/tutorials/contributing.md @@ -16,7 +16,40 @@ This tutorial walks through making your first contribution to BluemeOps - from u Before contributing, you'll need: - Access to the [[tailscale|Tailscale]] network (request from Erich) - SSH key added to [[forgejo|Forgejo]] (https://forge.ops.eblu.me) -- `tea` CLI installed for PR creation +- Development tools installed (see below) + +## Tooling Setup + +The repo includes a `Brewfile` and `mise.toml` for easy setup, but these are optional - install the tools however you prefer. + +### Required Tools + +- `tea` - Gitea/Forgejo CLI for creating PRs +- `argocd` - ArgoCD CLI for deployments +- `pre-commit` - Git hooks for validation + +### Using Brewfile (Optional) + +```bash +brew bundle # installs tea, argocd, mise, etc. +``` + +### Using Mise (Optional) + +Mise manages language toolchains and runs tasks: +```bash +mise install # installs Python, Node.js, etc. from mise.toml +``` + +### Pre-commit Hooks + +Pre-commit hooks validate changes on `git commit`: +```bash +pre-commit install +pre-commit run --all-files # verify setup +``` + +All hooks should pass on a fresh clone. ## Understanding the Codebase @@ -47,6 +80,8 @@ Depending on what you're changing: **For Kubernetes services:** - Edit manifests in `argocd/manifests//` - Or create new Application in `argocd/apps/` +- For new apps, set `targetRevision` to your feature branch for testing +- For existing apps, you'll need to temporarily change the revision via `argocd app set` **For Indri services:** - Edit or create roles in `ansible/roles/` @@ -80,10 +115,9 @@ For Kubernetes changes: argocd app diff ``` -For Ansible changes: +For DNS changes: ```bash -# Dry run -mise run provision-indri -- --check --diff --tags +mise run dns-preview ``` ### 5. Commit and Push @@ -137,13 +171,7 @@ annotations: ``` 3. Create PR and wait for sync -## Getting Help - -- Browse [[reference/index|Reference]] for technical details -- Check `CLAUDE.md` in the repo for rules and conventions -- Ask Erich directly (he's friendly) - ## Related -- [[ai-assistance-guide]] - If using AI assistance for contributions +- [[adding-a-service]] - Full tutorial on deploying a new service - [[replicating-blumeops]] - If you want to build your own instead diff --git a/docs/tutorials/exploring-the-docs.md b/docs/tutorials/exploring-the-docs.md index 1e98fa2..37b4c3d 100644 --- a/docs/tutorials/exploring-the-docs.md +++ b/docs/tutorials/exploring-the-docs.md @@ -41,20 +41,20 @@ Context for effective assistance: ### For External Readers Understanding what this is: -- [[what-is-blumeops]] gives the high-level overview - [[reference/index|Reference]] shows what's actually running - Browse service pages to see specific implementations +- The repo's README has project context ### For Contributors Getting started with changes: - [[contributing]] walks through the workflow - [[reference/index|Reference]] tells you where things live -- The `CLAUDE.md` in the repo root has contribution rules ### For Replicators -Building your own: +Replicators are people who want to build their own similar homelab GitOps setup, using BlumeOps as inspiration. + - [[replicating-blumeops]] provides the overview - The `replication/` tutorials go deep on components - Reference pages show specific configuration choices @@ -64,10 +64,12 @@ Building your own: Documentation uses `[[wiki-links]]` for cross-references: - `[[service-name]]` links to a reference page - `[[folder/page]]` links to nested pages -- `[[page|Display Text]]` customizes the link text +- `[[page | Display Text]]` customizes the link text When reading on the web (docs.ops.eblu.me), these render as clickable links. The backlinks panel shows what references each page. +Pre-commit hooks automatically validate that all wiki-links point to existing files and that link targets are unambiguous. + ## Legacy Content The `docs/zk/` directory contains zettelkasten cards from before the restructuring. These are read-only reference - new content goes in the structured sections. The cards will eventually be migrated or archived. diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md index 35d4e61..776e42b 100644 --- a/docs/tutorials/index.md +++ b/docs/tutorials/index.md @@ -24,7 +24,6 @@ Each tutorial indicates which audiences it serves: | Tutorial | Audiences | Description | |----------|-----------|-------------| -| [[what-is-blumeops]] | Reader, AI | High-level orientation to the project | | [[exploring-the-docs]] | All | How to navigate and use this documentation | | [[ai-assistance-guide]] | AI, Owner | Context for effective AI-assisted operations | @@ -33,6 +32,7 @@ Each tutorial indicates which audiences it serves: | Tutorial | Audiences | Description | |----------|-----------|-------------| | [[contributing]] | Contributor | Your first contribution to BlumeOps | +| [[adding-a-service]] | Contributor, Replicator | Deploy a new service via ArgoCD | ## Replication @@ -42,6 +42,7 @@ For those building their own homelab GitOps setup. |----------|-----------|-------------| | [[replicating-blumeops]] | Replicator | Overview: building a similar environment | | [[tutorials/replication/tailscale-setup | Tailscale Setup]] | Replicator | Setting up Tailscale networking | +| [[tutorials/replication/core-services | Core Services]] | Replicator | Forgejo and container registry | | [[tutorials/replication/kubernetes-bootstrap | Kubernetes Bootstrap]] | Replicator | Bootstrapping a Kubernetes cluster | | [[tutorials/replication/argocd-config | ArgoCD Config]] | Replicator | Configuring GitOps with ArgoCD | | [[tutorials/replication/observability-stack | Observability Stack]] | Replicator | Metrics, logs, and dashboards | diff --git a/docs/tutorials/replicating-blumeops.md b/docs/tutorials/replicating-blumeops.md index 78132bf..6ddb5c5 100644 --- a/docs/tutorials/replicating-blumeops.md +++ b/docs/tutorials/replicating-blumeops.md @@ -26,7 +26,7 @@ BluemeOps runs on modest hardware. At minimum: | Component | BlumeOps Uses | Minimum Alternative | |-----------|---------------|---------------------| -| **Server** | Mac Mini M1 | Any machine with 16GB RAM | +| **Server** | Mac Mini M1 | Any machine with sufficient RAM (16GB recommended) | | **NAS** | Synology DS920+ | USB drive or second machine | | **Workstation** | MacBook Air M4 | Whatever you use daily | @@ -45,7 +45,18 @@ Before deploying services, establish secure connectivity. This replaces: traditional VPNs, port forwarding, dynamic DNS -### Phase 2: Kubernetes Cluster +### Phase 2: Core Services + +Bootstrap the essential services that everything else depends on. + +**[[tutorials/replication/core-services | Core Services Setup]]** +- Set up [[forgejo]] for git hosting and CI/CD +- Optionally set up [[zot]] container registry +- Configure SSH access and deploy keys + +Forgejo is central to GitOps - it's where your infrastructure definitions live and where CI/CD workflows run. + +### Phase 3: Kubernetes Cluster A cluster for running containerized workloads. @@ -56,7 +67,7 @@ A cluster for running containerized workloads. BlumeOps uses minikube for simplicity, but the patterns apply to any distribution. -### Phase 3: GitOps with ArgoCD +### Phase 4: GitOps with ArgoCD Declarative, git-driven deployments. @@ -68,7 +79,7 @@ Declarative, git-driven deployments. This is the heart of GitOps - changes in git automatically sync to your cluster. -### Phase 4: Observability Stack +### Phase 5: Observability Stack Know what's happening in your infrastructure. @@ -80,13 +91,14 @@ Know what's happening in your infrastructure. Without observability, you're flying blind. -### Phase 5: Your First Services +### Phase 6: Your First Services With the foundation in place, deploy actual workloads. BluemeOps runs: - [[miniflux]] - RSS reader - [[jellyfin]] - Media server - [[immich]] - Photo management - [[navidrome]] - Music streaming +- [[docs]] - Documentation site (Quartz) Pick what matters to you. Each service follows similar patterns: 1. Create Kubernetes manifests @@ -94,7 +106,7 @@ Pick what matters to you. Each service follows similar patterns: 3. Configure ingress routing 4. Sync and verify -### Phase 6: Backups and Resilience +### Phase 7: Backups and Resilience Protect your data. @@ -123,6 +135,5 @@ Begin with [[tutorials/replication/tailscale-setup]] - networking is the foundat ## Related -- [[what-is-blumeops]] - Understand what you're replicating - [[reference/index]] - See BlumeOps' specific configurations - [[contributing]] - Help improve BlumeOps instead diff --git a/docs/tutorials/replication/argocd-config.md b/docs/tutorials/replication/argocd-config.md index c3a09c4..2dcbe85 100644 --- a/docs/tutorials/replication/argocd-config.md +++ b/docs/tutorials/replication/argocd-config.md @@ -49,16 +49,13 @@ For Tailscale access: tailscale serve --bg --https 8443 https+insecure://localhost:$(kubectl -n argocd get svc argocd-server -o jsonpath='{.spec.ports[?(@.name=="https")].port}') ``` -Or create a Tailscale Ingress in Kubernetes. +Or create a Tailscale Ingress in Kubernetes (see [[tailscale-operator]]). Access at `https://your-server.tailnet.ts.net:8443` ### Install the CLI -```bash -brew install argocd # macOS -# or download from GitHub releases -``` +BlumeOps includes `argocd` in its Brewfile (`brew bundle`), or install it however you prefer. Login: ```bash diff --git a/docs/tutorials/replication/core-services.md b/docs/tutorials/replication/core-services.md new file mode 100644 index 0000000..3dc5847 --- /dev/null +++ b/docs/tutorials/replication/core-services.md @@ -0,0 +1,113 @@ +--- +title: core-services +tags: + - tutorials + - replication + - forgejo +--- + +# Core Services Setup + +> **Audiences:** Replicator + +This tutorial walks through setting up the foundational services that your GitOps infrastructure depends on: a git forge and optionally a container registry. + +## Why Core Services First? + +Before Kubernetes and ArgoCD, you need somewhere to store your infrastructure definitions. [[forgejo]] provides: +- Git hosting for your GitOps repository +- CI/CD workflows for building and deploying +- A web interface for code review and PRs + +The [[zot]] container registry is optional but useful for hosting your own container images. + +## Step 1: Install Forgejo + +Forgejo runs directly on your server (not in Kubernetes) because Kubernetes depends on it. + +### Using Ansible (BlumeOps Approach) + +BlumeOps manages Forgejo via an Ansible role. See [[reference/ansible/roles | Ansible Roles]]. + +### Manual Installation + +1. Download Forgejo from [forgejo.org](https://forgejo.org/download/) +2. Create a service user and directories +3. Configure with `app.ini` +4. Set up as a system service + +Key configuration points: +- SSH on a non-standard port (e.g., 2222) to avoid conflicts +- Database (SQLite works fine for personal use) +- Domain and URL settings for your Tailscale hostname + +## Step 2: Configure SSH Access + +Set up SSH for git operations: + +```bash +# Add your SSH key to Forgejo via the web UI +# Then test access: +ssh -T git@your-server.tailnet.ts.net -p 2222 +``` + +## Step 3: Create Your GitOps Repository + +1. Create a new repository in Forgejo (e.g., `infrastructure` or `homelab`) +2. Initialize the standard directory structure: + +``` +your-repo/ +├── ansible/ # Host configuration +│ ├── playbooks/ +│ └── roles/ +├── argocd/ # Kubernetes GitOps +│ ├── apps/ # ArgoCD Applications +│ └── manifests/ # K8s manifests per service +├── pulumi/ # IaC for Tailscale, DNS +└── docs/ # Documentation +``` + +3. Push your initial commit + +## Step 4: Set Up CI/CD Runner (Optional) + +Forgejo Actions runs workflows defined in `.forgejo/workflows/`. To use it: + +1. Register a runner on your server +2. Configure runner to access your build tools +3. Create workflow files for builds and deployments + +BlumeOps runs a Forgejo runner in Kubernetes - see [[forgejo]] for details. + +## Step 5: Container Registry (Optional) + +If you'll build custom container images, set up [[zot]]: + +1. Install Zot on your server +2. Configure authentication +3. Set up TLS (via Caddy or similar) + +For getting started, you can skip this and use public registries. + +## What You Now Have + +- Git hosting for infrastructure code +- SSH access for git operations +- Foundation for CI/CD workflows +- Optionally, a private container registry + +## Next Steps + +- [[tutorials/replication/kubernetes-bootstrap | Bootstrap Kubernetes]] - Now that you have a git repo, set up your cluster +- Configure Forgejo webhooks for ArgoCD (after ArgoCD is running) + +## BlumeOps Specifics + +BlumeOps' Forgejo setup includes: +- Ansible role for installation and updates +- SSH on port 2222, proxied via Caddy +- Integration with ArgoCD via deploy keys +- Forgejo runner in Kubernetes for CI/CD + +See [[forgejo]] and [[zot]] for full details. diff --git a/docs/tutorials/replication/observability-stack.md b/docs/tutorials/replication/observability-stack.md index 6a102d9..4c3adb2 100644 --- a/docs/tutorials/replication/observability-stack.md +++ b/docs/tutorials/replication/observability-stack.md @@ -177,7 +177,7 @@ spec: namespace: monitoring ``` -BluemeOps uses Alloy on both [[indri]] (for host metrics) and in the [[cluster]] (for pod logs and service probes). +BluemeOps uses Alloy on both [[indri]] (for host metrics, via [[reference/ansible/roles | Ansible role]]) and in the [[cluster]] (for pod logs and service probes). ## What You Now Have diff --git a/docs/tutorials/what-is-blumeops.md b/docs/tutorials/what-is-blumeops.md deleted file mode 100644 index cc65d17..0000000 --- a/docs/tutorials/what-is-blumeops.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: what-is-blumeops -tags: - - tutorials - - getting-started ---- - -# What is BlumeOps? - -> **Audiences:** Reader, AI - -BlumeOps is Erich Blume's personal infrastructure GitOps repository - a system for managing homelab services and infrastructure through version-controlled configuration. - -## The Short Version - -BlumeOps runs a collection of self-hosted services (media streaming, git hosting, photo management, RSS feeds, etc.) on home hardware, managed through code rather than manual configuration. Everything is tracked in a git repository, meaning changes are reviewable, reversible, and reproducible. - -## Why Does This Exist? - -Three motivations: - -1. **Learning** - A playground for exploring DevOps, Kubernetes, and infrastructure automation -2. **Privacy** - Self-hosting services keeps data under personal control -3. **Resilience** - Less dependence on cloud providers and their service changes - -## What's Running? - -BlumeOps consists of: - -- **A Mac Mini server** ([[indri]]) running Kubernetes and native services -- **A NAS** ([[sifaka]]) for storage and backups -- **~16 services** ranging from [[jellyfin|media streaming]] to [[grafana|observability dashboards]] -- **A Tailscale network** connecting everything securely - -See [[reference/index|Reference]] for the complete service inventory. - -## How Is It Organized? - -``` -blumeops/ -├── ansible/ # Configuration for services on indri -├── argocd/ # Kubernetes manifests and ArgoCD apps -├── pulumi/ # Tailscale ACLs and DNS -└── docs/ # This documentation -``` - -Changes follow a GitOps workflow: -1. Modify configuration in a feature branch -2. Create a pull request for review -3. Deploy via ArgoCD (Kubernetes) or Ansible (indri) -4. Merge to main after verification - -## Key Concepts - -| Concept | What It Means in BlumeOps | -|---------|---------------------------| -| **GitOps** | All infrastructure defined in git; deploys happen by syncing git state | -| **IaC** | Infrastructure as Code - servers, networks, services defined in files | -| **Homelab** | Personal server infrastructure at home, not in a datacenter | -| **Tailscale** | VPN mesh network connecting all devices securely | - -## Where to Go Next - -- **Want to understand the architecture?** See [[reference/index|Reference]] -- **Want to help with BlumeOps?** See [[contributing]] -- **Want to build something similar?** See [[replicating-blumeops]] -- **Working with AI assistance?** See [[ai-assistance-guide]]