{"id":13582238,"url":"https://github.com/davidsbond/homelab","last_synced_at":"2026-01-14T20:42:45.911Z","repository":{"id":40352095,"uuid":"297949482","full_name":"davidsbond/homelab","owner":"davidsbond","description":"Monorepo for my personal homelab","archived":true,"fork":false,"pushed_at":"2022-05-13T12:04:45.000Z","size":23535,"stargazers_count":159,"open_issues_count":10,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-06T14:36:09.580Z","etag":null,"topics":["golang","homelab","kubernetes","raspberry-pi"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidsbond.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-23T11:35:41.000Z","updated_at":"2025-03-28T19:16:49.000Z","dependencies_parsed_at":"2022-08-09T18:00:26.190Z","dependency_job_id":null,"html_url":"https://github.com/davidsbond/homelab","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/davidsbond/homelab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsbond%2Fhomelab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsbond%2Fhomelab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsbond%2Fhomelab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsbond%2Fhomelab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidsbond","download_url":"https://codeload.github.com/davidsbond/homelab/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsbond%2Fhomelab/sbom","scorecard":{"id":327601,"data":{"date":"2025-08-11","repo":{"name":"github.com/davidsbond/homelab","commit":"bb60f613cc1ffeaa144d4f238746bf8f458aa4a2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/13 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/docker.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":2,"reason":"dependency not pinned by hash detected -- score normalized to 2","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:52: update your workflow using https://app.stepsecurity.io/secureworkflow/davidsbond/homelab/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:65: update your workflow using https://app.stepsecurity.io/secureworkflow/davidsbond/homelab/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:80: update your workflow using https://app.stepsecurity.io/secureworkflow/davidsbond/homelab/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/davidsbond/homelab/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/davidsbond/homelab/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/davidsbond/homelab/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docker.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/davidsbond/homelab/docker.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/davidsbond/homelab/docker.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/davidsbond/homelab/docker.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1","Warn: goCommand not pinned by hash: vendor/github.com/json-iterator/go/build.sh:10","Warn: goCommand not pinned by hash: vendor/github.com/pelletier/go-toml/benchmark.sh:10","Warn: goCommand not pinned by hash: vendor/google.golang.org/grpc/regenerate.sh:35","Warn: goCommand not pinned by hash: vendor/google.golang.org/grpc/vet.sh:39","Warn: goCommand not pinned by hash: vendor/google.golang.org/grpc/vet.sh:49","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned","Info:   3 out of   8 goCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"38 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2022-0635","Warn: Project is vulnerable to: GO-2022-0646","Warn: Project is vulnerable to: GO-2024-2606 / GHSA-7jwh-3vrq-q3m8 / GHSA-mrww-27vc-gghv","Warn: Project is vulnerable to: GO-2024-2605 / GHSA-m7wr-2xf7-cm9p","Warn: Project is vulnerable to: GO-2022-0968 / GHSA-gwc9-m7rh-j2ww","Warn: Project is vulnerable to: GO-2021-0356 / GHSA-8c26-wmh5-6g9v","Warn: Project is vulnerable to: GO-2024-2961","Warn: Project is vulnerable to: GO-2023-2402 / GHSA-45x7-px36-x8w8","Warn: Project is vulnerable to: GO-2024-3321 / GHSA-v778-237x-gjrc","Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77","Warn: Project is vulnerable to: GO-2022-0969 / GHSA-69cg-p879-7622","Warn: Project is vulnerable to: GO-2022-1144 / GHSA-xrjj-mj9h-534m","Warn: Project is vulnerable to: GO-2023-1571 / GHSA-vvpx-j8f3-3w6h","Warn: Project is vulnerable to: GO-2023-1988 / GHSA-2wrh-6pvc-2jm9","Warn: Project is vulnerable to: GO-2023-2102 / GHSA-4374-p667-p6c8","Warn: Project is vulnerable to: GO-2023-2153 / GHSA-m425-mq94-257g / GHSA-qppj-fm5r-hxr3","Warn: Project is vulnerable to: GO-2024-2687 / GHSA-4v7x-pqxf-cx7m","Warn: Project is vulnerable to: GO-2024-3333","Warn: Project is vulnerable to: GO-2025-3503 / GHSA-qxp5-gwg8-xv66","Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw","Warn: Project is vulnerable to: GO-2025-3488 / GHSA-6v2p-p543-phr9","Warn: Project is vulnerable to: GO-2022-0493 / GHSA-p782-xgp4-8hr8","Warn: Project is vulnerable to: GO-2022-1059 / GHSA-69ch-w2m2-3vjp","Warn: Project is vulnerable to: GO-2024-2611 / GHSA-8r3f-844c-mc37","Warn: Project is vulnerable to: GO-2022-0603 / GHSA-hp87-p4gw-j4gq","Warn: Project is vulnerable to: GHSA-cpwx-vrp4-4pq7","Warn: Project is vulnerable to: GHSA-h5c8-rqwp-cp95","Warn: Project is vulnerable to: GHSA-h75v-3vvj-5mfj","Warn: Project is vulnerable to: GHSA-q2x7-8rv6-6q7h","Warn: Project is vulnerable to: PYSEC-2023-117 / GHSA-mrwq-x4v8-fh7p","Warn: Project is vulnerable to: GHSA-jh85-wwv9-24hv","Warn: Project is vulnerable to: GHSA-753j-mpmx-qq6g","Warn: Project is vulnerable to: GHSA-7cx3-6m66-7c5m","Warn: Project is vulnerable to: GHSA-8w49-h785-mj3c","Warn: Project is vulnerable to: PYSEC-2023-75 / GHSA-hj3f-6gcp-jg8j","Warn: Project is vulnerable to: GHSA-qppv-j76h-2rpx","Warn: Project is vulnerable to: GHSA-w235-7p84-xx57","Warn: Project is vulnerable to: GHSA-jfmj-5v4g-7637"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T02:50:47.723Z","repository_id":40352095,"created_at":"2025-08-18T02:50:47.723Z","updated_at":"2025-08-18T02:50:47.723Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28434494,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T18:57:19.464Z","status":"ssl_error","status_checked_at":"2026-01-14T18:52:48.501Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["golang","homelab","kubernetes","raspberry-pi"],"created_at":"2024-08-01T15:02:31.217Z","updated_at":"2026-01-14T20:42:45.891Z","avatar_url":"https://github.com/davidsbond.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# homelab [![PkgGoDev](https://pkg.go.dev/badge/github.com/davidsbond/homelab)](https://pkg.go.dev/github.com/davidsbond/homelab) [![Go Report Card](https://goreportcard.com/badge/github.com/davidsbond/homelab)](https://goreportcard.com/report/github.com/davidsbond/homelab)\n\nMonorepo for my personal homelab. It contains applications and kubernetes manifests for deployment.\n\n\u003c!-- ToC start --\u003e\n   1. [Getting started](#getting-started)\n   1. [Project structure](#project-structure)\n   1. [Third party applications](#third-party-applications)\n   1. [Prometheus exporters](#prometheus-exporters)\n   1. [Other tools](#other-tools)\n   1. [User interfaces](#user-interfaces)\n   1. [External services](#external-services)\n   1. [Cluster upgrades](#cluster-upgrades)\n   1. [Node maintenance](#node-maintenance)\n      1. [Crontab](#crontab)\n      1. [K3s services](#k3s-services)\n      1. [Overclocking](#overclocking)\n      1. [Multipath](#multipath)\n   1. [Managed infrastructure](#managed-infrastructure)\n      1. [Terraform Providers](#terraform-providers)\n      1. [Database provisioning](#database-provisioning)\n      1. [Docker images](#docker-images)\n   1. [Environment](#environment)\n\u003c!-- ToC end --\u003e\n\n## Getting started\n\nThis assumes you have the following tools:\n\n* [go](https://golang.org/)\n* [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl)\n* [kustomize](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization)\n* [make](https://www.gnu.org/software/make/manual/make.html)\n* [buildx](https://docs.docker.com/buildx/working-with-buildx/)\n* [terraform](https://www.terraform.io/)\n\nTo start working:\n\n* Clone the repository\n* Install golang-based tools using `make install-tools`\n* Run `make` to build all binaries\n\n## Project structure\n\n* `cmd` - Entry points to any bespoke applications.\n* `hack` - Node host specific config files and tweaks.\n* `internal` - Packages used throughout the application code.\n* `manifests` - Kubernetes manifests to run all my homelab applications.\n* `scripts` - Bash scripts for working within the repository.\n* `terraform` - Terraform files for managing infrastructure.\n* `vendor` - Vendored third-party code.\n\n## Third party applications\n\nHere's a list of third-party applications I'm using alongside my custom applications:\n\n* [longhorn](https://longhorn.io/) - Cloud native distributed block storage for Kubernetes.\n* [home-assistant](https://www.home-assistant.io/) - Open source home automation that puts local control and privacy first.\n* [pihole](https://pi-hole.net/) - A black hole for Internet advertisements.\n* [traefik](https://traefik.io/) - The Cloud Native Application Proxy.\n* [prometheus](https://prometheus.io/) - The Prometheus monitoring system and time series database.\n* [grafana](https://grafana.com/) - The open observability platform.\n* [jaeger](https://www.jaegertracing.io/) - Open source, end-to-end distributed tracing.\n* [node-exporter](https://github.com/prometheus/node_exporter) - Exporter for machine metrics.\n* [minio](https://min.io/) - High Performance, Kubernetes Native Object Storage.\n* [postgres](https://www.postgresql.org/) - The world's most advanced open source database.\n* [firefly](https://www.firefly-iii.org/) - A free and open source personal finances manager.\n* [photoprism](https://photoprism.pro/features) - Personal Photo Management powered by Go and Google TensorFlow.\n* [cert-manager](https://cert-manager.io/) - x509 certificate management for Kubernetes.\n* [docker-registry](https://docs.docker.com/registry/) - A stateless, highly scalable server side application that stores \n  and lets you distribute Docker images\n* [fluent-bit](https://fluentbit.io/) - Log processor and forwarder\n\n## Prometheus exporters\n\nI've implemented several custom prometheus exporters in this repo that power my dashboards, these are:\n\n* `coronavirus` - Exports UK coronavirus stats as prometheus metrics\n* `homehub` - Exports statistics from my BT HomeHub as prometheus metrics\n* `pihole` - Exports statistics from my pihole as prometheus metrics\n* `speedtest` - Exports [speedtest](https://speedtest.net) results as prometheus metrics\n* `weather` - Exports current weather data as prometheus metrics\n* `worldping` - Exports world ping times for the local host as prometheus metrics\n* `home-assistant` - Proxies prometheus metrics from a home-assistant server.\n* `synology` - Exports statistics from my NAS drive.\n* `minecraft` - Exports statistics for my Minecraft server.\n\n## Other tools\n\nHere are other tools I've implemented for use in the cluster.\n\n* `bucket-object-cleaner` - Deletes objects in a blob bucket older than a configured age.\n* `grafana-backup` - Copies all dashboards and data sources from grafana and writes them to a MinIO bucket.\n* [db-backup](https://github.com/davidsbond/db-backup) - A backup utility for databases.\n* `ftp-backup` - Copies all files from a specified path of an FTP server and writes them to a MinIO bucket.\n\n## User interfaces\n\nThis repo contains a few homemade user interfaces for navigation/overview of the applications running in the cluster.\n\n* `directory` - A simple YAML configured link page to access different services in the homelab.\n\n![Directory](img/directory.png)\n\n* `health-dashboard` - A simple UI that returns the health check status of custom services using the `pkg.dsb.dev`\nflavoured health checks.\n\n![Health Dashboard](img/health.png)\n\n## External services\n\nThese are devices/services that the cluster interacts with, without being directly installed in the cluster.\n\n* [Ring](https://ring.com/) - Home security devices, connected via home-assistant\n* [Tailscale](https://tailscale.com/) VPN - Used to access the cluster from anywhere\n* [Synology](https://www.synology.com/) NAS - Used as the storage backend for minio, primarily used for volume backups\n* [Phillips Hue](https://www.philips-hue.com/en-gb) - Smart lighting, connected via home-assistant\n* [Cloudflare](https://www.cloudflare.com/) - DNS, used to access my applications under the `*.homelab.dsb.dev` domain.\n* [Sentry](https://sentry.io/) -  Cloud-based error monitoring.\n\n## Cluster upgrades\n\nUpgrading the k3s cluster itself is managed using Rancher's [system-upgrade-controller](https://github.com/rancher/system-upgrade-controller).\nIt automates upgrading the cluster through the use of a CRD. To perform a cluster upgrade, see the [plans](manifests/kube-system/system-upgrade-controller/plans)\ndirectory. Each upgrade is stored in its own directory named using the desired version, when the plan manifests get applied\nvia kustomize jobs will be started by the controller that upgrade the master node, followed by the worker nodes. The upgrade only takes\na few minutes and tools like `k9s` and `kubectl` will not be able to communicate with the cluster for a small amount of time while\nthe master node upgrades.\n\n## Node maintenance\n\nThe [hack](./hack) diretory at the root of the repository contains files used on all nodes in the cluster.\n\n### Crontab\n \nThe `crontab` file describes scheduled tasks that clear out temporary and old files on the filesystem \n(/tmp, /var/log etc) and performs package upgrades on a weekly basis. It will also prune container images that are no \nlonger in use.\n\nThe crontab file can be deployed to all nodes using the `make install-cron-jobs` recipe. This command will copy over the\ncontents of the local crontab file to each node via SSH. You need to have used `ssh copy-key-id` for each node, so you \ndon't get any password prompts.\n\n### K3s services\n\nThe `k3s.service` and `k3s-agent.service` files are the `systemd` service files that run the service and agent nodes. It\nsets the cluster to communicate via the Tailscale network and stops k3s from installing traefik. This is because I run\ntraefik 2, whereas k3s comes with 1.7 by default.\n\n### Overclocking\n\nThe `usercfg.txt` file is stored at `/boot/firmware/usercfg.txt` and is used to set overclocking values for the Raspberry\nPis. Pretty certain this voids my warranty, so if you're not me and planning on using this repository you should keep that\nin mind.\n\nSee [Overclocking options in config.txt](https://www.raspberrypi.org/documentation/configuration/config-txt/overclocking.md)\nfor more details on these values.\n\n### Multipath\n\nThe `multipath.conf` file is the configuration file for the multipath daemon. It is used to overwrite the built-in \nconfiguration table of `multipathd`. Any line whose first non-white-space character is a '#' is considered a comment line. \nEmpty lines are ignored.\n\nThe sole reason for this existing, is to handle [an issue with longhorn](https://github.com/longhorn/longhorn/issues/1210)\nthat I was experiencing.\n\n## Managed infrastructure\n\nSome aspects of the homelab are managed using Terraform. These include DNS records via CloudFlare. To plan and apply\nchanges, use the `Makefile` in the [terraform](./terraform) directory. The `make plan` and `make apply` recipes will\nperform changes.\n\nThe terraform state is included in this repository. It is encrypted using strongbox, which is installed when using\n`make install-tools`.\n\n### Terraform Providers\n\nThis list contains all terraform providers used in the project:\n\n* [cloudflare](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs)\n* [minio](https://github.com/aminueza/terraform-provider-minio)\n* [grafana](https://registry.terraform.io/providers/grafana/grafana/latest/docs)\n* [tailscale](https://registry.terraform.io/providers/davidsbond/tailscale/latest/docs)\n* [sentry](https://registry.terraform.io/providers/jianyuan/sentry/latest/docs)\n\n### Database provisioning\n\nNew postgres databases can be provisioned using a kubernetes `Job` resource using the `createdb` binary included in standard\n`postgres` docker images. Below is an example:\n\n```yaml\napiVersion: batch/v1\nkind: Job\nmetadata:\n  name: example-db-init\nspec:\n  template:\n    spec:\n      containers:\n        - image: postgres:13.1-alpine\n          name: createdb\n          command:\n            - createdb\n          env:\n            - name: PGHOST\n              value: postgres.storage.svc.cluster.local\n            - name: PGDATABASE\n              value: example\n            - name: PGUSER\n              valueFrom:\n                secretKeyRef:\n                  key: postgres.user\n                  name: postgres\n            - name: PGPASSWORD\n              valueFrom:\n                secretKeyRef:\n                  key: postgres.password\n                  name: postgres\n      restartPolicy: Never\n  backoffLimit: 0\n```\n\nYou can view the documentation for the `createdb` command [here](https://www.postgresql.org/docs/current/app-createdb.html).\n\n### Docker images\n\nThe cluster contains a deployment of the docker registry that is used as a pull-through proxy for any images hosted\non hub.docker.com. When referencing images stored in the main library, like `postgres` or `busybox`, you use the image\nreference `registry.homelab.dsb.dev/library`. Otherwise, you just use the repository/tag combination. This increases\nthe speed at which images are pulled and also helps with docker's recent change to add API request limits.\n\n## Environment\n\n* 4 [Raspberry Pi 4b](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/) (8GB RAM)\n* Kubernetes via [k3s](https://k3s.io/)\n* [Zebra Bramble Cluster Case](https://www.c4labs.com/product/zebra-bramble-case-raspberry-pi-3-b-color-and-stack-options/) from [C4 Labs](https://www.c4labs.com/)\n* 4 [SanDisk Ultra 32 GB microSDHC](https://www.amazon.co.uk/gp/product/B073JWXGNT) Memory Cards\n* 4 [SanDisk Ultra Fit 128 GB USB 3.1 Flash Drive](https://www.amazon.co.uk/gp/product/B07855LJ99) USB Drives\n* [Synology DS115j](https://www.amazon.co.uk/Synology-DS115j-1TB-Desktop-Unit/dp/B00O8LLQBY) NAS drive.\n\n![Cluster](img/cluster.jpg)\n\n![Diagram](img/diagram.jpg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidsbond%2Fhomelab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidsbond%2Fhomelab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidsbond%2Fhomelab/lists"}