diff --git a/aleksis/core/apps.py b/aleksis/core/apps.py
index 5b87a04501275c8941d01277b6afedc7f40e8656..128d6e8194e04df90526ec79e9d0c9db8d6ea377 100644
--- a/aleksis/core/apps.py
+++ b/aleksis/core/apps.py
@@ -11,3 +11,19 @@ class CoreConfig(AppConfig):
 
     def config_updated(self, *args, **kwargs) -> None:
         clean_scss()
+
+    def post_migrate(
+        self,
+        app_config: django.apps.AppConfig,
+        verbosity: int,
+        interactive: bool,
+        using: str,
+        plan: List[Tuple],
+        apps: django.apps.Apps,
+    ) -> None:
+        super().post_migrate(app_config, verbosity, interactive, using, plan, apps)
+
+        # Ensure presence of a OTP YubiKey default config
+        apps.get_model('otp_yubikey', 'ValidationService').objects.using(using).update_or_create(
+            name='default', defaults={'use_ssl': True, 'param_sl': '', 'param_timeout': ''}
+        )
diff --git a/aleksis/core/migrations/0001_initial.py b/aleksis/core/migrations/0001_initial.py
index 2d330f9504b8c4fa389ec50bc091e9b814c73a29..15eb9d297b01a571c60120dd9ce64fb8bbeca446 100644
--- a/aleksis/core/migrations/0001_initial.py
+++ b/aleksis/core/migrations/0001_initial.py
@@ -14,6 +14,7 @@ class Migration(migrations.Migration):
 
     dependencies = [
         migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('otp_yubikey', '0001_initial'),
     ]
 
     operations = [
diff --git a/aleksis/core/migrations/0006_create_default_term.py b/aleksis/core/migrations/0006_create_default_term.py
deleted file mode 100644
index 724da0cd4bdbafab986d6b072930ccdf9f1050f4..0000000000000000000000000000000000000000
--- a/aleksis/core/migrations/0006_create_default_term.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from django.db import migrations, models
-
-from datetime import date
-
-def create_or_mark_current_term(apps, schema_editor):
-    db_alias = schema_editor.connection.alias
-
-    SchoolTerm = apps.get_model('core', 'SchoolTerm')  # noqa
-
-    if not SchoolTerm.objects.filter(current=True).exists():
-        if SchoolTerm.objects.using(db_alias).exists():
-            term = SchoolTerm.objects.using(db_alias).latest('date_start')
-            term.current=True
-            term.save()
-        else:
-            SchoolTerm.objects.using(db_alias).create(date_start=date.today(), current=True)
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0005_add_verbose_names_meta'),
-    ]
-
-    operations = [
-        migrations.RunPython(create_or_mark_current_term)
-    ]
diff --git a/aleksis/core/migrations/0007_create_admin_user.py b/aleksis/core/migrations/0007_create_admin_user.py
deleted file mode 100644
index 384e7cc10f2a474817d0386faade842aea72541d..0000000000000000000000000000000000000000
--- a/aleksis/core/migrations/0007_create_admin_user.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from django.contrib.auth import get_user_model
-from django.db import migrations
-
-
-def create_superuser(apps, schema_editor):
-    User = get_user_model()
-
-    if not User.objects.filter(is_superuser=True).exists():
-        User.objects.create_superuser(
-            username='admin',
-            email='root@example.com',
-            password='admin'
-        ).save()
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0006_create_default_term'),
-    ]
-
-    operations = [
-        migrations.RunPython(create_superuser)
-    ]
-
diff --git a/aleksis/core/migrations/0008_rename_fields_notification_activity.py b/aleksis/core/migrations/0008_rename_fields_notification_activity.py
index 4197d0feda366e3f3a4af3489f23763b1ed7104d..a84117c702effe8b85d997edbd14d6b2c04d537d 100644
--- a/aleksis/core/migrations/0008_rename_fields_notification_activity.py
+++ b/aleksis/core/migrations/0008_rename_fields_notification_activity.py
@@ -7,7 +7,7 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('core', '0007_create_admin_user'),
+        ('core', '0005_add_verbose_names_meta.py'),
     ]
 
     operations = [
diff --git a/aleksis/core/migrations/0010_create_validation_service.py b/aleksis/core/migrations/0010_create_validation_service.py
deleted file mode 100644
index e314a80a0d9bdd1cbe1a51c7f590590ed94ecc19..0000000000000000000000000000000000000000
--- a/aleksis/core/migrations/0010_create_validation_service.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from django.db import migrations
-
-
-def create_validation_service(apps, schema_editor):
-    apps.get_model('otp_yubikey', 'ValidationService').objects.update_or_create(
-        name='default', defaults={'use_ssl': True, 'param_sl': '', 'param_timeout': ''}
-    )
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0009_dashboard_widget'),
-        ('otp_yubikey', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.RunPython(create_validation_service)
-    ]
-
diff --git a/aleksis/core/migrations/0011_make_primary_group_optional.py b/aleksis/core/migrations/0011_make_primary_group_optional.py
index 1a4d47137201a3bd2aef5e6e4991768259b9fad0..e081ad5f0317594adff50aaebfaa598b00605afb 100644
--- a/aleksis/core/migrations/0011_make_primary_group_optional.py
+++ b/aleksis/core/migrations/0011_make_primary_group_optional.py
@@ -7,7 +7,7 @@ import django.db.models.deletion
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('core', '0010_create_validation_service'),
+        ('core', '0009_dashboard_widget.py'),
     ]
 
     operations = [
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index fc5a86f95483cf4ee8b97f5437397d0855e8e555..c97d95f464c2ae6c999264d55753b3cdff94c90a 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -1,3 +1,4 @@
+from datetime import date
 from typing import Optional
 
 from django.contrib.auth import get_user_model
@@ -62,6 +63,16 @@ class SchoolTerm(ExtensibleModel):
             self.current = None
         super().save(*args, **kwargs)
 
+    @classmethod
+    def maintain_default_data(cls):
+        if not cls.objects.filter(current=True).exists():
+            if cls.objects.exists():
+                term = cls.objects.latest('date_start')
+                term.current=True
+                term.save()
+            else:
+                cls.objects.create(date_start=date.today(), current=True)
+
     class Meta:
         verbose_name = _("School term")
         verbose_name_plural = _("School terms")
@@ -171,6 +182,22 @@ class Person(ExtensibleModel):
     def __str__(self) -> str:
         return self.full_name
 
+    @classmethod
+    def maintain_default_data(cls):
+        # First, ensure we have an admin user
+        User = get_user_model()
+        if not User.objects.filter(is_superuser=True).exists():
+            admin = User.objects.create_superuser(
+                username='admin',
+                email='root@example.com',
+                password='admin'
+            )
+            admin.save()
+
+            # Ensure this admin user has a person linked to it
+            person = Person(user=admin)
+            person.save()
+
 
 class Group(ExtensibleModel):
     """Any kind of group of persons in a school, including, but not limited