diff --git a/aleksis/core/admin.py b/aleksis/core/admin.py
index 24c7905093be9974a267b4ac2dfdbf97a18c1508..248603bf18e8a1cfcf74b2379107edede34311c3 100644
--- a/aleksis/core/admin.py
+++ b/aleksis/core/admin.py
@@ -1,5 +1,7 @@
 from django.contrib import admin
 
+from reversion.admin import VersionAdmin
+
 from .mixins import BaseModelAdmin
 from .models import (
     Group,
@@ -14,24 +16,20 @@ from .models import (
 )
 
 
-class PersonAdmin(BaseModelAdmin):
-    pass
-
-
-admin.site.register(Person, PersonAdmin)
-admin.site.register(Group)
-admin.site.register(School)
-admin.site.register(SchoolTerm)
-admin.site.register(Activity)
-admin.site.register(Notification)
-admin.site.register(CustomMenuItem)
+admin.site.register(Person, VersionAdmin)
+admin.site.register(Group, VersionAdmin)
+admin.site.register(School, VersionAdmin)
+admin.site.register(SchoolTerm, VersionAdmin)
+admin.site.register(Activity, VersionAdmin)
+admin.site.register(Notification, VersionAdmin)
+admin.site.register(CustomMenuItem, VersionAdmin)
 
 
 class AnnouncementRecipientInline(admin.StackedInline):
     model = AnnouncementRecipient
 
 
-class AnnouncementAdmin(BaseModelAdmin):
+class AnnouncementAdmin(BaseModelAdmin, VersionAdmin):
     inlines = [
         AnnouncementRecipientInline,
     ]
diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py
index 15b5c0c67c21a3cf473eda2b1c8637db849125b2..3c3ed2238494133513c08633b1254cd83a947733 100644
--- a/aleksis/core/mixins.py
+++ b/aleksis/core/mixins.py
@@ -10,6 +10,7 @@ from easyaudit.models import CRUDEvent
 from guardian.admin import GuardedModelAdmin
 from jsonstore.fields import JSONField, JSONFieldMixin
 from material.base import LayoutNode, Layout
+import reversion
 from rules.contrib.admin import ObjectPermissionsModelAdmin
 
 
@@ -28,6 +29,7 @@ class CRUDMixin(models.Model):
         ).select_related("user")
 
 
+@reversion.register()
 class ExtensibleModel(CRUDMixin):
     """ Base model for all objects in AlekSIS apps
 
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index eb92cb5d714aa3d538e9a407677b06f9cdc664ce..e072f0e2b6fa08add45f4cdbcba4a46fac81a42d 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -569,6 +569,7 @@ class CustomMenuItem(ExtensibleModel):
         verbose_name = _("Custom menu item")
         verbose_name_plural = _("Custom menu items")
 
+
 class GroupType(ExtensibleModel):
     name = models.CharField(verbose_name=_("Title of type"), max_length=50)
     description = models.CharField(verbose_name=_("Description"), max_length=500)
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 04728798c6552e2eca84712c1fc8364aacb45601..6fd8e14951bb0585f2138a37fe384d726f0b4ccc 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -75,6 +75,7 @@ INSTALLED_APPS = [
     "image_cropping",
     "maintenance_mode",
     "menu_generator",
+    "reversion",
     "phonenumber_field",
     "debug_toolbar",
     "django_select2",
diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh
index 8c9c64e55abb848ae6d67d42f99e5434f9916a94..4b68fa884420b1a40ed34d4bd4410aabd2ac1e3f 100755
--- a/docker/entrypoint.sh
+++ b/docker/entrypoint.sh
@@ -20,6 +20,7 @@ done
 python manage.py compilescss
 python manage.py collectstatic --no-input --clear
 python manage.py migrate
+python manage.py createinitialrevisions
 
 ARG=${$1:-"gunicorn"}
 
diff --git a/docs/dev/01_setup.rst b/docs/dev/01_setup.rst
index 880737d3087915f4e9cc8c9c76485b923e77243a..df0ffd11c21112912f0934c9f16aed909bd8cbb9 100644
--- a/docs/dev/01_setup.rst
+++ b/docs/dev/01_setup.rst
@@ -70,6 +70,7 @@ All three steps can be done with the ``poetry run`` command and
   poetry run ./manage.py collectstatic
   poetry run ./manage.py compilemessages
   poetry run ./manage.py migrate
+  poetry run ./manage.py createinitialrevisions
 
 (You might need database settings for the `migrate` command; see below.)
 
diff --git a/pyproject.toml b/pyproject.toml
index b0e9c84ee4820832417255a8f290c762fe270206..118325ec2e47142790983685cc36bb77531ccf03 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -75,6 +75,7 @@ celery-haystack = {version="^0.3.1", optional=true}
 django-dbbackup = "^3.3.0"
 spdx-license-list = "^0.4.0"
 license-expression = "^1.2"
+django-reversion = "^3.0.7"
 
 [tool.poetry.extras]
 ldap = ["django-auth-ldap"]