workout-system: deploy SparkyFitness v0.16.6.3, park wger, take over workout.dooplex.hu
SparkyFitness (https://github.com/CodeWithCJ/SparkyFitness) replaces wger on workout.dooplex.hu / workout.home with native Authentik OIDC. Components (sparkyfitness.yaml): dedicated postgres:15-alpine, server (3010, /api/health), frontend nginx (root image, listens :80). PVCs sparkyfitness-postgres + sparkyfitness-uploads (Longhorn, backup labels). In-app OIDC, no forward-auth. Deviations from the deploy spec, following upstream ground truth: - In-container mount path for uploads is /app/SparkyFitnessServer/uploads (per the upstream Helm chart values.yaml), not /app/uploads. - Frontend root image (codewithcj/sparkyfitness) has 'listen 80;' hardcoded -> NGINX_LISTEN_PORT=80, containerPort/Service 80. - Image names use the docker-compose variants (codewithcj/sparkyfitness_server, codewithcj/sparkyfitness); the upstream Helm chart uses -server/-frontend. - All wger Deployments scaled to 0 (incl. celery worker/beat), not just wger + wger-redis, so celery doesn't crashloop against the downed redis. Secrets (outside git): sparky-oauth (client-id/client-secret, pre-existing) + sparky-app (db + app-db creds, api-encryption-key, better-auth-secret). wger is parked, not deleted: Deployments at 0, both Ingresses removed (ArgoCD prune frees the hostnames); Services/ConfigMap/PVCs/CNPG DB kept for rollback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,496 @@
|
|||||||
|
# SparkyFitness - Workout / nutrition tracker
|
||||||
|
# https://github.com/CodeWithCJ/SparkyFitness
|
||||||
|
# Version: v0.16.6.3 (pinned)
|
||||||
|
# Domain: workout.dooplex.hu (+ workout.home)
|
||||||
|
# Auth: SparkyFitness NATIVE OIDC against Authentik (no forward-auth in front).
|
||||||
|
# DB: dedicated postgres:15-alpine in this namespace (NOT the shared CNPG cluster).
|
||||||
|
#
|
||||||
|
# ============================================================================
|
||||||
|
# Replaces wger (see workout.yaml — wger is parked, not deleted, for rollback).
|
||||||
|
#
|
||||||
|
# Image names: the upstream Helm chart uses codewithcj/sparkyfitness-{server,frontend};
|
||||||
|
# we use the docker-compose image names (codewithcj/sparkyfitness_server and
|
||||||
|
# codewithcj/sparkyfitness) as specified for this deployment. The frontend root
|
||||||
|
# image's nginx has `listen 80;` hardcoded, so the frontend listens on :80
|
||||||
|
# (NGINX_LISTEN_PORT set explicitly to match container/Service ports).
|
||||||
|
#
|
||||||
|
# Secrets (manual, NOT in git — created with kubectl):
|
||||||
|
# sparky-oauth : client-id, client-secret (OIDC; already created)
|
||||||
|
# sparky-app : db-user, db-password, app-db-user, (DB owner + app user +
|
||||||
|
# app-db-password, api-encryption-key, crypto keys)
|
||||||
|
# better-auth-secret
|
||||||
|
# api-encryption-key / better-auth-secret must NEVER change after first boot
|
||||||
|
# (changing them locks out 2FA users and makes encrypted data unrecoverable).
|
||||||
|
#
|
||||||
|
# Authentik provider: OAuth2/OpenID, application slug `sparkyfitness`, confidential,
|
||||||
|
# RS256, scopes `openid profile email`. Issuer must match SPARKY_FITNESS_OIDC_ISSUER_URL
|
||||||
|
# below. Register the exact oidc-callback redirect URI shown in SparkyFitness admin
|
||||||
|
# (Settings -> Authentication) once the app is up.
|
||||||
|
# ============================================================================
|
||||||
|
---
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Database: dedicated PostgreSQL 15 (alpine). POSTGRES_USER is the cluster
|
||||||
|
# superuser, so SparkyFitness auto-creates the limited app role, applies RLS
|
||||||
|
# table ownership, and installs uuid-ossp/pgcrypto/pg_stat_statements on its
|
||||||
|
# own — no init SQL or shared_preload_libraries tinkering needed.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: sparkyfitness-db
|
||||||
|
namespace: workout-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: postgres
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: postgres
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: postgres
|
||||||
|
spec:
|
||||||
|
enableServiceLinks: false
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 999
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres:15-alpine
|
||||||
|
env:
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-app
|
||||||
|
key: db-user
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-app
|
||||||
|
key: db-password
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
value: "sparkyfitness_db"
|
||||||
|
# Keep PG data in a subdir so the volume mount root can hold lost+found
|
||||||
|
- name: PGDATA
|
||||||
|
value: "/var/lib/postgresql/data/pgdata"
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
name: postgres
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /var/lib/postgresql/data
|
||||||
|
subPath: data
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["sh", "-c", "pg_isready -U \"$POSTGRES_USER\" -d \"$POSTGRES_DB\""]
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 15
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 5
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["sh", "-c", "pg_isready -U \"$POSTGRES_USER\" -d \"$POSTGRES_DB\""]
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: sparkyfitness-postgres
|
||||||
|
---
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Server: Node.js backend API (port 3010). Runs DB migrations + creates the
|
||||||
|
# limited app role on first boot. /api/health is the health endpoint.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: sparkyfitness-server
|
||||||
|
namespace: workout-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: server
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: server
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: server
|
||||||
|
annotations:
|
||||||
|
# Tag format is vMAJOR.MINOR.PATCH.BUILD (e.g. v0.16.6.3)
|
||||||
|
match-regex.version-checker.io/server: '^v\d+\.\d+\.\d+\.\d+$'
|
||||||
|
spec:
|
||||||
|
enableServiceLinks: false
|
||||||
|
securityContext:
|
||||||
|
# node user (UID 1000) needs to write to the uploads PVC
|
||||||
|
fsGroup: 1000
|
||||||
|
initContainers:
|
||||||
|
- name: wait-for-db
|
||||||
|
image: busybox:1.36
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
echo "Waiting for PostgreSQL..."
|
||||||
|
until nc -z sparkyfitness-db 5432; do
|
||||||
|
echo "PostgreSQL not ready, waiting..."
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "PostgreSQL is ready!"
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: codewithcj/sparkyfitness_server:v0.16.6.3
|
||||||
|
env:
|
||||||
|
# ---- Database (owner / superuser role, used for migrations) ----
|
||||||
|
- name: SPARKY_FITNESS_DB_HOST
|
||||||
|
value: "sparkyfitness-db"
|
||||||
|
- name: SPARKY_FITNESS_DB_PORT
|
||||||
|
value: "5432"
|
||||||
|
- name: SPARKY_FITNESS_DB_NAME
|
||||||
|
value: "sparkyfitness_db"
|
||||||
|
- name: SPARKY_FITNESS_DB_USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-app
|
||||||
|
key: db-user
|
||||||
|
- name: SPARKY_FITNESS_DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-app
|
||||||
|
key: db-password
|
||||||
|
# ---- Limited-privilege app role (auto-created on first boot) ----
|
||||||
|
- name: SPARKY_FITNESS_APP_DB_USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-app
|
||||||
|
key: app-db-user
|
||||||
|
- name: SPARKY_FITNESS_APP_DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-app
|
||||||
|
key: app-db-password
|
||||||
|
# ---- Crypto secrets (SET ONCE, NEVER CHANGE) ----
|
||||||
|
- name: SPARKY_FITNESS_API_ENCRYPTION_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-app
|
||||||
|
key: api-encryption-key
|
||||||
|
- name: BETTER_AUTH_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-app
|
||||||
|
key: better-auth-secret
|
||||||
|
# ---- App config ----
|
||||||
|
- name: NODE_ENV
|
||||||
|
value: "production"
|
||||||
|
- name: TZ
|
||||||
|
value: "Europe/Budapest"
|
||||||
|
- name: SPARKY_FITNESS_LOG_LEVEL
|
||||||
|
value: "INFO"
|
||||||
|
- name: SPARKY_FITNESS_FRONTEND_URL
|
||||||
|
value: "https://workout.dooplex.hu"
|
||||||
|
- name: SPARKY_FITNESS_DISABLE_SIGNUP
|
||||||
|
value: "true"
|
||||||
|
- name: SPARKY_FITNESS_ADMIN_EMAIL
|
||||||
|
value: "nagyfenyvesi.viktor@gmail.com"
|
||||||
|
- name: ALLOW_PRIVATE_NETWORK_CORS
|
||||||
|
value: "true"
|
||||||
|
- name: SPARKY_FITNESS_EXTRA_TRUSTED_ORIGINS
|
||||||
|
value: "https://workout.home"
|
||||||
|
# ---- Fail-safe: keep email/password login working during bring-up
|
||||||
|
# so a misconfigured OIDC can't lock you out. REMOVE this (and
|
||||||
|
# optionally set SPARKY_FITNESS_DISABLE_EMAIL_LOGIN=true) once the
|
||||||
|
# Authentik OIDC login is confirmed working end-to-end.
|
||||||
|
- name: SPARKY_FITNESS_FORCE_EMAIL_LOGIN
|
||||||
|
value: "true"
|
||||||
|
# ---- OIDC (Authentik) — env-based provider upsert ----
|
||||||
|
- name: SPARKY_FITNESS_OIDC_AUTH_ENABLED
|
||||||
|
value: "true"
|
||||||
|
- name: SPARKY_FITNESS_OIDC_ISSUER_URL
|
||||||
|
value: "https://authentik.dooplex.hu/application/o/sparkyfitness/"
|
||||||
|
- name: SPARKY_FITNESS_OIDC_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-oauth
|
||||||
|
key: client-id
|
||||||
|
- name: SPARKY_FITNESS_OIDC_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: sparky-oauth
|
||||||
|
key: client-secret
|
||||||
|
- name: SPARKY_FITNESS_OIDC_PROVIDER_SLUG
|
||||||
|
value: "authentik"
|
||||||
|
- name: SPARKY_FITNESS_OIDC_PROVIDER_NAME
|
||||||
|
value: "Authentik"
|
||||||
|
- name: SPARKY_FITNESS_OIDC_SCOPE
|
||||||
|
value: "openid profile email"
|
||||||
|
- name: SPARKY_FITNESS_OIDC_AUTO_REGISTER
|
||||||
|
value: "true"
|
||||||
|
ports:
|
||||||
|
- containerPort: 3010
|
||||||
|
name: http
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1Gi
|
||||||
|
volumeMounts:
|
||||||
|
- name: uploads
|
||||||
|
mountPath: /app/SparkyFitnessServer/uploads
|
||||||
|
# First boot runs DB migrations; startupProbe gives it room before
|
||||||
|
# liveness/readiness kick in.
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 30
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 10
|
||||||
|
failureThreshold: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 10
|
||||||
|
volumes:
|
||||||
|
- name: uploads
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: sparkyfitness-uploads
|
||||||
|
---
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Frontend: nginx serving the SPA. Its internal nginx proxies /api, /uploads,
|
||||||
|
# etc. to the server, so the ingress only needs to target this one Service.
|
||||||
|
# Root image listens on :80 (listen 80; hardcoded) — NGINX_LISTEN_PORT pinned.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: sparkyfitness-frontend
|
||||||
|
namespace: workout-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: frontend
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: frontend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: frontend
|
||||||
|
annotations:
|
||||||
|
match-regex.version-checker.io/frontend: '^v\d+\.\d+\.\d+\.\d+$'
|
||||||
|
spec:
|
||||||
|
enableServiceLinks: false
|
||||||
|
containers:
|
||||||
|
- name: frontend
|
||||||
|
image: codewithcj/sparkyfitness:v0.16.6.3
|
||||||
|
env:
|
||||||
|
- name: SPARKY_FITNESS_SERVER_HOST
|
||||||
|
value: "sparkyfitness-server"
|
||||||
|
- name: SPARKY_FITNESS_SERVER_PORT
|
||||||
|
value: "3010"
|
||||||
|
- name: SPARKY_FITNESS_FRONTEND_URL
|
||||||
|
value: "https://workout.dooplex.hu"
|
||||||
|
- name: NGINX_LISTEN_PORT
|
||||||
|
value: "80"
|
||||||
|
- name: TZ
|
||||||
|
value: "Europe/Budapest"
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
name: http
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 256Mi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 10
|
||||||
|
failureThreshold: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 10
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: sparkyfitness-db
|
||||||
|
namespace: workout-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: postgres
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
port: 5432
|
||||||
|
targetPort: postgres
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: postgres
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: sparkyfitness-server
|
||||||
|
namespace: workout-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: server
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 3010
|
||||||
|
targetPort: http
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: server
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: sparkyfitness-frontend
|
||||||
|
namespace: workout-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: frontend
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: http
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: frontend
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: sparkyfitness-postgres
|
||||||
|
namespace: workout-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: postgres
|
||||||
|
recurring-job-group.longhorn.io/needbackup: enabled
|
||||||
|
recurring-job.longhorn.io/source: enabled
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
storageClassName: longhorn
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: sparkyfitness-uploads
|
||||||
|
namespace: workout-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: server
|
||||||
|
recurring-job-group.longhorn.io/needbackup: enabled
|
||||||
|
recurring-job.longhorn.io/source: enabled
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
storageClassName: longhorn
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: sparkyfitness
|
||||||
|
namespace: workout-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sparkyfitness
|
||||||
|
app.kubernetes.io/name: frontend
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: workout.dooplex.hu,workout.home
|
||||||
|
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
|
||||||
|
# Auth is handled IN-APP (native OIDC) — no forward-auth annotations here.
|
||||||
|
# Hungary-only geo-block (same pattern as the rest of the DooPlex apps).
|
||||||
|
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||||
|
set $geo_allowed 0;
|
||||||
|
if ($remote_addr ~ "^192\.168\.") { set $geo_allowed 1; }
|
||||||
|
if ($remote_addr ~ "^10\.") { set $geo_allowed 1; }
|
||||||
|
if ($geoip2_country_code = "HU") { set $geo_allowed 1; }
|
||||||
|
if ($geo_allowed = 0) {
|
||||||
|
return 403 "Access restricted to Hungary";
|
||||||
|
}
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx-internal
|
||||||
|
rules:
|
||||||
|
- host: workout.dooplex.hu
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: sparkyfitness-frontend
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
- host: workout.home
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: sparkyfitness-frontend
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- workout.dooplex.hu
|
||||||
|
secretName: sparkyfitness-tls
|
||||||
+19
-114
@@ -1,3 +1,13 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# *** PARKED 2026-05-27 *** — wger has been REPLACED by SparkyFitness.
|
||||||
|
# SparkyFitness now owns workout.dooplex.hu / workout.home (see sparkyfitness.yaml).
|
||||||
|
# All wger Deployments are scaled to 0 and both wger Ingresses were removed
|
||||||
|
# (ArgoCD prune deletes them, freeing the hostnames). The wger Services,
|
||||||
|
# ConfigMap, PVCs (wger-media / wger-static) and the wger DB in the shared CNPG
|
||||||
|
# cluster are KEPT, untouched, for rollback.
|
||||||
|
# To revive wger: restore the two Ingress resources from git history and scale
|
||||||
|
# the wger / wger-redis / wger-celery-* Deployments back to 1.
|
||||||
|
# ============================================================================
|
||||||
# wger - Workout Manager
|
# wger - Workout Manager
|
||||||
# https://github.com/wger-project/wger
|
# https://github.com/wger-project/wger
|
||||||
# Version: 2.5 (official image, no custom fork)
|
# Version: 2.5 (official image, no custom fork)
|
||||||
@@ -40,7 +50,7 @@ metadata:
|
|||||||
app.kubernetes.io/instance: wger
|
app.kubernetes.io/instance: wger
|
||||||
app.kubernetes.io/name: wger-redis
|
app.kubernetes.io/name: wger-redis
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 0 # parked 2026-05-27 (replaced by SparkyFitness)
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/instance: wger
|
app.kubernetes.io/instance: wger
|
||||||
@@ -78,7 +88,7 @@ metadata:
|
|||||||
extensions.v1alpha1.version-checker.io/wger: "true"
|
extensions.v1alpha1.version-checker.io/wger: "true"
|
||||||
extensions.v1alpha1.version-checker.io/wger.match-regex: "^\\d+\\.\\d+$"
|
extensions.v1alpha1.version-checker.io/wger.match-regex: "^\\d+\\.\\d+$"
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 0 # parked 2026-05-27 (replaced by SparkyFitness)
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/instance: wger
|
app.kubernetes.io/instance: wger
|
||||||
@@ -256,7 +266,7 @@ metadata:
|
|||||||
app.kubernetes.io/instance: wger
|
app.kubernetes.io/instance: wger
|
||||||
app.kubernetes.io/name: wger-celery-worker
|
app.kubernetes.io/name: wger-celery-worker
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 0 # parked 2026-05-27 (replaced by SparkyFitness)
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/instance: wger
|
app.kubernetes.io/instance: wger
|
||||||
@@ -336,7 +346,7 @@ metadata:
|
|||||||
app.kubernetes.io/instance: wger
|
app.kubernetes.io/instance: wger
|
||||||
app.kubernetes.io/name: wger-celery-beat
|
app.kubernetes.io/name: wger-celery-beat
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 0 # parked 2026-05-27 (replaced by SparkyFitness)
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/instance: wger
|
app.kubernetes.io/instance: wger
|
||||||
@@ -439,117 +449,12 @@ spec:
|
|||||||
app.kubernetes.io/name: wger
|
app.kubernetes.io/name: wger
|
||||||
---
|
---
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Ingress #1: web UI paths (/) - Authentik forward-auth protected
|
# wger Ingresses (wger + wger-api) REMOVED 2026-05-27 — see PARKED note at top.
|
||||||
|
# SparkyFitness's ingress (sparkyfitness.yaml) now serves workout.dooplex.hu /
|
||||||
|
# workout.home. ArgoCD prune deletes the old Ingress objects from the cluster,
|
||||||
|
# releasing the hostnames + the wger-tls certificate's hosts.
|
||||||
|
# To revive wger: restore these two Ingress resources from git history.
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: wger
|
|
||||||
namespace: workout-system
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/instance: wger
|
|
||||||
app.kubernetes.io/name: wger
|
|
||||||
annotations:
|
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
||||||
external-dns.alpha.kubernetes.io/hostname: workout.dooplex.hu,workout.home
|
|
||||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
|
|
||||||
# Authentik Forward Auth (domain mode) - same pattern as your other SSO apps
|
|
||||||
# If you use an internal outpost service URL elsewhere, swap auth-url for it.
|
|
||||||
nginx.ingress.kubernetes.io/auth-url: http://ak-outpost-kisfenyo-outpost.auth-system.svc.cluster.local:9000/outpost.goauthentik.io/auth/nginx
|
|
||||||
nginx.ingress.kubernetes.io/auth-signin: https://workout.dooplex.hu/outpost.goauthentik.io/start?rd=$escaped_request_uri
|
|
||||||
nginx.ingress.kubernetes.io/auth-response-headers: "Set-Cookie,X-Authentik-Username,X-Authentik-Email,X-Authentik-Name,X-Authentik-Groups,X-Authentik-Uid"
|
|
||||||
nginx.ingress.kubernetes.io/auth-snippet: |
|
|
||||||
proxy_set_header X-Forwarded-Host $http_host;
|
|
||||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
|
||||||
set $geo_allowed 0;
|
|
||||||
if ($remote_addr ~ "^192\.168\.") { set $geo_allowed 1; }
|
|
||||||
if ($remote_addr ~ "^10\.") { set $geo_allowed 1; }
|
|
||||||
if ($geoip2_country_code = "HU") { set $geo_allowed 1; }
|
|
||||||
if ($geo_allowed = 0) {
|
|
||||||
return 403 "Access restricted to Hungary";
|
|
||||||
}
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx-internal
|
|
||||||
rules:
|
|
||||||
- host: workout.dooplex.hu
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: wger
|
|
||||||
port:
|
|
||||||
number: 80
|
|
||||||
- host: workout.home
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: wger
|
|
||||||
port:
|
|
||||||
number: 80
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- workout.dooplex.hu
|
|
||||||
secretName: wger-tls
|
|
||||||
---
|
|
||||||
# ============================================================================
|
|
||||||
# Ingress #2: API paths (/api/) - NO forward-auth, JWT token auth only
|
|
||||||
# Required so the wger Flutter mobile app can hit /api/v2/token for login.
|
|
||||||
# More-specific path match means /api/* hits this Ingress, not the / one.
|
|
||||||
# ============================================================================
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: wger-api
|
|
||||||
namespace: workout-system
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/instance: wger
|
|
||||||
app.kubernetes.io/name: wger-api
|
|
||||||
annotations:
|
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
||||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
|
||||||
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
|
|
||||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
|
||||||
# Same geo-block as the web UI ingress
|
|
||||||
set $geo_allowed 0;
|
|
||||||
if ($remote_addr ~ "^192\.168\.") { set $geo_allowed 1; }
|
|
||||||
if ($remote_addr ~ "^10\.") { set $geo_allowed 1; }
|
|
||||||
if ($geoip2_country_code = "HU") { set $geo_allowed 1; }
|
|
||||||
if ($geo_allowed = 0) {
|
|
||||||
return 403 "Access restricted to Hungary";
|
|
||||||
}
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx-internal
|
|
||||||
rules:
|
|
||||||
- host: workout.dooplex.hu
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /api
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: wger
|
|
||||||
port:
|
|
||||||
number: 80
|
|
||||||
- host: workout.home
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /api
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: wger
|
|
||||||
port:
|
|
||||||
number: 80
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- workout.dooplex.hu
|
|
||||||
secretName: wger-tls
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
|
|||||||
Reference in New Issue
Block a user