Wire Zabbix/Matrix credentials to 1Password-synced secrets, add OnePasswordItem CRDs

- Zabbix: Remove hardcoded zabbix-db-secret and zabbix-admin-secret, reference
  zabbix-credentials (1Password) for DB-User, DB-Password, and admin password
- Matrix: Remove hardcoded matrix-db-secret, reference matrix-credentials for
  Postgres user/password. Convert ConfigMap homeserver.yaml to template with
  __DB_PASSWORD__/__DB_USER__ placeholders, inject via busybox init container
- Guacamole: Add OnePasswordItem CRD for future use. MySQL DB creds remain in
  guac-db-secret (1Password item lacks DB-specific fields — gap documented)
- All three services now include OnePasswordItem CRD manifests for ArgoCD mgmt
This commit is contained in:
Andrew Stoltz
2026-03-09 18:28:38 -05:00
parent 8f405d4df0
commit 3199c509c0
3 changed files with 733 additions and 670 deletions

View File

@@ -1,326 +1,344 @@
# Apache Guacamole - Remote Desktop Gateway
# MySQL 8 + guacd + guacamole web
# ArgoCD managed - BlueJay Lab
---
apiVersion: v1
kind: Namespace
metadata:
name: guacamole
labels:
app.kubernetes.io/part-of: bluejay-infra
---
apiVersion: v1
kind: Secret
metadata:
name: guac-db-secret
namespace: guacamole
type: Opaque
stringData:
MYSQL_ROOT_PASSWORD: BlueJay-Guac-DB-2026
MYSQL_DATABASE: guacamole_db
MYSQL_USER: guacamole
MYSQL_PASSWORD: BlueJay-Guac-DB-2026
---
# MySQL 8 StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: guac-mysql
namespace: guacamole
labels:
app: guac-mysql
spec:
serviceName: guac-mysql
replicas: 1
selector:
matchLabels:
app: guac-mysql
template:
metadata:
labels:
app: guac-mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
name: mysql
envFrom:
- secretRef:
name: guac-db-secret
volumeMounts:
- name: guac-mysql-data
mountPath: /var/lib/mysql
resources:
requests:
memory: 256Mi
cpu: 100m
limits:
memory: 1Gi
cpu: 500m
livenessProbe:
exec:
command:
- mysqladmin
- ping
- -h
- localhost
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
exec:
command:
- mysqladmin
- ping
- -h
- localhost
initialDelaySeconds: 30
periodSeconds: 5
volumeClaimTemplates:
- metadata:
name: guac-mysql-data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
name: guac-mysql
namespace: guacamole
spec:
selector:
app: guac-mysql
ports:
- port: 3306
targetPort: 3306
name: mysql
clusterIP: None
---
# DB schema init Job
# Generates the MySQL schema and pipes it into the database
apiVersion: batch/v1
kind: Job
metadata:
name: guacamole-initdb
namespace: guacamole
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
ttlSecondsAfterFinished: 300
template:
spec:
restartPolicy: OnFailure
initContainers:
- name: wait-for-mysql
image: mysql:8.0
command:
- sh
- -c
- |
until mysqladmin ping -h guac-mysql --silent; do
echo "Waiting for MySQL..."
sleep 5
done
containers:
- name: initdb
image: guacamole/guacamole:latest
command:
- sh
- -c
- |
# Generate schema SQL
/opt/guacamole/bin/initdb.sh --mysql > /tmp/initdb.sql
# Apply schema (ignore errors if tables already exist)
mysql -h guac-mysql -u root -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" < /tmp/initdb.sql || true
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_ROOT_PASSWORD
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_DATABASE
---
# guacd (Guacamole daemon)
apiVersion: apps/v1
kind: Deployment
metadata:
name: guacd
namespace: guacamole
labels:
app: guacd
spec:
replicas: 1
selector:
matchLabels:
app: guacd
template:
metadata:
labels:
app: guacd
spec:
containers:
- name: guacd
image: guacamole/guacd:latest
ports:
- containerPort: 4822
name: guacd
resources:
requests:
memory: 128Mi
cpu: 100m
limits:
memory: 512Mi
cpu: 500m
livenessProbe:
tcpSocket:
port: 4822
initialDelaySeconds: 15
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: guacd
namespace: guacamole
spec:
selector:
app: guacd
ports:
- port: 4822
targetPort: 4822
name: guacd
---
# Guacamole Web Application
apiVersion: apps/v1
kind: Deployment
metadata:
name: guacamole
namespace: guacamole
labels:
app: guacamole
spec:
replicas: 1
selector:
matchLabels:
app: guacamole
template:
metadata:
labels:
app: guacamole
spec:
containers:
- name: guacamole
image: guacamole/guacamole:latest
ports:
- containerPort: 8080
name: http
env:
- name: GUACD_HOSTNAME
value: guacd
- name: GUACD_PORT
value: "4822"
- name: MYSQL_HOSTNAME
value: guac-mysql
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_DATABASE
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_USER
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_PASSWORD
resources:
requests:
memory: 256Mi
cpu: 100m
limits:
memory: 1Gi
cpu: 500m
livenessProbe:
httpGet:
path: /guacamole/
port: 8080
initialDelaySeconds: 120
periodSeconds: 10
readinessProbe:
httpGet:
path: /guacamole/
port: 8080
initialDelaySeconds: 60
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: guacamole
namespace: guacamole
spec:
selector:
app: guacamole
ports:
- port: 8080
targetPort: 8080
name: http
---
# Traefik addPrefix middleware
# External URL guac.iamworkin.lan/ gets prefix /guacamole added
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: guac-add-prefix
namespace: guacamole
spec:
addPrefix:
prefix: /guacamole
---
# TLS Certificate via cert-manager
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: guacamole-tls
namespace: guacamole
spec:
secretName: guacamole-tls
issuerRef:
name: step-ca-acme
kind: ClusterIssuer
dnsNames:
- guac.iamworkin.lan
---
# Traefik IngressRoute
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: guacamole
namespace: guacamole
spec:
entryPoints:
- websecure
routes:
- match: Host(`guac.iamworkin.lan`)
kind: Rule
middlewares:
- name: guac-add-prefix
services:
- name: guacamole
port: 8080
tls:
secretName: guacamole-tls
# Apache Guacamole - Remote Desktop Gateway
# MySQL 8 + guacd + guacamole web
# ArgoCD managed - BlueJay Lab
# DB credentials sourced from 1Password via OnePasswordItem CRD (guacamole-credentials)
# Note: guacamole-credentials contains Guacamole admin UI creds (username/password),
# not MySQL DB creds. MySQL root/user password is kept in guac-db-secret (still inline)
# because 1Password item lacks DB-specific fields. See gap notes below.
---
apiVersion: v1
kind: Namespace
metadata:
name: guacamole
labels:
app.kubernetes.io/part-of: bluejay-infra
---
apiVersion: v1
kind: Secret
metadata:
name: guac-db-secret
namespace: guacamole
type: Opaque
stringData:
MYSQL_ROOT_PASSWORD: BlueJay-Guac-DB-2026
MYSQL_DATABASE: guacamole_db
MYSQL_USER: guacamole
MYSQL_PASSWORD: BlueJay-Guac-DB-2026
---
# MySQL 8 StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: guac-mysql
namespace: guacamole
labels:
app: guac-mysql
spec:
serviceName: guac-mysql
replicas: 1
selector:
matchLabels:
app: guac-mysql
template:
metadata:
labels:
app: guac-mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
name: mysql
envFrom:
- secretRef:
name: guac-db-secret
volumeMounts:
- name: guac-mysql-data
mountPath: /var/lib/mysql
resources:
requests:
memory: 256Mi
cpu: 100m
limits:
memory: 1Gi
cpu: 500m
livenessProbe:
exec:
command:
- mysqladmin
- ping
- -h
- localhost
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
exec:
command:
- mysqladmin
- ping
- -h
- localhost
initialDelaySeconds: 30
periodSeconds: 5
volumeClaimTemplates:
- metadata:
name: guac-mysql-data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
name: guac-mysql
namespace: guacamole
spec:
selector:
app: guac-mysql
ports:
- port: 3306
targetPort: 3306
name: mysql
clusterIP: None
---
# DB schema init Job
# Generates the MySQL schema and pipes it into the database
apiVersion: batch/v1
kind: Job
metadata:
name: guacamole-initdb
namespace: guacamole
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
ttlSecondsAfterFinished: 300
template:
spec:
restartPolicy: OnFailure
initContainers:
- name: wait-for-mysql
image: mysql:8.0
command:
- sh
- -c
- |
until mysqladmin ping -h guac-mysql --silent; do
echo "Waiting for MySQL..."
sleep 5
done
containers:
- name: initdb
image: guacamole/guacamole:latest
command:
- sh
- -c
- |
# Generate schema SQL
/opt/guacamole/bin/initdb.sh --mysql > /tmp/initdb.sql
# Apply schema (ignore errors if tables already exist)
mysql -h guac-mysql -u root -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" < /tmp/initdb.sql || true
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_ROOT_PASSWORD
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_DATABASE
---
# guacd (Guacamole daemon)
apiVersion: apps/v1
kind: Deployment
metadata:
name: guacd
namespace: guacamole
labels:
app: guacd
spec:
replicas: 1
selector:
matchLabels:
app: guacd
template:
metadata:
labels:
app: guacd
spec:
containers:
- name: guacd
image: guacamole/guacd:latest
ports:
- containerPort: 4822
name: guacd
resources:
requests:
memory: 128Mi
cpu: 100m
limits:
memory: 512Mi
cpu: 500m
livenessProbe:
tcpSocket:
port: 4822
initialDelaySeconds: 15
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: guacd
namespace: guacamole
spec:
selector:
app: guacd
ports:
- port: 4822
targetPort: 4822
name: guacd
---
# Guacamole Web Application
apiVersion: apps/v1
kind: Deployment
metadata:
name: guacamole
namespace: guacamole
labels:
app: guacamole
spec:
replicas: 1
selector:
matchLabels:
app: guacamole
template:
metadata:
labels:
app: guacamole
spec:
containers:
- name: guacamole
image: guacamole/guacamole:latest
ports:
- containerPort: 8080
name: http
env:
- name: GUACD_HOSTNAME
value: guacd
- name: GUACD_PORT
value: "4822"
- name: MYSQL_HOSTNAME
value: guac-mysql
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_DATABASE
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_USER
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: guac-db-secret
key: MYSQL_PASSWORD
resources:
requests:
memory: 256Mi
cpu: 100m
limits:
memory: 1Gi
cpu: 500m
livenessProbe:
httpGet:
path: /guacamole/
port: 8080
initialDelaySeconds: 120
periodSeconds: 10
readinessProbe:
httpGet:
path: /guacamole/
port: 8080
initialDelaySeconds: 60
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: guacamole
namespace: guacamole
spec:
selector:
app: guacamole
ports:
- port: 8080
targetPort: 8080
name: http
---
# Traefik addPrefix middleware
# External URL guac.iamworkin.lan/ gets prefix /guacamole added
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: guac-add-prefix
namespace: guacamole
spec:
addPrefix:
prefix: /guacamole
---
# TLS Certificate via cert-manager
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: guacamole-tls
namespace: guacamole
spec:
secretName: guacamole-tls
issuerRef:
name: step-ca-acme
kind: ClusterIssuer
dnsNames:
- guac.iamworkin.lan
---
# Traefik IngressRoute
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: guacamole
namespace: guacamole
spec:
entryPoints:
- websecure
routes:
- match: Host(`guac.iamworkin.lan`)
kind: Rule
middlewares:
- name: guac-add-prefix
services:
- name: guacamole
port: 8080
tls:
secretName: guacamole-tls
---
# 1Password secret sync — creates guacamole-credentials K8s Secret
# Fields: username, password, URL, Note
# NOTE: This secret contains Guacamole admin UI credentials only.
# MySQL DB credentials (MYSQL_ROOT_PASSWORD, MYSQL_PASSWORD) are NOT in 1Password yet.
# To fully externalize: add DB-User, DB-Password, DB-Root-Password fields to the
# "Guacamole" 1Password item, then replace guac-db-secret refs with guacamole-credentials.
apiVersion: onepassword.com/v1
kind: OnePasswordItem
metadata:
name: guacamole-credentials
namespace: guacamole
spec:
itemPath: vaults/IAmWorkin/items/Guacamole