diff --git a/nix/configuration-test.nix b/nix/configuration-test.nix
index 94236770..4d5c2172 100644
--- a/nix/configuration-test.nix
+++ b/nix/configuration-test.nix
@@ -4,6 +4,11 @@ let
   full-text-search = {
     enabled = true;
     solr.url = "http://localhost:${toString config.services.solr.port}/solr/docspell";
+    postgresql = {
+      pg-config = {
+        "german" = "my-germam";
+      };
+    };
   };
 in
 {
diff --git a/nix/module-joex.nix b/nix/module-joex.nix
index ca7bbfc4..0663a699 100644
--- a/nix/module-joex.nix
+++ b/nix/module-joex.nix
@@ -213,6 +213,7 @@ Docpell Update Check
     };
     full-text-search = {
       enabled = false;
+      backend = "solr";
       solr = {
         url = "http://localhost:8983/solr/docspell";
         commit-within = 1000;
@@ -220,6 +221,17 @@ Docpell Update Check
         def-type = "lucene";
         q-op = "OR";
       };
+      postgresql = {
+        use-default-connection = false;
+        jdbc = {
+          url = "jdbc:postgresql://server:5432/db";
+          user = "pguser";
+          password = "";
+        };
+        pg-config = {};
+        pg-query-parser = "websearch_to_tsquery";
+        pg-rank-normalization = [ 4 ];
+      };
       migration = {
         index-all-chunk = 10;
       };
@@ -1371,6 +1383,12 @@ in {
                 Currently the SOLR search platform is supported.
               '';
             };
+            backend = mkOption {
+              type = types.str;
+              default = defaults.full-text-search.backend;
+              description = "The backend to use, either solr or postgresql";
+            };
+
             solr = mkOption {
               type = types.submodule({
                 options = {
@@ -1408,6 +1426,61 @@ in {
               default = defaults.full-text-search.solr;
               description = "Configuration for the SOLR backend.";
             };
+
+            postgresql = mkOption {
+              type = types.submodule({
+                options = {
+                  use-default-connection = mkOption {
+                    type = types.bool;
+                    default = defaults.full-text-search.postgresql.use-default-connection;
+                    description = "Whether to use the primary db connection.";
+                  };
+                  jdbc = mkOption {
+                    type = types.submodule ({
+                      options = {
+                        url = mkOption {
+                          type = types.str;
+                          default = defaults.jdbc.url;
+                          description = ''
+                            The URL to the database.
+                          '';
+                        };
+                        user = mkOption {
+                          type = types.str;
+                          default = defaults.jdbc.user;
+                          description = "The user name to connect to the database.";
+                        };
+                        password = mkOption {
+                          type = types.str;
+                          default = defaults.jdbc.password;
+                          description = "The password to connect to the database.";
+                        };
+                      };
+                    });
+                    default = defaults.full-text-search.postgresql.jdbc;
+                    description = "Database connection settings";
+                  };
+                  pg-config = mkOption {
+                    type = types.attrs;
+                    default = defaults.full-text-search.postgresql.pg-config;
+                    description = "";
+                  };
+                  pg-query-parser = mkOption {
+                    type = types.str;
+                    default = defaults.full-text-search.postgresql.pg-query-parser;
+                    description = "";
+                  };
+                  pg-rank-normalization = mkOption {
+                    type = types.listOf types.int;
+                    default = defaults.full-text-search.postgresql.pg-rank-normalization;
+                    description = "";
+                  };
+                };
+              });
+              default = defaults.full-text-search.postgresql;
+              description = "PostgreSQL for fulltext search";
+            };
+
             migration = mkOption {
               type = types.submodule({
                 options = {
diff --git a/nix/module-server.nix b/nix/module-server.nix
index c7c0a2ca..0e794290 100644
--- a/nix/module-server.nix
+++ b/nix/module-server.nix
@@ -62,6 +62,17 @@ let
         def-type = "lucene";
         q-op = "OR";
       };
+      postgresql = {
+        use-default-connection = false;
+        jdbc = {
+          url = "jdbc:postgresql://server:5432/db";
+          user = "pguser";
+          password = "";
+        };
+        pg-config = {};
+        pg-query-parser = "websearch_to_tsquery";
+        pg-rank-normalization = [ 4 ];
+      };
     };
     auth = {
       server-secret = "hex:caffee";
@@ -575,6 +586,60 @@ in {
               default = defaults.full-text-search.solr;
               description = "Configuration for the SOLR backend.";
             };
+
+            postgresql = mkOption {
+              type = types.submodule({
+                options = {
+                  use-default-connection = mkOption {
+                    type = types.bool;
+                    default = defaults.full-text-search.postgresql.use-default-connection;
+                    description = "Whether to use the primary db connection.";
+                  };
+                  jdbc = mkOption {
+                    type = types.submodule ({
+                      options = {
+                        url = mkOption {
+                          type = types.str;
+                          default = defaults.jdbc.url;
+                          description = ''
+                            The URL to the database.
+                          '';
+                        };
+                        user = mkOption {
+                          type = types.str;
+                          default = defaults.jdbc.user;
+                          description = "The user name to connect to the database.";
+                        };
+                        password = mkOption {
+                          type = types.str;
+                          default = defaults.jdbc.password;
+                          description = "The password to connect to the database.";
+                        };
+                      };
+                    });
+                    default = defaults.full-text-search.postgresql.jdbc;
+                    description = "Database connection settings";
+                  };
+                  pg-config = mkOption {
+                    type = types.attrs;
+                    default = defaults.full-text-search.postgresql.pg-config;
+                    description = "";
+                  };
+                  pg-query-parser = mkOption {
+                    type = types.str;
+                    default = defaults.full-text-search.postgresql.pg-query-parser;
+                    description = "";
+                  };
+                  pg-rank-normalization = mkOption {
+                    type = types.listOf types.int;
+                    default = defaults.full-text-search.postgresql.pg-rank-normalization;
+                    description = "";
+                  };
+                };
+              });
+              default = defaults.full-text-search.postgresql;
+              description = "PostgreSQL for fulltext search";
+            };
           };
         });
         default = defaults.full-text-search;