Compare commits
7
Commits
45948bfe7f
...
fa8ca940f1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa8ca940f1 | ||
|
|
7a560f6f97 | ||
|
|
39bda3c129 | ||
|
|
3e6f09720e | ||
|
|
1e35db8b4d | ||
|
|
76c7cfa39b | ||
|
|
2c86598ace |
+12
-13
@@ -1,16 +1,15 @@
|
|||||||
media/
|
|
||||||
default/*tt*
|
|
||||||
default/havenllo*
|
|
||||||
certs/ca*
|
|
||||||
|
|
||||||
lab/*
|
|
||||||
sandbox/*
|
|
||||||
!lab/nfs-pod.yaml
|
|
||||||
|
|
||||||
rbac
|
|
||||||
cronjobs
|
|
||||||
|
|
||||||
*.crt
|
*.crt
|
||||||
*.key
|
*.key
|
||||||
|
*.pem
|
||||||
|
*.pfx
|
||||||
|
|
||||||
chacal/
|
# Secrets & Environment files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
*.env
|
||||||
|
group_vars/**/vault.yml
|
||||||
|
!group_vars/**/vault.yml.example
|
||||||
|
*kubeconfig*
|
||||||
|
|
||||||
|
# Ansible artifacts
|
||||||
|
*.retry
|
||||||
|
|||||||
@@ -12,57 +12,25 @@ For setup details, see [SETUP.md](SETUP.md).
|
|||||||
|
|
||||||
The repository name references my local TLD, `.haven` ;)
|
The repository name references my local TLD, `.haven` ;)
|
||||||
|
|
||||||
## Namespaces
|
## Repository Layout
|
||||||
- default
|
```
|
||||||
- ArchiveBox
|
haven/
|
||||||
- Homarr
|
├── bootstrap/
|
||||||
- Homepage
|
│ ├── namespaces.yaml # cluster namespaces
|
||||||
- It-tools
|
│ ├── secretstores.yaml # cluster secret stores for BitWarden ESO
|
||||||
- Notepad
|
│ ├── address-pool.yaml # cluster IP pool for MetalLB
|
||||||
- Searxng
|
│ ├── argocd-install/ # Argo CD install manifests + ingress
|
||||||
- Uptimekuma
|
│ └── root-app.yaml # root Application watching apps/root
|
||||||
- Vaultwarden
|
├── secrets/
|
||||||
- OpenWebUI
|
│ ├── adguard.yaml # adguard credentials from BitWarden
|
||||||
- Paperless
|
│ ├── <app>.yaml # <app> credentials from BitWarden
|
||||||
- cloud
|
│ └── ...
|
||||||
- Cloudreve
|
├── apps/
|
||||||
- Slink
|
│ ├── root/
|
||||||
- dns
|
│ │ ├── kustomization.yaml # points to applicationset.yaml
|
||||||
- AdGuardHome
|
│ │ └── applicationset.yaml# auto-discovers apps/*/*.yaml
|
||||||
- AdGuardSync
|
│ └── <namespace>/ # e.g., dev/, default/, infra/, monitoring/
|
||||||
- infra
|
│ ├── <app-1>.yaml # all-in-one manifest per app
|
||||||
- [Haven Notify](https://git.ivanch.me/ivanch/server-scripts/src/branch/main/haven-notify)
|
│ ├── <app-2>.yaml # ...
|
||||||
- Beszel
|
| └──── ...
|
||||||
- Beszel Agent (running as a DaemonSet)
|
```
|
||||||
- Code Config (VS Code for internal config editing)
|
|
||||||
- WireGuard Easy
|
|
||||||
- dev
|
|
||||||
- Gitea Runner (x64)
|
|
||||||
- Gitea Runner (arm64)
|
|
||||||
- monitoring
|
|
||||||
- Grafana
|
|
||||||
- Prometheus
|
|
||||||
- Node Exporter
|
|
||||||
- Kube State Metrics
|
|
||||||
- Loki
|
|
||||||
- Alloy
|
|
||||||
|
|
||||||
#### Miscellaneous namespaces
|
|
||||||
|
|
||||||
- lab (a playground/sandbox namespace)
|
|
||||||
- nfs-pod (for testing and accessing NFS mounts)
|
|
||||||
- metallb-system
|
|
||||||
- MetalLB components
|
|
||||||
- cert-manager
|
|
||||||
- cert-manager components
|
|
||||||
- docker-ingress
|
|
||||||
- nginx ingress controller components for Docker-based services
|
|
||||||
|
|
||||||
## Todo
|
|
||||||
- Move ArchiveBox data to its own PVC on the NAS
|
|
||||||
- Move Uptime Kuma to the infra namespace
|
|
||||||
- Add links to each application's documentation
|
|
||||||
- Add links to server scripts
|
|
||||||
- Move Alloy to the monitoring namespace
|
|
||||||
- Install Loki, Grafana, and Prometheus via Helm charts
|
|
||||||
- Configure Loki and Prometheus to use PVCs
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
# Helm configuration for Alloy (OSS monitoring collector)
|
|
||||||
|
|
||||||
This directory contains Helm configuration for deploying Grafana Alloy, an open-source observability data collector.
|
|
||||||
|
|
||||||
## Quick Install
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm repo add grafana https://grafana.github.io/helm-charts
|
|
||||||
helm repo update
|
|
||||||
helm install alloy grafana/alloy --namespace alloy -f values.yaml
|
|
||||||
```
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
alloy:
|
|
||||||
clustering:
|
|
||||||
enabled: false # Single node deployment
|
|
||||||
|
|
||||||
configMap:
|
|
||||||
create: true
|
|
||||||
content: |-
|
|
||||||
discovery.kubernetes "all_pods" {
|
|
||||||
role = "pod"
|
|
||||||
|
|
||||||
selectors {
|
|
||||||
role = "pod"
|
|
||||||
field = "spec.nodeName=" + coalesce(env("HOSTNAME"), constants.hostname)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
discovery.relabel "all_pods" {
|
|
||||||
targets = discovery.kubernetes.all_pods.targets
|
|
||||||
|
|
||||||
rule {
|
|
||||||
source_labels = ["__meta_kubernetes_namespace"]
|
|
||||||
target_label = "namespace"
|
|
||||||
}
|
|
||||||
rule {
|
|
||||||
source_labels = ["__meta_kubernetes_pod_name"]
|
|
||||||
target_label = "pod"
|
|
||||||
}
|
|
||||||
rule {
|
|
||||||
source_labels = ["__meta_kubernetes_pod_container_name"]
|
|
||||||
target_label = "container"
|
|
||||||
}
|
|
||||||
rule {
|
|
||||||
source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"]
|
|
||||||
target_label = "app"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loki.source.kubernetes "all_logs" {
|
|
||||||
targets = discovery.relabel.all_pods.output
|
|
||||||
forward_to = [loki.write.main.receiver]
|
|
||||||
}
|
|
||||||
|
|
||||||
discovery.kubernetes "shared_pods" {
|
|
||||||
role = "pod"
|
|
||||||
selectors {
|
|
||||||
role = "pod"
|
|
||||||
field = "metadata.namespace=chacal"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
discovery.relabel "shared_pods" {
|
|
||||||
targets = discovery.kubernetes.shared_pods.targets
|
|
||||||
|
|
||||||
rule {
|
|
||||||
source_labels = ["__meta_kubernetes_namespace"]
|
|
||||||
target_label = "namespace"
|
|
||||||
}
|
|
||||||
rule {
|
|
||||||
source_labels = ["__meta_kubernetes_pod_name"]
|
|
||||||
target_label = "pod"
|
|
||||||
}
|
|
||||||
rule {
|
|
||||||
source_labels = ["__meta_kubernetes_pod_container_name"]
|
|
||||||
target_label = "container"
|
|
||||||
}
|
|
||||||
rule {
|
|
||||||
source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"]
|
|
||||||
target_label = "app"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loki.source.kubernetes "shared_logs" {
|
|
||||||
targets = discovery.relabel.shared_pods.output
|
|
||||||
forward_to = [loki.write.shared.receiver]
|
|
||||||
}
|
|
||||||
|
|
||||||
loki.write "main" {
|
|
||||||
endpoint {
|
|
||||||
url = "http://loki.monitoring.svc.cluster.local:3100/loki/api/v1/push"
|
|
||||||
headers = {
|
|
||||||
"X-Scope-OrgID" = "main",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loki.write "shared" {
|
|
||||||
endpoint {
|
|
||||||
url = "http://loki.monitoring.svc.cluster.local:3100/loki/api/v1/push"
|
|
||||||
headers = {
|
|
||||||
"X-Scope-OrgID" = "chacal",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mounts:
|
|
||||||
varlog: true # Mount host /var/log for pod logs
|
|
||||||
|
|
||||||
controller:
|
|
||||||
type: daemonset # Run on every node
|
|
||||||
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 128Mi
|
|
||||||
limits:
|
|
||||||
cpu: 200m
|
|
||||||
memory: 256Mi
|
|
||||||
@@ -33,6 +33,10 @@ all:
|
|||||||
ansible_host: nexus.haven
|
ansible_host: nexus.haven
|
||||||
ansible_user: root
|
ansible_user: root
|
||||||
ansible_python_interpreter: /usr/bin/python3
|
ansible_python_interpreter: /usr/bin/python3
|
||||||
|
polaris:
|
||||||
|
ansible_host: polaris.haven
|
||||||
|
ansible_user: root
|
||||||
|
ansible_python_interpreter: /usr/bin/python3
|
||||||
lxcs:
|
lxcs:
|
||||||
children:
|
children:
|
||||||
grp_docker_build: # group name == group_vars/grp_docker_build.yml
|
grp_docker_build: # group name == group_vars/grp_docker_build.yml
|
||||||
|
|||||||
@@ -57,6 +57,45 @@
|
|||||||
name: k3s-agent
|
name: k3s-agent
|
||||||
state: restarted
|
state: restarted
|
||||||
|
|
||||||
|
- name: Fetch authoritative CA bundle from control-plane
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: /var/lib/rancher/k3s/server/tls/{{ item }}
|
||||||
|
delegate_to: "{{ groups['grp_k3s_server'][0] }}"
|
||||||
|
register: ca_bundle
|
||||||
|
loop:
|
||||||
|
- client-ca.crt
|
||||||
|
- server-ca.crt
|
||||||
|
|
||||||
|
- name: Install server CAs into agent trust store
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "/var/lib/rancher/k3s/agent/{{ item.item }}"
|
||||||
|
content: "{{ item.content | b64decode }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0600"
|
||||||
|
loop: "{{ ca_bundle.results }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.item }}"
|
||||||
|
|
||||||
|
- name: Stop agent and clear stale client certs signed by old CA
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
systemctl stop k3s-agent
|
||||||
|
rm -f /var/lib/rancher/k3s/agent/client-kubelet.crt \
|
||||||
|
/var/lib/rancher/k3s/agent/client-k3s-controller.crt \
|
||||||
|
/var/lib/rancher/k3s/agent/client-kube-proxy.crt \
|
||||||
|
/var/lib/rancher/k3s/agent/serving-kubelet.crt \
|
||||||
|
/var/lib/rancher/k3s/agent/kubelet.kubeconfig \
|
||||||
|
/var/lib/rancher/k3s/agent/k3scontroller.kubeconfig \
|
||||||
|
/var/lib/rancher/k3s/agent/kubeproxy.kubeconfig \
|
||||||
|
/var/lib/rancher/k3s/agent/client-kubeconfig.yaml
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
|
||||||
|
- name: Restart k3s-agent so it re-issues certs against the server CA
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: k3s-agent
|
||||||
|
state: restarted
|
||||||
|
|
||||||
- name: Print update output
|
- name: Print update output
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
var: k3s_update
|
var: k3s_update
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
chart: true
|
||||||
|
metadata:
|
||||||
|
name: alloy
|
||||||
|
namespace: argocd
|
||||||
|
finalizers: [resources-finalizer.argocd.argoproj.io]
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: alloy
|
||||||
|
syncPolicy:
|
||||||
|
automated: { prune: true, selfHeal: true }
|
||||||
|
syncOptions: [CreateNamespace=true, ServerSideApply=true]
|
||||||
|
source:
|
||||||
|
repoURL: https://grafana.github.io/helm-charts
|
||||||
|
chart: alloy
|
||||||
|
targetRevision: 1.12.1
|
||||||
|
helm:
|
||||||
|
valuesObject:
|
||||||
|
controller:
|
||||||
|
type: daemonset
|
||||||
|
alloy:
|
||||||
|
clustering: { enabled: false }
|
||||||
|
mounts:
|
||||||
|
varlog: true
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
configMap:
|
||||||
|
create: true
|
||||||
|
content: |-
|
||||||
|
discovery.kubernetes "all_pods" {
|
||||||
|
role = "pod"
|
||||||
|
|
||||||
|
selectors {
|
||||||
|
role = "pod"
|
||||||
|
field = "spec.nodeName=" + coalesce(env("HOSTNAME"), constants.hostname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
discovery.relabel "all_pods" {
|
||||||
|
targets = discovery.kubernetes.all_pods.targets
|
||||||
|
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_kubernetes_namespace"]
|
||||||
|
target_label = "namespace"
|
||||||
|
}
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_kubernetes_pod_name"]
|
||||||
|
target_label = "pod"
|
||||||
|
}
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_kubernetes_pod_container_name"]
|
||||||
|
target_label = "container"
|
||||||
|
}
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"]
|
||||||
|
target_label = "app"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loki.source.kubernetes "all_logs" {
|
||||||
|
targets = discovery.relabel.all_pods.output
|
||||||
|
forward_to = [loki.write.main.receiver]
|
||||||
|
}
|
||||||
|
|
||||||
|
discovery.kubernetes "shared_pods" {
|
||||||
|
role = "pod"
|
||||||
|
selectors {
|
||||||
|
role = "pod"
|
||||||
|
field = "metadata.namespace=chacal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
discovery.relabel "shared_pods" {
|
||||||
|
targets = discovery.kubernetes.shared_pods.targets
|
||||||
|
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_kubernetes_namespace"]
|
||||||
|
target_label = "namespace"
|
||||||
|
}
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_kubernetes_pod_name"]
|
||||||
|
target_label = "pod"
|
||||||
|
}
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_kubernetes_pod_container_name"]
|
||||||
|
target_label = "container"
|
||||||
|
}
|
||||||
|
rule {
|
||||||
|
source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"]
|
||||||
|
target_label = "app"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loki.source.kubernetes "shared_logs" {
|
||||||
|
targets = discovery.relabel.shared_pods.output
|
||||||
|
forward_to = [loki.write.shared.receiver]
|
||||||
|
}
|
||||||
|
|
||||||
|
loki.write "main" {
|
||||||
|
endpoint {
|
||||||
|
url = "http://loki.monitoring.svc.cluster.local:3100/loki/api/v1/push"
|
||||||
|
headers = {
|
||||||
|
"X-Scope-OrgID" = "main",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loki.write "shared" {
|
||||||
|
endpoint {
|
||||||
|
url = "http://loki.monitoring.svc.cluster.local:3100/loki/api/v1/push"
|
||||||
|
headers = {
|
||||||
|
"X-Scope-OrgID" = "chacal",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# Auth (Authentik + Kyverno SSO annotation policy)
|
||||||
|
|
||||||
|
Draft manifests only — nothing applied yet. Convention: any Ingress annotated
|
||||||
|
with `use-sso-auth: "true"` gets the Authentik forward-auth annotations injected
|
||||||
|
by the Kyverno ClusterPolicy (`auth/sso-auth-policy.yaml`).
|
||||||
|
|
||||||
|
## Deploy order
|
||||||
|
|
||||||
|
1. **Authentik** (`auth/authentik.yaml`) — IdP + embedded outpost. Needs a
|
||||||
|
Postgres user/DB on postgresql.haven first (see below), plus secrets from
|
||||||
|
Vaultwarden/ESO.
|
||||||
|
2. **Proxy provider** — create in Authentik UI (or via API) once it's up:
|
||||||
|
one provider per app you want header-auth'd, mode "forward_auth (single
|
||||||
|
app)", or a domain-level provider with the embedded outpost.
|
||||||
|
3. **Kyverno** (`auth/kyverno-helm.yaml`) — policy engine.
|
||||||
|
4. **SSO policy** (`auth/sso-auth-policy.yaml`) — expands `use-sso-auth: "true"`
|
||||||
|
into `auth-url` / `auth-signin` / `auth-response-headers` annotations.
|
||||||
|
5. Annotate ingresses: `kubectl annotate ingress <name> -n <ns> use-sso-auth=true`
|
||||||
|
and mirror the change in this repo.
|
||||||
|
|
||||||
|
## Postgres bootstrap (one-time, on postgresql.haven)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE USER authentik WITH PASSWORD '<from-vaultwarden>';
|
||||||
|
CREATE DATABASE authentik OWNER authentik;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Outpost URL used everywhere is `https://auth.haven` — add DNS + ingress for
|
||||||
|
the outpost before annotating anything.
|
||||||
|
- Apps that should *consume* the injected `X-Authentik-*` headers (Grafana auth
|
||||||
|
proxy, Paperless remote-user, OpenWebUI trusted headers) need their own env
|
||||||
|
changes; those are app-side, not covered by the policy.
|
||||||
|
- API/WebSocket-heavy apps (arr stack, qBittorrent) should NOT get the
|
||||||
|
annotation on API paths — either skip the annotation or exclude paths.
|
||||||
|
|
||||||
|
## Which apps get the annotation (scoping)
|
||||||
|
|
||||||
|
Three tiers, applied per ingress — never blanket:
|
||||||
|
|
||||||
|
1. **OIDC tier** (no annotation, wire native OIDC in the app instead):
|
||||||
|
grafana, paperless, affine, openwebui, vaultwarden, beszel, slink.
|
||||||
|
Proper logout, group mapping, zero API breakage.
|
||||||
|
2. **Forward-auth tier** (`use-sso-auth: "true"`): browser-only utilities with
|
||||||
|
no real auth — it-tools, notepad, searxng, homepage, archivebox,
|
||||||
|
stirlingpdf, file-nginx, code-config, havenllo, own apps (chacal,
|
||||||
|
mindforge) if wanted.
|
||||||
|
3. **Hands off** (built-in auth is fine, forward-auth breaks clients):
|
||||||
|
sonarr, radarr, prowlarr, qbittorrent, adguard, changedetection,
|
||||||
|
uptimekuma, cloudreve (WebDAV), jellyfin (clients can't do redirects —
|
||||||
|
only the community SSO plugin route exists).
|
||||||
|
|
||||||
|
## Pre-annotation checklist (per new app)
|
||||||
|
|
||||||
|
Forward-auth breakage is loud and immediate if you look in the right places.
|
||||||
|
Before annotating any real hostname:
|
||||||
|
|
||||||
|
1. **Ask: what talks to this app that isn't a human in a browser?**
|
||||||
|
Mobile/desktop apps with own login, API-key consumers, push/webhook
|
||||||
|
receivers, cronjobs curling through the ingress, WebDAV/RSS → any of
|
||||||
|
those = hands off (tier 3) or exclude paths. "Just me in a browser" =
|
||||||
|
safe.
|
||||||
|
2. **Canary first:** create a scratch ingress for the same service
|
||||||
|
(`<app>-test.haven`) with the annotation; leave the original untouched
|
||||||
|
for ~a week. Forgotten integrations keep hitting the original and only
|
||||||
|
break the canary — instant rollback
|
||||||
|
(`kubectl annotate ingress <n> -n <ns> use-sso-auth-`).
|
||||||
|
3. **Grep the docs** (30s): "reverse proxy", "trusted header", "API key",
|
||||||
|
"webhook", "basic auth". A "running behind a reverse proxy" doc section
|
||||||
|
is where landmines are documented.
|
||||||
|
4. **Header-trust hygiene:** apps consuming `X-Authentik-*` must be
|
||||||
|
reachable ONLY through the ingress (no NodePort/exposed port, otherwise
|
||||||
|
LAN clients can forge headers straight to the pod). Keep built-in local
|
||||||
|
login enabled; never set SSO-only mode.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `kyverno-helm.yaml` — Kyverno install values
|
||||||
|
- `sso-auth-policy.yaml` — ClusterPolicy: `use-sso-auth` → nginx auth annotations
|
||||||
|
- `authentik.yaml` — Authentik server/worker + outpost, Postgres PVC, ingress
|
||||||
|
|
||||||
|
## Status / when to actually deploy this (decision from 2026-08-28)
|
||||||
|
|
||||||
|
NOT deployed — deliberate. Sole user, low login frequency, everything
|
||||||
|
reachable via wg-easy, so SSO solves a problem that doesn't exist. The
|
||||||
|
`*.ivanch.me` public ingresses were reviewed instead: exposure without usage
|
||||||
|
is pure risk, and the right fix is removing exposure (VPN-only), not adding
|
||||||
|
an IdP.
|
||||||
|
|
||||||
|
Pull the trigger only if one of these becomes true:
|
||||||
|
|
||||||
|
1. A second person uses the homelab regularly (SSO value scales with users).
|
||||||
|
2. Something must be exposed that can't sit behind VPN (third-party
|
||||||
|
webhooks/callbacks) — then public tier gets `use-sso-auth` + 2FA.
|
||||||
|
3. Login friction on the OIDC apps (grafana/paperless/affine/openwebui/
|
||||||
|
vaultwarden/beszel/slink) actually annoys on a weekly basis.
|
||||||
|
|
||||||
|
Until then this folder is a shelf-ready draft; cost of keeping it is zero.
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
# Authentik — IdP + embedded outpost (proxy provider forward-auth).
|
||||||
|
# Draft — do NOT apply as-is:
|
||||||
|
# - secret values are placeholders; create them from Vaultwarden/ESO first
|
||||||
|
# - requires the authentik user/DB on postgresql.haven (see README.md)
|
||||||
|
# - requires DNS record for auth.haven -> ingress IP (user manages DNS)
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: authentik-secrets
|
||||||
|
namespace: auth
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
postgres_password: "CHANGE_ME" # Vaultwarden -> ESO later
|
||||||
|
secret_key: "CHANGE_ME" # `openssl rand -base64 60`
|
||||||
|
bootstrap_password: "CHANGE_ME" # initial akadmin password
|
||||||
|
bootstrap_token: "CHANGE_ME" # outpost token
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: authentik-media
|
||||||
|
namespace: auth
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
storageClassName: nfs-fast-client # verified: exists in cluster (nfs-client is also default)
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
---
|
||||||
|
# Server (web + API)
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: authentik-server
|
||||||
|
namespace: auth
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels: { app: authentik, component: server }
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: { app: authentik, component: server }
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: ghcr.io/goauthentik/server:2026.8
|
||||||
|
args: [server]
|
||||||
|
env:
|
||||||
|
- name: AUTHENTIK_SECRET_KEY
|
||||||
|
valueFrom:
|
||||||
|
{ secretKeyRef: { name: authentik-secrets, key: secret_key } }
|
||||||
|
- name: AUTHENTIK_POSTGRESQL__HOST
|
||||||
|
value: postgresql.haven
|
||||||
|
- name: AUTHENTIK_POSTGRESQL__NAME
|
||||||
|
value: authentik
|
||||||
|
- name: AUTHENTIK_POSTGRESQL__USER
|
||||||
|
value: authentik
|
||||||
|
- name: AUTHENTIK_POSTGRESQL__PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
{
|
||||||
|
secretKeyRef:
|
||||||
|
{ name: authentik-secrets, key: postgres_password },
|
||||||
|
}
|
||||||
|
- name: AUTHENTIK_BOOTSTRAP_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
{
|
||||||
|
secretKeyRef:
|
||||||
|
{ name: authentik-secrets, key: bootstrap_password },
|
||||||
|
}
|
||||||
|
- name: AUTHENTIK_BOOTSTRAP_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
{
|
||||||
|
secretKeyRef:
|
||||||
|
{ name: authentik-secrets, key: bootstrap_token },
|
||||||
|
}
|
||||||
|
- name: AUTHENTIK_ERROR_REPORTING__ENABLED
|
||||||
|
value: "false"
|
||||||
|
ports:
|
||||||
|
- { containerPort: 9000, name: http }
|
||||||
|
- { containerPort: 9443, name: https }
|
||||||
|
readinessProbe:
|
||||||
|
httpGet: { path: /-/health/ready/, port: 9000 }
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 10
|
||||||
|
livenessProbe:
|
||||||
|
httpGet: { path: /-/health/live/, port: 9000 }
|
||||||
|
initialDelaySeconds: 40
|
||||||
|
periodSeconds: 20
|
||||||
|
resources:
|
||||||
|
requests: { cpu: 250m, memory: 512Mi }
|
||||||
|
limits: { memory: 1Gi, cpu: 1000m }
|
||||||
|
volumeMounts:
|
||||||
|
- { name: media, mountPath: /media }
|
||||||
|
volumes:
|
||||||
|
- name: media
|
||||||
|
persistentVolumeClaim: { claimName: authentik-media }
|
||||||
|
---
|
||||||
|
# Worker (policies, outpost management, scheduled tasks)
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: authentik-worker
|
||||||
|
namespace: auth
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels: { app: authentik, component: worker }
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: { app: authentik, component: worker }
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: worker
|
||||||
|
image: ghcr.io/goauthentik/server:2026.8
|
||||||
|
args: [worker]
|
||||||
|
env: # same env as server; kept duplicated for a flat draft manifest
|
||||||
|
- name: AUTHENTIK_SECRET_KEY
|
||||||
|
valueFrom:
|
||||||
|
{ secretKeyRef: { name: authentik-secrets, key: secret_key } }
|
||||||
|
- name: AUTHENTIK_POSTGRESQL__HOST
|
||||||
|
value: postgresql.haven
|
||||||
|
- name: AUTHENTIK_POSTGRESQL__NAME
|
||||||
|
value: authentik
|
||||||
|
- name: AUTHENTIK_POSTGRESQL__USER
|
||||||
|
value: authentik
|
||||||
|
- name: AUTHENTIK_POSTGRESQL__PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
{
|
||||||
|
secretKeyRef:
|
||||||
|
{ name: authentik-secrets, key: postgres_password },
|
||||||
|
}
|
||||||
|
- name: AUTHENTIK_BOOTSTRAP_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
{
|
||||||
|
secretKeyRef:
|
||||||
|
{ name: authentik-secrets, key: bootstrap_password },
|
||||||
|
}
|
||||||
|
- name: AUTHENTIK_BOOTSTRAP_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
{
|
||||||
|
secretKeyRef:
|
||||||
|
{ name: authentik-secrets, key: bootstrap_token },
|
||||||
|
}
|
||||||
|
- name: AUTHENTIK_ERROR_REPORTING__ENABLED
|
||||||
|
value: "false"
|
||||||
|
resources:
|
||||||
|
requests: { cpu: 200m, memory: 512Mi }
|
||||||
|
limits: { memory: 1Gi, cpu: 1000m }
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: authentik
|
||||||
|
namespace: auth
|
||||||
|
spec:
|
||||||
|
selector: { app: authentik, component: server }
|
||||||
|
ports:
|
||||||
|
- { name: http, port: 80, targetPort: 9000 }
|
||||||
|
---
|
||||||
|
# Embedded outpost — runs the proxy providers; this is what ingress-nginx
|
||||||
|
# calls for /auth/nginx on every use-sso-auth ingress.
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: authentik-outpost
|
||||||
|
namespace: auth
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels: { app: authentik, component: outpost }
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: { app: authentik, component: outpost }
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: outpost
|
||||||
|
image: ghcr.io/goauthentik/proxy:2026.8
|
||||||
|
env:
|
||||||
|
- name: AUTHENTIK_HOST
|
||||||
|
value: http://authentik.auth.svc.cluster.local
|
||||||
|
- name: AUTHENTIK_INSECURE
|
||||||
|
value: "true"
|
||||||
|
- name: AUTHENTIK_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
{
|
||||||
|
secretKeyRef:
|
||||||
|
{ name: authentik-secrets, key: bootstrap_token },
|
||||||
|
}
|
||||||
|
ports:
|
||||||
|
- { containerPort: 9000, name: http }
|
||||||
|
readinessProbe:
|
||||||
|
httpGet: { path: /outpost.goauthentik.io/ping, port: 9000 }
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
resources:
|
||||||
|
requests: { cpu: 200m, memory: 512Mi }
|
||||||
|
limits: { memory: 1Gi, cpu: 1000m }
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: authentik-outpost
|
||||||
|
namespace: auth
|
||||||
|
spec:
|
||||||
|
selector: { app: authentik, component: outpost }
|
||||||
|
ports:
|
||||||
|
- { name: http, port: 80, targetPort: 9000 }
|
||||||
|
---
|
||||||
|
# SSO portal (user-facing login) — auth.haven
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: authentik
|
||||||
|
namespace: auth
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
rules:
|
||||||
|
- host: auth.haven
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend: { service: { name: authentik, port: { number: 80 } } }
|
||||||
|
---
|
||||||
|
# Outpost route — the /outpost.goauthentik.io path must resolve on the same
|
||||||
|
# host the protected apps redirect to. Kept as a separate ingress so it can
|
||||||
|
# also be attached to other hosts later if needed (do NOT give it
|
||||||
|
# use-sso-auth — that would create an auth loop).
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: authentik-outpost
|
||||||
|
namespace: auth
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
rules:
|
||||||
|
- host: auth.haven
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /outpost.goauthentik.io
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
{ service: { name: authentik-outpost, port: { number: 80 } } }
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Kyverno — policy engine. Install with:
|
||||||
|
# helm repo add kyverno https://kyverno.github.io/kyverno
|
||||||
|
# helm upgrade --install kyverno kyverno/kyverno -n kyverno --create-namespace -f auth/kyverno-helm.yaml
|
||||||
|
# The only consumer of Kyverno here is the use-sso-auth mutation policy;
|
||||||
|
# if you later drop it, Kyverno can be removed with no other impact.
|
||||||
|
admissionController:
|
||||||
|
replicas: 1
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
memory: 256Mi
|
||||||
|
backgroundController:
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
memory: 128Mi
|
||||||
|
cleanupController:
|
||||||
|
enabled: false
|
||||||
|
reportsController:
|
||||||
|
enabled: false
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# ClusterPolicy: expands the single `use-sso-auth: "true"` Ingress annotation
|
||||||
|
# into the ingress-nginx forward-auth annotations pointed at the Authentik
|
||||||
|
# embedded outpost.
|
||||||
|
#
|
||||||
|
# Test before applying to real ingresses:
|
||||||
|
# kubectl apply -f auth/sso-auth-policy.yaml
|
||||||
|
# kubectl annotate ingress -n default homepage use-sso-auth=true --dry-run=server -o yaml # check annotations get injected
|
||||||
|
# # remove the test annotation afterwards
|
||||||
|
---
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: inject-sso-auth
|
||||||
|
spec:
|
||||||
|
validationFailureAction: Audit
|
||||||
|
background: false
|
||||||
|
rules:
|
||||||
|
- name: authentik-forward-auth
|
||||||
|
match:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
kinds: [Ingress]
|
||||||
|
preconditions:
|
||||||
|
all:
|
||||||
|
- key: "{{ request.object.metadata.annotations.\"use-sso-auth\" || '' }}"
|
||||||
|
operator: Equals
|
||||||
|
value: "true"
|
||||||
|
mutate:
|
||||||
|
patchStrategicMerge:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
nginx.ingress.kubernetes.io/auth-url: https://auth.haven/outpost.goauthentik.io/auth/nginx
|
||||||
|
nginx.ingress.kubernetes.io/auth-signin: https://auth.haven/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri
|
||||||
|
# NOTE: no auth-snippet used — ingress-nginx 1.15 rejects snippet
|
||||||
|
# annotations by default (allow-snippet-annotations=false, your
|
||||||
|
# controller ConfigMap is empty so it uses the default).
|
||||||
|
# ingress-nginx already forwards X-Original-URL to the auth
|
||||||
|
# backend automatically, which is all Authentik needs.
|
||||||
|
nginx.ingress.kubernetes.io/auth-response-headers: X-Authentik-Username,X-Authentik-Email,X-Authentik-Groups,X-Authentik-Name,X-Authentik-Metadata
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
---
|
---
|
||||||
# ============ AFFiNE app ============
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
@@ -116,7 +115,6 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
app: affine
|
app: affine
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: affine.haven
|
- host: affine.haven
|
||||||
http:
|
http:
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
# 2) Deployment
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
@@ -74,7 +73,6 @@ spec:
|
|||||||
server: 192.168.15.99
|
server: 192.168.15.99
|
||||||
path: /export/Storage/Cloud
|
path: /export/Storage/Cloud
|
||||||
---
|
---
|
||||||
# 3) Service (HTTP)
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
@@ -90,7 +88,6 @@ spec:
|
|||||||
name: http
|
name: http
|
||||||
|
|
||||||
---
|
---
|
||||||
# 4) Service (Slave node / WebDAV — optional)
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
@@ -111,7 +108,6 @@ spec:
|
|||||||
protocol: UDP
|
protocol: UDP
|
||||||
|
|
||||||
---
|
---
|
||||||
# 5) PersistentVolumeClaim
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
@@ -129,7 +125,6 @@ spec:
|
|||||||
limits:
|
limits:
|
||||||
storage: 50Gi
|
storage: 50Gi
|
||||||
---
|
---
|
||||||
# 6) Ingress
|
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
@@ -140,7 +135,6 @@ metadata:
|
|||||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
||||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: cloud.haven
|
- host: cloud.haven
|
||||||
http:
|
http:
|
||||||
@@ -153,7 +147,6 @@ spec:
|
|||||||
port:
|
port:
|
||||||
number: 5212
|
number: 5212
|
||||||
---
|
---
|
||||||
# 7) Ingress Public
|
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
@@ -164,7 +157,6 @@ metadata:
|
|||||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
||||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: cloud.ivanch.me
|
- host: cloud.ivanch.me
|
||||||
http:
|
http:
|
||||||
@@ -122,7 +122,6 @@ metadata:
|
|||||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
||||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: slink.haven
|
- host: slink.haven
|
||||||
http:
|
http:
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: renovate
|
||||||
|
namespace: cronjobs
|
||||||
|
spec:
|
||||||
|
schedule: "0 12 * * 0" # every Sunday 12:00
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: renovate
|
||||||
|
image: renovate/renovate:44.39.3
|
||||||
|
args:
|
||||||
|
- ivanch/haven
|
||||||
|
env:
|
||||||
|
- name: LOG_LEVEL
|
||||||
|
value: debug
|
||||||
|
- name: RENOVATE_AUTODISCOVER
|
||||||
|
value: "false"
|
||||||
|
- name: RENOVATE_PLATFORM
|
||||||
|
value: "gitea"
|
||||||
|
- name: RENOVATE_ENDPOINT
|
||||||
|
value: "https://git.ivanch.me"
|
||||||
|
- name: RENOVATE_GIT_AUTHOR
|
||||||
|
value: "Renovate Bot <bot@renovateapp.com>"
|
||||||
|
- name: RENOVATE_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: renovate-bot
|
||||||
|
key: RENOVATE_TOKEN
|
||||||
|
- name: RENOVATE_GITHUB_COM_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: renovate-bot
|
||||||
|
key: RENOVATE_GITHUB_COM_TOKEN
|
||||||
|
restartPolicy: Never
|
||||||
@@ -65,14 +65,17 @@ spec:
|
|||||||
- name: SONIC_PASSWORD
|
- name: SONIC_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: password
|
name: archivebox-password
|
||||||
key: password
|
key: password
|
||||||
- name: ADMIN_USERNAME
|
- name: ADMIN_USERNAME
|
||||||
value: "ivanch"
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: archivebox-password
|
||||||
|
key: password
|
||||||
- name: ADMIN_PASSWORD
|
- name: ADMIN_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: password
|
name: archivebox-password
|
||||||
key: password
|
key: password
|
||||||
- name: CSRF_TRUSTED_ORIGINS
|
- name: CSRF_TRUSTED_ORIGINS
|
||||||
value: "archive.haven"
|
value: "archive.haven"
|
||||||
@@ -121,7 +124,6 @@ spec:
|
|||||||
port: 8000
|
port: 8000
|
||||||
targetPort: 8000
|
targetPort: 8000
|
||||||
---
|
---
|
||||||
# 3) PersistentVolumeClaim
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
@@ -145,7 +147,6 @@ metadata:
|
|||||||
name: archivebox-ingress
|
name: archivebox-ingress
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: "archive.haven"
|
- host: "archive.haven"
|
||||||
http:
|
http:
|
||||||
@@ -98,7 +98,6 @@ spec:
|
|||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
terminationGracePeriodSeconds: 30
|
terminationGracePeriodSeconds: 30
|
||||||
---
|
---
|
||||||
# 2) Service
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
@@ -116,7 +115,6 @@ spec:
|
|||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: http
|
targetPort: http
|
||||||
---
|
---
|
||||||
# 3) PersistentVolumeClaim
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
@@ -134,7 +132,6 @@ spec:
|
|||||||
limits:
|
limits:
|
||||||
storage: 2Gi
|
storage: 2Gi
|
||||||
---
|
---
|
||||||
# 4) Ingress
|
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
@@ -143,7 +140,6 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: changedetection
|
app.kubernetes.io/name: changedetection
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: change.haven
|
- host: change.haven
|
||||||
http:
|
http:
|
||||||
@@ -192,7 +192,6 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: homepage
|
app.kubernetes.io/name: homepage
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: "homepage.haven"
|
- host: "homepage.haven"
|
||||||
http:
|
http:
|
||||||
@@ -53,7 +53,6 @@ metadata:
|
|||||||
name: it-tools-ingress
|
name: it-tools-ingress
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: "tools.haven"
|
- host: "tools.haven"
|
||||||
http:
|
http:
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
---
|
---
|
||||||
# 1) Deployment
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
@@ -19,9 +18,6 @@ spec:
|
|||||||
- name: notepad
|
- name: notepad
|
||||||
image: jdreinhardt/minimalist-web-notepad:latest
|
image: jdreinhardt/minimalist-web-notepad:latest
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
# The image entrypoint runs `chown -R www-data:www-data` on the NFS-mounted
|
|
||||||
# _tmp dir, which fails because the NFS export uses all_squash (anonuid=65534).
|
|
||||||
# Override the entrypoint to skip chown — ownership is handled by the NFS server.
|
|
||||||
command:
|
command:
|
||||||
- sh
|
- sh
|
||||||
- -c
|
- -c
|
||||||
@@ -47,7 +43,6 @@ spec:
|
|||||||
claimName: notepad-data
|
claimName: notepad-data
|
||||||
|
|
||||||
---
|
---
|
||||||
# 2) Service
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
@@ -61,7 +56,6 @@ spec:
|
|||||||
- port: 80
|
- port: 80
|
||||||
targetPort: 80
|
targetPort: 80
|
||||||
---
|
---
|
||||||
# 3) PersistentVolumeClaim
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
@@ -77,14 +71,12 @@ spec:
|
|||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
---
|
---
|
||||||
# 4) Ingress
|
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: notepad
|
name: notepad
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: notepad.haven
|
- host: notepad.haven
|
||||||
http:
|
http:
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
# 1) Deployment
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
@@ -57,7 +56,6 @@ spec:
|
|||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: openwebui-data
|
claimName: openwebui-data
|
||||||
---
|
---
|
||||||
# 2) Service
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
@@ -71,7 +69,6 @@ spec:
|
|||||||
- port: 8080
|
- port: 8080
|
||||||
targetPort: 8080
|
targetPort: 8080
|
||||||
---
|
---
|
||||||
# 3) PersistentVolumeClaim
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
@@ -89,7 +86,6 @@ spec:
|
|||||||
limits:
|
limits:
|
||||||
storage: 10Gi
|
storage: 10Gi
|
||||||
---
|
---
|
||||||
# 4) Ingress
|
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
@@ -98,7 +94,6 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
|
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: openwebui.haven
|
- host: openwebui.haven
|
||||||
http:
|
http:
|
||||||
@@ -137,7 +137,6 @@ metadata:
|
|||||||
name: paperless
|
name: paperless
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: paperless.haven
|
- host: paperless.haven
|
||||||
http:
|
http:
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: playwright
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: playwright
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: playwright
|
||||||
|
spec:
|
||||||
|
affinity:
|
||||||
|
nodeAffinity:
|
||||||
|
preferredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- preference:
|
||||||
|
matchExpressions:
|
||||||
|
- key: kubernetes.io/hostname
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- iris
|
||||||
|
weight: 100
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- npx
|
||||||
|
- -y
|
||||||
|
- playwright@1.58.0
|
||||||
|
- run-server
|
||||||
|
- --port
|
||||||
|
- "3000"
|
||||||
|
- --host
|
||||||
|
- 0.0.0.0
|
||||||
|
env:
|
||||||
|
- name: TZ
|
||||||
|
value: America/Sao_Paulo
|
||||||
|
image: mcr.microsoft.com/playwright:v1.62.1-noble
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: playwright
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
protocol: TCP
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: "4"
|
||||||
|
memory: 4Gi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
terminationMessagePath: /dev/termination-log
|
||||||
|
terminationMessagePolicy: File
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /dev/shm
|
||||||
|
name: dshm
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
schedulerName: default-scheduler
|
||||||
|
securityContext: {}
|
||||||
|
terminationGracePeriodSeconds: 30
|
||||||
|
volumes:
|
||||||
|
- emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
name: dshm
|
||||||
|
status:
|
||||||
|
availableReplicas: 1
|
||||||
|
conditions:
|
||||||
|
- lastTransitionTime: "2026-05-29T15:54:24Z"
|
||||||
|
lastUpdateTime: "2026-07-22T10:14:35Z"
|
||||||
|
message: ReplicaSet "playwright-86c74d7c78" has successfully progressed.
|
||||||
|
reason: NewReplicaSetAvailable
|
||||||
|
status: "True"
|
||||||
|
type: Progressing
|
||||||
|
- lastTransitionTime: "2026-08-28T06:04:14Z"
|
||||||
|
lastUpdateTime: "2026-08-28T06:04:14Z"
|
||||||
|
message: Deployment has minimum availability.
|
||||||
|
reason: MinimumReplicasAvailable
|
||||||
|
status: "True"
|
||||||
|
type: Available
|
||||||
|
observedGeneration: 95
|
||||||
|
readyReplicas: 1
|
||||||
|
replicas: 1
|
||||||
|
terminatingReplicas: 0
|
||||||
|
updatedReplicas: 1
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: playwright
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
internalTrafficPolicy: Cluster
|
||||||
|
ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
ipFamilyPolicy: SingleStack
|
||||||
|
ports:
|
||||||
|
- port: 3000
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 3000
|
||||||
|
selector:
|
||||||
|
app: playwright
|
||||||
|
sessionAffinity: None
|
||||||
|
type: ClusterIP
|
||||||
|
status:
|
||||||
|
loadBalancer: {}
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: playwright
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: playwright.haven
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- backend:
|
||||||
|
service:
|
||||||
|
name: playwright
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
|
path: /
|
||||||
|
pathType: Prefix
|
||||||
|
status:
|
||||||
|
loadBalancer:
|
||||||
|
ingress:
|
||||||
|
- ip: 192.168.20.204
|
||||||
@@ -80,7 +80,6 @@ metadata:
|
|||||||
name: searxng
|
name: searxng
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: search.haven
|
- host: search.haven
|
||||||
http:
|
http:
|
||||||
@@ -91,4 +90,4 @@ spec:
|
|||||||
service:
|
service:
|
||||||
name: searxng
|
name: searxng
|
||||||
port:
|
port:
|
||||||
number: 8080
|
number: 8080
|
||||||
@@ -99,7 +99,6 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
app: stirlingpdf
|
app: stirlingpdf
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: stirling.haven
|
- host: stirling.haven
|
||||||
http:
|
http:
|
||||||
@@ -56,7 +56,7 @@ spec:
|
|||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: uptimekuma-config
|
claimName: uptimekuma-config
|
||||||
---
|
---
|
||||||
# 2) Service
|
# 2) Service
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
@@ -93,7 +93,6 @@ metadata:
|
|||||||
name: uptimekuma
|
name: uptimekuma
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: uptimekuma.haven
|
- host: uptimekuma.haven
|
||||||
http:
|
http:
|
||||||
@@ -104,4 +103,4 @@ spec:
|
|||||||
service:
|
service:
|
||||||
name: uptimekuma
|
name: uptimekuma
|
||||||
port:
|
port:
|
||||||
number: 3001
|
number: 3001
|
||||||
@@ -110,7 +110,6 @@ metadata:
|
|||||||
cert-manager.io/cluster-issuer: internal-ca
|
cert-manager.io/cluster-issuer: internal-ca
|
||||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- vault.haven
|
- vault.haven
|
||||||
@@ -134,7 +133,6 @@ metadata:
|
|||||||
name: vaultwarden-public
|
name: vaultwarden-public
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: vault.ivanch.me
|
- host: vault.ivanch.me
|
||||||
http:
|
http:
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: adguardsync-pvc
|
||||||
|
namespace: dns
|
||||||
|
annotations:
|
||||||
|
nfs.io/storage-path: "adguardsync-config"
|
||||||
|
spec:
|
||||||
|
storageClassName: "nfs-client"
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 10Mi
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: adguardsync
|
||||||
|
namespace: dns
|
||||||
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: adguardsync
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: adguardsync
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: adguardsync
|
||||||
|
image: ghcr.io/bakito/adguardhome-sync:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
name: web-port
|
||||||
|
env:
|
||||||
|
- name: CRON
|
||||||
|
value: "0 * * * *"
|
||||||
|
- name: RUN_ON_START
|
||||||
|
value: "true"
|
||||||
|
- name: LOG_LEVEL
|
||||||
|
value: "info"
|
||||||
|
- name: ORIGIN_URL
|
||||||
|
value: "http://adguard.haven"
|
||||||
|
- name: ORIGIN_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: adguardhome-password
|
||||||
|
key: username
|
||||||
|
- name: ORIGIN_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: adguardhome-password
|
||||||
|
key: password
|
||||||
|
- name: REPLICA1_URL
|
||||||
|
value: "http://adguard2.haven"
|
||||||
|
- name: REPLICA1_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: adguardhome-password
|
||||||
|
key: username
|
||||||
|
- name: REPLICA1_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: adguardhome-password
|
||||||
|
key: password
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
volumeMounts:
|
||||||
|
- name: adguardsync-storage
|
||||||
|
mountPath: /config
|
||||||
|
volumes:
|
||||||
|
- name: adguardsync-storage
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: adguardsync-pvc
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: adguardsync-svc
|
||||||
|
namespace: dns
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: adguardsync
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 8080
|
||||||
|
targetPort: 8080
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: adguardsync-ingress
|
||||||
|
namespace: dns
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: adguardsync.haven
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: adguardsync-svc
|
||||||
|
port:
|
||||||
|
number: 8080
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: adguardhome-pvc
|
||||||
|
namespace: dns
|
||||||
|
annotations:
|
||||||
|
nfs.io/storage-path: "adguardhome-config"
|
||||||
|
spec:
|
||||||
|
storageClassName: "nfs-client"
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 10Gi
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: adguardhome
|
||||||
|
namespace: dns
|
||||||
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: adguardhome
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: adguardhome
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: adguardhome
|
||||||
|
image: adguard/adguardhome:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 53
|
||||||
|
protocol: TCP
|
||||||
|
- containerPort: 53
|
||||||
|
protocol: UDP
|
||||||
|
- containerPort: 3000
|
||||||
|
protocol: TCP
|
||||||
|
name: install-port
|
||||||
|
- containerPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
name: web-port
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2Gi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 80
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 80
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
volumeMounts:
|
||||||
|
- name: adguardhome-storage
|
||||||
|
mountPath: /opt/adguardhome/work
|
||||||
|
- name: adguardhome-storage
|
||||||
|
mountPath: /opt/adguardhome/conf
|
||||||
|
volumes:
|
||||||
|
- name: adguardhome-storage
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: adguardhome-pvc
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: adguardhome-svc
|
||||||
|
namespace: dns
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
selector:
|
||||||
|
app: adguardhome
|
||||||
|
loadBalancerIP: 192.168.20.200
|
||||||
|
ports:
|
||||||
|
- name: dns-tcp
|
||||||
|
port: 53
|
||||||
|
targetPort: 53
|
||||||
|
protocol: TCP
|
||||||
|
- name: dns-udp
|
||||||
|
port: 53
|
||||||
|
targetPort: 53
|
||||||
|
protocol: UDP
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: adguardhome-lan-svc
|
||||||
|
namespace: dns
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
selector:
|
||||||
|
app: adguardhome
|
||||||
|
loadBalancerIP: 192.168.15.200
|
||||||
|
ports:
|
||||||
|
- name: dns-tcp
|
||||||
|
port: 53
|
||||||
|
targetPort: 53
|
||||||
|
protocol: TCP
|
||||||
|
- name: dns-udp
|
||||||
|
port: 53
|
||||||
|
targetPort: 53
|
||||||
|
protocol: UDP
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: adguard-install-svc
|
||||||
|
namespace: dns
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: adguardhome
|
||||||
|
ports:
|
||||||
|
- name: install
|
||||||
|
port: 3000
|
||||||
|
targetPort: 3000
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: adguardhome-ingress
|
||||||
|
namespace: dns
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: adguard.haven
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: adguardhome-svc
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: adguardhome-install-ingress
|
||||||
|
namespace: dns
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: install.adguard.haven
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: adguard-install-svc
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
@@ -22,7 +22,7 @@ spec:
|
|||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: beszel-key
|
name: beszel-key
|
||||||
key: SECRET-KEY
|
key: SECRET-KEY
|
||||||
image: henrygd/beszel-agent:0.18.7
|
image: henrygd/beszel-agent:0.18.8
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
name: beszel-agent
|
name: beszel-agent
|
||||||
ports:
|
ports:
|
||||||
@@ -26,7 +26,7 @@ spec:
|
|||||||
- amd64
|
- amd64
|
||||||
containers:
|
containers:
|
||||||
- name: beszel
|
- name: beszel
|
||||||
image: ghcr.io/henrygd/beszel/beszel:0.18.7
|
image: ghcr.io/henrygd/beszel/beszel:0.18.8
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8090
|
- containerPort: 8090
|
||||||
@@ -83,7 +83,6 @@ metadata:
|
|||||||
name: beszel
|
name: beszel
|
||||||
namespace: infra
|
namespace: infra
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: beszel.haven
|
- host: beszel.haven
|
||||||
http:
|
http:
|
||||||
@@ -19,7 +19,7 @@ spec:
|
|||||||
kubernetes.io/arch: amd64
|
kubernetes.io/arch: amd64
|
||||||
containers:
|
containers:
|
||||||
- name: bitwarden-cli
|
- name: bitwarden-cli
|
||||||
image: ghcr.io/charlesthomas/bitwarden-cli:2026.3.0
|
image: ghcr.io/charlesthomas/bitwarden-cli:2026.7.0
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
# Override the baked entrypoint so --disable-origin-protection is
|
# Override the baked entrypoint so --disable-origin-protection is
|
||||||
# actually passed (it was commented out in the image's entrypoint.sh,
|
# actually passed (it was commented out in the image's entrypoint.sh,
|
||||||
@@ -29,9 +29,8 @@ spec:
|
|||||||
- |
|
- |
|
||||||
set -e
|
set -e
|
||||||
bw config server "${BW_HOST}"
|
bw config server "${BW_HOST}"
|
||||||
# Authenticate. Prefer the API key if client creds are present,
|
|
||||||
# otherwise fall back to username+password. The session is exported
|
# Authenticate. Prefer the API key if client creds are present.
|
||||||
# so the background loop can re-derive (and refresh) it.
|
|
||||||
login() {
|
login() {
|
||||||
if [ -n "$BW_CLIENTID" ] && [ -n "$BW_CLIENTSECRET" ]; then
|
if [ -n "$BW_CLIENTID" ] && [ -n "$BW_CLIENTSECRET" ]; then
|
||||||
echo "Using apikey to log in"
|
echo "Using apikey to log in"
|
||||||
@@ -42,15 +41,15 @@ spec:
|
|||||||
fi
|
fi
|
||||||
export BW_SESSION
|
export BW_SESSION
|
||||||
}
|
}
|
||||||
|
|
||||||
login
|
login
|
||||||
|
|
||||||
# Warm the vault cache once at startup so bw serve has data immediately.
|
# Warm the vault cache once at startup so bw serve has data immediately.
|
||||||
bw sync
|
bw sync
|
||||||
bw status
|
bw status
|
||||||
# Keep the session alive: RE-LOGIN every cycle and re-sync so the on-disk
|
|
||||||
# vault cache stays warm and the session token never lapses. A loop that
|
# Keep the session alive
|
||||||
# only re-ran `bw sync` with a captured session would eventually fail once
|
|
||||||
# the session expired (-> stale cache / "Not found" for changed items, or a
|
|
||||||
# full unauthenticated 400 if the initial login never happened at all).
|
|
||||||
echo "Starting periodic bw login+sync loop (every 5m)"
|
echo "Starting periodic bw login+sync loop (every 5m)"
|
||||||
(
|
(
|
||||||
while true; do
|
while true; do
|
||||||
@@ -60,6 +59,7 @@ spec:
|
|||||||
bw sync >/dev/null 2>&1 || echo "[$(date -u +%FT%TZ)] bw sync failed"
|
bw sync >/dev/null 2>&1 || echo "[$(date -u +%FT%TZ)] bw sync failed"
|
||||||
done
|
done
|
||||||
) &
|
) &
|
||||||
|
|
||||||
echo 'Running `bw serve` on port 8087'
|
echo 'Running `bw serve` on port 8087'
|
||||||
bw serve --hostname 0.0.0.0 --disable-origin-protection
|
bw serve --hostname 0.0.0.0 --disable-origin-protection
|
||||||
env:
|
env:
|
||||||
@@ -121,3 +121,24 @@ spec:
|
|||||||
port: 8087
|
port: 8087
|
||||||
targetPort: http
|
targetPort: http
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: bw-cli
|
||||||
|
namespace: infra
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: bitwarden-cli
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
# ESO pods in the external-secrets namespace.
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: external-secrets
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: external-secrets
|
||||||
@@ -99,7 +99,6 @@ metadata:
|
|||||||
name: code-config
|
name: code-config
|
||||||
namespace: infra
|
namespace: infra
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: code-config.haven
|
- host: code-config.haven
|
||||||
http:
|
http:
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
apiVersion: helm.cattle.io/v1
|
||||||
|
kind: HelmChart
|
||||||
|
metadata:
|
||||||
|
name: csi-driver-nfs
|
||||||
|
namespace: infra
|
||||||
|
spec:
|
||||||
|
repo: https://kubernetes-csi.github.io/csi-driver-nfs
|
||||||
|
chart: csi-driver-nfs
|
||||||
|
version: 4.13.4
|
||||||
|
targetNamespace: infra
|
||||||
|
valuesContent: |-
|
||||||
|
controller:
|
||||||
|
replicas: 1
|
||||||
|
logLevel: 5
|
||||||
|
defaultOnDeletePolicy: retain
|
||||||
|
storageClasses:
|
||||||
|
- name: nfs-client
|
||||||
|
annotations:
|
||||||
|
storageclass.kubernetes.io/is-default-class: "true"
|
||||||
|
parameters:
|
||||||
|
server: nfs-config.haven
|
||||||
|
share: /export/config
|
||||||
|
subDir: ${pvc.metadata.namespace}/${pvc.metadata.name}
|
||||||
|
onDelete: retain
|
||||||
|
reclaimPolicy: Retain
|
||||||
|
volumeBindingMode: Immediate
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: helm.cattle.io/v1
|
||||||
|
kind: HelmChart
|
||||||
|
metadata:
|
||||||
|
name: external-secrets
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
repo: https://charts.external-secrets.io
|
||||||
|
chart: external-secrets
|
||||||
|
version: 2.7.0
|
||||||
|
targetNamespace: external-secrets
|
||||||
|
createNamespace: true
|
||||||
@@ -115,7 +115,6 @@ metadata:
|
|||||||
nginx.ingress.kubernetes.io/enable-cors: "true"
|
nginx.ingress.kubernetes.io/enable-cors: "true"
|
||||||
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
|
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: file-nginx.haven
|
- host: file-nginx.haven
|
||||||
http:
|
http:
|
||||||
@@ -72,7 +72,6 @@ metadata:
|
|||||||
name: haven-notify
|
name: haven-notify
|
||||||
namespace: infra
|
namespace: infra
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: notify.haven
|
- host: notify.haven
|
||||||
http:
|
http:
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
apiVersion: helm.cattle.io/v1
|
||||||
|
kind: HelmChart
|
||||||
|
metadata:
|
||||||
|
name: traefik
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
repo: https://traefik.github.io/charts
|
||||||
|
chart: traefik
|
||||||
|
version: 41.2.0
|
||||||
|
targetNamespace: traefik
|
||||||
|
createNamespace: true
|
||||||
|
valuesContent: |-
|
||||||
|
deployment:
|
||||||
|
replicas: 2
|
||||||
|
ingressClass:
|
||||||
|
enabled: true
|
||||||
|
isDefaultClass: true
|
||||||
|
name: traefik
|
||||||
|
service:
|
||||||
|
annotations:
|
||||||
|
metallb.io/ip-allocated-from-pool: default-pool
|
||||||
|
metallb.io/loadBalancerIPs: "192.168.20.204"
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
externalTrafficPolicy: Local
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 90Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 256Mi
|
||||||
@@ -113,7 +113,6 @@ metadata:
|
|||||||
name: wg-easy-ingress
|
name: wg-easy-ingress
|
||||||
namespace: infra
|
namespace: infra
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: vpn.haven
|
- host: vpn.haven
|
||||||
http:
|
http:
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: helm.cattle.io/v1
|
||||||
|
kind: HelmChart
|
||||||
|
metadata:
|
||||||
|
name: metallb
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
repo: https://metallb.github.io/metallb
|
||||||
|
chart: metallb
|
||||||
|
version: 0.15.2
|
||||||
|
targetNamespace: metallb-system
|
||||||
@@ -94,7 +94,6 @@ metadata:
|
|||||||
namespace: monitoring
|
namespace: monitoring
|
||||||
name: grafana
|
name: grafana
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: grafana.haven
|
- host: grafana.haven
|
||||||
http:
|
http:
|
||||||
@@ -113,7 +112,6 @@ metadata:
|
|||||||
namespace: monitoring
|
namespace: monitoring
|
||||||
name: grafana-public
|
name: grafana-public
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
rules:
|
||||||
- host: grafanah.ivanch.me
|
- host: grafanah.ivanch.me
|
||||||
http:
|
http:
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: ApplicationSet
|
||||||
|
metadata:
|
||||||
|
name: haven-apps
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
goTemplate: true
|
||||||
|
goTemplateOptions: ["missingkey=error"]
|
||||||
|
generators:
|
||||||
|
- git:
|
||||||
|
repoURL: https://git.ivanch.me/ivanch/haven.git
|
||||||
|
revision: main
|
||||||
|
files:
|
||||||
|
- path: "apps/*/*.yaml"
|
||||||
|
- path: "apps/root/*.yaml"
|
||||||
|
exclude: true
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
name: '{{ .path.filename | trimSuffix ".yaml" }}'
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: https://git.ivanch.me/ivanch/haven.git
|
||||||
|
targetRevision: main
|
||||||
|
path: "{{ .path.path }}"
|
||||||
|
directory:
|
||||||
|
include: "{{ .path.filename }}"
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: "{{ index .path.segments 1 }}"
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
templatePatch: |
|
||||||
|
{{- if hasKey . "chart" }}
|
||||||
|
spec:
|
||||||
|
source:
|
||||||
|
$patch: replace
|
||||||
|
{{- toYaml .spec.source | nindent 4 }}
|
||||||
|
syncPolicy:
|
||||||
|
syncOptions: [CreateNamespace=true, ServerSideApply=true]
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- applicationset.yaml
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
apiVersion: metallb.io/v1beta1
|
||||||
|
kind: IPAddressPool
|
||||||
|
metadata:
|
||||||
|
name: default-pool
|
||||||
|
namespace: metallb-system
|
||||||
|
spec:
|
||||||
|
addresses:
|
||||||
|
- 192.168.15.200/32 # reserved for DNS 1
|
||||||
|
- 192.168.15.202/32 # reserved for wg-easy
|
||||||
|
- 192.168.15.203/32 # reserved for k3s ingress
|
||||||
|
- 192.168.20.200/32 # reserved for DNS 1
|
||||||
|
# - 192.168.20.201 is reserved for DNS 2
|
||||||
|
- 192.168.20.202-192.168.20.220
|
||||||
|
---
|
||||||
|
apiVersion: metallb.io/v1beta1
|
||||||
|
kind: L2Advertisement
|
||||||
|
metadata:
|
||||||
|
name: default-advertisement
|
||||||
|
namespace: metallb-system
|
||||||
|
spec:
|
||||||
|
ipAddressPools:
|
||||||
|
- default-pool
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: argocd-cm
|
||||||
|
namespace: argocd
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: argocd-cm
|
||||||
|
app.kubernetes.io/part-of: argocd
|
||||||
|
data:
|
||||||
|
accounts.api: apiKey
|
||||||
|
accounts.api.enabled: "true"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: argocd-rbac-cm
|
||||||
|
namespace: argocd
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: argocd-rbac-cm
|
||||||
|
app.kubernetes.io/part-of: argocd
|
||||||
|
data:
|
||||||
|
policy.csv: |
|
||||||
|
g, api, role:readonly
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: argocd-server
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: argocd.haven
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: argocd-server
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: argocd
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- https://github.com/argoproj/argo-cd.git/manifests/cluster-install?ref=stable
|
||||||
|
- ingress.yaml
|
||||||
|
|
||||||
|
patches:
|
||||||
|
- path: server-insecure-patch.yaml
|
||||||
|
- path: argocd-api-user.yaml
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: argocd-cmd-params-cm
|
||||||
|
data:
|
||||||
|
server.insecure: "true"
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
---
|
||||||
|
# ==============================================================================
|
||||||
|
# Core / System Namespaces
|
||||||
|
# ==============================================================================
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: default
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: kube-node-lease
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: kube-public
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: kube-system
|
||||||
|
---
|
||||||
|
# ==============================================================================
|
||||||
|
# Infrastructure, Ingress & GitOps
|
||||||
|
# ==============================================================================
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: argocd
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: cert-manager
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: dns
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: docker-ingress
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: external-secrets
|
||||||
|
labels:
|
||||||
|
name: external-secrets
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: infra
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: ingress-nginx
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: ingress-nginx
|
||||||
|
app.kubernetes.io/name: ingress-nginx
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: metallb-system
|
||||||
|
---
|
||||||
|
# ==============================================================================
|
||||||
|
# Observability & Monitoring
|
||||||
|
# ==============================================================================
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: alloy
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: monitoring
|
||||||
|
---
|
||||||
|
# ==============================================================================
|
||||||
|
# Storage & Data
|
||||||
|
# ==============================================================================
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: garage
|
||||||
|
labels:
|
||||||
|
name: garage
|
||||||
|
---
|
||||||
|
# ==============================================================================
|
||||||
|
# Environments & Workloads
|
||||||
|
# ==============================================================================
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: chacal
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: cloud
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: cronjobs
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: dev
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: lab
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: media
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: mindforge
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: vpn-session-pods
|
||||||
|
labels:
|
||||||
|
pod-security.kubernetes.io/audit: privileged
|
||||||
|
pod-security.kubernetes.io/enforce: privileged
|
||||||
|
pod-security.kubernetes.io/warn: privileged
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: root
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: https://git.ivanch.me/ivanch/haven.git
|
||||||
|
targetRevision: main
|
||||||
|
path: apps/root
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: argocd
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# internal-issuer.yaml
|
|
||||||
apiVersion: cert-manager.io/v1
|
|
||||||
kind: ClusterIssuer
|
|
||||||
metadata:
|
|
||||||
name: internal-ca
|
|
||||||
spec:
|
|
||||||
ca:
|
|
||||||
secretName: internal-ca-secret
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
## Creating gitea-runner secrets
|
|
||||||
|
|
||||||
```bash
|
|
||||||
kubectl create secret generic gitea-runner-token \
|
|
||||||
--from-literal=REGISTRATION_TOKEN='your_gitea_runner_token' -n dev
|
|
||||||
```
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: adguardsync-pvc
|
|
||||||
namespace: dns
|
|
||||||
annotations:
|
|
||||||
nfs.io/storage-path: "adguardsync-config"
|
|
||||||
spec:
|
|
||||||
storageClassName: "nfs-client"
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 10Mi
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: adguardsync
|
|
||||||
namespace: dns
|
|
||||||
spec:
|
|
||||||
strategy:
|
|
||||||
type: Recreate
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: adguardsync
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: adguardsync
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: adguardsync
|
|
||||||
image: ghcr.io/bakito/adguardhome-sync:latest
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 8080
|
|
||||||
protocol: TCP
|
|
||||||
name: web-port
|
|
||||||
env:
|
|
||||||
- name: CRON
|
|
||||||
value: "0 * * * *"
|
|
||||||
- name: RUN_ON_START
|
|
||||||
value: "true"
|
|
||||||
- name: LOG_LEVEL
|
|
||||||
value: "info"
|
|
||||||
- name: ORIGIN_URL
|
|
||||||
value: "http://adguard.haven"
|
|
||||||
- name: ORIGIN_USERNAME
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: adguardhome-password
|
|
||||||
key: username
|
|
||||||
- name: ORIGIN_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: adguardhome-password
|
|
||||||
key: password
|
|
||||||
- name: REPLICA1_URL
|
|
||||||
value: "http://adguard2.haven"
|
|
||||||
- name: REPLICA1_USERNAME
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: adguardhome-password
|
|
||||||
key: username
|
|
||||||
- name: REPLICA1_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: adguardhome-password
|
|
||||||
key: password
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 128Mi
|
|
||||||
limits:
|
|
||||||
cpu: 500m
|
|
||||||
memory: 512Mi
|
|
||||||
volumeMounts:
|
|
||||||
- name: adguardsync-storage
|
|
||||||
mountPath: /config
|
|
||||||
volumes:
|
|
||||||
- name: adguardsync-storage
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: adguardsync-pvc
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: adguardsync-svc
|
|
||||||
namespace: dns
|
|
||||||
spec:
|
|
||||||
type: ClusterIP
|
|
||||||
selector:
|
|
||||||
app: adguardsync
|
|
||||||
ports:
|
|
||||||
- name: web
|
|
||||||
port: 8080
|
|
||||||
targetPort: 8080
|
|
||||||
---
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: adguardsync-ingress
|
|
||||||
namespace: dns
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
|
||||||
- host: adguardsync.haven
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: adguardsync-svc
|
|
||||||
port:
|
|
||||||
number: 8080
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: adguardhome-pvc
|
|
||||||
namespace: dns
|
|
||||||
annotations:
|
|
||||||
nfs.io/storage-path: "adguardhome-config"
|
|
||||||
spec:
|
|
||||||
storageClassName: "nfs-client"
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 10Gi
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: adguardhome
|
|
||||||
namespace: dns
|
|
||||||
spec:
|
|
||||||
strategy:
|
|
||||||
type: Recreate
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: adguardhome
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: adguardhome
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: adguardhome
|
|
||||||
image: adguard/adguardhome:latest
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 53
|
|
||||||
protocol: TCP
|
|
||||||
- containerPort: 53
|
|
||||||
protocol: UDP
|
|
||||||
- containerPort: 3000
|
|
||||||
protocol: TCP
|
|
||||||
name: install-port
|
|
||||||
- containerPort: 80
|
|
||||||
protocol: TCP
|
|
||||||
name: web-port
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 128Mi
|
|
||||||
limits:
|
|
||||||
cpu: 1000m
|
|
||||||
memory: 2Gi
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: 80
|
|
||||||
initialDelaySeconds: 30
|
|
||||||
periodSeconds: 10
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: 80
|
|
||||||
initialDelaySeconds: 5
|
|
||||||
periodSeconds: 5
|
|
||||||
volumeMounts:
|
|
||||||
- name: adguardhome-storage
|
|
||||||
mountPath: /opt/adguardhome/work
|
|
||||||
- name: adguardhome-storage
|
|
||||||
mountPath: /opt/adguardhome/conf
|
|
||||||
volumes:
|
|
||||||
- name: adguardhome-storage
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: adguardhome-pvc
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: adguardhome-svc
|
|
||||||
namespace: dns
|
|
||||||
spec:
|
|
||||||
type: LoadBalancer
|
|
||||||
selector:
|
|
||||||
app: adguardhome
|
|
||||||
loadBalancerIP: 192.168.20.200
|
|
||||||
ports:
|
|
||||||
- name: dns-tcp
|
|
||||||
port: 53
|
|
||||||
targetPort: 53
|
|
||||||
protocol: TCP
|
|
||||||
- name: dns-udp
|
|
||||||
port: 53
|
|
||||||
targetPort: 53
|
|
||||||
protocol: UDP
|
|
||||||
- name: web
|
|
||||||
port: 80
|
|
||||||
targetPort: 80
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: adguardhome-lan-svc
|
|
||||||
namespace: dns
|
|
||||||
spec:
|
|
||||||
type: LoadBalancer
|
|
||||||
selector:
|
|
||||||
app: adguardhome
|
|
||||||
loadBalancerIP: 192.168.15.200
|
|
||||||
ports:
|
|
||||||
- name: dns-tcp
|
|
||||||
port: 53
|
|
||||||
targetPort: 53
|
|
||||||
protocol: TCP
|
|
||||||
- name: dns-udp
|
|
||||||
port: 53
|
|
||||||
targetPort: 53
|
|
||||||
protocol: UDP
|
|
||||||
- name: web
|
|
||||||
port: 80
|
|
||||||
targetPort: 80
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: adguard-install-svc
|
|
||||||
namespace: dns
|
|
||||||
spec:
|
|
||||||
type: ClusterIP
|
|
||||||
selector:
|
|
||||||
app: adguardhome
|
|
||||||
ports:
|
|
||||||
- name: install
|
|
||||||
port: 3000
|
|
||||||
targetPort: 3000
|
|
||||||
---
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: adguardhome-ingress
|
|
||||||
namespace: dns
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
|
||||||
- host: adguard.haven
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: adguardhome-svc
|
|
||||||
port:
|
|
||||||
number: 80
|
|
||||||
---
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: adguardhome-install-ingress
|
|
||||||
namespace: dns
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
|
||||||
- host: install.adguard.haven
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: adguard-install-svc
|
|
||||||
port:
|
|
||||||
number: 3000
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
## Create namespace
|
|
||||||
```bash
|
|
||||||
kubectl create namespace docker-ingress
|
|
||||||
```
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# docker-node: iris.haven
|
|
||||||
# port: 4100
|
|
||||||
|
|
||||||
# Service
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: changedetection-service
|
|
||||||
namespace: docker-ingress
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
targetPort: 4100
|
|
||||||
---
|
|
||||||
# Endpoints
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Endpoints
|
|
||||||
metadata:
|
|
||||||
name: changedetection-service
|
|
||||||
namespace: docker-ingress
|
|
||||||
subsets:
|
|
||||||
- addresses:
|
|
||||||
- ip: 192.168.20.100
|
|
||||||
ports:
|
|
||||||
- port: 4100
|
|
||||||
---
|
|
||||||
# Ingress
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: changedetection-ingress
|
|
||||||
namespace: docker-ingress
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: change.haven
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: changedetection-service
|
|
||||||
port:
|
|
||||||
number: 80
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
# docker-node: iris.haven
|
|
||||||
# port: 4100
|
|
||||||
|
|
||||||
# Service
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: dockge-service
|
|
||||||
namespace: docker-ingress
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
protocol: TCP
|
|
||||||
port: 80
|
|
||||||
targetPort: 5001
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Endpoints
|
|
||||||
metadata:
|
|
||||||
name: dockge-service
|
|
||||||
namespace: docker-ingress
|
|
||||||
subsets:
|
|
||||||
- addresses:
|
|
||||||
- ip: 192.168.20.100
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
protocol: TCP
|
|
||||||
port: 5001
|
|
||||||
---
|
|
||||||
# Ingress
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: dockge-ingress
|
|
||||||
namespace: docker-ingress
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: dockge.haven
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: dockge-service
|
|
||||||
port:
|
|
||||||
number: 80
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
```bash
|
|
||||||
kubectl create secret generic beszel-key --from-literal=SECRET-KEY=<KEY> -n infra
|
|
||||||
```
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: NetworkPolicy
|
|
||||||
metadata:
|
|
||||||
name: bw-cli
|
|
||||||
namespace: infra
|
|
||||||
spec:
|
|
||||||
podSelector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: bitwarden-cli
|
|
||||||
policyTypes:
|
|
||||||
- Ingress
|
|
||||||
ingress:
|
|
||||||
- from:
|
|
||||||
# ESO pods (app.kubernetes.io/name: external-secrets) in the external-secrets namespace.
|
|
||||||
# Both podSelector AND namespaceSelector must match for cross-namespace traffic.
|
|
||||||
- namespaceSelector:
|
|
||||||
matchLabels:
|
|
||||||
kubernetes.io/metadata.name: external-secrets
|
|
||||||
podSelector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: external-secrets
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: nfs-pod
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nfs-container
|
|
||||||
image: alpine:latest
|
|
||||||
env:
|
|
||||||
- name: PUID
|
|
||||||
value: "1000"
|
|
||||||
- name: PGID
|
|
||||||
value: "1000"
|
|
||||||
volumeMounts:
|
|
||||||
- name: nfs-backup
|
|
||||||
mountPath: /mnt/Backup
|
|
||||||
- name: nfs-storage
|
|
||||||
mountPath: /mnt/Storage
|
|
||||||
command: ["/bin/sh", "-c", "sleep infinity"]
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 128Mi
|
|
||||||
limits:
|
|
||||||
cpu: 800m
|
|
||||||
memory: 256Mi
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
volumes:
|
|
||||||
- name: nfs-backup
|
|
||||||
nfs:
|
|
||||||
server: 192.168.15.99
|
|
||||||
path: /srv/dev-md1/Backup
|
|
||||||
- name: nfs-storage
|
|
||||||
nfs:
|
|
||||||
server: 192.168.15.99
|
|
||||||
path: /export/Storage
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
apiVersion: metallb.io/v1beta1
|
|
||||||
kind: IPAddressPool
|
|
||||||
metadata:
|
|
||||||
name: default-pool
|
|
||||||
namespace: metallb-system
|
|
||||||
spec:
|
|
||||||
addresses:
|
|
||||||
- 192.168.15.200/32 # reserved for DNS 1
|
|
||||||
- 192.168.15.202/32 # reserved for wg-easy
|
|
||||||
- 192.168.15.203/32 # reserved for k3s ingress
|
|
||||||
- 192.168.20.200/32 # reserved for DNS 1
|
|
||||||
# - 192.168.20.201 is reserved for DNS 2
|
|
||||||
- 192.168.20.202-192.168.20.220
|
|
||||||
---
|
|
||||||
apiVersion: metallb.io/v1beta1
|
|
||||||
kind: L2Advertisement
|
|
||||||
metadata:
|
|
||||||
name: default-advertisement
|
|
||||||
namespace: metallb-system
|
|
||||||
spec:
|
|
||||||
ipAddressPools:
|
|
||||||
- default-pool
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata: { name: archivebox-password, namespace: default }
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
target:
|
||||||
|
name: archivebox-password
|
||||||
|
deletionPolicy: Retain
|
||||||
|
template:
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
username: "{{ .username }}"
|
||||||
|
password: "{{ .password }}"
|
||||||
|
data:
|
||||||
|
- secretKey: username
|
||||||
|
remoteRef:
|
||||||
|
{ key: 6b4ca371-dcd4-4e31-aebe-8e5ea48b1fb9, property: username }
|
||||||
|
sourceRef:
|
||||||
|
{ storeRef: { name: bitwarden-login, kind: ClusterSecretStore } }
|
||||||
|
- secretKey: password
|
||||||
|
remoteRef:
|
||||||
|
{ key: 6b4ca371-dcd4-4e31-aebe-8e5ea48b1fb9, property: password }
|
||||||
|
sourceRef:
|
||||||
|
{ storeRef: { name: bitwarden-login, kind: ClusterSecretStore } }
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
apiVersion: external-secrets.io/v1
|
|
||||||
kind: ExternalSecret
|
|
||||||
metadata: { name: radarr, namespace: media }
|
|
||||||
spec:
|
|
||||||
refreshInterval: 1h
|
|
||||||
target:
|
|
||||||
name: radarr-secret
|
|
||||||
deletionPolicy: Retain
|
|
||||||
template:
|
|
||||||
type: Opaque
|
|
||||||
data:
|
|
||||||
Radarr__Postgres__User: "{{ .Radarr__Postgres__User }}"
|
|
||||||
Radarr__Postgres__Password: "{{ .Radarr__Postgres__Password }}"
|
|
||||||
Radarr__Postgres__Host: "{{ .Radarr__Postgres__Host }}"
|
|
||||||
Radarr__Postgres__MainDb: "{{ .Radarr__Postgres__MainDb }}"
|
|
||||||
data:
|
|
||||||
- secretKey: Radarr__Postgres__User
|
|
||||||
remoteRef:
|
|
||||||
{
|
|
||||||
key: ab723b65-3ec8-469c-b01d-67a6e3049023,
|
|
||||||
property: username,
|
|
||||||
}
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-login, kind: ClusterSecretStore } }
|
|
||||||
- secretKey: Radarr__Postgres__Password
|
|
||||||
remoteRef:
|
|
||||||
{
|
|
||||||
key: ab723b65-3ec8-469c-b01d-67a6e3049023,
|
|
||||||
property: password,
|
|
||||||
}
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-login, kind: ClusterSecretStore } }
|
|
||||||
- secretKey: Radarr__Postgres__Host
|
|
||||||
remoteRef:
|
|
||||||
{
|
|
||||||
key: ab723b65-3ec8-469c-b01d-67a6e3049023,
|
|
||||||
property: Radarr__Postgres__Host,
|
|
||||||
}
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-fields, kind: ClusterSecretStore } }
|
|
||||||
- secretKey: Radarr__Postgres__MainDb
|
|
||||||
remoteRef:
|
|
||||||
{
|
|
||||||
key: ab723b65-3ec8-469c-b01d-67a6e3049023,
|
|
||||||
property: Radarr__Postgres__MainDb,
|
|
||||||
}
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-fields, kind: ClusterSecretStore } }
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
apiVersion: external-secrets.io/v1
|
|
||||||
kind: ExternalSecret
|
|
||||||
metadata: { name: recommender, namespace: media }
|
|
||||||
spec:
|
|
||||||
refreshInterval: 1h
|
|
||||||
target:
|
|
||||||
name: recommender-secrets
|
|
||||||
deletionPolicy: Retain
|
|
||||||
template:
|
|
||||||
type: Opaque
|
|
||||||
data:
|
|
||||||
OPENAI_API_KEY: "{{ .OPENAI_API_KEY }}"
|
|
||||||
DATABASE_URL: "{{ .DATABASE_URL }}"
|
|
||||||
data:
|
|
||||||
- secretKey: OPENAI_API_KEY
|
|
||||||
remoteRef:
|
|
||||||
{
|
|
||||||
key: 5079ef6f-3d1d-4522-b22c-6dd5f1c19acd,
|
|
||||||
property: OPENAI_API_KEY,
|
|
||||||
}
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-fields, kind: ClusterSecretStore } }
|
|
||||||
- secretKey: DATABASE_URL
|
|
||||||
remoteRef:
|
|
||||||
{ key: 5079ef6f-3d1d-4522-b22c-6dd5f1c19acd, property: DATABASE_URL }
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-fields, kind: ClusterSecretStore } }
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata: { name: renovate-bot, namespace: cronjobs }
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
target:
|
||||||
|
name: renovate-bot
|
||||||
|
deletionPolicy: Retain
|
||||||
|
template:
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
RENOVATE_GITHUB_COM_TOKEN: "{{ .RENOVATE_GITHUB_COM_TOKEN }}"
|
||||||
|
RENOVATE_TOKEN: "{{ .RENOVATE_TOKEN }}"
|
||||||
|
data:
|
||||||
|
- secretKey: RENOVATE_GITHUB_COM_TOKEN
|
||||||
|
remoteRef:
|
||||||
|
{
|
||||||
|
key: 25b1f5c9-0a2b-438e-a4c6-23ea1d58e2de,
|
||||||
|
property: RENOVATE_GITHUB_COM_TOKEN,
|
||||||
|
}
|
||||||
|
sourceRef:
|
||||||
|
{ storeRef: { name: bitwarden-fields, kind: ClusterSecretStore } }
|
||||||
|
- secretKey: RENOVATE_TOKEN
|
||||||
|
remoteRef:
|
||||||
|
{ key: 25b1f5c9-0a2b-438e-a4c6-23ea1d58e2de, property: RENOVATE_TOKEN }
|
||||||
|
sourceRef:
|
||||||
|
{ storeRef: { name: bitwarden-fields, kind: ClusterSecretStore } }
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
apiVersion: external-secrets.io/v1
|
|
||||||
kind: ExternalSecret
|
|
||||||
metadata: { name: sonarr, namespace: media }
|
|
||||||
spec:
|
|
||||||
refreshInterval: 1h
|
|
||||||
target:
|
|
||||||
name: sonarr-secret
|
|
||||||
deletionPolicy: Retain
|
|
||||||
template:
|
|
||||||
type: Opaque
|
|
||||||
data:
|
|
||||||
Sonarr__Postgres__User: "{{ .Sonarr__Postgres__User }}"
|
|
||||||
Sonarr__Postgres__Password: "{{ .Sonarr__Postgres__Password }}"
|
|
||||||
Sonarr__Postgres__Host: "{{ .Sonarr__Postgres__Host }}"
|
|
||||||
Sonarr__Postgres__MainDb: "{{ .Sonarr__Postgres__MainDb }}"
|
|
||||||
data:
|
|
||||||
- secretKey: Sonarr__Postgres__User
|
|
||||||
remoteRef:
|
|
||||||
{ key: 2c5b6d27-971f-4876-b10d-db400dfde7b2, property: username }
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-login, kind: ClusterSecretStore } }
|
|
||||||
- secretKey: Sonarr__Postgres__Password
|
|
||||||
remoteRef:
|
|
||||||
{ key: 2c5b6d27-971f-4876-b10d-db400dfde7b2, property: password }
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-login, kind: ClusterSecretStore } }
|
|
||||||
- secretKey: Sonarr__Postgres__Host
|
|
||||||
remoteRef:
|
|
||||||
{
|
|
||||||
key: 2c5b6d27-971f-4876-b10d-db400dfde7b2,
|
|
||||||
property: Sonarr__Postgres__Host,
|
|
||||||
}
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-fields, kind: ClusterSecretStore } }
|
|
||||||
- secretKey: Sonarr__Postgres__MainDb
|
|
||||||
remoteRef:
|
|
||||||
{
|
|
||||||
key: 2c5b6d27-971f-4876-b10d-db400dfde7b2,
|
|
||||||
property: Sonarr__Postgres__MainDb,
|
|
||||||
}
|
|
||||||
sourceRef:
|
|
||||||
{ storeRef: { name: bitwarden-fields, kind: ClusterSecretStore } }
|
|
||||||
Reference in New Issue
Block a user