From d3cea1aecda09ff1274937d3480097d05a6b4798 Mon Sep 17 00:00:00 2001 From: Daniel Cosme Date: Thu, 30 Apr 2026 18:05:24 -0400 Subject: [PATCH] Add Immich Stack --- apps/hydra/immich/kuztomization.yaml | 7 ++++ apps/hydra/immich/namespace.yaml | 6 +++ apps/hydra/linkding/deployment.yaml | 10 ++--- apps/hydra/linkding/kuztomization.yaml | 2 +- apps/hydra/linkding/pvc.yaml | 2 +- apps/hydra/linkding/srv.yaml | 6 +-- cmd/apps/main.go | 2 + .../hydra/cloud-native-pg/pg-cluster.yaml | 1 + .../hydra/truenas-csi/kuztomization.yaml | 14 +++---- pkg/cnpg/cluster.go | 35 ++++++++++++++++++ pkg/cnpg/cnpg.go | 20 ---------- pkg/immich/immich.go | 37 +++++++++++++++++++ pkg/linkding/linkding.go | 8 ++-- pkg/root/services.go | 21 ++++++++++- 14 files changed, 128 insertions(+), 43 deletions(-) create mode 100644 apps/hydra/immich/kuztomization.yaml create mode 100644 apps/hydra/immich/namespace.yaml create mode 100644 pkg/cnpg/cluster.go create mode 100644 pkg/immich/immich.go diff --git a/apps/hydra/immich/kuztomization.yaml b/apps/hydra/immich/kuztomization.yaml new file mode 100644 index 0000000..fa62a71 --- /dev/null +++ b/apps/hydra/immich/kuztomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +metadata: + name: immich + namespace: immich +resources: +- namespace.yaml diff --git a/apps/hydra/immich/namespace.yaml b/apps/hydra/immich/namespace.yaml new file mode 100644 index 0000000..359f8f7 --- /dev/null +++ b/apps/hydra/immich/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: immich +spec: {} +status: {} diff --git a/apps/hydra/linkding/deployment.yaml b/apps/hydra/linkding/deployment.yaml index dd3ca40..604f9f6 100644 --- a/apps/hydra/linkding/deployment.yaml +++ b/apps/hydra/linkding/deployment.yaml @@ -2,18 +2,18 @@ apiVersion: apps/v1 kind: Deployment metadata: labels: - app: linking - name: linking + app: linkding + name: linkding namespace: linkding spec: selector: matchLabels: - app: linking + app: linkding strategy: {} template: metadata: labels: - app: linking + app: linkding spec: containers: - env: @@ -46,5 +46,5 @@ spec: volumes: - name: data persistentVolumeClaim: - claimName: linking-pvc + claimName: linkding-pvc status: {} diff --git a/apps/hydra/linkding/kuztomization.yaml b/apps/hydra/linkding/kuztomization.yaml index c922b44..61fcd21 100644 --- a/apps/hydra/linkding/kuztomization.yaml +++ b/apps/hydra/linkding/kuztomization.yaml @@ -1,7 +1,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization metadata: - name: linking + name: linkding namespace: linkding resources: - namespace.yaml diff --git a/apps/hydra/linkding/pvc.yaml b/apps/hydra/linkding/pvc.yaml index 59f272d..47cc9f9 100644 --- a/apps/hydra/linkding/pvc.yaml +++ b/apps/hydra/linkding/pvc.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: linking-pvc + name: linkding-pvc namespace: linkding spec: accessModes: diff --git a/apps/hydra/linkding/srv.yaml b/apps/hydra/linkding/srv.yaml index 18f142e..6469f94 100644 --- a/apps/hydra/linkding/srv.yaml +++ b/apps/hydra/linkding/srv.yaml @@ -2,8 +2,8 @@ apiVersion: v1 kind: Service metadata: labels: - app: linking - name: linking + app: linkding + name: linkding namespace: linkding spec: ports: @@ -11,7 +11,7 @@ spec: port: 9090 targetPort: 0 selector: - app: linking + app: linkding type: NodePort status: loadBalancer: {} diff --git a/cmd/apps/main.go b/cmd/apps/main.go index 93fee66..d83be59 100644 --- a/cmd/apps/main.go +++ b/cmd/apps/main.go @@ -7,6 +7,7 @@ import ( "danicos.dev/daniel/go-kube/pkg/stack" "danicos.dev/daniel/homelab/pkg/cnpg" "danicos.dev/daniel/homelab/pkg/flux" + "danicos.dev/daniel/homelab/pkg/immich" "danicos.dev/daniel/homelab/pkg/linkding" "danicos.dev/daniel/homelab/pkg/longhorn" "danicos.dev/daniel/homelab/pkg/monitoring" @@ -37,6 +38,7 @@ func main() { hydra_apps := map[string]stack.Stack{ "linkding": linkding.Stack(), + "immich": immich.Stack(), } for name, s := range hydra_apps { fmt.Printf("STACK: %s\n", name) diff --git a/infrastructure/hydra/cloud-native-pg/pg-cluster.yaml b/infrastructure/hydra/cloud-native-pg/pg-cluster.yaml index 9a996fa..66fbd9b 100644 --- a/infrastructure/hydra/cloud-native-pg/pg-cluster.yaml +++ b/infrastructure/hydra/cloud-native-pg/pg-cluster.yaml @@ -6,6 +6,7 @@ metadata: spec: affinity: {} instances: 3 + managed: {} postgresql: syncReplicaElectionConstraint: enabled: false diff --git a/infrastructure/hydra/truenas-csi/kuztomization.yaml b/infrastructure/hydra/truenas-csi/kuztomization.yaml index 9ee4573..413913b 100644 --- a/infrastructure/hydra/truenas-csi/kuztomization.yaml +++ b/infrastructure/hydra/truenas-csi/kuztomization.yaml @@ -4,16 +4,16 @@ metadata: name: truenas-csi namespace: truenas-csi resources: +- namespace.yaml +- controller-service-account.yaml - controller-cluster-role.yaml - controller-binding.yaml -- node-cluster-role.yaml -- CSIDriver.yaml -- nfs-storage-class.yaml - node-service-account.yaml -- node-binding.yaml - node-deamonset.yaml +- CSIDriver.yaml - config.yaml -- iscsi-storage-class.yaml -- namespace.yaml - controller-deployment.yaml -- controller-service-account.yaml +- node-cluster-role.yaml +- node-binding.yaml +- nfs-storage-class.yaml +- iscsi-storage-class.yaml diff --git a/pkg/cnpg/cluster.go b/pkg/cnpg/cluster.go new file mode 100644 index 0000000..6032acd --- /dev/null +++ b/pkg/cnpg/cluster.go @@ -0,0 +1,35 @@ +package cnpg + +import ( + "danicos.dev/daniel/go-kube/pkg/kube" + "danicos.dev/daniel/homelab/pkg/root" + + kube_cnpg "danicos.dev/daniel/go-kube/pkg/cnpg" + pg "github.com/cloudnative-pg/api/pkg/api/v1" + core "k8s.io/api/core/v1" +) + +func Cluster() pg.Cluster { + meta := kube.NewMetadata(root.CloudNativePG+"-cluster", PGClusterNamespace) + spec := pg.ClusterSpec{ + Instances: 3, + StorageConfiguration: pg.StorageConfiguration{ + StorageClass: new(root.KUBE_LOCAL_STORAGE_CLASS), + Size: "10Gi", + ResizeInUseVolumes: new(true), + PersistentVolumeClaimTemplate: &core.PersistentVolumeClaimSpec{ + StorageClassName: new(root.KUBE_LOCAL_STORAGE_CLASS), + }, + }, + Managed: &pg.ManagedConfiguration{ + Roles: []pg.RoleConfiguration{}, + }, + } + return kube_cnpg.NewCluster(meta, spec) +} + +/* + Need a role and secret + - Username + - Password +*/ diff --git a/pkg/cnpg/cnpg.go b/pkg/cnpg/cnpg.go index 79f4810..91b1710 100644 --- a/pkg/cnpg/cnpg.go +++ b/pkg/cnpg/cnpg.go @@ -4,10 +4,6 @@ import ( "danicos.dev/daniel/go-kube/pkg/kube" "danicos.dev/daniel/go-kube/pkg/stack" "danicos.dev/daniel/homelab/pkg/root" - v1 "k8s.io/api/core/v1" - - kube_cnpg "danicos.dev/daniel/go-kube/pkg/cnpg" - pg "github.com/cloudnative-pg/api/pkg/api/v1" ) var meta kube.Metadata @@ -28,19 +24,3 @@ func Stack() stack.Stack { }) return s } - -func Cluster() pg.Cluster { - meta := kube.NewMetadata(root.CloudNativePG+"-cluster", PGClusterNamespace) - spec := pg.ClusterSpec{ - Instances: 3, - StorageConfiguration: pg.StorageConfiguration{ - StorageClass: new(root.KUBE_LOCAL_STORAGE_CLASS), - Size: "10Gi", - ResizeInUseVolumes: new(true), - PersistentVolumeClaimTemplate: &v1.PersistentVolumeClaimSpec{ - StorageClassName: new(root.KUBE_LOCAL_STORAGE_CLASS), - }, - }, - } - return kube_cnpg.NewCluster(meta, spec) -} diff --git a/pkg/immich/immich.go b/pkg/immich/immich.go new file mode 100644 index 0000000..da798ba --- /dev/null +++ b/pkg/immich/immich.go @@ -0,0 +1,37 @@ +package immich + +import ( + "danicos.dev/daniel/go-kube/pkg/kube" + "danicos.dev/daniel/go-kube/pkg/stack" + "danicos.dev/daniel/homelab/pkg/root" + core "k8s.io/api/core/v1" +) + +var Secret = struct { + Name string + DB_UserKey string + DB_PasswordKey string +}{ + Name: root.Immich.Name, + DB_UserKey: "db_username", + DB_PasswordKey: "db_password", +} + +var meta kube.Metadata +var Namespace = kube.Namespace(root.Immich.Name) +var srv core.Service +var pvc core.PersistentVolumeClaim + +func init() { + meta = kube.NewMetadata(root.Immich.Name, Namespace) +} + +func Stack() stack.Stack { + kz := kube.NewKuztomizedStack( + meta, + map[string]any{ + "namespace": Namespace, + }, + ) + return kz.Stack("immich") +} diff --git a/pkg/linkding/linkding.go b/pkg/linkding/linkding.go index b0977eb..782f8a1 100644 --- a/pkg/linkding/linkding.go +++ b/pkg/linkding/linkding.go @@ -19,15 +19,15 @@ var Secret = struct { } var meta kube.Metadata -var Namespace = kube.Namespace("linkding") +var Namespace = kube.Namespace(root.Linkding.Name) var srv core.Service var pvc core.PersistentVolumeClaim func init() { - meta = kube.NewMetadata("linking", Namespace) + meta = kube.NewMetadata(root.Linkding.Name, Namespace) srv = meta.Service(root.Linkding.Port) srv.Spec.Type = core.ServiceTypeNodePort - srv.Spec.Ports[0].NodePort = 30010 + srv.Spec.Ports[0].NodePort = int32(root.Linkding.Public.NodePort) pvc = meta.PVC() } @@ -47,7 +47,7 @@ func Stack() stack.Stack { func deployment() apps.Deployment { storage := kube.NewVolumeFrom(kube.VolumeSourcePVC, "data", pvc.Name) envMapping := map[string]string{ - "LD_CSRF_TRUSTED_ORIGINS": root.Linkding.PublicURL, + "LD_CSRF_TRUSTED_ORIGINS": root.Linkding.Public.URL, } secretMapping := map[string]string{ "LD_SUPERUSER_NAME": Secret.SuperUserKey, diff --git a/pkg/root/services.go b/pkg/root/services.go index 26022de..9ee4f8e 100644 --- a/pkg/root/services.go +++ b/pkg/root/services.go @@ -3,17 +3,34 @@ package root type Service struct { Name string Image string - PublicURL string Port int32 SecurityContextID int64 + Public *Public + Postgres *Postgres } +type Public struct { + URL string + NodePort int32 +} + +type Postgres struct{} + var Linkding = Service{ Name: "linkding", Image: "sissbruecker/linkding:1.45.0", - PublicURL: "https://link.danicos.me", Port: 9090, SecurityContextID: 33, // www-data user, group and FS ID + Public: &Public{ + URL: "https://link.danicos.me", + NodePort: 30010, + }, +} + +var Immich = Service{ + Name: "immich", + Image: "", + // PublicURL: "https://photos.danicos.me", } var (