{"id":51413877,"url":"https://github.com/jfroy/etincelle","last_synced_at":"2026-07-04T17:02:12.900Z","repository":{"id":359044233,"uuid":"1244255299","full_name":"jfroy/etincelle","owner":"jfroy","description":"We're going to light a fire.","archived":false,"fork":false,"pushed_at":"2026-06-08T17:42:34.000Z","size":64,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T19:22:02.890Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jfroy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-20T05:23:36.000Z","updated_at":"2026-06-08T17:42:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jfroy/etincelle","commit_stats":null,"previous_names":["jfroy/etincelle"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jfroy/etincelle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfroy%2Fetincelle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfroy%2Fetincelle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfroy%2Fetincelle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfroy%2Fetincelle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jfroy","download_url":"https://codeload.github.com/jfroy/etincelle/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfroy%2Fetincelle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35129190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-04T17:02:12.265Z","updated_at":"2026-07-04T17:02:12.882Z","avatar_url":"https://github.com/jfroy.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ✨ etincelle\n\nBootstrap utility server for the [flatops](https://github.com/jfroy/flatops) Kubernetes cluster. Runs Fedora image-mode (bootc), managed via GitOps — push to `main` builds and publishes a new OS image to ghcr.io.\n\n## Services\n\n| Service | Purpose |\n|---------|---------|\n| [Talos discovery service](https://github.com/siderolabs/discovery-service) | Node discovery for Talos cluster bootstrap (`ds.etincelle.cloud`) |\n| [Talos image factory](https://github.com/siderolabs/image-factory) | Builds custom Talos OS images for cluster nodes (`tif.etincelle.cloud`) |\n| [Distribution registry](https://github.com/distribution/distribution) | OCI registry used as image factory artifact cache (`registry.etincelle.cloud`) |\n| [Caddy](https://caddyserver.com) | Reverse proxy with automatic TLS via Cloudflare DNS-01 |\n| [Beszel agent](https://beszel.dev) | System and container metrics agent reporting to an external hub |\n| [Prometheus node exporter](https://github.com/prometheus/node_exporter) | Host metrics on `:9100` (default collectors) |\n\n## Build\n\nProduces a bootable qcow2 from the current `Containerfile` via [bootc-image-builder](https://github.com/osbuild/bootc-image-builder). Output lands at `output/qcow2/disk.qcow2` (10 GiB virtual, ~1.2 GiB sparse).\n\nPrerequisites:\n\n- `podman`, `qemu-img`, `go-task`\n- **Linux**: SELinux-enforcing hosts need `osbuild-selinux` installed. The build runs rootless (no `sudo`) using bootc-image-builder's `--in-vm` KVM mode, so `/dev/kvm` must be accessible to the invoking user.\n- **macOS**: rootful `podman machine` is required (rootless `--in-vm` cannot reach KVM inside Apple's hypervisor):\n\n  ```sh\n  podman machine init --cpus 2 --memory 2048 --disk-size 40\n  podman machine set --rootful\n  podman machine start\n  ```\n\nBuild:\n\n```sh\ntask bake\n```\n\nThe bake task pulls `ghcr.io/jfroy/etincelle:latest` for the host architecture (amd64 or arm64; the GitHub Actions workflow publishes both) and builds a matching qcow2.\n\n## Deploy\n\nOne-time install on a fresh VM:\n\n1. **(Optional) Resize the qcow2** before first boot. The image ships at 10 GiB; the root partition auto-grows to fill the disk on first boot via `systemd-growfs`, but the underlying disk must be enlarged first:\n\n   ```sh\n   qemu-img resize output/qcow2/disk.qcow2 100G\n   ```\n\n2. **Boot the VM.** Any UEFI-capable hypervisor works (UTM on Apple Silicon, `virt-install`/libvirt on Linux, etc.). The image has no BIOS fallback — UEFI is required.\n\n3. **SSH in** as the user defined in `config.toml` (currently `etincelle`). The key in `config.toml` is the only authorized credential; there is no console login or password.\n\n   ```sh\n   ssh etincelle@\u003cvm-ip\u003e\n   ```\n\n4. **Provision secrets and join Tailscale.** Requires the [1Password CLI](https://developer.1password.com/docs/cli/) signed in to the `kantai` vault on the workstation running the task:\n\n   ```sh\n   task provision HOST=\u003cvm-ip\u003e\n   ```\n\n   This installs `/etc/image-factory/keys/*`, `/etc/etincelle/secrets/caddy.env`, and `/etc/etincelle/secrets/beszel-agent.env` on the VM, starts `caddy.service`, `image-factory.service`, and `beszel-agent.service`, then prompts for a Tailscale auth key and runs `tailscale up`. Pass the key non-interactively with `TS_AUTHKEY=tskey-...`; submit an empty key to skip.\n\nOngoing updates are automatic: pushes to `main` build a new image via GitHub Actions, and `bootc-fetch-apply-updates.timer` on the VM applies it on the next interval (reboots into the new deployment).\n\n## Secrets and host state\n\nProvisioned post-install by `scripts/provision-secrets.sh`, never committed to this repo:\n\n- `/etc/image-factory/keys/` — Talos image factory signing keys\n- `/etc/etincelle/secrets/caddy.env` — Cloudflare API token for ACME DNS challenge\n- `/etc/etincelle/secrets/beszel-agent.env` — Beszel agent `TOKEN`\n- `/var/lib/tailscale/` — Tailscale node identity (created on first `tailscale up`)\n\nThe image grants passwordless `sudo` to the `wheel` group via `/etc/sudoers.d/wheel-nopasswd`, so the user defined in `config.toml` (currently `etincelle`) can run privileged commands without a password.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjfroy%2Fetincelle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjfroy%2Fetincelle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjfroy%2Fetincelle/lists"}