- MySQL StatefulSet, initdb Job, Guacamole web all reference guacamole-credentials - DB-User, DB-Password, DB-Root-Password, DB-Name fields added to 1Password item - Zero inline secrets remain in manifest
345 lines
8.0 KiB
YAML
345 lines
8.0 KiB
YAML
# Apache Guacamole - Remote Desktop Gateway
|
|
# MySQL 8 + guacd + guacamole web
|
|
# ArgoCD managed - BlueJay Lab
|
|
# ALL credentials sourced from 1Password via OnePasswordItem CRD (guacamole-credentials)
|
|
# Fields: username, password, DB-User, DB-Password, DB-Root-Password, DB-Name, URL
|
|
---
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: guacamole
|
|
labels:
|
|
app.kubernetes.io/part-of: bluejay-infra
|
|
---
|
|
# 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
|
|
env:
|
|
- name: MYSQL_ROOT_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: guacamole-credentials
|
|
key: DB-Root-Password
|
|
- name: MYSQL_DATABASE
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: guacamole-credentials
|
|
key: DB-Name
|
|
- name: MYSQL_USER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: guacamole-credentials
|
|
key: DB-User
|
|
- name: MYSQL_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: guacamole-credentials
|
|
key: DB-Password
|
|
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: guacamole-credentials
|
|
key: DB-Root-Password
|
|
- name: MYSQL_DATABASE
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: guacamole-credentials
|
|
key: DB-Name
|
|
---
|
|
# 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: guacamole-credentials
|
|
key: DB-Name
|
|
- name: MYSQL_USER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: guacamole-credentials
|
|
key: DB-User
|
|
- name: MYSQL_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: guacamole-credentials
|
|
key: DB-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, DB-User, DB-Password, DB-Root-Password, DB-Name, URL
|
|
apiVersion: onepassword.com/v1
|
|
kind: OnePasswordItem
|
|
metadata:
|
|
name: guacamole-credentials
|
|
namespace: guacamole
|
|
spec:
|
|
itemPath: vaults/IAmWorkin/items/Guacamole
|