├── .gitignore
├── talos
├── patches
│ ├── allow-controlplane-workloads.yaml
│ ├── interface-names.yaml
│ ├── dhcp.yaml
│ ├── etcd-metrics.yaml
│ ├── vip.yaml
│ ├── kubelet-certificates.yaml
│ ├── nfs-config.yaml
│ ├── local-path-provisioner-mount.yaml
│ └── allow-controlplane-metallb.yaml
├── image-schematic.yaml
└── talos.secret.sops.yaml
├── kubernetes
├── homepage
│ ├── config
│ │ ├── kubernetes.yaml
│ │ ├── settings.yaml
│ │ ├── widgets.yaml
│ │ ├── bookmarks.yaml
│ │ └── services.yaml
│ ├── ns.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── kustomization.yaml
│ ├── serviceaccount.yaml
│ ├── clusterrole.yaml
│ ├── deployment.yaml
│ └── homepage.secret.sops.yaml
├── common
│ ├── kustomization.yaml
│ └── repos
│ │ ├── kustomization.yaml
│ │ └── app-template.yaml
├── traefik
│ ├── ns.yaml
│ ├── repo.yaml
│ ├── kustomization.yaml
│ ├── dashboard-ingress.yaml
│ ├── middlewares.yaml
│ ├── release.yaml
│ ├── tinyauth.secret.sops.yaml
│ ├── tinyauth.yaml
│ └── external-ingress.yaml
├── volsync
│ ├── ns.yaml
│ ├── kustomization.yaml
│ ├── repo.yaml
│ └── release.yaml
├── cert-manager
│ ├── ns.yaml
│ ├── certificates
│ │ ├── kustomization.yaml
│ │ ├── production
│ │ │ └── axis.yaml
│ │ └── staging
│ │ │ └── axis.yaml
│ ├── kustomization.yaml
│ ├── issuers
│ │ ├── kustomization.yaml
│ │ ├── letsencrypt-production.yaml
│ │ ├── letsencrypt-staging.yaml
│ │ └── cloudflare-issuer.secret.sops.yaml
│ ├── repo.yaml
│ └── release.yaml
├── flux-system
│ ├── kustomization.yaml
│ └── gotk-sync.yaml
├── actual
│ ├── backup
│ │ ├── kustomization.yaml
│ │ ├── backup.yaml
│ │ └── backblaze.secret.sops.yaml
│ ├── akahu-actual
│ │ ├── kustomization.yaml
│ │ ├── release.yaml
│ │ └── akahu-actual.secret.sops.yaml
│ ├── kustomization.yaml
│ ├── ns.yaml
│ ├── pvc.yaml
│ ├── ingress.yaml
│ └── release.yaml
├── gitea
│ ├── backup
│ │ ├── kustomization.yaml
│ │ ├── backup.yaml
│ │ └── backblaze.secret.sops.yaml
│ ├── ns.yaml
│ ├── repo.yaml
│ ├── pvc.yaml
│ ├── mirror-pvc.yaml
│ ├── kustomization.yaml
│ ├── ingress.yaml
│ ├── mirror-ingress.yaml
│ ├── mirror.secret.sops.yaml
│ ├── release.yaml
│ ├── gitea.secret.sops.yaml
│ └── mirror-release.yaml
├── kube-system
│ ├── metrics-server
│ │ ├── kustomization.yaml
│ │ ├── repo.yaml
│ │ └── release.yaml
│ └── snapshot-controller
│ │ ├── kustomization.yaml
│ │ ├── repo.yaml
│ │ └── release.yaml
├── storage
│ ├── local-path-provisioner
│ │ ├── kustomization.yaml
│ │ ├── repo.yaml
│ │ └── release.yaml
│ ├── democratic-csi
│ │ ├── kustomization.yaml
│ │ ├── repo.yaml
│ │ └── iscsi.secret.sops.yaml
│ ├── kustomization.yaml
│ └── ns.yaml
├── ccinvoice
│ ├── backup
│ │ ├── kustomization.yaml
│ │ ├── backup.yaml
│ │ └── backblaze.secret.sops.yaml
│ ├── kustomization.yaml
│ ├── ns.yaml
│ ├── pvc.yaml
│ ├── ingress.yaml
│ ├── release.yaml
│ └── ccinvoice.secret.sops.yaml
├── media
│ ├── radarr
│ │ ├── backup
│ │ │ ├── kustomization.yaml
│ │ │ ├── backup.yaml
│ │ │ └── backblaze.secret.sops.yaml
│ │ ├── kustomization.yaml
│ │ ├── ingress.yaml
│ │ ├── pvc.yaml
│ │ └── release.yaml
│ ├── sonarr
│ │ ├── backup
│ │ │ ├── kustomization.yaml
│ │ │ ├── backup.yaml
│ │ │ └── backblaze.secret.sops.yaml
│ │ ├── kustomization.yaml
│ │ ├── ingress.yaml
│ │ ├── pvc.yaml
│ │ └── release.yaml
│ ├── prowlarr
│ │ ├── backup
│ │ │ ├── kustomization.yaml
│ │ │ ├── backup.yaml
│ │ │ └── backblaze.secret.sops.yaml
│ │ ├── kustomization.yaml
│ │ ├── pvc.yaml
│ │ ├── ingress.yaml
│ │ └── release.yaml
│ ├── qbittorrent
│ │ ├── kustomization.yaml
│ │ ├── pvc.yaml
│ │ ├── ingress.yaml
│ │ └── release.yaml
│ ├── kustomization.yaml
│ ├── ns.yaml
│ └── recyclarr
│ │ ├── kustomization.yaml
│ │ ├── recyclarr.secret.sops.yaml
│ │ ├── config
│ │ └── recyclarr.yml
│ │ └── release.yaml
├── home-assistant
│ ├── backup
│ │ ├── kustomization.yaml
│ │ ├── backup.yaml
│ │ └── backblaze.secret.sops.yaml
│ ├── kustomization.yaml
│ ├── ns.yaml
│ ├── pvc.yaml
│ ├── ingress.yaml
│ └── release.yaml
├── monitoring
│ ├── loki
│ │ ├── kustomization.yaml
│ │ ├── repo.yaml
│ │ ├── promtail.yaml
│ │ └── release.yaml
│ ├── kube-prometheus-stack
│ │ ├── kustomization.yaml
│ │ ├── repo.yaml
│ │ ├── alertmanagerconfig.yaml
│ │ ├── ingress.yaml
│ │ ├── alertmanager.secret.sops.yaml
│ │ └── release.yaml
│ ├── kustomization.yaml
│ ├── ns.yaml
│ └── grafana
│ │ ├── kustomization.yaml
│ │ ├── repo.yaml
│ │ ├── ingress.yaml
│ │ ├── admin.secret.sops.yaml
│ │ └── release.yaml
└── metallb-system
│ ├── kustomization.yaml
│ ├── ns.yaml
│ ├── repo.yaml
│ ├── addresspool.yaml
│ └── release.yaml
├── .github
├── CODEOWNERS
└── workflows
│ └── ci.yaml
├── .editorconfig
├── taskfile.yaml
├── .taskfiles
├── sops.yaml
├── volsync.yaml
└── talos.yaml
├── .gitattributes
├── .sops.yaml
├── LICENSE
├── scripts
├── sops.sh
├── pick-backup.sh
└── restore.sh
├── README.md
└── .renovaterc.json5
/.gitignore:
--------------------------------------------------------------------------------
1 | *.secret.yaml
2 | talos/rendered/*
3 |
--------------------------------------------------------------------------------
/talos/patches/allow-controlplane-workloads.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | cluster:
3 | allowSchedulingOnControlPlanes: true
4 |
--------------------------------------------------------------------------------
/talos/patches/interface-names.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | machine:
3 | install:
4 | extraKernelArgs:
5 | - net.ifnames=0
6 |
--------------------------------------------------------------------------------
/talos/patches/dhcp.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | machine:
3 | network:
4 | interfaces:
5 | - interface: eth0
6 | dhcp: true
7 |
--------------------------------------------------------------------------------
/talos/patches/etcd-metrics.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | cluster:
3 | etcd:
4 | extraArgs:
5 | listen-metrics-urls: http://0.0.0.0:2381
6 |
--------------------------------------------------------------------------------
/kubernetes/homepage/config/kubernetes.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # https://gethomepage.dev/configs/kubernetes/
3 | mode: cluster
4 | ingress: traefik
5 |
--------------------------------------------------------------------------------
/talos/patches/vip.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | machine:
3 | network:
4 | interfaces:
5 | - interface: eth0
6 | vip:
7 | ip: 10.0.10.10
8 |
--------------------------------------------------------------------------------
/talos/image-schematic.yaml:
--------------------------------------------------------------------------------
1 | customization:
2 | systemExtensions:
3 | officialExtensions:
4 | - siderolabs/qemu-guest-agent
5 | - siderolabs/iscsi-tools
6 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
2 | * @scottmckendry
3 |
--------------------------------------------------------------------------------
/kubernetes/homepage/config/settings.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # https://gethomepage.dev/configs/settings/
3 | title: AXIS
4 | theme: dark
5 | color: stone
6 | hideVersion: true
7 | disableUpdateCheck: true
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | indest_style = space
3 | indent_size = 2
4 | end_of_line = lf
5 | charset = utf-8
6 | trim_trailing_whitespace = true
7 | insert_final_newline = true
8 |
9 | [*.sh]
10 | indent_size = 4
11 |
--------------------------------------------------------------------------------
/kubernetes/common/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - repos
7 |
--------------------------------------------------------------------------------
/taskfile.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://taskfile.dev/schema.json
3 | version: 3
4 |
5 | includes:
6 | talos: .taskfiles/talos.yaml
7 | sops: .taskfiles/sops.yaml
8 | volsync: .taskfiles/volsync.yaml
9 |
--------------------------------------------------------------------------------
/kubernetes/homepage/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: homepage
7 |
--------------------------------------------------------------------------------
/kubernetes/traefik/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: traefik
7 |
--------------------------------------------------------------------------------
/kubernetes/volsync/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: volsync
7 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: cert-manager
7 |
--------------------------------------------------------------------------------
/kubernetes/common/repos/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - app-template.yaml
7 |
--------------------------------------------------------------------------------
/kubernetes/flux-system/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - gotk-components.yaml
7 | - gotk-sync.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/volsync/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - ns.yaml
7 | - release.yaml
8 | - repo.yaml
9 |
--------------------------------------------------------------------------------
/kubernetes/actual/backup/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - backup.yaml
7 | - backblaze.secret.sops.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/gitea/backup/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - backup.yaml
7 | - backblaze.secret.sops.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/kube-system/metrics-server/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - release.yaml
7 | - repo.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/storage/local-path-provisioner/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - release.yaml
7 | - repo.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/actual/akahu-actual/kustomization.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | resources:
5 | - release.yaml
6 | - akahu-actual.secret.sops.yaml
7 |
--------------------------------------------------------------------------------
/kubernetes/ccinvoice/backup/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - backup.yaml
7 | - backblaze.secret.sops.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/kube-system/snapshot-controller/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - repo.yaml
7 | - release.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/media/radarr/backup/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - backup.yaml
7 | - backblaze.secret.sops.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/media/sonarr/backup/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - backup.yaml
7 | - backblaze.secret.sops.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/storage/democratic-csi/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - iscsi.secret.sops.yaml
7 | - repo.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/home-assistant/backup/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - backup.yaml
7 | - backblaze.secret.sops.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/media/prowlarr/backup/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - backup.yaml
7 | - backblaze.secret.sops.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/media/qbittorrent/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - release.yaml
7 | - ingress.yaml
8 | - pvc.yaml
9 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/loki/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - promtail.yaml
7 | - release.yaml
8 | - repo.yaml
9 |
--------------------------------------------------------------------------------
/kubernetes/storage/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - ns.yaml
7 | - local-path-provisioner
8 | - democratic-csi
9 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/certificates/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - staging/axis.yaml
7 | - production/axis.yaml
8 |
--------------------------------------------------------------------------------
/kubernetes/gitea/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: gitea
7 | annotations:
8 | volsync.backube/priveleged-movers: "true"
9 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/kube-prometheus-stack/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - release.yaml
7 | - repo.yaml
8 | - ingress.yaml
9 |
--------------------------------------------------------------------------------
/kubernetes/media/prowlarr/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - release.yaml
7 | - ingress.yaml
8 | - pvc.yaml
9 | - backup
10 |
--------------------------------------------------------------------------------
/kubernetes/media/radarr/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - release.yaml
7 | - ingress.yaml
8 | - pvc.yaml
9 | - backup
10 |
--------------------------------------------------------------------------------
/kubernetes/media/sonarr/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - release.yaml
7 | - ingress.yaml
8 | - pvc.yaml
9 | - backup
10 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - ns.yaml
7 | - kube-prometheus-stack
8 | - grafana
9 | - loki
10 |
--------------------------------------------------------------------------------
/kubernetes/storage/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: storage
7 | labels:
8 | pod-security.kubernetes.io/enforce: privileged
9 |
--------------------------------------------------------------------------------
/talos/patches/kubelet-certificates.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | machine:
3 | kubelet:
4 | extraArgs:
5 | rotate-server-certificates: true
6 |
7 | cluster:
8 | extraManifests:
9 | - https://raw.githubusercontent.com/alex1989hu/kubelet-serving-cert-approver/main/deploy/standalone-install.yaml
10 |
--------------------------------------------------------------------------------
/kubernetes/metallb-system/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - ns.yaml
7 | - release.yaml
8 | - repo.yaml
9 | - addresspool.yaml
10 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: monitoring
7 | labels:
8 | pod-security.kubernetes.io/enforce: privileged
9 |
--------------------------------------------------------------------------------
/kubernetes/home-assistant/kustomization.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | resources:
5 | - ns.yaml
6 | - pvc.yaml
7 | - release.yaml
8 | - ingress.yaml
9 | - backup
10 |
--------------------------------------------------------------------------------
/kubernetes/home-assistant/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: home-assistant
7 | annotations:
8 | volsync.backube/priveleged-movers: "true"
9 |
--------------------------------------------------------------------------------
/kubernetes/metallb-system/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: metallb-system
7 | labels:
8 | pod-security.kubernetes.io/enforce: privileged
9 |
--------------------------------------------------------------------------------
/talos/patches/nfs-config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | machine:
3 | files:
4 | - op: overwrite
5 | path: /etc/nfsmount.conf
6 | permissions: 0o644
7 | content: |
8 | [ NFSMount_Global_Options ]
9 | nfsvers=4.2
10 | hard=True
11 | nconnect=16
12 | noatime=True
13 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - ns.yaml
7 | - release.yaml
8 | - repo.yaml
9 | - issuers
10 | - certificates
11 |
--------------------------------------------------------------------------------
/kubernetes/media/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - ns.yaml
7 | - prowlarr
8 | - qbittorrent
9 | - radarr
10 | - recyclarr
11 | - sonarr
12 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/grafana/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - release.yaml
7 | - repo.yaml
8 | - ingress.yaml
9 | - admin.secret.sops.yaml
10 |
--------------------------------------------------------------------------------
/talos/patches/local-path-provisioner-mount.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | machine:
3 | kubelet:
4 | extraMounts:
5 | - destination: /var/local-path-provisioner
6 | type: bind
7 | source: /var/local-path-provisioner
8 | options:
9 | - bind
10 | - rshared
11 | - rw
12 |
--------------------------------------------------------------------------------
/kubernetes/actual/kustomization.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | resources:
5 | - ns.yaml
6 | - pvc.yaml
7 | - release.yaml
8 | - ingress.yaml
9 | - backup
10 | - akahu-actual
11 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/issuers/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - cloudflare-issuer.secret.sops.yaml
7 | - letsencrypt-staging.yaml
8 | - letsencrypt-production.yaml
9 |
--------------------------------------------------------------------------------
/kubernetes/ccinvoice/kustomization.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | resources:
5 | - ns.yaml
6 | - pvc.yaml
7 | - release.yaml
8 | - ingress.yaml
9 | - ccinvoice.secret.sops.yaml
10 | - backup
11 |
--------------------------------------------------------------------------------
/kubernetes/gitea/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: HelmRepository
5 | metadata:
6 | name: gitea
7 | namespace: gitea
8 | spec:
9 | url: https://dl.gitea.io/charts
10 | interval: 1h
11 |
--------------------------------------------------------------------------------
/kubernetes/actual/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: actual
7 | annotations:
8 | volsync.backube/priveleged-movers: "true" # required for setting file permissions during a backup restore
9 |
--------------------------------------------------------------------------------
/kubernetes/media/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: media
7 | annotations:
8 | volsync.backube/priveleged-movers: "true" # required for setting file permissions during a backup restore
9 |
--------------------------------------------------------------------------------
/kubernetes/traefik/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: HelmRepository
5 | metadata:
6 | name: traefik
7 | namespace: traefik
8 | spec:
9 | url: https://helm.traefik.io/traefik
10 | interval: 1h
11 |
--------------------------------------------------------------------------------
/kubernetes/ccinvoice/ns.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/namespace.json
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: ccinvoice
7 | annotations:
8 | volsync.backube/priveleged-movers: "true" # required for setting file permissions during a backup restore
9 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: HelmRepository
5 | metadata:
6 | name: cert-manager
7 | namespace: cert-manager
8 | spec:
9 | url: https://charts.jetstack.io
10 | interval: 1h
11 |
--------------------------------------------------------------------------------
/kubernetes/volsync/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: HelmRepository
5 | metadata:
6 | name: backube
7 | namespace: volsync
8 | spec:
9 | url: https://backube.github.io/helm-charts
10 | interval: 1h
11 |
--------------------------------------------------------------------------------
/.taskfiles/sops.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://taskfile.dev/schema.json
3 | version: 3
4 |
5 | tasks:
6 | encrypt:
7 | desc: Encrypt all secret files with SOPS
8 | cmds:
9 | - ./scripts/sops.sh encrypt
10 |
11 | decrypt:
12 | desc: Decrypt all secret files with SOPS
13 | cmds:
14 | - ./scripts/sops.sh decrypt
15 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/loki/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: HelmRepository
5 | metadata:
6 | name: loki
7 | namespace: monitoring
8 | spec:
9 | url: https://grafana.github.io/helm-charts
10 | interval: 1h
11 |
--------------------------------------------------------------------------------
/kubernetes/metallb-system/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: HelmRepository
5 | metadata:
6 | name: metallb
7 | namespace: metallb-system
8 | spec:
9 | url: https://metallb.github.io/metallb
10 | interval: 1h
11 |
--------------------------------------------------------------------------------
/kubernetes/metallb-system/addresspool.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: metallb.io/v1beta1
3 | kind: IPAddressPool
4 | metadata:
5 | name: default-pool
6 | namespace: metallb-system
7 | spec:
8 | addresses:
9 | - 10.0.10.1-10.0.10.9
10 | ---
11 | apiVersion: metallb.io/v1beta1
12 | kind: L2Advertisement
13 | metadata:
14 | name: default-pool
15 | namespace: metallb-system
16 |
--------------------------------------------------------------------------------
/kubernetes/storage/democratic-csi/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: HelmRepository
5 | metadata:
6 | name: democratic-csi
7 | namespace: storage
8 | spec:
9 | url: https://democratic-csi.github.io/charts/
10 | interval: 1h
11 |
--------------------------------------------------------------------------------
/kubernetes/actual/pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
3 | apiVersion: v1
4 | kind: PersistentVolumeClaim
5 | metadata:
6 | name: actual
7 | namespace: actual
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 2Gi
14 |
--------------------------------------------------------------------------------
/kubernetes/gitea/pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
3 | apiVersion: v1
4 | kind: PersistentVolumeClaim
5 | metadata:
6 | name: gitea-data
7 | namespace: gitea
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 20Gi
14 |
--------------------------------------------------------------------------------
/kubernetes/ccinvoice/pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
3 | apiVersion: v1
4 | kind: PersistentVolumeClaim
5 | metadata:
6 | name: ccinvoice
7 | namespace: ccinvoice
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 1Gi
14 |
--------------------------------------------------------------------------------
/kubernetes/media/prowlarr/pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
3 | apiVersion: v1
4 | kind: PersistentVolumeClaim
5 | metadata:
6 | name: prowlarr
7 | namespace: media
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 1Gi
14 |
--------------------------------------------------------------------------------
/talos/patches/allow-controlplane-metallb.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # removes the following from node labels
3 | # node.kubernetes.io/exclude-from-external-load-balancers: ""
4 |
5 | # TODO: **Work out why I can't target the propety directly**
6 | # Targeting the property directly does not work when gerenating the configuration from
7 | # this patch.
8 |
9 | machine:
10 | nodeLabels:
11 | $patch: delete
12 |
--------------------------------------------------------------------------------
/kubernetes/gitea/mirror-pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
3 | apiVersion: v1
4 | kind: PersistentVolumeClaim
5 | metadata:
6 | name: gitea-mirror-data
7 | namespace: gitea
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 5Gi
14 |
--------------------------------------------------------------------------------
/kubernetes/kube-system/metrics-server/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: HelmRepository
5 | metadata:
6 | namespace: kube-system
7 | name: metrics-server
8 | spec:
9 | url: https://kubernetes-sigs.github.io/metrics-server/
10 | interval: 24h
11 |
--------------------------------------------------------------------------------
/kubernetes/media/qbittorrent/pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
3 | apiVersion: v1
4 | kind: PersistentVolumeClaim
5 | metadata:
6 | name: qbittorrent
7 | namespace: media
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 1Gi
14 |
--------------------------------------------------------------------------------
/kubernetes/traefik/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - ns.yaml
7 | - release.yaml
8 | - repo.yaml
9 | - dashboard-ingress.yaml
10 | - middlewares.yaml
11 | - tinyauth.yaml
12 | - tinyauth.secret.sops.yaml
13 | - external-ingress.yaml
14 |
--------------------------------------------------------------------------------
/kubernetes/homepage/config/widgets.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # https://gethomepage.dev/configs/info-widgets/
3 | - kubernetes:
4 | cluster:
5 | show: false
6 | cpu: true
7 | memory: true
8 | showLabel: true
9 | label: "cluster"
10 | nodes:
11 | show: true
12 | cpu: true
13 | memory: true
14 | showLabel: true
15 | - search:
16 | provider: brave
17 | target: _blank
18 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | push:
4 | pull_request:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | release:
10 | runs-on: ubuntu-latest
11 | if: github.ref == 'refs/heads/main'
12 | steps:
13 | - uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4
14 | with:
15 | token: ${{ secrets.GITHUB_TOKEN }}
16 | release-type: simple
17 |
--------------------------------------------------------------------------------
/kubernetes/gitea/kustomization.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | resources:
5 | - ns.yaml
6 | - pvc.yaml
7 | - gitea.secret.sops.yaml
8 | - repo.yaml
9 | - release.yaml
10 | - ingress.yaml
11 | - backup
12 | - mirror-release.yaml
13 | - mirror-pvc.yaml
14 | - mirror.secret.sops.yaml
15 | - mirror-ingress.yaml
16 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 | *.env linguist-detectable linguist-language=SHELL
3 | *.json linguist-detectable linguist-language=JSON
4 | *.json5 linguist-detectable linguist-language=JSON5
5 | *.md linguist-detectable linguist-language=MARKDOWN
6 | *.sh linguist-detectable linguist-language=SHELL
7 | *.toml linguist-detectable linguist-language=TOML
8 | *.yml linguist-detectable linguist-language=YAML
9 | *.yaml linguist-detectable linguist-language=YAML
10 |
--------------------------------------------------------------------------------
/kubernetes/media/recyclarr/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - ./recyclarr.secret.sops.yaml
7 | - ./release.yaml
8 | configMapGenerator:
9 | - name: recyclarr-configmap
10 | namespace: media
11 | files:
12 | - recyclarr.yml=./config/recyclarr.yml
13 | generatorOptions:
14 | disableNameSuffixHash: true
15 |
--------------------------------------------------------------------------------
/.sops.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | creation_rules:
3 | - path_regex: "kubernetes/.*?(secret|sops).ya?ml$"
4 | encrypted_regex: "^(data|stringData|email|host|apiKey)$"
5 | age: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
6 |
7 | - path_regex: "talos/.*?(secret|sops).ya?ml$"
8 | encrypted_regex: "^.*(id|key|secret|password|token|passphrase|ca|crt|pem).*$"
9 | age: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
10 |
11 | stores:
12 | yaml:
13 | indent: 2
14 |
--------------------------------------------------------------------------------
/kubernetes/metallb-system/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | namespace: metallb-system
7 | name: metallb
8 | spec:
9 | chart:
10 | spec:
11 | chart: metallb
12 | version: 0.15.3
13 | sourceRef:
14 | kind: HelmRepository
15 | name: metallb
16 | interval: 1h
17 | timeout: 10m
18 |
--------------------------------------------------------------------------------
/kubernetes/homepage/service.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/service.json
3 | apiVersion: v1
4 | kind: Service
5 | metadata:
6 | name: homepage
7 | namespace: homepage
8 | labels:
9 | app.kubernetes.io/name: homepage
10 | spec:
11 | type: ClusterIP
12 | ports:
13 | - port: 3000
14 | targetPort: http
15 | protocol: TCP
16 | name: http
17 | selector:
18 | app.kubernetes.io/name: homepage
19 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/grafana/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: OCIRepository
5 | metadata:
6 | name: grafana
7 | namespace: monitoring
8 | spec:
9 | interval: 5m
10 | layerSelector:
11 | mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
12 | operation: copy
13 | ref:
14 | tag: 10.4.0
15 | url: oci://ghcr.io/grafana/helm-charts/grafana
16 |
--------------------------------------------------------------------------------
/kubernetes/actual/backup/backup.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/replicationsource_v1alpha1.json
3 | apiVersion: volsync.backube/v1alpha1
4 | kind: ReplicationSource
5 | metadata:
6 | name: actual-actual
7 | namespace: actual
8 | spec:
9 | sourcePVC: actual
10 | trigger:
11 | schedule: "0 13 * * *"
12 | restic:
13 | pruneIntervalDays: 14
14 | repository: restic-actual-actual
15 | retain:
16 | daily: 7
17 | weekly: 4
18 | monthly: 2
19 | copyMethod: Direct
20 |
--------------------------------------------------------------------------------
/kubernetes/kube-system/snapshot-controller/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: OCIRepository
5 | metadata:
6 | name: snapshot-controller
7 | namespace: kube-system
8 | spec:
9 | interval: 5m
10 | layerSelector:
11 | mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
12 | operation: copy
13 | ref:
14 | tag: 4.2.0
15 | url: oci://ghcr.io/piraeusdatastore/helm-charts/snapshot-controller
16 |
--------------------------------------------------------------------------------
/kubernetes/actual/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: actual
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`budget.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | services:
16 | - name: actual
17 | namespace: actual
18 | port: 5006
19 | tls:
20 | secretName: axis-tls
21 |
--------------------------------------------------------------------------------
/kubernetes/gitea/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: gitea-web
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`git.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | services:
16 | - name: gitea-http
17 | namespace: gitea
18 | port: 3000
19 | tls:
20 | secretName: axis-tls
21 |
--------------------------------------------------------------------------------
/kubernetes/kube-system/metrics-server/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | namespace: kube-system
7 | name: metrics-server
8 | spec:
9 | chart:
10 | spec:
11 | sourceRef:
12 | kind: HelmRepository
13 | name: metrics-server
14 | chart: metrics-server
15 | version: 3.13.0
16 | interval: 1h
17 | values:
18 | args:
19 | - --kubelet-insecure-tls
20 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/kube-prometheus-stack/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: OCIRepository
5 | metadata:
6 | name: kube-prometheus-stack
7 | namespace: monitoring
8 | spec:
9 | interval: 5m
10 | layerSelector:
11 | mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
12 | operation: copy
13 | ref:
14 | tag: 79.12.0
15 | url: oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack
16 |
--------------------------------------------------------------------------------
/kubernetes/storage/local-path-provisioner/repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/gitrepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: GitRepository
5 | metadata:
6 | namespace: storage
7 | name: local-path-provisioner
8 | spec:
9 | interval: 24h
10 | url: https://github.com/rancher/local-path-provisioner
11 | ref:
12 | tag: v0.0.32
13 | ignore: |
14 | # exclude all
15 | /*
16 | # include charts directory
17 | !/deploy/chart/local-path-provisioner/
18 |
--------------------------------------------------------------------------------
/kubernetes/traefik/dashboard-ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: traefik-dashboard
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`traefik.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | services:
16 | - name: api@internal
17 | kind: TraefikService
18 | tls:
19 | secretName: axis-tls
20 |
--------------------------------------------------------------------------------
/kubernetes/ccinvoice/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: ccinvoice
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`invoices.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | services:
16 | - name: ccinvoice
17 | namespace: ccinvoice
18 | port: 3000
19 | tls:
20 | secretName: axis-tls
21 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/grafana/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: grafana
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`grafana.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | services:
16 | - name: grafana
17 | namespace: monitoring
18 | port: 80
19 | tls:
20 | secretName: axis-tls
21 |
--------------------------------------------------------------------------------
/kubernetes/gitea/mirror-ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: gitea-mirror-web
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`gitea-mirror.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | services:
16 | - name: gitea-mirror
17 | namespace: gitea
18 | port: 4321
19 | tls:
20 | secretName: axis-tls
21 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/certificates/production/axis.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/certificate_v1.json
3 | apiVersion: cert-manager.io/v1
4 | kind: Certificate
5 | metadata:
6 | name: axis
7 | namespace: traefik # needs to be in the same namespace as the ingressroutes & middlewares
8 | spec:
9 | secretName: axis-tls
10 | issuerRef:
11 | name: letsencrypt-production
12 | kind: ClusterIssuer
13 | commonName: "*.axis.scottmckendry.tech"
14 | dnsNames:
15 | - "axis.scottmckendry.tech"
16 | - "*.axis.scottmckendry.tech"
17 |
--------------------------------------------------------------------------------
/kubernetes/common/repos/app-template.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json
3 | # https://github.com/bjw-s-labs/helm-charts/blob/main/charts/library/common/values.yaml
4 | apiVersion: source.toolkit.fluxcd.io/v1
5 | kind: OCIRepository
6 | metadata:
7 | name: app-template
8 | namespace: flux-system
9 | spec:
10 | interval: 5m
11 | layerSelector:
12 | mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
13 | operation: copy
14 | ref:
15 | tag: 3.7.3
16 | url: oci://ghcr.io/bjw-s/helm/app-template
17 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/certificates/staging/axis.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/certificate_v1.json
3 | apiVersion: cert-manager.io/v1
4 | kind: Certificate
5 | metadata:
6 | name: axis-staging
7 | namespace: traefik # needs to be in the same namespace as the ingressroutes & middlewares
8 | spec:
9 | secretName: axis-staging-tls
10 | issuerRef:
11 | name: letsencrypt-staging
12 | kind: ClusterIssuer
13 | commonName: "*.axis.scottmckendry.tech"
14 | dnsNames:
15 | - "axis.scottmckendry.tech"
16 | - "*.axis.scottmckendry.tech"
17 |
--------------------------------------------------------------------------------
/kubernetes/homepage/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: homepage
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | - name: forwardauth
16 | namespace: traefik
17 | services:
18 | - name: homepage
19 | namespace: homepage
20 | port: 3000
21 | tls:
22 | secretName: axis-tls
23 |
--------------------------------------------------------------------------------
/kubernetes/media/radarr/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: radarr
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`radarr.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | - name: forwardauth
16 | namespace: traefik
17 | services:
18 | - name: radarr
19 | namespace: media
20 | port: 80
21 | tls:
22 | secretName: axis-tls
23 |
--------------------------------------------------------------------------------
/kubernetes/media/sonarr/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: sonarr
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`sonarr.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | - name: forwardauth
16 | namespace: traefik
17 | services:
18 | - name: sonarr
19 | namespace: media
20 | port: 80
21 | tls:
22 | secretName: axis-tls
23 |
--------------------------------------------------------------------------------
/kubernetes/homepage/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/kustomization.json
3 | apiVersion: kustomize.config.k8s.io/v1beta1
4 | kind: Kustomization
5 | resources:
6 | - ns.yaml
7 | - clusterrole.yaml
8 | - serviceaccount.yaml
9 | - deployment.yaml
10 | - service.yaml
11 | - ingress.yaml
12 | - homepage.secret.sops.yaml
13 | configMapGenerator:
14 | - name: homepage
15 | namespace: homepage
16 | files:
17 | - config/kubernetes.yaml
18 | - config/settings.yaml
19 | - config/bookmarks.yaml
20 | - config/services.yaml
21 | - config/widgets.yaml
22 |
--------------------------------------------------------------------------------
/kubernetes/media/prowlarr/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: prowlarr
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`prowlarr.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | - name: forwardauth
16 | namespace: traefik
17 | services:
18 | - name: prowlarr-app
19 | namespace: media
20 | port: 80
21 | tls:
22 | secretName: axis-tls
23 |
--------------------------------------------------------------------------------
/kubernetes/media/qbittorrent/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: qbittorrent
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`qbt.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | - name: forwardauth
16 | namespace: traefik
17 | services:
18 | - name: qbittorrent
19 | namespace: media
20 | port: 80
21 | tls:
22 | secretName: axis-tls
23 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/issuers/letsencrypt-production.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/clusterissuer_v1.json
3 | apiVersion: cert-manager.io/v1
4 | kind: ClusterIssuer
5 | metadata:
6 | name: letsencrypt-production
7 | namespace: cert-manager
8 | spec:
9 | acme:
10 | server: https://acme-v02.api.letsencrypt.org/directory
11 | privateKeySecretRef:
12 | name: letsencrypt-production
13 | solvers:
14 | - dns01:
15 | cloudflare:
16 | apiTokenSecretRef:
17 | name: cloudflare-issuer-secret
18 | key: CLOUDFLARE_DNS_TOKEN
19 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/issuers/letsencrypt-staging.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/clusterissuer_v1.json
3 | apiVersion: cert-manager.io/v1
4 | kind: ClusterIssuer
5 | metadata:
6 | name: letsencrypt-staging
7 | namespace: cert-manager
8 | spec:
9 | acme:
10 | server: https://acme-staging-v02.api.letsencrypt.org/directory
11 | privateKeySecretRef:
12 | name: letsencrypt-staging
13 | solvers:
14 | - dns01:
15 | cloudflare:
16 | apiTokenSecretRef:
17 | name: cloudflare-issuer-secret
18 | key: CLOUDFLARE_DNS_TOKEN
19 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/loki/promtail.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: promtail
7 | namespace: monitoring
8 | spec:
9 | chart:
10 | spec:
11 | chart: promtail
12 | version: 6.17.1
13 | sourceRef:
14 | kind: HelmRepository
15 | name: loki
16 | interval: 1h
17 | timeout: 10m
18 | values:
19 | config:
20 | clients:
21 | - url: http://loki-headless.monitoring.svc.cluster.local:3100/loki/api/v1/push
22 | serviceMonitor:
23 | enabled: true
24 |
--------------------------------------------------------------------------------
/kubernetes/storage/local-path-provisioner/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | namespace: storage
7 | name: local-path-provisioner
8 | spec:
9 | chart:
10 | spec:
11 | chart: deploy/chart/local-path-provisioner
12 | version: 0.0.31
13 | sourceRef:
14 | kind: GitRepository
15 | name: local-path-provisioner
16 | interval: 1h
17 | values:
18 | nodePathMap:
19 | - node: DEFAULT_PATH_FOR_NON_LISTED_NODES
20 | paths:
21 | - /var/local-path-provisioner
22 | replicaCount: 3
23 |
--------------------------------------------------------------------------------
/kubernetes/kube-system/snapshot-controller/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: snapshot-controller
7 | namespace: kube-system
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: snapshot-controller
13 | install:
14 | crds: CreateReplace
15 | remediation:
16 | retries: -1
17 | upgrade:
18 | cleanupOnFail: true
19 | crds: CreateReplace
20 | remediation:
21 | retries: 3
22 | values:
23 | controller:
24 | replicaCount: 2
25 | serviceMonitor:
26 | create: true
27 |
--------------------------------------------------------------------------------
/kubernetes/volsync/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | namespace: volsync
7 | name: volsync
8 | spec:
9 | chart:
10 | spec:
11 | chart: volsync
12 | version: 0.14.0
13 | sourceRef:
14 | kind: HelmRepository
15 | name: backube
16 | interval: 1h
17 | timeout: 10m
18 | values:
19 | manageCRDs: true
20 | replicaCount: 2
21 | metrics:
22 | enabled: true
23 | disableAuth: true
24 | serviceMonitor:
25 | enabled: true
26 | namespace: monitoring
27 | honorLabels: true
28 |
--------------------------------------------------------------------------------
/kubernetes/gitea/backup/backup.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/replicationsource_v1alpha1.json
3 | apiVersion: volsync.backube/v1alpha1
4 | kind: ReplicationSource
5 | metadata:
6 | name: gitea-gitea
7 | namespace: gitea
8 | spec:
9 | sourcePVC: gitea-data
10 | trigger:
11 | schedule: "0 13 * * *"
12 | restic:
13 | moverSecurityContext:
14 | runAsNonRoot: true
15 | runAsUser: 1000
16 | runAsGroup: 1000
17 | fsGroup: 1000
18 | fsGroupChangePolicy: OnRootMismatch
19 | pruneIntervalDays: 14
20 | repository: restic-gitea-gitea
21 | retain:
22 | daily: 7
23 | weekly: 4
24 | monthly: 2
25 | copyMethod: Direct
26 |
--------------------------------------------------------------------------------
/kubernetes/media/radarr/backup/backup.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/replicationsource_v1alpha1.json
3 | apiVersion: volsync.backube/v1alpha1
4 | kind: ReplicationSource
5 | metadata:
6 | name: media-radarr
7 | namespace: media
8 | spec:
9 | sourcePVC: radarr
10 | trigger:
11 | schedule: "0 13 * * *"
12 | restic:
13 | moverSecurityContext:
14 | runAsNonRoot: true
15 | runAsUser: 1000
16 | runAsGroup: 1000
17 | fsGroup: 1000
18 | fsGroupChangePolicy: OnRootMismatch
19 | pruneIntervalDays: 14
20 | repository: restic-media-radarr
21 | retain:
22 | daily: 7
23 | weekly: 4
24 | monthly: 2
25 | copyMethod: Direct
26 |
--------------------------------------------------------------------------------
/kubernetes/media/sonarr/backup/backup.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/replicationsource_v1alpha1.json
3 | apiVersion: volsync.backube/v1alpha1
4 | kind: ReplicationSource
5 | metadata:
6 | name: media-sonarr
7 | namespace: media
8 | spec:
9 | sourcePVC: sonarr
10 | trigger:
11 | schedule: "0 13 * * *"
12 | restic:
13 | moverSecurityContext:
14 | runAsNonRoot: true
15 | runAsUser: 1000
16 | runAsGroup: 1000
17 | fsGroup: 1000
18 | fsGroupChangePolicy: OnRootMismatch
19 | pruneIntervalDays: 14
20 | repository: restic-media-sonarr
21 | retain:
22 | daily: 7
23 | weekly: 4
24 | monthly: 2
25 | copyMethod: Direct
26 |
--------------------------------------------------------------------------------
/kubernetes/media/prowlarr/backup/backup.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/replicationsource_v1alpha1.json
3 | apiVersion: volsync.backube/v1alpha1
4 | kind: ReplicationSource
5 | metadata:
6 | name: media-prowlarr
7 | namespace: media
8 | spec:
9 | sourcePVC: prowlarr
10 | trigger:
11 | schedule: "0 13 * * *"
12 | restic:
13 | moverSecurityContext:
14 | runAsNonRoot: true
15 | runAsUser: 1000
16 | runAsGroup: 1000
17 | fsGroup: 1000
18 | fsGroupChangePolicy: OnRootMismatch
19 | pruneIntervalDays: 14
20 | repository: restic-media-prowlarr
21 | retain:
22 | daily: 7
23 | weekly: 4
24 | monthly: 2
25 | copyMethod: Direct
26 |
--------------------------------------------------------------------------------
/kubernetes/ccinvoice/backup/backup.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/replicationsource_v1alpha1.json
3 | apiVersion: volsync.backube/v1alpha1
4 | kind: ReplicationSource
5 | metadata:
6 | name: ccinvoice-ccinvoice
7 | namespace: ccinvoice
8 | spec:
9 | sourcePVC: ccinvoice
10 | trigger:
11 | schedule: "0 13 * * *"
12 | restic:
13 | moverSecurityContext:
14 | runAsNonRoot: true
15 | runAsUser: 1000
16 | runAsGroup: 1000
17 | fsGroup: 1000
18 | fsGroupChangePolicy: OnRootMismatch
19 | pruneIntervalDays: 14
20 | repository: restic-ccinvoice-ccinvoice
21 | retain:
22 | daily: 7
23 | weekly: 4
24 | monthly: 2
25 | copyMethod: Direct
26 |
--------------------------------------------------------------------------------
/kubernetes/media/radarr/pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
3 | apiVersion: v1
4 | kind: PersistentVolumeClaim
5 | metadata:
6 | name: radarr
7 | namespace: media
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 1Gi
14 | ---
15 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
16 | apiVersion: v1
17 | kind: PersistentVolumeClaim
18 | metadata:
19 | name: radarr-cache
20 | namespace: media
21 | spec:
22 | accessModes:
23 | - ReadWriteOnce
24 | resources:
25 | requests:
26 | storage: 1Gi
27 |
--------------------------------------------------------------------------------
/kubernetes/media/sonarr/pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
3 | apiVersion: v1
4 | kind: PersistentVolumeClaim
5 | metadata:
6 | name: sonarr
7 | namespace: media
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 1Gi
14 | ---
15 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
16 | apiVersion: v1
17 | kind: PersistentVolumeClaim
18 | metadata:
19 | name: sonarr-cache
20 | namespace: media
21 | spec:
22 | accessModes:
23 | - ReadWriteOnce
24 | resources:
25 | requests:
26 | storage: 1Gi
27 |
--------------------------------------------------------------------------------
/kubernetes/homepage/serviceaccount.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/serviceaccount.json
3 | apiVersion: v1
4 | kind: ServiceAccount
5 | metadata:
6 | name: homepage
7 | namespace: homepage
8 | labels:
9 | app.kubernetes.io/name: homepage
10 | secrets:
11 | - name: homepage
12 | ---
13 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
14 | apiVersion: v1
15 | kind: Secret
16 | type: kubernetes.io/service-account-token
17 | metadata:
18 | name: homepage
19 | namespace: homepage
20 | labels:
21 | app.kubernetes.io/name: homepage
22 | annotations:
23 | kubernetes.io/service-account.name: homepage
24 |
--------------------------------------------------------------------------------
/kubernetes/home-assistant/backup/backup.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/replicationsource_v1alpha1.json
3 | apiVersion: volsync.backube/v1alpha1
4 | kind: ReplicationSource
5 | metadata:
6 | name: home-assistant-home-assistant
7 | namespace: home-assistant
8 | spec:
9 | sourcePVC: home-assistant
10 | trigger:
11 | schedule: "0 13 * * *"
12 | restic:
13 | moverSecurityContext:
14 | runAsNonRoot: true
15 | runAsUser: 1000
16 | runAsGroup: 1000
17 | fsGroup: 1000
18 | fsGroupChangePolicy: OnRootMismatch
19 | pruneIntervalDays: 14
20 | repository: restic-home-assistant-home-assistant
21 | retain:
22 | daily: 7
23 | weekly: 4
24 | monthly: 2
25 | copyMethod: Direct
26 |
--------------------------------------------------------------------------------
/kubernetes/home-assistant/pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
3 | apiVersion: v1
4 | kind: PersistentVolumeClaim
5 | metadata:
6 | name: home-assistant
7 | namespace: home-assistant
8 | spec:
9 | accessModes:
10 | - ReadWriteOnce
11 | resources:
12 | requests:
13 | storage: 1Gi
14 | ---
15 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/persistentvolumeclaim.json
16 | apiVersion: v1
17 | kind: PersistentVolumeClaim
18 | metadata:
19 | name: home-assistant-cache
20 | namespace: home-assistant
21 | spec:
22 | accessModes:
23 | - ReadWriteOnce
24 | resources:
25 | requests:
26 | storage: 1Gi
27 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/kube-prometheus-stack/alertmanagerconfig.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/alertmanagerconfig_v1alpha1.json
3 | apiVersion: monitoring.coreos.com/v1alpha1
4 | kind: AlertmanagerConfig
5 | metadata:
6 | name: alertmanager
7 | namespace: monitoring
8 | spec:
9 | route:
10 | groupBy: ["alertname", "job"]
11 | groupInterval: 5m
12 | groupWait: 1m
13 | receiver: discord
14 | repeatInterval: 12h
15 | routes:
16 | - matchers:
17 | - name: alertname
18 | matchType: "="
19 | value: Watchdog
20 | receiver: "null"
21 | receivers:
22 | - name: "null"
23 | - name: discord
24 | discordConfigs:
25 | - apiURL:
26 | name: alertmanager-discord
27 | key: DISCORD_WEBHOOK_URL
28 | sendResolved: true
29 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | namespace: cert-manager
7 | name: cert-manager
8 | spec:
9 | chart:
10 | spec:
11 | chart: cert-manager
12 | version: v1.19.2
13 | sourceRef:
14 | kind: HelmRepository
15 | name: cert-manager
16 | interval: 1h
17 | timeout: 10m
18 | values:
19 | extraArgs:
20 | - --dns01-recursive-nameservers=1.1.1.1:53,9.9.9.9:53
21 | - --dns01-recursive-nameservers-only=true
22 | replicaCount: 3
23 | crds:
24 | enabled: true
25 | podDnsPolicy: "None"
26 | podDnsConfig:
27 | nameservers:
28 | - 1.1.1.1
29 | - 9.9.9.9
30 |
31 | prometheus:
32 | enabled: true
33 | servicemonitor:
34 | enabled: true
35 |
--------------------------------------------------------------------------------
/kubernetes/flux-system/gotk-sync.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/gitrepository_v1.json
3 | apiVersion: source.toolkit.fluxcd.io/v1
4 | kind: GitRepository
5 | metadata:
6 | name: flux-system
7 | namespace: flux-system
8 | spec:
9 | interval: 1m0s
10 | ref:
11 | branch: main
12 | secretRef:
13 | name: flux-system
14 | url: https://github.com/scottmckendry/axis.git
15 | ---
16 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json
17 | apiVersion: kustomize.toolkit.fluxcd.io/v1
18 | kind: Kustomization
19 | metadata:
20 | name: flux-system
21 | namespace: flux-system
22 | spec:
23 | interval: 10m0s
24 | path: ./kubernetes
25 | prune: true
26 | sourceRef:
27 | kind: GitRepository
28 | name: flux-system
29 | decryption:
30 | provider: sops
31 | secretRef:
32 | name: sops-age
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Scott McKendry
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/kubernetes/home-assistant/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: home-assistant
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`ha.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | services:
16 | - name: home-assistant-app
17 | namespace: home-assistant
18 | port: 8123
19 | tls:
20 | secretName: axis-tls
21 | ---
22 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
23 | apiVersion: traefik.io/v1alpha1
24 | kind: IngressRoute
25 | metadata:
26 | name: home-assistant-code
27 | namespace: traefik
28 | spec:
29 | routes:
30 | - match: Host(`ha-code.axis.scottmckendry.tech`)
31 | kind: Rule
32 | middlewares:
33 | - name: ipallowlist
34 | namespace: traefik
35 | - name: forwardauth
36 | namespace: traefik
37 | services:
38 | - name: home-assistant-code
39 | namespace: home-assistant
40 | port: 8081
41 | tls:
42 | secretName: axis-tls
43 |
--------------------------------------------------------------------------------
/kubernetes/traefik/middlewares.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: Middleware
5 | metadata:
6 | name: ipallowlist
7 | namespace: traefik
8 | spec:
9 | ipAllowList:
10 | sourceRange:
11 | - 127.0.0.1/32
12 | - 10.0.0.0/8
13 | - 192.168.0.0/16
14 | ---
15 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
16 | apiVersion: traefik.io/v1alpha1
17 | kind: Middleware
18 | metadata:
19 | name: forwardauth
20 | namespace: traefik
21 | spec:
22 | forwardAuth:
23 | address: http://tinyauth.traefik.svc.cluster.local:3000/api/auth/traefik
24 | ---
25 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
26 | apiVersion: traefik.io/v1alpha1
27 | kind: Middleware
28 | metadata:
29 | name: default-headers
30 | namespace: traefik
31 | spec:
32 | headers:
33 | frameDeny: true
34 | sslRedirect: true
35 | browserXssFilter: true
36 | contentTypeNosniff: true
37 | forceSTSHeader: true
38 | stsIncludeSubdomains: true
39 | stsPreload: true
40 | stsSeconds: 15552000
41 | customFrameOptionsValue: SAMEORIGIN
42 | customRequestHeaders:
43 | X-Forwarded-Proto: https
44 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/kube-prometheus-stack/ingress.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
3 | apiVersion: traefik.io/v1alpha1
4 | kind: IngressRoute
5 | metadata:
6 | name: prometheus
7 | namespace: traefik
8 | spec:
9 | routes:
10 | - match: Host(`prometheus.axis.scottmckendry.tech`)
11 | kind: Rule
12 | middlewares:
13 | - name: ipallowlist
14 | namespace: traefik
15 | - name: forwardauth
16 | namespace: traefik
17 | services:
18 | - name: kube-prometheus-stack-prometheus
19 | namespace: monitoring
20 | port: 9090
21 | tls:
22 | secretName: axis-tls
23 | ---
24 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
25 | apiVersion: traefik.io/v1alpha1
26 | kind: IngressRoute
27 | metadata:
28 | name: alertmanager
29 | namespace: traefik
30 | spec:
31 | routes:
32 | - match: Host(`am.axis.scottmckendry.tech`)
33 | kind: Rule
34 | middlewares:
35 | - name: ipallowlist
36 | namespace: traefik
37 | - name: forwardauth
38 | namespace: traefik
39 | services:
40 | - name: kube-prometheus-stack-alertmanager
41 | namespace: monitoring
42 | port: 9093
43 | tls:
44 | secretName: axis-tls
45 |
--------------------------------------------------------------------------------
/kubernetes/traefik/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | namespace: traefik
7 | name: traefik
8 | spec:
9 | chart:
10 | spec:
11 | chart: traefik
12 | version: 37.4.0
13 | sourceRef:
14 | kind: HelmRepository
15 | name: traefik
16 | interval: 1h
17 | timeout: 10m
18 | values:
19 | # https://github.com/traefik/traefik-helm-chart/blob/master/traefik/values.yaml
20 | additionalArguments:
21 | - --serversTransport.insecureskipverify=true
22 |
23 | deployment:
24 | enabled: true
25 | replicas: 3
26 |
27 | ports:
28 | web:
29 | redirections:
30 | entrypoint:
31 | to: websecure
32 | priority: 10
33 |
34 | service:
35 | enabled: true
36 | type: LoadBalancer
37 | LoadBalancerIP: 10.0.10.1
38 | externalTrafficPolicy: Local
39 |
40 | providers:
41 | kubernetesCRD:
42 | allowCrossNamespace: true
43 | allowExternalNameServices: true
44 |
45 | metrics:
46 | prometheus:
47 | service:
48 | enabled: true
49 | serviceMonitor:
50 | enabled: true
51 | namespace: monitoring
52 | honorLabels: true
53 |
--------------------------------------------------------------------------------
/kubernetes/gitea/mirror.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: gitea-mirror-secret
7 | namespace: gitea
8 | stringData:
9 | BETTER_AUTH_SECRET: ENC[AES256_GCM,data:UzWXX+iwBl0wHimp3RNkj/dn+pTq4Qru9G5UaNL3pH4=,iv:Kh2eUPa1+ugGbBJgso7CdOR42r1lNlUBNPUf75Wbs+g=,tag:0fMDL4UoLNcH84Z1tdclSA==,type:str]
10 | sops:
11 | age:
12 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
13 | enc: |
14 | -----BEGIN AGE ENCRYPTED FILE-----
15 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaWmtKOVh3cFJ5NTE1czZ4
16 | eUp3M3pJbytkU3NkQW42VmZoV0tZanFzL3hZCmJvOG1oSGpuQTZBU3MzWmFyMXRQ
17 | WVlwUzl1akRJVjRVNkp5cGl3SEU1UE0KLS0tIFprbFBEenlocFNPbTRLc3IyVTZC
18 | ZWttUFcyY1hSRElzQ3FmN29EK2VaUHcK8w/H1ERdfDOQzHEfL82zWZHta75uPeR0
19 | 36rI9Fms/wsfjVEMw0xmNET+wAZvM89qlkHh5ddxC2hintcsLy2Lhg==
20 | -----END AGE ENCRYPTED FILE-----
21 | lastmodified: "2025-10-24T21:47:11Z"
22 | mac: ENC[AES256_GCM,data:IZo21ej6Xz5F3vGFksMHpgvVTIzu6NY5zD3VG8qvDT3gXwg+aLJ5oW4a8iJ/5jJW4qbjTdZ1wk0zw4j5elWyy7/8YKDcmhbsRMZSoEwMCxRae+QXzJtTQM2c0OMsLqrKNW/ogaCUicF2YxwlLvF9HuGLJyoAaTxig6VqVYCoHOU=,iv:tqdnuwcY/1SA0d55FGlMh3gieZe5gLbMLtVxIsyh+fc=,tag:o8xkB0bqKWSkjmuvYX6pjg==,type:str]
23 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
24 | version: 3.11.0
25 |
--------------------------------------------------------------------------------
/kubernetes/actual/akahu-actual/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: akahu-actual
7 | namespace: actual
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: app-template
13 | namespace: flux-system
14 | dependsOn:
15 | - name: actual
16 | namespace: actual
17 | values:
18 | controllers:
19 | akahu-actual:
20 | type: cronjob
21 | cronjob:
22 | schedule: 49 * * * *
23 | containers:
24 | tag:
25 | image:
26 | repository: ghcr.io/scottmckendry/akahu-actual
27 | tag: v0.9.0@sha256:2be76e9936f255950d2b0fa2ab0b321e64622d194a1d22fb16283ab84e00fb2b
28 | envFrom:
29 | - secretRef:
30 | name: akahu-actual-secret
31 | securityContext:
32 | allowPrivilegeEscalation: false
33 | readOnlyRootFilesystem: true
34 | capabilities: { drop: ["ALL"] }
35 | defaultPodOptions:
36 | securityContext:
37 | runAsNonRoot: true
38 | runAsUser: 1000
39 | runAsGroup: 1000
40 | persistence:
41 | tmp:
42 | type: emptyDir
43 | globalMounts:
44 | - path: /tmp
45 | readOnly: false
46 |
--------------------------------------------------------------------------------
/kubernetes/ccinvoice/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: ccinvoice
7 | namespace: ccinvoice
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: app-template
13 | namespace: flux-system
14 | values:
15 | controllers:
16 | main:
17 | containers:
18 | app:
19 | image:
20 | repository: ghcr.io/scottmckendry/ccinvoice
21 | tag: v3.2.1@sha256:69c5c19479c7c04c3a35dd03b8291a2065cbb64a1a42bccdf7b955bd48346f8e
22 | envFrom:
23 | - secretRef:
24 | name: ccinvoice-secrets
25 | securityContext:
26 | allowPrivilegeEscalation: false
27 | capabilities:
28 | drop: ["ALL"]
29 | seccompProfile:
30 | type: RuntimeDefault
31 | defaultPodOptions:
32 | securityContext:
33 | runAsNonRoot: true
34 | runAsUser: 1000
35 | runAsGroup: 1000
36 | fsGroup: 1000
37 | service:
38 | main:
39 | controller: main
40 | ports:
41 | http:
42 | port: 3000
43 | persistence:
44 | data:
45 | existingClaim: ccinvoice
46 | globalMounts:
47 | - path: /app/data
48 |
--------------------------------------------------------------------------------
/kubernetes/cert-manager/issuers/cloudflare-issuer.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: cloudflare-issuer-secret
6 | namespace: cert-manager
7 | type: Opaque
8 | stringData:
9 | CLOUDFLARE_DNS_TOKEN: ENC[AES256_GCM,data:ejtn+RWqSEYB4KMNXh2mRZGKsa7MJMbdNJ6IP3SnY9jwR63hiuUEBg==,iv:udyOcMsEwSwOYfZEJs8k5i9RDIvC/90OhkUFcR62WDk=,tag:PieqEHfr/8rnM2aOzLCa5Q==,type:str]
10 | sops:
11 | kms: []
12 | gcp_kms: []
13 | azure_kv: []
14 | hc_vault: []
15 | age:
16 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
17 | enc: |
18 | -----BEGIN AGE ENCRYPTED FILE-----
19 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXekZjdWxQZ002ZVpaUEd3
20 | dTRiOE1rVW0xSTJLbE8rM0cyOFJiMW1LSjBvClNlcGtXaTQ1UTJzOVZ0TUU5RVpM
21 | M1JMRC9wdTcya05pQ1gyUmJZeEUvVzAKLS0tIFhiSHhYNlN0dXJWbElLa3A0dis2
22 | N1A4VmJHNk1SZWp4RndBWlZmenJTQWMKxIJPcvqu4cTyMw0rJr0to0aSBy49z/b/
23 | i9u05iCOE4ywaByd0XL4EBxOCgQ515ac8wc5VmZiKE/AZN0g9zLbsg==
24 | -----END AGE ENCRYPTED FILE-----
25 | lastmodified: "2025-04-08T00:30:13Z"
26 | mac: ENC[AES256_GCM,data:/5s6F9fq7wqWOvQMlrXdTukGr1MKu6vyf4SIlimmuQjanjWQfNXX6BVV2Qf2gepz5KkUxQip4KM71Kdw5VptCpxRSnaC9pavVjf1zCiclZULfFDkdjwLwD/YnWvBjblWYzJM8COegmrk92v4ae6TKHR8empNpxr6YtFjUJokdJY=,iv:zVkGGGLnD/SSjZkni/D7AWjXjmnAgqKoOUL6RX2Jtm8=,tag:wdmA/Iv79wip6jb1LwWxtw==,type:str]
27 | pgp: []
28 | encrypted_regex: ^(data|stringData|email)$
29 | version: 3.9.4
30 |
--------------------------------------------------------------------------------
/kubernetes/media/recyclarr/recyclarr.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: recyclarr-secret
6 | namespace: media
7 | type: Opaque
8 | stringData:
9 | SONARR_API_KEY: ENC[AES256_GCM,data:eJc+5fCwugmR8mfUX9sod380rXM4g2myvfcLWYXWNgA=,iv:6DdW+SByC3H7al97K+RcDPN129TYdViiWoTYP/0E5+E=,tag:qWJ+OsHGVHuNfbDg0NlTmA==,type:str]
10 | RADARR_API_KEY: ENC[AES256_GCM,data:l4E99hO65lHipkPffiDznrqrrmocw9iQRFzjpqVZ0Kc=,iv:XGajhEpTFjyiwLkxqwRieo6Em7nLT1La+mJ+bYRX61c=,tag:jp5rx4QD8bOoyNc086MJqg==,type:str]
11 | sops:
12 | age:
13 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
14 | enc: |
15 | -----BEGIN AGE ENCRYPTED FILE-----
16 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0MDNqN0F3Tkx1K0tid29V
17 | eElHbGFvOG1YTGJ1OXpRaFkwWkkwVEJNY1JRCnh1a0tQT1FDZVNWWmQ4OXF2N1Fm
18 | am5kTXlDdjV6WTR6SkFtak1kT0trZmsKLS0tIE1mcVVBbk5DVVpRRGNWMEYrR0Zh
19 | c1FVdWdXMmxUVHU3eDN0TkxJb3c3YjAKBFDMvsvacEtS+1Joh0pf/HAKqT9U+pDs
20 | Qyths4U8vXYYN2sWzH/kvNPe39GPs3GrpY13TUM+8/oo6wxjbHwjdQ==
21 | -----END AGE ENCRYPTED FILE-----
22 | lastmodified: "2025-05-07T08:01:12Z"
23 | mac: ENC[AES256_GCM,data:r04yHLLhQLGV098/1LosGyxdkV4U031X9TJHKTTu6MXHGphLo7jcIlRCv02gjo6tyU26UjWEscNyQJZJV80d6jyij5y98l7MdSf4y83NUtKXrN6d0eQYZNL1PZ2yodXwxRR1ssR1bPm8K1EkWQjDdEtb8cUng7xeJaTbcgTh9Pc=,iv:xqsKiR2CrZiMj+5oBbhcEO9PEA0jnRaTPpzmkpkXL1k=,tag:bp7wZqyHkzGjM/gSNGr6JQ==,type:str]
24 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
25 | version: 3.10.2
26 |
--------------------------------------------------------------------------------
/kubernetes/gitea/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: gitea
7 | namespace: gitea
8 | spec:
9 | chart:
10 | spec:
11 | chart: gitea
12 | version: 12.4.0
13 | sourceRef:
14 | kind: HelmRepository
15 | name: gitea
16 | interval: 1h
17 | timeout: 10m
18 | values:
19 | postgresql-ha:
20 | enabled: false
21 | valkey-cluster:
22 | enabled: false
23 | postgresql:
24 | enabled: true
25 | valkey:
26 | enabled: true
27 |
28 | gitea:
29 | admin:
30 | existingSecret: gitea-secrets
31 | metrics:
32 | enabled: true
33 | serviceMonitor:
34 | enabled: true
35 | config:
36 | indexer:
37 | REPO_INDEXER_ENABLED: true
38 | ISSUE_INDEXER_TYPE: bleve
39 | server:
40 | ROOT_URL: https://git.axis.scottmckendry.tech
41 | podAnnotations: {}
42 |
43 | image:
44 | rootless: true
45 | podSecurityContext:
46 | runAsUser: 1000
47 | runAsGroup: 1000
48 | fsGroup: 1000
49 | fsGroupChangePolicy: OnRootMismatch
50 |
51 | persistence:
52 | enabled: true
53 | claimName: gitea-data
54 | create: false
55 |
56 | service:
57 | http:
58 | type: ClusterIP
59 | port: 3000
60 |
61 | ingress:
62 | enabled: false # Using Traefik IngressRoute
63 |
64 | securityContext:
65 | capabilities:
66 | drop:
67 | - ALL
68 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/grafana/admin.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: grafana-admin-credentials
7 | namespace: monitoring
8 | stringData:
9 | admin-user: ENC[AES256_GCM,data:f8vY4TY=,iv:A+dEOMPxt2Y01qyVDitwzzK1/cBfXGER+u/1WIjqLBc=,tag:iEJvavjd7s9miXHfat4NYw==,type:str]
10 | admin-password: ENC[AES256_GCM,data:kldvClk50QmatrJo0id7,iv:HT0RM5ge5+gWxJksY6BUgDou2NrJi33TR49H7XgCmIg=,tag:qumIAgOTTCLvGO1r5WzAMw==,type:str]
11 | sops:
12 | kms: []
13 | gcp_kms: []
14 | azure_kv: []
15 | hc_vault: []
16 | age:
17 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
18 | enc: |
19 | -----BEGIN AGE ENCRYPTED FILE-----
20 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUZDh1cWJ3NFhRTjd4V0Iy
21 | bFBBeVEwMFVvblFqOXd4Q2JId2FTSVNMMVJZClAzWDEwSDdYSDczZlZSWkVzZG9j
22 | dWRGWlFTS2wzOUdVUnQzTHY1TlN1R00KLS0tIHVSVnVZcGd6aHNYcUpZSFRpSE9S
23 | WmZzdlduS0hwaXYrdm5VUStCWU1SUk0K2rD5jat8ogo2dLU7ZRRzjxBwL05202SA
24 | mba9WGgYvnmD41ZZ4TM+nTvxTmTpIxl1OBYpCsmd8R9tHtIyiw9vDA==
25 | -----END AGE ENCRYPTED FILE-----
26 | lastmodified: "2025-04-18T03:28:24Z"
27 | mac: ENC[AES256_GCM,data:r4xkzEKDyAlNGO1+e1b2eLEpQv9pVlgWG/JtsmHJgID00aDXoaUd2pgQSSmwZzUtGWtFmOkUurVU0k6FkzCnc/kWGTYxf+ln7Jyv77/0iSr8N9BNtzAqjR/R98HHAYbAcy95pKWiCPzQkDcr5diVVsIxCvqX3p+YlE+DWe8BgQE=,iv:dCyqToxKchx//IYOTHd3ws/HoQTkCad7xIyGwrENwCI=,tag:/Qvw5YLhURt/D3grvwJfkA==,type:str]
28 | pgp: []
29 | encrypted_regex: ^(data|stringData|email)$
30 | version: 3.9.4
31 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/kube-prometheus-stack/alertmanager.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: alertmanager-discord
6 | type: Opaque
7 | stringData:
8 | DISCORD_WEBHOOK_URL: ENC[AES256_GCM,data:Wmd7nzTbqjImbToxVHPVbPlY7m/Q5+Y5KN8NLtlxUHWH4/XY1trWZ7RRVyfeLhio/IhzGZzt7qinWao9NnHLdwUfv/J0Py5j7GL6fV30DeoOnwvMnS5yy2e51E29TfVMyDZ4GvZNlSXNP/JNlXiZU+0W68Zo+dPJqg==,iv:Z66ckwEKsC+le1aNBZ7wFrEErCjInCUK850KOnsI18Y=,tag:uoB+0+2SYncE/FdR6F6osw==,type:str]
9 | sops:
10 | kms: []
11 | gcp_kms: []
12 | azure_kv: []
13 | hc_vault: []
14 | age:
15 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
16 | enc: |
17 | -----BEGIN AGE ENCRYPTED FILE-----
18 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVQmZFSk5TUlVmNkdLeXly
19 | Vmk1MEw3MXRad2pVRkgzMithdlR3eFpPb2s4Ck1hWlk1dndvazBueW5JNERhMjdj
20 | ZkN5MDVTbGlFOUFXZ2M3bXF0U3pwN3cKLS0tIFNvVmJlV3hYSnBUQ0tzTHlUK3Vq
21 | M3B4dW9CeGNkbVRmM3U2OUdxdjdlUTAKv7Q9k6MpQkSvddcYYY7rui7kiCv1L9MG
22 | cm5Pq0bRiBRtASWEcZIswQmAYS5DZr23nBqZxGs7dHhsk7D3cYEMkA==
23 | -----END AGE ENCRYPTED FILE-----
24 | lastmodified: "2025-05-14T17:44:32Z"
25 | mac: ENC[AES256_GCM,data:kAMbKeKUx9ua0dsxAf4xkgILqRN30EpbPf8xFMw7l155baRnHeQVt6mK3PDsdQA/i0CQjyxKhOIUWGZ3dJmf8zwk+IoevbrvrWnP026OV1o0v36A1mys5kt6YyI2OVYqAJPXmQpPNmEAOAKOIvcl4+sh0HVFYAkgeSK+UQ/OL7A=,iv:INDkmEXv58OKEerqgkOh73wh5Fc0OxjMRIF8m9zSW3g=,tag:dUxszBcd5RY4chBiIINpow==,type:str]
26 | pgp: []
27 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
28 | version: 3.9.4
29 |
--------------------------------------------------------------------------------
/kubernetes/homepage/clusterrole.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/clusterrole.json
3 | apiVersion: rbac.authorization.k8s.io/v1
4 | kind: ClusterRole
5 | metadata:
6 | name: homepage
7 | namespace: homepage
8 | labels:
9 | app.kubernetes.io/name: homepage
10 | rules:
11 | - apiGroups:
12 | - ""
13 | resources:
14 | - namespaces
15 | - pods
16 | - nodes
17 | verbs:
18 | - get
19 | - list
20 | - apiGroups:
21 | - extensions
22 | - networking.k8s.io
23 | resources:
24 | - ingresses
25 | verbs:
26 | - get
27 | - list
28 | - apiGroups:
29 | - traefik.io
30 | resources:
31 | - ingressroutes
32 | verbs:
33 | - get
34 | - list
35 | - apiGroups:
36 | - gateway.networking.k8s.io
37 | resources:
38 | - httproutes
39 | - gateways
40 | verbs:
41 | - get
42 | - list
43 | - apiGroups:
44 | - metrics.k8s.io
45 | resources:
46 | - nodes
47 | - pods
48 | verbs:
49 | - get
50 | - list
51 | ---
52 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/clusterrolebinding.json
53 | apiVersion: rbac.authorization.k8s.io/v1
54 | kind: ClusterRoleBinding
55 | metadata:
56 | name: homepage
57 | namespace: homepage
58 | labels:
59 | app.kubernetes.io/name: homepage
60 | roleRef:
61 | apiGroup: rbac.authorization.k8s.io
62 | kind: ClusterRole
63 | name: homepage
64 | subjects:
65 | - kind: ServiceAccount
66 | name: homepage
67 | namespace: homepage
68 |
--------------------------------------------------------------------------------
/kubernetes/actual/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: actual
7 | namespace: actual
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: app-template
13 | namespace: flux-system
14 | values:
15 | controllers:
16 | actual:
17 | containers:
18 | app:
19 | image:
20 | repository: ghcr.io/actualbudget/actual-server
21 | tag: 25.12.0
22 | ports:
23 | - containerPort: 5006
24 | env:
25 | - name: ACTUAL_PORT
26 | value: "5006"
27 | securityContext:
28 | allowPrivilegeEscalation: false
29 | capabilities:
30 | drop: ["ALL"]
31 | seccompProfile:
32 | type: RuntimeDefault
33 | probes:
34 | liveness:
35 | enabled: true
36 | custom: true
37 | spec:
38 | exec:
39 | command:
40 | - node
41 | - src/scripts/health-check.js
42 | initialDelaySeconds: 20
43 | periodSeconds: 60
44 | timeoutSeconds: 10
45 | failureThreshold: 3
46 | service:
47 | app:
48 | controller: actual
49 | ports:
50 | http:
51 | port: 5006
52 | persistence:
53 | data:
54 | existingClaim: actual
55 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/loki/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | # TODO: Investigate object storage options for persisted data e.g. minio
4 | apiVersion: helm.toolkit.fluxcd.io/v2
5 | kind: HelmRelease
6 | metadata:
7 | name: loki
8 | namespace: monitoring
9 | spec:
10 | chart:
11 | spec:
12 | chart: loki
13 | version: 6.49.0
14 | sourceRef:
15 | kind: HelmRepository
16 | name: loki
17 | interval: 1h
18 | timeout: 10m
19 | values:
20 | deploymentMode: SingleBinary
21 | loki:
22 | auth_enabled: false
23 | analytics:
24 | reporting_enabled: false
25 | server:
26 | log_level: info
27 | commonConfig:
28 | replication_factor: 1
29 | ingester:
30 | chunk_encoding: snappy
31 | limits_config:
32 | retention_period: 14d
33 | storage:
34 | type: filesystem
35 | schemaConfig:
36 | configs:
37 | - from: "2025-01-01"
38 | store: tsdb
39 | object_store: filesystem
40 | schema: v13
41 | index:
42 | prefix: loki_index_
43 | period: 24h
44 | singleBinary:
45 | replicas: 1
46 | persistence:
47 | enabled: true
48 | size: 20Gi
49 | gateway:
50 | replicas: 0
51 | backend:
52 | replicas: 0
53 | read:
54 | replicas: 0
55 | write:
56 | replicas: 0
57 | chunksCache:
58 | enabled: false
59 | resultsCache:
60 | enabled: false
61 | lokiCanary:
62 | enabled: false
63 | test:
64 | enabled: false
65 |
--------------------------------------------------------------------------------
/kubernetes/gitea/gitea.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: gitea-secrets
7 | namespace: gitea
8 | labels:
9 | app.kubernetes.io/name: gitea
10 | stringData:
11 | username: ENC[AES256_GCM,data:MVuktoI=,iv:7XRxg9hBVVD3gkELkOzUkUf9AGI4Rf1bN87dlxPYAS8=,tag:qoelmZGXwXHe7QBatNtiYw==,type:str]
12 | password: ENC[AES256_GCM,data:BoYvwbRmlB4dWrBD1pEV,iv:cKUHcK6KBCG5k+au5gHAGaVuAuDZdOmhh3TtJ2PWBIM=,tag:8GJfOVUnvG7OtvQ/YjKqdw==,type:str]
13 | email: ENC[AES256_GCM,data:TWsOtBKgnT+gDZkTM9I+ftMJH6wN,iv:zKhyqLQ3yTrKyyDWi6dUHfQBsd98Y/MfS+vrYFYdIcA=,tag:4WZTLe6pNCxgH3wNbveygA==,type:str]
14 | sops:
15 | age:
16 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
17 | enc: |
18 | -----BEGIN AGE ENCRYPTED FILE-----
19 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSNVBuRlFaMCtSWmZaUkll
20 | djZLZUd1TVpmdE9IakRVdVNmUzdlNmttYjNrCmxqZDJVbWdxMmFQeVdqbFlReW5k
21 | Y1VDd1BuRGc0OXJtOWJJTGpCR3l4K2sKLS0tIG12VWNzSzkzQkx0THRoaWV0cmRa
22 | RGJ1WkJ6SnA0MWl2RFZMUjZGV1l2VmcKTA9coWV6b360yupTqnhShg6qNzRa5vem
23 | NScVT+w/QVOv+Zi9wu2X1BGwzAslq2zNv/GmPssA/N1Yj3bSrxjxeg==
24 | -----END AGE ENCRYPTED FILE-----
25 | lastmodified: "2025-10-24T21:52:42Z"
26 | mac: ENC[AES256_GCM,data:UH2+Cc09DyngRRk7dbfNrNJFRoyM0H4U4jXJhNtR7qmtIXKtDng5lTp4BA/+BOHcNfNWK97dI1jt7tKVV75lNpwsdqoLD8rHx8PVPVgKlctSwXH3xbzW5HEtHZnJa3Bo7KJM7UQm0SrnWQMHEVPLdD6UrWpRCxxOyQoa47Vf9IM=,iv:6moGKo9XyDgPMAJ2uDG3wF+9Bt8wVX/eUp9AJsuwgyc=,tag:8wP5+SziyU41sK/SrUtTeA==,type:str]
27 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
28 | version: 3.11.0
29 |
--------------------------------------------------------------------------------
/kubernetes/homepage/config/bookmarks.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # https://gethomepage.dev/configs/bookmarks/
3 | - dev:
4 | - axis:
5 | - icon: si-github
6 | href: https://github.com/scottmckendry/axis
7 | - nix:
8 | - icon: si-github
9 | href: https://github.com/scottmckendry/nix
10 | - windots:
11 | - icon: si-github
12 | href: https://github.com/scottmckendry/windots
13 | - akahu-actual:
14 | - icon: si-github
15 | href: https://github.com/scottmckendry/akahu-actual
16 | - entertainment:
17 | - youtube:
18 | - icon: si-youtube
19 | href: https://youtube.com
20 | - twitch:
21 | - icon: si-twitch
22 | href: https://twitch.tv
23 | - imdb:
24 | - icon: si-imdb
25 | href: https://imdb.com
26 | - tmdb:
27 | - icon: si-themoviedatabase
28 | href: https://themoviedb.org
29 | - tools:
30 | - bitwarden:
31 | - icon: si-bitwarden
32 | href: https://vault.bitwarden.com
33 | - backblaze b2:
34 | - icon: si-backblaze
35 | href: https://secure.backblaze.com/b2_buckets.htm
36 | - renovate:
37 | - icon: si-renovate
38 | href: https://developer.mend.io/
39 | - copilot chat:
40 | - icon: si-githubcopilot
41 | href: https://github.com/copilot/
42 |
43 | - docs:
44 | - talos:
45 | - icon: si-talos
46 | href: https://talos.dev/docs/
47 | - kubernetes:
48 | - icon: si-kubernetes
49 | href: https://kubernetes.io/docs/home/
50 | - helm:
51 | - icon: si-helm
52 | href: https://helm.sh/docs/
53 | - flux:
54 | - icon: si-flux
55 | href: https://fluxcd.io/docs/
56 |
--------------------------------------------------------------------------------
/kubernetes/media/recyclarr/config/recyclarr.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/recyclarr/recyclarr/master/schemas/config-schema.json
3 | sonarr:
4 | sonarr:
5 | base_url: http://sonarr.media.svc.cluster.local
6 | api_key: !env_var SONARR_API_KEY
7 | delete_old_custom_formats: true
8 | replace_existing_custom_formats: true
9 | include:
10 | - template: sonarr-v4-quality-profile-web-1080p
11 | - template: sonarr-v4-custom-formats-web-1080p
12 | - template: sonarr-v4-quality-profile-web-2160p
13 | - template: sonarr-v4-custom-formats-web-2160p
14 |
15 | # Custom Formats: https://recyclarr.dev/wiki/yaml/config-reference/custom-formats/
16 | custom_formats:
17 | - trash_ids:
18 | - 47435ece6b99a0b477caf360e79ba0bb # x265 (HD)
19 | - 9b64dff695c2115facf1b6ea59c9bd07 # x265 (no HDR/DV)
20 | assign_scores_to:
21 | - name: WEB-1080p
22 | score: 100
23 | - name: WEB-2160p
24 | score: 100
25 |
26 | radarr:
27 | radarr:
28 | base_url: http://radarr.media.svc.cluster.local
29 | api_key: !env_var RADARR_API_KEY
30 |
31 | include:
32 | - template: radarr-quality-profile-hd-bluray-web
33 | - template: radarr-custom-formats-hd-bluray-web
34 | - template: radarr-quality-profile-uhd-bluray-web
35 | - template: radarr-custom-formats-uhd-bluray-web
36 |
37 | custom_formats:
38 | - trash_ids:
39 | - dc98083864ea246d05a42df0d05f81cc # x265 (HD)
40 | - 839bea857ed2c0a8e084f3cbdbd65ecb # x265 (no HDR/DV)
41 | assign_scores_to:
42 | - name: HD Bluray + WEB
43 | score: 100
44 | - name: UHD Bluray + WEB
45 | score: 100
46 |
--------------------------------------------------------------------------------
/.taskfiles/volsync.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://taskfile.dev/schema.json
3 | version: 3
4 |
5 | # Constraints:
6 | # 1. Replication source MUST be named "[namespace]-[pvc-name]".
7 | # 2. Restic repo secret MUST be named "restic-[namespace]-[pvc-name]".
8 | # 3. Backups in the environment variables below MUST be named "[namespace]_[pvc-name]", replacing ALL hypens with underscores.
9 |
10 | # backups are defined as environment variables. We check if they exist to ensure only valid names are used.
11 | # new backups should be added (and tested!) here.
12 | env:
13 | actual_actual: --name actual --namespace actual --manage-pods --runner-id 1000
14 | ccinvoice_ccinvoice: --name ccinvoice --namespace ccinvoice --manage-pods --runner-id 1000
15 | gitea_gitea: --name gitea --namespace gitea --manage-pods --runner-id 1000
16 | home_assistant_home_assistant: --name home-assistant --namespace home-assistant --manage-pods --runner-id 1000
17 | media_prowlarr: --name prowlarr --namespace media --manage-pods --runner-id 1000
18 | media_radarr: --name radarr --namespace media --manage-pods --runner-id 1000
19 | media_sonarr: --name sonarr --namespace media --manage-pods --runner-id 1000
20 |
21 | # TODO: add manual backup task/s that can be run on demand.
22 | tasks:
23 | restore-*:
24 | desc: "Restore a PVC from a restic backup. example: task restore-ccinvoice"
25 | vars:
26 | NAME: "{{index .MATCH 0}}"
27 | preconditions:
28 | - sh: '[ "${{.NAME}}" != "" ]' # check if NAME env var is not empty
29 | cmds:
30 | - cmd: ./scripts/restore.sh {{.CLI_ARGS}} ${{.NAME}}
31 |
32 | interactive-restore:
33 | desc: "Interactive restore for PVCs. Pick a namespace and restore point"
34 | interactive: true
35 | cmds:
36 | - cmd: ./scripts/pick-backup.sh
37 |
--------------------------------------------------------------------------------
/kubernetes/media/recyclarr/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: recyclarr
7 | namespace: media
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: app-template
13 | namespace: flux-system
14 | values:
15 | controllers:
16 | recyclarr:
17 | type: cronjob
18 | cronjob:
19 | schedule: 0 0 * * *
20 | backoffLimit: 0
21 | concurrencyPolicy: Forbid
22 | successfulJobsHistory: 1
23 | failedJobsHistory: 1
24 | ttlSecondsAfterFinished: 86400
25 | containers:
26 | app:
27 | image:
28 | repository: ghcr.io/recyclarr/recyclarr
29 | tag: 7.5.2@sha256:2550848d43a453f2c6adf3582f2198ac719f76670691d76de0819053103ef2fb
30 | envFrom:
31 | - secretRef:
32 | name: recyclarr-secret
33 | args: ["sync"]
34 | securityContext:
35 | allowPrivilegeEscalation: false
36 | readOnlyRootFilesystem: true
37 | capabilities: { drop: ["ALL"] }
38 | pod:
39 | restartPolicy: Never
40 | defaultPodOptions:
41 | securityContext:
42 | runAsNonRoot: true
43 | runAsUser: 1000
44 | runAsGroup: 1000
45 | fsGroup: 1000
46 | fsGroupChangePolicy: OnRootMismatch
47 | persistence:
48 | config-file:
49 | type: configMap
50 | name: recyclarr-configmap
51 | globalMounts:
52 | - path: /config/recyclarr.yml
53 | subPath: recyclarr.yml
54 | readOnly: true
55 |
--------------------------------------------------------------------------------
/kubernetes/gitea/backup/backblaze.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: restic-gitea-gitea
7 | namespace: gitea
8 | stringData:
9 | RESTIC_REPOSITORY: ENC[AES256_GCM,data:HXWOGFj5SDQFrb3MfOHsWafG0X+cA9zfm706AiO0gEsRIkiOs4lhj7j1G2muNUXwbevy4L0BXHL8FA==,iv:uakX1LNy/BZCjjeP4GQJyq+U2sHQhQzwOcsoTjcj40I=,tag:dgVCvnc8Nq1JwCQxvT8WTw==,type:str]
10 | RESTIC_PASSWORD: ENC[AES256_GCM,data:bv7LNSm9i8fw+wnjVc+xLmwQUE4x3OZJh2FNkRHQI3A=,iv:Cy5f2sgl16dtEbu5BnqPVc3Ua+6zzqdXn/EKJA/cMi0=,tag:ABsdunwJB1VUwZnXm923WQ==,type:str]
11 | AWS_ACCESS_KEY_ID: ENC[AES256_GCM,data:4SqElR3swZ8ktaRBx4hVLHQzSzY041OUCw==,iv:hFPiFQimogmHBBw2btcBIto9yVt9hXuzuQSSW2CbxNM=,tag:R11S8209CVkvY1Thui1B8A==,type:str]
12 | AWS_SECRET_ACCESS_KEY: ENC[AES256_GCM,data:W1tMZGr7lIZtMFbg5RaKPyhPaqNPq5DOH2SsOJu1rw==,iv:n72acdCEN/cV1R4PQRFli6XOavmELH25Zc44B1wi41U=,tag:ZEQUwVZnmz1ENtsFMWlitQ==,type:str]
13 | sops:
14 | age:
15 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
16 | enc: |
17 | -----BEGIN AGE ENCRYPTED FILE-----
18 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArWlVnOWdFTkJHOEpjQ202
19 | RzJ2WERjbWNRZ2wvWFY0dFpPT0NvU1dWYXo4Cm1saGE5QTljazhVcTFOWHZSdmR4
20 | aVJKa2taVi9vOTZXamxJVTlKZFl1UTAKLS0tIHpJL2RyNXl3YUEyL3g1amdZSFJE
21 | R1BuTllHUE5xazlFWlBDVE9iNWp1aUkKYMejWAdBEOdxAL0aa0xcBdS91y86o1jw
22 | HwDQiov54MvTaLdLyixJMyJ2l3WmRSksi1+yb7X4+eXPhQSfEp6mRQ==
23 | -----END AGE ENCRYPTED FILE-----
24 | lastmodified: "2025-10-24T23:40:38Z"
25 | mac: ENC[AES256_GCM,data:QXPZVzFy5XFNk4EFQgk6ELoTdh7I/GucQBi80zu9Lz5bbe9C+UO/e4E5k8cWnglke19QHcdhWpMISMF4sh5cJASHHEfaSw07Uhcz/a1gbEbxzIIBKfgh9PNq9MQ6OshArJyXZTJMDfYBNPjAwzTb4ELrePGC9+8Z7NKE1Kz7iCg=,iv:p6KxYz/cWizRBtmHOysy+/iuvD2WDxWYm2dSa4bAKyI=,tag:x07ThGhkGD+DWWGhs1hGtQ==,type:str]
26 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
27 | version: 3.11.0
28 |
--------------------------------------------------------------------------------
/kubernetes/media/radarr/backup/backblaze.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: restic-media-radarr
7 | namespace: media
8 | stringData:
9 | RESTIC_REPOSITORY: ENC[AES256_GCM,data:02VMG8SctYiE4rWupmjzXuWNpxJAdwuA/44vFQGfLRM7gfwH+FjpdEwdIUS4QxxY2ac7dvuZyMU47Yg=,iv:TVUCkyvzWDQaubQjGhfM4saV6kLsOyCPzcqigHKZlTs=,tag:5NWfnqbnI3gS/FYNjejLgQ==,type:str]
10 | RESTIC_PASSWORD: ENC[AES256_GCM,data:0Zo0cuvZJyEgRFgm79+8TXHkrpCpEh+1DZI6CDZnmXM=,iv:8IIUz1Un65bExOA3NypnL1jwfkUsKxzvoorYs4uuFLE=,tag:vDJ7JBKb4sxrJXY1e3wdRw==,type:str]
11 | AWS_ACCESS_KEY_ID: ENC[AES256_GCM,data:fpwPolvqKd1mOCU+ZcdlDImxflluZ7SxxA==,iv:yq+whk1tWxYmuhyWsTnpya1ofbDblM5ndUpZZYVz1R4=,tag:CxlOLkuJQN2vbdotPOg7Dg==,type:str]
12 | AWS_SECRET_ACCESS_KEY: ENC[AES256_GCM,data:fGrMP4lggNGNXxrSn2jo0odFchGlLA4Z+vYKu5dfUw==,iv:YPuVr+Hd3eLfWTXp8MNnDyKLY7KXygJXcMzrGaRFK+U=,tag:HmxGlafyTX54fSn/nh36sA==,type:str]
13 | sops:
14 | age:
15 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
16 | enc: |
17 | -----BEGIN AGE ENCRYPTED FILE-----
18 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiYlJWOHBUSGZxNDlBNzFF
19 | cys0KzhDa1QwdUpQa0RxejZYRGQzYzVIOVNjCm4zWXdZNEkyRkE0Qjc0cy9uL1F1
20 | M0oxcWhTV3BPdVJiQjVKdmJ6YWUzalkKLS0tIG1sNExpUlJhbllQL3FlQmVBdmg4
21 | MURyWU1ybUZ1QWRIRE1aUXltbXBicFUKq2R/aEOEqvkinylIjYc4RiI8xOSes0te
22 | BjB8wRbsrcgfCOY6OPBKH1unwMSTYoDDPyzKJBvenljvmQeabmMk6A==
23 | -----END AGE ENCRYPTED FILE-----
24 | lastmodified: "2025-05-07T07:46:32Z"
25 | mac: ENC[AES256_GCM,data:OjXdK6LvCsAfBOVwaSL9/ERiMLkq6auUMnClZLfFnLalqBx504uzTMyDtjmQSLTcGYQBcp9+adECTLqEDCY0Z1Kbji0Ts3vje3qZ7Sc2I7E6CyyX04bYevlLocb57lJ23LdzHTY9LBFIEIASKQJ9hoiv6avJg4ZLTgEVkvqX2Wg=,iv:6LHLUa97q/qETX9n70aaWKSJuBOc146o3WbqBE8hm2Q=,tag:5Pc11Zj2/pq8cEkfOFW+Rw==,type:str]
26 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
27 | version: 3.10.2
28 |
--------------------------------------------------------------------------------
/kubernetes/media/sonarr/backup/backblaze.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: restic-media-sonarr
7 | namespace: media
8 | stringData:
9 | RESTIC_REPOSITORY: ENC[AES256_GCM,data:/JieuI31g8dBh+q7khHT1OjqNiDyjWdWPH7UGueFeJAqBB7kqAVCUSFLVZdwcfnbNI/KIZjMdRRn4Aw=,iv:a7wBm4fHKXsdO/wzxPcZMx+jfcDBBY4pzAAscMjYeYM=,tag:Z/RarFb66VGgX3Sde6hRYA==,type:str]
10 | RESTIC_PASSWORD: ENC[AES256_GCM,data:HKAjp7PgXbFKRAlnze0+u9RMwWPM61ec8yyykid6mkU=,iv:pri9Ft3teieZ+a4g9qlQV70/mKGWhA1S/iab3wXsKfM=,tag:tWHhrgA/37mYJq1P4mrnUA==,type:str]
11 | AWS_ACCESS_KEY_ID: ENC[AES256_GCM,data:Cn8Tb5kVxpfI524NaLVJNLByWvuMHzYUpA==,iv:2srLvNJn0mYOIHf+9NjSl/Jj6QhUZYWQGy0EWiCp7lk=,tag:vXzdpbuxLUvLEYPkonsfmg==,type:str]
12 | AWS_SECRET_ACCESS_KEY: ENC[AES256_GCM,data:b6wHky5lvWx8ASTAj9YPpXLt5Ynli13L6NQzRzh/Gw==,iv:kE9oyw8BmcUK13DEodM40N0EpHDDQLGAtxG9hRhF5Uo=,tag:5Nkuf44anoW0vycRR8RuEA==,type:str]
13 | sops:
14 | age:
15 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
16 | enc: |
17 | -----BEGIN AGE ENCRYPTED FILE-----
18 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRQkhkRW56T2dUalE3bFpG
19 | bXVwT2g4WU8xU2IycVZuMXVMbkFPaU1oY2lvClk2R25nQjBaeGp1REJWb0dwYk5P
20 | cUJGMVRKSjBxMWpQYmNaK3FsMERJOEEKLS0tIGF3eTg0eTBIMUgyTHRveWM5eEVB
21 | QWUyQlJYZ3RVTnE4cFRhbXdocmdFUFkK+omZTB57pQBUoZNLLS9BCzVhuBdW7pB8
22 | ZjvHfnDdRofOFs/zxfe9dy53GJ7pI3BP00Hj5cvR7orAVWR3tde7hw==
23 | -----END AGE ENCRYPTED FILE-----
24 | lastmodified: "2025-05-05T19:23:17Z"
25 | mac: ENC[AES256_GCM,data:vBBt5zCVALGGsefpFTs6qp4nJkINWvPz0h5V2qfpcIeUprb5TUd4aIyDOKZZJR86mPZgNikJrahlAvw1Z4/069XjBIYaCTQV0/GpwV3vZvG49LoLTm4ipsQQm6WeC8Jc1aOIXiP7D7+uObtJQWxg+W2J5a5LAdSRCUnaMgeexy8=,iv:EKW+K9ojIAqxyoi/DltYwWVtZNbx16QwFboKqb4N9Do=,tag:1EYX3U5CjpcgrmN49iae4Q==,type:str]
26 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
27 | version: 3.10.2
28 |
--------------------------------------------------------------------------------
/kubernetes/media/prowlarr/backup/backblaze.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: restic-media-prowlarr
7 | namespace: media
8 | stringData:
9 | RESTIC_REPOSITORY: ENC[AES256_GCM,data:CXR2D8yF1Vdqw3F5buizHP5/7HaryMbInFVfT5m3/AlWcOd0typOIo8gxi3C01KWRaikZU0hdSPNeUCWwQ==,iv:Imk9lYobEhOUb9lGa4v+5J+HEtGUKJ+L9lTwVMM6vTw=,tag:Omtk/r5O0oOxoSilYiF23g==,type:str]
10 | RESTIC_PASSWORD: ENC[AES256_GCM,data:L+oxZOig1J5QIKMwgGpsvUccu/onc8TbrGAsq9QpzTs=,iv:65N2cjHlH4QBpeOjr0lle4To6RozqsvDCvYapjLmVTk=,tag:m64TsTTgkEu2RyiRsTuhUg==,type:str]
11 | AWS_ACCESS_KEY_ID: ENC[AES256_GCM,data:HInpIMrhmSi/8HQ+sdnZ09T0avR2+mgzmw==,iv:0MxFvx8uZ1aH8PCunT1mUJKGk1OBhrNHUr02rCk+D48=,tag:+P17WZTxqQHn2yf+ZMqXow==,type:str]
12 | AWS_SECRET_ACCESS_KEY: ENC[AES256_GCM,data:9d98lhNAKL9w+YNbFfuYviA161hRV51CesmRrxDnIA==,iv:hq21ytptPSWxA2UQ3OGZ1HAuPBK5ocl2Upw2qcPgrYQ=,tag:dUjHANQnZL6xsYJv6ehIUg==,type:str]
13 | sops:
14 | age:
15 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
16 | enc: |
17 | -----BEGIN AGE ENCRYPTED FILE-----
18 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxVTN4dExtZHBGZ0dwaDlu
19 | N253WFY1QjE4V3M0SlNsNWhQcEh1MWJpQlJrClpBZU1naGVzN3kwNmVUaHRMWjBL
20 | TTBReVVHWGZXOFNoR29ETi83SnUxUTQKLS0tIGdZOWUxV3F0dmpnckJTODlySEcy
21 | dmNGSWNLdUEvemcrUTF3aUVXdXBaQTgK57ZWqvJXH50qYyEVXKL9M2ofRYyOHz5x
22 | 3zKRt8GnPWrahEQ74no9D6/QtTH702EMk35gaNFwKZDHSVq7lUeBvg==
23 | -----END AGE ENCRYPTED FILE-----
24 | lastmodified: "2025-05-05T19:23:17Z"
25 | mac: ENC[AES256_GCM,data:ogcbM3v4m8KZ3qRp8FgpP5KkXSKoxFPiUdlOKX4cqxl/tYoPiMBTsTSFLttgG4mtYkwaiptAM622iHyXsvEE9rWfXdm2obLhVcnD8z3aksXDbWlEpXKarbe2W7DI69gFYKAoNVaBWv5jyjdOt8NhwbHts4spcyzWmfWdFlvIsms=,iv:JBp+fCOxxKvxZhkLoA3KlJjQLUK/mqk5LVZ+CYmHLiE=,tag:Vq2T8o45BKiav+Gs+WS0dg==,type:str]
26 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
27 | version: 3.10.2
28 |
--------------------------------------------------------------------------------
/kubernetes/media/radarr/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: radarr
7 | namespace: media
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: app-template
13 | namespace: flux-system
14 | values:
15 | controllers:
16 | radarr:
17 | containers:
18 | app:
19 | image:
20 | repository: ghcr.io/home-operations/radarr
21 | tag: 6.1.0.10309@sha256:10f94c85f605d42e5e78de928f24758b5750a4e99eee8d0ef9ff150f7a2df033
22 | env:
23 | RADARR__APP__INSTANCENAME: Radarr
24 | RADARR__APP__THEME: dark
25 | RADARR__AUTH__METHOD: External
26 | RADARR__AUTH__REQUIRED: DisabledForLocalAddresses
27 | RADARR__LOG__DBENABLED: "False"
28 | RADARR__LOG__LEVEL: info
29 | RADARR__SERVER__PORT: 80
30 | RADARR__UPDATE__BRANCH: develop
31 | TZ: Pacific/Auckland
32 | securityContext:
33 | allowPrivilegeEscalation: false
34 | readOnlyRootFilesystem: true
35 | capabilities: { drop: ["ALL"] }
36 | defaultPodOptions:
37 | securityContext:
38 | runAsNonRoot: true
39 | runAsUser: 1000
40 | runAsGroup: 1000
41 | fsGroup: 1000
42 | fsGroupChangePolicy: OnRootMismatch
43 | service:
44 | app:
45 | controller: radarr
46 | ports:
47 | http:
48 | port: 80
49 | persistence:
50 | config:
51 | existingClaim: radarr
52 | config-cache:
53 | existingClaim: radarr-cache
54 | globalMounts:
55 | - path: /config/MediaCover
56 | media:
57 | type: nfs
58 | server: 10.0.6.1
59 | path: /mnt/TrueBlue/media
60 | globalMounts:
61 | - path: /media
62 |
--------------------------------------------------------------------------------
/kubernetes/media/sonarr/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: sonarr
7 | namespace: media
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: app-template
13 | namespace: flux-system
14 | values:
15 | controllers:
16 | sonarr:
17 | containers:
18 | app:
19 | image:
20 | repository: ghcr.io/home-operations/sonarr
21 | tag: 4.0.16.2943@sha256:0a1b8f5cb5b072f7ad8c6ff64a25dc512115d1a114ecf19a58a3b4f870207ddd
22 | env:
23 | SONARR__APP__INSTANCENAME: Sonarr
24 | SONARR__APP__THEME: dark
25 | SONARR__AUTH__METHOD: External
26 | SONARR__AUTH__REQUIRED: DisabledForLocalAddresses
27 | SONARR__LOG__DBENABLED: "False"
28 | SONARR__LOG__LEVEL: info
29 | SONARR__SERVER__PORT: 80
30 | SONARR__UPDATE__BRANCH: develop
31 | TZ: Pacific/Auckland
32 | securityContext:
33 | allowPrivilegeEscalation: false
34 | readOnlyRootFilesystem: true
35 | capabilities: { drop: ["ALL"] }
36 | defaultPodOptions:
37 | securityContext:
38 | runAsNonRoot: true
39 | runAsUser: 1000
40 | runAsGroup: 1000
41 | fsGroup: 1000
42 | fsGroupChangePolicy: OnRootMismatch
43 | service:
44 | app:
45 | controller: sonarr
46 | ports:
47 | http:
48 | port: 80
49 | persistence:
50 | config:
51 | existingClaim: sonarr
52 | config-cache:
53 | existingClaim: sonarr-cache
54 | globalMounts:
55 | - path: /config/MediaCover
56 | media:
57 | type: nfs
58 | server: 10.0.6.1
59 | path: /mnt/TrueBlue/media
60 | globalMounts:
61 | - path: /media
62 |
--------------------------------------------------------------------------------
/kubernetes/actual/backup/backblaze.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: restic-actual-actual
7 | namespace: actual
8 | stringData:
9 | RESTIC_REPOSITORY: ENC[AES256_GCM,data:JP0iym8/xDOMX1aivRjVd+f7TMzq4KWRcw7f5VQUSJV9HgkMZ7sQBF+j1G8YMksGtP/qSAVJTPnEp5Hn,iv:CASrJig2mBFArGtw56P1fIPmtvKqjdSSQMMzwOPQOc4=,tag:SXwUF8TW9vItPmwW8o1r0Q==,type:str]
10 | RESTIC_PASSWORD: ENC[AES256_GCM,data:cpJJVBE7KQaND5+zdr4mR3h1352mZbX4ee1HwMV/Fv8=,iv:eQRi/cQm9SOuqk4QwAT8joFBv1jNs5I69+ScIUjRoCI=,tag:oWvW8i/AEugV0AlzesQOew==,type:str]
11 | AWS_ACCESS_KEY_ID: ENC[AES256_GCM,data:uhP4MxZD8nQI0BgNbugqc2jlzu7x/Zqk+Q==,iv:YI4/V7ihYhY8QTUFsZsdQ3Z1kAhQXtDGEx1XXH8whDk=,tag:g+D4wTvuENjjn6XhT+8ZnQ==,type:str]
12 | AWS_SECRET_ACCESS_KEY: ENC[AES256_GCM,data:bqH5qaByO/u4zqYd5VmF7RyT8ZmjupkuLZBHRXAOfg==,iv:NKWSZJXUmlrbc0wcqP86otv9S151+/XPvJDbm4cYkp0=,tag:RC5iXms13W6iIxnHXCNEDQ==,type:str]
13 | sops:
14 | kms: []
15 | gcp_kms: []
16 | azure_kv: []
17 | hc_vault: []
18 | age:
19 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
20 | enc: |
21 | -----BEGIN AGE ENCRYPTED FILE-----
22 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKdGppS3UzbCtWTnJYckZi
23 | SlFpbVBIcDJscnNOSngzUWtIWXV5azBlTVNFCjlXZWc2dWErR0E1a3B5Rm1GQk1C
24 | UGtMWVRjQmJqRThhVWlkczI0ZndZYTAKLS0tIHVYZGxNaGc3MXZHYXUyN2Q2b0l3
25 | dndFSWNiZElOZHZESzBWKzJNZVl1S0kKRBpKM7i0ooEh7snaqvjKg/8EfdYis93U
26 | U7MPd3fIdHKtsz40P+YXcEDiGv1ScN4FRXnS/5tlCSavpxfzRLKYlg==
27 | -----END AGE ENCRYPTED FILE-----
28 | lastmodified: "2025-05-06T06:44:25Z"
29 | mac: ENC[AES256_GCM,data:rj7M32WwglybtLzo7qrbLNp7qyEDIecNLltju/WwAeqqYda5zyf3StEpTO0Hg360k5XrCZ51xKs5wQZ0/jAsLnC8WNgfbm2b/v+tKc42KA2+XTZVBkZ+8Pc+qfa9jz970Bl1gZNgnHF6lD21yXknBTYtdZ6UWwib/tJk9GF/HUE=,iv:KFl9jLL4FFSXt11y2IeNhXefb78Ui1HeBOf0ZunuCgs=,tag:NB7dgjHFqYSXrN2bagaPcQ==,type:str]
30 | pgp: []
31 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
32 | version: 3.9.4
33 |
--------------------------------------------------------------------------------
/kubernetes/monitoring/kube-prometheus-stack/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: kube-prometheus-stack
7 | namespace: monitoring
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: kube-prometheus-stack
13 | values:
14 | # https://github.com/prometheus-community/helm-charts/blob/main/charts/kube-prometheus-stack/values.yaml
15 | namespaceOverride: monitoring
16 |
17 | defaultRules:
18 | rules:
19 | kubeControllerManager: false
20 | kubeSchedulerAlerting: false
21 | kubelet: false
22 | disabled:
23 | KubeletPodStartUpLatencyHigh: true
24 | CPUThrottlingHigh: true
25 |
26 | alertmanager:
27 | alertmanagerSpec:
28 | externalUrl: https://am.axis.scottmckendry.tech
29 | replicas: 3
30 | alertmanagerConfiguration:
31 | name: alertmanager
32 | global:
33 | resolveTimeout: 5m
34 |
35 | grafana:
36 | enabled: false
37 | forceDeployDashboards: true
38 |
39 | prometheus:
40 | prometheusSpec:
41 | externalUrl: https://prometheus.axis.scottmckendry.tech
42 | podMonitorSelectorNilUsesHelmValues: false
43 | probeSelectorNilUsesHelmValues: false
44 | ruleSelectorNilUsesHelmValues: false
45 | scrapeConfigSelectorNilUsesHelmValues: false
46 | serviceMonitorSelectorNilUsesHelmValues: false
47 | storageSpec:
48 | volumeClaimTemplate:
49 | spec:
50 | resources:
51 | requests:
52 | storage: 10Gi
53 |
54 | prometheusOperator:
55 | kubeletService:
56 | enabled: false
57 |
58 | kubeEtcd:
59 | service:
60 | selector:
61 | component: kube-apiserver
62 |
63 | kubeProxy:
64 | enabled: false
65 | kubeControllerManager:
66 | enabled: false
67 | kubeScheduler:
68 | enabled: false
69 |
--------------------------------------------------------------------------------
/kubernetes/ccinvoice/backup/backblaze.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: restic-ccinvoice-ccinvoice
7 | namespace: ccinvoice
8 | stringData:
9 | RESTIC_REPOSITORY: ENC[AES256_GCM,data:LcJHV5kRf5+w/AWoNUeSUjFVgrx8ZiP1YvCHZgqsQrGwNoXYytmPIY0ENI7q6flPGHIbk8YoueDAJGAm6MNOPFtu,iv:lIunLI6p0hsELq3rCByC1t6qVnA38pgOyWSAVXAJGFI=,tag:bLrPs449W2MCEsQBhYklBw==,type:str]
10 | RESTIC_PASSWORD: ENC[AES256_GCM,data:6tPA918YTE2vhah4Rg4hqAYXkKfzusEP3extF3j2BF8=,iv:fE9mo0yedEtyNx/Ufe79b1mFSVkcWggdYOf7avYtybY=,tag:RqKFEBj/QAr4DCvOhgvOfA==,type:str]
11 | AWS_ACCESS_KEY_ID: ENC[AES256_GCM,data:RS5Tm+FL3fH30MwW9ga5Il/u/506fkEEAg==,iv:guePuq/xWkBP400fHMvqdY2HJD4DE7LOUzWcX7Xj9pE=,tag:ZkxDg3RJ/LDbL0cP0YgFjQ==,type:str]
12 | AWS_SECRET_ACCESS_KEY: ENC[AES256_GCM,data:/leEx/FDAvfhNaWOxQNaM5Mtv+Jbvp+kdsvYLuq5uQ==,iv:CSG9L/uAB2b8JvwX66qaeyw/G8ilrJjyKFJh08oGicE=,tag:DM1nufX5QoAHTT84TWDJaQ==,type:str]
13 | sops:
14 | kms: []
15 | gcp_kms: []
16 | azure_kv: []
17 | hc_vault: []
18 | age:
19 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
20 | enc: |
21 | -----BEGIN AGE ENCRYPTED FILE-----
22 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1RWprVnFXeFNOcUE1V3FH
23 | ZFd3UTUwWVBIaWZ4NDdsZlAzZW9RRGZRQlhjCkFxL3BQaFBCTGxHZU1zTUJhb3I3
24 | bTdUT25mNG43YndJNy9WWWRvUHlROWsKLS0tIFp4TGVSTlpIeFRUSUxQUStGaHVI
25 | TGVwZ3lGUzVCdFpBWm44WEkrSE1HWm8K7igmamO7bJPa/y1BjfJEjEsD5PHjwRLA
26 | q8LJDlTlUw6NMFcgKDPRewcBZZ7LE07C3BfXqPydyjYvdC224nTryg==
27 | -----END AGE ENCRYPTED FILE-----
28 | lastmodified: "2025-05-05T17:55:07Z"
29 | mac: ENC[AES256_GCM,data:rs4rtzdb1ihziWfTfG1BpONzbGNLe5bARfHGtYONJS04u7FPJmGMCsERMuyV+fLJlPUzkRX8UaEU7YC8lChPy3WCNMrsTbDMfkDhB7Wxu6aQgBNkmE93WnCPJLFhf9inZZ4hDcB7DsXdyIMhI7ATOS1t220eF3UQnG4EhlgifuA=,iv:zWseDP/iM5s1yp5So4WNKEmopGnUKnRf/3F4ExTt1Xo=,tag:rRaRzPzZ2UAXpFF40yc+yg==,type:str]
30 | pgp: []
31 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
32 | version: 3.9.4
33 |
--------------------------------------------------------------------------------
/kubernetes/home-assistant/backup/backblaze.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: restic-home-assistant-home-assistant
7 | namespace: home-assistant
8 | stringData:
9 | RESTIC_REPOSITORY: ENC[AES256_GCM,data:kalc4/rolNfc6Z7Pwi/ZYCg73E9Y9G6Ql8u9XBWIHbYaClhLCacrHU2nAdNSySzuNKocX6ZiaCnE1m3xfxvjWJ48IQPQv+tvpu0Uhw==,iv:mPDco+Y+QF7qgRkiLx+I1408WYL8jsEDZKF7CVNINF4=,tag:y+WIRVqy1TCeYfWJ99S+hQ==,type:str]
10 | RESTIC_PASSWORD: ENC[AES256_GCM,data:EMlmaomWugBoUw8HJuto5e+6hkmM8gW+Xy3Csd3bDTU=,iv:5tEIVEtEnXe/Ko5yfgCeZhClwhYIkV6H3R1DQ+d4Mqk=,tag:f70SfYKiIX5Dh1yxNWhNVQ==,type:str]
11 | AWS_ACCESS_KEY_ID: ENC[AES256_GCM,data:cSfePeQdXJt5wRcs1+pFuPRSMN3IVgCpIg==,iv:DX8PJkb8F8c/hKiUdrc3toqCdCV9kYkeEpVSSX4xOho=,tag:KphhuVaqmb9w6e5/9/dvWw==,type:str]
12 | AWS_SECRET_ACCESS_KEY: ENC[AES256_GCM,data:R/FLAetPFsO/wJl75vDn4LtTb6ym5Z1iZQq6xanmhg==,iv:oKL2rKEWfX4JSWhFP1fxEEY0C0YX3Wzf5R2Q6Uwb63E=,tag:p/ZFeiTStY4Edb8wBqTs9A==,type:str]
13 | sops:
14 | kms: []
15 | gcp_kms: []
16 | azure_kv: []
17 | hc_vault: []
18 | age:
19 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
20 | enc: |
21 | -----BEGIN AGE ENCRYPTED FILE-----
22 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEU2tFTlAzUHpuZXcwSklB
23 | WGZlNnpiUURRVStSNDhGZHdxRTU4T2ZyblZvCmhCWWpSWVh4NWNqV3hQOXI1anJw
24 | SmU5WGd2ZmdkZmw5WmtyYnJZNHVBdkEKLS0tIGExNjNyNXk2enVhMHhnaEdMaCtr
25 | eFNUdmE2ZnByb3E1VWNkRXBGV1hobVEK7xZAP8B9Zspz65AQc1RXT8J93Ss+ynr9
26 | YSxNdLnMzRtiB+HHLkrufk76jztoDg4j+6mfw+jQJ0QO/zP+dE1e6Q==
27 | -----END AGE ENCRYPTED FILE-----
28 | lastmodified: "2025-05-05T17:55:07Z"
29 | mac: ENC[AES256_GCM,data:URLuhdJZbBwxPHKZBMA3CcQnxm4sdgMDvTfGBKgk5OgYwICy9Yhg51X6BggOxvPro8X5NimsnDisaTJ11f50XTHYk53xJoqqkW2XzRHjK2j1ZcV66iGiMp+yr2KflY8uGZclY0WnmzO2A0G8gDJAgaHOzaFNxYwrVUvNl5UqHA8=,iv:TkBAqxnzHS7ztsHdluS50n9Iee3NIjztdyLO7cogIPU=,tag:fF/c9yh/6wRNcYnUj/4RMg==,type:str]
30 | pgp: []
31 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
32 | version: 3.9.4
33 |
--------------------------------------------------------------------------------
/kubernetes/media/qbittorrent/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: qbittorrent
7 | namespace: media
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: app-template
13 | namespace: flux-system
14 | values:
15 | controllers:
16 | qbittorrent:
17 | containers:
18 | app:
19 | image:
20 | repository: ghcr.io/home-operations/qbittorrent
21 | tag: 5.1.4@sha256:25fc7caf22101f85276ede9b1f76a46b7a93971bb6b70b6c58d14d6ab7f51415
22 | env:
23 | TZ: Pacific/Auckland
24 | QBT_WEBUI_PORT: 80
25 | QBT_TORRENTING_PORT: 50413
26 | probes:
27 | liveness:
28 | enabled: true
29 | readiness:
30 | enabled: true
31 | startup:
32 | enabled: true
33 | spec:
34 | failureThreshold: 30
35 | periodSeconds: 10
36 | securityContext:
37 | allowPrivilegeEscalation: false
38 | readOnlyRootFilesystem: true
39 | capabilities: { drop: ["ALL"] }
40 | defaultPodOptions:
41 | securityContext:
42 | runAsNonRoot: true
43 | runAsUser: 1000
44 | runAsGroup: 1000
45 | fsGroup: 1000
46 | fsGroupChangePolicy: OnRootMismatch
47 | service:
48 | app:
49 | controller: qbittorrent
50 | ports:
51 | http:
52 | primary: true
53 | port: 80
54 | bittorrent:
55 | enabled: true
56 | port: 50413
57 | protocol: TCP
58 | persistence:
59 | config:
60 | existingClaim: qbittorrent
61 | downloads:
62 | type: nfs
63 | server: 10.0.6.1
64 | path: /mnt/TrueBlue/media
65 | globalMounts:
66 | - path: /media/Downloads
67 | subPath: Downloads
68 |
--------------------------------------------------------------------------------
/kubernetes/homepage/deployment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/deployment.json
3 | apiVersion: apps/v1
4 | kind: Deployment
5 | metadata:
6 | name: homepage
7 | namespace: homepage
8 | labels:
9 | app.kubernetes.io/name: homepage
10 | spec:
11 | replicas: 1
12 | selector:
13 | matchLabels:
14 | app.kubernetes.io/name: homepage
15 | template:
16 | metadata:
17 | labels:
18 | app.kubernetes.io/name: homepage
19 | spec:
20 | serviceAccountName: homepage
21 | automountServiceAccountToken: true
22 | dnsPolicy: ClusterFirst
23 | enableServiceLinks: true
24 | containers:
25 | - name: homepage
26 | image: ghcr.io/gethomepage/homepage:v1.8.0@sha256:7dc099d5c6ec7fc945d858218565925b01ff8a60bcbfda990fc680a8b5cd0b6e
27 | imagePullPolicy: Always
28 | env:
29 | - name: HOMEPAGE_ALLOWED_HOSTS
30 | value: axis.scottmckendry.tech
31 | ports:
32 | - name: http
33 | containerPort: 3000
34 | protocol: TCP
35 | volumeMounts:
36 | - mountPath: /app/config/bookmarks.yaml
37 | name: homepage-config
38 | subPath: bookmarks.yaml
39 | - mountPath: /app/config/kubernetes.yaml
40 | name: homepage-config
41 | subPath: kubernetes.yaml
42 | - mountPath: /app/config/services.yaml
43 | name: homepage-config
44 | subPath: services.yaml
45 | - mountPath: /app/config/settings.yaml
46 | name: homepage-config
47 | subPath: settings.yaml
48 | - mountPath: /app/config/widgets.yaml
49 | name: homepage-config
50 | subPath: widgets.yaml
51 | - mountPath: /app/config/logs
52 | name: logs
53 | envFrom:
54 | - secretRef:
55 | name: homepage-secrets
56 | volumes:
57 | - name: homepage-config
58 | configMap:
59 | name: homepage
60 | - name: logs
61 | emptyDir: {}
62 |
--------------------------------------------------------------------------------
/kubernetes/gitea/mirror-release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: gitea-mirror
7 | namespace: gitea
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: app-template
13 | namespace: flux-system
14 | values:
15 | defaultPodOptions:
16 | securityContext:
17 | runAsUser: 1000
18 | runAsGroup: 1000
19 | fsGroup: 1000
20 | runAsNonRoot: true
21 | fsGroupChangePolicy: OnRootMismatch
22 | controllers:
23 | gitea-mirror:
24 | containers:
25 | app:
26 | image:
27 | repository: ghcr.io/raylabshq/gitea-mirror
28 | tag: v3.9.2@sha256:6e3edc29884c11a8a7bb3f65adae266d4f51c32d829c857152372e7dba35a410
29 | env:
30 | BETTER_AUTH_URL: https://gitea-mirror.axis.scottmckendry.tech
31 | BETTER_AUTH_TRUSTED_ORIGINS: https://gitea-mirror.axis.scottmckendry.tech
32 | PUBLIC_BETTER_AUTH_URL: https://gitea-mirror.axis.scottmckendry.tech
33 | NODE_ENV: production
34 | DATABASE_URL: file:data/gitea-mirror.db
35 | HOST: 0.0.0.0
36 | PORT: 4321
37 | GITEA_MIRROR_INTERVAL: 24h
38 | envFrom:
39 | - secretRef:
40 | name: gitea-mirror-secret
41 | securityContext:
42 | allowPrivilegeEscalation: false
43 | readOnlyRootFilesystem: true
44 | capabilities: { drop: ["ALL"] }
45 | probes:
46 | readiness:
47 | enabled: true
48 | custom: true
49 | spec:
50 | httpGet:
51 | path: /api/health
52 | port: 4321
53 | initialDelaySeconds: 10
54 | periodSeconds: 30
55 | timeoutSeconds: 5
56 | failureThreshold: 5
57 | service:
58 | app:
59 | controller: gitea-mirror
60 | ports:
61 | http:
62 | port: 4321
63 | persistence:
64 | data:
65 | existingClaim: gitea-mirror-data
66 | globalMounts:
67 | - path: /app/data
68 |
--------------------------------------------------------------------------------
/kubernetes/traefik/tinyauth.secret.sops.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/secret.json
2 | apiVersion: v1
3 | kind: Secret
4 | type: Opaque
5 | metadata:
6 | name: tinyauth-secrets
7 | namespace: traefik
8 | labels:
9 | app.kubernetes.io/name: tinyauth
10 | stringData:
11 | APP_URL: ENC[AES256_GCM,data:4taYWBSFplQA2CgM9+1K2fTAsHq0NmdTRy/Ts0sCcd9tekb5,iv:AcHNeVHlr9fdOUmq7iLZXDmBNIRXjhKklCl61PpeG6k=,tag:ZXGQkXflMNrMBaGehK8R0Q==,type:str]
12 | PROVIDERS_GITHUB_CLIENT_ID: ENC[AES256_GCM,data:UBEtbCZeLl3Fm5Td+d1IYqYNf4o=,iv:juvqkjkUX+NIMOmeVDf6gc3KIkRsbT+XVD6ahSWzxYc=,tag:TnB5BmnynhwG3YrWsp6kig==,type:str]
13 | PROVIDERS_GITHUB_CLIENT_SECRET: ENC[AES256_GCM,data:mylE4x3wY0Ij15Q0GLHnrhPi6e1jAsMzrJtf1lYSn61qv0m1MiXusg==,iv:Xm2CtUv/m1LAEsWku/VkdzezJNHtpM+FVcLgKbVzhnY=,tag:QeWu04u57+u7MM8seZBVaw==,type:str]
14 | OAUTH_WHITELIST: ENC[AES256_GCM,data:FG9kjxgA1Ht4+L6Bg/8LJ3qwMYEl,iv:uj5ndrtxfkw+WFB7g4SM9KL66xlhLzxo3MCWVUiDgIE=,tag:WK7/Q9FpOvazjBQnu0vLBg==,type:str]
15 | DISABLE_CONTINUE: ENC[AES256_GCM,data:MJiDfg==,iv:aC4vfktIUS89us0P50MO4YUUXrnD8CqJddtkJR7vmLE=,tag:Ll0JdeUfUbO9E/BATyVFsg==,type:str]
16 | SESSION_EXPIRY: ENC[AES256_GCM,data:wx12o00s,iv:9ht/f5nE0T7IZmhFCJw6FhAyZX6zjQ9QyA2JbCxqasE=,tag:FgTQMss6K7dxz786X+6j1Q==,type:str]
17 | APP_TITLE: ENC[AES256_GCM,data:h6/iyw==,iv:Hy8URsYX1p1HKRrFylJDF/tKREbxQF/ffjYdx4/Atm0=,tag:4NG67a98I15FYCZyQlwFfA==,type:str]
18 | sops:
19 | age:
20 | - recipient: age1ht2mpnqakafawr4akvukz2ketzdlwuwkhdzwsy8hl7rwfkhkh90qp36und
21 | enc: |
22 | -----BEGIN AGE ENCRYPTED FILE-----
23 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuV211YnRlbVpVZVhBQ0FF
24 | SThOM0o2Vy9sdVFWV0gySDNYekNkZ1hXVEdzCjQvVnp4dWpMVmc4RkhxM0pOaDJu
25 | U2kyLzF0aXppSUFFYmdqR2kzVEZoUEkKLS0tIFZjNVI1VkdvZ0pqNlNkT0VTM2R1
26 | b0UxT3JoMGMwUGc3M2JoTkd5YmJaOVkKtJidi5EIKHyu2pvn+kNZRpq+K+ShpkmR
27 | iGkJywE7Qcja3DT/bF05CXiQpaA4uLM6kiQu5oSTbm+J4q8DZxXLWw==
28 | -----END AGE ENCRYPTED FILE-----
29 | lastmodified: "2025-10-12T06:20:33Z"
30 | mac: ENC[AES256_GCM,data:XQ4ehL3omKpeX+k97Nu5W9LoeBVDPy4bs5zMIoaVWGmzOO1BxWFmp50Fp4IgUHyYmu/pHKWM1pTDje+ZHfg8M0Vgp2DziO3OxJ8SkPrAFQCMTfDbYS5LgPOW+tVhR6yF+3OjNMGOvVdyiAV2qZrMVM/DAwIOCA/gZzen4OOOzJk=,iv:O+UCtvARKyydgWEwj2EJsqcRYOUXha5IVu7u+7GKEU0=,tag:93x618eBE9aJJ8MPdsDQeA==,type:str]
31 | encrypted_regex: ^(data|stringData|email|host|apiKey)$
32 | version: 3.11.0
33 |
--------------------------------------------------------------------------------
/kubernetes/traefik/tinyauth.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/deployment.json
3 | apiVersion: apps/v1
4 | kind: Deployment
5 | metadata:
6 | name: tinyauth
7 | namespace: traefik
8 | labels:
9 | app: tinyauth
10 | spec:
11 | replicas: 1
12 | selector:
13 | matchLabels:
14 | app: tinyauth
15 | template:
16 | metadata:
17 | labels:
18 | app: tinyauth
19 | spec:
20 | # securityContext:
21 | # fsGroup: 1000
22 | # fsGroupChangePolicy: OnRootMismatch
23 | containers:
24 | - name: tinyauth
25 | image: ghcr.io/steveiliop56/tinyauth
26 | tag: v4.0.1@sha256:815a53c517b4b8f29c02245fc89185186d12162f6bfc2e7566acf888c72ff14b
27 | securityContext:
28 | runAsUser: 1000
29 | runAsGroup: 1000
30 | allowPrivilegeEscalation: false
31 | runAsNonRoot: true
32 | capabilities:
33 | drop: ["ALL"]
34 | seccompProfile:
35 | type: RuntimeDefault
36 | ports:
37 | - containerPort: 3000
38 | envFrom:
39 | - secretRef:
40 | name: tinyauth-secrets
41 | volumeMounts:
42 | - name: data
43 | mountPath: /data
44 | livenessProbe:
45 | httpGet:
46 | path: /api/healthz
47 | port: 3000
48 | readinessProbe:
49 | httpGet:
50 | path: /api/healthz
51 | port: 3000
52 | volumes:
53 | - name: data
54 | emptyDir: {}
55 | ---
56 | # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master/service.json
57 | apiVersion: v1
58 | kind: Service
59 | metadata:
60 | name: tinyauth
61 | namespace: traefik
62 | spec:
63 | ports:
64 | - port: 3000
65 | targetPort: 3000
66 | protocol: TCP
67 | selector:
68 | app: tinyauth
69 | ---
70 | # yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json
71 | apiVersion: traefik.io/v1alpha1
72 | kind: IngressRoute
73 | metadata:
74 | name: tinyauth
75 | namespace: traefik
76 | spec:
77 | routes:
78 | - match: Host(`auth.axis.scottmckendry.tech`)
79 | kind: Rule
80 | services:
81 | - name: tinyauth
82 | namespace: traefik
83 | port: 3000
84 | tls:
85 | secretName: axis-tls
86 |
--------------------------------------------------------------------------------
/kubernetes/home-assistant/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 | apiVersion: helm.toolkit.fluxcd.io/v2
4 | kind: HelmRelease
5 | metadata:
6 | name: home-assistant
7 | namespace: home-assistant
8 | spec:
9 | interval: 1h
10 | chartRef:
11 | kind: OCIRepository
12 | name: app-template
13 | namespace: flux-system
14 | values:
15 | defaultPodOptions:
16 | securityContext:
17 | runAsNonRoot: true
18 | runAsUser: 1000
19 | runAsGroup: 1000
20 | fsGroup: 1000
21 | fsGroupChangePolicy: OnRootMismatch
22 |
23 | controllers:
24 | home-assistant:
25 | containers:
26 | app:
27 | image:
28 | repository: ghcr.io/home-operations/home-assistant
29 | tag: 2025.12.4@sha256:c1743f2ed4c2cac05693525d477b73fb45386100660f3f1d6ac23b1720f48023
30 | securityContext:
31 | allowPrivilegeEscalation: false
32 | readOnlyRootFilesystem: true
33 | capabilities: { drop: ["ALL"] }
34 | code:
35 | dependsOn:
36 | - app
37 | image:
38 | repository: ghcr.io/coder/code-server
39 | tag: 4.107.0@sha256:4b622c4cd1b0f559fec0df67fcf09042d63e9ce84c575102066afd9511695627
40 | args:
41 | - --auth
42 | - "none"
43 | - --user-data-dir
44 | - "/config/.vscode"
45 | - --extensions-dir
46 | - "/config/.vscode"
47 | - --port
48 | - "8081"
49 | - "/config"
50 |
51 | service:
52 | app:
53 | controller: home-assistant
54 | ports:
55 | http:
56 | port: 8123
57 | code:
58 | controller: home-assistant
59 | ports:
60 | http:
61 | port: 8081
62 | persistence:
63 | config:
64 | existingClaim: home-assistant
65 | globalMounts:
66 | - path: /config
67 | config-cache:
68 | existingClaim: home-assistant-cache
69 | globalMounts:
70 | - path: /config/.venv
71 | config-logs:
72 | type: emptyDir
73 | globalMounts:
74 | - path: /config/logs
75 | config-tts:
76 | type: emptyDir
77 | globalMounts:
78 | - path: /config/tts
79 | tmp:
80 | type: emptyDir
81 | globalMounts:
82 | - path: /tmp
83 |
--------------------------------------------------------------------------------
/scripts/sops.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # 🔐 SOPS Encryption/Decryption Helper
4 | # Manages secret files in the repository using SOPS
5 |
6 | set -euo pipefail
7 |
8 | RED='\033[0;31m'
9 | GREEN='\033[0;32m'
10 | BLUE='\033[0;34m'
11 | BOLD='\033[1m'
12 | NC='\033[0m' # No Color
13 |
14 | check_dependencies() {
15 | local missing_deps=()
16 | command -v sops >/dev/null 2>&1 || missing_deps+=("sops")
17 | command -v age >/dev/null 2>&1 || missing_deps+=("age")
18 |
19 | if [ ${#missing_deps[@]} -ne 0 ]; then
20 | echo -e "${RED}Error: Missing required dependencies: ${missing_deps[*]}${NC}"
21 | exit 1
22 | fi
23 | }
24 |
25 | check_age_keys() {
26 | local config_dir="${XDG_CONFIG_HOME:-$HOME/.config}"
27 | local keys_path="$config_dir/sops/age/keys.txt"
28 |
29 | if [ ! -f "$keys_path" ]; then
30 | echo -e "${RED}Error: Age keys file not found at: $keys_path${NC}"
31 | exit 1
32 | fi
33 | }
34 |
35 | usage() {
36 | cat <
2 |
8 | Automated eXperimental Infrastructure System
9 |
5 | AXIS
7 |