Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Mafyuh/iac
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a989e47b8bf1c20762122893def6f8f7d6c3a969
Choose a base ref
..
head repository: Mafyuh/iac
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c08ae2e3348050b79d0b26590fc3280bbb9e80fb
Choose a head ref
Showing with 546 additions and 262 deletions.
  1. +8 −0 .github/renovate.json
  2. +63 −6 README.md
  3. +2 −2 docker/AI/docker-compose.yml
  4. +1 −1 docker/arrs/docker-compose.yml
  5. +1 −1 docker/jellyfin/docker-compose.yml
  6. +1 −1 docker/kasm/docker-compose.yml
  7. +7 −1 kubernetes/apps/production/arr/flaresolverr/deployment.yaml
  8. +111 −0 kubernetes/apps/production/arr/jellyseerr/helmrelease.yaml
  9. +4 −0 kubernetes/apps/production/arr/jellyseerr/kustomization.yaml
  10. +1 −0 kubernetes/apps/production/arr/kustomization.yaml
  11. +0 −53 kubernetes/apps/production/arr/prowlarr/deployment.yaml
  12. +124 −0 kubernetes/apps/production/arr/prowlarr/helmrelease.yaml
  13. +0 −22 kubernetes/apps/production/arr/prowlarr/ingress.yaml
  14. +1 −3 kubernetes/apps/production/arr/prowlarr/kustomization.yaml
  15. +0 −13 kubernetes/apps/production/arr/prowlarr/service.yaml
  16. +0 −99 kubernetes/apps/production/arr/qbitty/deployment.yaml
  17. +137 −0 kubernetes/apps/production/arr/qbitty/helmrelease.yaml
  18. +0 −22 kubernetes/apps/production/arr/qbitty/ingress.yaml
  19. +1 −3 kubernetes/apps/production/arr/qbitty/kustomization.yaml
  20. +0 −13 kubernetes/apps/production/arr/qbitty/service.yaml
  21. +15 −3 kubernetes/apps/production/arr/radarr/helmrelease.yaml
  22. +6 −1 kubernetes/apps/production/arr/recyclarr/helmrelease.yaml
  23. +26 −7 kubernetes/apps/production/arr/sabnzbd/helmrelease.yaml
  24. +10 −4 kubernetes/apps/production/arr/sonarr/helmrelease.yaml
  25. +3 −3 kubernetes/apps/production/authentik/configmap.yaml
  26. +18 −0 kubernetes/apps/production/cert-manager/certificates/public.yaml
  27. +1 −0 kubernetes/apps/production/cert-manager/issuers/letsencrypt.yaml
  28. +1 −0 kubernetes/apps/production/cert-manager/kustomization.yaml
  29. +4 −4 kubernetes/secrets/recyclarr.yaml
8 changes: 8 additions & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
@@ -37,6 +37,14 @@
"registryUrls": [
"https://emberstack.github.io/helm-charts"
]
},
{
"matchPackageNames": [
"app-template"
],
"registryUrls": [
"https://bjw-s.github.io/helm-charts"
]
}
],
"kubernetes": {
69 changes: 63 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -9,19 +9,76 @@

# iac (wip)

Currently migrating [Auto-Homelab](https://git.mafyuh.dev/mafyuh/Auto-Homelab), [Iac-Homelab](https://git.mafyuh.dev/mafyuh/IaC-Homelab), [ansible-playbooks](https://git.mafyuh.dev/mafyuh/ansible-playbooks) and [kub](https://git.mafyuh.dev/mafyuh/kub) repos into this one.
This is my homelab infrastructure, defined in code.

This is my homelab, defined in code.
</div>

---

<div align="center">

| Hypervisor | OS | Tools | VPS (arm) | Firewall | Misc. Automations |
|---|---|---|---|---|---|
| [![Proxmox](https://img.shields.io/badge/-Proxmox-%23c9d1d9?logo=Proxmox)](https://www.proxmox.com) | [![Ubuntu](https://img.shields.io/badge/Ubuntu_22.04-%23c9d1d9?&logo=ubuntu&logoColor=red)](https://releases.ubuntu.com/jammy/) [![Ubuntu](https://img.shields.io/badge/Ubuntu_24-%23c9d1d9?&logo=ubuntu&logoColor=red)](https://releases.ubuntu.com/noble/) | [![Forgejo](https://img.shields.io/badge/-Forgejo-%23c9d1d9?logo=forgejo&logoColor=orange)](https://forgejo.org/) [![Docker](https://img.shields.io/badge/-Docker-%23c9d1d9?logo=docker)](https://www.docker.com/) [![Renovate](https://img.shields.io/badge/-Renovate-%23c9d1d9?logo=renovate&logoColor=blue)](https://github.com/renovatebot/renovate) [![OpenTofu](https://img.shields.io/badge/-OpenTofu-%23c9d1d9?logo=opentofu&logoColor=black)](https://opentofu.org/) [![Packer](https://img.shields.io/badge/-Packer-%23c9d1d9?logo=packer)](https://www.packer.io/) [![Ansible](https://img.shields.io/badge/-Ansible-%23c9d1d9?logo=ansible&logoColor=red)](https://www.ansible.com/) | [![Oracle](https://img.shields.io/badge/-Oracle_Cloud-%23c9d1d9?logo=oracle&logoColor=red)](https://www.oracle.com/cloud/) | [![pfSense](https://img.shields.io/badge/-pfSense-%23c9d1d9?logo=pfsense&logoColor=blue)](https://www.pfsense.org/) | [![n8n](https://img.shields.io/badge/-n8n-%23c9d1d9?logo=n8n)](https://n8n.io/)
| Hypervisor | OS | Tools | Firewall | Misc. Automations |
|---|---|---|---|---|
| [![Proxmox](https://img.shields.io/badge/-Proxmox-%23c9d1d9?logo=Proxmox)](https://www.proxmox.com) | [![Debian](https://img.shields.io/badge/Debian-%23c9d1d9?&logo=debian&logoColor=black)](https://www.debian.org/) [![Ubuntu](https://img.shields.io/badge/Ubuntu-%23c9d1d9?&logo=ubuntu&logoColor=red)](https://releases.ubuntu.com/noble/) | [![Forgejo](https://img.shields.io/badge/-Forgejo-%23c9d1d9?logo=forgejo&logoColor=orange)](https://forgejo.org/) [![Docker](https://img.shields.io/badge/-Docker-%23c9d1d9?logo=docker)](https://www.docker.com/) [![Kubernetes](https://img.shields.io/badge/-Kubernetes-%23c9d1d9?logo=kubernetes)](https://k3s.io/) [![Renovate](https://img.shields.io/badge/-Renovate-%23c9d1d9?logo=renovate&logoColor=blue)](https://github.com/renovatebot/renovate) [![OpenTofu](https://img.shields.io/badge/-OpenTofu-%23c9d1d9?logo=opentofu)](https://opentofu.org/) [![Packer](https://img.shields.io/badge/-Packer-%23c9d1d9?logo=packer)](https://www.packer.io/) [![Ansible](https://img.shields.io/badge/-Ansible-%23c9d1d9?logo=ansible&logoColor=red)](https://www.ansible.com/) | [![pfSense](https://img.shields.io/badge/-pfSense-%23c9d1d9?logo=pfsense&logoColor=blue)](https://www.pfsense.org/) | [![n8n](https://img.shields.io/badge/-n8n-%23c9d1d9?logo=n8n)](https://n8n.io/) [![Actions](https://img.shields.io/badge/-Actions-%23c9d1d9?logo=forgejo&logoColor=orange)](https://forgejo.org/docs/latest/user/actions/)

</div>

## To-Do
## 📖 **Overview**
This repository contains the IaC ([Infrastructure as Code](https://en.wikipedia.org/wiki/Infrastructure_as_code)) configuration for my homelab.

Most of my homelab runs on **Proxmox**, with VMs managed and maintained using [OpenTofu](https://opentofu.org/). All VMs are cloned from templates I created with [Packer](https://www.packer.io/).

All services are **containerized**, either managed with **Docker Compose** or **orchestrated with Kubernetes ([K3s](https://k3s.io/))**. Over time, I’ve been migrating everything to Kubernetes using **[GitOps](https://en.wikipedia.org/wiki/DevOps) practices**, which is my long-term goal.

To automate infrastructure updates, I use **Forgejo Actions**, which trigger workflows upon changes to this repo. This ensures seamless deployment and maintenance across my homelab:

- **[Flux](https://fluxcd.io/)** manages Continuous Deployment (CD) for Kubernetes, bootstrapped via [OpenTofu](https://git.mafyuh.dev/mafyuh/iac/src/branch/main/terraform/flux/main.tf).
- **[Docker CD Workflow](https://git.mafyuh.dev/mafyuh/iac/src/branch/main/.forgejo/workflows/CD.yml)** handles Continuous Deployment for Docker services.
- **[Renovate](https://github.com/renovatebot/renovate)** keeps services updated by opening PRs for new versions.
- **[Yamllint](https://github.com/adrienverge/yamllint)** ensures configuration files are properly structured.
- **[Ansible](https://github.com/ansible/ansible)** is used to execute playbooks on all of my VMs, automating management and configurations

### 🔒 **Security & Networking**
For Secret management I use [Bitwarden Secrets](https://bitwarden.com/products/secrets-manager/) and their various [integrations](https://bitwarden.com/help/ansible-integration/) into the tools used.
> Kubernetes is using SOPS with Age encryption until migration over to Bitwarden Secrets.
I use **Oracle Cloud** for their [Always-Free](https://www.oracle.com/cloud/free/) VM's and deploy Docker services that require uptime here (Uptime Kuma, this website). [Twingate](https://www.twingate.com/) is used to connect my home network to the various VPS's securely using [Zero Trust architecture](https://en.wikipedia.org/wiki/Zero_trust_architecture).

I use **Cloudflare** for my DNS provider with **Cloudflare Tunnels** to expose some of the services to the world. **Cloudflare Access** is used to restrict the access to some of the services, this is paired with **Fail2Ban** looking through all my reverse proxy logs for malicious actors who made it through **Access** and banning them via **Cloudflare WAF**.

For my home network I use **PfSense** with VLAN segmentation and strict firewall rules to isolate public-facing machines, ensuring they can only communicate with the necessary services and nothing else.

### **📊 Monitoring & Observability**
I use a combination of **Grafana, Loki, and Prometheus** with various exporters to collect and visualize system metrics, logs, and alerts. This helps maintain visibility into my infrastructure and detect issues proactively.

- **Prometheus** – Metrics collection and alerting
- **Loki** – Centralized logging for containers and VMs
- **Grafana** – Dashboarding and visualization
- **Exporters** – Node Exporter, cAdvisor, Blackbox Exporter, etc.

## 🧑‍💻 **Getting Started**
This repo is not structured like a project you can easily replicate. Although if you are new to any of the tools used I encourage you to read through the directories that make up each tool to see how I am using them.

Over time I will try to add more detailed instructions in each directories README.

Some good references for how I learned this stuff (other than RTM)
- [Kubernetes Cluster Setup](https://technotim.live/posts/k3s-etcd-ansible/)
- [Kubernetes + Flux](https://technotim.live/posts/flux-devops-gitops/)
- [Kubernetes Secrets with SOPS](https://technotim.live/posts/secret-encryption-sops/)
- [Packer with Proxmox](https://www.youtube.com/watch?v=1nf3WOEFq1Y)
- [Terraform with Proxmox](https://www.youtube.com/watch?v=dvyeoDBUtsU)
- [Docker](https://www.youtube.com/watch?v=eGz9DS-aIeY)
- [Ansible](https://www.youtube.com/watch?v=goclfp6a2IQ)

## 🖥️ **Hardware**

| Name | Device | CPU | RAM | Storage | Purpose |
|------------|--------------|----------------|-------------|--------------------------------|--------------------------------|
| Arc-Ripper | Optiplex 3050 | Intel i5-6500 | 32 GB DDR4 | 1TB NVMe | Jellyfin Server, Blu-ray Ripper |
| PVE Node 1 | Custom | Intel i7-9700K | 64 GB DDR4 | NVMe for boot and VMs, 4x4TB HDD RaidZ10 | Main node with most VMs, NAS |
| PVE Node 2 | Custom | Intel i7-8700K | 64 GB DDR4 | 1x2TB NVMe | More VMs |


## 📌 **To-Do**
See [Project Board](https://git.mafyuh.dev/mafyuh/iac/projects/2)

4 changes: 2 additions & 2 deletions docker/AI/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
ollama:
image: ollama/ollama:0.5.10
image: ollama/ollama:0.5.11
container_name: ollama
restart: unless-stopped
networks:
@@ -39,7 +39,7 @@ services:
- host.docker.internal:host-gateway

searxng:
image: searxng/searxng@sha256:e22d8617effc484649d01fa80614b4859e134c6b77a5d2a2cff9236789aa1749
image: searxng/searxng@sha256:0da476ff64bf801e3b36fd3c79c50f30f7041ab78b27cbc8c189c4c6f8c696d6
container_name: searxng
networks:
- ai-stack
2 changes: 1 addition & 1 deletion docker/arrs/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -148,7 +148,7 @@ services:

## Should move this to Ubu
code-server:
image: ghcr.io/linuxserver/code-server@sha256:5c900277e10a8c2868d4db86d0870c94096c9e3140ec9480cb7c47726b9d059c
image: ghcr.io/linuxserver/code-server@sha256:95a811ff3262083bbbc2b14fc03d4b65271140be904a8e0cabc2e320233474a7
container_name: code-server
environment:
- PUID=1000
2 changes: 1 addition & 1 deletion docker/jellyfin/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
services:
jellyfin:
image: ghcr.io/linuxserver/jellyfin@sha256:7cdcd4b6b60765290af7a2740960ce30c1f5548313ae60f7e23f6995ed4d147e
image: ghcr.io/linuxserver/jellyfin@sha256:075bc77361e6466f5cd546c9d97646428cc1f26d4b355991e8f66d0ffbc7c15a
container_name: jellyfin
devices:
- /dev/dri/renderD129:/dev/dri/renderD129
2 changes: 1 addition & 1 deletion docker/kasm/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
services:
kasm:
image: ghcr.io/linuxserver/kasm@sha256:5ff0ef8bd7f279cb6806aae9caabe5457eaadd89fb0f02e63ce26dcdac747d10
image: ghcr.io/linuxserver/kasm@sha256:64da6db15ab574d67f9fbdcc812796f00f259be543e6dc2e60ad4f5d6c05d005
container_name: kasm
privileged: true
environment:
8 changes: 7 additions & 1 deletion kubernetes/apps/production/arr/flaresolverr/deployment.yaml
Original file line number Diff line number Diff line change
@@ -30,4 +30,10 @@ spec:
cpu: "100m"
limits:
memory: "300Mi"
cpu: "200m"
cpu: "200m"
dnsPolicy: None
dnsConfig:
nameservers:
- 10.43.0.10
- 1.1.1.1
- 8.8.8.8
111 changes: 111 additions & 0 deletions kubernetes/apps/production/arr/jellyseerr/helmrelease.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: &app jellyseerr
namespace: arr
spec:
interval: 15m
chart:
spec:
chart: app-template
version: 3.7.1
interval: 30m
sourceRef:
kind: HelmRepository
name: bjw-s
namespace: flux-system

install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3

values:
global:
fullnameOverride: *app
namespace: arr

controllers:
jellyseerr:
enabled: true
type: statefulset
annotations:
reloader.stakater.com/auto: "true"

replicas: 1

statefulset:
volumeClaimTemplates:
- name: jellyseerr-config
accessMode: ReadWriteOnce
size: 2Gi
storageClass: longhorn
globalMounts:
- path: /app/config

pod:
securityContext:
runAsUser: 1000
runAsGroup: &group 1000
fsGroup: *group
fsGroupChangePolicy: "OnRootMismatch"
dnsPolicy: None
dnsConfig:
nameservers:
- 10.43.0.10
- 1.1.1.1
- 8.8.8.8

containers:
app:
image:
repository: fallenbagel/jellyseerr
tag: 2.3.0
pullPolicy: IfNotPresent
env:
TZ: "${TZ}"
LOG_LEVEL: info

probes:
liveness:
enabled: false

securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL

resources:
requests:
cpu: 20m
memory: 128Mi
limits:
memory: 256Mi

service:
app:
primary: true
controller: jellyseerr
ports:
http:
port: 5055

ingress:
internal:
enabled: true
className: nginx
hosts:
- host: "request.${PUBLIC_DOMAIN}"
paths:
- path: /
pathType: Prefix
service:
identifier: app
port: http
tls:
- hosts:
- "request.${PUBLIC_DOMAIN}"
secretName: mafyuh-dev-production-tls
4 changes: 4 additions & 0 deletions kubernetes/apps/production/arr/jellyseerr/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- helmrelease.yaml
1 change: 1 addition & 0 deletions kubernetes/apps/production/arr/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ resources:
- bazarr/
- flaresolverr/
- prowlarr/
- jellyseerr/
- qbitty/
- radarr/
- recyclarr/
53 changes: 0 additions & 53 deletions kubernetes/apps/production/arr/prowlarr/deployment.yaml

This file was deleted.

Loading