diff --git a/CHANGELOG.md b/CHANGELOG.md
index 101228528ebce23436702c5fc329a4c39408b669..1f345d81c5f6312582d8972518e7a85b7276ee99 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Changed
 
-- ...
+- The `program/rrule.json` fixture contains all the supported recurrence rules.
 
 ### Deprecated
 
diff --git a/Makefile b/Makefile
index 679ef847d9c02dd820db9ddf4b85d36fa09e27d4..0e82f89d46a67467dc22d624955dcbc251747080 100644
--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,13 @@ POETRY_RUN_MANAGE = $(POETRY_RUN) ./manage.py
 
 .DEFAULT_GOAL := run.prod
 
-TANK_CALLBACK_BASE_URL ?= "${AURA_PROTO}://${AURA_HOST}/tank"
-DASHBOARD_CALLBACK_BASE_URL ?= "${AURA_PROTO}://${AURA_HOST}"
+ifndef TANK_CALLBACK_BASE_URL
+override TANK_CALLBACK_BASE_URL = "${AURA_PROTO}://${AURA_HOST}/tank"
+endif
+
+ifndef DASHBOARD_CALLBACK_BASE_URL
+override DASHBOARD_CALLBACK_BASE_URL = "${AURA_PROTO}://${AURA_HOST}"
+endif
 
 initialize: migrate loadfixtures
 	$(POETRY_RUN_MANAGE) collectstatic --clear --no-input
@@ -27,11 +32,17 @@ loadfixtures:
 loaddata:
 	$(POETRY_RUN_MANAGE) loaddata ${DATA}
 
-run.dev: migrate
+removestaleimages:
+	$(POETRY_RUN_MANAGE) removestaleimages
+
+run.dev: dev.install migrate
 	$(POETRY_RUN_MANAGE) runserver 0.0.0.0:8000
 
+dev.install:
+	$(POETRY) install --no-root
+
 run.prod: migrate
-	$(POETRY_RUN) gunicorn --bind 0.0.0.0:8000 --workers `(nproc)` steering.wsgi
+	$(POETRY_RUN) gunicorn --bind 0.0.0.0:8000 --workers `nproc` steering.wsgi
 
 run.debug: migrate
 	DEBUG=1 $(POETRY_RUN_MANAGE) runserver_plus 0.0.0.0:8000
diff --git a/fixtures/auth/group.json b/fixtures/auth/group.json
deleted file mode 100644
index 06dbacd7e25d17fe967c3abda8d2d0c46df9132a..0000000000000000000000000000000000000000
--- a/fixtures/auth/group.json
+++ /dev/null
@@ -1,10 +0,0 @@
-[
-  {
-    "model": "auth.group",
-    "pk": 1,
-    "fields": {
-      "name": "ProgrammmacherInnen",
-      "permissions": []
-    }
-  }
-]
diff --git a/fixtures/auth/group_permissions.json b/fixtures/auth/group_permissions.json
deleted file mode 100644
index c2b8e7c683df387460ce633b4a523b45f1c27a56..0000000000000000000000000000000000000000
--- a/fixtures/auth/group_permissions.json
+++ /dev/null
@@ -1,50 +0,0 @@
-[
-  {
-    "model": "auth.group_permissions",
-    "pk": 1,
-    "fields": {
-      "group": 1,
-      "permission": 35
-    }
-  },
-  {
-    "model": "auth.group_permissions",
-    "pk": 2,
-    "fields": {
-      "group": 1,
-      "permission": 28
-    }
-  },
-  {
-    "model": "auth.group_permissions",
-    "pk": 3,
-    "fields": {
-      "group": 1,
-      "permission": 29
-    }
-  },
-  {
-    "model": "auth.group_permissions",
-    "pk": 4,
-    "fields": {
-      "group": 1,
-      "permission": 30
-    }
-  },
-  {
-    "model": "auth.group_permissions",
-    "pk": 5,
-    "fields": {
-      "group": 1,
-      "permission": 8
-    }
-  },
-  {
-    "model": "auth.group_permissions",
-    "pk": 6,
-    "fields": {
-      "group": 1,
-      "permission": 23
-    }
-  }
-]
diff --git a/fixtures/auth/user.json b/fixtures/auth/user.json
deleted file mode 100644
index 59c9850cb3a9158320ee38a2d7b79256db34ce8b..0000000000000000000000000000000000000000
--- a/fixtures/auth/user.json
+++ /dev/null
@@ -1,38 +0,0 @@
-[
-  {
-    "model": "auth.user",
-    "pk": 1,
-    "fields": {
-      "password": "pbkdf2_sha256$36000$uMBrNYea7vcc$6599RKSDzRkpoO8lcOjOQI/O1ufPXphIYh10VNqZcYU=",
-      "last_login": null,
-      "is_superuser": true,
-      "username": "admin",
-      "first_name": "",
-      "last_name": "",
-      "email": "",
-      "is_staff": true,
-      "is_active": true,
-      "date_joined": "2017-12-31T22:00:00Z",
-      "groups": [],
-      "user_permissions": []
-    }
-  },
-  {
-    "model": "auth.user",
-    "pk": 2,
-    "fields": {
-      "password": "pbkdf2_sha256$36000$VVSM5LeZfBZM$w0XSHCrucEb7Oj1Qpjdy1SKq5KelpXSPiUXbxh3rWpM=",
-      "last_login": null,
-      "is_superuser": false,
-      "username": "pm1",
-      "first_name": "",
-      "last_name": "",
-      "email": "",
-      "is_staff": true,
-      "is_active": true,
-      "date_joined": "2017-12-31T22:00:00Z",
-      "groups": [],
-      "user_permissions": []
-    }
-  }
-]
diff --git a/fixtures/auth/user_groups.json b/fixtures/auth/user_groups.json
deleted file mode 100644
index ca3a1e2715920725a31c694012f76d093ae48bea..0000000000000000000000000000000000000000
--- a/fixtures/auth/user_groups.json
+++ /dev/null
@@ -1,10 +0,0 @@
-[
-  {
-    "model": "auth.user_groups",
-    "pk": 1,
-    "fields": {
-      "user": 2,
-      "group": 1
-    }
-  }
-]
diff --git a/program/management/commands/removestaleimages.py b/program/management/commands/removestaleimages.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e1d5f6512fa544a395b7677d9ddcd9d6109859d
--- /dev/null
+++ b/program/management/commands/removestaleimages.py
@@ -0,0 +1,49 @@
+import os
+
+from versatileimagefield.fields import VersatileImageField
+
+from django.apps import apps
+from django.conf import settings
+from django.core.management.base import BaseCommand
+from django.db.models import ImageField, Q
+
+
+class Command(BaseCommand):
+    help = "removes images from the MEDIA_ROOT that are not referenced in the database."
+
+    def handle(self, *args, **options):
+        def remove_file(path: str) -> None:
+            print(f"REMOVED {path}")
+            os.remove(path)
+
+        image_names = []  # names (without extensions) of the images in the database
+
+        for model in apps.get_models():
+            for field in model._meta.get_fields():
+                if isinstance(field, VersatileImageField) or isinstance(field, ImageField):
+                    is_empty = Q(**{f"{field.name}": ""})
+                    images = model.objects.exclude(is_empty).values_list(field.name, flat=True)
+
+                    for image in images:
+                        basename = os.path.basename(image)
+                        filename, ext = os.path.splitext(basename)
+                        image_names.append(filename)
+
+        media_root = getattr(settings, "MEDIA_ROOT")
+
+        for relative_root, dirs, files in os.walk(media_root):
+            for file_ in files:
+                relative_path = os.path.join(os.path.relpath(relative_root, media_root), file_)
+                head, tail = os.path.split(relative_path)
+                filename, ext = os.path.splitext(tail)
+
+                fullpath = os.path.join(media_root, relative_path)
+
+                if not head.startswith("__sized__"):
+                    if filename not in image_names:
+                        remove_file(fullpath)
+                else:
+                    # cropped images
+                    name, _ = filename.split("-crop-")
+                    if name not in image_names:
+                        remove_file(fullpath)
diff --git a/run.sh b/run.sh
deleted file mode 100755
index d97be642c6af7b2fb67e87445d9587bbce312b1d..0000000000000000000000000000000000000000
--- a/run.sh
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/bin/bash
-# Default mode
-mode="dev"
-docker="false"
-
-#
-# Run Script for AURA Steering
-#
-# Call with one of these parameters:
-#
-# - init
-# - dev
-# - prod
-# - test
-
-# - docker:build
-# - docker:push
-# - docker:dev
-# 
-
-if [[ $* =~ ^(init|init-db|dev|prod|test|build|push|serve)$ ]]; then
-	mode=$1
-fi
-
-if [[ "$1" == *"docker:"* ]]; then
-	docker="true"
-	mode=${1#*:}
-fi
-
-
-echo "[ Run mode=$mode ]"
-echo "[ Docker=$docker ]"
-
-
-
-# +++ DEFAULT COMMANDS +++ #
-
-if [[ $docker == "false" ]]; then
-
-	if [[ $mode == "init-db" ]]; then
-		echo "apply database migrations"
-		poetry run ./manage.py migrate
-    echo "collect static resources"
-    poetry run ./manage.py collectstatic --clear --noinput
-		echo "create django superuser"
-		poetry run ./manage.py createsuperuser --noinput
-		echo "create rsa key"
-		poetry run ./manage.py creatersakey
-		if [[ -z ${TANK_CALLBACK_BASE_URL} ]]; then
-			TANK_CALLBACK_BASE_URL="${AURA_PROTO}://${AURA_HOST}/tank"
-		fi
-		if [[ -z ${DASHBOARD_CALLBACK_BASE_URL} ]]; then
-			DASHBOARD_CALLBACK_BASE_URL="${AURA_PROTO}://${AURA_HOST}"
-		fi
-		echo "create dashboard client with client id $DASHBOARD_OIDC_CLIENT_ID"
-    poetry run ./manage.py create_oidc_client dashboard public --client-id $DASHBOARD_OIDC_CLIENT_ID --client-secret $DASHBOARD_OIDC_CLIENT_SECRET -r "id_token token" -u ${DASHBOARD_CALLBACK_BASE_URL}/oidc_callback.html -u ${DASHBOARD_CALLBACK_BASE_URL}/oidc_callback_silentRenew.html -p ${DASHBOARD_CALLBACK_BASE_URL} -p ${DASHBOARD_CALLBACK_BASE_URL}/
-    echo "create tank client with client id $TANK_OIDC_CLIENT_ID"
-		poetry run ./manage.py create_oidc_client tank confidential --client-id $TANK_OIDC_CLIENT_ID --client-secret $TANK_OIDC_CLIENT_SECRET -r "code" -u ${TANK_CALLBACK_BASE_URL}/auth/oidc/callback
-	fi
-
-	### Initializes the project (Development) ###
-
-	if [[ $mode == "init" ]]; then
-		echo "Installing dependencies with Poetry"
-		poetry install --no-root
-	fi
-
-	### Runs Steering in development mode (Virtualenv) ###
-
-	if [[ $mode == "dev" ]]; then
-		echo "Activating Python Environment"
-		poetry run python manage.py runserver
-	fi
-
-	### Runs Steering in production mode (WSGI) ###
-
-	if [[ $mode == "prod" ]]; then
-		echo "!!! Not yet implemented !!!"
-		#gunicorn -c config/gunicorn.conf.py src.app:app
-	fi
-
-	### Runs the test-cases ###
-
-	if [[ $mode == "test" ]]; then
-		echo "!!! Not yet implemented !!!"
-	fi
-
-fi
-
-
-# +++ DOCKER COMMANDS +++ #
-
-if [[ $docker == "true" ]]; then
-	BASE_D=$(realpath "${BASH_SOURCE%/*}/")
-
-	### Runs Steering from Docker ###
-
-	if [[ $mode == "dev" ]]; then
-		exec sudo docker run --rm -it \
-            -u $UID:$GID \
-            -p 127.0.0.1:8000:8000 \
-            -v "$BASE_D":/srv autoradio/steering /srv/manage.py \
-            runserver 0.0.0.0:8000
-	fi
-
-	### Create Docker Image from local project ###
-
-	if [[ $mode == "build" ]]; then
-		exec sudo docker build -t autoradio/steering .
-	fi
-
-	### Pushes the latest Docker Image to Docker Hub ###
-
-	if [[ $mode == "push" ]]; then
-		exec sudo docker push autoradio/steering
-	fi
-fi