Compare commits

...

37 Commits

Author SHA1 Message Date
bc910787df Open for node port 2025-12-04 03:07:18 -06:00
4e16bfc88e Add DB for Nextcloud 2025-12-04 03:02:23 -06:00
3b8be5c7ee Add DB for Nextcloud 2025-12-04 03:02:16 -06:00
6243db3cba Swap to using externalDb because Nextcloud chart absolutely sucks with defining custom values for the login info of the DB... 2025-12-04 03:02:01 -06:00
cff8972366 Fix Gitea c: 2025-12-04 03:01:19 -06:00
7aeee2f3c5 Alpha build at long last, finished 2025-12-03 01:39:57 -06:00
63b859b576 Add Velero and all remaining Matrix resources 2025-12-03 01:36:59 -06:00
96363ed7ca Add Velero 2025-12-03 01:36:46 -06:00
23b479a851 Add Velero annotations 2025-12-03 01:36:29 -06:00
8ad304a663 Define MMR DB 2025-12-03 01:35:58 -06:00
c6785f0b9b Flesh out homeserver 2025-12-03 01:35:41 -06:00
6b260de324 Clean up and remove httproute 2025-12-03 01:34:27 -06:00
07216ddae5 Properly set up DB for discord bridge 2025-12-03 01:33:57 -06:00
e26b421d44 Add Discord Bridge 2025-12-03 01:32:53 -06:00
e0c9e71fda Set correct port and add name 2025-12-03 01:32:38 -06:00
ae903af93c Add Matrix stack 2025-11-30 05:23:52 -06:00
11af17cd8a Add new resources 2025-11-30 05:23:39 -06:00
b0f9fa7205 Add to firewall 2025-11-30 05:23:25 -06:00
87fdd5b2fe Fix Prometheus 2025-11-30 05:23:13 -06:00
97ebd04d99 Fix Nextcloud (wtf broadcom) 2025-11-30 05:22:46 -06:00
e5ce37638e Define coturn (not enabling for awhile tho) 2025-11-30 05:22:28 -06:00
a920a01815 quickly outline mmr-db 2025-11-30 05:21:57 -06:00
0ac3993314 Define DB for just mautrix 2025-11-30 05:21:22 -06:00
bc6fc1dafe Split DB into two and delete the single resource here 2025-11-30 05:21:08 -06:00
350c7db62a Define MMR 2025-11-30 05:20:12 -06:00
01e405d125 Moved livekit into element-call 2025-11-30 05:19:53 -06:00
089f7045cc Since no more Caddy, Well-known needs to be split into its own resource 2025-11-30 05:19:30 -06:00
2be11cec39 Begin defining our homeserver 2025-11-30 05:19:05 -06:00
0b5e4285c7 Define Livekit Server 2025-11-30 05:18:47 -06:00
a3422f0e84 Define Livekit JWT 2025-11-30 05:18:31 -06:00
5261340c9e Define Element call 2025-11-30 05:18:20 -06:00
3caeb8cc0d Define Element 2025-11-30 05:17:58 -06:00
6e6410c824 Define Cinny 2025-11-30 05:15:29 -06:00
68946832dc add homeassistant 2025-11-30 05:15:17 -06:00
93da50fba1 Swap to using s3 w/ pvc and juicefs 2025-11-30 05:15:01 -06:00
2db2c19461 Add name to service port 2025-11-30 05:13:26 -06:00
ab7c7a1e04 Add name to service port 2025-11-30 05:13:16 -06:00
27 changed files with 837 additions and 152 deletions

View File

@@ -1,10 +1,10 @@
{:paths ["src/main"]
:deps {
#_gigiaj/pulumicljs #_{:local/root "../pulumi-clojurescript"}
;;gigiaj/pulumicljs {:local/root "../pulumi-clojurescript"}
gigiaj/pulumicljs
{:git/url "https://github.com/GigiaJ/pulumi-clojurescript.git"
:git/sha "5c85ae0ae5a4f99cd6b1eaa765b6a5d9854db08f"
:git/sha "b7467d9da44a86a185e3bfe4307a7fe71add4134"
}
funcool/promesa {:mvn/version "11.0.678"}
}}

View File

@@ -10,7 +10,8 @@
initialize-resources-definition
shared-resources-definition
preparation-resources-definition
deployment-resources-definition]]
deployment-resources-definition
matrix-resources-definition]]
)
(:require-macros [pulumicljs.execution.general :refer [p->]]))
@@ -49,9 +50,10 @@
#(execute
shared-resources-definition
(fn [output] (let [secrets (p-> output .-harbor "vault:prepare" "stringData")]
#js {:url (p-> secrets .-host (fn [x] (str "https://" x)))
:username (p-> secrets .-username)
:password (p-> secrets .-password)})))))
#js {
:url (p-> secrets .-host (fn [x] (str "https://" x)))
:username (p-> secrets .-username)
:password (p-> secrets .-password)})))))
(def prepare-deployment-stack
(define-stack
@@ -67,6 +69,13 @@
"/home/jaggar/dotfiles/iac"
#(execute deployment-resources-definition (fn [output] {}))))
(def matrix-stack
(define-stack
"hetzner-k3s"
"matrix"
"/home/jaggar/dotfiles/iac"
#(execute matrix-resources-definition (fn [output] {}))))
(defn deploy-stack
([stack-definition inputs]
@@ -109,9 +118,10 @@
shared-outputs (deploy-stack shared-platform-stack
(conj reused-configs {:name "hetzner-k3s:apiToken" :value (-> cfg :apiToken) :secret true})
1000)
1000)
prepare-outputs (deploy-stack prepare-deployment-stack reused-configs 3000)
deployment-outputs (deploy-stack deployment-stack reused-configs 2000)
matrix-outputs (deploy-stack matrix-stack reused-configs 2000)
_ (.kill port-forward)]
"All stacks deployed and cleaned up successfully."))

View File

@@ -69,7 +69,10 @@
{:direction "in" :protocol "udp" :port "51820" :sourceIps ["0.0.0.0/0" "::/0"]}
{:direction "in" :protocol "tcp" :port "80" :sourceIps ["0.0.0.0/0" "::/0"]}
{:direction "in" :protocol "tcp" :port "443" :sourceIps ["0.0.0.0/0" "::/0"]}
{:direction "in" :protocol "icmp" :sourceIps ["0.0.0.0/0" "::/0"]}]}))
{:direction "in" :protocol "tcp" :port "30022" :sourceIps ["0.0.0.0/0" "::/0"]}
{:direction "in" :protocol "icmp" :sourceIps ["0.0.0.0/0" "::/0"]}
{:direction "in" :protocol "udp" :port "31000-31100" :sourceIps ["0.0.0.0/0" "::/0"]}
]}))
master (hcloud/Server.
"k3s-master-de"

View File

@@ -39,4 +39,5 @@
{:metadata {:name "juicefs-redis" :namespace "kube-system"}
:spec {:type "ClusterIP"
:selector {:app "juicefs-redis"}
:ports [{:port 6379 :targetPort 6379}]}}})
:ports [{:name 'app-name
:port 6379 :targetPort 6379}]}}})

View File

@@ -54,6 +54,7 @@
:k8s:service-opts
{:spec
{:ports
[{:port 80
[{:name 'app-name
:port 80
:targetPort 80}]}}})

View File

@@ -1,25 +1,51 @@
(ns k8s.services.gitea.service)
(def config
{:stack [:vault:prepare :k8s:deployment :k8s:service :k8s:httproute]
:image-port 3000
{:stack [:vault:prepare :k8s:pvc :k8s:deployment :k8s:service :k8s:httproute :k8s:tcproute]
:app-namespace "generic"
:app-name "gitea"
:k8s:deployment-opts {:spec {:template {:spec {:initContainers [
{:name "init-permissions"
:image "busybox:latest"
:command ["sh" "-c" "chown -R 1000:1000 /var/lib/gitea && chown -R 1000:1000 /etc/gitea"]
:volumeMounts [{:name "gitea-data" :mountPath "/var/lib/gitea"}
{:name "gitea-config" :mountPath "/etc/gitea"}]
:securityContext {:runAsUser 0 :runAsGroup 0}}
]
:containers [{:name 'app-name :image '(str repo "/" app-name ":latest-rootless")
:volumeMounts [{:name "gitea-data" :mountPath "/var/lib/gitea"}
{:name "gitea-config" :mountPath "/etc/gitea"}
{:name "timezone" :mountPath "/etc/timezone" :readOnly true}
{:name "localtime" :mountPath "/etc/localtime" :readOnly true}]}]
:volumes [{:name "gitea-data" :hostPath {:path "/opt/gitea/data" :type "DirectoryOrCreate"}}
{:name "gitea-config" :hostPath {:path "/opt/gitea/config" :type "DirectoryOrCreate"}}
{:name "timezone" :hostPath {:path "/etc/timezone" :type "File"}}
{:name "localtime" :hostPath {:path "/etc/localtime" :type "File"}}]}}}}
:k8s:httproute-opts {:spec {::hostnames ['host]}}})
:image-port 3000
:k8s:pvc-opts
{:metadata {:name "gitea-state"
:namespace "generic"}
:spec {:storageClassName "juicefs-sc"
:accessModes ["ReadWriteMany"]
:resources {:requests {:storage "1Ti"}}}}
:k8s:deployment-opts
{:spec
{:template
{:metadata {:annotations {"backup.velero.io/backup-volumes" "gitea-state"}}
:spec
{:containers
[{:name 'app-name
:image '(str repo "/" app-name ":latest-rootless")
:command ["/usr/local/bin/gitea"]
:args ["web"
"-c" "/var/lib/gitea/custom/conf/app.ini"]
:env [{:name "TZ" :value "America/Chicago"}]
:envFrom [{:secretRef {:name "gitea-secrets"}}]
:ports [{:name "ssh" :containerPort 2222}]
:volumeMounts [{:name "gitea-state" :mountPath "/var/lib/gitea"}]}]
:volumes
[{:name "gitea-state"
:persistentVolumeClaim {:claimName "gitea-state"}}]}}}}
:k8s:service-opts
{:spec
{:type "NodePort"
:selector {:app "gitea"}
:ports [{:name 'app-name :port 3000 :targetPort 3000}
{:name "ssh"
:port 22
:targetPort 2222
:nodePort 30022}]}}
:k8s:httproute-opts {:spec {::hostnames ['host]
:rules [{:matches [{:path {:type "PathPrefix"
:value "/"}}]
:backendRefs [{:name 'app-name
:port 3000}]}]}}})

View File

@@ -0,0 +1,34 @@
(ns k8s.services.homeassistant.service)
(def config
{:stack [:vault:prepare :k8s:pvc :k8s:deployment :k8s:service :k8s:httproute]
:image-port 8123
:app-namespace "home"
:app-name "homeassistant"
:k8s:pvc-opts
{"ha-config" {:storageClass "hcloud-volumes"
:accessModes ["ReadWriteOnce"]
:storage "10Gi"}}
:k8s:deployment-opts
{:spec
{:template
{:spec
{:containers
[{:name 'app-name
:image '(str repo "/home-assistant:stable")
:env [{:name "TZ" :value "America/Chicago"}]
:volumeMounts [{:name "config" :mountPath "/config"}]}]
:volumes
[{:name "config" :persistentVolumeClaim {:claimName "ha-config"}}]}}}}
:k8s:service-opts
{:spec {:selector {:app 'app-name}
:ports [{:name 'app-name :port 8123 :targetPort 8123}]}}
:k8s:httproute-opts
{:spec
{:hostnames ['host]
:rules [{:matches [{:path {:type "PathPrefix" :value "/"}}]
:backendRefs [{:name 'app-name :port 8123}]}]}}})

View File

@@ -1,12 +1,29 @@
(ns k8s.services.matrix.cinny.service)
(def config
{:stack [:vault-secrets :docker-image :deployment :service :ingress]
:image-port 80
{:stack [:vault:prepare
:harbor:robot-account
:docker:image
[:k8s :deployment :service :httproute]]
:app-namespace "matrix"
:app-name "cinny"
:image-opts {:build {:args {:FOUNDRY_USERNAME 'FOUNDRY_USERNAME
:FOUNDRY_PASSWORD 'FOUNDRY_PASSWORD}}
:imageName '(str repo "/" app-name ":latest")}
:deployment-opts {:spec {:template {:spec {:imagePullSecrets [{:name "harbor-creds-secrets"}]
:containers [{:name 'app-name :image '(str repo "/" app-name ":latest")}]}}}}})
:docker:image-opts {:context {:location "https://github.com/GigiaJ/cinny.git"}
:imageName '(str registry-base "/" registry-namespace "/" app-name ":latest")
:registry {:server '(str registry-base "/" registry-namespace)
:username '(-> :harbor:robot-account .-name)
:password '(-> :harbor:robot-account .-secret)}
:tags ['(str registry-base "/" registry-namespace "/" app-name)]
:push true}
:harbor:robot-account-opts {:name 'app-name
:permissions [{:kind "project"
:namespace 'registry-namespace
:access [{:action "pull" :resource "repository"}
{:action "push" :resource "repository"}
{:action "list" :resource "repository"}]}]}
:k8s:deployment-opts {:spec {:template {:spec {:imagePullSecrets [{:name "harbor-creds-secrets"}]
:containers [{:name 'app-name
:image '(str registry-base "/" registry-namespace "/" app-name ":latest")
:ports [{:containerPort 80}]}]}}}}
:k8s:httproute-opts {:spec {::hostnames ['host]}}})

View File

@@ -1,13 +0,0 @@
(ns k8s.services.matrix.database.service)
;; env_file:
;; - .env
;; volumes:
;; - ${PWD}/db-data/:/var/lib/postgresql/data/
(def config
{:stack [:deployment :service :ingress]
:image-port 80
:app-namespace "matrix"
:app-name "postgres"
:deployment-opts {:spec {:template {:spec {:containers [{:name 'app-name :image '(str repo "/" 'app-name ":latest")}]}}}}})

View File

@@ -1,14 +1,69 @@
;; volumes:
;; - ./personal/matrix/element-config.json:/app/config.json
;; environment:
;; ELEMENT_WEB_PORT: 3030
(ns k8s.services.matrix.element.service)
(def config
{:stack [:vault-secrets :docker-image :deployment :service :ingress]
:image-port 80
{:stack [:vault:prepare [:k8s :config-map :deployment :service :httproute]]
:image-port 80
:app-namespace "matrix"
:app-name "element"
:deployment-opts {:spec {:template {:spec {:imagePullSecrets [{:name "harbor-creds-secrets"}]
:containers [{:name 'app-name :image '(str repo "/" app-name ":latest")}]}}}}})
:app-name "element-web"
:k8s:config-map-opts {:data {"config.json"
'(stringify
{:default_server_name homeserver
:default_server_config
{:m.homeserver
{:base_url (str "https://" homeserver)}
:m.identity_server
{:base_url identity-server}}
:brand brand-name
:integrations_ui_url "https://scalar.vector.im/"
:integrations_rest_url "https://scalar.vector.im/api"
:integrations_widgets_urls
["https://scalar.vector.im/_matrix/integrations/v1"
"https://scalar.vector.im/api"
"https://scalar-staging.vector.im/_matrix/integrations/v1"
"https://scalar-staging.vector.im/api"
"https://scalar-staging.riot.im/scalar/api"]
:bug_report_endpoint_url "https://element.io/bugreports/submit"
:uisi_autorageshake_app "element-auto-uisi"
:show_labs_settings true
:room_directory
{:servers [homeserver]}
:enable_presence_by_hs_url
{"https://matrix.org" false
"https://matrix-client.matrix.org" false}
:terms_and_conditions_links
[{:url (str "https://" homeserver "/privacy")
:text "Privacy Policy"}
{:url (str "https://" homeserver "/cookie-policy")
:text "Cookie Policy"}]
:sentry
{:dsn "https://029a0eb289f942508ae0fb17935bd8c5@sentry.matrix.org/6"
:environment "develop"}
:posthog
{:project_api_key "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO"
:api_host (str "https://posthog." homeserver)}
:privacy_policy_url (str "https://" homeserver "/cookie-policy")
:features
{:threadsActivityCentre true
:feature_video_rooms true
:feature_group_calls true
:feature_element_call_video_rooms true}
:setting_defaults
{:RustCrypto.staged_rollout_percent 100
:Registration.mobileRegistrationHelper true}
:element_call
{:url (str "https://livekit." homeserver)}
:map_style_url "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"})}}
:k8s:deployment-opts {:spec
{:template
{:spec
{:volumes [{:name "config-vol"
:configMap {:name 'app-name}}]
:containers [{:name 'app-name :image '(str repo "/" app-name ":latest")
:env [{:name "ELEMENT_WEB_PORT" :value "80"}]
:volumeMounts [{:name "config-vol"
:mountPath "/app/config.json"
:subPath "config.json"}]}]}}}}
:k8s:httproute-opts {:spec {::hostnames ['host]}}})

View File

@@ -0,0 +1,22 @@
(ns k8s.services.matrix.element-call.livekit-jwt.service)
(def config
{:stack [:vault:prepare [:k8s :deployment :service :httproute]]
:image-port 8080
:app-namespace "matrix"
:app-name "livekit-jwt"
:k8s:deployment-opts {:spec
{:template
{:spec
{:containers [{:name 'app-name :image '(str repo "/" "lk-jwt-service" ":latest")
:env [{:name "LIVEKIT_KEY" :value 'key-name}
{:name "LIVEKIT_SECRET" :value 'dev-key}
{:name "LIVEKIT_JWT_PORT" :value "8080"}
{:name "LIVEKIT_URL" :value 'livekit-url}]}]}}}}
:k8s:httproute-opts
{:spec
{:hostnames ['host]
:rules [{:matches [{:path {:type "PathPrefix" :value "/livekit/jwt"}}]
:backendRefs [{:name 'app-name :port 80}]}
{:matches [{:path {:type "PathPrefix" :value "/sfu/get"}}]
:backendRefs [{:name 'app-name :port 80}]}]}}})

View File

@@ -0,0 +1,76 @@
(ns k8s.services.matrix.element-call.livekit-server.service)
(defn generate-all-ports [tcp-port start-udp end-udp]
(concat
[{:name "http"
:port tcp-port
:targetPort tcp-port
:containerPort tcp-port
:protocol "TCP"}]
(map (fn [p]
{:name (str "udp-" p)
:port p
:targetPort p
:nodePort p
:containerPort p
:protocol "UDP"})
(range start-udp (inc end-udp)))))
(def all-ports (generate-all-ports 7880 31000 31100))
(def config
{:stack [:vault:prepare [:k8s :config-map :deployment :service :httproute]]
:image-port nil
:app-namespace "matrix"
:app-name "livekit-server"
:k8s:config-map-opts
{:metadata {:name "livekit-config"}
:data {"livekit.yaml"
'(stringify
{:port 7880
:bind_addresses ["0.0.0.0"]
:rtc {:tcp_port 7881
:port_range_start 31000
:port_range_end 31100
:use_external_ip true} ;; Required for Hetzner Public IP discovery
:logging {:level "debug"}
:turn {:enabled false
:udp_port 443
:tls_port 5349}
:keys {:devkey dev-key}})}}
:k8s:deployment-opts
{:spec
{:template
{:spec
{:volumes [{:name "config-vol" :configMap {:name "livekit-config"}}]
:containers [{:name 'app-name
:image '(str repo "/" app-name ":latest")
:command ["/livekit-server"]
:args ["--config" "/etc/livekit.yaml"]
:ports (map #(select-keys % [:name :containerPort :protocol])
all-ports)
:volumeMounts [{:name "config-vol"
:mountPath "/etc/livekit.yaml"
:subPath "livekit.yaml"}]}]}}}}
:k8s:service-opts
{:spec {:type "NodePort"
:selector {:app 'app-name}
:ports (map #(select-keys % [:name :port :targetPort :nodePort :protocol])
all-ports)}}
:k8s:httproute-opts
{:spec
{:hostnames ['host]
:rules [{:matches [{:path {:type "PathPrefix" :value "/livekit/sfu"}}]
:filters [{:type "URLRewrite"
:urlRewrite {:path {:type "ReplacePrefixMatch"
:replacePrefixMatch "/"}}}]
:backendRefs [{:name 'app-name :port 7880}]}]}}})

View File

@@ -1,18 +1,26 @@
(ns k8s.services.matrix.element-call.service)
;; volumes:
;; - ./personal/matrix/elementcall/config.json:/app/config.json
(def config
{:stack [:vault-secrets :deployment :service :ingress]
{:stack [:vault:prepare [:k8s :config-map :deployment :service :httproute]]
:image-port 80
:app-namespace "matrix"
:app-name "element-call"
:deployment-opts {:spec {:template {:spec {:containers [{:name 'app-name :image '(str repo "/" app-name ":sha-1702b15")
:volumeMounts [{:name "data" :mountPath "/data"}]}]
:initContainers [{:name "init-permissions"
:image "busybox:latest"
:command ["sh" "-c" "chown -R 1000:1000 /data"]
:volumeMounts [{:name "data" :mountPath "/data"}]
:securityContext {:runAsUser 0 :runAsGroup 0}}]
:volumes [{:name "data" :hostPath {:path "/opt/mmr/data" :type "DirectoryOrCreate"}}]}}}}})
:k8s:config-map-opts {:data {"config.json"
'(stringify
{:default_server_config
{:m.homeserver
{:base_url (str "https://" homeserver)
:server_name homeserver}}
:features
{:feature_use_device_session_member_events true}
:ssla "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf"})}}
:k8s:deployment-opts {:spec
{:template
{:spec
{:volumes [{:name "config-vol"
:configMap {:name 'app-name}}]
:containers [{:name 'app-name :image '(str repo "/" app-name ":latest")
:volumeMounts [{:name "config-vol"
:mountPath "/app/config.json"
:subPath "config.json"}]}]}}}}
:k8s:httproute-opts {:spec {::hostnames ['host]}}})

View File

@@ -1,10 +1,53 @@
;; homeserver:
;; volumes:
;; - db:/var/lib/conduwuit
(def config
{:stack [:vault-secrets :docker-image :deployment :service :ingress]
:image-port 80
(ns k8s.services.matrix.home-server.service)
(def config
{:stack [:vault:prepare [:k8s :pvc :deployment :service :httproute]]
:app-namespace "matrix"
:app-name "tuwunel"
:deployment-opts {:spec {:template {:spec {:containers [{:name 'app-name :image '(str repo "/" 'app-name ":latest")}]}}}}})
:k8s:pvc-opts
{:metadata {:name "conduwuit-db"
:namespace "matrix"}
:spec {:storageClassName "hcloud-volumes"
:accessModes ["ReadWriteOnce"]
:resources {:requests {:storage "50Gi"}}}}
:k8s:deployment-opts
{:spec
{:strategy {:type "Recreate"}
:template
{:metadata {:annotations {"backup.velero.io/backup-volumes" "db"}}
:spec
{:containers
[{:name 'app-name
:image '(str repo "/tuwunel:latest")
:envFrom [{:secretRef {:name '(str app-name "-secrets")}}]
:ports [{:containerPort 'port}]
:volumeMounts [{:name "db" :mountPath "/var/lib/conduwuit"}
#_{:name "discord-reg"
:mountPath "/etc/conduwuit/discord-registration.yaml"
:subPath "registration.yaml"}]}]
:volumes
[{:name "db" :persistentVolumeClaim {:claimName "conduwuit-db"}}
#_{:name "discord-reg" :configMap {:name "discord-bridge-config"}}
]}}}}
:k8s:service-opts
{:spec {:ports [{:name 'app-name :port 'port :targetPort 'port}]}}
:k8s:httproute-opts
{:spec
{:hostnames ['host]
:rules [{:matches [{:path {:type "PathPrefix" :value "/_matrix/media"}}]
:backendRefs [{:name "matrix-media-repo" :port 80}]}
{:matches [{:path {:type "PathPrefix" :value "/_matrix/client/v1/media"}}]
:backendRefs [{:name "matrix-media-repo" :port 80}]}
{:matches [{:path {:type "PathPrefix" :value "/.well-known/matrix"}}]
:backendRefs [{:name "matrix-well-known" :port 80}]}
{:matches [{:path {:type "PathPrefix" :value "/"}}]
:backendRefs [{:name 'app-name :port 'port}]}]}}})

View File

@@ -0,0 +1,27 @@
(ns k8s.services.matrix.home-server.well-known.service)
(def config
{:stack [:vault:prepare :k8s:config-map :k8s:deployment :k8s:service]
:app-namespace "matrix"
:app-name "matrix-well-known"
:k8s:config-map-opts
{:metadata {:name "well-known-json"}
:data {"server" "{\"m.server\": \"hampter.quest:443\"}"
"client" '(stringify
{:m.homeserver {:base_url (str "https://" homeserver)}
:org.matrix.msc4143.rtc_foci [{:type "livekit"
:livekit_service_url livekit-url}]})}}
:k8s:deployment-opts
{:spec
{:template
{:spec
{:containers
[{:name 'app-name
:ports [{:containerPort 80}]
:image '(str repo "/nginx:alpine")
:volumeMounts [{:name "config" :mountPath "/usr/share/nginx/html/.well-known/matrix"}]}]
:volumes [{:name "config" :configMap {:name "well-known-json"}}]}}}}
:k8s:service-opts
{:spec {:ports [{:name 'app-name :port 80 :targetPort 80}]}}})

View File

@@ -1,8 +0,0 @@
(ns k8s.services.matrix.livekit-jwt.service)
(def config
{:stack [:vault-secrets :docker-image :deployment :service :ingress]
:image-port 80
:app-namespace "matrix"
:app-name "livekit-jwt"
:deployment-opts {:spec {:template {:spec {:containers [{:name 'app-name :image '(str repo "/" lk-jwt-service ":0.2.3")}]}}}}})

View File

@@ -1,16 +0,0 @@
;; livekit:
;; command: --config /etc/livekit.yaml
;; - ./personal/matrix/elementcall/livekit.yaml:/etc/livekit.yaml
;; ports:
;; - 50100-50200:50100-50200/udp
(ns k8s.services.matrix.livekit-server.service)
(def config
{:stack [:vault-secrets :docker-image :deployment :service :ingress]
:image-port 80
:app-namespace "matrix"
:app-name "livekit-server"
:deployment-opts {:spec {:template {:spec {:containers [{:name 'app-name :image '(str repo "/" 'app-name ":latest")}]}}}}})

View File

@@ -0,0 +1,37 @@
(ns k8s.services.matrix.mautrix-discord.database.service)
(def config
{:stack [:vault:prepare :k8s:pvc :k8s:deployment :k8s:service]
:app-namespace "matrix"
:app-name "mautrix-discord-db"
:k8s:pvc-opts
{:metadata {:name "mautrix-discord-pg-data"
:namespace "matrix"}
:spec {:storageClassName "hcloud-volumes"
:accessModes ["ReadWriteOnce"]
:resources {:requests {:storage "10Gi"}}}}
:k8s:deployment-opts
{:spec
{:template
{:metadata
{:annotations
{"backup.velero.io/backup-volumes" "db"}}
:spec
{:containers
[{:name 'app-name
:image "postgres:14-alpine"
:ports [{:containerPort 5432}]
:env [{:name "PGDATA" :value "/var/lib/postgresql/data/pgdata"}
{:name "POSTGRES_USER" :value 'username}
{:name "POSTGRES_PASSWORD" :value 'password}
{:name "POSTGRES_DB" :value 'db-name}]
:volumeMounts [{:name "db" :mountPath "/var/lib/postgresql/data"}]}]
:volumes
[{:name "db" :persistentVolumeClaim {:claimName "mautrix-discord-pg-data"}}]}}}}
:k8s:service-opts
{:spec {:selector {:app 'app-name}
:ports [{:name 'app-name :port 5432 :targetPort 5432}]}}})

View File

@@ -1,10 +1,78 @@
;; - ./personal/matrix/discord/data:/data
(ns k8s.services.matrix.mautrix-discord.service)
(def config
{:stack [:vault-secrets :docker-image :deployment :service :ingress]
:image-port 80
{:stack [:vault:prepare :k8s:pvc :k8s:config-map :k8s:deployment :k8s:service]
:app-namespace "matrix"
:app-name "mautrix-discord"
:deployment-opts {:spec {:template {:spec {:containers [{:name 'app-name :image '(str repo "/" "discord" ":4927a73ce7411f3970803d35c22f0c8c96dc2d7e-amd64")}]}}}}})
:k8s:config-map-opts
{:metadata {:name "discord-bridge-config"}
:data {"config.yaml" '(stringify
{:homeserver {:address (str "https://" homeserver)
:domain homeserver}
:appservice {:port port
:address (str "http://mautrix-discord:" port)
:hostname "0.0.0.0"
:database {:type "postgres"
:uri db-login-url
:max_open_conns 20
:max_idle_cons 2}
:id "discord"
:as_token as-token
:hs_token hs-token
:ephemeral_events true
:bot {:username "discordbot"
:displayname "Discord bridge bot"}}
:bridge {:permissions (parse permissions)
;;:login_shared_secret_map (parse login-shared-secret-map)
;;:double_puppet_server_map (parse double-puppet-server-map)
:use_discord_cdn_upload true
:command_prefix "!discord"
:encryption {:allow false
:default false}}})
"registration.yaml" '(stringify {:id "discord"
:url (str "http://mautrix-discord:" port)
:as_token as-token
:hs_token hs-token
:sender_localpart sender-localpart
:rate_limited false
:namespaces {:users [{:regex user1-regex
:exclusive true}
{:regex user2-regex
:exclusive true}]}
:de.sorunome.msc2409.push_ephemeral true
:push_ephemeral true})}}
:k8s:pvc-opts
{:metadata {:name "discord-bridge-data"
:namespace "matrix"}
:spec {:storageClassName "juicefs-sc"
:accessModes ["ReadWriteMany"]
:resources {:requests {:storage "1Gi"}}}}
:k8s:deployment-opts
{:spec
{:template
{:spec
{:initContainers
[{:name "config-loader"
:image "busybox:latest"
:command ["sh" "-c" "cp -f /config_source/* /data/"]
:volumeMounts [{:name "data" :mountPath "/data"}
{:name "config" :mountPath "/config_source"}]}]
:containers
[{:name 'app-name
:image '(str repo "/discord:latest")
:args ["/usr/bin/mautrix-discord" "-c" "/data/config.yaml" "-r" "/data/registration.yaml"]
:ports [{:containerPort 'port}]
:volumeMounts [{:name "data" :mountPath "/data"}
#_{:name "config" :mountPath "/data/config.yaml" :subPath "config.yaml"}
#_{:name "config" :mountPath "/data/registration.yaml" :subPath "registration.yaml"}]}]
:volumes
[{:name "data" :persistentVolumeClaim {:claimName "discord-bridge-data"}}
{:name "config" :configMap {:name "discord-bridge-config"}}]}}}}
:k8s:service-opts
{:spec {:selector {:app 'app-name}
:ports [{:name 'app-name :port 'port :targetPort 'port}]}}})

View File

@@ -0,0 +1,37 @@
(ns k8s.services.matrix.mmr.database.service)
(def config
{:stack [:vault:prepare :k8s:pvc :k8s:deployment :k8s:service]
:app-namespace "matrix"
:app-name "mmr-db"
:k8s:pvc-opts
{:metadata {:name "mmr-pg-data"
:namespace "matrix"}
:spec {:storageClassName "hcloud-volumes"
:accessModes ["ReadWriteOnce"]
:resources {:requests {:storage "10Gi"}}}}
:k8s:deployment-opts
{:spec
{:template
{:metadata
{:annotations
{"backup.velero.io/backup-volumes" "db"}}
:spec
{:containers
[{:name 'app-name
:image "postgres:14-alpine"
:ports [{:containerPort 5432}]
:env [{:name "PGDATA" :value "/var/lib/postgresql/data/pgdata"}
{:name "POSTGRES_USER" :value 'username}
{:name "POSTGRES_PASSWORD" :value 'password}
{:name "POSTGRES_DB" :value 'db-name}]
:volumeMounts [{:name "db" :mountPath "/var/lib/postgresql/data"}]}]
:volumes
[{:name "db" :persistentVolumeClaim {:claimName "mmr-pg-data"}}]}}}}
:k8s:service-opts
{:spec {:selector {:app 'app-name}
:ports [{:name 'app-name :port 5432 :targetPort 5432}]}}})

View File

@@ -2,20 +2,57 @@
(ns k8s.services.matrix.mmr.service)
(def config
{:stack [:vault-secrets :deployment :service :ingress]
{:stack [:vault:prepare [:k8s :config-map :deployment :service]]
:image-port 80
:app-namespace "matrix"
:app-name "matrix-media-repo"
:deployment-opts {:spec {:template {:spec {:containers [{:name 'app-name :image '(str repo "/" app-name ":v1.3.8")
:volumeMounts [{:name "data" :mountPath "/data"}]}]
:initContainers [{:name "init-permissions"
:image "busybox:latest"
:command ["sh" "-c" "chown -R 1000:1000 /data"]
:volumeMounts [{:name "data" :mountPath "/data"}]
:securityContext {:runAsUser 0 :runAsGroup 0}}]
:volumes [{:name "data" :hostPath {:path "/opt/mmr/data" :type "DirectoryOrCreate"}}]}}}}})
:k8s:config-map-opts
{:metadata {:name "mmr-config"}
:data {"media-repo.yaml"
'(stringify
{:repo {:port port
:bindAddress "0.0.0.0"
:logLevel "debug"}
:database {:postgres db-login-url}
:homeservers [{:name homeserver
:csApi (str "https://" homeserver)}]
:accessTokens {:appservices [{:id "discord"
:asToken discord-app-service-token
:senderUserId discord-send-user-id
:userNamespaces [{:regex user-namespace-regex}]}]}
:admins [admin]
:datastores [{:type "s3"
:id s3-id
:forKinds ["all"]
:opts {:tempPath "/tmp/media-repo"
:endpoint s3-endpoint
:accessKeyId s3-access-key
:accessSecret s3-secret-key
:ssl true
:bucketName s3-bucket-name
:region s3-region}}]
:rateLimit {:enabled false}})}}
:k8s:deployment-opts
{:spec
{:template
{:spec
{:containers
[{:name 'app-name
:image '(str repo "/" app-name ":v1.3.8")
:command ["/usr/local/bin/media_repo"]
:args ["-config" "/data/media-repo.yaml"]
:volumeMounts [{:name "config-vol"
:mountPath "/data/media-repo.yaml"
:subPath "media-repo.yaml"}
{:name "temp-vol"
:mountPath "/tmp/media-repo"}]}]
:volumes
[{:name "config-vol" :configMap {:name "mmr-config"}}
{:name "temp-vol" :emptyDir {}}]}}}}
})
;;
;; - ./personal/matrix/mmr:/data

View File

@@ -1,14 +1,67 @@
(ns k8s.services.matrix.turn.service)
;; - ./personal/matrix/coturn.conf:/etc/coturn/turnserver.conf
(defn generate-all-ports [start-relay end-relay]
(concat
[{:name "signaling-udp" :port 3478 :targetPort 3478 :nodePort 30478 :containerPort 3478 :protocol "UDP"}
{:name "signaling-tcp" :port 3478 :targetPort 3478 :nodePort 30478 :containerPort 3478 :protocol "TCP"}
{:name "tls-udp" :port 5349 :targetPort 5349 :nodePort 30549 :containerPort 5349 :protocol "UDP"}
{:name "tls-tcp" :port 5349 :targetPort 5349 :nodePort 30549 :containerPort 5349 :protocol "TCP"}]
(map (fn [p]
{:name (str "relay-" p)
:port p
:targetPort p
:nodePort p
:containerPort p
:protocol "UDP"})
(range start-relay (inc end-relay)))))
(def all-ports (generate-all-ports 32000 32050))
(def config
{:stack [:vault-secrets :docker-image :deployment :service :ingress]
:image-port 80
{:stack [:vault:prepare [:k8s :config-map :deployment :service]]
:image-port nil
:app-namespace "matrix"
:app-name "coturn"
:image-opts {:build {:args {:FOUNDRY_USERNAME 'FOUNDRY_USERNAME
:FOUNDRY_PASSWORD 'FOUNDRY_PASSWORD}}
:imageName '(str repo "/" app-name ":latest")}
:deployment-opts {:spec {:template {:spec {:imagePullSecrets [{:name "harbor-creds-secrets"}]
:containers [{:name 'app-name :image '(str repo "/" app-name ":latest")}]}}}}})
:k8s:config-map-opts
{:metadata {:name "coturn-config"}
:data {"turnserver.conf"
'(str
"listening-port=3478\n"
"tls-listening-port=5349\n"
"min-port=32000\n"
"max-port=32050\n"
(str "external-ip=" public-ip "\n")
(str "realm" homeserver "\n")
(str "server-name=" host "\n")
"log-file=stdout\n"
"use-auth-secret\n"
(str "static-auth-secret=" secret-auth "\n")
"fingerprint\n"
"lt-cred-mech\n")}}
:k8s:deployment-opts
{:spec
{:template
{:spec
{:volumes [{:name "config" :configMap {:name "coturn-config"}}]
:containers [{:name 'app-name
:image "coturn/coturn:latest"
:ports (map #(select-keys % [:name :containerPort :protocol])
all-ports)
:volumeMounts [{:name "config"
:mountPath "/etc/coturn/turnserver.conf"
:subPath "turnserver.conf"}]}]}}}}
:k8s:service-opts
{:spec {:type "NodePort"
:selector {:app 'app-name}
:ports (map #(select-keys % [:name :port :targetPort :nodePort :protocol])
all-ports)}}})

View File

@@ -0,0 +1,40 @@
(ns k8s.services.nextcloud.database.service)
(def config
{:stack [:vault:prepare :k8s:pvc :k8s:deployment :k8s:service]
:app-namespace "nextcloud"
:app-name "nextcloud-db"
:k8s:pvc-opts
{:metadata {:name "nextcloud-mariadb-disk"
:namespace "nextcloud"}
:spec {:storageClassName "hcloud-volumes"
:accessModes ["ReadWriteOnce"]
:resources {:requests {:storage "10Gi"}}}}
:k8s:deployment-opts
{:spec
{:template
{:metadata
{:annotations {"backup.velero.io/backup-volumes" "db"}}
:spec
{:containers
[{:name 'app-name
:image "mariadb:10.6"
:ports [{:containerPort 3306}]
:env [{:name "MYSQL_ROOT_PASSWORD" :value 'mariadb-root-password}
{:name "MYSQL_DATABASE" :value "nextcloud"}
{:name "MYSQL_USER" :value 'username}
{:name "MYSQL_PASSWORD" :value 'mariadb-password}]
:volumeMounts [{:name "db" :mountPath "/var/lib/mysql"}]}]
:volumes
[{:name "db" :persistentVolumeClaim {:claimName "nextcloud-mariadb-disk"}}]}}}}
:k8s:service-opts
{:spec {:selector {:app 'app-name}
:ports [{:name 'app-name :port 3306 :targetPort 3306}]}}})

View File

@@ -1,20 +1,61 @@
(ns k8s.services.nextcloud.service)
;; Need to automate set-up/restore
(def config
{:stack [:vault-secrets :k8s:chart :k8s:httproute]
{:stack [:vault:prepare [:k8s :httproute :chart]]
:app-namespace "nextcloud"
:app-name "nextcloud"
:image-port 8080
:image-port 80
:vault-load-yaml true
:k8s:chart-opts {:repositoryOpts {:repo "https://nextcloud.github.io/helm/"}
:values {:nextcloud {:host 'host
:trustedDomains ['host 'app-name]}}
:transformations (fn [args _opts]
(let [kind (get-in args [:resource :kind])]
(if (some #{kind} ["StatefulSet" "PersistentVolumeClaim" "Ingress"])
(update-in args [:resource :metadata :annotations]
#(assoc (or % {}) "pulumi.com/skipAwait" "true"))
args)))}
:k8s:httproute-opts {:spec {::hostnames ['host]}}
})
:values
{:podAnnotations {"backup.velero.io/backup-volumes" "data"}
:trustedDomains ['host 'app-name]
:nextcloud {:username 'username
:password 'password
:host 'host
:containerPort 80
:persistence {:enabled true
:storageClass "juicefs-sc"
:accessMode "ReadWriteMany"
:size "1Ti"}}
:service {:port 80}
:redis {:auth {:password 'redis-password}}
:externalDatabase {:enabled true
:type "mysql"
:host "nextcloud-db.nextcloud.svc.cluster.local"
:database "nextcloud"
:user 'username
:password 'mariadb-password}
:internalDatabase {:enabled false}
:mariadb {:enabled false
:auth {:username 'username
:password 'mariadb-password
:rootPassword 'mariadb-root-password}
:architecture "standalone"
:primary {:podAnnotations {"backup.velero.io/backup-volumes" "data"}
:persistence {:enabled true
:storageClass "hcloud-volumes"
:size "8Gi"}}
;; Obligatory what the fuck Broadcom, why are you like this. RIP Bitnami
:volumePermissions {:enabled true
:image {:registry "docker.io"
:repository "bitnami/os-shell"
:tag "latest"
:pullPolicy "Always"}}}
:transformations (fn [args _opts]
(let [kind (get-in args [:resource :kind])]
(if (some #{kind} ["StatefulSet" "PersistentVolumeClaim" "Ingress"])
(update-in args [:resource :metadata :annotations]
#(assoc (or % {}) "pulumi.com/skipAwait" "true"))
args)))}}
:k8s:httproute-opts {:spec {::hostnames ['host]
:rules [{:matches [{:path {:type "PathPrefix" :value "/"}}]
:filters [{:type "ResponseHeaderModifier"
:responseHeaderModifier
{:set [{:name "Content-Security-Policy"
:value "frame-src 'self' https://cinny.hampter.quest https://productive.chickensalad.quest https://gitea.chickensalad.quest;"}]
:remove ["X-Content-Security-Policy"]}}]
:backendRefs [{:name "nextcloud"
:port 80}]}]}}})

View File

@@ -1,12 +1,10 @@
(ns k8s.services.prometheus.service)
(def config
{:stack [:vault-secrets :chart]
{:stack [:vault:prepare :k8s:chart]
:app-namespace "prometheus"
:app-name "prometheus"
:image-port 8080
:vault-load-yaml true
:chart-opts {:chart "kube-prometheus-stack"
:k8s:chart-opts {:chart "kube-prometheus-stack"
:repositoryOpts {:repo "https://prometheus-community.github.io/helm-charts"}
:namespace "monitoring"
:values {:grafana {:adminPassword 'password

View File

@@ -0,0 +1,55 @@
(ns k8s.services.velero.service)
(def config
{:stack [:vault:prepare :k8s:secret :k8s:chart]
:app-namespace "velero"
:app-name "velero"
:k8s:secret-opts
{:metadata {:name "velero-s3-creds"}
:stringData {"cloud" '(str "[default]\n"
"aws_access_key_id = " s3-access-key "\n"
"aws_secret_access_key = " s3-secret-key)}}
:k8s:chart-opts
{:repositoryOpts {:repo 'repo}
:chart "velero"
:version "5.1.0"
:values
{:deployNodeAgent true
:configuration
{:backupStorageLocation
[{:name "default"
:provider "aws"
:bucket 's3-bucket-name
:config {:region 's3-region
:s3ForcePathStyle true
:s3Url 's3-url}}]
:volumeSnapshotLocation
[{:name "default"
:provider "aws"
:config {:region 's3-region}}]}
:credentials {:useSecret true
:existingSecret "velero-s3-creds"}
:initContainers
[{:name "velero-plugin-for-aws"
:image "velero/velero-plugin-for-aws:v1.8.0"
:volumeMounts [{:mountPath "/target" :name "plugins"}]}]
:defaultVolumesToFsBackup true
:nodeAgent {:resources {:requests {:cpu "50m" :memory "64Mi"}
:limits {:cpu "1000m" :memory "1Gi"}}}
:schedules
{:daily-backup
{:disabled false
:schedule "0 4 * * *"
:template {:ttl "720h"
:includedNamespaces ["matrix" "generic" "home" "nextcloud"]}}}}}})

View File

@@ -5,7 +5,6 @@
[k8s.add-ons.csi-driver.hetzner :as hetzner-csi]
[infra.dns :as dns]
[k8s.preparers.harbor :as harbor-prepare]
[k8s.add-ons.gateway.traefik :as traefik]
[k8s.add-ons.cert-manager :as cert-manager]
[k8s.add-ons.crd.cert-manager :as cert-manager-crd]
@@ -18,12 +17,25 @@
[k8s.add-ons.secret-replicator :as secret-replicator]
[k8s.add-ons.proxy :as proxy]
[k8s.services.nextcloud.service :as nextcloud-service]
[k8s.services.nextcloud.database.service :as nextcloud-db-service]
[k8s.services.mesite.service :as mesite-service]
[k8s.services.gitea.service :as gitea-service]
[k8s.services.act-runner.service :as act-runner-service]
[k8s.services.foundryvtt.service :as foundryvtt-service]
[k8s.services.foundryvtt.service-2 :as girls-foundry-service]
[k8s.services.productive.service :as productive-service]))
[k8s.services.productive.service :as productive-service]
[k8s.services.velero.service :as velero-service]
[k8s.services.matrix.cinny.service :as cinny-service]
[k8s.services.matrix.element-call.service :as element-call-service]
[k8s.services.matrix.element.service :as element-service]
[k8s.services.matrix.element-call.livekit-server.service :as livekit-server-service]
[k8s.services.matrix.element-call.livekit-jwt.service :as livekit-jwt-service]
[k8s.services.matrix.mmr.service :as mmr-service]
[k8s.services.matrix.mmr.database.service :as mmr-db-service]
[k8s.services.matrix.mautrix-discord.database.service :as mautrix-discord-db-service]
[k8s.services.matrix.mautrix-discord.service :as mautrix-discord-service]
[k8s.services.matrix.home-server.well-known.service :as matrix-well-known-service]
[k8s.services.matrix.home-server.service :as homeserver-service]))
(defn general-provider-output-refs []
{:vault {:stack :init
@@ -77,12 +89,33 @@
(def deployment-resources-definition
(create-resource-definition
[girls-foundry-service/config
foundryvtt-service/config mesite-service/config productive-service/config gitea-service/config act-runner-service/config
#_nextcloud-service/config
[girls-foundry-service/config foundryvtt-service/config
mesite-service/config productive-service/config
nextcloud-db-service/config
nextcloud-service/config
velero-service/config
gitea-service/config
;;act-runner-service/config
]
["base" "init" "shared"]
(general-provider-output-refs)))
(def deployment-matrix-service-registry [])
(def matrix-resources-definition
(create-resource-definition
[cinny-service/config
element-call-service/config
element-service/config
livekit-server-service/config
livekit-jwt-service/config
mmr-db-service/config
mmr-service/config
mautrix-discord-db-service/config
mautrix-discord-service/config
matrix-well-known-service/config
homeserver-service/config
]
["base" "init" "shared"]
(general-provider-output-refs)))