diff --git a/aleksis/core/migrations/0001_initial.py b/aleksis/core/migrations/0001_initial.py
index 4dd6486f478a00e23a42876d302bbbe954648084..9999e1a6615138251c1745d4e33b3d9d404d0c7b 100644
--- a/aleksis/core/migrations/0001_initial.py
+++ b/aleksis/core/migrations/0001_initial.py
@@ -8,7 +8,6 @@ import django.contrib.postgres.fields.jsonb
 import django.contrib.sites.managers
 from django.db import migrations, models
 import django.db.models.deletion
-import image_cropping.fields
 import phonenumber_field.modelfields
 
 
@@ -125,8 +124,8 @@ class Migration(migrations.Migration):
                 ('email', models.EmailField(blank=True, max_length=254, verbose_name='E-mail address')),
                 ('date_of_birth', models.DateField(blank=True, null=True, verbose_name='Date of birth')),
                 ('sex', models.CharField(blank=True, choices=[('f', 'female'), ('m', 'male')], max_length=1, verbose_name='Sex')),
-                ('photo', image_cropping.fields.ImageCropField(blank=True, null=True, upload_to='', verbose_name='Photo')),
-                ('photo_cropping', image_cropping.fields.ImageRatioField('photo', '600x800', adapt_rotation=False, allow_fullsize=False, free_crop=False, help_text=None, hide_image_field=False, size_warning=True, verbose_name='photo cropping')),
+                ('photo', models.CharField(blank=True, max_length=1)),
+                ('photo_cropping', models.CharField(blank=True, max_length=1)),
                 ('description', models.TextField(blank=True, verbose_name='Description')),
                 ('guardians', models.ManyToManyField(blank=True, related_name='children', to='core.Person', verbose_name='Guardians / Parents')),
                 ('primary_group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.Group', verbose_name='Primary group')),
diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py
index 8eb2b0f23293982cb303e10e3fdb76f2858f13a4..653e8e0ee81d84be46f9a4faa9787574e5d9af68 100644
--- a/aleksis/core/mixins.py
+++ b/aleksis/core/mixins.py
@@ -433,11 +433,11 @@ class SuccessMessageMixin(ModelFormMixin):
         return super().form_valid(form)
 
 
-class AdvancedCreateView(CreateView, SuccessMessageMixin):
+class AdvancedCreateView(SuccessMessageMixin, CreateView):
     pass
 
 
-class AdvancedEditView(UpdateView, SuccessMessageMixin):
+class AdvancedEditView(SuccessMessageMixin, UpdateView):
     pass
 
 
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 73c153ba0e209e1d56aaff88868f59adf5b889fd..a04471a0084c16919a0395c2df4ff25cc46aea9f 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -4,7 +4,6 @@ from glob import glob
 from django.utils.translation import gettext_lazy as _
 
 from dynaconf import LazySettings
-from easy_thumbnails.conf import settings as thumbnail_settings
 
 from .util.core_helpers import (
     get_app_packages,
@@ -69,7 +68,6 @@ INSTALLED_APPS = [
     "django_any_js",
     "django_yarnpkg",
     "django_tables2",
-    "easy_thumbnails",
     "maintenance_mode",
     "menu_generator",
     "reversion",
@@ -160,8 +158,6 @@ TEMPLATES = [
     },
 ]
 
-THUMBNAIL_PROCESSORS = () + thumbnail_settings.THUMBNAIL_PROCESSORS
-
 WSGI_APPLICATION = "aleksis.core.wsgi.application"
 
 # Database
@@ -420,6 +416,9 @@ DBBACKUP_COMPRESS_MEDIA = _settings.get("backup.media.compress", True)
 DBBACKUP_ENCRYPT_MEDIA = _settings.get("backup.media.encrypt", DBBACKUP_GPG_RECIPIENT is not None)
 DBBACKUP_CLEANUP_DB = _settings.get("backup.database.clean", True)
 DBBACKUP_CLEANUP_MEDIA = _settings.get("backup.media.clean", True)
+DBBACKUP_CONNECTOR_MAPPING = {
+    "django_prometheus.db.backends.postgresql": "dbbackup.db.postgresql.PgDumpConnector",
+}
 
 IMPERSONATE = {"USE_HTTP_REFERER": True, "REQUIRE_SUPERUSER": True, "ALLOW_SUPERUSER": True}
 
diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index 6b5c01c6f7cb5dc1aa5511aa249c765dce2744e6..060a0ef7aee06c51efe8ef2034e32b576e37fec6 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -64,7 +64,7 @@ def dt_show_toolbar(request: HttpRequest) -> bool:
 
 def get_app_packages() -> Sequence[str]:
     """Find all registered apps from the setuptools entrypoint."""
-    return [f"{ep.module}.{ep.attr}" for ep in metadata.entry_points()["aleksis.app"]]
+    return [f"{ep.module}.{ep.attr}" for ep in metadata.entry_points().get("aleksis.app", [])]
 
 
 def merge_app_settings(
diff --git a/tox.ini b/tox.ini
index eca63a758a5f6a20b1cd11887330817fec7908d7..cbe278cd8f7b1f3cd38760cb63a1b009786edcd2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,7 @@
 [tox]
 skipsdist = True
 skip_missing_interpreters = true
-envlist = py37,py38
+envlist = py37,py38,py39
 
 [testenv]
 whitelist_externals = poetry
@@ -22,8 +22,8 @@ setenv =
 
 [testenv:lint]
 commands =
-    - poetry run black --check --diff aleksis/
-    - poetry run isort -c --diff --stdout aleksis/
+    poetry run black --check --diff aleksis/
+    poetry run isort -c --diff --stdout aleksis/
     poetry run flake8 {posargs} aleksis/
 
 [testenv:security]