diff --git a/nixos/server/sonarr.nix b/nixos/server/sonarr.nix
new file mode 100644
index 0000000000000000000000000000000000000000..54ac20483d5df3f87bf9c564ca6c9d799fb248cf
--- /dev/null
+++ b/nixos/server/sonarr.nix
@@ -0,0 +1,46 @@
+{ lib, ... }:
+
+{
+  services.sonarr.enable = true;
+
+  systemd.services = {
+    sonarr.environment = {
+      SONARR_SERVER_BINDADDRESS = "::1";
+      SONARR_SERVER_PORT = "61038";
+      SONARR_SERVER_ENABLESSL = "false";
+
+      SONARR_POSTGRES_HOST = "/run/postgresql";
+      SONARR_POSTGRES_USER = "sonarr";
+      SONARR_POSTGRES_MAINDB = "sonarr-main";
+      SONARR_POSTGRES_LOGDB = "sonarr-log";
+
+      SONARR_UPDATE_AUTOMATICALLY = "false";
+    };
+    # because Sonarr needs two DBs, we can't use ensureDBOwnership
+    postgresql.postStart = lib.mkAfter ''
+      $PSQL -tAc 'ALTER DATABASE "sonarr-main" OWNER TO "sonarr";'
+      $PSQL -tAc 'ALTER DATABASE "sonarr-log" OWNER TO "sonarr";'
+    '';
+  };
+
+  services.postgresql = {
+    ensureUsers = [ { name = "sonarr"; } ];
+    ensureDatabases = [ "sonarr-main" "sonarr-log" ];
+  };
+
+  environment.persistence."/persist".directories = [ "/var/lib/sonarr" ];
+
+  services.traefik.dynamicConfigOptions.http = {
+    routers.dashboard = {
+      rule = "Host(`dashboard.eisfunke.com`)";
+      entrypoints = [ "websecure" ];
+      tls.certResolver = "tls";
+      service = "dashboard";
+    };
+    services.dashboard = {
+      loadBalancer.servers = [
+        { url = "http://localhost:61038"; }
+      ];
+    };
+  };
+}