Keeps blumeops-managed state grouped under a single namespace in the home dir rather than scattered top-level dirs. Caddy block paths are derived from cv_content_dir / docs_content_dir, so the role-defaults edit propagates automatically. Validated end-to-end on indri: tarballs extracted to the new paths, sentinels written, second run is idempotent. Old ~/cv and ~/docs from the earlier validation run were removed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
69 lines
2.6 KiB
Markdown
69 lines
2.6 KiB
Markdown
---
|
|
title: CV
|
|
modified: 2026-04-29
|
|
last-reviewed: 2026-04-29
|
|
tags:
|
|
- service
|
|
- resume
|
|
---
|
|
|
|
# CV (Resume)
|
|
|
|
Personal resume/CV served as a static HTML page with PDF download, built from YAML source via Jinja2 and WeasyPrint.
|
|
|
|
## Quick Reference
|
|
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| **Public URL** | `cv.eblu.me` (via [[flyio-proxy]]) |
|
|
| **Private URL** | `cv.ops.eblu.me` (Caddy on indri) |
|
|
| **Deployment** | Ansible role `cv` on indri (no daemon — Caddy serves files directly) |
|
|
| **Content dir** | `~/blumeops/cv/content/` on indri |
|
|
| **Source repo** | `forge.eblu.me/eblume/cv` (private, not mirrored to GitHub) |
|
|
| **Content packages** | `forge.eblu.me/eblume/-/packages` (generic package `cv`) |
|
|
|
|
Migrated from minikube to indri-native on 2026-04-29 (see [[cv-on-indri]]).
|
|
|
|
## Architecture
|
|
|
|
1. **Source**: `resume.yaml` (content) + `template.html` (Jinja2) + `style.css` in the cv repo
|
|
2. **Build**: `render.py` (uv script runner) generates `index.html`; WeasyPrint generates `resume.pdf`
|
|
3. **Release**: Dagger `build` function packages `index.html`, `style.css`, `resume.pdf` into a tarball, uploaded to Forgejo generic packages
|
|
4. **Deploy**: ansible role downloads the tarball into `~/blumeops/cv/content/` on indri; Caddy serves the directory directly
|
|
|
|
## Endpoints
|
|
|
|
| Path | Description |
|
|
|------|-------------|
|
|
| `/` | Resume HTML page |
|
|
| `/resume.pdf` | PDF download (Caddy adds `Content-Disposition: attachment`) |
|
|
|
|
## Configuration
|
|
|
|
**Key files (blumeops):**
|
|
|
|
- `ansible/roles/cv/defaults/main.yml` — pinned `cv_version` and tarball URL
|
|
- `ansible/roles/cv/tasks/main.yml` — sentinel-gated download + extract
|
|
- `ansible/roles/caddy/defaults/main.yml` — `cv` service entry (`kind: static`, `download_paths` for the PDF)
|
|
|
|
**Key files (cv repo):**
|
|
|
|
- `resume.yaml` — Resume content (YAML)
|
|
- `template.html` — Jinja2 HTML template
|
|
- `style.css` — CSS with screen/print media queries
|
|
- `render.py` — uv script runner (PEP 723) that renders YAML → HTML
|
|
- `src/cv_ci/main.py` — Dagger pipeline (alpine + uv + WeasyPrint)
|
|
- `.forgejo/workflows/cv-release.yaml` — Release workflow
|
|
|
|
## Release flow
|
|
|
|
1. Release a new package from the cv repo (`Release CV` workflow)
|
|
2. Run the blumeops `Deploy CV` workflow → bumps `cv_version` in the ansible role and pushes
|
|
3. Run `mise run provision-indri -- --tags cv` from gilbert
|
|
4. Purge the Fly.io proxy cache so the new content is fetched
|
|
|
|
## Related
|
|
|
|
- [[cv-on-indri]] — Operations how-to
|
|
- [[docs]] — Similar architecture (Caddy serving a tarball-extracted dir)
|
|
- [[flyio-proxy]] — Exposes `cv.eblu.me` publicly via Tailscale tunnel
|