feat: revamp and use single namespace and update to latest versions

This commit is contained in:
2025-09-21 17:53:34 +05:00
parent 9b0434721b
commit cc90d7793a
18 changed files with 277 additions and 194 deletions

View File

@@ -5,7 +5,6 @@ import { Construct } from "constructs";
type AuthentikServerOptions = {
provider: HelmProvider;
version: string;
name: string;
namespace: string;
};

View File

@@ -3,25 +3,25 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: cloudflare-domains-config
namespace: cloudflare-system
namespace: homelab
data:
DOMAINS: "auth.dogar.dev,grafana.dogar.dev,vpn.dogar.dev"
DOMAINS: "auth.dogar.dev,grafana.dogar.dev"
PROXIED: "true"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cloudflare-domains-config-non-proxied
namespace: cloudflare-system
namespace: homelab
data:
DOMAINS: "postgres.dogar.dev"
DOMAINS: "dogar.dev,git.dogar.dev"
PROXIED: "false"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudflare-ddns
namespace: cloudflare-system
namespace: homelab
spec:
replicas: 1
selector:
@@ -40,7 +40,7 @@ spec:
valueFrom:
secretKeyRef:
name: cloudflare-token
key: credential
key: token
- name: DOMAINS
valueFrom:
configMapKeyRef:
@@ -55,7 +55,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudflare-ddns-non-proxied
namespace: cloudflare-system
namespace: homelab
spec:
replicas: 1
selector:
@@ -74,7 +74,7 @@ spec:
valueFrom:
secretKeyRef:
name: cloudflare-token
key: credential
key: token
- name: DOMAINS
valueFrom:
configMapKeyRef:

View File

@@ -5,7 +5,6 @@ import { Construct } from "constructs";
type GiteaServerOptions = {
provider: HelmProvider;
version: string;
name: string;
namespace: string;
};

View File

@@ -1,17 +1,86 @@
global:
addPrometheusAnnotations: true
securityContext:
runAsUser: 1000
fsGroup: 1000
env:
- name: AUTHENTIK_SECRET_KEY
valueFrom:
secretKeyRef:
name: authentik-secret-key
key: password
- name: AUTHENTIK_EMAIL__USERNAME
valueFrom:
secretKeyRef:
name: smtp-token
key: authentik-username
- name: AUTHENTIK_EMAIL__PASSWORD
valueFrom:
secretKeyRef:
name: smtp-token
key: authentik-password
- name: AUTHENTIK_EMAIL__FROM
valueFrom:
secretKeyRef:
name: smtp-token
key: authentik-username
- name: AUTHENTIK_EMAIL__USE_TLS
value: "true"
- name: AUTHENTIK_POSTGRESQL__USER
valueFrom:
secretKeyRef:
name: authentik-postgres
key: username
- name: AUTHENTIK_POSTGRESQL__NAME
valueFrom:
secretKeyRef:
name: authentik-postgres
key: database
- name: AUTHENTIK_POSTGRESQL__SSLMODE
value: verify-full
- name: AUTHENTIK_POSTGRESQL__SSLROOTCERT
value: "/opt/authentik/certs/ca.crt"
- name: AUTHENTIK_POSTGRESQL__SSLCERT
value: "/opt/authentik/certs/tls.crt"
- name: AUTHENTIK_POSTGRESQL__SSLKEY
value: "/opt/authentik/certs/tls.key"
- name: AUTHENTIK_REDIS__PASSWORD
valueFrom:
secretKeyRef:
name: valkey
key: password
volumes:
- name: ssl-bundle
projected:
sources:
- secret:
name: authentik-client-cert
items:
- key: tls.crt
path: tls.crt
- key: tls.key
path: tls.key
mode: 0600
- secret:
name: postgres-server-cert
items:
- key: ca.crt
path: ca.crt
volumeMounts:
- name: ssl-bundle
mountPath: /opt/authentik/certs
readOnly: true
authentik:
secret_key: "c8cc2e4a498c697a0443d96b31fe042c69c2158dc8bfb3da3878d1dbfbe6128e"
error_reporting:
enabled: false
email:
host: "smtp.protonmail.ch"
port: 587
postgresql:
host: postgres-cluster-rw.postgres-system.svc.cluster.local
user: file:///postgres-creds/username
password: file:///postgres-creds/password
host: postgres-cluster-rw
redis:
host: redis-master.redis-system.svc.cluster.local
password: file:///redis-creds/password
host: valkey
server:
replicas: 3
@@ -21,45 +90,20 @@ server:
cert-manager.io/cluster-issuer: cloudflare-issuer
cert-manager.io/acme-challenge-type: dns01
cert-manager.io/private-key-size: "4096"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
ingressClassName: nginx-internal
https: true
hosts:
- auth.dogar.dev
- auth.rihla.digital
tls:
- secretName: authentik-tls
hosts:
- auth.dogar.dev
- auth.rihla.digital
volumes:
- name: postgres-creds
secret:
secretName: authentik-postgres
- name: redis-creds
secret:
secretName: authentik-redis
volumeMounts:
- name: postgres-creds
mountPath: /postgres-creds
readOnly: true
- name: redis-creds
mountPath: /redis-creds
readOnly: true
worker:
replicas: 3
volumes:
- name: postgres-creds
secret:
secretName: authentik-postgres
- name: redis-creds
secret:
secretName: authentik-redis
volumeMounts:
- name: postgres-creds
mountPath: /postgres-creds
readOnly: true
- name: redis-creds
mountPath: /redis-creds
readOnly: true
postgresql:
enabled: false

View File

@@ -3,7 +3,7 @@ provider: pihole
policy: upsert-only
txtOwnerId: "homelab"
pihole:
server: http://pihole-web.pihole-system.svc.cluster.local
server: http://pihole-web
extraEnvVars:
- name: EXTERNAL_DNS_PIHOLE_PASSWORD
valueFrom:

View File

@@ -1,22 +1,34 @@
global:
storageClass: longhorn-crypto
image:
rootless: false
service:
http:
annotations:
metallb.universe.tf/allow-shared-ip: gitea
port: 443
targetPort: 443
ssh:
annotations:
metallb.universe.tf/allow-shared-ip: gitea
ingress:
enabled: true
className: nginx-internal
annotations:
kubernetes.io/ingress.class: nginx-internal
cert-manager.io/cluster-issuer: cloudflare-issuer
cert-manager.io/acme-challenge-type: dns01
cert-manager.io/private-key-size: "4096"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
hosts:
- host: git.dogar.dev
paths:
- path: /
pathType: Prefix
backend:
service:
name: gitea-http
port:
number: 443
tls:
- secretName: gitea-tls
hosts:
@@ -37,19 +49,23 @@ gitea:
ENABLE_GZIP: true
LFS_START_SERVER: true
SSH_DOMAIN: git.dogar.dev
HTTP_PORT: 443
PROTOCOL: https
CERT_FILE: /opt/gitea/tls/cert.pem
KEY_FILE: /opt/gitea/tls/key.pem
database:
DB_TYPE: postgres
HOST: postgres-cluster-rw.postgres-system.svc.cluster.local:5432
HOST: postgres-cluster-rw
NAME: gitea
USER: gitea
SSL_MODE: require
cache:
ADAPTER: memcache
HOST: memcached.memcached-system.svc.cluster.local:11211
ADAPTER: memory
session:
PROVIDER: db
PROVIDER_CONFIG: ""
queue:
TYPE: redis
TYPE: channel
lfs:
STORAGE_TYPE: local
service:
@@ -69,27 +85,76 @@ gitea:
iconUrl: "https://goauthentik.io/img/icon.png"
scopes: "email profile"
additionalConfigFromEnvs:
- name: GITEA__DATABASE__PASSWD
valueFrom:
secretKeyRef:
name: gitea-postgres
key: password
- name: GITEA__QUEUE__CONN_STR
valueFrom:
secretKeyRef:
name: gitea-redis
key: password
- name: GITEA__MAILER__PASSWD
valueFrom:
secretKeyRef:
name: smtp-token
key: password
key: gitea-password
livenessProbe:
enabled: true
tcpSocket:
port: 443
readinessProbe:
enabled: true
tcpSocket:
port: 443
startupProbe:
enabled: true
tcpSocket:
port: 443
persistence:
enabled: true
storageClass: longhorn-crypto
accessModes:
- ReadWriteMany
deployment:
env:
- name: PGSSLMODE
value: verify-full
- name: PGSSLROOTCERT
value: /opt/gitea/.postgresql/root.crt
- name: PGSSLCERT
value: /opt/gitea/.postgresql/postgresql.crt
- name: PGSSLKEY
value: /opt/gitea/.postgresql/postgresql.key
extraVolumes:
- name: ssl-bundle
projected:
sources:
- secret:
name: gitea-client-cert
items:
- key: tls.crt
path: postgresql.crt
- key: tls.key
path: postgresql.key
mode: 0600
- secret:
name: postgres-server-cert
items:
- key: ca.crt
path: root.crt
- name: tls-bundle
projected:
sources:
- secret:
name: gitea-tls
items:
- key: tls.crt
path: cert.pem
- key: tls.key
path: key.pem
extraInitVolumeMounts:
- name: ssl-bundle
mountPath: /opt/gitea/.postgresql
readOnly: true
extraContainerVolumeMounts:
- name: ssl-bundle
mountPath: /opt/gitea/.postgresql
readOnly: true
- name: tls-bundle
mountPath: /opt/gitea/tls
readOnly: true
postgresql-ha:
enabled: false
redis-cluster:
valkey-cluster:
enabled: false

View File

@@ -1,8 +1,10 @@
defaultSettings:
backupTarget: "s3://homelab-backups@apac/longhorn"
backupTargetCredentialSecret: longhorn-backup
defaultReplicaCount: 2
storageOverProvisioningPercentage: 100
backupCompressionMethod: "gzip"
backupConcurrentLimit: 4
defaultBackupStore:
backupTarget: "s3://homelab@auto/longhorn"
backupTargetCredentialSecret: cloudflare-token
metrics:
serviceMonitor:
enabled: true

View File

@@ -1,11 +0,0 @@
containerSecurityContext:
readOnlyRootFilesystem: false
service:
annotations:
external-dns.alpha.kubernetes.io/hostname: memcached.dogar.dev
metrics:
enabled: true
serviceMonitor:
enabled: true
interval: 10s
scrapeTimeout: 10s

View File

@@ -6,12 +6,6 @@ controller:
controllerValue: "k8s.io/ingress-nginx"
parameters: {}
ingressClass: nginx-internal
service:
annotations:
external-dns.alpha.kubernetes.io/hostname: "postgres.dogar.dev"
tcp:
22: "gitea-system/gitea-ssh:22"
5432: "postgres-system/postgres-cluster-rw:5432"
6379: "redis-system/redis-master-0:6379"
11211: "memcached-system/memcached:11211"
35432: "rihla/postgres-cluster-rw:5432"
22: "homelab/gitea-ssh:22"
25565: "minecraft/monifactory-server:25565"

View File

@@ -3,8 +3,6 @@ DNS1:
1.1.1.1
DNS2:
1.0.0.1
nodeSelector:
pihole: "true"
admin:
enabled: true
existingSecret: pihole-admin
@@ -30,19 +28,16 @@ ingress:
serviceWeb:
annotations:
metallb.universe.tf/allow-shared-ip: pihole-svc
type: LoadBalancer
loadBalancerIP: 192.168.18.250
type: ClusterIP
https:
enabled: false
serviceDns:
annotations:
metallb.universe.tf/allow-shared-ip: pihole-svc
type: LoadBalancer
loadBalancerIP: 192.168.18.250
serviceDhcp:
annotations:
metallb.universe.tf/allow-shared-ip: pihole-svc
enabled: true
type: LoadBalancer
loadBalancerIP: 192.168.18.250
enabled: false
probes:
liveness:
enabled: false
@@ -55,7 +50,6 @@ dnsmasq:
- dhcp-host=B0:41:6F:0F:A0:CD,192.168.18.12,homelab-2
hostNetwork: true
hostname: pihole
privileged: true
capabilities:
add:
- NET_ADMIN

View File

@@ -1,23 +0,0 @@
architecture: standalone
auth:
enabled: true
sentinel: true
existingSecret: redis
existingSecretPasswordKey: password
master:
persistence:
enabled: false
service:
type: LoadBalancer
annotations:
external-dns.alpha.kubernetes.io/hostname: redis.dogar.dev
replica:
replicaCount: 0
persistence:
enabled: false
sentinel:
enabled: false

View File

@@ -3,7 +3,7 @@ apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: pool
namespace: metallb-system
namespace: homelab
spec:
addresses:
- 192.168.18.192/26
@@ -12,7 +12,7 @@ apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: pool
namespace: metallb-system
namespace: homelab
spec:
ipAddressPools:
- pool

View File

@@ -10,7 +10,6 @@ type LonghornOptions = {
kubernetes: KubernetesProvider;
helm: HelmProvider;
};
version: string;
name: string;
namespace: string;
};
@@ -24,11 +23,11 @@ export class Longhorn extends Construct {
new Release(this, id, {
name: options.name,
namespace: options.namespace,
version: options.version,
provider: helm,
repository: "https://charts.longhorn.io",
chart: "longhorn",
createNamespace: true,
upgradeInstall: true,
values: [
fs.readFileSync("helm/values/longhorn.values.yaml", {
encoding: "utf8",
@@ -36,6 +35,25 @@ export class Longhorn extends Construct {
],
});
new Manifest(this, "recurring-backup-job", {
provider: kubernetes,
manifest: {
apiVersion: "longhorn.io/v1beta1",
kind: "RecurringJob",
metadata: {
name: "daily-backup",
namespace: options.namespace,
},
spec: {
cron: "0 0 * * *",
task: "backup",
retain: 30,
groups: ["default"],
concurrency: 3,
},
},
});
new Manifest(this, "longhorn-crypto-storage-class", {
provider: kubernetes,
manifest: {

107
main.ts
View File

@@ -10,11 +10,10 @@ import { OnePassword } from "./1password";
import { PostgresCluster } from "./postgres";
import { Longhorn } from "./longhorn";
import { AuthentikServer } from "./authentik";
import { RedisCluster } from "./redis";
import { ValkeyCluster } from "./valkey";
import { CertManager } from "./cert-manager";
import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest";
import { PiHole } from "./pihole";
import { MemcachedCluster } from "./memcached";
import { Nginx } from "./nginx";
import { Prometheus } from "./prometheus";
import { MetalLB } from "./metallb";
@@ -28,6 +27,8 @@ const env = cleanEnv(process.env, {
BUCKET: str({ desc: "The name of the R2 bucket." }),
});
const r2Endpoint = `https://${env.ACCOUNT_ID}.r2.cloudflarestorage.com`;
class Homelab extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id);
@@ -42,13 +43,15 @@ class Homelab extends TerraformStack {
},
});
new Manifest(this, "namespace", {
const namespace = "homelab";
const ns = new Manifest(this, "namespace", {
provider: kubernetes,
manifest: {
kind: "Namespace",
apiVersion: "v1",
metadata: {
name: "homelab",
name: namespace,
},
spec: {},
},
@@ -72,54 +75,40 @@ class Homelab extends TerraformStack {
},
});
new Longhorn(this, "longhorn", {
namespace: "longhorn-system",
const longhorn = new Longhorn(this, "longhorn", {
namespace,
name: "longhorn",
version: "1.8.2",
providers: {
kubernetes,
helm,
},
});
longhorn.node.addDependency(ns);
new MetalLB(this, "metallb", {
provider: helm,
name: "metallb",
namespace: "metallb-system",
version: "0.15.2",
namespace,
});
new OnePassword(this, "one-password", {
provider: kubernetes,
namespace,
});
new Nginx(this, "nginx", {
const nginx = new Nginx(this, "nginx", {
provider: helm,
namespace: "nginx-system",
name: "ingress-nginx-internal",
version: "4.13.0",
});
new PiHole(this, "pihole", {
namespace: "pihole-system",
provider: helm,
name: "pihole",
version: "2.26.1",
});
new Prometheus(this, "prometheus", {
provider: helm,
namespace: "prometheus-system",
name: "prometheus-operator",
version: "75.10.0",
namespace,
name: "nginx-ingress",
});
const certManagerApiVersion = "cert-manager.io/v1";
new CertManager(this, "cert-manager", {
const cm = new CertManager(this, "cert-manager", {
certManagerApiVersion,
name: "cert-manager",
namespace: "cert-manager",
namespace,
version: "1.18.2",
providers: {
kubernetes,
@@ -127,47 +116,64 @@ class Homelab extends TerraformStack {
},
});
new PostgresCluster(this, "postgres-cluster", {
const pihole = new PiHole(this, "pihole", {
namespace,
provider: helm,
name: "pihole",
});
pihole.node.addDependency(longhorn);
pihole.node.addDependency(nginx);
pihole.node.addDependency(cm);
new Prometheus(this, "prometheus", {
provider: helm,
namespace,
name: "prometheus-operator",
version: "75.10.0",
});
const pg = new PostgresCluster(this, "postgres-cluster", {
certManagerApiVersion,
version: "0.24.0",
name: "postgres-cluster",
namespace: "postgres-system",
namespace,
providers: {
kubernetes,
helm,
},
storageClass: "longhorn-crypto",
users: ["shahab", "budget-tracker"],
users: ["shahab", "budget-tracker", "authentik", "gitea"],
primaryUser: "shahab",
initSecretName: "postgres-password",
backupR2EndpointURL: `https://${env.ACCOUNT_ID}.r2.cloudflarestorage.com`,
backupR2EndpointURL: r2Endpoint,
});
new RedisCluster(this, "redis-cluster", {
provider: helm,
namespace: "redis-system",
name: "redis",
pg.node.addDependency(pihole);
const valkey = new ValkeyCluster(this, "valkey-cluster", {
provider: kubernetes,
namespace,
name: "valkey",
});
new MemcachedCluster(this, "memcached-cluster", {
provider: helm,
namespace: "memcached-system",
name: "memcached",
});
valkey.node.addDependency(pihole);
new AuthentikServer(this, "authentik-server", {
const authentik = new AuthentikServer(this, "authentik-server", {
provider: helm,
name: "authentik",
namespace: "authentik-system",
version: "2025.8.1",
namespace,
});
new GiteaServer(this, "gitea-server", {
authentik.node.addDependency(pg);
authentik.node.addDependency(valkey);
const gitea = new GiteaServer(this, "gitea-server", {
name: "gitea",
namespace: "gitea-system",
namespace,
provider: helm,
version: "12.1.1",
});
gitea.node.addDependency(authentik);
}
}
@@ -175,6 +181,7 @@ const app = new App();
const stack = new Homelab(app, "homelab");
new S3Backend(stack, {
encrypt: true,
bucket: env.BUCKET,
key: "terraform.tfstate",
region: "auto",
@@ -186,7 +193,7 @@ new S3Backend(stack, {
accessKey: env.R2_ACCESS_KEY_ID,
secretKey: env.R2_SECRET_ACCESS_KEY,
endpoints: {
s3: `https://${env.ACCOUNT_ID}.r2.cloudflarestorage.com/${env.BUCKET}`,
s3: `${r2Endpoint}/${env.BUCKET}`,
},
});

View File

@@ -6,7 +6,6 @@ type MetalLBOptions = {
provider: HelmProvider;
name: string;
namespace: string;
version: string;
};
export class MetalLB extends Construct {

View File

@@ -7,7 +7,6 @@ type NginxOptions = {
provider: HelmProvider;
name: string;
namespace: string;
version: string;
};
export class Nginx extends Construct {

View File

@@ -5,7 +5,6 @@ import { Construct } from "constructs";
type PiHoleOptions = {
provider: HelmProvider;
version: string;
name: string;
namespace: string;
};
@@ -18,7 +17,7 @@ export class PiHole extends Construct {
...options,
repository: "https://mojo2600.github.io/pihole-kubernetes",
chart: "pihole",
createNamespace: true,
version: "2.26.1",
values: [
fs.readFileSync("helm/values/pihole.values.yaml", {
encoding: "utf8",
@@ -30,7 +29,7 @@ export class PiHole extends Construct {
provider: options.provider,
name: "externaldns-pihole",
namespace: options.namespace,
repository: "https://charts.bitnami.com/bitnami",
repository: "oci://registry-1.docker.io/bitnamicharts/",
chart: "external-dns",
values: [
fs.readFileSync("helm/values/externaldns.values.yaml", {

View File

@@ -16,7 +16,6 @@ type PostgresClusterOptions = {
primaryUser: string;
initSecretName: string;
certManagerApiVersion: string;
version: string;
backupR2EndpointURL: string;
};
@@ -28,27 +27,27 @@ export class PostgresCluster extends Construct {
new Release(this, "cnpg-operator", {
provider: helm,
version: options.version,
repository: "https://cloudnative-pg.github.io/charts",
chart: "cloudnative-pg",
name: "postgres-system",
namespace: options.namespace,
namespace: "cnpg-system",
});
const destinationPath = "s3://homelab-backups/";
const destinationPath = "s3://homelab/";
const endpointURL = options.backupR2EndpointURL;
const barmanStoreName = "r2-postgres-backup-store";
const barmanConfiguration = {
destinationPath,
endpointURL,
s3Credentials: {
accessKeyId: {
name: "cloudflare-r2-token",
key: "access_key",
name: "cloudflare-token",
key: "access_key_id",
},
secretAccessKey: {
name: "cloudflare-r2-token",
key: "secret_key",
name: "cloudflare-token",
key: "secret_access_key",
},
},
};
@@ -60,7 +59,7 @@ export class PostgresCluster extends Construct {
kind: "ObjectStore",
metadata: {
namespace: options.namespace,
name: "r2-postgres-backup-store-homelab",
name: barmanStoreName,
},
spec: {
configuration: {
@@ -178,9 +177,8 @@ export class PostgresCluster extends Construct {
secretName: certNames.server,
usages: ["server auth"],
dnsNames: [
"postgres-cluster-rw.postgres-system.svc.cluster.local",
"postgres-cluster-ro.postgres-system.svc.cluster.local",
"postgres-cluster-r.postgres-system.svc.cluster.local",
"postgres-cluster-rw",
"postgres-cluster-rw.homelab.svc.cluster.local",
"postgres.dogar.dev",
],
duration: "4380h", // 6 months
@@ -342,7 +340,7 @@ export class PostgresCluster extends Construct {
enabled: true,
isWALArchiver: true,
parameters: {
barmanObjectName: "r2-postgres-backup-store",
barmanObjectName: barmanStoreName,
},
},
],
@@ -396,7 +394,7 @@ export class PostgresCluster extends Construct {
storageClass: options.storageClass,
},
walStorage: {
size: "10Gi",
size: "1Gi",
storageClass: options.storageClass,
},
},