diff --git a/.env.build.example b/.env.build.example
new file mode 100644
index 0000000..eca18b9
--- /dev/null
+++ b/.env.build.example
@@ -0,0 +1,101 @@
+PRETALX_VERSION=2024.1.0
+
+# Base image
+BASE_IMAGE=docker.io/library/python
+BASE_TAG=3.12-bookworm
+
+PRETALX_BASE_IMAGE=docker.io/pretalx/base
+PRETALX_BASE_TAG=${BASE_TAG}
+
+##
+#
+# Builds from packaged release versions
+#
+##
+
+# Pretalx stock image name and tag
+PRETALX_IMAGE=docker.io/pretalx/pretalx
+PRETALX_TAG=${PRETALX_VERSION}
+
+# Default image
+PRETALX_DEFAULT_BASE_IMAGE=${PRETALX_BASE_IMAGE}
+PRETALX_DEFAULT_BASE_TAG=${PRETALX_BASE_TAG}
+
+
+# Extended image with plugins
+PRETALX_EXTENDED_BASE_IMAGE=${PRETALX_IMAGE}
+PRETALX_EXTENDED_BASE_TAG=${PRETALX_TAG}
+
+PRETALX_EXTENDED_IMAGE=${PRETALX_IMAGE}-extended
+PRETALX_EXTENDED_TAG=${PRETALX_TAG}
+
+
+# Extended image and cron
+PRETALX_EXTENDED_CRON_BASE_IMAGE=${PRETALX_EXTENDED_IMAGE}
+PRETALX_EXTENDED_CRON_BASE_TAG=${PRETALX_EXTENDED_TAG}
+
+PRETALX_EXTENDED_CRON_IMAGE=${PRETALX_EXTENDED_IMAGE}
+PRETALX_EXTENDED_CRON_TAG=${PRETALX_EXTENDED_TAG}-cron
+
+
+##
+#
+# Builds from packaged release versions for standalone usage
+#
+##
+
+
+# Standalone image
+PRETALX_STANDALONE_BASE_IMAGE=${PRETALX_IMAGE}
+PRETALX_STANDALONE_BASE_TAG=${PRETALX_TAG}
+
+PRETALX_STANDALONE_IMAGE=docker.io/pretalx/standalone
+PRETALX_STANDALONE_TAG=${PRETALX_VERSION}
+
+
+# Extended standalone image
+PRETALX_STANDALONE_EXTENDED_BASE_IMAGE=${PRETALX_STANDALONE_IMAGE}
+PRETALX_STANDALONE_EXTENDED_BASE_TAG=${PRETALX_STANDALONE_TAG}
+
+PRETALX_STANDALONE_EXTENDED_IMAGE=${PRETALX_STANDALONE_IMAGE}-extended
+PRETALX_STANDALONE_EXTENDED_TAG=${PRETALX_STANDALONE_TAG}
+
+
+# Extended standalone image with cron
+PRETALX_STANDALONE_EXTENDED_CRON_BASE_IMAGE=${PRETALX_STANDALONE_EXTENDED_IMAGE}
+PRETALX_STANDALONE_EXTENDED_CRON_BASE_TAG=${PRETALX_STANDALONE_EXTENDED_TAG}
+
+PRETALX_STANDALONE_EXTENDED_CRON_IMAGE=${PRETALX_STANDALONE_IMAGE}-extended
+PRETALX_STANDALONE_EXTENDED_CRON_TAG=${PRETALX_STANDALONE_EXTENDED_TAG}-cron
+
+
+##
+#
+# Source builds
+#
+##
+
+
+PRETALX_REPO=https://github.com/pretalx/pretalx.git
+PRETALX_REF=main
+
+
+# Extended build from remote source with cron
+PRETALX_SOURCE_EXTENDED_CRON_IMAGE=${PRETALX_EXTENDED_IMAGE}
+PRETALX_SOURCE_EXTENDED_CRON_TAG=${PRETALX_REF}-source-remote-cron
+
+
+# Standalone build, from local or remote source
+PRETALX_SOURCE_STANDALONE_IMAGE=${PRETALX_STANDALONE_IMAGE}
+PRETALX_SOURCE_STANDALONE_TAG=${PRETALX_REF}-source
+
+PRETALX_SOURCE_STANDALONE_LOCAL_TAG=${PRETALX_SOURCE_STANDALONE_TAG}-local
+PRETALX_SOURCE_STANDALONE_REMOTE_TAG=${PRETALX_SOURCE_STANDALONE_TAG}-remote
+
+
+# Standalone extended build from remote source with cron
+PRETALX_SOURCE_STANDALONE_EXTENDED_CRON_BASE_IMAGE=${PRETALX_SOURCE_STANDALONE_IMAGE}
+PRETALX_SOURCE_STANDALONE_EXTENDED_CRON_BASE_TAG=${PRETALX_SOURCE_STANDALONE_REMOTE_TAG}
+
+PRETALX_SOURCE_STANDALONE_EXTENDED_CRON_IMAGE=${PRETALX_SOURCE_STANDALONE_IMAGE}-extended
+PRETALX_SOURCE_STANDALONE_EXTENDED_CRON_TAG=${PRETALX_SOURCE_STANDALONE_REMOTE_TAG}-cron
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..ad65138
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,54 @@
+PRETALX_VERSION=2024.1.0
+
+PRETALX_IMAGE=docker.io/pretalx/pretalx
+PRETALX_TAG=${PRETALX_VERSION}
+
+FQDN=localhost.local
+
+POSTGRES_PASSWORD=veryunsecureplschange
+POSTGRES_USER=pretalx
+POSTGRES_DB=pretalx
+
+PRETALX_LOG_LEVEL=info
+
+PRETALX_DEBUG=False
+PRETALX_SITE_URL=http://localhost:8080
+
+PRETALX_LANGUAGE_CODE=en
+PRETALX_TIME_ZONE=UTC
+
+PRETALX_DATA_DIR=/data
+PRETALX_FILESYSTEM_LOGS=/data/logs
+
+PRETALX_FILESYSTEM_MEDIA=/public/media
+PRETALX_FILESYSTEM_STATIC=/public/static
+
+PRETALX_SITE_CSP=
+PRETALX_SITE_CSP_STYLE=
+PRETALX_SITE_CSP_SCRIPT=
+PRETALX_SITE_CSP_IMG=
+PRETALX_SITE_CSP_FORM=
+
+PRETALX_LOGGING_EMAIL=
+PRETALX_LOGGING_EMAIL_LEVEL=ERROR
+
+#PRETALX_MAIL_FROM=admin@localhost
+#PRETALX_MAIL_HOST=localhost
+#PRETALX_MAIL_PORT=25
+#PRETALX_MAIL_USER=
+#PRETALX_MAIL_PASSWORD=
+#PRETALX_MAIL_TLS=False
+#PRETALX_MAIL_SSL=False
+
+PRETALX_DB_NAME=${POSTGRES_DB}
+PRETALX_DB_USER=${POSTGRES_USER}
+PRETALX_DB_PASS=${POSTGRES_PASSWORD}
+PRETALX_DB_TYPE=postgresql
+PRETALX_DB_HOST=postgres
+PRETALX_DB_PORT=5432
+
+PRETALX_REDIS=redis://redis/0
+PRETALX_REDIS_SESSIONS=true
+
+PRETALX_CELERY_BACKEND=redis://redis/1
+PRETALX_CELERY_BROKER=redis://redis/2
diff --git a/.github/workflows/build-and-push.yml b/.github/workflows/build-and-push.yml
new file mode 100644
index 0000000..990357b
--- /dev/null
+++ b/.github/workflows/build-and-push.yml
@@ -0,0 +1,162 @@
+name: Build/Push OCI image
+
+on:
+ workflow_call:
+ inputs:
+
+ ref:
+ description: "Reference for a git object to check out, string"
+ required: false
+ type: string
+ default: ${{ github.ref }}
+
+
+ platforms:
+ description: "Mandatory comma-separated list of CPU platforms to build for, string"
+ required: false
+ type: string
+ default: linux/amd64,linux/arm64
+ image-name:
+ description: "Mandatory name of the image to build, string"
+ required: true
+ type: string
+ default: ${{ github.event.repository.name }}
+
+
+ build-args:
+ description: "Optional build arguments, takes a YAML multiline string | with ENV=variables"
+ type: string
+ required: false
+ default: ""
+ image-tags:
+ description: "Optional additional image tags, takes a YAML multiline string |"
+ type: string
+ required: false
+ default: ""
+ context:
+ description: "Optional build context, defaults to the ref that triggered the run, and not ./ in the checkout root, string"
+ type: string
+ required: false
+ default: "."
+ file:
+ description: "Optional path to a Dockerfile to build, relative to the build context, string"
+ type: string
+ required: false
+ default: Dockerfile
+
+
+ docker_io:
+ description: "Optional toggle for disabling Docker Hub Registry, boolean"
+ type: boolean
+ required: false
+ default: true
+ ghcr_io:
+ description: "Optional toggle for disabling GitHub Container Registry, boolean"
+ type: boolean
+ required: false
+ default: true
+
+ outputs:
+ imageid:
+ description: "Image ID, String"
+ value: ${{ jobs.build-and-push.outputs.imageid }}
+ digest:
+ description: "Image digest, String"
+ value: ${{ jobs.build-and-push.outputs.digest }}
+ metadata:
+ description: "Build result metadata, JSON"
+ value: ${{ jobs.build-and-push.outputs.metadata }}
+
+
+jobs:
+
+ build-and-push:
+
+ name: Build/Push image
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ id-token: write
+ packages: write
+
+ outputs:
+ imageid: ${{ steps.build-push.outputs.imageid }}
+ digest: ${{ steps.build-push.outputs.digest }}
+ metadata: ${{ steps.build-push.outputs.metadata }}
+
+ env:
+ docker_io: ${{ inputs.docker_io && secrets.DOCKER_USERNAME != null && secrets.DOCKER_PASSWORD != null }}
+
+ steps:
+
+ -
+ name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.ref }}
+
+ -
+ name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ context: git
+ images: |
+ name=ghcr.io/${{ github.repository_owner }}/${{ inputs.image-name }},enable=${{ inputs.ghcr_io }}
+ name=docker.io/${{ github.repository_owner }}/${{ inputs.image-name }},enable=${{ env.docker_io }}
+ labels: |
+ org.opencontainers.image.title=${{ inputs.image-name }}
+ org.opencontainers.image.vendor=Pretalx Community
+ org.opencontainers.image.description=An unprivileged Pretalx container image for use with the PostgreSQL database and prepared to be used with cron.
+ org.opencontainers.image.licenses=CC0
+
+ tags: |
+ type=semver,pattern={{ version }}
+ type=semver,pattern={{ major }}.{{ minor }}
+ type=ref,event=branch
+ type=ref,event=tag
+ type=ref,event=pr
+ {{ sha }}
+ ${{ inputs.image-tags }}
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ -
+ name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+
+ -
+ name: Login to Docker Hub Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && env.docker_io == 'true'
+ with:
+ registry: "docker.io"
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ -
+ name: Login to GitHub Packages Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && inputs.ghcr_io
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+
+
+ -
+ name: Build and push Container image
+ uses: docker/build-push-action@v5
+ id: build-push
+ with:
+ push: "${{ github.event_name != 'pull_request' }}"
+ provenance: false
+ platforms: "${{ inputs.platforms }}"
+ context: "{{ defaultContext }}:${{ inputs.context }}"
+ file: "${{ inputs.file }}"
+ build-args: "${{ inputs.build-args }}"
+ tags: "${{ steps.meta.outputs.tags }}"
+ labels: "${{ steps.meta.outputs.labels }}"
diff --git a/.github/workflows/build.all.yml b/.github/workflows/build.all.yml
new file mode 100644
index 0000000..f409d33
--- /dev/null
+++ b/.github/workflows/build.all.yml
@@ -0,0 +1,824 @@
+name: Build all images
+
+on:
+ workflow_dispatch:
+ inputs:
+
+ ref:
+ description: "Reference for a git object to check out, string"
+ required: false
+ type: string
+
+
+ platforms:
+ description: "Mandatory comma-separated list of CPU platforms to build for, string"
+ required: false
+ type: string
+ default: linux/amd64
+ #default: linux/amd64,linux/arm64
+ image-name:
+ description: "Mandatory name of the image to build, string"
+ required: true
+ type: string
+ default: pretalx
+
+
+ base-image:
+ type: string
+ required: false
+ default: docker.io/library/python
+ base-tag:
+ type: string
+ required: false
+ default: 3.12-bookworm
+
+ image-tags:
+ description: "Optional additional image tags, takes a YAML multiline string |"
+ type: string
+ required: false
+ default: ""
+ file:
+ description: "Optional path to a Dockerfile to build, relative to the build context, string"
+ type: string
+ required: false
+ default: Dockerfile.debian
+
+
+ docker_io:
+ description: "Optional toggle for disabling Docker Hub Registry, boolean"
+ type: boolean
+ required: false
+ default: true
+ ghcr_io:
+ description: "Optional toggle for disabling GitHub Container Registry, boolean"
+ type: boolean
+ required: false
+ default: true
+
+ release:
+ types: [published]
+
+permissions:
+ contents: read
+ id-token: write
+ packages: write
+
+env:
+ docker_io: ${{ secrets.DOCKER_USERNAME != null && secrets.DOCKER_PASSWORD != null }}
+ ghcr_io: true
+
+ platforms: linux/amd64
+ image-name: pretalx
+
+ base-image: docker.io/library/python
+ base-tag: 3.12-bookworm
+
+ image-tags: ""
+ file: Dockerfile.debian
+
+jobs:
+
+ # pretalx/base:*
+ base:
+
+ name: Build base image
+ runs-on: ubuntu-latest
+
+ outputs:
+ imageid: ${{ steps.build-push.outputs.imageid }}
+ digest: ${{ steps.build-push.outputs.digest }}
+ metadata: ${{ steps.build-push.outputs.metadata }}
+
+ steps:
+
+ -
+ name: Checkout repository
+ uses: actions/checkout@v4
+
+
+ -
+ name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ context: git
+ images: |
+ name=ghcr.io/${{ github.repository_owner }}/base,enable=${{ inputs.ghcr_io || env.ghcr_io }}
+ labels: |
+ org.opencontainers.image.title=Pretalx base
+ org.opencontainers.image.vendor=Pretalx Community
+ org.opencontainers.image.description=An unprivileged Pretalx base image
+ org.opencontainers.image.licenses=CC0
+
+ tags: |
+ type=match,pattern=v(.*),group=1
+ type=match,pattern=\d+-\d+-\d+
+ type=ref,event=branch
+ type=ref,event=tag
+ type=ref,event=pr
+ type=sha
+ ${{ inputs.image-tags || env.image-tags }}
+ ${{ inputs.base-tag || env.base-tag }}
+
+ -
+ name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ -
+ name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+
+ -
+ name: Login to GitHub Packages Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( inputs.ghcr_io || env.ghcr_io )
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+
+ -
+ name: Build and push Container image
+ uses: docker/build-push-action@v5
+ id: build-push
+ with:
+ provenance: false
+ push: "${{ github.event_name != 'pull_request' }}"
+ platforms: "${{ inputs.platforms || env.platforms }}"
+ context: "{{ defaultContext }}:./context/base"
+ file: "${{ inputs.file || env.file }}"
+ build-args: |
+ BASE_IMAGE=${{ inputs.base-image || env.base-image }}
+ BASE_TAG=${{ inputs.base-tag || env.base-tag }}
+ tags: "${{ steps.meta.outputs.tags }}"
+ labels: "${{ steps.meta.outputs.labels }}"
+ outputs: "type=docker,dest=/tmp/pretalx-base.tar"
+
+ -
+ name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: pretalx-base
+ path: /tmp/pretalx-base.tar
+
+
+ # pretalx/pretalx:*
+ default:
+
+ name: Build default image
+ needs: base
+ runs-on: ubuntu-latest
+
+ outputs:
+ imageid: ${{ steps.build-push.outputs.imageid }}
+ digest: ${{ steps.build-push.outputs.digest }}
+ metadata: ${{ steps.build-push.outputs.metadata }}
+
+ steps:
+
+ -
+ name: Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: pretalx-base
+ path: /tmp
+ -
+ name: Load image
+ run: |
+ docker load --input /tmp/pretalx-base.tar
+ docker image ls -a
+ IMAGE_REPO=$(docker images --format "{{.Repository}}" | head -n 1)
+ IMAGE_TAG=$(docker images --format "{{.Tag}}" | head -n 1)
+ echo "BASE_IMAGE=${IMAGE_REPO}" >> "$GITHUB_ENV"
+ echo "BASE_TAG=${IMAGE_TAG}" >> "$GITHUB_ENV"
+
+ -
+ name: Checkout repository
+ uses: actions/checkout@v4
+
+
+ -
+ name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ context: git
+ images: |
+ name=ghcr.io/${{ github.repository_owner }}/${{ inputs.image-name || env.image-name }},enable=${{ inputs.ghcr_io || env.ghcr_io }}
+ name=docker.io/${{ github.repository_owner }}/${{ inputs.image-name || env.image-name }},enable=${{ inputs.docker_io || env.docker_io }}
+ labels: |
+ org.opencontainers.image.title=Pretalx
+ org.opencontainers.image.vendor=Pretalx Community
+ org.opencontainers.image.description=An unprivileged Pretalx container image
+ org.opencontainers.image.licenses=CC0
+
+ tags: |
+ type=match,pattern=v(.*),group=1
+ type=match,pattern=\d+-\d+-\d+
+ type=ref,event=branch
+ type=ref,event=tag
+ type=ref,event=pr
+ type=sha
+ ${{ inputs.image-tags || env.image-tags }}
+
+ -
+ name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ -
+ name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+
+ -
+ name: Login to Docker Hub Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( ( inputs.docker_io || env.docker_io ) == 'true' )
+ with:
+ registry: "docker.io"
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ -
+ name: Login to GitHub Packages Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( inputs.ghcr_io || env.ghcr_io )
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+
+ -
+ name: Build and push Container image
+ uses: docker/build-push-action@v5
+ id: build-push
+ with:
+ provenance: false
+ push: "${{ github.event_name != 'pull_request' }}"
+ platforms: "${{ inputs.platforms || env.platforms }}"
+ context: "{{ defaultContext }}:./context/default"
+ file: "${{ inputs.file || env.file }}"
+ build-args: |
+ BASE_IMAGE=${{ env.BASE_IMAGE }}
+ BASE_TAG=${{ env.BASE_TAG }}
+ tags: "${{ steps.meta.outputs.tags }}"
+ labels: "${{ steps.meta.outputs.labels }}"
+ outputs: "type=docker,dest=/tmp/pretalx-default.tar"
+
+ -
+ name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: pretalx-default
+ path: /tmp/pretalx-default.tar
+
+
+ # pretalx/pretalx-extended:*
+ extended:
+
+ name: Build extended image
+ needs: default
+ runs-on: ubuntu-latest
+
+ outputs:
+ imageid: ${{ steps.build-push.outputs.imageid }}
+ digest: ${{ steps.build-push.outputs.digest }}
+ metadata: ${{ steps.build-push.outputs.metadata }}
+
+ steps:
+
+ -
+ name: Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: pretalx-default
+ path: /tmp
+ -
+ name: Load image
+ run: |
+ docker load --input /tmp/pretalx-default.tar
+ docker image ls -a
+ IMAGE_REPO=$(docker images --format "{{.Repository}}" | head -n 1)
+ IMAGE_TAG=$(docker images --format "{{.Tag}}" | head -n 1)
+ echo "BASE_IMAGE=${IMAGE_REPO}" >> "$GITHUB_ENV"
+ echo "BASE_TAG=${IMAGE_TAG}" >> "$GITHUB_ENV"
+
+ -
+ name: Checkout repository
+ uses: actions/checkout@v4
+
+
+ -
+ name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ context: git
+ images: |
+ name=ghcr.io/${{ github.repository_owner }}/${{ inputs.image-name || env.image-name }}-extended,enable=${{ inputs.ghcr_io || env.ghcr_io }}
+ name=docker.io/${{ github.repository_owner }}/${{ inputs.image-name || env.image-name }}-extended,enable=${{ inputs.docker_io || env.docker_io }}
+ labels: |
+ org.opencontainers.image.title=Pretalx extended
+ org.opencontainers.image.vendor=Pretalx Community
+ org.opencontainers.image.description=An unprivileged Pretalx container image that is extended with cron and a series of pretalx plugins
+ org.opencontainers.image.licenses=CC0
+
+ tags: |
+ type=match,pattern=v(.*),group=1
+ type=match,pattern=\d+-\d+-\d+
+ type=ref,event=branch
+ type=ref,event=tag
+ type=ref,event=pr
+ type=sha
+ ${{ inputs.image-tags || env.image-tags }}
+
+ -
+ name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ -
+ name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+
+ -
+ name: Login to Docker Hub Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( ( inputs.docker_io || env.docker_io ) == 'true' )
+ with:
+ registry: "docker.io"
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ -
+ name: Login to GitHub Packages Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( inputs.ghcr_io || env.ghcr_io )
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+
+ -
+ name: Build and push Container image
+ uses: docker/build-push-action@v5
+ id: build-push
+ with:
+ provenance: false
+ push: "${{ github.event_name != 'pull_request' }}"
+ platforms: "${{ inputs.platforms || env.platforms }}"
+ context: "{{ defaultContext }}:./context/extended"
+ file: "${{ inputs.file || env.file }}"
+ build-args: |
+ PRETALX_BASE_IMAGE=${{ env.BASE_IMAGE }}
+ PRETALX_BASE_TAG=${{ env.BASE_TAG }}
+ tags: "${{ steps.meta.outputs.tags }}"
+ labels: "${{ steps.meta.outputs.labels }}"
+ outputs: "type=docker,dest=/tmp/pretalx-extended.tar"
+
+ -
+ name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: pretalx-extended
+ path: /tmp/pretalx-extended.tar
+
+
+ # pretalx/pretalx-extended:*-cron
+ extended-cron:
+
+ name: Build extended image with cron
+ needs: extended
+ runs-on: ubuntu-latest
+
+ outputs:
+ imageid: ${{ steps.build-push.outputs.imageid }}
+ digest: ${{ steps.build-push.outputs.digest }}
+ metadata: ${{ steps.build-push.outputs.metadata }}
+
+ steps:
+
+ -
+ name: Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: pretalx-extended
+ path: /tmp
+ -
+ name: Load image
+ run: |
+ docker load --input /tmp/pretalx-extended.tar
+ docker image ls -a
+ IMAGE_REPO=$(docker images --format "{{.Repository}}" | head -n 1)
+ IMAGE_TAG=$(docker images --format "{{.Tag}}" | head -n 1)
+ echo "BASE_IMAGE=${IMAGE_REPO}" >> "$GITHUB_ENV"
+ echo "BASE_TAG=${IMAGE_TAG}" >> "$GITHUB_ENV"
+
+ -
+ name: Checkout repository
+ uses: actions/checkout@v4
+
+
+ -
+ name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ context: git
+ images: |
+ name=ghcr.io/${{ github.repository_owner }}/${{ inputs.image-name || env.image-name }}-extended,enable=${{ inputs.ghcr_io || env.ghcr_io }}
+ name=docker.io/${{ github.repository_owner }}/${{ inputs.image-name || env.image-name }}-extended,enable=${{ inputs.docker_io || env.docker_io }}
+ labels: |
+ org.opencontainers.image.title=Pretalx extended and cron
+ org.opencontainers.image.vendor=Pretalx Community
+ org.opencontainers.image.description=An unprivileged Pretalx container image that is extended with cron and a series of pretalx plugins
+ org.opencontainers.image.licenses=CC0
+
+ tags: |
+ type=match,pattern=v(.*),group=1,suffix=-cron
+ type=match,pattern=\d+-\d+-\d+,suffix=-cron
+ type=ref,event=branch,suffix=-cron
+ type=ref,event=tag,suffix=-cron
+ type=ref,event=pr,suffix=-cron
+ type=sha,suffix=-cron
+ ${{ inputs.image-tags || env.image-tags }}
+
+ -
+ name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ -
+ name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+
+ -
+ name: Login to Docker Hub Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( ( inputs.docker_io || env.docker_io ) == 'true' )
+ with:
+ registry: "docker.io"
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ -
+ name: Login to GitHub Packages Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( inputs.ghcr_io || env.ghcr_io )
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+
+ -
+ name: Build and push Container image
+ uses: docker/build-push-action@v5
+ id: build-push
+ with:
+ provenance: false
+ push: "${{ github.event_name != 'pull_request' }}"
+ platforms: "${{ inputs.platforms || env.platforms }}"
+ context: "{{ defaultContext }}:./context/extended"
+ file: "${{ inputs.file || env.file }}"
+ build-args: |
+ PRETALX_BASE_IMAGE=${{ env.BASE_IMAGE }}
+ PRETALX_BASE_TAG=${{ env.BASE_TAG }}
+ tags: "${{ steps.meta.outputs.tags }}"
+ labels: "${{ steps.meta.outputs.labels }}"
+
+
+ # pretalx/standalone:*
+ standalone:
+
+ name: Build standalone image
+ needs: default
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ id-token: write
+ packages: write
+
+ outputs:
+ imageid: ${{ steps.build-push.outputs.imageid }}
+ digest: ${{ steps.build-push.outputs.digest }}
+ metadata: ${{ steps.build-push.outputs.metadata }}
+
+ steps:
+
+ -
+ name: Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: pretalx-default
+ path: /tmp
+ -
+ name: Load image
+ run: |
+ docker load --input /tmp/pretalx-default.tar
+ docker image ls -a
+ IMAGE_REPO=$(docker images --format "{{.Repository}}" | head -n 1)
+ IMAGE_TAG=$(docker images --format "{{.Tag}}" | head -n 1)
+ echo "BASE_IMAGE=${IMAGE_REPO}" >> "$GITHUB_ENV"
+ echo "BASE_TAG=${IMAGE_TAG}" >> "$GITHUB_ENV"
+
+ -
+ name: Checkout repository
+ uses: actions/checkout@v4
+
+
+ -
+ name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ context: git
+ images: |
+ name=ghcr.io/${{ github.repository_owner }}/standalone,enable=${{ inputs.ghcr_io || env.ghcr_io }}
+ name=docker.io/${{ github.repository_owner }}/standalone,enable=${{ inputs.docker_io || env.docker_io }}
+ labels: |
+ org.opencontainers.image.title=Pretalx standalone
+ org.opencontainers.image.vendor=Pretalx Community
+ org.opencontainers.image.description=A partially privileged and unprivileged, standalone Pretalx container image
+ org.opencontainers.image.licenses=CC0
+
+ tags: |
+ type=match,pattern=v(.*),group=1
+ type=match,pattern=\d+-\d+-\d+
+ type=ref,event=branch
+ type=ref,event=tag
+ type=ref,event=pr
+ type=sha
+ ${{ inputs.image-tags || env.image-tags }}
+
+ -
+ name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ -
+ name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+
+ -
+ name: Login to Docker Hub Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( ( inputs.docker_io || env.docker_io ) == 'true' )
+ with:
+ registry: "docker.io"
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ -
+ name: Login to GitHub Packages Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( inputs.ghcr_io || env.ghcr_io )
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+
+ -
+ name: Build and push Container image
+ uses: docker/build-push-action@v5
+ id: build-push
+ with:
+ provenance: false
+ push: "${{ github.event_name != 'pull_request' }}"
+ platforms: "${{ inputs.platforms || env.platforms }}"
+ context: "{{ defaultContext }}:./context/standalone/default"
+ file: "${{ inputs.file || env.file }}"
+ build-args: |
+ PRETALX_BASE_IMAGE=${{ env.BASE_IMAGE }}
+ PRETALX_BASE_TAG=${{ env.BASE_TAG }}
+ tags: "${{ steps.meta.outputs.tags }}"
+ labels: "${{ steps.meta.outputs.labels }}"
+ outputs: "type=docker,dest=/tmp/pretalx-standalone.tar"
+
+ -
+ name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: pretalx-standalone
+ path: /tmp/pretalx-standalone.tar
+
+
+ # pretalx/standalone-extended:*
+ standalone-extended:
+
+ name: Build extended standalone image
+ needs: standalone
+ runs-on: ubuntu-latest
+
+ outputs:
+ imageid: ${{ steps.build-push.outputs.imageid }}
+ digest: ${{ steps.build-push.outputs.digest }}
+ metadata: ${{ steps.build-push.outputs.metadata }}
+
+ steps:
+
+ -
+ name: Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: pretalx-standalone
+ path: /tmp
+ -
+ name: Load image
+ run: |
+ docker load --input /tmp/pretalx-standalone.tar
+ docker image ls -a
+ IMAGE_REPO=$(docker images --format "{{.Repository}}" | head -n 1)
+ IMAGE_TAG=$(docker images --format "{{.Tag}}" | head -n 1)
+ echo "BASE_IMAGE=${IMAGE_REPO}" >> "$GITHUB_ENV"
+ echo "BASE_TAG=${IMAGE_TAG}" >> "$GITHUB_ENV"
+
+ -
+ name: Checkout repository
+ uses: actions/checkout@v4
+
+
+ -
+ name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ context: git
+ images: |
+ name=ghcr.io/${{ github.repository_owner }}/standalone-extended,enable=${{ inputs.ghcr_io || env.ghcr_io }}
+ name=docker.io/${{ github.repository_owner }}/standalone-extended,enable=${{ inputs.docker_io || env.docker_io }}
+ labels: |
+ org.opencontainers.image.title=Pretalx standalone extended
+ org.opencontainers.image.vendor=Pretalx Community
+ org.opencontainers.image.description=A partially privileged and unprivileged, standalone Pretalx container image with plugins
+ org.opencontainers.image.licenses=CC0
+
+ tags: |
+ type=match,pattern=v(.*),group=1
+ type=match,pattern=\d+-\d+-\d+
+ type=ref,event=branch
+ type=ref,event=tag
+ type=ref,event=pr
+ type=sha
+ ${{ inputs.image-tags || env.image-tags }}
+
+ -
+ name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ -
+ name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+
+ -
+ name: Login to Docker Hub Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( ( inputs.docker_io || env.docker_io ) == 'true' )
+ with:
+ registry: "docker.io"
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ -
+ name: Login to GitHub Packages Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( inputs.ghcr_io || env.ghcr_io )
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+
+ -
+ name: Build and push Container image
+ uses: docker/build-push-action@v5
+ id: build-push
+ with:
+ provenance: false
+ push: "${{ github.event_name != 'pull_request' }}"
+ platforms: "${{ inputs.platforms || env.platforms }}"
+ context: "{{ defaultContext }}:./context/standalone/extended"
+ file: "${{ inputs.file || env.file }}"
+ build-args: |
+ PRETALX_BASE_IMAGE=${{ env.BASE_IMAGE }}
+ PRETALX_BASE_TAG=${{ env.BASE_TAG }}
+ tags: "${{ steps.meta.outputs.tags }}"
+ labels: "${{ steps.meta.outputs.labels }}"
+ outputs: "type=docker,dest=/tmp/pretalx-standalone-extended.tar"
+
+ -
+ name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: pretalx-standalone-extended
+ path: /tmp/pretalx-standalone-extended.tar
+
+
+ # pretalx/standalone-extended:*-cron
+ standalone-extended-cron:
+
+ name: Build extended standalone image with cron
+ needs: standalone-extended
+ runs-on: ubuntu-latest
+
+ outputs:
+ imageid: ${{ steps.build-push.outputs.imageid }}
+ digest: ${{ steps.build-push.outputs.digest }}
+ metadata: ${{ steps.build-push.outputs.metadata }}
+
+ steps:
+
+ -
+ name: Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: pretalx-standalone-extended
+ path: /tmp
+ -
+ name: Load image
+ run: |
+ docker load --input /tmp/pretalx-standalone-extended.tar
+ docker image ls -a
+ IMAGE_REPO=$(docker images --format "{{.Repository}}" | head -n 1)
+ IMAGE_TAG=$(docker images --format "{{.Tag}}" | head -n 1)
+ echo "BASE_IMAGE=${IMAGE_REPO}" >> "$GITHUB_ENV"
+ echo "BASE_TAG=${IMAGE_TAG}" >> "$GITHUB_ENV"
+
+ -
+ name: Checkout repository
+ uses: actions/checkout@v4
+
+
+ -
+ name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ context: git
+ images: |
+ name=ghcr.io/${{ github.repository_owner }}/standalone-extended,enable=${{ inputs.ghcr_io || env.ghcr_io }}
+ name=docker.io/${{ github.repository_owner }}/standalone-extended,enable=${{ inputs.docker_io || env.docker_io }}
+ labels: |
+ org.opencontainers.image.title=Pretalx standalone extended with cron
+ org.opencontainers.image.vendor=Pretalx Community
+ org.opencontainers.image.description=A partially privileged and unprivileged, standalone Pretalx container image with cron and plugins
+ org.opencontainers.image.licenses=CC0
+
+ tags: |
+ type=match,pattern=v(.*),group=1,suffix=-cron
+ type=match,pattern=\d+-\d+-\d+,suffix=-cron
+ type=ref,event=branch,suffix=-cron
+ type=ref,event=tag,suffix=-cron
+ type=ref,event=pr,suffix=-cron
+ type=sha,suffix=-cron
+ ${{ inputs.image-tags || env.image-tags }}
+
+ -
+ name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ -
+ name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+
+ -
+ name: Login to Docker Hub Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( ( inputs.docker_io || env.docker_io ) == 'true' )
+ with:
+ registry: "docker.io"
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ -
+ name: Login to GitHub Packages Registry
+ uses: docker/login-action@v3
+ if: github.event_name != 'pull_request' && ( inputs.ghcr_io || env.ghcr_io )
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+
+ -
+ name: Build and push Container image
+ uses: docker/build-push-action@v5
+ id: build-push
+ with:
+ provenance: false
+ push: "${{ github.event_name != 'pull_request' }}"
+ platforms: "${{ inputs.platforms || env.platforms }}"
+ context: "{{ defaultContext }}:./context/standalone/extended.cron"
+ file: "${{ inputs.file || env.file }}"
+ build-args: |
+ PRETALX_BASE_IMAGE=${{ env.BASE_IMAGE }}
+ PRETALX_BASE_TAG=${{ env.BASE_TAG }}
+ tags: "${{ steps.meta.outputs.tags }}"
+ labels: "${{ steps.meta.outputs.labels }}"
diff --git a/.github/workflows/build.default.yml b/.github/workflows/build.default.yml
new file mode 100644
index 0000000..d6a107b
--- /dev/null
+++ b/.github/workflows/build.default.yml
@@ -0,0 +1,54 @@
+name: Pretalx OCI image
+
+on:
+ workflow_call:
+ inputs:
+ ref:
+ required: true
+ type: string
+ default: ${{ github.ref }}
+
+ workflow_dispatch:
+ inputs:
+ ref:
+ required: false
+ type: string
+
+
+permissions:
+ contents: read
+ packages: write
+ id-token: write
+
+
+jobs:
+
+ call-build-and-push:
+ name: Call image build
+ uses: ./.github/workflows/build-and-push.yml
+ if: ( inputs.ref == 0 )
+ with:
+ image-name: pretalx
+ platforms: linux/amd64
+ context: ./context/default
+ file: Dockerfile.debian
+ build-args: |
+ BASE_IMAGE=docker.io/library/python
+ BASE_TAG=3.12-bookworm
+ PRETALX_VERSION=2024.1.0
+ secrets: inherit
+ call-build-and-push-ref:
+ name: Call tagged image build
+ uses: ./.github/workflows/build-and-push.yml
+ if: ( inputs.ref != 0 )
+ with:
+ image-name: pretalx
+ platforms: linux/amd64
+ context: ./context/default
+ file: Dockerfile.debian
+ ref: ${{ inputs.ref }}
+ build-args: |
+ BASE_IMAGE=docker.io/library/python
+ BASE_TAG=3.12-bookworm
+ PRETALX_VERSION=2024.1.0
+ secrets: inherit
diff --git a/.github/workflows/build.extended.yml b/.github/workflows/build.extended.yml
new file mode 100644
index 0000000..de25b33
--- /dev/null
+++ b/.github/workflows/build.extended.yml
@@ -0,0 +1,52 @@
+name: Pretalx extended OCI image
+
+on:
+ workflow_call:
+ inputs:
+ ref:
+ required: true
+ type: string
+ default: ${{ github.ref }}
+
+ workflow_dispatch:
+ inputs:
+ ref:
+ required: false
+ type: string
+
+
+permissions:
+ contents: read
+ packages: write
+ id-token: write
+
+
+jobs:
+
+ call-build-and-push:
+ name: Call image build
+ uses: ./.github/workflows/build-and-push.yml
+ if: ( inputs.ref == 0 )
+ with:
+ image-name: pretalx-extended
+ platforms: linux/amd64
+ context: ./context/extended
+ file: Dockerfile.debian
+ build-args: |
+ BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/pretalx
+ BASE_TAG=latest
+ secrets: inherit
+ call-build-and-push-ref:
+ name: Call tagged image build
+ uses: ./.github/workflows/build-and-push.yml
+ if: ( inputs.ref != 0 )
+ with:
+ image-name: pretalx-extended
+ platforms: linux/amd64
+ context: ./context/extended
+ file: Dockerfile.debian
+ ref: ${{ inputs.ref }}
+ build-args: |
+ BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/pretalx
+ BASE_TAG=latest
+ secrets: inherit
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
deleted file mode 100644
index bea4136..0000000
--- a/.github/workflows/docker.yml
+++ /dev/null
@@ -1,58 +0,0 @@
-name: Docker
-
-on:
- workflow_dispatch: # allows to be run manually
- push:
- tags:
- - '*'
- pull_request:
- branches:
- - 'main'
-
-jobs:
- build_and_push:
- name: Build and push Docker image to Docker Hub or GHCR
- runs-on: ubuntu-latest
- env:
- push_to_docker_hub: ${{ secrets.DOCKER_USERNAME != null && secrets.DOCKER_PASSWORD != null }}
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- submodules: true
-
- - name: Docker meta
- id: meta
- uses: docker/metadata-action@v5
- with:
- images: ${{ env.push_to_docker_hub == 'true' && 'pretalx/standalone' || format('ghcr.io/{0}', github.repository) }}
-
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Login to DockerHub
- if: github.event_name != 'pull_request' && env.push_to_docker_hub == 'true'
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKER_USERNAME }}
- password: ${{ secrets.DOCKER_PASSWORD }}
-
- - name: Login to GHCR
- if: github.event_name != 'pull_request' && env.push_to_docker_hub == 'false'
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Build and push
- uses: docker/build-push-action@v5
- with:
- context: .
- platforms: linux/amd64,linux/arm64
- push: ${{ github.event_name != 'pull_request' }}
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
diff --git a/.gitignore b/.gitignore
index 57d9655..d58e53b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,8 @@
-volumes/
+*.swp
+.env
+.env.build
+.env.pretalx
+.state
+pretalx.cfg
+docker-compose.yml
+context/source/standalone/pretalx
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index c84c449..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,4 +0,0 @@
-[submodule "pretalx"]
- path = pretalx
- url = https://github.com/pretalx/pretalx
- branch = 3e0cebd4db782e6a271b6ddc86468e9181411831
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index a55b563..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,54 +0,0 @@
-FROM python:3.10-bookworm
-
-RUN apt-get update && \
- apt-get install -y git gettext libmariadb-dev libpq-dev locales libmemcached-dev build-essential \
- supervisor \
- sudo \
- locales \
- --no-install-recommends && \
- apt-get clean && \
- rm -rf /var/lib/apt/lists/* && \
- dpkg-reconfigure locales && \
- locale-gen C.UTF-8 && \
- /usr/sbin/update-locale LANG=C.UTF-8 && \
- mkdir /etc/pretalx && \
- mkdir /data && \
- mkdir /public && \
- groupadd -g 999 pretalxuser && \
- useradd -r -u 999 -g pretalxuser -d /pretalx -ms /bin/bash pretalxuser && \
- echo 'pretalxuser ALL=(ALL) NOPASSWD: /usr/bin/supervisord' >> /etc/sudoers
-
-ENV LC_ALL=C.UTF-8
-
-
-COPY pretalx/pyproject.toml /pretalx
-COPY pretalx/src /pretalx/src
-COPY deployment/docker/pretalx.bash /usr/local/bin/pretalx
-COPY deployment/docker/supervisord.conf /etc/supervisord.conf
-
-RUN pip3 install -U pip setuptools wheel typing && \
- pip3 install -e /pretalx/[mysql,postgres,redis] && \
- pip3 install pylibmc && \
- pip3 install gunicorn
-
-
-RUN python3 -m pretalx makemigrations
-RUN python3 -m pretalx migrate
-
-RUN apt-get update && \
- apt-get install -y nodejs npm && \
- apt-get clean && \
- rm -rf /var/lib/apt/lists/* && \
- python3 -m pretalx rebuild
-
-RUN chmod +x /usr/local/bin/pretalx && \
- cd /pretalx/src && \
- rm -f pretalx.cfg && \
- chown -R pretalxuser:pretalxuser /pretalx /data /public && \
- rm -f /pretalx/src/data/.secret
-
-USER pretalxuser
-VOLUME ["/etc/pretalx", "/data", "/public"]
-EXPOSE 80
-ENTRYPOINT ["pretalx"]
-CMD ["all"]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d30ca65
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1 @@
+CC0
diff --git a/README.md b/README.md
index 6de7812..807b866 100644
--- a/README.md
+++ b/README.md
@@ -1,65 +1,643 @@
# pretalx-docker
-This repository contains a docker-compose setup as well as an [ansible](https://docs.ansible.com) role for a
-[pretalx](https://github.com/pretalx/pretalx) installation based on docker.
-
-**Please note that this repository is provided by the pretalx community, and not supported by the pretalx team.**
-
-## Installation with docker-compose
-
-### For testing
-
-* Run ``docker-compose up -d``. After a few minutes the setup should be accessible at http://localhost/orga
-* Set up a user and an organizer by running ``docker exec -ti pretalx pretalx init``.
-
-### For production
-
-* Edit ``conf/pretalx.cfg`` and fill in your own values (→ [configuration
- documentation](https://docs.pretalx.org/en/latest/administrator/configure.html))
-* Edit ``docker-compose.yml`` and remove the complete section with ``ports: - "80:80"`` from the file (if you go with
- traefic as reverse proxy) or change the line to ``ports: - "127.0.0.1:8355:80"`` (if you use nginx). **Change the
- database password.**
-* If you don't want to use docker volumes, create directories for the persistent data and make them read-writeable for
- the userid 999 and the groupid 999. Change ``pretalx-redis``, ``pretalx-db``, ``pretalx-data`` and ``pretalx-public`` to the corresponding
- directories you've chosen.
-* Configure a reverse-proxy for better security and to handle TLS. Pretalx listens on port 80 in the ``pretalxdocker``
- network. I recommend to go with traefik for its ease of setup, docker integration and [LetsEncrypt
- support](https://docs.traefik.io/user-guide/docker-and-lets-encrypt/). An example to copy into the normal compose file
- is located at ``reverse-proxy-examples/docker-compose``. You can also find a few words on an nginx configuration at
- ``reverse-proxy-examples/nginx``
-* Make sure you serve all requests for the `/static/` and `/media/` paths (when `debug=false`). See [installation](https://docs.pretalx.org/administrator/installation/#step-7-ssl) for more information
-* Optional: Some of the Gunicorn parameters can be adjusted via environment viariables:
- * To adjust the number of [Gunicorn workers](https://docs.gunicorn.org/en/stable/settings.html#workers), provide
- the container with `GUNICORN_WORKERS` environment variable.
- * `GUNICORN_MAX_REQUESTS` and `GUNICORN_MAX_REQUESTS_JITTER` to configure the requests a worker instance will process before restarting.
- * `GUNICORN_FORWARDED_ALLOW_IPS` lets you specify which IPs to trust (i.e. which reverse proxies' `X-Forwarded-*` headers can be used to infer connection security).
- * `GUNICORN_BIND_ADDR` can be used to change the interface and port that Gunicorn will listen on. Default: `0.0.0.0:80`
-
- Here's how to set an environment variable [in
- `docker-compose.yml`](https://docs.docker.com/compose/environment-variables/set-environment-variables/)
- or when using [`docker run` command](https://docs.docker.com/engine/reference/run/#env-environment-variables).
-* Run ``docker-compose up -d ``. After a few minutes the setup should be accessible under http://yourdomain.com/orga
-* Set up a user and an organizer by running ``docker exec -ti pretalx pretalx init``.
-* Set up a cronjob for periodic tasks like this ``15,45 * * * * docker exec pretalx-app pretalx runperiodic``
-
-
-## Installation with ansible
-
-(Please note that we also provide a second ansible role for use without docker
-[here](https://github.com/pretalx/ansible-pretalx/)).
-
-### For testing
-
-* Add the role at ``ansible-role`` to your ansible setup.
-* Roll out the role
-* You should be able to reach pretalx at ``http://localhost/orga``
-* Set up a user and an organizer by running ``docker exec -ti pretalx pretalx init``.
-
-### For production
-
-* Add the role at ``ansible-role`` to your ansible setup.
-* Fill in the variables listed in the ``vars/main.yml`` file. **Make sure to set testing to false!**
-* Set up a reverse proxy to handle TLS. traefik is recommended. The containers that get rolled out are already tagged
- for traefik. An example role for traefik is included at ``reverse-proxy-examples/ansible/traefik``.
-* Roll out the role. After a few minutes pretalx should be reachable at the configured domain.
-* Set up a user and an organizer by running ``docker exec -ti pretalx pretalx init`` .
+This repository contains a Container image and a Docker Compose setup for a
+[pretalx](https://github.com/pretalx/pretalx) installation.
+
+> **Please note that the repository is provided by the pretalx community and not officially supported.**
+
+## Contents
+
+- [Components](#components)
+- [Installation](#installation)
+- [Configuration](#configuration)
+- [Build](#build)
+ - [CI](#ci)
+ - [Setting up the build environment](#setting-up-the-build-environment)
+ - [Local building of the Container image and the Compose manifest](#local-building-of-the-container-image-and-the-compose-manifest)
+ - [Live deployment](#live-deployment)
+ - [Local live-like deployment](#local-live-like-deployment)
+ - [With plugins](#with-plugins)
+- [Run](#run)
+ - [Locally](#locally)
+ - [Live](#live)
+ - [Management commands](#management-commands)
+- [Initialisation](#initialisation)
+- [Recycle](#recycle)
+- [Legacy](#legacy)
+- [Authors](#authors)
+- [License](#license)
+- [Copyright](#copyright)
+
+## Components
+
+The repository holds the a collection of usable components.
+
+- Dockerfiles to build container images
+- Compose manifests to show how to use the containers
+- CI manifests to automatically build the images
+
+Files and directories explained
+
+### Directories
+
+You can list the directories in this repository with:
+
+```sh
+$ tree -d -L 3 -a -I '.git'
+```
+
+- `.github/`, GitHub-specific contents
+ - `workflows/`, GitHub Actions workflows
+- `bin/`, maintenance and life-cycle scripts
+- `compose/`, Compose overlays, to be used as additional `-f` flags
+ - `build/`, overlays for locally building the images
+ - `source/`, overlays for source builds
+ - `standalone/`, overlays for building standalone images
+- `config/`, runtime configuration files
+- `context/`, Container image build contexts
+ - `base/`, the pretalx base image with its system dependencies
+ - `cron/`, an image variant with cron
+ - `default/`, the Pretalx stock image
+ - `extended/`, an extended Pretalx image variant with plugins
+ - `source/`, contexts to build Pretalx images from source
+ - `extended.cron/`, an extended Pretalx image with plugins and cron
+ - `standalone`, a standalone Pretalx image with supervisor; builds from local or remote sources
+ - `standalone.extended.cron/`, a standalone Pretalx image with cron, supervisor and plugins
+ - `standalone/`, contexts to build standalone Pretalx images
+ - `default/`, a standalone Pretalx image with supervisor
+ - `extended/`, an extended standalone Pretalx image with supervisor and plugins
+ - `extended.cron`, an extended standalone Pretalx image with supervisor, cron and plugins
+- `legacy/`, support for the legacy Python version of `docker-compose`
+
+### Files
+
+The application stack is defined by a Compose manifest and an environment file, which are extended by overlay Compose manifests.
+
+An additional environment is provided for conducting image builds with Compose.
+
+- `.env.build.example`, example environment to build images
+- `.env.example`, example environment
+- `compose.yml`, Compose manifest
+
+#### .github/
+
+GitHub-specific configuration files.
+
+- `dependabot.yml`, configuration to automatically update dependencies
+
+##### .github/workflows/
+
+GitHub Actions workflows to build the images in CI.
+
+- `build-and-push.yml`, parametrised build workflow to be called by other workflows
+- `build.default.yml`, build workflow that builds the `default` context
+- `build.plugins.yml`, build workflow that builds the `plugins` context
+
+#### bin/
+
+Scripts to perfom bulk operations on the repository.
+
+- `clean`, removes generated data, including built images and an eventual clone of pretalx for the local source overlay
+- `build`, builds the `pretalx/base:3.12-bookworm`, `pretalx/pretalx:2024.1.0`, `pretalx/pretalx-extended:2024.1.0` and `pretalx/pretalx-extended:2024.1.0-cron` images
+- `build.source`, builds the `pretalx/base:3.12-bookworm`, `pretalx/pretalx-extended:main-source-remote-cron`, `pretalx/standalone:main-source-{local,remote}` and `pretalx/standalone-extended:main-source-remote-cron` images
+- `build.standalone`, builds the `pretalx/pretalx:2024.1.0`, `pretalx/standalone:2024.1.0` and `pretalx/standalone-extended:2024.1.0{,-cron}` images
+
+#### compose/
+
+Compose overlays for running locally and/or behind a Traefik reverse proxy.
+
+- `local.yml`, overlay to add a local listening port for the `web` container
+- `traefik.yml`, overlay to add the Traefik-specific external `web` network and associated configuration labels
+
+##### compose/build/
+
+Compose overlays to exemplify the build of certain image variants.
+
+- `base.yml`, builds the `base` context, used for the `pretalx/base` image
+- `default.yml`, builds the image from the `default` context, used for the `pretalx/pretalx` image
+- `extended.yml`, builds the image from the `extended` context, based on `default`, used for the `pretalx/pretalx-extended` image
+- `extended.cron.yml`, builds the image from the `cron` context, based on `extended`, used for the `pretalx/pretalx-extended` image, tagged `-cron`
+
+###### compose/source/
+
+Compose overlays to build the pretalx application from its source code.
+
+- `extended.cron.remote.yml`, builds an extended image from the latest, remotely pulled git source, with cron and plugins
+- `standalone.local.yml`, builds a standalone image from locally available sources
+- `standalone.remote.yml`, builds a standalone image from a remote git source
+- `standalone.extended.cron.remote.yml`, extends the previous image with cron and plugins
+
+###### compose/standalone/
+
+- `default.yml`, a standalone image, equivalent with the `pretalx/standalone` image from CI
+- `extended.yml`, a standalone image extended with plugins
+- `extended.cron.yml`, a standalone image extended with cron and plugins
+
+#### config/
+
+Configuration manifests of run-time components.
+
+- `nginx.conf`, configuration for Nginx that serves static assets and otherwise proxies to the application container
+- `pretalx.cfg.example`, depreciated, example of a configuration file to be used optionally, e.g. with the `local` overlay
+
+#### context/
+
+The Docker build contexts that define the various images supported by this repository.
+
+##### context/base/
+
+- `Dockerfile.debian`, Debian-based container image manifest for Pretalx, used for the `pretalx/base` image
+- `entrypoint.sh`, script to be evaluated at runtime when the container starts; prepared for all variants; expects an argument
+
+##### context/cron/
+
+- `crontab`, configuration to run periodic tasks; adapted for use inside a container
+- `Dockerfile.debian`, Debian-based container image manifest for Pretalx, includes cron
+
+##### context/default/
+
+- `Dockerfile.debian`, Debian-based container image manifest for Pretalx, used for the `pretalx/pretalx` image
+
+##### context/extended/
+
+- `Dockerfile.debian`, Debian-based container image manifest for Pretalx, includes plugins
+
+##### context/source/
+
+The source contexts are used to build pretalx from locally or remotely available source code.
+
+###### context/source/extended.cron/
+
+- `crontab`, configuration to run periodic tasks; adapted for use inside a container
+- `Dockerfile.debian.remote`, Debian-based container image manifest for Pretalx
+
+###### context/source/standalone/
+
+- `Dockerfile.debian.local`, Debian-based container image manifest for Pretalx; continuation of the old `pretalx/standalone` image
+- `Dockerfile.debian.remote`, Debian-based container image manifest for Pretalx; extended with supervisor; used for the `pretalx/standalone` image
+- `supervisord.conf`, configuration to run multiple unprivileged processes in the same container
+
+###### context/source/standalone.extended.cron/
+
+- `crontab`, configuration to run periodic tasks; adapted to be run via the supervisor
+- `Dockerfile.debian.remote`, Debian-based container image manifest for Pretalx, extended with cron and plugins
+- `supervisord.conf`, configuration to run multiple privileged and unprivileged processes in the same container; adapted for use with cron
+
+##### context/standalone/
+
+The standalone context is provided for compatibility with the `pretalx/standalone` image created with the `pretalx-docker` repository before 05.2024. These containers run both processes of the main Gunicorn process and the Celery task worker. This is useful for testing, but they cannot be scaled independently in a real-world scenario, why migration to the newer `pretalx/pretalx` image with running both processes in separate containers is recommended.
+
+This depreciates the old standalone container, which was tightly coupled with source code in a git submodule, which has been depreciated. A new version that offers a migration path with a decoupled git repository is available in `context/source/standalone/Dockerfile.debian.local`.
+
+###### context/standalone/default/
+
+- `Dockerfile.debian`, Debian-based container image manifest for Pretalx
+- `supervisord.conf`, configuration to run multiple unprivileged processes in the same container
+
+###### context/standalone/extended/
+
+- `Dockerfile.debian`, Debian-based container image manifest for Pretalx, extended with plugins
+
+###### context/standalone/extended.cron/
+
+- `crontab`, configuration to run periodic tasks; adapted to be run via the supervisor
+- `Dockerfile.debian`, container image manifest that adds plugins to Pretalx, extended with cron and plugins
+- `supervisord.conf`, configuration to run multiple privileged and unprivileged processes in the same container; adapted for use with cron
+
+#### legacy/
+
+- `docker-compose.build.yml.example`, overlay example to build an `pretalx-extended` image from the `extended` context
+- `docker-compose.env.example`, Compose, Traefik and Postgres environment example
+- `docker-compose.env.pretalx.example`, Pretalx environment example
+- `docker-compose.yml.example`, Docker Compose manifest example
+
+Please read on thorugh the following sections to find out how they interact with each other.
+
+
+
+## Installation
+
+This repository follows the Pretalx installation instructions as closely as possible.
+
+- [Installation — pretalx documentation](https://docs.pretalx.org/administrator/installation/)
+
+## Configuration
+
+The repository implements the dot env pattern to configure all application containers through environmental variables.
+
+Copy the example and modify it according to your setup:
+
+```sh
+cp .env.example .env
+```
+
+The Pretalx image and version to pull or build are indicated at the top:
+
+- `PRETALX_IMAGE`, Pretalx Container image name
+- `PRETALX_TAG`, Pretalx Container image tag
+
+### Run-time variables
+
+The setup uses all environmental variables used by Pretalx:
+
+- [Configuration — pretalx documentation](https://docs.pretalx.org/administrator/configure/)
+
+You will likely want to uncomment and provide email settings to a live environment.
+
+These variables configure the web proxy, the application processes and the database:
+
+- `FQDN`, fully-qualified domain name, used for the `Host` matcher in the `traefik` configuration and for the `plugins` images
+- `POSTGRES_DB`, Postgres database name
+- `POSTGRES_USER`, Postgres user name
+- `POSTGRES_PASSWORD`, Postgres user password
+- `PRETALX_LOG_LEVEL`, Gunicorn and Celery log level
+
+The following variables are available to configure the Gunicorn web process:
+
+- `GUNICORN_WORKERS`
+- `GUNICORN_MAX_REQUESTS`
+- `GUNICORN_MAX_REQUESTS_JITTER`
+- `GUNICORN_FORWARDED_ALLOW_IPS`
+- `GUNICORN_BIND_ADDR`
+
+Please refer to [`context/default/entrypoint.sh`](./context/default/entrypoint.sh) and [the Gunicorn settings documentation](https://docs.gunicorn.org/en/stable/settings.html) about their usage.
+
+## Building
+
+This repository is used for developing Container images from the source manifests present in the `context/` directory.
+
+> It does not cover the use case of building a Pretalx development environment.
+>
+> It is left for the curious reader to propose this with [development containers](https://containers.dev/) directly to the `pretalx/pretalx` repository.
+
+### CI
+
+We provide CI manifests to build and push container images to Docker Hub (`docker.io`) and to the GitHub Container Registry (`ghcr.io`).
+
+Find them in [`.github/workflows/`](.github/workflows/).
+
+- `build-and-push.yml`, a generic build and push workflow that is called by other workflows and releases artifacts into Docker Hub and the GitHub Container Registry.
+- `build.default.yml`, builds the `default` context into a `pretalx` image.
+- `build.plugins.yml`, builds the `plugins` context into a `pretalx-extended` image.
+
+The artifacts are published to:
+
+- [pretalx/pretalx Tags | Docker Hub](https://hub.docker.com/r/pretalx/pretalx/tags)
+- [pretalx/pretalx-extended Tags | Docker Hub](https://hub.docker.com/r/pretalx/pretalx-extended/tags)
+- [pretalx versions · pretalx · GHCR](https://github.com/pretalx/pretalx-docker/pkgs/container/pretalx/versions)
+- [pretalx-extended versions · pretalx · GHCR](https://github.com/pretalx/pretalx-docker/pkgs/container/pretalx-extended/versions)
+
+### Prerequisites
+
+This setup was implemented with Docker Compose on a Rootless Podman context on a SELinux-enabled Linux host, using the Docker CLI with a context on the local socket of the Podman systemd user unit for educational purposes.
+
+It also works with rootful or rootless Docker and rootful Podman respectively.
+
+Optional: Using Rootless Podman with Docker Compose via a Docker Context
+
+- [Using Podman and Docker Compose | Enable Sysadmin](https://www.redhat.com/sysadmin/podman-docker-compose)
+
+```sh
+$ systemctl --user start podman.service podman.socket
+$ docker context create podman --docker 'host=tcp:///run/user/1000/podman/podman.sock'
+$ docker context use podman
+$ docker context ls
+NAME DESCRIPTION DOCKER ENDPOINT ERROR
+default Current DOCKER_HOST based configuration unix:///var/run/docker.sock
+podman * unix:///run/user/1000/podman/podman.sock
+```
+
+
+
+Optional: Removing the SELinux compatibility, if not needed
+
+If your system does not have SELinux enabled or you wish to use this only with the rootful tooling, remove the SELinux-specific configuration:
+
+```sh
+sed '/selinux/d' -i compose.yml
+```
+
+
+
+Optional: Work around BuildKit issues with caching and newer Docker features
+
+The Docker Buildx BuildKit configuration does not allow to reuse cached image layers in subsequent build steps.
+
+- [Docker build "FROM" Fails to search local images · Issue #795 · docker/buildx](https://github.com/docker/buildx/issues/795)
+
+#### Using Docker, Buildx and Compose to build all images locally (using cache)
+
+To use this repository with Docker, Docker Compose and Docker Buildx, we need to switch back from BuildKit in a container to the default docker builder.
+
+```sh
+docker context use default
+docker buildx ls
+docker buildx use default
+```
+
+We can now locally conduct layered image builds with Docker, Compose through Buildx.
+
+#### Using rootless Podman, Buildx and Compose to build all images locally (using cache)
+
+To use this repository with rootless Podman, Docker Compose and Docker Buildx, we need to disable BuildKit entirely
+
+```sh
+docker context use podman
+export DOCKER_BUILDKIT=0
+```
+
+
+
+We are making good use of [YAML Fragments in the Compose files](https://docs.docker.com/compose/compose-file/10-fragments/). Be sure to learn what they do, which will aid you in reading the manifests.
+
+> Feel free to adapt these examples to your liking. E.g. you may need to copy and paste the adaptations into the single manifest, e.g. to run without `-f` modifiers, or have the main file called `docker-compose.yml` for the ancient version of `docker-compose`. See the *legacy* section for this use case.
+
+### Build-time variables
+
+To start building the images locally, copy the build environment example:
+
+```sh
+cp .env.build.example .env.build
+```
+
+The variables present in `.env.build` should not be modified and can be considered as sane defaults.
+
+The values are (hopefully) mostly self-explaining. Those you may want to experiment with changing are:
+
+- `PRETALX_VERSION`, the Pretalx version to install into the image
+- `BASE_IMAGE`, the base image to build from
+- `BASE_TAG`, the base image tag to build from
+- `PRETALX_BASE_IMAGE`, the name of the pretalx base image to build
+- `PRETALX_BASE_TAG`, the tag of the pretalx base image to build
+- `PRETALX_IMAGE`, the name of the pretalx image to build
+- `PRETALX_TAG`, the tag of the pretalx image to build
+
+### Local building of the Container images with using the Compose manifests
+
+Use the `build*` scripts in the `bin/` repository to conduct local builds, which package the most common use cases.
+
+```sh
+bin/build
+bin/build.standalone
+bin/build.source
+```
+
+The commands below help to develop and debug the Compose manifests and are provided as a reference:
+
+```sh
+docker compose --env-file .env -f compose.yml --env-file .env.build -f compose/build/default.yml build app
+```
+
+This will build the image with the name `${PRETALX_IMAGE}:${PRETALX_TAG}`, as specified by the inferred `image:` directive.
+
+### Building different combinations of overlays
+
+There is a need to accommodate for the presence of Pretalx plugins together with the application.
+
+This is achieved by creating overlay OCI file system layers and building a custom container image based on the default build context.
+
+```sh
+docker compose --env-file .env -f compose.yml -f compose/local.yml --env-file .env.build -f compose/build/extended.yml config
+```
+
+Or in a live environment:
+
+```sh
+docker compose --env-file .env -f compose.yml -f compose/traefik.yml --env-file .env.build -f compose/build/extended.yml config
+```
+
+All Compose commands in place of `config` apply from here.
+
+If you had successfully built your local Pretalx image, you could build an image extended with plugins with:
+
+```sh
+docker compose -f compose.yml --env-file .env.build -f compose/build/extended.yml build app
+```
+
+## Running
+
+During development, you may want to watch your container scheduler for the health of the containers from another shell:
+
+```sh
+watch -n 0.5 docker ps
+```
+
+### Locally
+
+When you are done with building and preloading the images into your container engine's image store, you can start the composition with:
+
+```sh
+docker compose --env-file .env -f compose.yml -f compose/local.yml --env-file .env.build -f compose/build/extended.yml up -d
+```
+
+> - *Continue* to **Initialisation** below.
+
+---
+
+### Local live-like environment
+
+If you were running a local `traefik` instance on a local `web` network, maybe even with a Smallstep CA for provisioning ACME certificates for your `.internal` network, you could add the network and necessary labels with:
+
+```sh
+docker compose -f compose.yml -f compose/local.yml -f compose/traefik.yml config
+```
+
+### Live
+
+To run this in a live environment, it is not needed to build the images locally. They will be provided by the container registry.
+
+This further assumes the presence of a fully configured `traefik` instance connected to the `web` network.
+
+Review the configuration you are about to launch:
+
+```sh
+docker compose -f compose.yml -f compose/traefik.yml config
+```
+
+Launch a selected configuration:
+
+```sh
+docker compose -f compose.yml -f compose/traefik.yml --env-file .env.build -f compose/build/extended.yml up -d
+```
+
+> - *Continue* to **Initialisation** below.
+
+---
+
+### Management commands
+
+The [entrypoint](./context/default/entrypoint.sh) provides convenience commands to run the Container with different processes from the same image in the same environment.
+
+- `migrate` launches the database migrations and initiates a `rebuild`.
+- `rebuild` regenerates static Django assets in `$PRETALX_FILESYSTEM_STATIC`, but only once. Can be `--force`d.
+- `gunicorn` launches the Gunicorn Python web server to serve Pretalx.
+ Can be configured with the `GUNICORN_*` environmental variables mentioned above.
+- `celery` launches the Celery task worker.
+- `cron` launches the Cron daemon to schedule the commands in the [`context/default/crontab`](./context/default/crontab).
+- `supervisor` launches the Supervisor daemon to run multiple long-running processes in the same container.
+
+All other commands are passed down to Pretalx.
+
+- [Management commands — pretalx documentation](https://docs.pretalx.org/administrator/commands/)
+
+They can be executed from within a running `app` container with `python` calling the `pretalx` module and passing the name of the task as an argument, in this example `showmigrations`:
+
+```sh
+docker compose exec app python -m pretalx showmigrations
+```
+
+This command does not need to have the `-f compose.{local,traefik,build/default,build/extended}.yml` arguments for defining overlays present, as it only modifies runtime state of an already existing container.
+
+## Initialisation
+
+You can start configuring your instance, when your `web` container shows as `healthy` in `docker ps`.
+
+Invoke the initialisation command:
+
+```sh
+docker compose exec app python -m pretalx init
+```
+
+You will see this configuration summary and the initialisation wizard:
+
+```console
+┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
+┃ ┏━━━━━━━━━━┓ pretalx v2024.1.0 ┃
+┃ ┃ ┌─·──╮ ┃ Settings: ┃
+┃ ┃ │ O │ ┃ Database: pretalx (postgresql) ┃
+┃ ┃ │ ┌──╯ ┃ Logging: /data/logs ┃
+┃ ┃ └─┘ ┃ Root dir: /pretalx/.local/lib/python3.12/site-packages/pretalx ┃
+┃ ┗━━━┯━┯━━━━┛ Python: /usr/local/bin/python ┃
+┃ ╰─╯ Plugins: pretalx_pages, pretalx_public_voting, prtx_faq ┃
+┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
+
+Welcome to pretalx! This is my initialization command, please use it only once.
+You can abort this command at any time using C-c, and it will save no data.
+
+Let's get you a user with the right to create new events and access every event on this pretalx instance.
+E-mail:
+```
+
+After finishing the questionnaire, you can login at [`http://localhost:8080/orga/`](http://localhost:8080/orga/).
+
+As you can see, we are not using a settings file. This is not needed, due to following the dot env pattern for [12factor.net](https://12factor.net) container-native applications. An example for `pretalx.cfg` and how to add it to the containers is available in `compose/local.yml` and in the `config/` subdirectory, in case needed.
+
+> *Please note:* Users of the `standalone` images need to manually run the database migrations, before the application can be initialised. Follow these steps instead:
+>
+> ```sh
+> docker compose run --rm app migrate
+> docker compose run --rm -it app init
+> ```
+
+## Upgrading
+
+In case the images used in this composition are updated in the container registry, you can update your installation with few interventions:
+
+1. Change the `PRETALX_TAG` to the newer version in the `.env` file
+2. Pull new images with `docker compose pull`
+3. Recreate existing containers with `docker compose up -d`
+
+> *Note:* Users of the standalone image also need to run `docker compose run --rm app migrate` between the steps 2. and 3.
+
+## Migrating from the old `pretalx/standalone` container image/build …
+
+The repository has seen a major refactor in May 2024. While it depreciates some of the original developments, it continues their work and seeks compatibility with the development patterns that were present. While there are many ways in which the components of the repository can be combined and adjusted, we would like to give some hints on common migration paths.
+
+More detailed instructions will be added here, when we find them.
+
+### … to the `pretalx/pretalx` image
+
+The `pretalx/pretalx` image does not bundle the supervisor, why you have to run two independent containers for the application server (Gunicorn) and the task worker (Celery). Please read `compose.yml` carefully on how to set this up.
+
+A more concise example may be given in the `legacy/` folder.
+
+Configuration values from `pretalx.cfg` have been converted into environment variables in `.env`. For future-compatibility, you are advised to perform the migration. It is still possible to mount a configuration file at `/pretalx/.pretalx.cfg`. Please refer to `local.yml` and `standalone.extended.cron.remote.yml` for examples.
+
+### … to the updated `pretalx/standalone` image
+
+As theory has it, you should be able to pull newly-tagged `pretalx/standalone` images and use them as a drop in replacement. Please leave us an issue, if that is not the case.
+
+### … to a custom source build based on the new `pretalx/standalone` image
+
+Please feel free to explore the range of examples that are given in the `build/` contexts to evaluate how you can reproduce the previous local source builds. `context/source/standalone/Dockerfile.debian.local` tries to be as close as possible to the previous setup that was using a git submodule to build images from.
+
+While this pattern has been depreciated for regular image builds, the previous way has been continued and tested with the others. Please report back any issue that you may encounter.
+
+## Recycle
+
+There are few life-cycle commands, which can help you reduce local resource usage. They are:
+
+```sh
+docker compose down --remove-orphans
+docker images | grep '' | awk '{ print $3 }' | xargs docker rmi
+```
+
+You can now start building images and creating containers from scratch.
+
+To delete eventual state, you can run either of these commands:
+
+```sh
+docker compose down --volumes
+docker volume rm $(docker volume ls -q | grep pretalx)
+```
+
+Remove `.env` when you need to reset the whole setup completely.
+
+```sh
+docker compose down -v --remove-orphans
+rm .env
+```
+
+To also clean your working directory, you can run:
+
+```sh
+bin/clean
+```
+
+To also clean your container engine's build cache, also run:
+
+```sh
+docker buildx prune -a
+```
+
+## Legacy
+
+The repository contains an example configuration for supporting the legacy version of Docker Compose.
+Due to the different feature set, an independent manifest is used.
+
+Please refer to [`legacy/`](./legacy/) to learn more.
+
+## Authors
+
+- Bastian Hodapp
+- Bruno Morisson
+- Daniel Goodman
+- Hadrien
+- Ian Foster
+- Johan Van de Wauw
+- Jon Richter
+- Jonathan Günz
+- Luca
+- Lukas
+- Marcus Müller
+- Matt Yaraskavitch
+- MaxR
+- Michal Stanke
+- Simeon Keske
+- Simon
+- Simon Hötten
+- Timon Erhart
+- Tobias Kunze
+- geleeroyale
+- jascha ehrenreich
+- kuhball
+- plaste
+- realitygaps
+
+## License
+
+CC0
+
+## Copyright
+
+© 2018—2024 Pretalx Community
diff --git a/ansible-role/pretalx/tasks/main.yml b/ansible-role/pretalx/tasks/main.yml
deleted file mode 100644
index 5179e95..0000000
--- a/ansible-role/pretalx/tasks/main.yml
+++ /dev/null
@@ -1,146 +0,0 @@
----
-- name: Ensures pretalx-config dir exists
- become: yes
- file:
- path: "{{ pretalx_cfg_dir }}"
- state: directory
- owner: "{{ pretalx_user }}"
- group: "{{ pretalx_group }}"
-
-- name: Adding pretalx.cfg file
- become: yes
- template:
- src: ../templates/pretalx.cfg.j2
- dest: "{{ pretalx_cfg_dir }}/pretalx.cfg"
- owner: "{{ pretalx_user }}"
- group: "{{ pretalx_group }}"
- mode: 0700
- register: pretalx_config_change
-
-- name: Create the pretalx network
- docker_network:
- name: pretalx
-
-- name: Create pretalx db volume
- docker_volume:
- name: pretalx_db
-
-- name: Create pretalx redis volume
- docker_volume:
- name: pretalx_redis
-
-- name: Create pretalx data volume
- docker_volume:
- name: pretalx_data
-
-- name: Create pretalx public volume
- docker_volume:
- name: pretalx_public
-
-- name: Create redis container
- docker_container:
- name: pretalx-redis
- image: redis:latest
- volumes:
- - pretalx_redis:/data
- networks:
- - name: pretalx
- purge_networks: yes
- labels:
- traefik.enable: "false"
-
-- name: Create db container
- docker_container:
- name: pretalx-db
- image: mysql:5
- volumes:
- - pretalx_db:/var/lib/mysql
- networks:
- - name: pretalx
- purge_networks: yes
- labels:
- traefik.enable: "false"
- env:
- MYSQL_DATABASE: "{{ db_name }}"
- MYSQL_USER: "{{ db_user }}"
- MYSQL_PASSWORD: "{{ db_pass }}"
- MYSQL_RANDOM_ROOT_PASSWORD: "1"
- register: pretalx_db_change
-
-- name: Wait for DB
- wait_for: timeout=30
- when: pretalx_db_change.changed == True
-
-
-
-- name: Create Pretalx container
- docker_container:
- name: pretalx
- image: maxrink/pretalx:docker-dev
- pull: yes
- restart_policy: unless-stopped
- volumes:
- - pretalx_data:/data
- - pretalx_public:/public
- - "{{ pretalx_cfg_dir }}/pretalx.cfg:/etc/pretalx/pretalx.cfg"
- networks:
- - name: web
- - name: pretalx
- labels:
- traefik.docker.network: "web"
- traefik.enable: "true"
- env:
- PRETALX_FILESYSTEM_MEDIA: /public/media
- PRETALX_FILESYSTEM_STATIC: /public/static
- purge_networks: yes
- register: pretalx_change
- when: not testsetup
-
-- name: Create Pretalx container
- docker_container:
- name: pretalx
- image: maxrink/pretalx:docker-dev
- pull: yes
- restart_policy: unless-stopped
- ports:
- - "80:80"
- volumes:
- - pretalx_data:/data
- - pretalx_public:/public
- - "{{ pretalx_cfg_dir }}/pretalx.cfg:/etc/pretalx/pretalx.cfg"
- networks:
- - name: web
- - name: pretalx
- labels:
- traefik.docker.network: "web"
- traefik.enable: "true"
- env:
- PRETALX_FILESYSTEM_MEDIA: /public/media
- PRETALX_FILESYSTEM_STATIC: /public/static
- purge_networks: yes
- register: pretalx_change
- when: testsetup
-
-- name: Create SMTP-Sink
- docker_container:
- name: pretalx-smtp-sink
- image: tecnativa/smtp-sink
- networks:
- - name: pretalx
- when: testsetup
-
-
-
-- name: Setup Cronjob for pretalx
- cron:
- name: "pretalx cron"
- job: "/usr/bin/docker exec pretalx pretalx cron"
-
-- name: Restart Pretalx on config pretalx_config_change
- docker_container:
- name: pretalx
- restart : yes
- when:
- - pretalx_config_change.changed == True
- - pretalx_change.changed == False
-
diff --git a/ansible-role/pretalx/templates/pretalx.cfg.j2 b/ansible-role/pretalx/templates/pretalx.cfg.j2
deleted file mode 100644
index be945e9..0000000
--- a/ansible-role/pretalx/templates/pretalx.cfg.j2
+++ /dev/null
@@ -1,42 +0,0 @@
-[filesystem]
-# use PRETALX_FILESYSTEM_* env vars
-
-[site]
-debug = {{ pretalx_debug }}
-url = https://{{ pretalx_url }}
-
-[database]
-backend = mysql
-name = {{ db_name }}
-user = {{ db_user }}
-password = {{ db_pass }}
-host = pretalx-db
-port = 3306
-
-[mail]
-from={{ pretalx_mailfrom }}
-host={{ pretalx_mailhost }}
-user={{ pretalx_mailuser }}
-password={{ pretalx_mailpass }}
-port={{ pretalx_mailport }}
-tls={{ pretalx_mailtls }}
-ssl={{ pretalx_mailssl }}
-
-
-[celery]
-backend = redis://pretalx-redis/1
-broker = redis://pretalx-redis/2
-
-[redis]
-location=redis://pretalx-redis/0
-; Remove the following line if you are unsure about your redis' security
-; to reduce impact if redis gets compromised.
-sessions=true
-
-[logging]
-email={{ pretalx_loggingmail }}
-email_level=ERROR
-
-[locale]
-language_code={{ pretalx_locale }}
-time_zone={{ pretalx_timezone }}
\ No newline at end of file
diff --git a/ansible-role/pretalx/vars/main.yml b/ansible-role/pretalx/vars/main.yml
deleted file mode 100644
index 9967d98..0000000
--- a/ansible-role/pretalx/vars/main.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-testsetup: True
-pretalx_user: 999
-pretalx_group: 999
-pretalx_cfg_dir: /docker-config/pretalx
-db_pass: verysecurepw
-db_user: pretalx
-db_name: pretalx
-pretalx_url: localhost
-pretalx_debug: True
-pretalx_loggingmail: pretalxlogs@yourdomain.com
-pretalx_locale: de
-pretalx_timezone: Europe/Berlin
-pretalx_mailfrom: pretalx@yourdomain.com
-pretalx_mailhost: pretalx-smtp-sink
-pretalx_mailuser: pretalx
-pretalx_mailpass: verysecurepw
-pretalx_mailport: 25
-pretalx_mailtls: off
-pretalx_mailssl: off
diff --git a/bin/build b/bin/build
new file mode 100755
index 0000000..72e01a2
--- /dev/null
+++ b/bin/build
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+set -euxo pipefail
+
+COMPOSE_DEFAULT_ARGS="-f compose.yml"
+
+BUILD_ENVS=(
+ "--env-file .env.build -f compose/build/base.yml"
+ "--env-file .env.build -f compose/build/default.yml"
+ "--env-file .env.build -f compose/build/extended.yml"
+ "--env-file .env.build -f compose/build/extended.cron.yml"
+)
+
+for env in "${BUILD_ENVS[@]}"
+do
+ docker compose ${COMPOSE_DEFAULT_ARGS} $env build app
+done
+
+set +x
+source .env.build
+
+BUILD_ARTIFACTS=(
+ "${PRETALX_BASE_IMAGE}"
+ "${PRETALX_IMAGE}"
+ "${PRETALX_EXTENDED_IMAGE}"
+)
+
+for artifact in "${BUILD_ARTIFACTS[@]}"
+do
+ docker image ls "${artifact/${artifact/\/*/}\/}"
+done
diff --git a/bin/build.source b/bin/build.source
new file mode 100755
index 0000000..bb5480b
--- /dev/null
+++ b/bin/build.source
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+source .env.build
+set -euxo pipefail
+
+COMPOSE_DEFAULT_ARGS="-f compose.yml"
+
+BUILD_ENVS=(
+ "--env-file .env.build -f compose/build/base.yml"
+ "--env-file .env.build -f compose/build/source/standalone.local.yml"
+ "--env-file .env.build -f compose/build/source/standalone.remote.yml"
+ "--env-file .env.build -f compose/build/source/standalone.extended.cron.remote.yml"
+ "--env-file .env.build -f compose/build/source/extended.cron.remote.yml"
+)
+
+PRETALX_STANDALONE_SOURCE_DIR=context/source/standalone/pretalx
+
+[ ! -d $PRETALX_STANDALONE_SOURCE_DIR ] && git clone --depth 1 -b $PRETALX_REF $PRETALX_REPO $PRETALX_STANDALONE_SOURCE_DIR
+
+for env in "${BUILD_ENVS[@]}"
+do
+ docker compose ${COMPOSE_DEFAULT_ARGS} $env build app
+done
+
+BUILD_ARTIFACTS=(
+ "${PRETALX_BASE_IMAGE}"
+ "${PRETALX_EXTENDED_IMAGE}"
+ "${PRETALX_STANDALONE_IMAGE}"
+ "${PRETALX_STANDALONE_EXTENDED_IMAGE}"
+)
+
+for artifact in "${BUILD_ARTIFACTS[@]}"
+do
+ docker image ls "${artifact/${artifact/\/*/}\/}"
+done
diff --git a/bin/build.standalone b/bin/build.standalone
new file mode 100755
index 0000000..d595fc7
--- /dev/null
+++ b/bin/build.standalone
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+set -euxo pipefail
+
+COMPOSE_DEFAULT_ARGS="-f compose.yml"
+
+BUILD_ENVS=(
+ "--env-file .env.build -f compose/build/default.yml"
+ "--env-file .env.build -f compose/build/standalone/default.yml"
+ "--env-file .env.build -f compose/build/standalone/extended.yml"
+ "--env-file .env.build -f compose/build/standalone/extended.cron.yml"
+)
+
+for env in "${BUILD_ENVS[@]}"
+do
+ docker compose ${COMPOSE_DEFAULT_ARGS} $env build app
+done
+
+set +x
+source .env.build
+
+BUILD_ARTIFACTS=(
+ "${PRETALX_IMAGE}"
+ "${PRETALX_STANDALONE_IMAGE}"
+ "${PRETALX_STANDALONE_EXTENDED_IMAGE}"
+)
+
+for artifact in "${BUILD_ARTIFACTS[@]}"
+do
+ docker image ls "${artifact/${artifact/\/*/}\/}"
+done
diff --git a/bin/clean b/bin/clean
new file mode 100755
index 0000000..c768c39
--- /dev/null
+++ b/bin/clean
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+set -euxo pipefail
+
+docker images | grep pretalx | awk '{ print $3 }' | xargs docker rmi -f
+
+## Use with caution
+# docker buildx prune -a
+
+PRETALX_STANDALONE_SOURCE_DIR=context/source/standalone/pretalx
+[ -d $PRETALX_STANDALONE_SOURCE_DIR ]; rm -rf $PRETALX_STANDALONE_SOURCE_DIR
diff --git a/compose.yml b/compose.yml
new file mode 100644
index 0000000..15eb929
--- /dev/null
+++ b/compose.yml
@@ -0,0 +1,184 @@
+volumes:
+ pretalx-public:
+ pretalx-data:
+ pretalx-postgres:
+ pretalx-redis:
+
+networks:
+ data:
+
+
+x-default: &default
+ networks:
+ - data
+ restart: unless-stopped
+
+x-healthcheck: &healthcheck
+ start_period: 10s
+ interval: 30s
+ retries: 5
+ timeout: 3s
+
+x-pretalx: &pretalx
+ <<: *default
+ image: ${PRETALX_IMAGE}:${PRETALX_TAG}
+ volumes:
+ - pretalx-data:/data
+ - pretalx-public:/public
+ environment:
+ - PRETALX_LOG_LEVEL
+
+ - PRETALX_DB_NAME
+ - PRETALX_DB_USER
+ - PRETALX_DB_PASS
+
+ - PRETALX_DATA_DIR
+ - PRETALX_FILESYSTEM_LOGS
+
+ - PRETALX_FILESYSTEM_MEDIA
+ - PRETALX_FILESYSTEM_STATIC
+
+ - PRETALX_DEBUG
+ - PRETALX_SITE_URL
+
+ - PRETALX_SITE_CSP
+ - PRETALX_SITE_CSP_STYLE
+ - PRETALX_SITE_CSP_SCRIPT
+ - PRETALX_SITE_CSP_IMG
+ - PRETALX_SITE_CSP_FORM
+
+ - PRETALX_DB_TYPE
+ - PRETALX_DB_HOST
+ - PRETALX_DB_PORT
+
+ - PRETALX_MAIL_FROM
+ - PRETALX_MAIL_HOST
+ - PRETALX_MAIL_PORT
+ - PRETALX_MAIL_USER
+ - PRETALX_MAIL_PASSWORD
+ - PRETALX_MAIL_TLS
+ - PRETALX_MAIL_SSL
+
+ - PRETALX_CELERY_BACKEND
+ - PRETALX_CELERY_BROKER
+
+ - PRETALX_REDIS
+ - PRETALX_REDIS_SESSIONS
+
+ - PRETALX_LOGGING_EMAIL
+ - PRETALX_LOGGING_EMAIL_LEVEL
+
+ - PRETALX_LANGUAGE_CODE
+ - PRETALX_TIME_ZONE
+
+x-pretalx-depends-on-databases: &pretalx-depends-on-databases
+ redis:
+ condition: service_healthy
+ postgres:
+ condition: service_healthy
+
+x-pretalx-depends-on-migrations: &pretalx-depends-on-migrations
+ <<: *pretalx-depends-on-databases
+ migrations:
+ condition: service_completed_successfully
+
+
+services:
+
+ web:
+ <<: *default
+ image: nginx:alpine
+
+ deploy:
+ replicas: 1
+
+ healthcheck:
+ test: ['CMD-SHELL', 'ash -c "[[ $(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:80) == \"200\" ]]" || exit 1']
+ <<: *healthcheck
+
+ depends_on:
+ app:
+ condition: service_healthy
+
+ volumes:
+ - type: bind
+ source: ./config/nginx.conf
+ target: /etc/nginx/nginx.conf
+ read_only: true
+ bind:
+ selinux: z
+ create_host_path: true
+ - pretalx-public:/public
+
+
+ app:
+ <<: *pretalx
+ command: gunicorn
+
+ deploy:
+ replicas: 1
+
+ healthcheck:
+ test: ['CMD-SHELL', 'bash -c "[[ $(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:8080) == \"200\" ]]" || exit 1']
+ <<: *healthcheck
+
+ depends_on: *pretalx-depends-on-migrations
+
+ worker:
+ <<: *pretalx
+ command: celery
+
+ deploy:
+ replicas: 1
+
+ healthcheck:
+ test: ['CMD-SHELL', 'bash -c "[[ \"$(pgrep celery)\" != \"\" ]]" || exit 1']
+ <<: *healthcheck
+
+ depends_on: *pretalx-depends-on-migrations
+
+ cron:
+ <<: *pretalx
+ command: cron
+ user: root
+ init: true
+
+ healthcheck:
+ test: ['CMD-SHELL', 'bash -c "[[ \"$(pgrep cron)\" != \"\" ]]" || exit 1']
+ <<: *healthcheck
+
+ depends_on: *pretalx-depends-on-migrations
+
+ migrations:
+ <<: *pretalx
+ command: migrate
+ restart: no
+
+ depends_on: *pretalx-depends-on-databases
+
+
+ postgres:
+ <<: *default
+ image: docker.io/library/postgres:15-alpine
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
+ start_period: 20s
+ interval: 30s
+ retries: 5
+ timeout: 5s
+ volumes:
+ - pretalx-postgres:/var/lib/postgresql/data
+ environment:
+ - POSTGRES_PASSWORD
+ - POSTGRES_USER
+ - POSTGRES_DB
+
+ redis:
+ <<: *default
+ image: docker.io/library/redis:alpine
+ command: --save 60 1 --loglevel warning
+ healthcheck:
+ test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
+ <<: *healthcheck
+ volumes:
+ - pretalx-redis:/data
diff --git a/compose/build/base.yml b/compose/build/base.yml
new file mode 100644
index 0000000..6d3a659
--- /dev/null
+++ b/compose/build/base.yml
@@ -0,0 +1,12 @@
+services:
+ app: &build-base
+ image: ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+ build:
+ context: ./context/base
+ dockerfile: Dockerfile.debian
+ args:
+ BASE_IMAGE: ${BASE_IMAGE}
+ BASE_TAG: ${BASE_TAG}
+ worker: *build-base
+ cron: *build-base
+ migrations: *build-base
diff --git a/compose/build/default.yml b/compose/build/default.yml
new file mode 100644
index 0000000..790d733
--- /dev/null
+++ b/compose/build/default.yml
@@ -0,0 +1,12 @@
+services:
+ app: &build-default
+ build:
+ context: ./context/default
+ dockerfile: Dockerfile.debian
+ args:
+ BASE_IMAGE: ${PRETALX_BASE_IMAGE}
+ BASE_TAG: ${PRETALX_BASE_TAG}
+ PRETALX_VERSION: ${PRETALX_VERSION}
+ worker: *build-default
+ cron: *build-default
+ migrations: *build-default
diff --git a/compose/build/extended.cron.yml b/compose/build/extended.cron.yml
new file mode 100644
index 0000000..b40b3c9
--- /dev/null
+++ b/compose/build/extended.cron.yml
@@ -0,0 +1,12 @@
+services:
+ app: &build-extended-cron
+ image: ${PRETALX_EXTENDED_CRON_IMAGE}:${PRETALX_EXTENDED_CRON_TAG}
+ build:
+ context: ./context/cron
+ dockerfile: Dockerfile.debian
+ args:
+ PRETALX_BASE_IMAGE: ${PRETALX_EXTENDED_CRON_BASE_IMAGE}
+ PRETALX_BASE_TAG: ${PRETALX_EXTENDED_CRON_BASE_TAG}
+ worker: *build-extended-cron
+ cron: *build-extended-cron
+ migrations: *build-extended-cron
diff --git a/compose/build/extended.yml b/compose/build/extended.yml
new file mode 100644
index 0000000..32fd14b
--- /dev/null
+++ b/compose/build/extended.yml
@@ -0,0 +1,12 @@
+services:
+ app: &build-extended
+ image: ${PRETALX_EXTENDED_IMAGE}:${PRETALX_EXTENDED_TAG}
+ build:
+ context: ./context/extended
+ dockerfile: Dockerfile.debian
+ args:
+ PRETALX_BASE_IMAGE: ${PRETALX_EXTENDED_BASE_IMAGE}
+ PRETALX_BASE_TAG: ${PRETALX_EXTENDED_BASE_TAG}
+ worker: *build-extended
+ cron: *build-extended
+ migrations: *build-extended
diff --git a/compose/build/source/extended.cron.remote.yml b/compose/build/source/extended.cron.remote.yml
new file mode 100644
index 0000000..951162e
--- /dev/null
+++ b/compose/build/source/extended.cron.remote.yml
@@ -0,0 +1,14 @@
+services:
+ app: &build-extended
+ image: ${PRETALX_SOURCE_EXTENDED_CRON_IMAGE}:${PRETALX_SOURCE_EXTENDED_CRON_TAG}
+ build:
+ context: ./context/source/extended.cron
+ dockerfile: Dockerfile.debian.remote
+ args:
+ PRETALX_BASE_IMAGE: ${PRETALX_BASE_IMAGE}
+ PRETALX_BASE_TAG: ${PRETALX_BASE_TAG}
+ PRETALX_REPO: ${PRETALX_REPO}
+ PRETALX_REF: ${PRETALX_REF}
+ worker: *build-extended
+ cron: *build-extended
+ migrations: *build-extended
diff --git a/compose/build/source/standalone.extended.cron.remote.yml b/compose/build/source/standalone.extended.cron.remote.yml
new file mode 100644
index 0000000..da73dc2
--- /dev/null
+++ b/compose/build/source/standalone.extended.cron.remote.yml
@@ -0,0 +1,24 @@
+services:
+ app: &build-standalone-extended-cron
+ image: ${PRETALX_SOURCE_STANDALONE_EXTENDED_CRON_IMAGE}:${PRETALX_SOURCE_STANDALONE_EXTENDED_CRON_TAG}
+ build:
+ context: ./context/source/standalone.extended.cron
+ dockerfile: Dockerfile.debian.remote
+ args:
+ PRETALX_BASE_IMAGE: ${PRETALX_SOURCE_STANDALONE_EXTENDED_CRON_BASE_IMAGE}
+ PRETALX_BASE_TAG: ${PRETALX_SOURCE_STANDALONE_EXTENDED_CRON_BASE_TAG}
+ command: supervisor
+ # volumes:
+ # - ./config/pretalx.cfg:/pretalx/.pretalx.cfg
+ worker:
+ <<: *build-standalone-extended-cron
+ deploy:
+ replicas: 0
+ cron:
+ <<: *build-standalone-extended-cron
+ deploy:
+ replicas: 0
+ migrations:
+ <<: *build-standalone-extended-cron
+ deploy:
+ replicas: 0
diff --git a/compose/build/source/standalone.local.yml b/compose/build/source/standalone.local.yml
new file mode 100644
index 0000000..d9203c0
--- /dev/null
+++ b/compose/build/source/standalone.local.yml
@@ -0,0 +1,31 @@
+services:
+ app: &build-standalone-local
+ image: ${PRETALX_SOURCE_STANDALONE_IMAGE}:${PRETALX_SOURCE_STANDALONE_LOCAL_TAG}
+ build:
+ context: ./context/source/standalone
+ dockerfile: Dockerfile.debian.local
+ args:
+ PRETALX_BASE_IMAGE: ${PRETALX_STANDALONE_BASE_IMAGE}
+ PRETALX_BASE_TAG: ${PRETALX_STANDALONE_BASE_TAG}
+ volumes:
+ # The prior submodule has been depreciated. Work from an independent clone, e.g.:
+ # git clone https://github.com/pretalx/pretalx.git ./context/source.standalone/pretalx
+ - ./context/source/local.standalone/pretalx/pyproject.toml:/pretalx/pyproject.toml
+ - ./context/source/local.standalone/pretalx/src:/pretalx/src
+ # We map the Pretalx source code into the container for convenience.
+ # All sorts of things become possible, e.g. live reloading during development
+ # of the repository at ./context/source/pretalx in the container.
+ # Make sure to apply all necessary life cycle commands, such as
+ # migrate, rebuild, regenerate_css et al.
+ worker:
+ <<: *build-standalone-local
+ deploy:
+ replicas: 0
+ cron:
+ <<: *build-standalone-local
+ deploy:
+ replicas: 0
+ migrations:
+ <<: *build-standalone-local
+ deploy:
+ replicas: 0
diff --git a/compose/build/source/standalone.remote.yml b/compose/build/source/standalone.remote.yml
new file mode 100644
index 0000000..779c0a3
--- /dev/null
+++ b/compose/build/source/standalone.remote.yml
@@ -0,0 +1,23 @@
+services:
+ app: &build-standalone-remote
+ image: ${PRETALX_SOURCE_STANDALONE_IMAGE}:${PRETALX_SOURCE_STANDALONE_REMOTE_TAG}
+ build:
+ context: ./context/source/standalone
+ dockerfile: Dockerfile.debian.remote
+ args:
+ PRETALX_BASE_IMAGE: ${PRETALX_STANDALONE_BASE_IMAGE}
+ PRETALX_BASE_TAG: ${PRETALX_STANDALONE_BASE_TAG}
+ PRETALX_REPO: ${PRETALX_REPO}
+ PRETALX_REF: ${PRETALX_REF}
+ worker:
+ <<: *build-standalone-remote
+ deploy:
+ replicas: 0
+ cron:
+ <<: *build-standalone-remote
+ deploy:
+ replicas: 0
+ migrations:
+ <<: *build-standalone-remote
+ deploy:
+ replicas: 0
diff --git a/compose/build/standalone/default.yml b/compose/build/standalone/default.yml
new file mode 100644
index 0000000..8ab528f
--- /dev/null
+++ b/compose/build/standalone/default.yml
@@ -0,0 +1,12 @@
+services:
+ app: &build-standalone
+ image: ${PRETALX_STANDALONE_IMAGE}:${PRETALX_STANDALONE_TAG}
+ build:
+ context: ./context/standalone/default
+ dockerfile: Dockerfile.debian
+ args:
+ PRETALX_BASE_IMAGE: ${PRETALX_STANDALONE_BASE_IMAGE}
+ PRETALX_BASE_TAG: ${PRETALX_STANDALONE_BASE_TAG}
+ worker: *build-standalone
+ cron: *build-standalone
+ migrations: *build-standalone
diff --git a/compose/build/standalone/extended.cron.yml b/compose/build/standalone/extended.cron.yml
new file mode 100644
index 0000000..e1215a1
--- /dev/null
+++ b/compose/build/standalone/extended.cron.yml
@@ -0,0 +1,12 @@
+services:
+ app: &build-standalone-extended-cron
+ image: ${PRETALX_STANDALONE_EXTENDED_CRON_IMAGE}:${PRETALX_STANDALONE_EXTENDED_CRON_TAG}
+ build:
+ context: ./context/standalone/extended.cron
+ dockerfile: Dockerfile.debian
+ args:
+ PRETALX_BASE_IMAGE: ${PRETALX_STANDALONE_EXTENDED_CRON_BASE_IMAGE}
+ PRETALX_BASE_TAG: ${PRETALX_STANDALONE_EXTENDED_CRON_BASE_TAG}
+ worker: *build-standalone-extended-cron
+ cron: *build-standalone-extended-cron
+ migrations: *build-standalone-extended-cron
diff --git a/compose/build/standalone/extended.yml b/compose/build/standalone/extended.yml
new file mode 100644
index 0000000..d326efe
--- /dev/null
+++ b/compose/build/standalone/extended.yml
@@ -0,0 +1,12 @@
+services:
+ app: &build-standalone-extended
+ image: ${PRETALX_STANDALONE_EXTENDED_IMAGE}:${PRETALX_STANDALONE_EXTENDED_TAG}
+ build:
+ context: ./context/standalone/extended
+ dockerfile: Dockerfile.debian
+ args:
+ PRETALX_BASE_IMAGE: ${PRETALX_STANDALONE_EXTENDED_BASE_IMAGE}
+ PRETALX_BASE_TAG: ${PRETALX_STANDALONE_EXTENDED_BASE_TAG}
+ worker: *build-standalone-extended
+ cron: *build-standalone-extended
+ migrations: *build-standalone-extended
diff --git a/compose/local.yml b/compose/local.yml
new file mode 100644
index 0000000..7bafd3b
--- /dev/null
+++ b/compose/local.yml
@@ -0,0 +1,11 @@
+services:
+ web:
+ ports:
+ - 8080:80
+# app: &local-default
+# volumes:
+# - ./context/default/entrypoint.sh:/pretalx/entrypoint.sh:z
+# - ./config/pretalx.cfg:/pretalx/.pretalx.cfg:z
+# worker: *local-default
+# cron: *local-default
+# migrations: *local-default
diff --git a/compose/traefik.yml b/compose/traefik.yml
new file mode 100644
index 0000000..c9c45f8
--- /dev/null
+++ b/compose/traefik.yml
@@ -0,0 +1,13 @@
+networks:
+ web:
+ external: true
+
+services:
+ web:
+ networks:
+ - web
+ labels:
+ traefik.enable: true
+ traefik.http.routers.local-localhost.rule: Host(`${FQDN}`)
+ traefik.http.routers.local-localhost.tls: true
+ traefik.http.routers.local-localhost.tls.certresolver: letsencrypt
diff --git a/config/nginx.conf b/config/nginx.conf
new file mode 100644
index 0000000..29e00f9
--- /dev/null
+++ b/config/nginx.conf
@@ -0,0 +1,53 @@
+events {
+ worker_connections 768;
+}
+
+http {
+ server_tokens off;
+ sendfile on;
+ charset utf-8;
+ tcp_nopush on;
+ tcp_nodelay on;
+ client_max_body_size 0;
+
+ log_format private '[$time_local] $host "$request" $status $body_bytes_sent';
+
+ types_hash_max_size 2048;
+ server_names_hash_bucket_size 64;
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+ add_header X-Content-Type-Options nosniff;
+
+ access_log /var/log/nginx/access.log private;
+ error_log /var/log/nginx/error.log;
+ add_header Referrer-Policy same-origin;
+
+ gzip off;
+
+ server {
+ listen 80;
+
+ index index.html;
+ root /public;
+
+ location /media {
+ expires 7d;
+ access_log off;
+ }
+
+ location /static {
+ access_log off;
+ expires 365d;
+ add_header Cache-Control "public";
+ }
+
+ location / {
+ 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 https;
+
+ proxy_pass http://app:8080;
+ }
+ }
+}
diff --git a/conf/pretalx.cfg b/config/pretalx.cfg.example
similarity index 69%
rename from conf/pretalx.cfg
rename to config/pretalx.cfg.example
index 044ab12..528de43 100644
--- a/conf/pretalx.cfg
+++ b/config/pretalx.cfg.example
@@ -5,32 +5,32 @@
; never run debug in production. Make sure you serve all requests for the
; `/static/` and `/media/` paths when debug is False.
; See [installation](https://docs.pretalx.org/administrator/installation/#step-7-ssl) for more information
-debug = True
-url = http://localhost
+debug = False
+url = http://localhost:8080
[database]
-backend = mysql
+backend = postgresql
name = pretalx
user = pretalx
password = veryunsecureplschange
-host = pretalx-db
-port = 3306
+host = postgres
+port = 5432
-[mail]
-from = some@email.address
-host = smtp
-port = 25
+#[mail]
+#from = some@email.address
+#host = smtp
+#port = 25
#user = admin
#password = something
#tls = False
#ssl = True
[celery]
-backend = redis://pretalx-redis/1
-broker = redis://pretalx-redis/2
+backend = redis://redis/1
+broker = redis://redis/2
[redis]
-location=redis://pretalx-redis/0
+location=redis://redis/0
; Remove the following line if you are unsure about your redis' security
; to reduce impact if redis gets compromised.
-sessions=true
+sessions = true
diff --git a/context/base/Dockerfile.debian b/context/base/Dockerfile.debian
new file mode 100644
index 0000000..51c6931
--- /dev/null
+++ b/context/base/Dockerfile.debian
@@ -0,0 +1,59 @@
+ARG BASE_IMAGE=docker.io/library/python
+ARG BASE_TAG=3.12-bookworm
+
+
+FROM ${BASE_IMAGE}:${BASE_TAG}
+
+# Install system dependencies
+RUN apt update && \
+ apt install -y \
+ git \
+ gettext \
+ libmariadb-dev \
+ libpq-dev \
+ locales \
+ libmemcached-dev \
+ locales \
+ nodejs \
+ npm \
+ --no-install-recommends && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/* && \
+ dpkg-reconfigure locales && \
+ locale-gen C.UTF-8 && \
+ /usr/sbin/update-locale LANG=C.UTF-8 \
+ npm i -g npm
+
+ENV LC_ALL=C.UTF-8
+
+# Add unprivileged user with home directory /pretalx
+RUN groupadd -g 999 pretalx && \
+ useradd -r -u 999 -g pretalx -d /pretalx -ms /bin/bash pretalx
+
+# Add directories for volumes
+RUN mkdir -p /data /public && \
+ chown -R 999:999 /data /public
+
+COPY --chown=999 --chmod=755 entrypoint.sh /pretalx/entrypoint.sh
+
+
+# Switch to unprivileged user
+USER pretalx
+WORKDIR /pretalx
+
+# Provide PIP with a correct path to install binaries
+RUN mkdir -p /pretalx/.local/bin
+ENV PATH="/pretalx/.local/bin:${PATH}"
+
+# Install build and runtime dependencies
+RUN pip3 install -U --user pip \
+ setuptools \
+ wheel \
+ typing \
+ pylibmc \
+ gunicorn
+
+# Shared resources used
+VOLUME ["/data", "/public"]
+ENTRYPOINT ["/pretalx/entrypoint.sh"]
+EXPOSE 8080
diff --git a/context/base/entrypoint.sh b/context/base/entrypoint.sh
new file mode 100755
index 0000000..1561680
--- /dev/null
+++ b/context/base/entrypoint.sh
@@ -0,0 +1,79 @@
+#!/usr/bin/env bash
+
+export PRETALX_DATA_DIR="${PRETALX_DATA_DIR:-/data}"
+
+PRETALX_FILESYSTEM_LOGS="${PRETALX_FILESYSTEM_LOGS:-/data/logs}"
+PRETALX_FILESYSTEM_MEDIA="${PRETALX_FILESYSTEM_MEDIA:-/data/media}"
+PRETALX_FILESYSTEM_STATIC="${PRETALX_FILESYSTEM_STATIC:-/data/static}"
+
+GUNICORN_WORKERS="${GUNICORN_WORKERS:-${WEB_CONCURRENCY:-4}}"
+GUNICORN_MAX_REQUESTS="${GUNICORN_MAX_REQUESTS:-1200}"
+GUNICORN_MAX_REQUESTS_JITTER="${GUNICORN_MAX_REQUESTS_JITTER:-50}"
+GUNICORN_FORWARDED_ALLOW_IPS="${GUNICORN_FORWARDED_ALLOW_IPS:-127.0.0.1}"
+GUNICORN_BIND_ADDR="${GUNICORN_BIND_ADDR:-0.0.0.0:8080}"
+
+if [ "$PRETALX_FILESYSTEM_LOGS" != "/data/logs" ]; then
+ export PRETALX_FILESYSTEM_LOGS
+fi
+if [ "$PRETALX_FILESYSTEM_MEDIA" != "/data/media" ]; then
+ export PRETALX_FILESYSTEM_MEDIA
+fi
+if [ "$PRETALX_FILESYSTEM_STATIC" != "/data/static" ]; then
+ export PRETALX_FILESYSTEM_STATIC
+fi
+
+if [ ! -d "$PRETALX_FILESYSTEM_LOGS" ]; then
+ mkdir -p "$PRETALX_FILESYSTEM_LOGS";
+fi
+if [ ! -d "$PRETALX_FILESYSTEM_MEDIA" ]; then
+ mkdir -p "$PRETALX_FILESYSTEM_MEDIA";
+fi
+if [ ! -d "$PRETALX_FILESYSTEM_STATIC" ]; then
+ mkdir -p "$PRETALX_FILESYSTEM_STATIC"
+fi
+
+case "${1}" in
+ # maintenance commands
+ migrate)
+ python3 -m pretalx migrate --noinput
+ ${0} rebuild
+ ;;
+ rebuild)
+ if [ ! -f "$PRETALX_FILESYSTEM_STATIC"/.built ] || [ "${2}" == "--force" ]; then
+ echo "Running one-time build of static assets."
+ python3 -m pretalx rebuild
+ touch "$PRETALX_FILESYSTEM_STATIC/.built"
+ fi
+ ;;
+ upgrade)
+ ${0} rebuild
+ python3 -m pretalx regenerate_css
+ ;;
+
+ # default web and task workers
+ gunicorn)
+ exec gunicorn pretalx.wsgi \
+ --name pretalx \
+ --workers "${GUNICORN_WORKERS}" \
+ --max-requests "${GUNICORN_MAX_REQUESTS}" \
+ --max-requests-jitter "${GUNICORN_MAX_REQUESTS_JITTER}" \
+ --forwarded-allow-ips "${GUNICORN_FORWARDED_ALLOW_IPS}" \
+ --log-level=${PRETALX_LOG_LEVEL} \
+ --bind="${GUNICORN_BIND_ADDR}"
+ ;;
+ celery)
+ exec celery -A pretalx.celery_app worker -l ${PRETALX_LOG_LEVEL}
+ ;;
+
+ # for use with the cron base image
+ cron)
+ exec cron -f -L 15
+ ;;
+ # for use with the standalone image variant
+ supervisor)
+ ${0} migrate
+ exec sudo -E /usr/bin/supervisord -n -c /etc/supervisord.conf
+ ;;
+ *)
+ python3 -m pretalx "$@"
+esac
diff --git a/context/cron/Dockerfile.debian b/context/cron/Dockerfile.debian
new file mode 100644
index 0000000..47b9e0f
--- /dev/null
+++ b/context/cron/Dockerfile.debian
@@ -0,0 +1,21 @@
+
+ARG PRETALX_BASE_IMAGE=docker.io/library/pretalx/pretalx
+ARG PRETALX_BASE_TAG=2024.1.0
+
+
+FROM ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+USER root
+
+# Install cron
+RUN apt update && \
+ apt install -y \
+ cron \
+ --no-install-recommends && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# Provide and enable crontab
+COPY --chown=0 --chmod=644 crontab /etc/crontab
+RUN crontab /etc/crontab
+
+USER pretalx
diff --git a/context/cron/crontab b/context/cron/crontab
new file mode 100644
index 0000000..76ffbde
--- /dev/null
+++ b/context/cron/crontab
@@ -0,0 +1,2 @@
+*/15 * * * * su pretalx -c 'python -m pretalx runperiodic' > /proc/1/fd/1 2> /proc/1/fd/2
+0 4 1 * * su pretalx -c 'python -m pretalx clearsessions' > /proc/1/fd/1 2> /proc/1/fd/2
diff --git a/context/default/Dockerfile.debian b/context/default/Dockerfile.debian
new file mode 100644
index 0000000..d3f3ca1
--- /dev/null
+++ b/context/default/Dockerfile.debian
@@ -0,0 +1,10 @@
+ARG BASE_IMAGE=docker.io/pretalx/base
+ARG BASE_TAG=3.12-bookworm
+
+FROM ${BASE_IMAGE}:${BASE_TAG}
+
+# Set pretalx version
+ARG PRETALX_VERSION=2024.1.0
+
+# Install Pretalx with Postgres and Redis database adapters
+RUN pip3 install -U --user pretalx[mysql,postgres,redis]==${PRETALX_VERSION}
diff --git a/context/extended/Dockerfile.debian b/context/extended/Dockerfile.debian
new file mode 100644
index 0000000..6b86e4a
--- /dev/null
+++ b/context/extended/Dockerfile.debian
@@ -0,0 +1,7 @@
+ARG PRETALX_BASE_IMAGE=docker.io/library/pretalx/pretalx
+ARG PRETALX_BASE_TAG=2024.1.0
+
+FROM ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+RUN pip3 install -U --user prtx-faq \
+ pretalx-pages \
+ pretalx-public-voting
diff --git a/context/source/extended.cron/Dockerfile.debian.remote b/context/source/extended.cron/Dockerfile.debian.remote
new file mode 100644
index 0000000..4de7024
--- /dev/null
+++ b/context/source/extended.cron/Dockerfile.debian.remote
@@ -0,0 +1,29 @@
+
+ARG PRETALX_BASE_IMAGE=docker.io/library/pretalx/pretalx
+ARG PRETALX_BASE_TAG=2024.1.0
+
+FROM ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+
+ARG PRETALX_REPO=https://github.com/pretalx/pretalx.git
+ARG PRETALX_REF=main
+RUN pip3 install --user git+${PRETALX_REPO}@${PRETALX_REF}#egg=pretalx[mysql,postgres,redis]
+
+RUN pip3 install --user git+https://github.com/pretalx/prtx-faq.git@master#egg=prtx-faq \
+ git+https://github.com/pretalx/pretalx-pages.git@main#egg=pretalx-pages \
+ git+https://github.com/pretalx/pretalx-public-voting.git@main#egg=pretalx-public-voting
+
+USER root
+
+# Install cron
+RUN apt update && \
+ apt install -y \
+ cron \
+ --no-install-recommends && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# Provide and enable crontab
+COPY --chown=0 --chmod=644 crontab /etc/crontab
+RUN crontab /etc/crontab
+
+USER pretalx
diff --git a/context/source/extended.cron/crontab b/context/source/extended.cron/crontab
new file mode 100644
index 0000000..76ffbde
--- /dev/null
+++ b/context/source/extended.cron/crontab
@@ -0,0 +1,2 @@
+*/15 * * * * su pretalx -c 'python -m pretalx runperiodic' > /proc/1/fd/1 2> /proc/1/fd/2
+0 4 1 * * su pretalx -c 'python -m pretalx clearsessions' > /proc/1/fd/1 2> /proc/1/fd/2
diff --git a/context/source/standalone.extended.cron/Dockerfile.debian.remote b/context/source/standalone.extended.cron/Dockerfile.debian.remote
new file mode 100644
index 0000000..d1504f4
--- /dev/null
+++ b/context/source/standalone.extended.cron/Dockerfile.debian.remote
@@ -0,0 +1,23 @@
+ARG PRETALX_BASE_IMAGE=pretalx/standalone
+ARG PRETALX_BASE_TAG=2024.1.0-source-remote
+
+FROM ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+
+USER pretalx
+RUN pip3 install --user git+https://github.com/pretalx/prtx-faq.git@master#egg=prtx-faq \
+ git+https://github.com/pretalx/pretalx-pages.git@main#egg=pretalx-pages \
+ git+https://github.com/pretalx/pretalx-public-voting.git@main#egg=pretalx-public-voting
+
+USER root
+RUN apt update && \
+ apt install -y \
+ cron \
+ --no-install-recommends && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/* && \
+ echo 'pretalx ALL=(ALL) NOPASSWD:SETENV: /usr/bin/supervisord' >> /etc/sudoers
+
+COPY --chown=0 --chmod=644 crontab /etc/crontab
+RUN crontab /etc/crontab
+
+COPY --chown=0 --chmod=644 supervisord.conf /etc/supervisord.conf
diff --git a/context/source/standalone.extended.cron/crontab b/context/source/standalone.extended.cron/crontab
new file mode 100644
index 0000000..05adaa9
--- /dev/null
+++ b/context/source/standalone.extended.cron/crontab
@@ -0,0 +1,2 @@
+*/15 * * * * su pretalx -c 'python -m pretalx runperiodic' > /dev/stdout 2>&1
+0 4 1 * * su pretalx -c 'python -m pretalx clearsessions' > /dev/stdout 2>&1
diff --git a/context/source/standalone.extended.cron/supervisord.conf b/context/source/standalone.extended.cron/supervisord.conf
new file mode 100644
index 0000000..ea0e40a
--- /dev/null
+++ b/context/source/standalone.extended.cron/supervisord.conf
@@ -0,0 +1,51 @@
+[unix_http_server]
+file=/tmp/supervisor.sock
+
+[supervisord]
+logfile=/tmp/supervisord.log
+logfile_maxbytes=50MB
+logfile_backups=10
+loglevel=info
+pidfile=/tmp/supervisord.pid
+nodaemon=false
+minfds=1024
+minprocs=200
+
+[rpcinterface:supervisor]
+supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
+
+[supervisorctl]
+serverurl=unix:///tmp/supervisor.sock
+
+[program:web]
+command=/pretalx/entrypoint.sh gunicorn
+autostart=true
+autorestart=true
+priority=5
+user=pretalx
+environment=HOME="/pretalx",PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
+
+[program:worker]
+command=/pretalx/entrypoint.sh celery
+autostart=true
+autorestart=true
+priority=5
+user=pretalx
+environment=HOME="/pretalx",PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
+
+[program:cron]
+command=/pretalx/entrypoint.sh cron
+environment=PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+autostart=true
+autorestart=true
+priority=5
+user=root
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
diff --git a/context/source/standalone/Dockerfile.debian.local b/context/source/standalone/Dockerfile.debian.local
new file mode 100644
index 0000000..0cbc392
--- /dev/null
+++ b/context/source/standalone/Dockerfile.debian.local
@@ -0,0 +1,24 @@
+ARG PRETALX_BASE_IMAGE=pretalx/base
+ARG PRETALX_BASE_TAG=3.12-bookworm
+
+FROM ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+
+COPY --chown=999 pretalx/pyproject.toml /pretalx
+COPY --chown=999 pretalx/src /pretalx/src
+
+RUN pip3 install --user -e /pretalx/[mysql,postgres,redis]
+
+USER root
+# Install supervisor
+RUN apt update && \
+ apt install -y \
+ supervisor \
+ --no-install-recommends && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/* && \
+ echo 'pretalx ALL=(ALL) NOPASSWD:SETENV: /usr/bin/supervisord' >> /etc/sudoers
+
+# Provide and enable supervisor configuration
+COPY --chown=0 --chmod=644 supervisord.conf /etc/supervisord.conf
+
+CMD ["supervisor"]
diff --git a/context/source/standalone/Dockerfile.debian.remote b/context/source/standalone/Dockerfile.debian.remote
new file mode 100644
index 0000000..f4fb074
--- /dev/null
+++ b/context/source/standalone/Dockerfile.debian.remote
@@ -0,0 +1,25 @@
+ARG PRETALX_BASE_IMAGE=pretalx/base
+ARG PRETALX_BASE_TAG=3.12-bookworm
+
+FROM ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+
+ARG PRETALX_REPO=https://github.com/pretalx/pretalx.git
+ARG PRETALX_REF=main
+
+RUN pip3 install --user git+${PRETALX_REPO}@${PRETALX_REF}#egg=pretalx[mysql,postgres,redis]
+
+USER root
+# Install supervisor
+RUN apt update && \
+ apt install -y \
+ sudo \
+ supervisor \
+ --no-install-recommends && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/* && \
+ echo 'pretalx ALL=(ALL) NOPASSWD:SETENV: /usr/bin/supervisord' >> /etc/sudoers
+
+# Provide and enable supervisor configuration
+COPY --chown=0 --chmod=644 supervisord.conf /etc/supervisord.conf
+
+CMD ["supervisor"]
diff --git a/context/source/standalone/supervisord.conf b/context/source/standalone/supervisord.conf
new file mode 100644
index 0000000..c0874ce
--- /dev/null
+++ b/context/source/standalone/supervisord.conf
@@ -0,0 +1,40 @@
+[unix_http_server]
+file=/tmp/supervisor.sock
+
+[supervisord]
+logfile=/tmp/supervisord.log
+logfile_maxbytes=50MB
+logfile_backups=10
+loglevel=info
+pidfile=/tmp/supervisord.pid
+nodaemon=false
+minfds=1024
+minprocs=200
+
+[rpcinterface:supervisor]
+supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
+
+[supervisorctl]
+serverurl=unix:///tmp/supervisor.sock
+
+[program:web]
+command=/pretalx/entrypoint.sh gunicorn
+autostart=true
+autorestart=true
+priority=5
+user=pretalx
+environment=HOME="/pretalx",PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
+
+[program:worker]
+command=/pretalx/entrypoint.sh celery
+autostart=true
+autorestart=true
+priority=5
+user=pretalx
+environment=HOME="/pretalx",PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
diff --git a/context/standalone/default/Dockerfile.debian b/context/standalone/default/Dockerfile.debian
new file mode 100644
index 0000000..b08419d
--- /dev/null
+++ b/context/standalone/default/Dockerfile.debian
@@ -0,0 +1,20 @@
+ARG PRETALX_BASE_IMAGE=docker.io/pretalx/pretalx
+ARG PRETALX_BASE_TAG=2024.1.0
+
+FROM ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+
+USER root
+# Install supervisor
+RUN apt update && \
+ apt install -y \
+ sudo \
+ supervisor \
+ --no-install-recommends && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/* && \
+ echo 'pretalx ALL=(ALL) NOPASSWD:SETENV: /usr/bin/supervisord' >> /etc/sudoers
+
+# Provide and enable supervisor configuration
+COPY --chown=0 --chmod=644 supervisord.conf /etc/supervisord.conf
+
+CMD ["supervisor"]
diff --git a/context/standalone/default/supervisord.conf b/context/standalone/default/supervisord.conf
new file mode 100644
index 0000000..c0874ce
--- /dev/null
+++ b/context/standalone/default/supervisord.conf
@@ -0,0 +1,40 @@
+[unix_http_server]
+file=/tmp/supervisor.sock
+
+[supervisord]
+logfile=/tmp/supervisord.log
+logfile_maxbytes=50MB
+logfile_backups=10
+loglevel=info
+pidfile=/tmp/supervisord.pid
+nodaemon=false
+minfds=1024
+minprocs=200
+
+[rpcinterface:supervisor]
+supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
+
+[supervisorctl]
+serverurl=unix:///tmp/supervisor.sock
+
+[program:web]
+command=/pretalx/entrypoint.sh gunicorn
+autostart=true
+autorestart=true
+priority=5
+user=pretalx
+environment=HOME="/pretalx",PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
+
+[program:worker]
+command=/pretalx/entrypoint.sh celery
+autostart=true
+autorestart=true
+priority=5
+user=pretalx
+environment=HOME="/pretalx",PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
diff --git a/context/standalone/extended.cron/Dockerfile.debian b/context/standalone/extended.cron/Dockerfile.debian
new file mode 100644
index 0000000..7ac7520
--- /dev/null
+++ b/context/standalone/extended.cron/Dockerfile.debian
@@ -0,0 +1,16 @@
+ARG PRETALX_BASE_IMAGE=pretalx/standalone-extended
+ARG PRETALX_BASE_TAG=2024.2.1
+
+FROM ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+
+RUN apt update && \
+ apt install -y \
+ cron \
+ --no-install-recommends && \
+ apt clean && \
+ rm -rf /var/lib/apt/lists/*
+
+COPY --chown=0 --chmod=644 crontab /etc/crontab
+RUN crontab /etc/crontab
+
+COPY --chown=0 --chmod=644 supervisord.conf /etc/supervisord.conf
diff --git a/context/standalone/extended.cron/crontab b/context/standalone/extended.cron/crontab
new file mode 100644
index 0000000..05adaa9
--- /dev/null
+++ b/context/standalone/extended.cron/crontab
@@ -0,0 +1,2 @@
+*/15 * * * * su pretalx -c 'python -m pretalx runperiodic' > /dev/stdout 2>&1
+0 4 1 * * su pretalx -c 'python -m pretalx clearsessions' > /dev/stdout 2>&1
diff --git a/context/standalone/extended.cron/supervisord.conf b/context/standalone/extended.cron/supervisord.conf
new file mode 100644
index 0000000..ea0e40a
--- /dev/null
+++ b/context/standalone/extended.cron/supervisord.conf
@@ -0,0 +1,51 @@
+[unix_http_server]
+file=/tmp/supervisor.sock
+
+[supervisord]
+logfile=/tmp/supervisord.log
+logfile_maxbytes=50MB
+logfile_backups=10
+loglevel=info
+pidfile=/tmp/supervisord.pid
+nodaemon=false
+minfds=1024
+minprocs=200
+
+[rpcinterface:supervisor]
+supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
+
+[supervisorctl]
+serverurl=unix:///tmp/supervisor.sock
+
+[program:web]
+command=/pretalx/entrypoint.sh gunicorn
+autostart=true
+autorestart=true
+priority=5
+user=pretalx
+environment=HOME="/pretalx",PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
+
+[program:worker]
+command=/pretalx/entrypoint.sh celery
+autostart=true
+autorestart=true
+priority=5
+user=pretalx
+environment=HOME="/pretalx",PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
+
+[program:cron]
+command=/pretalx/entrypoint.sh cron
+environment=PATH="/pretalx/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+autostart=true
+autorestart=true
+priority=5
+user=root
+redirect_stderr=true
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
diff --git a/context/standalone/extended/Dockerfile.debian b/context/standalone/extended/Dockerfile.debian
new file mode 100644
index 0000000..74df317
--- /dev/null
+++ b/context/standalone/extended/Dockerfile.debian
@@ -0,0 +1,12 @@
+
+ARG PRETALX_BASE_IMAGE=docker.io/library/pretalx/pretalx
+ARG PRETALX_BASE_TAG=2024.1.0
+
+FROM ${PRETALX_BASE_IMAGE}:${PRETALX_BASE_TAG}
+
+USER pretalx
+RUN pip3 install -U --user prtx-faq \
+ pretalx-pages \
+ pretalx-public-voting
+
+USER root
diff --git a/deployment/docker/pretalx.bash b/deployment/docker/pretalx.bash
deleted file mode 100644
index 0271987..0000000
--- a/deployment/docker/pretalx.bash
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/bash
-cd /pretalx/src || exit 1
-export PRETALX_DATA_DIR="${PRETALX_DATA_DIR:-/data}"
-export HOME=/pretalx
-
-PRETALX_FILESYSTEM_LOGS="${PRETALX_FILESYSTEM_LOGS:-/data/logs}"
-PRETALX_FILESYSTEM_MEDIA="${PRETALX_FILESYSTEM_MEDIA:-/data/media}"
-PRETALX_FILESYSTEM_STATIC="${PRETALX_FILESYSTEM_STATIC:-/pretalx/src/static.dist}"
-
-GUNICORN_WORKERS="${GUNICORN_WORKERS:-${WEB_CONCURRENCY:-$((2 * $(nproc)))}}"
-GUNICORN_MAX_REQUESTS="${GUNICORN_MAX_REQUESTS:-1200}"
-GUNICORN_MAX_REQUESTS_JITTER="${GUNICORN_MAX_REQUESTS_JITTER:-50}"
-GUNICORN_FORWARDED_ALLOW_IPS="${GUNICORN_FORWARDED_ALLOW_IPS:-127.0.0.1}"
-GUNICORN_BIND_ADDR="${GUNICORN_BIND_ADDR:-0.0.0.0:80}"
-
-AUTOMIGRATE="${AUTOMIGRATE:-yes}"
-AUTOREBUILD="${AUTOREBUILD:-yes}"
-
-if [ "$PRETALX_FILESYSTEM_LOGS" != "/data/logs" ]; then
- export PRETALX_FILESYSTEM_LOGS
-fi
-if [ "$PRETALX_FILESYSTEM_MEDIA" != "/data/media" ]; then
- export PRETALX_FILESYSTEM_MEDIA
-fi
-if [ "$PRETALX_FILESYSTEM_STATIC" != "/pretalx/src/static.dist" ]; then
- export PRETALX_FILESYSTEM_STATIC
-fi
-
-if [ ! -d "$PRETALX_FILESYSTEM_LOGS" ]; then
- mkdir "$PRETALX_FILESYSTEM_LOGS";
-fi
-if [ ! -d "$PRETALX_FILESYSTEM_MEDIA" ]; then
- mkdir "$PRETALX_FILESYSTEM_MEDIA";
-fi
-if [ "$PRETALX_FILESYSTEM_STATIC" != "/pretalx/src/static.dist" ] &&
- [ ! -d "$PRETALX_FILESYSTEM_STATIC" ] &&
- [ "$AUTOREBUILD" = "yes" ]; then
- mkdir -p "$PRETALX_FILESYSTEM_STATIC"
- flock --nonblock /pretalx/.lockfile python3 -m pretalx rebuild
-fi
-
-if [ "$1" == "cron" ]; then
- exec python3 -m pretalx runperiodic
-fi
-
-if [ "$AUTOMIGRATE" = "yes" ]; then
- python3 -m pretalx migrate --noinput
-fi
-
-if [ "$1" == "all" ]; then
- exec sudo /usr/bin/supervisord -n -c /etc/supervisord.conf
-fi
-
-if [ "$1" == "webworker" ]; then
- exec gunicorn pretalx.wsgi \
- --name pretalx \
- --workers "${GUNICORN_WORKERS}" \
- --max-requests "${GUNICORN_MAX_REQUESTS}" \
- --max-requests-jitter "${GUNICORN_MAX_REQUESTS_JITTER}" \
- --forwarded-allow-ips "${GUNICORN_FORWARDED_ALLOW_IPS}" \
- --log-level=info \
- --bind="${GUNICORN_BIND_ADDR}"
-fi
-
-if [ "$1" == "taskworker" ]; then
- exec celery -A pretalx.celery_app worker -l info
-fi
-
-if [ "$1" == "shell" ]; then
- exec python3 -m pretalx shell
-fi
-
-if [ "$1" == "upgrade" ]; then
- python3 -m pretalx rebuild
- exec python3 -m pretalx regenerate_css
-fi
-
-exec python3 -m pretalx "$@"
diff --git a/deployment/docker/supervisord.conf b/deployment/docker/supervisord.conf
deleted file mode 100644
index f9711ab..0000000
--- a/deployment/docker/supervisord.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-[unix_http_server]
-file=/tmp/supervisor.sock
-
-[supervisord]
-logfile=/tmp/supervisord.log
-logfile_maxbytes=50MB
-logfile_backups=10
-loglevel=info
-pidfile=/tmp/supervisord.pid
-nodaemon=false
-minfds=1024
-minprocs=200
-
-[rpcinterface:supervisor]
-supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
-
-[supervisorctl]
-serverurl=unix:///tmp/supervisor.sock
-
-[program:pretalxweb]
-command=/usr/local/bin/pretalx webworker
-autostart=true
-autorestart=true
-priority=5
-user=pretalxuser
-environment=HOME=/pretalx
-
-[program:pretalxtask]
-command=/usr/local/bin/pretalx taskworker
-autostart=true
-autorestart=true
-priority=5
-user=pretalxuser
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index e3cfabc..0000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-version: '3'
-services:
- pretalx:
- image: pretalx/standalone:latest
- container_name: pretalx
- restart: unless-stopped
- depends_on:
- - redis
- - db
- environment:
- # Hint: Make sure you serve all requests for the `/static/` and `/media/` paths when debug is False. See [installation](https://docs.pretalx.org/administrator/installation/#step-7-ssl) for more information
- PRETALX_FILESYSTEM_MEDIA: /public/media
- PRETALX_FILESYSTEM_STATIC: /public/static
- ports:
- - "80:80"
- volumes:
- - ./conf/pretalx.cfg:/etc/pretalx/pretalx.cfg:ro
- - pretalx-data:/data
- - pretalx-public:/public
- labels:
- traefik.docker.network: "pretalxdocker"
- traefik.enable: "true"
-
- db:
- image: mysql:latest
- container_name: pretalx-db
- restart: unless-stopped
- volumes:
- - pretalx-db:/var/lib/mysql
- environment:
- MYSQL_DATABASE: pretalx
- MYSQL_USER: pretalx
- MYSQL_PASSWORD: veryunsecureplschange
- MYSQL_RANDOM_ROOT_PASSWORD: "1"
- command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci']
-
- redis:
- image: redis:latest
- container_name: pretalx-redis
- restart: unless-stopped
- volumes:
- - pretalx-redis:/data
-
-volumes:
- pretalx-db:
- pretalx-data:
- pretalx-public:
- pretalx-redis:
-
diff --git a/legacy/README.md b/legacy/README.md
new file mode 100644
index 0000000..26e0ef7
--- /dev/null
+++ b/legacy/README.md
@@ -0,0 +1,145 @@
+# Legacy docker-compose support
+
+This example demonstrates a setup that is compatible with the legacy version of Docker Compose.
+
+It assumes:
+
+- availability of the image specified by `PRETALX_IMAGE` and `PRETALX_TAG`
+
+It contains changes that accommodate for a specific environment:
+
+- removes SELinux settings
+- uses host-mounted volumes
+- uses only a single Compose manifest to launch without multiple `-f` flags
+- adds a separate `.env.pretalx` environment file, due to unsupported YAML interpolation syntax
+- deactivates running the automatic migrations container and turns its function into a manual step, due to unsupported `service_completed_successfully`
+- adapts the healthcheck interpolation syntax by escaping `$` escape signs
+
+Please use the example as a basis for your own modifications.
+
+## Preparation
+
+Run these commands from the root of the repository.
+
+Copy the example files in place:
+
+```sh
+cp legacy/docker-compose.yml.example docker-compose.yml
+cp legacy/docker-compose.env.example .env
+cp legacy/docker-compose.env.pretalx.example .env.pretalx
+```
+
+Remove the now redundant original configuration:
+
+```sh
+rm compose.yml
+```
+
+## Environment
+
+This legacy Docker Compose setup for running the Pretalx system brings two configuration files for adapting the environment.
+
+- `.env`, used for Docker Compose, the Traefik Reverse Proxy and the database credentials.
+- `.env.pretalx`, used for all application-specific configuration options. Refer to the original documentation for details.
+
+### .env
+
+- Modify the `VOLUME`s as needed.
+- Use a valid and available `IMAGE`/`TAG` combination.
+- Set the `FQDN`.
+- Specify the database credentials.
+
+### .env.pretalx
+
+- Adapt the `SITE_URL` to match the `FQDN` and the expected scheme.
+- Set a preferred `LANGUAGE_CODE`.
+- Choose the expected `TIME_ZONE`.
+- Choose a `LOGGING_EMAIL`.
+- Configure `MAIL` settings.
+
+## Volumes
+
+Create the directories which will be used as host-mounted volumes.
+
+```sh
+grep VOLUME .env | cut -d"=" -f2 | xargs -I% sh -c 'set -x; if [ ! -d "%" ]; then echo "Create: %"; mkdir -p "%"; else echo "Exists: %"; fi'
+```
+
+Apply the expected permissions:
+
+```sh
+grep -e 'DATA' -e 'PUBLIC' .env | cut -d"=" -f2 | xargs -L1 chown 999:999
+```
+
+Rootful Docker cannot perform subuid/-gid mapping.
+
+## Build
+
+This setup is prepared to perform a custom build with a selection of plugins, which are defined in the [`context/plugins/Dockerfile`](./context/plugins/Dockerfile).
+
+In case you wish to perform such a custom build, prepare the application image:
+
+```sh
+cp legacy/docker-compose.build.yml.example build.yml
+docker-compose -f docker-compose.yml -f build.yml build app
+```
+
+## First run
+
+Before running the application, check your `.env` and `.env.pretalx` files again. For example, you may want to replace the `pretalx/pretalx` image with `pretalx/pretalx-extended`, if you wanted to use one with plugins. When the files look good, prepare your Container engine with pulling the used images:
+
+```sh
+docker-compose pull
+```
+
+Skip this step for custom builds.
+
+Due to missing exit code evaluation of service dependencies in the legacy Docker Compose, we need a more manual approach to applying state to the containers, as with the non-legacy setup.
+
+Begin with initialising the databases:
+
+```sh
+docker-compose up -d postgres redis
+```
+
+Run the database migrations and implied build of static assets manually:
+
+```sh
+docker-compose run --rm app migrate
+```
+
+This is needed, since missing static assets will lead to errors when starting the other application containers.
+
+You are now ready to start the rest of the whole application.
+
+## Run
+
+This will take a moment, due to the dependencies between containers and the latency of the healthchecks intervals.
+
+```sh
+docker-compose up -d
+```
+
+Then prepare your initial user and the initial conference organiser:
+
+```sh
+docker-compose exec app python -m pretalx init
+```
+
+You can now login at `$PRETALX_SITE_URL/orga/`.
+
+One useful initial step is to navitagte to `$PRETALX_SITE_URL/orga/me` after login and to provide a username, which was omitted during the `init` step.
+
+## Validate
+
+Validate your configuration on `$PRETALX_SITE_URL/orga/admin`.
+
+Try to invite other members to your organiser and send yourself a password reset email to test email deliverability.
+
+Otherwise use the Django built-in:
+
+```sh
+docker-compose exec app python -m pretalx sendtestemail
+```
+
+Congratulations, you have setup a fully working Pretalx instance!
diff --git a/legacy/docker-compose.build.yml.example b/legacy/docker-compose.build.yml.example
new file mode 100644
index 0000000..32db66c
--- /dev/null
+++ b/legacy/docker-compose.build.yml.example
@@ -0,0 +1,22 @@
+services:
+ app:
+ image: ${PRETALX_IMAGE}-extended:${PRETALX_TAG}
+ build:
+ context: ./context/extended
+ args:
+ BASE_IMAGE: ${PRETALX_IMAGE}
+ BASE_TAG: ${PRETALX_TAG}
+ worker:
+ image: ${PRETALX_IMAGE}-extended:${PRETALX_TAG}
+ build:
+ context: ./context/extended
+ args:
+ BASE_IMAGE: ${PRETALX_IMAGE}
+ BASE_TAG: ${PRETALX_TAG}
+ cron:
+ image: ${PRETALX_IMAGE}-extended:${PRETALX_TAG}
+ build:
+ context: ./context/extended
+ args:
+ BASE_IMAGE: ${PRETALX_IMAGE}
+ BASE_TAG: ${PRETALX_TAG}
diff --git a/legacy/docker-compose.env.example b/legacy/docker-compose.env.example
new file mode 100644
index 0000000..beb7a5d
--- /dev/null
+++ b/legacy/docker-compose.env.example
@@ -0,0 +1,13 @@
+PRETALX_VOLUME_DATA=./.state/data
+PRETALX_VOLUME_PUBLIC=./.state/public
+PRETALX_VOLUME_POSTGRES=./.state/postgres
+PRETALX_VOLUME_REDIS=./.state/redis
+
+PRETALX_IMAGE=docker.io/pretalx/pretalx
+PRETALX_TAG=latest
+
+FQDN=localhost.local
+
+POSTGRES_PASSWORD=
+POSTGRES_USER=pretalx
+POSTGRES_DB=pretalx
diff --git a/legacy/docker-compose.env.pretalx.example b/legacy/docker-compose.env.pretalx.example
new file mode 100644
index 0000000..3c9ebb0
--- /dev/null
+++ b/legacy/docker-compose.env.pretalx.example
@@ -0,0 +1,40 @@
+PRETALX_LOG_LEVEL=info
+
+PRETALX_DEBUG=False
+PRETALX_SITE_URL=https://fqdn
+
+PRETALX_LANGUAGE_CODE=en
+PRETALX_TIME_ZONE=UTC
+
+PRETALX_DATA_DIR=/data
+PRETALX_FILESYSTEM_LOGS=/data/logs
+
+PRETALX_FILESYSTEM_MEDIA=/public/media
+PRETALX_FILESYSTEM_STATIC=/public/static
+
+PRETALX_SITE_CSP=
+PRETALX_SITE_CSP_STYLE=
+PRETALX_SITE_CSP_SCRIPT=
+PRETALX_SITE_CSP_IMG=
+PRETALX_SITE_CSP_FORM=
+
+PRETALX_LOGGING_EMAIL=
+PRETALX_LOGGING_EMAIL_LEVEL=ERROR
+
+#PRETALX_MAIL_FROM=admin@localhost
+#PRETALX_MAIL_HOST=localhost
+#PRETALX_MAIL_PORT=25
+#PRETALX_MAIL_USER=
+#PRETALX_MAIL_PASSWORD=
+#PRETALX_MAIL_TLS=False
+#PRETALX_MAIL_SSL=False
+
+PRETALX_DB_TYPE=postgresql
+PRETALX_DB_HOST=postgres
+PRETALX_DB_PORT=5432
+
+PRETALX_REDIS=redis://redis/0
+PRETALX_REDIS_SESSIONS=true
+
+PRETALX_CELERY_BACKEND=redis://redis/1
+PRETALX_CELERY_BROKER=redis://redis/2
diff --git a/legacy/docker-compose.yml.example b/legacy/docker-compose.yml.example
new file mode 100644
index 0000000..70ae1b4
--- /dev/null
+++ b/legacy/docker-compose.yml.example
@@ -0,0 +1,176 @@
+networks:
+ data:
+ web:
+ external: true
+
+services:
+
+ web:
+ image: nginx:alpine
+ restart: unless-stopped
+
+ deploy:
+ replicas: 1
+
+ healthcheck:
+ test: ['CMD-SHELL', 'ash -c "[[ $$(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:80) == \"200\" ]]" || exit 1']
+ start_period: 10s
+ interval: 30s
+ retries: 5
+ timeout: 3s
+
+ depends_on:
+ app:
+ condition: service_healthy
+
+ networks:
+ - data
+ - web
+ volumes:
+ - ./config/nginx.conf:/etc/nginx/nginx.conf:ro
+ - ${PRETALX_VOLUME_PUBLIC}:/public
+
+ labels:
+ traefik.enable: true
+ traefik.http.routers.fqdn-pretalx-web.entrypoints: web
+ traefik.http.routers.fqdn-pretalx-web.rule: Host(`${FQDN}`)
+ traefik.http.routers.fqdn-pretalx-web.middlewares: http-to-https
+ traefik.http.middlewares.http-to-https.redirectscheme.scheme: https
+ traefik.http.middlewares.http-to-https.redirectscheme.permanent: true
+ traefik.http.routers.fqdn-pretalx-webs.entrypoints: webs
+ traefik.http.routers.fqdn-pretalx-webs.rule: Host(`${FQDN}`)
+ traefik.http.routers.fqdn-pretalx-webs.tls: true
+ traefik.http.routers.fqdn-pretalx-webs.tls.certresolver: letsencrypt
+
+
+ app:
+ image: ${PRETALX_IMAGE}:${PRETALX_TAG}
+ command: gunicorn
+ restart: unless-stopped
+
+ deploy:
+ replicas: 1
+
+ healthcheck:
+ test: ['CMD-SHELL', 'bash -c "[[ $$(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:8080) == \"200\" ]]" || exit 1']
+ start_period: 10s
+ interval: 30s
+ retries: 5
+ timeout: 3s
+
+ depends_on:
+ redis:
+ condition: service_healthy
+ postgres:
+ condition: service_healthy
+
+ networks:
+ - data
+ volumes:
+ - ${PRETALX_VOLUME_DATA}:/data
+ - ${PRETALX_VOLUME_PUBLIC}:/public
+ env_file: [".env.pretalx"]
+ environment:
+ PRETALX_LOG_LEVEL: ${PRETALX_LOG_LEVEL}
+ PRETALX_DB_NAME: ${POSTGRES_DB}
+ PRETALX_DB_USER: ${POSTGRES_USER}
+ PRETALX_DB_PASS: ${POSTGRES_PASSWORD}
+
+ worker:
+ image: ${PRETALX_IMAGE}:${PRETALX_TAG}
+ command: celery
+ restart: unless-stopped
+
+ deploy:
+ replicas: 1
+
+ healthcheck:
+ test: ['CMD-SHELL', 'bash -c "[[ \"$$(pgrep celery)\" != \"\" ]]" || exit 1']
+ start_period: 10s
+ interval: 30s
+ retries: 5
+ timeout: 3s
+
+ depends_on:
+ redis:
+ condition: service_healthy
+ postgres:
+ condition: service_healthy
+
+ networks:
+ - data
+ volumes:
+ - ${PRETALX_VOLUME_DATA}:/data
+ - ${PRETALX_VOLUME_PUBLIC}:/public
+ env_file: [".env.pretalx"]
+ environment:
+ PRETALX_LOG_LEVEL: ${PRETALX_LOG_LEVEL}
+ PRETALX_DB_NAME: ${POSTGRES_DB}
+ PRETALX_DB_USER: ${POSTGRES_USER}
+ PRETALX_DB_PASS: ${POSTGRES_PASSWORD}
+
+ cron:
+ image: ${PRETALX_IMAGE}:${PRETALX_TAG}
+ command: cron
+ user: root
+ init: true
+ restart: unless-stopped
+
+ healthcheck:
+ test: ['CMD-SHELL', 'bash -c "[[ \"$$(pgrep cron)\" != \"\" ]]" || exit 1']
+ start_period: 10s
+ interval: 30s
+ retries: 5
+ timeout: 3s
+
+ depends_on:
+ redis:
+ condition: service_healthy
+ postgres:
+ condition: service_healthy
+
+ networks:
+ - data
+ volumes:
+ - ${PRETALX_VOLUME_DATA}:/data
+ - ${PRETALX_VOLUME_PUBLIC}:/public
+ env_file: [".env.pretalx"]
+ environment:
+ PRETALX_DB_NAME: ${POSTGRES_DB}
+ PRETALX_DB_USER: ${POSTGRES_USER}
+ PRETALX_DB_PASS: ${POSTGRES_PASSWORD}
+
+
+ postgres:
+ image: docker.io/library/postgres:15-alpine
+ restart: unless-stopped
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
+ start_period: 20s
+ interval: 30s
+ retries: 5
+ timeout: 5s
+ networks:
+ - data
+ volumes:
+ - ${PRETALX_VOLUME_POSTGRES}:/var/lib/postgresql/data
+ environment:
+ - POSTGRES_PASSWORD
+ - POSTGRES_USER
+ - POSTGRES_DB
+
+ redis:
+ image: docker.io/library/redis:alpine
+ command: --save 60 1 --loglevel warning
+ restart: unless-stopped
+ healthcheck:
+ test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
+ start_period: 10s
+ interval: 30s
+ retries: 5
+ timeout: 3s
+ networks:
+ - data
+ volumes:
+ - ${PRETALX_VOLUME_REDIS}:/data
+
diff --git a/pretalx b/pretalx
deleted file mode 160000
index 6dc9c1b..0000000
--- a/pretalx
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 6dc9c1b6c9ab5d00f976012cbd5affa41dcab46a
diff --git a/reverse-proxy-examples/ansible/traefik/defaults/main.yml b/reverse-proxy-examples/ansible/traefik/defaults/main.yml
deleted file mode 100644
index 6519f6f..0000000
--- a/reverse-proxy-examples/ansible/traefik/defaults/main.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-main_url: example.com
-acme_mail: acme@example.com
\ No newline at end of file
diff --git a/reverse-proxy-examples/ansible/traefik/tasks/main.yml b/reverse-proxy-examples/ansible/traefik/tasks/main.yml
deleted file mode 100644
index 2f1c616..0000000
--- a/reverse-proxy-examples/ansible/traefik/tasks/main.yml
+++ /dev/null
@@ -1,65 +0,0 @@
----
-- name: Ensures traefik dir exists
- become: yes
- file:
- path: "{{ traefik_dir }}"
- state: directory
- owner: "{{ user }}"
- group: "{{ group }}"
-
-
-- name: Check acme.json file exists
- become: yes
- stat:
- path: "{{ traefik_dir }}/acme.json"
- register: stat_result
-
-- name: Create acme.json file, if it doesnt exist already
- become: yes
- file:
- path: "{{ traefik_dir }}/acme.json"
- state: touch
- mode: 0600
- when: stat_result.stat.exists == False
-
-- name: Adding traefik.toml file
- become: yes
- template:
- src: ../templates/traefik.toml.j2
- dest: "{{ traefik_dir }}/traefik.toml"
- mode: 0600
- register: traefik_config_change
-
-- name: Create the web network
- docker_network:
- name: web
-
-- name: Create the traefik container
- docker_container:
- name: traefik
- image: traefik
- restart_policy: unless-stopped
- networks:
- - name: web
- ports:
- - "80:80"
- - "443:443"
- - "8080:8080"
- volumes:
- - "{{ traefik_dir }}/traefik.toml:/etc/traefik/traefik.toml"
- - "{{ traefik_dir }}/acme.json:/acme.json"
- - /var/run/docker.sock:/var/run/docker.sock
- labels:
- traefik.docker.network: "web"
- traefik.port: "8080"
- traefik.enable: "false"
- register: traefik_change
-
-
-- name: Restart traefik on config change
- docker_container:
- name: traefik
- restart : yes
- when:
- - traefik_config_change.changed == True
- - traefik_change.changed == False
diff --git a/reverse-proxy-examples/ansible/traefik/templates/traefik.toml.j2 b/reverse-proxy-examples/ansible/traefik/templates/traefik.toml.j2
deleted file mode 100644
index 220507e..0000000
--- a/reverse-proxy-examples/ansible/traefik/templates/traefik.toml.j2
+++ /dev/null
@@ -1,62 +0,0 @@
-debug = false
-
-logLevel = "INFO"
-
-defaultEntryPoints = ["https","http"]
-
-[entryPoints]
- [entryPoints.http]
- address = ":80"
- [entryPoints.http.redirect]
- entryPoint = "https"
- [entryPoints.https]
- address = ":443"
- [entryPoints.https.tls]
- minVersion = "VersionTLS12"
-
-
-[retry]
-
-[docker]
-endpoint = "unix:///var/run/docker.sock"
-domain = "{{ main_url }}"
-watch = true
-exposedByDefault = true
-
-[acme]
-email = "{{ acme_mail }}"
-storage = "acme.json"
-entryPoint = "https"
-onHostRule = true
-acmeLogging = true
-
-[acme.httpChallenge]
-entryPoint = "http"
-
-
-
-
-[api]
- # Name of the related entry point
- #
- # Optional
- # Default: "traefik"
- #
- #entryPoint = "traefik"
-
- # Enable Dashboard
- #
- # Optional
- # Default: true
- #
- dashboard = true
-
- # Enable debug mode.
- # This will install HTTP handlers to expose Go expvars under /debug/vars and
- # pprof profiling data under /debug/pprof/.
- # Additionally, the log level will be set to DEBUG.
- #
- # Optional
- # Default: false
- #
- debug = false
diff --git a/reverse-proxy-examples/ansible/traefik/vars/main.yml b/reverse-proxy-examples/ansible/traefik/vars/main.yml
deleted file mode 100644
index 0631c66..0000000
--- a/reverse-proxy-examples/ansible/traefik/vars/main.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-user: root
-group: docker
-traefik_dir: /docker-config/traefik
diff --git a/reverse-proxy-examples/docker-compose/Readme.md b/reverse-proxy-examples/docker-compose/Readme.md
deleted file mode 100644
index a421d3d..0000000
--- a/reverse-proxy-examples/docker-compose/Readme.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Traefik-config for pretalx
-This includes basic config to run traefik as an reverse proxy for pretalx.
-A more in-depth-guide can be found under
diff --git a/reverse-proxy-examples/docker-compose/traefik.toml b/reverse-proxy-examples/docker-compose/traefik.toml
deleted file mode 100644
index 609439f..0000000
--- a/reverse-proxy-examples/docker-compose/traefik.toml
+++ /dev/null
@@ -1,34 +0,0 @@
-debug = false
-
-logLevel = "INFO"
-
-defaultEntryPoints = ["https","http"]
-
-[entryPoints]
- [entryPoints.http]
- address = ":80"
- [entryPoints.http.redirect]
- entryPoint = "https"
- [entryPoints.https]
- address = ":443"
- [entryPoints.https.tls]
- minVersion = "VersionTLS12"
-
-
-[retry]
-
-[docker]
-endpoint = "unix:///var/run/docker.sock"
-domain = "example.com"
-watch = true
-exposedByDefault = false
-
-[acme]
-email = "youremail@exampledomain.com"
-storage = "acme.json"
-entryPoint = "https"
-onHostRule = true
-acmeLogging = true
-
-[acme.httpChallenge]
-entryPoint = "http"
diff --git a/reverse-proxy-examples/nginx/Readme.MD b/reverse-proxy-examples/nginx/Readme.MD
deleted file mode 100644
index 71bc753..0000000
--- a/reverse-proxy-examples/nginx/Readme.MD
+++ /dev/null
@@ -1,27 +0,0 @@
-# NGINX Config example
-
-Your config could look like this:
-
-```
-server {
- listen 80 default_server;
- listen [::]:80 ipv6only=on default_server;
- server_name pretalx.mydomain.com;
-}
-server {
- listen 443 default_server;
- listen [::]:443 ipv6only=on default_server;
- server_name pretalx.mydomain.com;
-
- ssl on;
- ssl_certificate /path/to/cert.chain.pem;
- ssl_certificate_key /path/to/key.pem;
-
- location / {
- proxy_pass http://localhost:8355/;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto https;
- proxy_set_header Host $http_host;
- }
-}
-```