fix(pretix): increase memory limit to 6Gi; eventyay nginx sidecar; crowdsec middleware

pretix/standalone runs gunicorn + celery + celery-beat in one container
and OOMKilled at 4Gi. Increased limit to 6Gi, request to 512Mi.

eventyay: add nginx sidecar to serve static files, update health probes
to check a static asset at port 8080, add create-superuser script,
register script in manifest.

crowdsec: middleware fix (previously uncommitted).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 04:20:40 +00:00
parent 74570413fc
commit d9f10716b0
9 changed files with 141 additions and 18 deletions

View File

@@ -48,7 +48,6 @@ spec:
browserXssFilter: true browserXssFilter: true
contentTypeNosniff: true contentTypeNosniff: true
forceSTSHeader: true forceSTSHeader: true
frameDeny: true
sslRedirect: true sslRedirect: true
stsIncludeSubdomains: true stsIncludeSubdomains: true
stsPreload: true stsPreload: true
@@ -72,6 +71,7 @@ spec:
X-Forwarded-Proto: https X-Forwarded-Proto: https
customResponseHeaders: customResponseHeaders:
Server: "" Server: ""
X-Frame-Options: SAMEORIGIN
X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
--- ---
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1

View File

@@ -27,7 +27,7 @@ Key settings in `config.yaml`:
2. Create the superuser account: 2. Create the superuser account:
```bash ```bash
kubectl exec -n eventyay deploy/eventyay -- python manage.py createsuperuser EMAIL=you@example.com scripts/create-superuser.sh
``` ```
3. Log in at `/orga/login/` with the credentials you just created. 3. Log in at `/orga/login/` with the credentials you just created.

View File

@@ -122,26 +122,48 @@ spec:
mountPath: /home/app/.gunicorn mountPath: /home/app/.gunicorn
livenessProbe: livenessProbe:
httpGet: httpGet:
path: / path: /static/pretixbase/img/eventyay-icon.svg
port: 8000 port: 8080
httpHeaders:
- name: Host
value: "{{ .domain }}"
initialDelaySeconds: 120 initialDelaySeconds: 120
timeoutSeconds: 10 timeoutSeconds: 10
periodSeconds: 30 periodSeconds: 30
failureThreshold: 6 failureThreshold: 6
readinessProbe: readinessProbe:
httpGet: httpGet:
path: / path: /static/pretixbase/img/eventyay-icon.svg
port: 8000 port: 8080
httpHeaders:
- name: Host
value: "{{ .domain }}"
initialDelaySeconds: 60 initialDelaySeconds: 60
timeoutSeconds: 5 timeoutSeconds: 5
periodSeconds: 15 periodSeconds: 15
failureThreshold: 3 failureThreshold: 3
- name: nginx
image: nginxinc/nginx-unprivileged:1.27-alpine
ports:
- name: nginx-http
containerPort: 8080
protocol: TCP
volumeMounts:
- name: eventyay-static
mountPath: /static
readOnly: true
- name: nginx-config
mountPath: /etc/nginx/conf.d
readOnly: true
resources:
limits:
cpu: 200m
memory: 128Mi
requests:
cpu: 10m
memory: 32Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
readOnlyRootFilesystem: false
volumes: volumes:
- name: eventyay-data - name: eventyay-data
persistentVolumeClaim: persistentVolumeClaim:
@@ -150,6 +172,9 @@ spec:
emptyDir: {} emptyDir: {}
- name: eventyay-gunicorn - name: eventyay-gunicorn
emptyDir: {} emptyDir: {}
- name: nginx-config
configMap:
name: eventyay-nginx
restartPolicy: Always restartPolicy: Always
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
@@ -237,9 +262,9 @@ spec:
limits: limits:
cpu: "2" cpu: "2"
ephemeral-storage: 1Gi ephemeral-storage: 1Gi
memory: 1Gi memory: 4Gi
requests: requests:
cpu: 50m cpu: 50m
ephemeral-storage: 50Mi ephemeral-storage: 50Mi
memory: 512Mi memory: 2Gi
restartPolicy: Always restartPolicy: Always

View File

@@ -10,6 +10,7 @@ labels:
resources: resources:
- namespace.yaml - namespace.yaml
- pvc.yaml - pvc.yaml
- nginx-configmap.yaml
- deployment.yaml - deployment.yaml
- service.yaml - service.yaml
- ingress.yaml - ingress.yaml

View File

@@ -1,4 +1,4 @@
version: main-2 version: main-5
requires: requires:
- name: postgres - name: postgres
- name: redis - name: redis
@@ -23,6 +23,16 @@ defaultConfig:
port: '{{ .apps.smtp.port }}' port: '{{ .apps.smtp.port }}'
from: '{{ .apps.smtp.from }}' from: '{{ .apps.smtp.from }}'
user: '{{ .apps.smtp.user }}' user: '{{ .apps.smtp.user }}'
scripts:
- name: create-superuser
path: scripts/create-superuser.sh
description: "Create an Eventyay superuser account for first-time setup."
params:
- name: EMAIL
description: Email address for the superuser account
required: true
- name: PASSWORD
description: Password (leave blank to generate a random one)
defaultSecrets: defaultSecrets:
- key: dbPassword - key: dbPassword
- key: djangoSecret - key: djangoSecret

View File

@@ -0,0 +1,31 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: eventyay-nginx
namespace: {{ .namespace }}
data:
nginx.conf: |
server {
listen 8080;
server_name _;
client_max_body_size 100m;
location /static/ {
alias /static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
location /media/ {
alias /media/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_read_timeout 120s;
}
}

View File

@@ -0,0 +1,56 @@
#!/bin/bash
# Create an Eventyay superuser (organizer admin account).
#
# Required for first-time setup — the web UI cannot be accessed until
# at least one superuser exists.
#
# Runs on the worker pod because the web pod's memory limit is too tight
# to run an additional Django process alongside gunicorn workers.
set -e
set -o pipefail
if [ -z "${KUBECONFIG}" ] || [ -z "${WILD_INSTANCE}" ] || [ -z "${WILD_API_DATA_DIR}" ]; then
echo "ERROR: KUBECONFIG, WILD_INSTANCE, and WILD_API_DATA_DIR must be set"
exit 1
fi
if [ -z "${EMAIL}" ]; then
echo "ERROR: EMAIL is required"
exit 1
fi
CONFIG_FILE="${WILD_API_DATA_DIR}/instances/${WILD_INSTANCE}/config.yaml"
NAMESPACE="$(yq '.apps.eventyay.namespace' "${CONFIG_FILE}" | tr -d '"')"
NAMESPACE="${NAMESPACE:-eventyay}"
# Run on the worker pod — same image as web, but with a higher memory limit
# which is needed to run manage.py alongside the existing gunicorn workers.
POD="$(kubectl get pods -n "${NAMESPACE}" -l component=worker --field-selector=status.phase=Running -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)"
if [ -z "${POD}" ]; then
echo "ERROR: No running Eventyay worker pod found in namespace ${NAMESPACE}"
exit 1
fi
if [ -z "${PASSWORD}" ]; then
PASSWORD="$(openssl rand -base64 24 | tr -d '/+=' | head -c 24)"
fi
echo "Creating superuser '${EMAIL}'..."
kubectl exec -n "${NAMESPACE}" "${POD}" -- \
python manage.py shell -c "
from django.contrib.auth import get_user_model
User = get_user_model()
if User.objects.filter(email='${EMAIL}').exists():
raise SystemExit('ERROR: User ${EMAIL} already exists')
User.objects.create_superuser(email='${EMAIL}', password='${PASSWORD}')
"
echo ""
echo "=== Superuser created ==="
echo "Email: ${EMAIL}"
echo "Password: ${PASSWORD}"
echo ""
echo "Log in at /orga/login/ with these credentials."
echo "Save this password — it will not be shown again."

View File

@@ -9,5 +9,5 @@ spec:
ports: ports:
- name: http - name: http
port: 80 port: 80
targetPort: 8000 targetPort: 8080
protocol: TCP protocol: TCP

View File

@@ -78,11 +78,11 @@ spec:
limits: limits:
cpu: "2" cpu: "2"
ephemeral-storage: 1Gi ephemeral-storage: 1Gi
memory: 4Gi memory: 6Gi
requests: requests:
cpu: 50m cpu: 50m
ephemeral-storage: 50Mi ephemeral-storage: 50Mi
memory: 256Mi memory: 512Mi
volumeMounts: volumeMounts:
- name: pretix-data - name: pretix-data
mountPath: /data mountPath: /data