- HCL 98.4%
- Shell 1.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
terraform / check (push) Successful in 33s
Reviewed-on: #29 |
||
| .agents/skills | ||
| .forgejo/workflows | ||
| modules | ||
| scripts | ||
| .gitignore | ||
| .terraform.lock.hcl | ||
| AGENTS.md | ||
| backend.hcl.example | ||
| backend.tf | ||
| dns.tf | ||
| main.tf | ||
| nodes.tf | ||
| outputs.tf | ||
| providers.tf | ||
| README.md | ||
| terraform.tfvars.example | ||
| variables.tf | ||
| versions.tf | ||
homelab
Terraform configuration for a three-node Raspberry Pi k3s homelab. Terraform manages Kubernetes resources and Cloudflare configuration; it does not install or manage the Pi operating systems or the k3s control plane.
Overview
- Public web applications use Cloudflare Tunnel to reach the cluster's Traefik ingress. Jellyfin is LAN-only.
- Authentik provides SSO; application roles are assigned through Authentik groups.
- Terraform state is stored in RustFS inside the cluster.
The Homelab knowledge base records repository-declared architecture, service, and storage facts. It is not a live health dashboard. Terraform and application configuration in this repository remain the sources of desired state.
Centralized logs
Grafana Alloy collects Kubernetes container logs and node systemd journal
entries (including K3s and kernel messages) and sends them to Loki. Loki retains
logs for 14 days on a 10Gi Longhorn volume; the Loki data source is available
inside Grafana and is not exposed as a separate public service. The overview
dashboard's node logs panel includes a threshold level filter: selecting a
severity shows that level and higher severities based on structured level or
severity fields, so words in the message body do not affect the threshold.
Its All option also shows logs without a recognized severity field.
The same dashboard section includes a top-20 table of structured error-level
messages over a fixed rolling 72-hour window, grouped by namespace, container,
severity, and message across pods.
Alloy reads host journals from /var/log/journal and /run/log/journal. For
replay of logs across reboots, configure persistent journaling on each node
(Storage=persistent in /etc/systemd/journald.conf) and restart
systemd-journald; the repository does not manage node OS configuration. Logs
can contain application data and should be treated as sensitive.
Getting started
Use the shared cluster and state only with authorized access. Local prerequisites
are Git, Terraform 1.7 or later, and kubectl configured for the cluster. A
maintainer provides terraform.tfvars; it contains credentials and is never
committed.
git clone https://git.113lab.dev/finn/homelab.git
cd homelab
cp terraform.tfvars.example terraform.tfvars
scripts/tf plan
scripts/tf reads the RustFS backend credentials from the cluster, opens a
temporary port-forward, and runs terraform init on first use. The Forgejo CI
workflow checks formatting and validation; it does not apply Terraform.
Authentik access
Applications can map Authentik group claims to application roles. Current group names and membership are not maintained as a static inventory: inspect the Authentik blueprint and the app's role mapping for configured groups, and query Authentik for live membership. When onboarding an app, document the role groups and grants introduced for that app in this README; do not keep a global snapshot of current group names.
Repository layout
- Root
*.tffiles wire providers, variables, outputs, and modules. modules/contains service and platform Terraform..forgejo/contains central Forgejo workflows and issue forms..agents/skills/contains task-specific agent skills and on-demand references.scripts/contains Terraform and maintenance helpers;test/contains workflow tests.
terraform.tfvars, backend.hcl, Terraform state, saved plans, and secret
material are local or remote operational data, not repository files.