Adds pretix app.

This commit is contained in:
2026-06-19 21:33:23 +00:00
parent cd37c07a33
commit 274d7a8fb9
11 changed files with 382 additions and 0 deletions

5
pretix/app.yaml Normal file
View File

@@ -0,0 +1,5 @@
name: pretix
is: pretix
description: Pretix is an open-source ticket selling platform for events of all sizes, with powerful features for registration, payments, and attendee management.
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/pretix.svg
latest: "2026"

View File

@@ -0,0 +1,42 @@
# Pretix
Pretix is an open-source ticketing system for selling tickets and managing event registrations.
## Dependencies
- **PostgreSQL** - Database for storing events, orders, and attendees
- **Redis** - Used for caching and background task queuing
- **SMTP** - For sending order confirmations and tickets
## Configuration
Key settings in `config.yaml`:
- **domain** - Where Pretix will be accessible
- **storage** - Persistent volume size (default: `2Gi`)
- **currency** - Default currency for ticket prices (default: `EUR`)
- **timezone** - Timezone for event scheduling (default: `UTC`)
- **smtp** - Email settings inherited from your Wild Cloud SMTP service
## First-Time Setup
1. Add and deploy the app:
```bash
wild app add pretix
wild app deploy pretix
```
2. Create the admin user via the management command:
```bash
kubectl exec -n pretix deploy/pretix -- python manage.py createsuperuser
```
3. Log in at `/control/` with the credentials you just created.
4. Create an organizer, then create your first event and configure ticket types and pricing.
## Notes
- The organizer is the top-level entity — events belong to organizers
- Ticket PDFs and QR codes are generated automatically on order completion
- The `/control/` prefix is the admin interface; the public-facing shop is at the root

View File

@@ -0,0 +1,46 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: pretix-config
namespace: {{ .namespace }}
data:
pretix.cfg.tpl: |
[pretix]
instance_name={{ .domain }}
url=https://{{ .domain }}
currency={{ .currency }}
datadir=/data
trust_x_forwarded_for=on
trust_x_forwarded_proto=on
[database]
backend=postgresql
name={{ .db.name }}
user={{ .db.user }}
host={{ .db.host }}
port={{ .db.port }}
password=DB_PASSWORD_PLACEHOLDER
sslmode=disable
[redis]
location=redis://:REDIS_PASSWORD_PLACEHOLDER@{{ .redis.host }}:{{ .redis.port }}/0
sessions=true
[celery]
broker=redis://:REDIS_PASSWORD_PLACEHOLDER@{{ .redis.host }}:{{ .redis.port }}/1
backend=redis://:REDIS_PASSWORD_PLACEHOLDER@{{ .redis.host }}:{{ .redis.port }}/2
[mail]
from={{ .smtp.from }}
host={{ .smtp.host }}
port={{ .smtp.port }}
user={{ .smtp.user }}
password=SMTP_PASSWORD_PLACEHOLDER
tls=on
[locale]
timezone={{ .timezone }}
[django]
debug=false
secret=DJANGO_SECRET_PLACEHOLDER

View File

@@ -0,0 +1,63 @@
apiVersion: batch/v1
kind: Job
metadata:
name: pretix-db-init
labels:
component: db-init
spec:
template:
metadata:
labels:
component: db-init
spec:
restartPolicy: OnFailure
securityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 999
seccompProfile:
type: RuntimeDefault
containers:
- name: db-init
image: postgres:17
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
command: ["/bin/bash", "-c"]
args:
- |
PGPASSWORD=${POSTGRES_ADMIN_PASSWORD} psql -h ${DB_HOSTNAME} -U postgres <<EOF
DO \$\$
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${DB_USER}') THEN
CREATE USER ${DB_USER} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
ELSE
ALTER USER ${DB_USER} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
END IF;
END
\$\$;
SELECT 'CREATE DATABASE ${DB_NAME}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${DB_NAME}')\gexec
ALTER DATABASE ${DB_NAME} OWNER TO ${DB_USER};
GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};
EOF
env:
- name: POSTGRES_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secrets
key: password
- name: DB_HOSTNAME
value: "{{ .db.host }}"
- name: DB_NAME
value: "{{ .db.name }}"
- name: DB_USER
value: "{{ .db.user }}"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: pretix-secrets
key: dbPassword

View File

@@ -0,0 +1,122 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: pretix
namespace: {{ .namespace }}
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
component: web
template:
metadata:
labels:
component: web
spec:
securityContext:
runAsNonRoot: false
runAsUser: 0
seccompProfile:
type: RuntimeDefault
initContainers:
- name: config-init
image: pretix/standalone:2026.5.1
command: ["/bin/sh", "-c"]
args:
- |
sed \
-e "s|DB_PASSWORD_PLACEHOLDER|${DB_PASSWORD}|g" \
-e "s|REDIS_PASSWORD_PLACEHOLDER|${REDIS_PASSWORD}|g" \
-e "s|SMTP_PASSWORD_PLACEHOLDER|${SMTP_PASSWORD}|g" \
-e "s|DJANGO_SECRET_PLACEHOLDER|${DJANGO_SECRET}|g" \
/etc/pretix-base/pretix.cfg.tpl > /etc/pretix/pretix.cfg
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: pretix-secrets
key: dbPassword
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: pretix-secrets
key: redis.password
- name: SMTP_PASSWORD
valueFrom:
secretKeyRef:
name: pretix-secrets
key: smtpPassword
- name: DJANGO_SECRET
valueFrom:
secretKeyRef:
name: pretix-secrets
key: djangoSecret
volumeMounts:
- name: pretix-config-base
mountPath: /etc/pretix-base
- name: pretix-config
mountPath: /etc/pretix
containers:
- name: pretix
image: pretix/standalone:2026.5.1
ports:
- name: http
containerPort: 80
protocol: TCP
securityContext:
allowPrivilegeEscalation: true
readOnlyRootFilesystem: false
resources:
limits:
cpu: "2"
ephemeral-storage: 1Gi
memory: 4Gi
requests:
cpu: 50m
ephemeral-storage: 50Mi
memory: 256Mi
volumeMounts:
- name: pretix-data
mountPath: /data
- name: pretix-config
mountPath: /etc/pretix
livenessProbe:
httpGet:
path: /healthcheck/
port: 80
httpHeaders:
- name: Host
value: "{{ .domain }}"
initialDelaySeconds: 120
timeoutSeconds: 10
periodSeconds: 30
failureThreshold: 6
readinessProbe:
httpGet:
path: /healthcheck/
port: 80
httpHeaders:
- name: Host
value: "{{ .domain }}"
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 15
failureThreshold: 3
volumes:
- name: pretix-data
persistentVolumeClaim:
claimName: pretix-data
- name: pretix-config-base
configMap:
name: pretix-config
- name: pretix-config
emptyDir: {}
restartPolicy: Always

View File

@@ -0,0 +1,26 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pretix
namespace: {{ .namespace }}
annotations:
external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }}
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
external-dns.alpha.kubernetes.io/ttl: "60"
spec:
ingressClassName: traefik
rules:
- host: {{ .domain }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: pretix
port:
number: 80
tls:
- hosts:
- {{ .domain }}
secretName: {{ .tlsSecretName }}

View File

@@ -0,0 +1,17 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: {{ .namespace }}
labels:
- includeSelectors: true
pairs:
app: pretix
managedBy: kustomize
partOf: wild-cloud
resources:
- namespace.yaml
- configmap.yaml
- pvc.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
- db-init-job.yaml

View File

@@ -0,0 +1,33 @@
version: 2026.5.1-1
requires:
- name: postgres
- name: redis
- name: smtp
defaultConfig:
namespace: pretix
externalDnsDomain: '{{ .cloud.domain }}'
domain: pretix.{{ .cloud.domain }}
tlsSecretName: wildcard-wild-cloud-tls
storage: 2Gi
currency: EUR
timezone: UTC
db:
host: '{{ .apps.postgres.host }}'
port: '{{ .apps.postgres.port }}'
name: pretix
user: pretix
redis:
host: '{{ .apps.redis.host }}'
port: '6379'
smtp:
host: '{{ .apps.smtp.host }}'
port: '{{ .apps.smtp.port }}'
from: '{{ .apps.smtp.from }}'
user: '{{ .apps.smtp.user }}'
defaultSecrets:
- key: dbPassword
- key: djangoSecret
- key: smtpPassword
requiredSecrets:
- postgres.password
- redis.password

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .namespace }}

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pretix-data
namespace: {{ .namespace }}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .storage }}

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: pretix
namespace: {{ .namespace }}
spec:
selector:
component: web
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP