ci / Compose (pull_request) Successful in 27s
ci / Workflows (pull_request) Successful in 14s
ci / Shell (pull_request) Successful in 34s
ci / Python and tests (pull_request) Successful in 19s
ci / YAML (pull_request) Successful in 17s
ci / Dockerfiles (pull_request) Successful in 6s
ci / Formatting (pull_request) Successful in 36s
ci / Kubernetes (pull_request) Successful in 14s
ci / image-plan (pull_request) Skipped
ci / Image (${{ matrix.name }}) (pull_request) Skipped
ci / build (pull_request) Skipped
renovate-ci / validate-renovate (pull_request_target) Successful in 3m13s
164 lines
9.2 KiB
Markdown
164 lines
9.2 KiB
Markdown
# Homelab
|
|
|
|
Configuration for my homelab: Kubernetes manifests, Docker Compose stacks, and the
|
|
Gitea Actions that build and deploy them. Most applications have both deployment
|
|
formats. Headscale and Nextcloud AIO have Compose deployments with Kubernetes
|
|
ingress; the media stack has Compose and Kubernetes routing configuration.
|
|
|
|
These files contain this lab's domains, IP addresses, storage paths, and private
|
|
registry names. Running them on another machine takes some editing.
|
|
|
|
## Start here
|
|
|
|
- [Service list](#services) — what each directory contains.
|
|
- [Deployment workflow](.gitea/README.md) — selection, validation, and recovery.
|
|
- [Repository review](docs/repository-review.md) — findings from the 6 October baseline and their status.
|
|
- [EDU ownership handoff](.gitea/EDU_HANDOFF.md) — the EDU workloads now live in their own repository.
|
|
- [Shared PostgreSQL](postgres/README.md), [Traefik](traefik/README.md), and
|
|
[cert-manager](cert-manager/README.md) — common dependencies.
|
|
|
|
## What gets deployed
|
|
|
|
The `active` files are switches for the deploy workflow, not health indicators.
|
|
|
|
| File | Effect |
|
|
| ---------------------- | ----------------------------------------------------------- |
|
|
| `<service>/active` | Include that directory's `compose.yaml` or `compose.yml`. |
|
|
| `<service>/k8s/active` | Include its Kubernetes manifests or Kustomize overlay. |
|
|
| Both | Run the Compose stack and apply the Kubernetes resources. |
|
|
| Neither | Keep the configuration in Git without automatic deployment. |
|
|
|
|
`shared-compose.yaml`, `client.compose.yaml`, and `renovate-compose.yaml` are
|
|
manual entry points. The deploy script does not discover them.
|
|
|
|
Kubernetes selection excludes secret files, examples, Helm values, and patches.
|
|
Helm releases listed in `deploy-lib.sh` are upgraded separately. Traefik,
|
|
cert-manager, and CrowdSec have additional bootstrap steps; an `active` marker
|
|
does not install their charts.
|
|
|
|
The table below describes committed configuration. It does not claim that a
|
|
service is currently healthy or running.
|
|
|
|
## Services
|
|
|
|
| Service | Configuration | Selected by markers |
|
|
| ---------------------------------------------- | ---------------------------- | ------------------- |
|
|
| [AdGuard Home](adguardhome/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Authentik](authentik/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [cert-manager](cert-manager/README.md) | Kubernetes / Helm | Manual |
|
|
| [Cloudflare DDNS](cfddns/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Checkmk](checkmk/README.md) | Kubernetes + Compose | Manual |
|
|
| [Cloudflare Tunnel](cloudflared/README.md) | Kubernetes / Helm | Manual |
|
|
| [File converters](converters/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [CrowdSec](crowdsec/README.md) | Kubernetes / Helm | Manual |
|
|
| [Dockmon](dockmon/README.md) | Kubernetes + Compose | Manual |
|
|
| [Downtify](downtify/README.md) | Kubernetes + Compose | Manual |
|
|
| [Error pages](errorpages/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Gitea](gitea/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Glance](glance/README.md) | Kubernetes + Compose | Manual |
|
|
| [Headscale](headscale/README.md) | Compose + Kubernetes routing | Compose, Kubernetes |
|
|
| [Homarr](homarr/README.md) | Kubernetes + Compose | Manual |
|
|
| [Homepages](homepages/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Immich](immich/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Kener](kener/README.md) | Kubernetes + Compose | Manual |
|
|
| [Loki and Alloy](loki/README.md) | Kubernetes / Helm | Kubernetes |
|
|
| [MeTube](metube/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [n8n](n8n/README.md) | Kubernetes + Compose | Manual |
|
|
| [NetBird](netbird/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [NetBox](netbox/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Netronome](netronome/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Nextcloud AIO](nextcloud/README.md) | Compose + Kubernetes routing | Compose, Kubernetes |
|
|
| [Penpot](penpot/README.md) | Compose | Manual |
|
|
| [Portainer](portainer/README.md) | Kubernetes + Compose | Manual |
|
|
| [Shared PostgreSQL](postgres/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Monitoring stack](prometheus-stack/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [RackPeek](rackpeek/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Reloader](reloader/README.md) | Kubernetes / Helm | Kubernetes |
|
|
| [Renovate](renovate/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [SearXNG](searxng/README.md) | Kubernetes + Compose | Manual |
|
|
| [Media stack](streaming/README.md) | Compose + Kubernetes routing | Manual |
|
|
| [Termix](termix/README.md) | Kubernetes + Compose | Manual |
|
|
| [Traefik](traefik/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Uptime Kuma](uptime-kuma/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [Vaultwarden](vaultwarden/README.md) | Kubernetes + Compose | Kubernetes |
|
|
| [3x-ui](vpn/xui/README.md) | Kubernetes | Kubernetes |
|
|
|
|
## Running a Compose stack
|
|
|
|
Use the service README first. Where a service has an env example, copy it inside
|
|
that service's directory and replace the placeholders. The root `.env.example`
|
|
is an older collection of variables, not a complete configuration for every stack.
|
|
|
|
For example, from the repository root:
|
|
|
|
```sh
|
|
cd netbox
|
|
cp .env.example .env
|
|
$EDITOR .env
|
|
docker compose config --quiet
|
|
docker compose up -d
|
|
docker compose ps
|
|
```
|
|
|
|
Stacks that attach to `proxy` require an existing Docker network of that name and
|
|
an appropriate reverse proxy. Published host ports still work independently of
|
|
Traefik. Check port conflicts before starting an alternative to a Kubernetes
|
|
service: DNS, STUN, and HTTP listeners can share the same host.
|
|
|
|
`docker compose down` keeps named volumes. Adding `-v` removes them.
|
|
|
|
## Preparing Kubernetes
|
|
|
|
The manifests assume Traefik CRDs, cert-manager, and a working storage provisioner.
|
|
PrometheusRule and ServiceMonitor resources also need the Prometheus Operator.
|
|
Replace the lab's hosts and addresses before using the configuration elsewhere.
|
|
|
|
Create a service's namespace, then prepare its ignored Secret from the example.
|
|
For example:
|
|
|
|
```sh
|
|
kubectl apply -f netbox/k8s/namespace.yaml
|
|
cp netbox/k8s/secrets.yaml.example netbox/k8s/secrets.yaml
|
|
$EDITOR netbox/k8s/secrets.yaml
|
|
kubectl apply -f netbox/k8s/secrets.yaml
|
|
```
|
|
|
|
The deploy workflow applies the tracked resources for marked services. Avoid
|
|
applying an entire `k8s/` directory blindly: some directories contain Helm values,
|
|
examples, and alternative routes. For a manual change, apply the selected manifest
|
|
explicitly and check the resulting rollout.
|
|
|
|
Shared database passwords must agree between the `database` namespace and each
|
|
application's Secret. Updating the PostgreSQL Secret does not change an existing
|
|
role's password; see the database README.
|
|
|
|
## Local checks
|
|
|
|
CI pins its tools in `.gitea/workflows/tool-versions.env`. Use the same versions:
|
|
|
|
```fish
|
|
set tools_dir (bash .gitea/workflows/install-ci-tools.sh)
|
|
set -gx PATH $tools_dir $PATH
|
|
ruff check .
|
|
ruff format --check .
|
|
actionlint -config-file .gitea/actionlint.yaml .gitea/workflows/*.yaml
|
|
.gitea/workflows/sync-renovate-configmap.sh --check
|
|
```
|
|
|
|
The [workflow README](.gitea/README.md#ci) lists the rest of the checks.
|
|
Structure checks do not establish that local Secrets, mounted files, storage,
|
|
or external services are ready.
|
|
|
|
## Data and recovery
|
|
|
|
State lives outside Git: PVCs, Docker volumes, bind mounts, databases, and ignored
|
|
configuration. Keep backups of application data and the keys needed to read it.
|
|
An image rollback does not roll back database migrations or ConfigMap contents.
|
|
|
|
Many PVCs use the cluster's default StorageClass; monitoring explicitly uses
|
|
`local-path`. Check the PV reclaim policy before deleting a PVC or namespace.
|
|
The manifests do not provide a repository-wide backup schedule.
|
|
|
|
`incident-archive/` contains past incident notes. `.docs/storage-audit-instruction.md`
|
|
is a planning document, not evidence that NFS has been installed.
|