diff --git a/opentech/apply/urls.py b/opentech/apply/urls.py
index 27483633b8fb3bad18a4649f396e9a4a7758cc62..deb32700492d24ef9fe3db8d49680f0241fcb757 100644
--- a/opentech/apply/urls.py
+++ b/opentech/apply/urls.py
@@ -1,9 +1,11 @@
+from django.conf import settings
 from django.urls import include, path
 
+from .utils import views
 from .users import urls as users_urls
 from .dashboard import urls as dashboard_urls
 
-from opentech.urls import urlpatterns as base_urlpatterns
+from opentech.urls import base_urlpatterns
 
 
 urlpatterns = [
@@ -14,4 +16,13 @@ urlpatterns = [
     path('hijack/', include('hijack.urls', 'hijack')),
 ]
 
+if settings.DEBUG:
+    urlpatterns += [
+        # Add views for testing 404 and 500 templates
+        path('test404/', views.page_not_found),
+    ]
+
 urlpatterns += base_urlpatterns
+
+
+handler404 = 'opentech.apply.utils.views.page_not_found'
diff --git a/opentech/apply/utils/__init__.py b/opentech/apply/utils/__init__.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..406254cfe657826bdc2a6ce7992d38cb46a4af9f 100644
--- a/opentech/apply/utils/__init__.py
+++ b/opentech/apply/utils/__init__.py
@@ -0,0 +1 @@
+default_app_config = 'opentech.apply.utils.app.UtilsConfig'
diff --git a/opentech/apply/utils/app.py b/opentech/apply/utils/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7215b4e1eb04ecd21099117b9989161f82be7ad
--- /dev/null
+++ b/opentech/apply/utils/app.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class UtilsConfig(AppConfig):
+    name = 'opentech.apply.utils'
+    label = 'apply_utils'
diff --git a/opentech/apply/utils/templates/apply/404.html b/opentech/apply/utils/templates/apply/404.html
new file mode 100644
index 0000000000000000000000000000000000000000..30b1072c3da83893225f7fe931f2292f5f4b5651
--- /dev/null
+++ b/opentech/apply/utils/templates/apply/404.html
@@ -0,0 +1,13 @@
+{% 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>
+    {{ settings.utils.SystemMessagesSettings.body_404|richtext }}
+</div>
+{% endblock %}
diff --git a/opentech/apply/utils/views.py b/opentech/apply/utils/views.py
index d77666e5accbec25b5f044e3b5b315c3915341dc..87932814703c400b72c81e554d1bc1695c9e806e 100644
--- a/opentech/apply/utils/views.py
+++ b/opentech/apply/utils/views.py
@@ -1,10 +1,17 @@
 from django.contrib.auth.decorators import login_required
 from django.utils.decorators import method_decorator
+from django.views import defaults
 from django.views.generic import DetailView, View
 from django.views.generic.detail import SingleObjectTemplateResponseMixin
 from django.views.generic.edit import ModelFormMixin, ProcessFormView
 
 
+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)
+
+
 @method_decorator(login_required, name='dispatch')
 class ViewDispatcher(View):
     admin_view: View = None
diff --git a/opentech/public/mailchimp/templates/mailchimp/newsletter_signup.html b/opentech/public/mailchimp/templates/mailchimp/newsletter_signup.html
index 1bd9984c700dee25081225c9309e896eb011efed..d45a2dfd5298a870f4c0c8c42a49533f8aebf4db 100644
--- a/opentech/public/mailchimp/templates/mailchimp/newsletter_signup.html
+++ b/opentech/public/mailchimp/templates/mailchimp/newsletter_signup.html
@@ -1,5 +1,5 @@
 <h4>Get the latest internet freedom news</h4>
-<form class="form" action="{% url "newsletter:subscribe" %}" method="post">
+<form class="form" action="{{ PUBLIC_SITE.root_url }}{% url "newsletter:subscribe" %}" method="post">
     <div>
         {% for field in newsletter_form %}
         <label for="{{ field.id_for_label }}"{% if field.field.required %} required{% endif %}>
diff --git a/opentech/public/search/views.py b/opentech/public/search/views.py
index 63031455fffca994a04892891a63b22de1fa91d3..a3aa058ae5361db6acfb7cd267ee70bd73ff02d9 100644
--- a/opentech/public/search/views.py
+++ b/opentech/public/search/views.py
@@ -1,11 +1,17 @@
 from django.conf import settings
 from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
+from django.http import Http404
 from django.shortcuts import render
 from wagtail.core.models import Page
 from wagtail.search.models import Query
 
+from opentech.public.home.models import HomePage
+
 
 def search(request):
+    if request.site != HomePage.objects.first().get_site():
+        raise Http404
+
     search_query = request.GET.get('query', None)
     page = request.GET.get('page', 1)
 
diff --git a/opentech/settings/base.py b/opentech/settings/base.py
index fcc8b176491a55f3f33252a97ba5eb5f35808816..9dd20ddfa73ef003f5011bea3c2fded7b4c02cdc 100644
--- a/opentech/settings/base.py
+++ b/opentech/settings/base.py
@@ -73,6 +73,7 @@ INSTALLED_APPS = [
     'opentech.apply.review',
     'opentech.apply.determinations',
     'opentech.apply.stream_forms',
+    'opentech.apply.utils',
 
     'opentech.public.funds',
     'opentech.public.home',
diff --git a/opentech/templates/base.html b/opentech/templates/base.html
index 94e1cd306d2ef3fa48167831508a0af03cccee3a..0844af725b963c8d288c791f1eeea958e0afb73d 100644
--- a/opentech/templates/base.html
+++ b/opentech/templates/base.html
@@ -129,7 +129,7 @@
                 </div>
 
                 <div class="header__search">
-                    <form action="{% url 'search' %}" method="get" role="search" class="form form--header-search-desktop">
+                    <form action="{{ PUBLIC_SITE.root_url }}{% url 'search' %}" method="get" role="search" class="form form--header-search-desktop">
                         <button class="button" type="submit" aria-label="Search">
                             <svg class="icon icon--magnifying-glass icon--search"><use xlink:href="#magnifying-glass"></use></svg>
                         </button>
diff --git a/opentech/urls.py b/opentech/urls.py
index 8cb2fe3067cbc3bd1c7e042adb4d2243ae8c6b07..e6845757630e342d14af0be4b2e95fdb6cd03a13 100644
--- a/opentech/urls.py
+++ b/opentech/urls.py
@@ -14,14 +14,27 @@ from opentech.public import urls as public_urls
 from opentech.apply.users.urls import public_urlpatterns as user_urls
 
 
+def apply_cache_control(*patterns):
+    # Cache-control
+    cache_length = getattr(settings, 'CACHE_CONTROL_MAX_AGE', None)
+
+    if cache_length:
+        patterns = decorate_urlpatterns(
+            patterns,
+            cache_control(max_age=cache_length)
+        )
+
+    return list(patterns)
+
+
 urlpatterns = [
     path('django-admin/', admin.site.urls),
     path('admin/', include(wagtailadmin_urls)),
 
     path('documents/', include(wagtaildocs_urls)),
     path('sitemap.xml', sitemap),
-    path('', include(public_urls)),
     path('', include((user_urls, 'users_public'))),
+    path('', include(public_urls)),
     path('', include('social_django.urls', namespace='social')),
     path('tinymce/', include('tinymce.urls')),
     path('select2/', include('django_select2.urls')),
@@ -52,18 +65,14 @@ urlpatterns += [
     path('', include(wagtail_urls)),
 ]
 
+urlpatterns = apply_cache_control(*urlpatterns)
 
-# Cache-control
-cache_length = getattr(settings, 'CACHE_CONTROL_MAX_AGE', None)
-
-if cache_length:
-    urlpatterns = decorate_urlpatterns(
-        urlpatterns,
-        cache_control(max_age=cache_length)
-    )
 
 if settings.DEBUG and settings.DEBUGTOOLBAR:
     import debug_toolbar
     urlpatterns = [
         path('__debug__/', include(debug_toolbar.urls)),
     ] + urlpatterns
+
+
+base_urlpatterns = [*urlpatterns]