diff --git a/.gitignore b/.gitignore
index 5b31142..542fc9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,4 @@ __pycache__
 /nummi-git/
 /pkg/
 /src/
-/nummi/media
+/media
diff --git a/nummi/main/urls.py b/nummi/main/urls.py
index 1db30b0..cb48dca 100644
--- a/nummi/main/urls.py
+++ b/nummi/main/urls.py
@@ -4,7 +4,6 @@ from . import views
 
 urlpatterns = [
     path("", views.IndexView.as_view(), name="index"),
-    path("media/user/<username>/<path:path>", views.MediaView.as_view(), name="media"),
     path("login", views.LoginView.as_view(), name="login"),
     path("logout", views.LogoutView.as_view(), name="logout"),
     path("transactions", views.TransactionListView.as_view(), name="transactions"),
diff --git a/nummi/main/views.py b/nummi/main/views.py
index b40c629..efadff2 100644
--- a/nummi/main/views.py
+++ b/nummi/main/views.py
@@ -1,4 +1,3 @@
-from django.conf import settings
 from django.contrib.auth import views as auth_views
 from django.contrib.auth.mixins import LoginRequiredMixin
 from django.contrib.postgres.search import (
@@ -7,12 +6,9 @@ from django.contrib.postgres.search import (
     SearchVector,
     TrigramSimilarity,
 )
-from django.core.exceptions import PermissionDenied
 from django.db import models
-from django.http import HttpResponse
 from django.shortcuts import get_object_or_404, redirect
 from django.urls import reverse_lazy
-from django.views import View
 from django.views.generic import (
     CreateView,
     DeleteView,
@@ -22,7 +18,6 @@ from django.views.generic import (
     UpdateView,
 )
 from django.views.generic.dates import MonthArchiveView
-from django.views.static import serve
 
 from .forms import (
     AccountForm,
@@ -417,22 +412,6 @@ class SearchView(TransactionListView):
         return super().get_context_data(**kwargs) | {"search": self.kwargs["search"]}
 
 
-class MediaView(LoginRequiredMixin, View):
-    def get(self, request, *args, **kwargs):
-        _username = kwargs.get("username")
-        _path = kwargs.get("path")
-        if request.user.get_username() != _username:
-            raise PermissionDenied
-
-        if settings.DEBUG:
-            return serve(request, f"user/{_username}/{_path}", settings.MEDIA_ROOT)
-
-        _res = HttpResponse()
-        _res["Content-Type"] = ""
-        _res["X-Accel-Redirect"] = f"/internal/media/user/{_username}/{_path}"
-        return _res
-
-
 class TransactionMonthView(UserMixin, MonthArchiveView):
     template_name = "main/month/transaction.html"
     model = Transaction
diff --git a/nummi/media/__init__.py b/nummi/media/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/nummi/media/apps.py b/nummi/media/apps.py
new file mode 100644
index 0000000..1afca3f
--- /dev/null
+++ b/nummi/media/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class MediaConfig(AppConfig):
+    name = "media"
+    verbose_name = "Media"
diff --git a/nummi/media/urls.py b/nummi/media/urls.py
new file mode 100644
index 0000000..7537aed
--- /dev/null
+++ b/nummi/media/urls.py
@@ -0,0 +1,7 @@
+from django.urls import path
+
+from . import views
+
+urlpatterns = [
+    path("user/<username>/<path:path>", views.MediaView.as_view(), name="media"),
+]
diff --git a/nummi/media/views.py b/nummi/media/views.py
new file mode 100644
index 0000000..7164ef1
--- /dev/null
+++ b/nummi/media/views.py
@@ -0,0 +1,22 @@
+from django.conf import settings
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.core.exceptions import PermissionDenied
+from django.http import HttpResponse
+from django.views import View
+from django.views.static import serve
+
+
+class MediaView(LoginRequiredMixin, View):
+    def get(self, request, *args, **kwargs):
+        _username = kwargs.get("username")
+        _path = kwargs.get("path")
+        if request.user.get_username() != _username:
+            raise PermissionDenied
+
+        if settings.DEBUG:
+            return serve(request, f"user/{_username}/{_path}", settings.MEDIA_ROOT)
+
+        _res = HttpResponse()
+        _res["Content-Type"] = ""
+        _res["X-Accel-Redirect"] = f"/internal/media/user/{_username}/{_path}"
+        return _res
diff --git a/nummi/nummi/settings.py b/nummi/nummi/settings.py
index c227a46..3acd55f 100644
--- a/nummi/nummi/settings.py
+++ b/nummi/nummi/settings.py
@@ -45,6 +45,7 @@ CSRF_TRUSTED_ORIGINS = CONFIG.get("trusted_origins", ["http://localhost"])
 
 INSTALLED_APPS = [
     "main.apps.MainConfig",
+    "media.apps.MediaConfig",
     "django.contrib.admin",
     "django.contrib.auth",
     "django.contrib.contenttypes",
diff --git a/nummi/nummi/urls.py b/nummi/nummi/urls.py
index 683dc20..560f321 100644
--- a/nummi/nummi/urls.py
+++ b/nummi/nummi/urls.py
@@ -19,6 +19,7 @@ from django.urls import include, path
 
 urlpatterns = i18n_patterns(
     path("", include("main.urls")),
+    path("media/", include("media.urls")),
     path("admin/", admin.site.urls),
     prefix_default_language=False,
 )
