mirror of
https://gitlab.kube.huskypup.net/Scooby/Homelabv4.git
synced 2026-08-21 05:26:49 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
metadata:
|
||||
name: pg-guacamole
|
||||
namespace: guacamole
|
||||
spec:
|
||||
imageName: ghcr.io/cloudnative-pg/postgresql:16
|
||||
instances: 2
|
||||
|
||||
# Resource limits to prevent OOM
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
|
||||
# Spread replicas across different nodes
|
||||
affinity:
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
storage:
|
||||
size: 10Gi
|
||||
storageClass: rook-ceph-block
|
||||
|
||||
primaryUpdateStrategy: unsupervised
|
||||
|
||||
# PostgreSQL configuration for Guacamole
|
||||
postgresql:
|
||||
parameters:
|
||||
max_connections: "100"
|
||||
shared_buffers: "256MB"
|
||||
effective_cache_size: "768MB"
|
||||
maintenance_work_mem: "64MB"
|
||||
checkpoint_completion_target: "0.9"
|
||||
wal_buffers: "8MB"
|
||||
default_statistics_target: "100"
|
||||
random_page_cost: "1.1"
|
||||
effective_io_concurrency: "200"
|
||||
work_mem: "1310kB"
|
||||
min_wal_size: "1GB"
|
||||
max_wal_size: "4GB"
|
||||
|
||||
bootstrap:
|
||||
initdb:
|
||||
database: guacamole
|
||||
owner: guacamole
|
||||
|
||||
monitoring:
|
||||
enablePodMonitor: true
|
||||
@@ -0,0 +1,114 @@
|
||||
# Job to initialize Guacamole database schema
|
||||
# This should run once after the PostgreSQL cluster is ready
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: guacamole-init-schema
|
||||
namespace: guacamole
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 300
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
initContainers:
|
||||
- name: wait-for-postgres
|
||||
image: postgres:16-alpine
|
||||
securityContext:
|
||||
runAsUser: 10000
|
||||
runAsGroup: 10000
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
echo "Waiting for PostgreSQL to be ready..."
|
||||
until pg_isready -h pg-guacamole-rw -p 5432 -U guacamole; do
|
||||
echo "PostgreSQL not ready, waiting..."
|
||||
sleep 5
|
||||
done
|
||||
echo "PostgreSQL is ready!"
|
||||
env:
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: pg-guacamole-app
|
||||
key: password
|
||||
- name: generate-initdb
|
||||
image: guacamole/guacamole:1.6.0
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
/opt/guacamole/bin/initdb.sh --postgresql > /initdb/initdb.sql
|
||||
test -s /initdb/initdb.sql
|
||||
volumeMounts:
|
||||
- name: initdb
|
||||
mountPath: /initdb
|
||||
containers:
|
||||
- name: init-schema
|
||||
image: postgres:16-alpine
|
||||
securityContext:
|
||||
runAsUser: 10000
|
||||
runAsGroup: 10000
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
echo "Checking if schema already exists..."
|
||||
TABLES=$(PGPASSWORD="$PGPASSWORD" psql -h pg-guacamole-rw -U guacamole -d guacamole -tA -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_name = 'guacamole_user';" 2>/dev/null | tr -d '[:space:]' || printf '0')
|
||||
TABLES=${TABLES:-0}
|
||||
|
||||
if [ "$TABLES" -gt "0" ]; then
|
||||
echo "Schema already exists."
|
||||
else
|
||||
echo "Initializing Guacamole database schema..."
|
||||
PGPASSWORD="$PGPASSWORD" psql -v ON_ERROR_STOP=1 -h pg-guacamole-rw -U guacamole -d guacamole -f /initdb/initdb.sql
|
||||
echo "Schema initialization complete!"
|
||||
fi
|
||||
|
||||
echo "Setting up Authentik Admins group permissions..."
|
||||
PGPASSWORD="$PGPASSWORD" psql -v ON_ERROR_STOP=1 -h pg-guacamole-rw -U guacamole -d guacamole -f /schema/permissions.sql
|
||||
echo "Authentik Admins group permissions configured!"
|
||||
env:
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: pg-guacamole-app
|
||||
key: password
|
||||
volumeMounts:
|
||||
- name: initdb
|
||||
mountPath: /initdb
|
||||
- name: schema
|
||||
mountPath: /schema
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: initdb
|
||||
emptyDir: {}
|
||||
- name: schema
|
||||
configMap:
|
||||
name: guacamole-schema
|
||||
@@ -0,0 +1,256 @@
|
||||
# Guacamole complete deployment with OpenID/Authentik support
|
||||
# This deployment includes:
|
||||
# - Environment-based OpenID configuration
|
||||
# - PostgreSQL backend for connections/users
|
||||
# - Authentik uses Let's Encrypt (no custom cert import needed)
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: guacamole
|
||||
namespace: guacamole
|
||||
labels:
|
||||
app: guacamole
|
||||
component: client
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 0
|
||||
maxUnavailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: guacamole
|
||||
component: client
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: guacamole
|
||||
component: client
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- name: guacamole
|
||||
image: guacamole/guacamole:1.6.0
|
||||
securityContext:
|
||||
runAsUser: 10000
|
||||
runAsGroup: 10000
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: tomcat-work
|
||||
mountPath: /usr/local/tomcat/work
|
||||
- name: tomcat-logs
|
||||
mountPath: /usr/local/tomcat/logs
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: GUACD_HOSTNAME
|
||||
value: "guacd"
|
||||
- name: GUACD_PORT
|
||||
value: "4822"
|
||||
- name: POSTGRESQL_HOSTNAME
|
||||
value: "pg-guacamole-rw"
|
||||
- name: POSTGRESQL_PORT
|
||||
value: "5432"
|
||||
- name: POSTGRESQL_DATABASE
|
||||
value: "guacamole"
|
||||
- name: POSTGRESQL_ENABLED
|
||||
value: "true"
|
||||
- name: POSTGRESQL_USERNAME
|
||||
value: "guacamole"
|
||||
- name: POSTGRESQL_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: pg-guacamole-app
|
||||
key: password
|
||||
- name: POSTGRESQL_AUTO_CREATE_ACCOUNTS
|
||||
value: "true"
|
||||
- name: ENABLE_ENVIRONMENT_PROPERTIES
|
||||
value: "true"
|
||||
- name: LOG_LEVEL
|
||||
value: "debug"
|
||||
- name: WEBAPP_CONTEXT
|
||||
value: "ROOT"
|
||||
# FIX: Enabled WebSockets to stop the 10-second tunnel timeout
|
||||
- name: ENABLE_WEBSOCKET
|
||||
value: "true"
|
||||
- name: EXTENSION_PRIORITY
|
||||
value: "*,openid"
|
||||
- name: OPENID_RESPONSE_TYPE
|
||||
value: "code"
|
||||
- name: OPENID_AUTHORIZATION_ENDPOINT
|
||||
value: "https://auth.kube.huskypup.net/application/o/authorize/"
|
||||
- name: OPENID_JWKS_ENDPOINT
|
||||
value: "https://auth.kube.huskypup.net/application/o/guacamole/jwks/"
|
||||
- name: OPENID_ISSUER
|
||||
value: "https://auth.kube.huskypup.net/application/o/guacamole/"
|
||||
- name: OPENID_TOKEN_ENDPOINT
|
||||
value: "https://auth.kube.huskypup.net/application/o/token/"
|
||||
- name: OPENID_REDIRECT_URI
|
||||
value: "https://guacamole.kube.huskypup.net/"
|
||||
- name: OPENID_USERNAME_CLAIM_TYPE
|
||||
value: "preferred_username"
|
||||
- name: OPENID_GROUPS_CLAIM_TYPE
|
||||
value: "groups"
|
||||
- name: OPENID_SCOPE
|
||||
value: "openid email profile groups"
|
||||
- name: OPENID_ALLOWED_CLOCK_SKEW
|
||||
value: "30"
|
||||
- name: OPENID_MAX_TOKEN_VALIDITY
|
||||
value: "300"
|
||||
- name: OPENID_MAX_NONCE_VALIDITY
|
||||
value: "60"
|
||||
- name: OPENID_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: guacamole-oauth-secret
|
||||
key: client-id
|
||||
- name: OPENID_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: guacamole-oauth-secret
|
||||
key: client-secret
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "1000m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/languages
|
||||
port: http
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 30
|
||||
# FIX: Relaxed readiness probe so minor DB lags don't kill the Endpoint
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/languages
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 15
|
||||
failureThreshold: 5
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: tomcat-work
|
||||
emptyDir: {}
|
||||
- name: tomcat-logs
|
||||
emptyDir: {}
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: guacd
|
||||
namespace: guacamole
|
||||
labels:
|
||||
app: guacamole
|
||||
component: guacd
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: guacamole
|
||||
component: guacd
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: guacamole
|
||||
component: guacd
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- name: guacd
|
||||
image: guacamole/guacd:1.6.0
|
||||
securityContext:
|
||||
runAsUser: 10000
|
||||
runAsGroup: 10000
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: home
|
||||
mountPath: /home
|
||||
ports:
|
||||
- name: guacd
|
||||
containerPort: 4822
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: LOG_LEVEL
|
||||
value: "debug"
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "10m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 4822
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 1
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: home
|
||||
emptyDir: {}
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: guacamole
|
||||
namespace: guacamole
|
||||
labels:
|
||||
app: guacamole
|
||||
component: client
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: guacamole
|
||||
component: client
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: guacd
|
||||
namespace: guacamole
|
||||
labels:
|
||||
app: guacamole
|
||||
component: guacd
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 4822
|
||||
targetPort: guacd
|
||||
protocol: TCP
|
||||
name: guacd
|
||||
selector:
|
||||
app: guacamole
|
||||
component: guacd
|
||||
@@ -0,0 +1,67 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: guacamole-envoy-tls
|
||||
namespace: guacamole
|
||||
spec:
|
||||
secretName: guacamole-envoy-tls
|
||||
issuerRef:
|
||||
kind: ClusterIssuer
|
||||
name: letsencrypt-production
|
||||
dnsNames:
|
||||
- guacamole.kube.huskypup.net
|
||||
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: guacamole
|
||||
namespace: guacamole
|
||||
spec:
|
||||
gatewayClassName: envoy-gateway
|
||||
listeners:
|
||||
- name: https
|
||||
hostname: guacamole.kube.huskypup.net
|
||||
port: 443
|
||||
protocol: HTTPS
|
||||
tls:
|
||||
mode: Terminate
|
||||
certificateRefs:
|
||||
- kind: Secret
|
||||
name: guacamole-envoy-tls
|
||||
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: guacamole
|
||||
namespace: guacamole
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: guacamole
|
||||
sectionName: https
|
||||
hostnames:
|
||||
- guacamole.kube.huskypup.net
|
||||
rules:
|
||||
# Legacy path support: https://host/guacamole/* -> https://host/*
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /guacamole
|
||||
filters:
|
||||
- type: URLRewrite
|
||||
urlRewrite:
|
||||
path:
|
||||
type: ReplacePrefixMatch
|
||||
replacePrefixMatch: /
|
||||
backendRefs:
|
||||
- name: guacamole
|
||||
port: 8080
|
||||
# Standard root routing
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: guacamole
|
||||
port: 8080
|
||||
@@ -0,0 +1,33 @@
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: guacamole
|
||||
namespace: guacamole
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: edge
|
||||
namespace: gateway
|
||||
sectionName: https
|
||||
hostnames:
|
||||
- guacamole.kube.huskypup.net
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /guacamole
|
||||
filters:
|
||||
- type: URLRewrite
|
||||
urlRewrite:
|
||||
path:
|
||||
type: ReplacePrefixMatch
|
||||
replacePrefixMatch: /
|
||||
backendRefs:
|
||||
- name: guacamole
|
||||
port: 8080
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: guacamole
|
||||
port: 8080
|
||||
@@ -0,0 +1,29 @@
|
||||
# kubernetes/apps/guacamole/external-secret.yaml
|
||||
# ExternalSecrets for Guacamole - pulls credentials from Vault
|
||||
|
||||
# Note: Database password is managed by CNPG cluster (pg-guacamole-app secret)
|
||||
# We reference it directly in the guacamole values.yaml
|
||||
|
||||
---
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: guacamole-oauth
|
||||
namespace: guacamole
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: vault-backend
|
||||
target:
|
||||
name: guacamole-oauth-secret
|
||||
creationPolicy: Owner
|
||||
data:
|
||||
- secretKey: client-id
|
||||
remoteRef:
|
||||
key: guacamole-oauth
|
||||
property: client-id
|
||||
- secretKey: client-secret
|
||||
remoteRef:
|
||||
key: guacamole-oauth
|
||||
property: client-secret
|
||||
@@ -0,0 +1,16 @@
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: guacamole
|
||||
namespace: guacamole
|
||||
spec:
|
||||
hosts:
|
||||
- guacamole.kube.huskypup.net
|
||||
gateways:
|
||||
- istio-system/edge
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: guacamole.guacamole.svc.cluster.local
|
||||
port:
|
||||
number: 8080
|
||||
Reference in New Issue
Block a user