Installation
turnierplan.NET comes as a pre-built container image which can be deployed with minimal configuration. The image is available on GitHub: ghcr.io/turnierplan-net/turnierplan
Getting Started
In the simplest case, you can configure the container to use an in-memory data store. Note that this in-memory store is only meant for quick testing and is obviously not suitable for a production environment.
docker run -p 80:8080 -e Database__InMemory="true" ghcr.io/turnierplan-net/turnierplan:latest
You should see the following output. The credentials of the initial admin user are displayed in the container logs. You can now open up http://localhost in your browser and log in using those credentials.
__ ___ __
/\ \__ __ /\_ \ /\ \__
\ \ ,_\ __ __ _ __ ___ /\_\ __ _ __ _____\//\ \ __ ___ ___ __\ \ ,_\
\ \ \/ /\ \/\ \/\`'__\/' _ `\/\ \ /'__`\/\`'__\/\ '__`\\ \ \ /'__`\ /' _ `\ /' _ `\ /'__`\ \ \/
\ \ \_\ \ \_\ \ \ \/ /\ \/\ \ \ \/\ __/\ \ \/ \ \ \L\ \\_\ \_/\ \L\.\_/\ \/\ \ __/\ \/\ \/\ __/\ \ \_
\ \__\\ \____/\ \_\ \ \_\ \_\ \_\ \____\\ \_\ \ \ ,__//\____\ \__/.\_\ \_\ \_\/\_\ \_\ \_\ \____\\ \__\
\/__/ \/___/ \/_/ \/_/\/_/\/_/\/____/ \/_/ \ \ \/ \/____/\/__/\/_/\/_/\/_/\/_/\/_/\/_/\/____/ \/__/
\ \_\
\/_/ v2025.4.0
info: Turnierplan.ImageStorage.Local.LocalImageStorage[0]
Using the following directory for local image storage: '/var/turnierplan/images'
info: Turnierplan.App.DatabaseMigrator[0]
An initial user was created: You can log in using "admin" and the password "53fe6bac-1050-4801-bb11-be2dbd479d66". IMMEDIATELY change this password when running in a production environment!
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:8080
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app
Persisting Data
The application stores the following data in the /var/turnierplan directory:
/var/turnierplan/identity/jwt-signing-key.bin- The SHA512 signature key used to sign and verify JWT tokens./var/turnierplan/images/**- If not configured otherwise (see section below), this folder will contain all uploaded image files.
Therefore, there should always be a volume mapping for this path.
Environment Variables
For a basic installation, the following environment variables must be set:
| Environment Variable | Description |
|---|---|
Turnierplan__ApplicationUrl |
The URL used to access the website. |
Database__ConnectionString |
The PostgreSQL connection string with read/write permission. |
The following environment variables can be set if you want to enable specific features or modify default behavior:
| Environment Variable | Description | Default |
|---|---|---|
ApplicationInsights__ConnectionString |
Can be set if you wish that your instance sends telemetry data to Azure Application Insights. | - |
Identity__AccessTokenLifetime |
Defines the lifetime of issued JWT access tokens. | 00:03:00 |
Identity__RefreshTokenLifetime |
Defines the lifetime of issued JWT refresh tokens. | 1.00:00:00 |
Turnierplan__InstanceName |
The instance name is displayed in the header/footer of the public pages. If not specified, the string turnierplan.NET will be shown instead. |
- |
Turnierplan__LogoUrl |
The URL of the custom logo to be displayed in the header of the public pages. If not specified, the turnierplan.NET logo will be shown instead. | - |
Turnierplan__ImprintUrl |
The URL of your external imprint page if you want it to be linked on the public pages. | - |
Turnierplan__PrivacyUrl |
The URL of your external privacy page if you want it to be linked on the public pages. | - |
Note
The token lifetimes must be specified as .NET TimeSpan strings. For example 00:03:00 means 3 minutes or 1.00:00.00 means 1 day.
Docker Compose
A minimal recommended configuration for a production environment is shown in the following docker compose example:
services:
turnierplan.database:
image: postgres:latest
environment:
- POSTGRES_PASSWORD=P@ssw0rd
- POSTGRES_DB=turnierplan
volumes:
- turnierplan-database-data:/var/lib/postgresql/data
networks:
- turnierplan
restart: unless-stopped
turnierplan.app:
image: ghcr.io/turnierplan-net/turnierplan:latest
depends_on:
- turnierplan.database
environment:
- Turnierplan__ApplicationUrl=http://localhost
- Database__ConnectionString=Host=turnierplan.database;Database=turnierplan;Username=postgres;Password=P@ssw0rd
volumes:
- turnierplan-app-data:/var/turnierplan
networks:
- turnierplan
restart: unless-stopped
ports:
- '80:8080'
volumes:
turnierplan-database-data:
turnierplan-app-data:
networks:
turnierplan:
Tip
It is recommended to not use the latest tag. Rather, pin your docker services to a specific image version.
Feel free to modify the environment variables or add additional ones as described in the environment variables section above.
Storing Images
By default, all uploaded image files are stored in the /var/turnierplan/images directory. Whilst this is a very simple solution, it also means that the turnierplan.NET backend will serve all image files which can potentially lead to high load on the application server. Alternatively, you can configure the application to save image files to an external storage service. This way, clients can load the images directly from the external service.
Warning
The differnt implementations do not necessarily use the same folder structure to organizie the files. Because of this, migrating from one image storage implementation to another can be difficult - so choose wisely!
The following implementations are currently available:
- Local - The default, which saves images in a local folder as described above
- AWS S3 (or compatible)
- Azure Blob Storage
Configuring AWS S3
To store uploaded images in an AWS S3 or S3-compatible bucket, add the following environment variables to your deployment:
| Environment Variable | Description |
|---|---|
ImageStorage__Type |
The image storage type, must be S3. |
ImageStorage__RegionEndpoint |
The AWS region endpoint, such as eu-central-1. |
ImageStorage__ServiceUrl |
The service URL when using a non-AWS S3 bucket. |
ImageStorage__AccessKey |
The access key identifier. |
ImageStorage__AccessKeySecret |
The access key secret. |
ImageStorage__BucketName |
The name of the bucket. |
The access key must have permissions to create, read and delete objects.
The RegionEndpoint and ServiceUrl variables are mutually exclusive. Use the former if you are using an AWS S3 bucket and use the latter if you use a S3-compatible bucket from a third party.
Configuring Azure Blob Storage
To store uploaded images in an Azure Blob Storage container, add the following environment variables to your deployment:
| Environment Variable | Description |
|---|---|
ImageStorage__Type |
The image storage type, must be Azure. |
ImageStorage__StorageAccountName |
The name of the storage account. |
ImageStorage__ContainerName |
The name of the blob container. |
By default, a DefaultAzureCredential will be used. Therefore, if you use Azure Managed Identities, you won't have to do any further configuration. In addition, this implementation supports two additional means of authentication listed below.
When using Entra ID based authentication, the managed identity / app registration must have permission to create/read/delete blobs in the storage account. This can be achieved by assigning the Storage Blob Data Contributor role.
Access key authentication
Refer to the documentation on how to view and manage the access keys.
The following environment variables must be set to enable access key authentication:
| Environment Variable | Description |
|---|---|
ImageStorage__UseAccountKey |
Set to true to use account key authentication. |
ImageStorage__AccountKey |
The value of the account key. |
Client secret authentication
If you have an Entra ID app registration with the necessary permissions on the storage account, you can set the following environment variables to enable client secret authentication:
| Environment Variable | Description |
|---|---|
ImageStorage__UseClientSecret |
Set to true to use client credentials authentication. |
ImageStorage__TenantId |
The tenant id where the app registration resides. |
ImageStorage__ClientId |
The client id of the app registration. |
ImageStorage__ClientSecret |
The value of the client secret. |