How to Self-Host Pretix with Docker Compose
What Is Pretix?
Pretix is an open-source event ticketing platform built with Python and Django. It handles ticket sales, seating charts, check-in management, and payment processing for events of any size — from local meetups to multi-day conferences. It replaces Eventbrite, Tito, and similar SaaS ticketing platforms, giving you full control over your ticket sales, attendee data, and branding without per-ticket fees.
Updated February 2026: Verified with latest Docker images and configurations.
The project is maintained by rami.io GmbH and has been in active development since 2014.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 2 GB of free RAM (minimum)
- 10 GB of free disk space
- A domain name with SSL (required for payment processing)
- SMTP credentials for sending email (ticket confirmations, order receipts)
Docker Compose Configuration
Create a project directory:
mkdir -p /opt/pretix && cd /opt/pretix
Create a pretix.cfg configuration file:
[pretix]
instance_name=My Pretix
url=https://tickets.yourdomain.com
currency=USD
; Timezone for event displays
timezone=America/New_York
; Default language
locale=en
; Set to true after initial setup
registration=on
; Data directory inside the container
datadir=/data
[django]
; Generate a strong random secret — use: python3 -c "import secrets; print(secrets.token_urlsafe(50))"
secret=CHANGE_THIS_TO_A_RANDOM_STRING_AT_LEAST_50_CHARACTERS
[database]
backend=postgresql
name=pretix
user=pretix
password=CHANGE_THIS_STRONG_DB_PASSWORD
host=postgres
port=5432
[redis]
location=redis://redis:6379/0
; Use Redis for session storage (faster than database)
sessions=true
[celery]
broker=redis://redis:6379/1
backend=redis://redis:6379/2
[mail]
; SMTP settings for sending tickets and order confirmations
from[email protected]
host=smtp.yourdomain.com
port=587
user=your-smtp-user
password=your-smtp-password
tls=on
; ssl=off
Create a docker-compose.yml file:
services:
postgres:
image: postgres:16.6-alpine
restart: unless-stopped
environment:
POSTGRES_DB: pretix
POSTGRES_USER: pretix
POSTGRES_PASSWORD: CHANGE_THIS_STRONG_DB_PASSWORD # Must match pretix.cfg
volumes:
- pretix-db:/var/lib/postgresql/data
networks:
- pretix-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U pretix"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7.4-alpine
restart: unless-stopped
volumes:
- pretix-redis:/data
networks:
- pretix-net
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
pretix:
image: pretix/pretix:2026.2.0
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
ports:
- "127.0.0.1:8345:80" # Bind to localhost — use reverse proxy for public access
volumes:
- ./pretix.cfg:/etc/pretix/pretix.cfg:ro # Configuration file
- pretix-data:/data # Media uploads, logs, cache
environment:
AUTOMIGRATE: "yes" # Run database migrations on startup
networks:
- pretix-net
volumes:
pretix-db:
pretix-redis:
pretix-data:
networks:
pretix-net:
Create a .env file alongside:
# No additional env vars needed — all config is in pretix.cfg
# The database password must match between docker-compose.yml and pretix.cfg
Start the stack:
docker compose up -d
Wait about 60 seconds for database migrations to complete on first start. Check progress:
docker compose logs -f pretix
Look for Booting worker messages indicating the web and task workers are ready.
Initial Setup
- Navigate to
https://tickets.yourdomain.com(orhttp://localhost:8345if not using a reverse proxy yet) - Create your admin account at the registration page
- After creating your account, edit
pretix.cfgand setregistration=offto prevent public signups - Restart the container:
docker compose restart pretix
Creating Your First Event
- Log into the admin panel
- Click “Create a new organizer” — this is your organization/brand
- Under your organizer, click “Create a new event”
- Configure:
- Event name, dates, and timezone
- Currency and tax settings
- Ticket categories and pricing
- Payment methods (Stripe, PayPal, bank transfer, manual)
- Go to the “Shop” section to customize your ticket page design
- Enable the event when ready to sell
Configuration
Key Configuration Options
| Section | Key | Purpose | Default |
|---|---|---|---|
[pretix] | url | Public URL of your instance | Required |
[pretix] | currency | Default currency | EUR |
[pretix] | registration | Allow new account creation | on |
[pretix] | timezone | Server timezone | UTC |
[django] | secret | Cryptographic secret key | Required |
[database] | backend | Database type | sqlite3 |
[mail] | from | Sender address for emails | pretix@localhost |
[mail] | host | SMTP server hostname | localhost |
[mail] | tls | Use STARTTLS | off |
Payment Providers
Pretix supports multiple payment providers as plugins:
| Provider | Plugin | Cost |
|---|---|---|
| Stripe | Built-in | 2.9% + $0.30 |
| PayPal | Built-in | 2.99% + fixed fee |
| Bank transfer | Built-in | Free |
| Manual payment | Built-in | Free |
| Mollie | Community plugin | Varies |
| Square | Community plugin | 2.6% + $0.10 |
Configure payment providers per-event under Settings → Payment.
Email Configuration
Pretix sends emails for order confirmations, ticket delivery, and event updates. SMTP is required for production use.
Test your email configuration:
docker compose exec pretix python -m pretix runserver --check-email
If using Gmail SMTP:
- Host:
smtp.gmail.com - Port:
587 - TLS:
on - Use an App Password (not your regular password)
Plugins
Pretix has a plugin system. Common plugins include:
- pretix-pages — add custom content pages to your ticket shop
- pretix-venueless — virtual event platform integration
- pretix-passbook — Apple Wallet ticket delivery
- pretix-covid-certificates — COVID certificate validation (legacy)
Install plugins by adding them to the Docker image or using pip inside the container.
Reverse Proxy
Pretix requires HTTPS for payment processing. Configure your reverse proxy to forward traffic to port 8345.
Nginx Proxy Manager:
- Forward hostname:
pretix - Forward port:
80(internal container port, or8345from host) - Enable SSL with Let’s Encrypt
- Set “Websockets Support” to on
Caddy configuration:
tickets.yourdomain.com {
reverse_proxy localhost:8345
}
Nginx manual configuration:
server {
listen 443 ssl http2;
server_name tickets.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:8345;
proxy_set_header Host $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 $scheme;
}
}
See Reverse Proxy Setup for detailed instructions.
Backup
What to Back Up
| Data | Location | Importance |
|---|---|---|
| PostgreSQL database | pretix-db volume | Critical — all orders, attendees, event data |
| Media uploads | pretix-data volume (/data/media/) | Important — ticket designs, event images |
| Configuration | ./pretix.cfg | Important — contains secrets and settings |
| Redis data | pretix-redis volume | Low — cache and sessions, regenerated automatically |
Database Backup
docker compose exec postgres pg_dump -U pretix pretix > pretix-backup-$(date +%Y%m%d).sql
Full Volume Backup
docker compose stop pretix
tar czf pretix-data-$(date +%Y%m%d).tar.gz -C /var/lib/docker/volumes/ pretix-data
docker compose start pretix
See Backup Strategy for automated backup approaches.
Troubleshooting
Pretix Won’t Start — Migration Errors
Symptom: Container logs show django.db.utils.OperationalError or migration failures.
Fix:
docker compose exec pretix python -m pretix migrate
docker compose restart pretix
Emails Not Sending
Symptom: Orders complete but no confirmation emails arrive.
Fix:
- Verify SMTP credentials in
pretix.cfg - Check the Celery worker is running:
docker compose logs pretix | grep "celery" - Verify the Redis connection — Celery uses Redis as its message broker
- Check your SMTP provider’s sending limits
Static Files Missing (404 on CSS/JS)
Symptom: Pretix loads but looks unstyled — CSS and JavaScript return 404.
Fix:
docker compose exec pretix python -m pretix updateassets
docker compose restart pretix
Slow Performance Under Load
Symptom: Pages load slowly during high-traffic ticket sales.
Fix: Increase the number of Gunicorn workers:
services:
pretix:
environment:
NUM_WORKERS: "8" # Default is 2x CPU cores
Also consider adding a CDN for static assets and increasing PostgreSQL’s shared_buffers.
Payment Provider Configuration Error
Symptom: “Payment method not available” or payment page errors.
Fix:
- Ensure HTTPS is properly configured — payment providers require SSL
- Check the
urlinpretix.cfgmatches your actual domain - Verify API credentials for your payment provider in the event settings
Resource Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| RAM | 1 GB | 2-4 GB |
| CPU | 1 core | 2+ cores |
| Disk | 5 GB | 10-20 GB (scales with media) |
| Network | Stable connection | Low-latency for ticket sales |
Memory breakdown: PostgreSQL ~128 MB, Redis ~50 MB, Pretix web worker ~256-512 MB, Celery worker ~128-256 MB.
Verdict
Pretix is the best self-hosted ticketing platform available. It handles everything from free community events to paid multi-day conferences with reserved seating. The admin interface is polished, the plugin ecosystem covers common needs, and the check-in app works well for door management.
Choose Pretix if you run events regularly and want to eliminate per-ticket fees from Eventbrite or Tito. A single event selling 200 tickets at $50 each would cost $650+ in Eventbrite fees — your VPS hosting for an entire year costs less than one event’s platform fees.
Skip Pretix if you only run one or two events per year — the setup and maintenance overhead won’t justify the savings.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments