diff --git a/hypha/apply/funds/templates/funds/round.html b/hypha/apply/funds/templates/funds/round.html
index c3b5e925cc5e16133504d3ae0d2cb1d33679bf16..7bb3cb704e412538da5ec0ec67b753a52d850c44 100644
--- a/hypha/apply/funds/templates/funds/round.html
+++ b/hypha/apply/funds/templates/funds/round.html
@@ -6,8 +6,8 @@
 
 {% block header_menu %}
     <section class="header__menus header__menus--desktop">
-        {% if settings.utils.SystemMessagesSettings.nav_content %}
-            {{ settings.utils.SystemMessagesSettings.nav_content|safe }}
+        {% if settings.core.SystemSettings.nav_content %}
+            {{ settings.core.SystemSettings.nav_content|safe }}
         {% else %}
             {% include "core/navigation/primarynav-apply.html" %}
         {% endif %}
diff --git a/hypha/apply/utils/templates/apply/403.html b/hypha/apply/utils/templates/apply/403.html
deleted file mode 100644
index dc66c58154cb9a5a8ff7ae0f87643d878e7c0fb8..0000000000000000000000000000000000000000
--- a/hypha/apply/utils/templates/apply/403.html
+++ /dev/null
@@ -1,13 +0,0 @@
-{% extends "base-apply.html" %}
-{% load wagtailcore_tags wagtailsettings_tags %}
-
-{% block title %}{{ settings.utils.SystemMessagesSettings.title_403 }}{% endblock %}
-
-{% block body_class %}template-403{% endblock %}
-
-{% block content %}
-    <div class="wrapper wrapper--small wrapper--inner-space-large">
-        <h1>{{ settings.utils.SystemMessagesSettings.title_403 }}</h1>
-        <div class="rich-text">{{ settings.utils.SystemMessagesSettings.body_403|richtext }}</div>
-    </div>
-{% endblock %}
diff --git a/hypha/apply/utils/templates/apply/404.html b/hypha/apply/utils/templates/apply/404.html
deleted file mode 100644
index 52077dd8285315fc3b8fb4cdff09558fad6e9958..0000000000000000000000000000000000000000
--- a/hypha/apply/utils/templates/apply/404.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% extends "base-apply.html" %}
-{% load wagtailcore_tags wagtailsettings_tags %}
-
-{% block title %}{{ settings.utils.SystemMessagesSettings.title_404 }}{% endblock %}
-
-{% block body_class %}template-404{% endblock %}
-
-{% block content %}
-    <div class="wrapper wrapper--small wrapper--inner-space-large">
-        <h1>{{ settings.utils.SystemMessagesSettings.title_404 }}</h1>
-        <p>If you typed the web address, check it is correct.</p>
-        <p>If you pasted the web address, check you copied the entire address.</p>
-        <div class="rich-text">{{ settings.utils.SystemMessagesSettings.body_404|richtext }}</div>
-    </div>
-{% endblock %}
diff --git a/hypha/apply/utils/views.py b/hypha/apply/utils/views.py
index a3bc8f408354b2598c5ad1a98c627d961e06800e..f04e933d39e773eeeef55f6da19ca5ae1d017b0b 100644
--- a/hypha/apply/utils/views.py
+++ b/hypha/apply/utils/views.py
@@ -5,7 +5,6 @@ from django.http import HttpResponseForbidden
 from django.shortcuts import get_object_or_404, redirect
 from django.utils.decorators import method_decorator
 from django.utils.translation import gettext as _
-from django.views import defaults
 from django.views.generic import View
 from django.views.generic.base import ContextMixin
 from django.views.generic.detail import SingleObjectTemplateResponseMixin
@@ -16,18 +15,6 @@ from wagtail.admin.views.pages.delete import delete
 from wagtail.models import Page
 
 
-def page_not_found(request, exception=None, template_name="apply/404.html"):
-    if not request.user.is_authenticated:
-        template_name = "404.html"
-    return defaults.page_not_found(request, exception, template_name)
-
-
-def permission_denied(request, exception=None, template_name="apply/403.html"):
-    if not request.user.is_authenticated:
-        template_name = "403.html"
-    return defaults.permission_denied(request, exception, template_name)
-
-
 @method_decorator(login_required, name="dispatch")
 class ViewDispatcher(View):
     admin_view: View = None
diff --git a/hypha/core/migrations/0003_initial.py b/hypha/core/migrations/0003_initial.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed0a721f0f4b12ef429af5c148c01ee4752a43ce
--- /dev/null
+++ b/hypha/core/migrations/0003_initial.py
@@ -0,0 +1,110 @@
+# Generated by Django 4.2.11 on 2024-03-11 08:01
+
+from django.db import migrations, models
+import django.db.models.deletion
+import wagtail.fields
+
+
+class Migration(migrations.Migration):
+    initial = True
+
+    dependencies = [
+        ("images", "0006_alter_rendition_file"),
+        ("core", "0002_auto_20240215_remove_mailhimp"),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="SystemSettings",
+            fields=[
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "site_logo_link",
+                    models.URLField(
+                        blank=True,
+                        default="",
+                        help_text='Link for the site logo, e.g. "https://www.example.org/". If not set, defaults to page with slug set to "home".',
+                    ),
+                ),
+                (
+                    "nav_content",
+                    models.TextField(
+                        blank=True,
+                        help_text="This will overwrite the default front page navigation bar, html tags is allowed.",
+                        verbose_name="Front page navigation content",
+                    ),
+                ),
+                (
+                    "footer_content",
+                    models.TextField(
+                        blank=True,
+                        default="<p>Configure this text in Wagtail admin -> Settings -> System settings.</p>",
+                        help_text="This will be added to the footer, html tags is allowed.",
+                        verbose_name="Footer content",
+                    ),
+                ),
+                (
+                    "title_404",
+                    models.CharField(
+                        default="Page not found", max_length=255, verbose_name="Title"
+                    ),
+                ),
+                (
+                    "body_404",
+                    wagtail.fields.RichTextField(
+                        default="<p>You may be trying to find a page that doesn&rsquo;t exist or has been moved.</p>",
+                        verbose_name="Text",
+                    ),
+                ),
+                (
+                    "title_403",
+                    models.CharField(
+                        default="Permission Denied",
+                        max_length=255,
+                        verbose_name="Title",
+                    ),
+                ),
+                (
+                    "body_403",
+                    wagtail.fields.RichTextField(
+                        default="<p>You might not have access to the requested resource.</p>",
+                        verbose_name="Text",
+                    ),
+                ),
+                (
+                    "site_logo_default",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Default site logo",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="images.customimage",
+                    ),
+                ),
+                (
+                    "site_logo_mobile",
+                    models.ForeignKey(
+                        blank=True,
+                        help_text="Mobil site logo (if not set default will be used)",
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="images.customimage",
+                    ),
+                ),
+            ],
+            options={
+                "verbose_name": "System settings",
+                "db_table": "system_settings",
+            },
+        ),
+    ]
diff --git a/hypha/core/migrations/0004_move_system_settings_data.py b/hypha/core/migrations/0004_move_system_settings_data.py
new file mode 100644
index 0000000000000000000000000000000000000000..5331655c8d0ad2cb450b6d9efd9e97b8474e5bdf
--- /dev/null
+++ b/hypha/core/migrations/0004_move_system_settings_data.py
@@ -0,0 +1,42 @@
+# Generated by Django 4.2.11 on 2024-03-11 08:02
+
+from django.db import migrations
+
+
+def copy_public_system_messages_settings(apps, schema_editor):
+    if not apps.is_installed("utils"):
+        return
+
+    SystemSettings = apps.get_model("core", "SystemSettings")
+    PublicSystemMessages = apps.get_model("utils", "SystemMessagesSettings")
+
+    for old_settings in PublicSystemMessages.objects.all():
+        SystemSettings.objects.create(
+            site_logo_default=old_settings.site_logo_default,
+            site_logo_mobile=old_settings.site_logo_mobile,
+            site_logo_link=old_settings.site_logo_link,
+            nav_content=old_settings.nav_content,
+            footer_content=old_settings.footer_content,
+            title_404=old_settings.title_404,
+            body_404=old_settings.body_404,
+            title_403=old_settings.title_403,
+            body_403=old_settings.body_403,
+        )
+
+
+def reverse_copy_public_system_messages_settings(apps, schema_editor):
+    SystemSettings = apps.get_model("core", "SystemSettings")
+    SystemSettings.objects.all().delete()
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("core", "0003_initial"),
+    ]
+
+    operations = [
+        migrations.RunPython(
+            copy_public_system_messages_settings,
+            reverse_copy_public_system_messages_settings,
+        ),
+    ]
diff --git a/hypha/core/models/__init__.py b/hypha/core/models/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3cfea00fc05a1e840cc0b0d6842b6e13df673c86
--- /dev/null
+++ b/hypha/core/models/__init__.py
@@ -0,0 +1,3 @@
+from .system_settings import SystemSettings
+
+__all__ = ["SystemSettings"]
diff --git a/hypha/public/utils/models.py b/hypha/core/models/system_settings.py
similarity index 96%
rename from hypha/public/utils/models.py
rename to hypha/core/models/system_settings.py
index 591759fec427924583207893258eb0fa1f27c542..f3307bc7bf0320e48d0e7ee612b910cf949d7b94 100644
--- a/hypha/public/utils/models.py
+++ b/hypha/core/models/system_settings.py
@@ -12,11 +12,10 @@ from wagtail.fields import RichTextField
 
 
 @register_setting
-class SystemMessagesSettings(BaseGenericSetting):
-    wagtail_reference_index_ignore = True
-
+class SystemSettings(BaseGenericSetting):
     class Meta:
         verbose_name = "System settings"
+        db_table = "system_settings"
 
     site_logo_default = models.ForeignKey(
         "images.CustomImage",
diff --git a/hypha/home/templates/apply_home/apply_home_page.html b/hypha/home/templates/apply_home/apply_home_page.html
index 3b870184daa110a791e9b9a96ccac56719fde2fd..8fcf67bb81519f353b6494af9979dcbfebd3ce8a 100644
--- a/hypha/home/templates/apply_home/apply_home_page.html
+++ b/hypha/home/templates/apply_home/apply_home_page.html
@@ -3,8 +3,8 @@
 
 {% block header_menu %}
     <section class="header__menus header__menus--desktop">
-        {% if settings.utils.SystemMessagesSettings.nav_content %}
-            {{ settings.utils.SystemMessagesSettings.nav_content|safe }}
+        {% if settings.core.SystemSettings.nav_content %}
+            {{ settings.core.SystemSettings.nav_content|safe }}
         {% else %}
             {% include "core/navigation/primarynav-apply.html" %}
         {% endif %}
diff --git a/hypha/public/utils/migrations/0013_delete_systemmessagessettings.py b/hypha/public/utils/migrations/0013_delete_systemmessagessettings.py
new file mode 100644
index 0000000000000000000000000000000000000000..7b15311ac434176201ce18b333066062297b688e
--- /dev/null
+++ b/hypha/public/utils/migrations/0013_delete_systemmessagessettings.py
@@ -0,0 +1,16 @@
+# Generated by Django 4.2.11 on 2024-03-11 16:36
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("utils", "0012_alter_systemmessagessettings_footer_content"),
+        ("core", "0004_move_system_settings_data"),
+    ]
+
+    operations = [
+        migrations.DeleteModel(
+            name="SystemMessagesSettings",
+        ),
+    ]
diff --git a/hypha/templates/403.html b/hypha/templates/403.html
index 6a457099ad0817a62ad7a1e95994633f68a38548..eda2005db0ab5b33b6145a24ead6bdc1a40ba782 100644
--- a/hypha/templates/403.html
+++ b/hypha/templates/403.html
@@ -1,13 +1,13 @@
-{% extends "base.html" %}
+{% extends "base-apply.html" %}
 {% load wagtailcore_tags wagtailsettings_tags %}
 
-{% block title %}{{ settings.utils.SystemMessagesSettings.title_403 }}{% endblock %}
+{% block title %}{{ settings.core.SystemSettings.title_403 }}{% endblock %}
 
 {% block body_class %}template-403{% endblock %}
 
 {% block content %}
     <div class="wrapper wrapper--small wrapper--inner-space-large">
-        <h1>{{ settings.utils.SystemMessagesSettings.title_403 }}</h1>
-        <div class="rich-text">{{ settings.utils.SystemMessagesSettings.body_403|richtext }}</div>
+        <h1>{{ settings.core.SystemSettings.title_403 }}</h1>
+        <div class="rich-text">{{ settings.core.SystemSettings.body_403|richtext }}</div>
     </div>
 {% endblock %}
diff --git a/hypha/templates/404.html b/hypha/templates/404.html
index 7807d6b1ecebbb47e3e07c27a896e189a851656b..efd09bcee424b905eccf0e5e6cb0b161af4c14d8 100644
--- a/hypha/templates/404.html
+++ b/hypha/templates/404.html
@@ -1,13 +1,13 @@
-{% extends "base.html" %}
+{% extends "base-apply.html" %}
 {% load wagtailcore_tags wagtailsettings_tags %}
 
-{% block title %}{{ settings.utils.SystemMessagesSettings.title_404 }}{% endblock %}
+{% block title %}{{ settings.core.SystemSettings.title_404 }}{% endblock %}
 
 {% block body_class %}template-404{% endblock %}
 
 {% block content %}
     <div class="wrapper wrapper--small wrapper--inner-space-large">
-        <h1>{{ settings.utils.SystemMessagesSettings.title_404 }}</h1>
-        <div class="rich-text">{{ settings.utils.SystemMessagesSettings.body_404|richtext }}</div>
+        <h1>{{ settings.core.SystemSettings.title_404 }}</h1>
+        <div class="rich-text">{{ settings.core.SystemSettings.body_404|richtext }}</div>
     </div>
 {% endblock %}
diff --git a/hypha/templates/base-apply.html b/hypha/templates/base-apply.html
index 0c393448e30246bfcf1697d0b93e2b1780e6fb46..d10900a315c0f02c9f13105c15ec0ec1133f9988 100644
--- a/hypha/templates/base-apply.html
+++ b/hypha/templates/base-apply.html
@@ -4,26 +4,26 @@
 {% block header %}
     <header class="header">
         <div class="header__inner wrapper wrapper--large">
-            <a href="{{ settings.utils.SystemMessagesSettings.site_logo_link|default:"/" }}" aria-label="{% trans "Home link" %}">
-                {% if settings.utils.SystemMessagesSettings.site_logo_default %}
-                    {% image settings.utils.SystemMessagesSettings.site_logo_default width-215 as logo_default %}
+            <a href="{{ settings.core.SystemSettings.site_logo_link|default:"/" }}" aria-label="{% trans "Home link" %}">
+                {% if settings.core.SystemSettings.site_logo_default %}
+                    {% image settings.core.SystemSettings.site_logo_default width-215 as logo_default %}
                     <img class="header__logo header__logo--desktop"
                          width="215"
                          src="{{ logo_default.url }}"
-                         alt="{{ settings.utils.SystemMessagesSettings.site_logo_default.alt }}"
+                         alt="{{ settings.core.SystemSettings.site_logo_default.alt }}"
                     >
-                    {% if settings.utils.SystemMessagesSettings.site_logo_mobile %}
-                        {% image settings.utils.SystemMessagesSettings.site_logo_mobile width-60 as logo_mobile %}
+                    {% if settings.core.SystemSettings.site_logo_mobile %}
+                        {% image settings.core.SystemSettings.site_logo_mobile width-60 as logo_mobile %}
                         <img class="header__logo header__logo--mobile"
                              width="60"
                              src="{{ logo_mobile.url }}"
-                             alt="{{ settings.utils.SystemMessagesSettings.site_logo_mobile.alt }}"
+                             alt="{{ settings.core.SystemSettings.site_logo_mobile.alt }}"
                         >
                     {% else %}
                         <img class="header__logo header__logo--mobile"
                              width="60"
                              src="{{ logo_default.url }}"
-                             alt="{{ settings.utils.SystemMessagesSettings.site_logo_default.alt }}"
+                             alt="{{ settings.core.SystemSettings.site_logo_default.alt }}"
                         >
                     {% endif %}
                 {% else %}
@@ -62,13 +62,13 @@
 
             <section class="header__menus header__menus--mobile">
                 <div class="header__inner header__inner--menu-open">
-                    <a href="{{ settings.utils.SystemMessagesSettings.site_logo_link|default:"/" }}" aria-label="Home link">
-                        {% if settings.utils.SystemMessagesSettings.site_logo_mobile %}
-                            {% image settings.utils.SystemMessagesSettings.site_logo_mobile width-60 as logo_mobile %}
+                    <a href="{{ settings.core.SystemSettings.site_logo_link|default:"/" }}" aria-label="Home link">
+                        {% if settings.core.SystemSettings.site_logo_mobile %}
+                            {% image settings.core.SystemSettings.site_logo_mobile width-60 as logo_mobile %}
                             <img class="header__logo header__logo--mobile"
                                  width="60"
                                  src="{{ logo_mobile.url }}"
-                                 alt="{{ settings.utils.SystemMessagesSettings.site_logo_mobile.alt }}"
+                                 alt="{{ settings.core.SystemSettings.site_logo_mobile.alt }}"
                             >
                         {% else %}
                             <img class="header__logo header__logo--mobile"
@@ -133,10 +133,10 @@
 {% endblock header %}
 
 {% block footer %}
-    {% if settings.utils.SystemMessagesSettings.footer_content %}
+    {% if settings.core.SystemSettings.footer_content %}
         <footer class="footer px-4 py-10 shrink-0  bg-dark-blue">
             <div class="wrapper wrapper--large prose prose-invert max-w-none text-white">
-                {{ settings.utils.SystemMessagesSettings.footer_content|safe }}
+                {{ settings.core.SystemSettings.footer_content|safe }}
             </div>
         </footer>
     {% endif %}
diff --git a/hypha/templates/styleguide.html b/hypha/templates/styleguide.html
index fa572c662315cee0d4aa8d80718ed0492adac70d..5cb8677df01b10dff7c243a12b57b4e201f8b5b3 100644
--- a/hypha/templates/styleguide.html
+++ b/hypha/templates/styleguide.html
@@ -38,11 +38,11 @@
 
             <div class="header__inner wrapper wrapper--large">
                 <a href="{% site_logo_link current_site %}" aria-label="Home link">
-                    {% if settings.utils.SystemMessagesSettings.site_logo_default %}
-                        {% image settings.utils.SystemMessagesSettings.site_logo_default width-215 as logo_default %}
+                    {% if settings.core.SystemSettings.site_logo_default %}
+                        {% image settings.core.SystemSettings.site_logo_default width-215 as logo_default %}
                         <img class="header__logo header__logo--desktop" src="{{ logo_default.url }}">
-                        {% if settings.utils.SystemMessagesSettings.site_logo_mobile %}
-                            {% image settings.utils.SystemMessagesSettings.site_logo_mobile width-60 as logo_mobile %}
+                        {% if settings.core.SystemSettings.site_logo_mobile %}
+                            {% image settings.core.SystemSettings.site_logo_mobile width-60 as logo_mobile %}
                             <img class="header__logo header__logo--mobile" src="{{ logo_mobile.url }}">
                         {% else %}
                             <img class="header__logo header__logo--mobile" src="{{ logo_default.url }}">
diff --git a/hypha/urls.py b/hypha/urls.py
index f7f50a6b1d34a1a5f020024262908080a9663272..b1e18c027f7461d6d12be75b53fcfaeab7bef4f3 100644
--- a/hypha/urls.py
+++ b/hypha/urls.py
@@ -17,9 +17,6 @@ from hypha.apply.users.urls import urlpatterns as user_urls
 from hypha.apply.users.views import become
 from hypha.apply.utils.views import custom_wagtail_page_delete
 
-handler404 = "hypha.apply.utils.views.page_not_found"
-handler403 = "hypha.apply.utils.views.permission_denied"
-
 urlpatterns = [
     path("apply/", include("hypha.apply.funds.urls", "apply")),
     path("activity/", include("hypha.apply.activity.urls", "activity")),
@@ -54,15 +51,31 @@ if settings.HIJACK_ENABLE:
 if settings.DEBUG:
     from django.conf.urls.static import static
     from django.contrib.staticfiles.urls import staticfiles_urlpatterns
+    from django.urls import get_callable
+    from django.views import defaults as dj_default_views
 
     # Serve static and media files from development server
     urlpatterns += staticfiles_urlpatterns()
     urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 
     urlpatterns += [
-        # Add views for testing 404 and 500 templates
-        path("test404/", TemplateView.as_view(template_name="404.html")),
-        path("test500/", TemplateView.as_view(template_name="500.html")),
+        path(
+            "test400/",
+            dj_default_views.bad_request,
+            kwargs={"exception": Exception("Bad Request!")},
+        ),
+        path(
+            "test403/",
+            dj_default_views.permission_denied,
+            kwargs={"exception": Exception("Permission Denied!")},
+        ),
+        path("test403_csrf/", get_callable(settings.CSRF_FAILURE_VIEW)),
+        path(
+            "test404/",
+            dj_default_views.page_not_found,
+            kwargs={"exception": Exception("Not Found!")},
+        ),
+        path("test500/", dj_default_views.server_error),
     ]
 
 if settings.DEBUG or settings.ENABLE_STYLEGUIDE: