Compare commits

...

53 Commits

Author SHA1 Message Date
Grant Hunter
b518b96a6d increase postgres memory 2026-01-01 15:20:33 -07:00
Grant Hunter
dff2f4871e add just command to refresh client cert 2026-01-01 15:20:06 -07:00
Grant Hunter
6117c9d826 simplify helm deploy args 2025-12-23 10:45:11 -07:00
Grant Hunter
d9a9187607 bump versions 2025-12-23 10:45:02 -07:00
Grant Hunter
2eb738325b switch gitea to single valkey instance 2025-12-14 22:35:26 -07:00
Grant Hunter
c28540cd44 update certs 2025-12-14 22:27:45 -07:00
Grant Hunter
e733a2584b bump version add skip-deps for speed 2025-12-14 13:03:49 -07:00
Grant Hunter
149506224f update mem limit 2025-12-08 09:11:54 -07:00
Grant Hunter
708efca878 set memory limits 2025-12-07 15:25:24 -07:00
Grant Hunter
6d604c269d update ceph limits 2025-12-07 14:01:39 -07:00
Grant Hunter
8bdff3bcea remove grafana 2025-12-07 13:46:33 -07:00
Grant Hunter
87a5a3a1ab bump versions 2025-12-07 13:27:28 -07:00
Grant Hunter
6b3eb79f88 remove old values.yaml 2025-12-07 13:16:22 -07:00
Grant Hunter
332f776c4f update to gotmpl 2025-12-07 13:14:48 -07:00
Grant Hunter
6aa777f880 update gitignore 2025-12-07 12:50:24 -07:00
Grant Hunter
2a7521e474 add talos upgrade just command 2025-11-25 22:17:56 -07:00
Grant Hunter
83eedaa96e bump version 2025-11-25 21:48:13 -07:00
Grant Hunter
bbd382c667 update install instructions, update talos install version 2025-09-22 20:01:59 -06:00
Grant Hunter
5963ba52e1 bump versions 2025-09-16 10:54:16 -06:00
Grant Hunter
7d5a5fa56e simplify just diff, add goatchat register commands 2025-07-29 21:45:50 -06:00
Grant Hunter
4535d872b1 bump version 2025-07-29 21:45:20 -06:00
Grant
e4706a960c Bump app versions 2025-05-29 21:05:16 -06:00
Grant
446914fadc Add lock files 2025-05-19 17:20:06 -06:00
Grant
dca9e445c2 Split helmfile into components 2025-05-19 14:09:30 -06:00
Grant
12bcabf7b2 Add pg restart script to just 2025-05-19 11:38:26 -06:00
Grant
23cc0fd76c Increase priority of tailscale pods 2025-05-19 11:38:04 -06:00
Grant
485f26ca19 Bump dependencies 2025-05-19 11:37:30 -06:00
Grant
1e00abc934 update dependencies 2025-04-28 22:11:59 -06:00
Grant
366a624024 Fix postgres backups 2025-04-28 22:11:40 -06:00
Grant
d486eca1b3 Increase mimir storage, reduce retention 2025-04-14 20:58:48 -06:00
Grant
b1a3de3b41 Update dependencies 2025-04-14 20:58:37 -06:00
Grant
3575d99821 Cleanup unneeded files 2025-04-07 23:14:50 -06:00
Grant
be0d72e035 Update dependencies 2025-04-07 23:14:35 -06:00
Grant
f997133283 Add talos worker config and other niceties 2025-04-07 22:36:12 -06:00
Grant
0ba65b2060 Update versions 2025-03-29 10:42:12 -06:00
Grant
fe101ef7cc Update versions 2025-03-26 17:03:06 -06:00
Grant
6966e7dc1e More request balancing 2025-03-24 22:27:27 -06:00
Grant
1200d7c46a reduce job history limits 2025-03-24 21:19:31 -06:00
Grant
cbdf15d4b1 Rebalance requests and limits 2025-03-24 21:19:15 -06:00
Grant
d81c8cd210 Update deps 2025-03-22 23:15:49 -06:00
Grant
07107aac4f Add s3 to pgo backups 2025-03-22 22:41:28 -06:00
Grant
381fca64d0 Fix prune schedule 2025-03-22 22:13:53 -06:00
Grant
b6edc128ad Improve backups 2025-03-22 21:58:11 -06:00
Grant
bcaeafa455 Add args to just commands 2025-03-22 21:57:10 -06:00
Grant
211b84b8b5 Update immich 2025-03-20 18:12:41 -06:00
Grant
ca2ffc39b7 update talos version 2025-03-19 22:08:17 -06:00
Grant
61f1f8c930 increase immich storage, add resource limits 2025-03-19 22:07:14 -06:00
Grant
64e4993c28 add ksm metrics 2025-03-19 22:06:48 -06:00
Grant
951057490a Fix monitoring, remove limits from immich 2025-03-17 23:22:39 -06:00
Grant
ac1350aa3b Add immich 2025-03-17 12:19:34 -06:00
Grant
38a6ee61c9 Add incngrnt website along with gitea runner to build it 2025-03-16 19:05:50 -06:00
Grant
2830ed72c1 Add just tool dependency 2025-03-15 23:08:30 -06:00
Grant
10d564b6d5 Enable ssh git interface 2025-03-15 22:55:00 -06:00
65 changed files with 1163 additions and 744 deletions

3
.gitignore vendored
View File

@@ -15,3 +15,6 @@ kgnot/config.production.json
*.key
*.pub
.envrc
.config

View File

@@ -3,7 +3,7 @@ image:
ghostBlogTitle: 53rd Parallel Photography
ghostHost: https://53ll.ca
ghostUsername: # set through cli args
ghostUsername: {{ requiredEnv "GHOST_53LL_USER_NAME" }}
existingSecret: ghost-53ll-user-secret
allowEmptyPassword: false
@@ -13,14 +13,14 @@ readinessProbe:
enabled: false
resources:
requests:
cpu: 10m
ephemeral-storage: 50Mi
memory: 64Mi
limits:
cpu: 500m
ephemeral-storage: 2Gi
memory: 192Mi
requests:
cpu: 100m
ephemeral-storage: 50Mi
memory: 128Mi
memory: 224Mi
persistence:
size: 1Gi
@@ -48,6 +48,21 @@ ingress:
enabled: true
hostname: 53ll.ca
tls: true
annotations:
"traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt"
extraTls:
- secretName: 53ll-ca-tls
hosts:
- 53ll.ca
extraDeploy:
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: 53ll-ca
namespace: ghost
spec:
secretName: 53ll-ca-tls
issuerRef:
name: letsencrypt-53ll
kind: ClusterIssuer
dnsNames:
- 53ll.ca

View File

@@ -7,7 +7,7 @@ Like the cloud but local.
- helm (https://helm.sh/ )
- helmfile (https://helmfile.readthedocs.io/en/latest/ )
- bitwarded secrets CLI (https://bitwarden.com/help/secrets-manager-cli/ )
- just (https://just.systems/man/en/ )
## Talos Cluster
### Hardware
- HP ProDesk 400 G3 (x3)
@@ -33,9 +33,17 @@ talosctl gen config fog https://192.168.1.43:6443 \
--with-secrets talos/secrets.yaml \
--config-patch @talos/machine_patch.yaml \
--config-patch-control-plane @talos/cluster_patch.yaml \
--config-patch-control-plane @talos/remove_node_label_patch.yaml
--config-patch-control-plane @talos/remove_node_label_patch.yaml \
--config-patch-worker @talos/framework_patch.yaml
```
### Add node to talos cluster
1. Create an ISO USB
```sh
sudo dd if=metal-amd64.iso of=/dev/sdc bs=4M
```
2. Start the machine with the USB. Once it has booted **REMOVE** the USB so that it doesn't get selected as an install location.
3. Apply config to install the OS to disk
```sh
talosctl apply-config [--insecure] -n <ips> controlplane.yaml
```
@@ -103,7 +111,7 @@ kubectl -n datastore exec -it "$PRIMARY_POD" -- createdb --encoding=UTF8 --local
```
#### gitea
copy secret from datastore over to goatchat namespace
copy secret from datastore over to gitea namespace
```sh
kubectl get secrets -n datastore postgres-pguser-gitea -o json | jq 'del(.metadata.resourceVersion,.metadata.uid,.metadata.ownerReferences) | .metadata.creationTimestamp=null,.metadata.namespace="gitea"' | kubectl apply -f -
```
@@ -115,6 +123,20 @@ PGPASSWORD=$(kubectl -n datastore get secrets "postgres-pguser-grant" -o go-tem
kubectl -n datastore exec -it "$PRIMARY_POD" -- psql -c 'DROP DATABASE gitea;'
kubectl -n datastore exec -it "$PRIMARY_POD" -- createdb --encoding=UTF8 --locale=C --template=template0 --owner=gitea gitea
```
create runner token
```sh
kubectl exec -it <pod> -- gitea --config /data/gitea/conf/app.ini actions generate-runner-token
kubectl create secret generic gitea-runner-token --from-literal=token='<token>'
```
allow priviledge pods
```sh
kubectl label namespace gitea pod-security.kubernetes.io/enforce=privileged
```
#### Immich
copy secret from datastore over to immich namespace
```sh
kubectl get secrets -n datastore postgres-pguser-immich -o json | jq 'del(.metadata.resourceVersion,.metadata.uid,.metadata.ownerReferences) | .metadata.creationTimestamp=null,.metadata.namespace="immich"' | kubectl apply -f -
```
#### Ghost Blogs
I got tired of fighting the docker container so I manually overrode the `config.production.json`

View File

@@ -0,0 +1,11 @@
groupName: acme.hetzner.com
certManager:
namespace: cert-manager
serviceAccountName: cert-manager
secretName:
- hetzner-dns-credentials
secrets:
apiToken: {{ requiredEnv "HETZNER_API_KEY" }}

View File

@@ -0,0 +1,5 @@
apiVersion: v2
name: cert-manager-issuers
description: cert-manager ClusterIssuers for Let's Encrypt
type: application
version: 0.1.0

View File

@@ -0,0 +1,88 @@
apiVersion: v1
kind: Secret
metadata:
name: hetzner-dns-credentials
namespace: cert-manager
type: Opaque
stringData:
api-key: {{ .Values.hetzner.apiToken }}
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-incngrnt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: {{ .Values.acme.email }}
privateKeySecretRef:
name: letsencrypt-incngrnt-private-key
solvers:
- dns01:
webhook:
groupName: acme.hetzner.com
solverName: hetzner
config:
secretName: hetzner-dns-credentials
zoneName: incngrnt.ca
apiUrl: https://dns.hetzner.com/api/v1
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-goatchat
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: {{ .Values.acme.email }}
privateKeySecretRef:
name: letsencrypt-goatchat-private-key
solvers:
- dns01:
webhook:
groupName: acme.hetzner.com
solverName: hetzner
config:
secretName: hetzner-dns-credentials
zoneName: goatchat.ca
apiUrl: https://dns.hetzner.com/api/v1
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-53ll
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: {{ .Values.acme.email }}
privateKeySecretRef:
name: letsencrypt-53ll-private-key
solvers:
- dns01:
webhook:
groupName: acme.hetzner.com
solverName: hetzner
config:
secretName: hetzner-dns-credentials
zoneName: 53ll.ca
apiUrl: https://dns.hetzner.com/api/v1
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-kgnot
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: {{ .Values.acme.email }}
privateKeySecretRef:
name: letsencrypt-kgnot-private-key
solvers:
- dns01:
webhook:
groupName: acme.hetzner.com
solverName: hetzner
config:
secretName: hetzner-dns-credentials
zoneName: kgnot.ca
apiUrl: https://dns.hetzner.com/api/v1

View File

@@ -0,0 +1,5 @@
hetzner:
apiToken: {{ requiredEnv "HETZNER_API_KEY" }}
acme:
email: {{ requiredEnv "ACME_EMAIL" }}

View File

@@ -0,0 +1,27 @@
installCRDs: true
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 1
memory: 128Mi
webhook:
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 1
memory: 64Mi
cainjector:
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 1
memory: 128Mi

View File

View File

@@ -35,9 +35,12 @@ gitea:
secretKeyRef:
name: postgres-pguser-gitea
key: password
admin:
password: {{ requiredEnv "GITEA_ADMIN_PASSWORD" }}
strategy:
type: Recreate
ingress:
enabled: true
hosts:
@@ -45,15 +48,52 @@ ingress:
paths:
- path: "/"
pathType: Prefix
annotations:
"traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt"
tls:
- secretName: git-incngrnt-ca-tls
hosts:
- git.incngrnt.ca
service:
ssh:
type: ClusterIP
port: 22
clusterIP:
redis:
valkey:
enabled: true
redis-cluster:
valkey-cluster:
enabled: false
postgresql:
enabled: false
postgresql-ha:
enabled: false
extraDeploy:
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: git-incngrnt-ca
namespace: gitea
spec:
secretName: git-incngrnt-ca-tls
issuerRef:
name: letsencrypt-incngrnt
kind: ClusterIssuer
dnsNames:
- git.incngrnt.ca
- apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: gitea-ssh
namespace: gitea
labels:
app: gitea
spec:
entryPoints:
- ssh
routes:
- match: HostSNI(`*`)
services:
- name: gitea-ssh
port: 22

View File

@@ -1,23 +0,0 @@
alloy:
configMap:
content: |-
logging {
level = "info"
format = "logfmt"
}
discovery.kubernetes "pods" {
role = "pod"
}
loki.source.kubernetes "pods" {
targets = discovery.kubernetes.pods.targets
forward_to = [loki.write.loki.receiver]
}
loki.write "loki" {
endpoint {
url = "http://loki.grafana.svc.cluster.local:3100/loki/api/v1/push"
}
}

View File

@@ -1,9 +0,0 @@
ingress:
enabled: true
hosts:
- watcher.incngrnt.ca
annotations:
"traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt"
persistence:
enabled: true

View File

@@ -1,70 +0,0 @@
loki:
commonConfig:
replication_factor: 1
schemaConfig:
configs:
- from: "2024-04-01"
store: tsdb
object_store: s3
schema: v13
index:
prefix: loki_index_
period: 24h
pattern_ingester:
enabled: true
limits_config:
allow_structured_metadata: true
volume_enabled: true
ruler:
enable_api: true
auth_enabled: false
resultsCache:
resources:
request:
cpu: 100ms
memory: 500Mi
limits:
memory: 500Mi
chunksCache:
resources:
request:
cpu: 100ms
memory: 500Mi
limits:
memory: 500Mi
minio:
enabled: true
deploymentMode: SingleBinary
singleBinary:
replicas: 1
# Zero out replica counts of other deployment modes
backend:
replicas: 0
read:
replicas: 0
write:
replicas: 0
ingester:
replicas: 0
querier:
replicas: 0
queryFrontend:
replicas: 0
queryScheduler:
replicas: 0
distributor:
replicas: 0
compactor:
replicas: 0
indexGateway:
replicas: 0
bloomCompactor:
replicas: 0
bloomGateway:
replicas: 0

View File

@@ -1,3 +0,0 @@
rometheus-node-exporter:
rbac:
pspEnabled: true

View File

@@ -0,0 +1,22 @@
version: 1.2.3
dependencies:
- name: cert-manager
repository: https://charts.jetstack.io
version: v1.19.2
- name: cert-manager-webhook-hetzner
repository: https://vadimkim.github.io/cert-manager-webhook-hetzner
version: 1.4.2
- name: rook-ceph
repository: https://charts.rook.io/release
version: v1.18.8
- name: rook-ceph-cluster
repository: https://charts.rook.io/release
version: v1.18.8
- name: tailscale-operator
repository: https://pkgs.tailscale.com/helmcharts
version: 1.92.4
- name: traefik
repository: https://traefik.github.io/charts
version: 38.0.1
digest: sha256:3297bc0c10765abe170881882f7daf441a4dd735ed0ee7d1f4233692e8888c3c
generated: "2025-12-23T10:31:34.409765694-07:00"

View File

@@ -0,0 +1,68 @@
repositories:
- name: rook-release
url: https://charts.rook.io/release
- name: traefik
url: https://traefik.github.io/charts
- name: tailscale
url: https://pkgs.tailscale.com/helmcharts
- name: jetstack
url: https://charts.jetstack.io
- name: cert-manager-webhook-hetzner
url: https://vadimkim.github.io/cert-manager-webhook-hetzner
lockFilePath: ./helmfile.d/01-infrastructure.lock
releases:
# networking
- name: metallb
namespace: metallb-system
createNamespace: true
chart: ../metallb
values:
- ../metallb/values.yaml.gotmpl
- name: cert-manager
namespace: cert-manager
createNamespace: true
chart: jetstack/cert-manager
values:
- ../cert-manager/values.yaml.gotmpl
- name: cert-manager-webhook-hetzner
namespace: cert-manager
createNamespace: true
chart: cert-manager-webhook-hetzner/cert-manager-webhook-hetzner
values:
- ../cert-manager-hetzner-webhook/values.yaml.gotmpl
- name: cert-manager-issuers
namespace: cert-manager
createNamespace: true
chart: ../cert-manager-issuers
values:
- ../cert-manager-issuers/values.yaml.gotmpl
- name: traefik
namespace: traefik
createNamespace: true
chart: traefik/traefik
values:
- ../traefik/values.yaml.gotmpl
- name: tailscale-operator
namespace: tailscale
createNamespace: true
chart: tailscale/tailscale-operator
values:
- ../tailscale/values.yaml.gotmpl
# storage infrastructure
- name: rook-ceph
namespace: rook-ceph
createNamespace: true
chart: rook-release/rook-ceph
values:
- ../rook-ceph/values.yaml.gotmpl
- name: rook-ceph-cluster
namespace: rook-ceph
createNamespace: true
chart: rook-release/rook-ceph-cluster
values:
- ../rook-ceph-cluster/values.yaml.gotmpl
set:
- name: operatorNamespace
value: rook-ceph

View File

@@ -0,0 +1,16 @@
version: 1.2.3
dependencies:
- name: k8up
repository: https://k8up-io.github.io/k8up
version: 4.8.6
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 24.0.2
- name: pgo
repository: git+https://github.com/grantdhunter/postgres-operator@helm?ref=main
version: 5.8.1
- name: postgrescluster
repository: git+https://github.com/grantdhunter/postgres-operator@helm?ref=main
version: 5.7.4
digest: sha256:f8989df670b3574b6d87438486b66fdaf44bc1ed379d3a98e00963a27703003a
generated: "2025-12-14T14:14:05.060998516-07:00"

View File

@@ -0,0 +1,37 @@
repositories:
- name: crunchydata
url: git+https://github.com/grantdhunter/postgres-operator@helm?ref=main
- name: bitnami
url: https://charts.bitnami.com/bitnami
- name: k8up-io
url: https://k8up-io.github.io/k8up
lockFilePath: ./helmfile.d/02-datastore.lock
releases:
# data storage
- name: pgo
namespace: postgres-operator
createNamespace: true
chart: crunchydata/pgo
values:
- ../postgres/operator-values.yaml.gotmpl
- name: postgres
namespace: datastore
createNamespace: true
chart: crunchydata/postgrescluster
values:
- ../postgres/values.yaml.gotmpl
- name: mariadb
namespace: datastore
createNamespace: true
chart: bitnami/mariadb
values:
- ../mariadb/values.yaml.gotmpl
# backup infrastructure
- name: k8up
namespace: k8up
createNamespace: true
chart: k8up-io/k8up
values:
- ../k8up/values.yaml.gotmpl

37
helmfile.d/03-apps.lock Normal file
View File

@@ -0,0 +1,37 @@
version: 1.2.3
dependencies:
- name: ghost
repository: https://charts.bitnami.com/bitnami
version: 25.0.4
- name: ghost
repository: https://charts.bitnami.com/bitnami
version: 25.0.4
- name: gitea
repository: https://dl.gitea.io/charts
version: 12.4.0
- name: immich
repository: https://immich-app.github.io/immich-charts
version: 0.10.3
- name: k8up-backup
repository: git+https://git.incngrnt.ca/grant/charts@charts?ref=main
version: 0.0.3
- name: k8up-backup
repository: git+https://git.incngrnt.ca/grant/charts@charts?ref=main
version: 0.0.3
- name: k8up-backup
repository: git+https://git.incngrnt.ca/grant/charts@charts?ref=main
version: 0.0.3
- name: k8up-backup
repository: git+https://git.incngrnt.ca/grant/charts@charts?ref=main
version: 0.0.3
- name: matrix-registration
repository: git+https://git.incngrnt.ca/grant/charts@charts?ref=main
version: 0.1.0
- name: matrix-synapse
repository: https://ananace.gitlab.io/charts
version: 3.12.17
- name: static-site
repository: git+https://github.com/cfpb/static-site@charts?ref=main
version: 0.1.1
digest: sha256:b44d082b71203ca6bb4fd881d8c6ce71575db556f432bbcc46078a535c8cd9c3
generated: "2025-12-23T10:31:37.404126839-07:00"

91
helmfile.d/03-apps.yaml Normal file
View File

@@ -0,0 +1,91 @@
repositories:
- name: ananace-charts
url: https://ananace.gitlab.io/charts
- name: bitnami
url: https://charts.bitnami.com/bitnami
- name: immich
url: https://immich-app.github.io/immich-charts
- name: gitea
url: https://dl.gitea.io/charts
- name: static-site
url: git+https://github.com/cfpb/static-site@charts?ref=main
- name: incngrnt
url: git+https://git.incngrnt.ca/grant/charts@charts?ref=main
lockFilePath: ./helmfile.d/03-apps.lock
releases:
# goatchat matrix
- name: goatchat
namespace: goatchat
createNamespace: true
chart: ananace-charts/matrix-synapse
values:
- ../synapse/values.yaml.gotmpl
- name: gate
namespace: goatchat
createNamespace: true
chart: incngrnt/matrix-registration
values:
- ../matrix-registration/values.yaml.gotmpl
- name: immich
namespace: immich
createNamespace: true
chart: immich/immich
values:
- ../immich/values.yaml.gotmpl
# website
- name: incngrnt-web
namespace: incngrnt-web
createNamespace: true
chart: static-site/static-site
values:
- ../incngrnt-web/values.yaml.gotmpl
# ghost blogs
- name: kgnot-ghost
namespace: ghost
createNamespace: true
chart: bitnami/ghost
values:
- ../kgnot/values.yaml.gotmpl
- name: ghost-53ll
namespace: ghost
createNamespace: true
chart: bitnami/ghost
values:
- ../53ll/values.yaml.gotmpl
# dev tools
- name: gitea
namespace: gitea
createNamespace: true
chart: gitea/gitea
values:
- ../gitea/values.yaml.gotmpl
# backups
- name: ghost-backup
namespace: ghost
chart: incngrnt/k8up-backup
createNamespace: true
values:
- ../k8up-backup/values.yaml.gotmpl
- name: goatchat-backup
namespace: goatchat
chart: incngrnt/k8up-backup
createNamespace: true
values:
- ../k8up-backup/values.yaml.gotmpl
- name: gitea-backup
namespace: gitea
chart: incngrnt/k8up-backup
createNamespace: true
values:
- ../k8up-backup/values.yaml.gotmpl
- name: immich-backup
namespace: immich
chart: incngrnt/k8up-backup
createNamespace: true
values:
- ../k8up-backup/values.yaml.gotmpl

View File

@@ -2,51 +2,54 @@ version: 0.170.1
dependencies:
- name: alloy
repository: https://grafana.github.io/helm-charts
version: 0.12.5
version: 1.0.3
- name: ghost
repository: https://charts.bitnami.com/bitnami
version: 22.2.0
version: 23.0.3
- name: ghost
repository: https://charts.bitnami.com/bitnami
version: 22.2.0
version: 23.0.3
- name: gitea
repository: https://dl.gitea.io/charts
version: 11.0.0
- name: grafana
repository: https://grafana.github.io/helm-charts
version: 8.10.3
version: 11.0.1
- name: immich
repository: https://immich-app.github.io/immich-charts
version: 0.9.3
- name: k8up
repository: https://k8up-io.github.io/k8up
version: 4.8.4
- name: loki
- name: kube-state-metrics
repository: https://prometheus-community.github.io/helm-charts
version: 5.33.1
- name: lgtm-distributed
repository: https://grafana.github.io/helm-charts
version: 6.28.0
version: 2.1.0
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 20.4.1
version: 20.5.5
- name: matrix-synapse
repository: https://ananace.gitlab.io/charts
version: 3.11.5
version: 3.12.0
- name: pgo
repository: git+https://github.com/grantdhunter/postgres-operator@helm?ref=main
version: 5.7.2
version: 5.8.1
- name: postgrescluster
repository: git+https://github.com/grantdhunter/postgres-operator@helm?ref=main
version: 5.7.2
- name: prometheus
repository: https://prometheus-community.github.io/helm-charts
version: 27.5.1
version: 5.7.4
- name: rook-ceph
repository: https://charts.rook.io/release
version: v1.16.5
version: v1.17.2
- name: rook-ceph-cluster
repository: https://charts.rook.io/release
version: v1.16.5
version: v1.17.2
- name: static-site
repository: git+https://github.com/cfpb/static-site@charts?ref=main
version: 0.1.1
- name: tailscale-operator
repository: https://pkgs.tailscale.com/helmcharts
version: 1.80.3
version: 1.82.0
- name: traefik
repository: https://traefik.github.io/charts
version: 34.4.1
digest: sha256:b28767f0ec4d8549e0b1de7446f3468555a2a67bf88d2b554e9a12c2de723d2d
generated: "2025-03-15T14:34:49.001292746-06:00"
version: 35.2.0
digest: sha256:1a28daf0763e7dab2d0a974f717a4f9818bf0e7785e5ba1b1cef182dee2833e0
generated: "2025-05-19T00:03:46.329319824-06:00"

View File

@@ -1,224 +0,0 @@
repositories:
- name: rook-release
url: https://charts.rook.io/release
# - name: metallb
# url: https://metallb.github.io/metallb
- name: traefik
url: https://traefik.github.io/charts
- name: ananace-charts
url: https://ananace.gitlab.io/charts
- name: bitnami
url: https://charts.bitnami.com/bitnami
- name: crunchydata
url: git+https://github.com/grantdhunter/postgres-operator@helm?ref=main
- name: immich
url: https://immich-app.github.io/immich-charts
- name: k8up-io
url: https://k8up-io.github.io/k8up
- name: tailscale
url: https://pkgs.tailscale.com/helmcharts
- name: gitea
url: https://dl.gitea.io/charts
- name: grafana
url: https://grafana.github.io/helm-charts
- name: prometheus-community
url: https://prometheus-community.github.io/helm-charts
releases:
# networking
- name: metallb
namespace: metallb-system
createNamespace: true
chart: ./metallb
- name: traefik
namespace: traefik
createNamespace: true
chart: traefik/traefik
values:
- ./traefik/values.yaml
setString:
- name: certificatesResolvers.letsencrypt.acme.email
value: {{ requiredEnv "ACME_EMAIL" }}
- name: extraObjects[0].stringData.password
value: {{ requiredEnv "TRAEFIK_ADMIN_PASSWORD" }}
- name: tailscale-operator
namespace: tailscale
createNamespace: true
chart: tailscale/tailscale-operator
setString:
- name: oauth.clientId
value: {{ requiredEnv "TAILSCALE_OAUTH_CLIENT_ID" }}
- name: oauth.clientSecret
value: {{ requiredEnv "TAILSCALE_OAUTH_CLIENT_SECRET" }}
- name: apiServerProxyConfig.mode
value: noauth
# storage infrastructure
- name: rook-ceph
namespace: rook-ceph
createNamespace: true
chart: rook-release/rook-ceph
values:
- ./rook-ceph/values.yaml
- name: rook-ceph-cluster
namespace: rook-ceph
createNamespace: true
chart: rook-release/rook-ceph-cluster
values:
- ./rook-ceph-cluster/values.yaml
set:
- name: operatorNamespace
value: rook-ceph
# data storage
- name: pgo
namespace: postgres-operator
createNamespace: true
chart: crunchydata/pgo
values:
- ./postgres/operator-values.yaml
- name: postgres
namespace: datastore
createNamespace: true
chart: crunchydata/postgrescluster
values:
- postgres/values.yaml
- name: mariadb
namespace: datastore
createNamespace: true
chart: bitnami/mariadb
values:
- mariadb/values.yaml
setString:
- name: auth.rootPassword
value: {{ requiredEnv "MARIADB_ROOT_PASSWORD" }}
# monitoring
- name: grafana
namespace: grafana
createNamespace: true
chart: grafana/grafana
values:
- grafana/grafana_values.yaml
setString:
- name: adminPassword
value: VYHEKk0Q9KfqQ3UpTx8oc4InrXlUQivUuEeGU8LJ
- name: prometheus
namespace: grafana
createNamespace: true
chart: prometheus-community/prometheus
values:
- grafana/prometheus_values.yaml
- name: loki
namespace: grafana
createNamespace: true
chart: grafana/loki
values:
- grafana/loki_values.yaml
- name: alloy
namespace: grafana
createNamespace: true
chart: grafana/alloy
values:
- grafana/alloy_values.yaml
# goatchat matrix
- name: goatchat
namespace: goatchat
createNamespace: true
chart: ananace-charts/matrix-synapse
values:
- ./synapse/values.yaml
setString:
- name: config.macaroonSecretKey
value: {{ requiredEnv "GOATCHAT_SYNAPSE_MACAROON_SECRET_KEY" }}
- name: config.registrationSharedSecret
value: {{ requiredEnv "GOATCHAT_REGISTRATION_SHARED_SECRET" }}
- name: extraConfig.email.smtp_pass
value: {{ requiredEnv "GOATCHAT_SMTP_PASSWORD" }}
- name: gate
namespace: goatchat
createNamespace: true
chart: ./matrix-registration
values:
- ./matrix-registration/values-overrides.yaml
setString:
- name: registrationSharedSecret
value: {{ requiredEnv "GOATCHAT_REGISTRATION_SHARED_SECRET"}}
- name: adminApiSharedSecret
value: {{ requiredEnv "GOATCHAT_REGISTRATION_ADMIN_API_SHARE_SECRET"}}
# ghost blogs
- name: kgnot-ghost
namespace: ghost
createNamespace: true
chart: bitnami/ghost
values:
- ./kgnot/values.yaml
setString:
- name: ghostUsername
value: {{ requiredEnv "KGNOT_GHOST_USER_NAME" }}
- name: ghost-53ll
namespace: ghost
createNamespace: true
chart: bitnami/ghost
values:
- ./53ll/values.yaml
setString:
- name: ghostUsername
value: {{ requiredEnv "GHOST_53LL_USER_NAME" }}
# dev tools
- name: gitea
namespace: gitea
createNamespace: true
chart: gitea/gitea
values:
- ./gitea/values.yaml
setString:
- name: gitea.admin.password
value: {{ requiredEnv "GITEA_ADMIN_PASSWORD" }}
# backup
- name: k8up
namespace: k8up
createNamespace: true
chart: k8up-io/k8up
# backups
- name: k8up-backup
namespace: ghost
chart: ./k8up-backup
createNamespace: true
values:
- ./k8up-backup/values_override.yaml
setString:
- name: credentials.id
value: {{ requiredEnv "HETZNER_S3_ACCESS_KEY" }}
- name: credentials.key
value: {{ requiredEnv "HETZNER_S3_ACCESS_SECRET" }}
- name: repoPassword
value: {{ requiredEnv "k8UP_REPO_PASSWORD" }}
- name: goatchat-backup
namespace: goatchat
chart: ./k8up-backup
createNamespace: true
values:
- ./k8up-backup/values_override.yaml
setString:
- name: credentials.id
value: {{ requiredEnv "HETZNER_S3_ACCESS_KEY" }}
- name: credentials.key
value: {{ requiredEnv "HETZNER_S3_ACCESS_SECRET" }}
- name: repoPassword
value: {{ requiredEnv "k8UP_REPO_PASSWORD" }}
- name: gitea-backup
namespace: gitea
chart: ./k8up-backup
createNamespace: true
values:
- ./k8up-backup/values_override.yaml
setString:
- name: credentials.id
value: {{ requiredEnv "HETZNER_S3_ACCESS_KEY" }}
- name: credentials.key
value: {{ requiredEnv "HETZNER_S3_ACCESS_SECRET" }}
- name: repoPassword
value: {{ requiredEnv "k8UP_REPO_PASSWORD" }}

View File

@@ -1,10 +1,11 @@
kind: PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ printf "%s-matrix-registration" .Release.Name }}
name: immich-data
spec:
accessModes:
- ReadWriteOnce
- ReadWriteOnce
resources:
requests:
storage: 100M
storage: 200Gi

76
immich/values.yaml.gotmpl Normal file
View File

@@ -0,0 +1,76 @@
controllers:
main:
containers:
main:
image:
tag: v2.4.1
env:
DB_HOSTNAME: {{ exec "kubectl" (list "-n" "immich" "get" "secrets" "postgres-pguser-immich" "-ogo-template='{{.data.host | base64decode }}'") }}
DB_USERNAME: {{ exec "kubectl" (list "-n" "immich" "get" "secrets" "postgres-pguser-immich" "-ogo-template='{{.data.user | base64decode }}'") }}
DB_DATABASE_NAME: {{ exec "kubectl" (list "-n" "immich" "get" "secrets" "postgres-pguser-immich" "-ogo-template='{{.data.dbname | base64decode }}'") }}
DB_PASSWORD: {{ exec "kubectl" (list "-n" "immich" "get" "secrets" "postgres-pguser-immich" "-ogo-template='{{.data.password | base64decode }}'") }}
DB_VECTOR_EXTENSION: pgvector
immich:
persistence:
library:
existingClaim: immich-data
valkey:
enabled: true
master:
persistence:
annotations:
k8up.io/backup: 'false'
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 1
memory: 32Mi
server:
enabled: true
controllers:
main:
strategy: Recreate
containers:
main:
resources:
requests:
cpu: 10m
memory: 256Mi
limits:
cpu: 1
memory: 700Mi
ingress:
main:
enabled: true
tls:
- secretName: photos-incngrnt-ca-tls
hosts:
- photos.incngrnt.ca
hosts:
- host: photos.incngrnt.ca
paths:
- path: "/"
service:
identifier: main
machine-learning:
enabled: true
controllers:
main:
containers:
main:
resources:
requests:
cpu: 10m
memory: 128Mi
limits:
cpu: 1
memory: 1Gi

View File

@@ -0,0 +1,25 @@
init:
method: wget
wget:
url: https://git.incngrnt.ca/grant/incngrnt/releases/download/v0.0.8/v0.0.8.tar
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 500m
memory: 32Mi
ingress:
enabled: true
tls:
- secretName: incngrnt-ca-tls
hosts:
- incngrnt.ca
hosts:
- host: incngrnt.ca
paths:
- path: /
pathType: ImplementationSpecific

View File

@@ -1,15 +1,54 @@
update:
bws run 'helmfile deps'
deploy:
bws run 'helmfile apply'
deploy ARGS='':
bws run 'helmfile apply --output simple --skip-deps {{ARGS}}'
sdiff:
bws run 'helmfile diff --output simple'
ddiff:
bws run 'helmfile diff --output dyff'
diff ARGS='':
bws run 'helmfile diff --output dyff --skip-deps {{ARGS}}'
cleanuppods:
kubectl get pods --no-headers | grep -v Running | awk '{print $1}' | xargs kubectl delete pod
#!/bin/bash
kubectl get pods --all-namespaces | grep -v Running | awk '{print $1, $2}' | tail -n +2 | while read namespace pod; do
kubectl delete pod "$pod" --namespace "$namespace"
done
cleanupjobs:
#!/bin/bash
kubectl get jobs --all-namespaces | grep -v Running | awk '{print $1, $2}' | tail -n +2 | while read namespace job; do
kubectl delete job "$job" --namespace "$namespace"
done
pgrestart:
kubectl patch postgrescluster/postgres --type merge --patch '{"spec":{"metadata":{"annotations":{"restarted":"'"$(date)"'"}}}}'
talos-upgrade VERSION NODE:
talosctl upgrade \
--image factory.talos.dev/metal-installer/376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba:{{VERSION}} \
-n {{NODE}}
goatchat-register:
bws run 'curl -v -H '\"'Authorization: SharedSecret $GOATCHAT_REGISTRATION_ADMIN_API_SHARE_SECRET'\"' \
-H "Content-Type: application/json" \
-d '\''{"max_usage": 0, "expiration_date": "2026-01-01"}'\'' \
https://goatchat.ca/gate/api/token'
goatchat-register-review:
bws run 'curl -v -H '\"'Authorization: SharedSecret $GOATCHAT_REGISTRATION_ADMIN_API_SHARE_SECRET'\"' \
-H "Content-Type: application/json" \
https://goatchat.ca/gate/api/token' | jq
refresh-client-cert:
#!/bin/bash
yq -r .machine.ca.crt controlplane.yaml | base64 -d > ca.crt
yq -r .machine.ca.key controlplane.yaml | base64 -d > ca.key
talosctl gen key --name admin
talosctl gen csr --key admin.key --ip 127.0.0.1
talosctl gen crt --ca ca --csr admin.csr --name admin
yq -i '.contexts.fog.ca = "'"$(base64 -w0 ca.crt)"\
'" | .contexts.fog.crt = "'"$(base64 -w0 admin.crt)"\
'" | .contexts.fog.key = "'"$(base64 -w0 admin.key)"'"' \
.config/talosconfig
talosctl kubeconfig .config/kubeconfig -n 192.168.1.43

View File

@@ -1,6 +0,0 @@
apiVersion: v2
name: k8up-backup
description: A Helm chart for a k8up backup
type: application
version: 0.0.3

View File

@@ -1,20 +0,0 @@
apiVersion: k8up.io/v1
kind: Backup
metadata:
name: {{ .Release.Name }}
spec:
failedJobsHistoryLimit: 2
successfulJobsHistoryLimit: 2
backend:
repoPasswordSecretRef:
name: "{{ .Release.Name }}-repopassword"
key: password
s3:
endpoint: "{{ .Values.endpoint }}"
bucket: "{{ .Values.bucket }}"
accessKeyIDSecretRef:
name: "{{ .Release.Name }}-credentials"
key: id
secretAccessKeySecretRef:
name: "{{ .Release.Name }}-credentials"
key: key

View File

@@ -1,14 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: "{{ .Release.Name }}-credentials"
data:
id: "{{ .Values.credentials.id | b64enc}}"
key: "{{ .Values.credentials.key | b64enc}}"
---
apiVersion: v1
kind: Secret
metadata:
name: "{{ .Release.Name }}-repopassword"
data:
password: "{{ .Values.repoPassword | b64enc}}"

View File

@@ -1,7 +0,0 @@
# endpoint:
# bucket
# repoPassword:
# credentials:
# id:
# key:

View File

@@ -0,0 +1,16 @@
endpoint: hel1.your-objectstorage.com
bucket: fog
credentials:
id: {{ requiredEnv "HETZNER_S3_ACCESS_KEY" }}
key: {{ requiredEnv "HETZNER_S3_ACCESS_SECRET" }}
repoPassword: {{ requiredEnv "k8UP_REPO_PASSWORD" }}
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 500m
memory: 128Mi

View File

@@ -1,3 +0,0 @@
endpoint: hel1.your-objectstorage.com
bucket: fog

View File

11
k8up/values.yaml.gotmpl Normal file
View File

@@ -0,0 +1,11 @@
k8up:
envVars:
- name: BACKUP_GLOBAL_CONCURRENT_BACKUP_JOBS_LIMIT
values: 1
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 500m
memory: 64Mi

View File

@@ -3,7 +3,7 @@ image:
ghostBlogTitle: K&G Tie the Kgnot
ghostHost: https://kgnot.ca
ghostUsername: # set through cli args
ghostUsername: {{ requiredEnv "KGNOT_GHOST_USER_NAME" }}
existingSecret: ghost-kgnot-user-secret
allowEmptyPassword: false
@@ -13,14 +13,14 @@ readinessProbe:
enabled: false
resources:
requests:
cpu: 10m
ephemeral-storage: 50Mi
memory: 64Mi
limits:
cpu: 500m
ephemeral-storage: 2Gi
memory: 192Mi
requests:
cpu: 100m
ephemeral-storage: 50Mi
memory: 128Mi
memory: 350Mi
persistence:
size: 1Gi
@@ -50,5 +50,21 @@ ingress:
enabled: true
hostname: kgnot.ca
tls: true
annotations:
"traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt"
extraTls:
- secretName: kgnot-ca-tls
hosts:
- kgnot.ca
extraDeploy:
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: kgnot-ca
namespace: ghost
spec:
secretName: kgnot-ca-tls
issuerRef:
name: letsencrypt-kgnot
kind: ClusterIssuer
dnsNames:
- kgnot.ca

View File

@@ -1,6 +0,0 @@
persistent:
size: 5Gi
primary:
resourcesPreset: micro

View File

@@ -0,0 +1,16 @@
auth:
rootPassword: {{ requiredEnv "MARIADB_ROOT_PASSWORD" }}
persistent:
size: 5Gi
primary:
resources:
requests:
cpu: 50m
ephemeral-storage: 50Mi
memory: 96Mi
limits:
cpu: 1
ephemeral-storage: 2Gi
memory: 192Mi

View File

@@ -1,8 +0,0 @@
apiVersion: v2
name: matrix-registration
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "0.9.1"

View File

@@ -1,52 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-matrix-registration" .Release.Name }}
data:
config.yaml: |
server_location: {{ .Values.serverLocation }}
server_name: {{ .Values.serverName }}
registration_shared_secret: {{ .Values.registrationSharedSecret }}
admin_api_shared_secret: {{ .Values.adminApiSharedSecret }}
base_url: {{ .Values.serverBaseUrl }}
client_redirect: 'https://app.element.io/#/login'
client_logo: 'static/images/element-logo.png' # use '{cwd}' for current working directory
db: 'sqlite:///{cwd}db.sqlite3'
host: '0.0.0.0'
port: 5000
rate_limit: ["100 per day", "10 per minute"]
allow_cors: false
ip_logging: false
logging:
disable_existing_loggers: false
version: 1
root:
level: DEBUG
handlers: [console]
formatters:
brief:
format: '%(name)s - %(levelname)s - %(message)s'
precise:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: INFO
formatter: brief
stream: ext://sys.stdout
file:
class: logging.handlers.RotatingFileHandler
formatter: precise
level: INFO
filename: m_reg.log
maxBytes: 10485760 # 10MB
backupCount: 3
encoding: utf8
# password requirements
password:
min_length: 8
# username requirements
username:
validation_regex: [] #list of regexes that the selected username must match. Example: '[a-zA-Z]\.[a-zA-Z]'
invalidation_regex: ['(admin|support|password)'] #list of regexes that the selected username must NOT match. Example: '(admin|support)'

View File

@@ -1,44 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ printf "%s-matrix-registration" .Release.Name }}
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: matrix-registration
app: matrix-registration
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
labels:
name: matrix-registration
app: matrix-registration
spec:
securityContext: {}
containers:
- image: zeratax/matrix-registration:{{ printf "v%s" .Chart.AppVersion }}
imagePullPolicy: IfNotPresent
name: matrix-registration
args: ["serve"]
ports:
- containerPort: 5000
name: web
protocol: TCP
volumeMounts:
- mountPath: /data/config
name: matrix-registration
restartPolicy: Always
volumes:
- name: matrix-registration
configMap:
name: {{ printf "%s-matrix-registration" .Release.Name }}
- name: data
persistentVolumeClaim:
claimName: {{ printf "%s-matrix-registration" .Release.Name }}

View File

@@ -1,16 +0,0 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: {{ printf "%s-matrix-registration" .Release.Name }}
spec:
entryPoints:
- websecure
routes:
- match: Host(`goatchat.ca`) && PathPrefix(`/gate/`)
kind: Rule
services:
- kind: Service
name: {{ printf "%s-matrix-registration" .Release.Name }}
port: 5000
tls:
certResolver: letsencrypt

View File

@@ -1,11 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: {{ printf "%s-matrix-registration" .Release.Name }}
spec:
selector:
app: matrix-registration
ports:
- name: web
protocol: TCP
port: 5000

View File

@@ -1,5 +0,0 @@
serverLocation: http://goatchat-matrix-synapse:8008
serverName: goatchat.ca
serverBaseUrl: /gate
registrationSharedSecret: # set through cli
adminApiSharedSecret: # set through cli

View File

@@ -1,5 +0,0 @@
# serverLocation:
# serverName:
# serverBaseUrl:
# registrationSharedSecret:
# adminApiSharedSecret:

View File

@@ -0,0 +1,13 @@
serverLocation: http://goatchat-matrix-synapse:8008
serverName: goatchat.ca
serverBaseUrl: /gate
registrationSharedSecret: {{ requiredEnv "GOATCHAT_REGISTRATION_SHARED_SECRET" }}
adminApiSharedSecret: {{ requiredEnv "GOATCHAT_REGISTRATION_ADMIN_API_SHARE_SECRET" }}
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 500m
memory: 64Mi

View File

View File

@@ -0,0 +1,17 @@
controller:
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 500m
memory: 64Mi
speaker:
resources:
requests:
cpu: 10m
memory: 48Mi
limits:
cpu: 500m
memory: 96Mi

View File

@@ -1,2 +0,0 @@
pgoControllerLeaseName: ''
replicas: 1

View File

@@ -0,0 +1,10 @@
pgoControllerLeaseName: ''
replicas: 1
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 500m
memory: 160Mi

View File

@@ -1,27 +0,0 @@
instanceSize: 10Gi
backupsSize: 10Gi
patroni:
dynamicConfiguration:
postgresql:
pg_hba:
- "host all all all scram-sha-256"
users:
- name: grant
databases:
- postgres
- synapse
- gitea
options: "SUPERUSER LOGIN"
- name: synapse
databases:
- synapse
options: "LOGIN"
- name: gitea
databases:
- gitea
options: "LOGIN"

View File

@@ -0,0 +1,64 @@
instanceSize: 50Gi
instanceMemory: 1Gi
instanceCPU: 2
instances:
- name: instance1
resources:
requests:
cpu: 100m
memory: 192Mi
limits:
cpu: 2
memory: 1Gi
dataVolumeClaimSpec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 50Gi
patroni:
dynamicConfiguration:
postgresql:
pg_hba:
- "host all all all scram-sha-256"
shared_preload_libraries: pgvector
users:
- name: grant
databases:
- postgres
- synapse
- gitea
- immich
options: "SUPERUSER LOGIN"
- name: synapse
databases:
- synapse
options: "LOGIN"
- name: gitea
databases:
- gitea
options: "LOGIN"
- name: immich
databases:
- immich
options: "LOGIN"
pgBackRestConfig:
global:
repo1-path: /pgbackrest/datastore/postgres/repo1
repo1-retention-full: "10"
repo1-retention-full-type: count
repo1-s3-key: {{ requiredEnv "HETZNER_S3_ACCESS_KEY" }}
repo1-s3-key-secret: {{ requiredEnv "HETZNER_S3_ACCESS_SECRET" }}
repo1-cipher-pass: {{ requiredEnv "PG_BACKREST_PASSWORD" }}
repos:
- name: repo1
s3:
bucket: fog
endpoint: hel1.your-objectstorage.com
region: hel1
schedules:
full: "0 1 * * 0"
differential: "0 1 * * 1-6"

View File

@@ -0,0 +1,8 @@
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ceph-stripprefix
spec:
stripPrefix:
prefixes:
- /fog/ceph

View File

@@ -1,28 +0,0 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: rook-ceph-mgr-dashboard
spec:
entryPoints:
- websecure
routes:
- match: Host(`fog.goatchat.ca`) && PathPrefix(`/fog/ceph`)
kind: Rule
middlewares:
- name: ceph-stripprefix
services:
- kind: Service
name: rook-ceph-mgr-dashboard
port: 7000
tls:
certResolver: letsencrypt
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ceph-stripprefix
spec:
stripPrefix:
prefixes:
- /fog/ceph

View File

@@ -6,25 +6,58 @@ cephClusterSpec:
useAllNodes: true
useAllDevices: false
deviceFilter: "^sda"
config:
osd_memory_target: "1073741824" # 1GB per OSD to maintain 70% node capacity
resources:
mgr:
requests:
cpu: 100m
cpu: 50m
memory: 256Mi
limits:
cpu: "1"
memory: 704Mi
mon:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: "1"
memory: 64Mi
osd:
requests:
cpu: 100m
memory: 256Mi
memory: 896Mi
limits:
cpu: "1"
memory: 1280Mi
ingress:
dashboard:
host:
name: fog.incngrnt.ca
path: /fog/ceph
pathType: Prefix
tls:
- secretName: fog-incngrnt-ca-tls
hosts:
- fog.incngrnt.ca
annotations:
"traefik.ingress.kubernetes.io/router.middlewares": "rook-ceph-ceph-stripprefix@kubernetescrd"
extraDeploy:
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: fog-ceph-incngrnt-ca
namespace: rook-ceph
spec:
secretName: fog-incngrnt-ca-tls
issuerRef:
name: letsencrypt-incngrnt
kind: ClusterIssuer
dnsNames:
- fog.incngrnt.ca
cephFileSystems:
- name: ceph-filesystem
# see https://github.com/rook/rook/blob/master/Documentation/ceph-filesystem-crd.md#filesystem-settings for available configuration
@@ -43,10 +76,11 @@ cephFileSystems:
activeStandby: true
resources:
requests:
cpu: 100m
memory: 256Mi
limit:
cpu: 50m
memory: 64Mi
limits:
cpu: "1"
memory: 32Mi
storageClass:
enabled: true
isDefault: false

View File

@@ -2,3 +2,6 @@ resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 1
memory: 300Mi

View File

@@ -13,9 +13,17 @@ signingkey:
synapse:
strategy:
type: Recreate
resources:
requests:
cpu: 10m
memory: 128Mi
limits:
cpu: '1'
memory: 256Mi
config:
macaroonSecretKey: # set through cli args
registrationSharedSecret: # set through cli args
macaroonSecretKey: {{ requiredEnv "GOATCHAT_SYNAPSE_MACAROON_SECRET_KEY" }}
registrationSharedSecret: {{ requiredEnv "GOATCHAT_REGISTRATION_SHARED_SECRET" }}
extraConfig:
url_preview_enabled: true
@@ -37,7 +45,7 @@ extraConfig:
smtp_host: "smtp.sendgrid.net"
smtp_port: 587
smtp_user: "apikey"
smtp_pass: # set through cli args
smtp_pass: {{ requiredEnv "GOATCHAT_SMTP_PASSWORD" }}
require_transport_security: true
notif_from: "Your Friendly %(app)s homeserver <noreply@goatchat.ca>"
app_name: Goatchat
@@ -61,8 +69,10 @@ extraConfig:
ingress:
traefikPaths: true
annotations:
"traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt"
tls:
- secretName: goatchat-ca-tls
hosts:
- goatchat.ca
persistence:

11
tailscale/connector.yaml Normal file
View File

@@ -0,0 +1,11 @@
apiVersion: tailscale.com/v1alpha1
kind: Connector
metadata:
name: home-cidr
spec:
tags:
- "tag:k8s"
hostname: home-cidr
subnetRouter:
advertiseRoutes:
- "192.168.1.0/24"

30
tailscale/rbac.yaml Normal file
View File

@@ -0,0 +1,30 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: tailscale
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tailscale
rules:
- apiGroups: [""]
resourceNames: ["tailscale-auth"]
resources: ["secrets"]
verbs: ["get", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tailscale
subjects:
- kind: ServiceAccount
name: tailscale
roleRef:
kind: Role
name: tailscale
apiGroup: rbac.authorization.k8s.io

View File

@@ -0,0 +1,16 @@
operatorConfig:
extraEnv:
- name: PROXY_PRIORITY_CLASS_NAME
value: critical
resources:
requests:
cpu: 10m
memory: 48Mi
limits:
cpu: 500m
memory: 64Mi
oauth:
clientId: {{ requiredEnv "TAILSCALE_OAUTH_CLIENT_ID" }}
clientSecret: {{ requiredEnv "TAILSCALE_OAUTH_CLIENT_SECRET" }}

View File

@@ -1,5 +1,6 @@
cluster:
proxy:
extraArgs:
ipvs-strict-arp: true
allowSchedulingOnControlPlanes: true
clusterName: fog
proxy:
extraArgs:
ipvs-strict-arp: true
allowSchedulingOnControlPlanes: true

View File

@@ -0,0 +1,4 @@
machine:
install:
disk: /dev/nvme0n1
wipe: true

View File

@@ -1,4 +1,6 @@
machine:
install:
image: ghcr.io/siderolabs/installer:v1.11.1
kubelet:
extraArgs:
rotate-server-certificates: true

View File

@@ -1,84 +0,0 @@
deployment:
initContainers:
- name: volume-permissions
image: busybox:latest
command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"]
volumeMounts:
- name: data
mountPath: /data
updateStrategy:
type: Recreate
env:
- name: HETZNER_API_KEY
valueFrom:
secretKeyRef:
name: hetzner-api-key
key: token
additionalArguments:
- "--api.basePath=/fog/traefik"
persistence:
enabled: true
logs:
format: json
access:
enabled: true
format: json
service:
spec:
externalTrafficPolicy: Local
ingressRoute:
dashboard:
enabled: true
matchRule: Host(`fog.goatchat.ca`) && (PathPrefix(`/fog/traefik/dashboard`) || PathPrefix(`/fog/traefik/api`))
entryPoints: ["websecure"]
middlewares:
- name: traefik-dashboard-auth
tls:
certResolver: letsencrypt
ports:
websecure:
middlewares:
- traefik-rate-limit@kubernetescrd
extraObjects:
- apiVersion: v1
kind: Secret
metadata:
name: traefik-dashboard-auth-secret
type: kubernetes.io/basic-auth
stringData:
username: admin
password: # set through cli args
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: traefik-dashboard-auth
spec:
basicAuth:
secret: traefik-dashboard-auth-secret
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
spec:
rateLimit:
average: 50
burst: 100
certificatesResolvers:
letsencrypt:
acme:
dnschallenge:
provider: hetzner
delaybeforecheck: 30
email: # set through cli args
storage: /data/acme.json

158
traefik/values.yaml.gotmpl Normal file
View File

@@ -0,0 +1,158 @@
deployment:
replicas: 2
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 1
memory: 128Mi
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
podDisruptionBudget:
enabled: true
minAvailable: 1
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- traefik
topologyKey: kubernetes.io/hostname
additionalArguments:
- "--api.basePath=/fog/traefik"
persistence:
enabled: false
logs:
format: json
access:
enabled: true
format: json
service:
spec:
externalTrafficPolicy: Local
ingressRoute:
dashboard:
enabled: true
matchRule: Host(`fog.incngrnt.ca`) && (PathPrefix(`/fog/traefik/dashboard`) || PathPrefix(`/fog/traefik/api`))
entryPoints: ["websecure"]
middlewares:
- name: traefik-dashboard-auth
tls:
secretName: fog-incngrnt-ca-tls
ports:
websecure:
middlewares:
- traefik-rate-limit@kubernetescrd
web:
middlewares:
- traefik-redirectscheme@kubernetescrd
ssh:
port: 2222
expose:
default: true
exposedPort: 2222
protocol: TCP
extraObjects:
- apiVersion: v1
kind: Secret
metadata:
name: traefik-dashboard-auth-secret
type: kubernetes.io/basic-auth
stringData:
username: admin
password: {{ requiredEnv "TRAEFIK_ADMIN_PASSWORD" }}
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: traefik-dashboard-auth
spec:
basicAuth:
secret: traefik-dashboard-auth-secret
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
spec:
rateLimit:
average: 50
burst: 100
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: redirectscheme
spec:
redirectScheme:
scheme: https
permanent: true
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: fog-incngrnt-ca
namespace: traefik
spec:
secretName: fog-incngrnt-ca-tls
issuerRef:
name: letsencrypt-incngrnt
kind: ClusterIssuer
dnsNames:
- fog.incngrnt.ca
# other certs
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: goatchat-ca
namespace: goatchat
spec:
secretName: goatchat-ca-tls
issuerRef:
name: letsencrypt-goatchat
kind: ClusterIssuer
dnsNames:
- goatchat.ca
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: incngrnt-ca
namespace: incngrnt-web
spec:
secretName: incngrnt-ca-tls
issuerRef:
name: letsencrypt-incngrnt
kind: ClusterIssuer
dnsNames:
- incngrnt.ca
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: photos-incngrnt-ca
namespace: immich
spec:
secretName: photos-incngrnt-ca-tls
issuerRef:
name: letsencrypt-incngrnt
kind: ClusterIssuer
dnsNames:
- photos.incngrnt.ca

View File

@@ -0,0 +1,15 @@
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: critical
value: 1000000
globalDefault: false
description: "This priority class is for admin and critical maintenance services"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high
value: 500000
globalDefault: false
description: "This priority class is for high value services"