about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--configurations/manwe/default.nix2
-rw-r--r--configurations/manwe/webserver.nix3
-rw-r--r--flake.lock367
-rw-r--r--flake.nix24
-rw-r--r--lib/my.nix1
-rw-r--r--modules/nixfiles/chromium.nix16
-rw-r--r--modules/nixfiles/common/documentation.nix9
-rw-r--r--modules/nixfiles/common/home-manager.nix15
-rw-r--r--modules/nixfiles/common/locale.nix11
-rw-r--r--modules/nixfiles/common/security.nix19
-rw-r--r--modules/nixfiles/emacs/default.nix10
-rw-r--r--modules/nixfiles/emacs/doom/init.el28
-rw-r--r--modules/nixfiles/endlessh-go.nix3
-rw-r--r--modules/nixfiles/firefox/default.nix262
-rw-r--r--modules/nixfiles/firefox/profile.nix480
-rw-r--r--modules/nixfiles/firefox/userContent.css68
-rw-r--r--modules/nixfiles/fonts.nix1
-rw-r--r--modules/nixfiles/games/lutris.nix3
-rw-r--r--modules/nixfiles/games/steam-run.nix1
-rw-r--r--modules/nixfiles/games/steam.nix1
-rw-r--r--modules/nixfiles/git.nix14
-rw-r--r--modules/nixfiles/gotify.nix11
-rw-r--r--modules/nixfiles/grafana.nix112
-rw-r--r--modules/nixfiles/hydra.nix2
-rw-r--r--modules/nixfiles/matrix/dendrite.nix246
-rw-r--r--modules/nixfiles/matrix/synapse.nix16
-rw-r--r--modules/nixfiles/monitoring/default.nix159
-rw-r--r--modules/nixfiles/nextcloud.nix2
-rw-r--r--modules/nixfiles/nsd.nix1
-rw-r--r--modules/nixfiles/postgresql.nix48
-rw-r--r--modules/nixfiles/profiles/default.nix4
-rw-r--r--modules/nixfiles/profiles/dev/default.nix229
-rw-r--r--modules/nixfiles/profiles/dev/editorconfig.ini83
-rw-r--r--modules/nixfiles/profiles/dev/gdbinit41
-rw-r--r--modules/nixfiles/profiles/headless.nix7
-rw-r--r--modules/nixfiles/qutebrowser.nix931
-rw-r--r--modules/nixfiles/rtorrent.nix270
-rw-r--r--modules/nixfiles/soju.nix16
-rw-r--r--modules/nixfiles/vaultwarden.nix173
39 files changed, 1871 insertions, 1818 deletions
diff --git a/configurations/manwe/default.nix b/configurations/manwe/default.nix
index db08c3f..b8dd324 100644
--- a/configurations/manwe/default.nix
+++ b/configurations/manwe/default.nix
@@ -23,6 +23,8 @@ with lib; {
 
     monitoring.enable = true;
 
+    postgresql.enable = true;
+
     git.server = {
       enable = true;
       domain = "git.${my.domain.azahi}";
diff --git a/configurations/manwe/webserver.nix b/configurations/manwe/webserver.nix
index 8c68441..dde3e63 100644
--- a/configurations/manwe/webserver.nix
+++ b/configurations/manwe/webserver.nix
@@ -7,7 +7,8 @@ with lib; {
   config.nixfiles.modules.nginx.virtualHosts = with my.domain;
     {
       ${shire}.locations."/".return = "301 https://www.youtube.com/watch?v=dQw4w9WgXcQ";
-      "git.${shire}".locations."/".return = "301 https://git.azahi.cc";
+      "git.${shire}".locations."/".return = "301 https://git.${azahi}";
+      "bitwarden.${shire}".locations."/".return = "301 https://vaultwarden.${shire}";
       ${azahi} = {
         serverAliases = ["frodo.${gondor}" "frodo.${rohan}"];
         locations."/".root = inputs.azahi-cc;
diff --git a/flake.lock b/flake.lock
index 761a302..bb5830d 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,5 +1,226 @@
 {
   "nodes": {
+    "100.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1652122178,
+        "narHash": "sha256-gitVP21/l26hfR+r7+ST2o7pY8ikr2u92n2uzuLgnKs=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "d6b26e75588bcd4311251c68912d3c77b8c6e996",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "100.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "101.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1655041107,
+        "narHash": "sha256-lGRqHEL9I8VgvSiUjT1DngFCsmEzM8n5J7vIfRj6TZM=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "1a899966a911dc2b69a808095ac7836bef5e214b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "101.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "102.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1656722605,
+        "narHash": "sha256-1M1lf3ah4I5KOPlTIZ52uEha8tuQu1wkgkdzEB4iK/0=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "ceacc9dd74086478d43ccf3a4f0bd5befda53a43",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "102.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "103.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1660764278,
+        "narHash": "sha256-MhlZav86gz8bH1aEWyNFNLnc6T7MBU1d3dGHtG2lEnA=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "0dba33688fe468aca9b58c60910201afb3b89f60",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "103.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "104.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1662893183,
+        "narHash": "sha256-NyP/kJlV1Ai7os3gMqukKMdRSQ78GAjPCJkZDZtDdeo=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "3f09afdee07c5aea33f6dc4194e1425d6400a0d7",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "104.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "105.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1664804773,
+        "narHash": "sha256-cktQJuMbGINAAfSrpln8OxisuyN/o8sPxon0lZ4vM7c=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "11e3c1b8f6676b45b2b35c0b624d15746c70c593",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "refs/pull/1541/head",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "93.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1634027026,
+        "narHash": "sha256-/ITf8nv/IWR1sKBchPtdkPjZO5OFH9p6FgVbDfBrJc8=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "85438d00e457bff692303af519da618c6372476b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "93.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "94.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1637651503,
+        "narHash": "sha256-RvG+GRh8Md1yrTzFniu1G2UpTnOb7KCGDfQmFvdtl58=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "cbfb8abf1544c3e87f412f64a9747bd1dea4a705",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "94.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "95.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1638965627,
+        "narHash": "sha256-4g1Vu4zF+EtHK123zSxIDP1wYROK2rqS897Kcv2C/cI=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "7e1b92567ca2bb76ad358d0fc786fd60b3cf7970",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "95.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "96.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1642736886,
+        "narHash": "sha256-P2C59t4DnM11I9GDL9xyc2m8Ml0T8gRuom7UtWykWnk=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "ac0820a5dc00e04fe14fc2a74ba75e590883293c",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "96.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "97.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1644750900,
+        "narHash": "sha256-Df2D2eBifkZpFklPBbE94AvgAUM/NUAAiuqUzp67Hdo=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "a98b73c64e2e0b505efb6b23d34e6c5d90abe2c8",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "97.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "98.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1646873050,
+        "narHash": "sha256-HJu+azYJRMW0C5hhU96pkwZxql7Ijpiz2sw9e/JoqR8=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "d9af90d05f477e5e25f8d9f545eeb7fe0a235d2a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "98.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
+    "99.0": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1649497545,
+        "narHash": "sha256-ScO19N/EVpmMzdN2kkfjYIJN7c0CQdZJ9qMZReqMpI4=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "4ff931781a1bf012e0e7e2ec89dc5c2a9bedd890",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "ref": "99.0",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
     "agenix": {
       "inputs": {
         "nixpkgs": [
@@ -7,11 +228,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1664140963,
-        "narHash": "sha256-pFxDtOLduRFlol0Y4ShE+soRQX4kbhaCNBtDOvx7ykw=",
+        "lastModified": 1665870395,
+        "narHash": "sha256-Tsbqb27LDNxOoPLh0gw2hIb6L/6Ow/6lIBvqcHzEKBI=",
         "owner": "ryantm",
         "repo": "agenix",
-        "rev": "6acb1fe5f8597d5ce63fc82bc7fcac7774b1cdf0",
+        "rev": "a630400067c6d03c9b3e0455347dc8559db14288",
         "type": "github"
       },
       "original": {
@@ -21,6 +242,41 @@
         "type": "github"
       }
     },
+    "arkenfox-nixos": {
+      "inputs": {
+        "100.0": "100.0",
+        "101.0": "101.0",
+        "102.0": "102.0",
+        "103.0": "103.0",
+        "104.0": "104.0",
+        "105.0": "105.0",
+        "93.0": "93.0",
+        "94.0": "94.0",
+        "95.0": "95.0",
+        "96.0": "96.0",
+        "97.0": "97.0",
+        "98.0": "98.0",
+        "99.0": "99.0",
+        "master": "master",
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1665906177,
+        "narHash": "sha256-fAPdYYF8AJtczGXFFTwMD8UxECRxPrR+VtHrUZgvxns=",
+        "owner": "dwarfmaster",
+        "repo": "arkenfox-nixos",
+        "rev": "83776435c05002a13c9b9f0536cc2041158798a8",
+        "type": "github"
+      },
+      "original": {
+        "owner": "dwarfmaster",
+        "ref": "main",
+        "repo": "arkenfox-nixos",
+        "type": "github"
+      }
+    },
     "azahi-cc": {
       "flake": false,
       "locked": {
@@ -121,11 +377,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1665120353,
-        "narHash": "sha256-4wOdNQoP7F9hOshrU/APxs/L7Lma75OABRR4eMcEhsk=",
+        "lastModified": 1666156198,
+        "narHash": "sha256-mTgPP4OIYerBpn9vVwcVdLn4GDjmlsZiqrVxHqZTiNo=",
         "owner": "nix-community",
         "repo": "emacs-overlay",
-        "rev": "db1c01c5faeea34547fff2017324f8a2d2253402",
+        "rev": "858214991200eccc2f0a4f929f4baa0ffd8281c6",
         "type": "github"
       },
       "original": {
@@ -329,11 +585,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1665119273,
-        "narHash": "sha256-neL/ZRrwk47Ke1nfjk8ltlIm+NRZyA3MBcNbqEGSBeE=",
+        "lastModified": 1666080735,
+        "narHash": "sha256-4YWYJgzt9mGuAvXAuEziYms+bYlk/1spyt3iLizRL5I=",
         "owner": "nix-community",
         "repo": "home-manager",
-        "rev": "9fcae11ff29ca5f959b05c206f3724486c28ff07",
+        "rev": "42f81ac107c5a9a177888080107094dba57f134e",
         "type": "github"
       },
       "original": {
@@ -359,6 +615,22 @@
         "type": "github"
       }
     },
+    "master": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1665257885,
+        "narHash": "sha256-4PNnCRLomAd5OdN4UEbsVSm8eNuteZHKaUqRVvIBvN8=",
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "rev": "f4187632faef76df4de0cbb0cdc7199f22fadd76",
+        "type": "github"
+      },
+      "original": {
+        "owner": "arkenfox",
+        "repo": "user.js",
+        "type": "github"
+      }
+    },
     "nix-doom-emacs": {
       "inputs": {
         "doom-emacs": "doom-emacs",
@@ -420,11 +692,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1665020519,
-        "narHash": "sha256-1DdFTskxpBw/McAuNNvUkWpNtSN1tUywpsBjNfsSBLY=",
+        "lastModified": 1666162820,
+        "narHash": "sha256-qnpE2nOJNm8tCDVk4g+ihjQoxJ/8gLPmI219QZrCnUY=",
         "owner": "jyooru",
         "repo": "nix-minecraft-servers",
-        "rev": "d34bbd2bbb2afb2f43365238c218f97365686742",
+        "rev": "3fc8a413a5f2e506980ba475e64a443e30c8c852",
         "type": "github"
       },
       "original": {
@@ -452,11 +724,11 @@
     },
     "nixos-hardware": {
       "locked": {
-        "lastModified": 1665040200,
-        "narHash": "sha256-glqL6yj3aUm40y92inzRmowGt9aIrUrpBX7eBAMic4I=",
+        "lastModified": 1665987993,
+        "narHash": "sha256-MvlaIYTRiqefG4dzI5p6vVCfl+9V8A1cPniUjcn6Ngc=",
         "owner": "NixOS",
         "repo": "nixos-hardware",
-        "rev": "47fd70289491c1f0c0d9a1f44fb5a9e2801120c9",
+        "rev": "0e6593630071440eb89cd97a52921497482b22c6",
         "type": "github"
       },
       "original": {
@@ -468,11 +740,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1665056165,
-        "narHash": "sha256-2C7VfNphJa0FxPoT+suMOmUDVrQ5RIE+NKfDWqElvE4=",
+        "lastModified": 1666154393,
+        "narHash": "sha256-G4jctSMlliZvG4zUrcas0O+t3qJHzM0moBpG93lcl44=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "27a89ba43b0fb735ce867e8ab3d2442f8cc61dad",
+        "rev": "7b38cb118ce4ad36d19a8b021068633b57ce0d3f",
         "type": "github"
       },
       "original": {
@@ -484,11 +756,11 @@
     },
     "nixpkgs-master": {
       "locked": {
-        "lastModified": 1665132380,
-        "narHash": "sha256-98YwYPul7feV+tQQXtTbLQ52t6yJnoBHaswoiIZ9KGk=",
+        "lastModified": 1666168327,
+        "narHash": "sha256-nQjQtchYCUPi35BxKpYi0H6Bvoqoh+HZO30dIb31FzQ=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "7e5b689f69fa15e3ed3aa355d1751c9b6e4cea78",
+        "rev": "ef859e282251e878f3d71ca4917e213253ad6cbf",
         "type": "github"
       },
       "original": {
@@ -498,45 +770,13 @@
         "type": "github"
       }
     },
-    "nixpkgs-pr-endlessh-go": {
-      "locked": {
-        "lastModified": 1663966554,
-        "narHash": "sha256-Ssvy4TushGEKa9AZlfo7hM+auQlw5JUA2PROWcbUNfc=",
-        "owner": "azahi",
-        "repo": "nixpkgs",
-        "rev": "99dc9b9c164af3bc6c08ff4a4db4c2b58e368160",
-        "type": "github"
-      },
-      "original": {
-        "owner": "azahi",
-        "ref": "endlessh-go",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-pr-please": {
-      "locked": {
-        "lastModified": 1664618495,
-        "narHash": "sha256-WIBCgnVHmqwblSZqXhx62cHa9MQo1+9JEDWIbYbEJf4=",
-        "owner": "azahi",
-        "repo": "nixpkgs",
-        "rev": "a1ebdc24da21d98c66f527c56abff4283b3df61a",
-        "type": "github"
-      },
-      "original": {
-        "owner": "azahi",
-        "ref": "please",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
     "nixpkgs-stable": {
       "locked": {
-        "lastModified": 1665132027,
-        "narHash": "sha256-zoHPqSQSENt96zTk6Mt1AP+dMNqQDshXKQ4I6MfjP80=",
+        "lastModified": 1666164185,
+        "narHash": "sha256-5v+YB4ijeUfg5LCz9ck4gIpCPhIS+qn02OyPJO48bCE=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "9ecc270f02b09b2f6a76b98488554dd842797357",
+        "rev": "c5203abb1329f7ea084c04acda330ca75d5b9fb5",
         "type": "github"
       },
       "original": {
@@ -598,11 +838,11 @@
     },
     "nur": {
       "locked": {
-        "lastModified": 1665132827,
-        "narHash": "sha256-MLYVbC4piJOUdDLvlX3428zRSq+t4YUUZnDJ5JfvwnY=",
+        "lastModified": 1666162734,
+        "narHash": "sha256-XFgV2TlQ7q2j1yjfgB/mayfORcKtmIAY2BGXTNRqNTs=",
         "owner": "nix-community",
         "repo": "NUR",
-        "rev": "aa9c7abdce11c70b770defb55dbf3de0de2d9cab",
+        "rev": "15e8a12e8793e845708c17921f1985f486400c2b",
         "type": "github"
       },
       "original": {
@@ -727,11 +967,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1664708386,
-        "narHash": "sha256-aCD8UUGNYb5nYzRmtsq/0yP9gFOQQHr/Lsb5vW+mucw=",
+        "lastModified": 1666160137,
+        "narHash": "sha256-8bQu+6poMzUyS2n3C1v3hkO6ZhRzj8Pf3CDCNckqQE4=",
         "owner": "cachix",
         "repo": "pre-commit-hooks.nix",
-        "rev": "2e4a708918e14fdbd534cc94aaa9470cd19b2464",
+        "rev": "e6c8efee1c108bb27522b9fd25b1cd0eb3288681",
         "type": "github"
       },
       "original": {
@@ -760,6 +1000,7 @@
     "root": {
       "inputs": {
         "agenix": "agenix",
+        "arkenfox-nixos": "arkenfox-nixos",
         "azahi-cc": "azahi-cc",
         "dns-nix": "dns-nix",
         "emacs-overlay": "emacs-overlay",
@@ -773,8 +1014,6 @@
         "nixos-hardware": "nixos-hardware",
         "nixpkgs": "nixpkgs",
         "nixpkgs-master": "nixpkgs-master",
-        "nixpkgs-pr-endlessh-go": "nixpkgs-pr-endlessh-go",
-        "nixpkgs-pr-please": "nixpkgs-pr-please",
         "nixpkgs-stable": "nixpkgs-stable",
         "nmap-vulners": "nmap-vulners",
         "nmap-vulscan": "nmap-vulscan",
diff --git a/flake.nix b/flake.nix
index 26f46fc..f5b1a48 100644
--- a/flake.nix
+++ b/flake.nix
@@ -33,22 +33,6 @@
     #   path = "/home/azahi/src/nixpkgs";
     # };
 
-    # FIXME https://github.com/NixOS/nixpkgs/pull/187026
-    nixpkgs-pr-endlessh-go = {
-      type = "github";
-      owner = "azahi";
-      repo = "nixpkgs";
-      ref = "endlessh-go";
-    };
-
-    # FIXME https://github.com/NixOS/nixpkgs/pull/192671
-    nixpkgs-pr-please = {
-      type = "github";
-      owner = "azahi";
-      repo = "nixpkgs";
-      ref = "please";
-    };
-
     nixos-hardware = {
       type = "github";
       owner = "NixOS";
@@ -85,6 +69,14 @@
       };
     };
 
+    arkenfox-nixos = {
+      type = "github";
+      owner = "dwarfmaster";
+      repo = "arkenfox-nixos";
+      ref = "main";
+      inputs.nixpkgs.follows = "nixpkgs";
+    };
+
     nix-doom-emacs = {
       type = "github";
       owner = "nix-community";
diff --git a/lib/my.nix b/lib/my.nix
index 05fd6e9..ac31734 100644
--- a/lib/my.nix
+++ b/lib/my.nix
@@ -155,6 +155,7 @@ with lib;
                 "alertmanager.${shire}"
                 "frodo.${rohan}"
                 "frodo.${gondor}"
+                "bitwarden.${shire}"
                 "git.${azahi}"
                 "git.${shire}"
                 "gotify.${shire}"
diff --git a/modules/nixfiles/chromium.nix b/modules/nixfiles/chromium.nix
index 337acc8..20b5347 100644
--- a/modules/nixfiles/chromium.nix
+++ b/modules/nixfiles/chromium.nix
@@ -11,24 +11,16 @@ in {
 
   config = mkIf cfg.enable {
     hm = {
-      home = {
-        # sessionVariables.BROWSER = mkOverride 300 "chromium";
-
-        packages = with pkgs; [profile-cleaner];
-      };
+      home.packages = with pkgs; [profile-cleaner];
 
       programs.chromium = {
         enable = true;
 
         package = pkgs.chromium;
 
-        extensions =
-          [
-            {id = "cjpalhdlnbpafiamejdnhcphjbkeiagm";} # UBlock Origin
-          ]
-          ++ optional config.nixfiles.modules.kde.enable {
-            id = "cimiefiiaegbelhefglklhhakcgmhkai"; # KDE Plasma Integration
-          };
+        extensions = [
+          {id = "cjpalhdlnbpafiamejdnhcphjbkeiagm";} # Unblock Origin
+        ];
       };
     };
 
diff --git a/modules/nixfiles/common/documentation.nix b/modules/nixfiles/common/documentation.nix
index 7f819a8..6e15aec 100644
--- a/modules/nixfiles/common/documentation.nix
+++ b/modules/nixfiles/common/documentation.nix
@@ -8,6 +8,15 @@
 with lib; {
   config = mkMerge [
     (mkIf this.isHeadful {
+      hm.manual = {
+        html.enable = false;
+        json.enable = false;
+        # FIXME Temporary workaround.
+        # https://github.com/nix-community/home-manager/issues/3342
+        # https://github.com/NixOS/nixpkgs/issues/196651
+        manpages.enable = false;
+      };
+
       documentation = {
         enable = true;
 
diff --git a/modules/nixfiles/common/home-manager.nix b/modules/nixfiles/common/home-manager.nix
index 91f6705..7ce872b 100644
--- a/modules/nixfiles/common/home-manager.nix
+++ b/modules/nixfiles/common/home-manager.nix
@@ -10,21 +10,16 @@ with lib; {
     (mkAliasOptionModule ["hm"] ["home-manager" "users" my.username])
   ];
 
+  hm = {
+    news.display = "silent";
+    home = {inherit (config.system) stateVersion;};
+  };
+
   home-manager = {
     backupFileExtension = "bak";
     useUserPackages = true;
     useGlobalPkgs = true;
     verbose = true;
-
-    users =
-      mapListToAttrs (_: {
-        home = {
-          inherit (config.system) stateVersion;
-        };
-      }) [
-        "root"
-        my.username
-      ];
   };
 
   system.extraDependencies = [inputs.home-manager];
diff --git a/modules/nixfiles/common/locale.nix b/modules/nixfiles/common/locale.nix
index 34a738b..5f0d5ae 100644
--- a/modules/nixfiles/common/locale.nix
+++ b/modules/nixfiles/common/locale.nix
@@ -1,6 +1,15 @@
 {lib, ...}:
 with lib; {
-  i18n.defaultLocale = mkDefault "en_GB.UTF-8";
+  i18n = {
+    defaultLocale = mkDefault "en_GB.UTF-8";
+    supportedLocales = [
+      "C.UTF-8/UTF-8"
+      "en_GB.UTF-8/UTF-8"
+      "en_US.UTF-8/UTF-8"
+      "ja_JP.UTF-8/UTF-8"
+      "ru_RU.UTF-8/UTF-8"
+    ];
+  };
 
   time.timeZone = mkDefault "Europe/Moscow";
 
diff --git a/modules/nixfiles/common/security.nix b/modules/nixfiles/common/security.nix
index 30b4276..09c5da1 100644
--- a/modules/nixfiles/common/security.nix
+++ b/modules/nixfiles/common/security.nix
@@ -26,23 +26,4 @@ with lib; {
       '';
     };
   };
-
-  # Remove this later.
-  # imports = ["${inputs.nixpkgs-pr-please}/nixos/modules/security/please.nix"];
-  # security.please = {
-  #   enable = true;
-  #   settings.root = {
-  #     name = my.username;
-  #     target = "root";
-  #     rule = ".*";
-  #     require_pass = false;
-  #   };
-  #   settings.root_edit = {
-  #     name = my.username;
-  #     type = "edit";
-  #     target = "root";
-  #     rule = ".*";
-  #     require_pass = false;
-  #   };
-  # };
 }
diff --git a/modules/nixfiles/emacs/default.nix b/modules/nixfiles/emacs/default.nix
index 41ef523..732cab5 100644
--- a/modules/nixfiles/emacs/default.nix
+++ b/modules/nixfiles/emacs/default.nix
@@ -47,10 +47,6 @@ in {
                 pyflakes # :lang python
                 python-lsp-server # :lang (python +lsp)
               ]))
-            python3Packages.black
-            python3Packages.isort
-            python3Packages.pyflakes
-            python3Packages.python-lsp-server
             asmfmt # :editor format
             bash-language-server # :lang (sh +lsp)
             clang-tools # :lang (cc +lsp) :editor format
@@ -60,6 +56,7 @@ in {
             dockerfile-language-server # :tools (docker +lsp)
             editorconfig # :tools editorconfig
             fd # doom!
+            gdb # :tools debugger
             gnuplot # :lang (org +gnuplot)
             gnutls # doom!
             gomodifytags # :lang go
@@ -77,6 +74,7 @@ in {
             html-tidy # :lang web
             jre # :lang plantuml
             json-language-server # :lang (json +lsp)
+            lldb # :tools debugger
             lua-language-server # :lang (lua +lsp)
             nix-language-server # :lang (nix +lsp)
             nixfmt # :lang nix :editor format
@@ -84,6 +82,7 @@ in {
             nodePackages.lua-fmt # :lang lua :editor format
             nodePackages.prettier # :editor format
             nodePackages.stylelint # :lang web
+            nodejs # :tools debugger
             pandoc # :lang org markdown latex
             pinentry-emacs # doom!
             pre-commit # :tools magit
@@ -94,6 +93,7 @@ in {
             shfmt # :lang sh :editor format
             sqlite # :lang (org +roam2) :tools lookup
             texlive.combined.scheme-full # :lang org tex
+            unzip # :tools debugger
             wordnet # :tools (lookup +dictionary +offline)
             xclip # :app everywhere
             xdotool # :app everywhere
@@ -113,6 +113,8 @@ in {
             concatMapStringsSep ":" (x: "${x}/bin") extraBins
           }"))
 
+          (setq custom-file (file-name-concat doom-emacs-dir "custom.el"))
+
           (setq doom-font (font-spec :family "${config.fontScheme.monospaceFont.family}"
                                      :size ${toString config.fontScheme.monospaceFont.size})
                 doom-unicode-font doom-font)
diff --git a/modules/nixfiles/emacs/doom/init.el b/modules/nixfiles/emacs/doom/init.el
index 718d5cb..1bf1ca2 100644
--- a/modules/nixfiles/emacs/doom/init.el
+++ b/modules/nixfiles/emacs/doom/init.el
@@ -79,11 +79,11 @@
 
        :lang
        (cc +lsp +tree-sitter)
-       common-lisp
+       ;; (common-lisp +lsp +tree-sitter)
        ;; (csharp +lsp +tree-sitter)
        data
-       dhall
-       emacs-lisp
+       ;; (dhall +lsp +tree-sitter)
+       (emacs-lisp +lsp +tree-sitter)
        (go +lsp +tree-sitter)
        ;; graphql
        (haskell +lsp +tree-sitter)
@@ -91,29 +91,23 @@
        (javascript +lsp +tree-sitter)
        json
        (latex +lsp +tree-sittter)
-       (lua +lsp +tree-sitter)
-       markdown
+       ;; (lua +lsp +tree-sitter)
+       (markdown +lsp +tree-sitter)
        (nix +lsp)
-       (org +hugo
-            +journal
-            +noter
-            +pandoc
-            +pomodoro
-            +present
-            +roam2)
+       (org +pandoc +roam2)
        plantuml
        (python +lsp +tree-sitter)
        ;; (racket +lsp +tree-sitter)
        ;; rst
-       (rust +lsp +tree-sitter)
-       ;; (scheme +racket)
+       ;; (rust +lsp +tree-sitter)
+       ;; (scheme +lsp +tree-sitter +racket)
        (sh +lsp +tree-sitter)
-       (web +lsp +tree-sitter)
+       web
        yaml
-       (zig +lsp +tree-sitter)
+       ;; (zig +lsp +tree-sitter)
 
        :email
-       (mu4e +org)
+       mu4e
 
        :app
        calendar
diff --git a/modules/nixfiles/endlessh-go.nix b/modules/nixfiles/endlessh-go.nix
index 56c415e..9ceb4e4 100644
--- a/modules/nixfiles/endlessh-go.nix
+++ b/modules/nixfiles/endlessh-go.nix
@@ -9,9 +9,6 @@
 with lib; let
   cfg = config.nixfiles.modules.endlessh-go;
 in {
-  # Remove this later.
-  imports = ["${inputs.nixpkgs-pr-endlessh-go}/nixos/modules/services/security/endlessh-go.nix"];
-
   options.nixfiles.modules.endlessh-go.enable = mkEnableOption "endlessh-go";
 
   config = let
diff --git a/modules/nixfiles/firefox/default.nix b/modules/nixfiles/firefox/default.nix
index 6dde7c3..d04adfd 100644
--- a/modules/nixfiles/firefox/default.nix
+++ b/modules/nixfiles/firefox/default.nix
@@ -1,5 +1,6 @@
 {
   config,
+  inputs,
   lib,
   pkgs,
   ...
@@ -11,41 +12,266 @@ in {
 
   config = mkIf cfg.enable {
     hm = {
-      home = {
-        # sessionVariables.BROWSER = mkOverride 200 "firefox";
-
-        packages = with pkgs; [
-          (writeShellScriptBin "firefox-vanilla" ''
-            ${config.hm.programs.firefox.package}/bin/firefox -p vanilla "$@"
-          '')
-          profile-cleaner
-        ];
-      };
+      imports = [inputs.arkenfox-nixos.hmModules.arkenfox];
+
+      home.packages = with pkgs; [profile-cleaner];
 
       programs.firefox = {
         enable = true;
 
-        package = pkgs.firefox.override {
-          cfg = with config.nixfiles.modules; {
-            enablePlasmaBrowserIntegration = kde.enable;
-          };
+        arkenfox = {
+          enable = true;
+          version = "105.0";
         };
 
-        profiles.default = (import ./profile.nix) config lib;
+        profiles.default = let
+          mkCssWithRoot = css:
+            mkMerge [
+              (with config.colourScheme; ''
+                :root {
+                    --black: ${black};
+                    --red: ${red};
+                    --green: ${green};
+                    --yellow: ${yellow};
+                    --blue: ${blue};
+                    --magenta: ${magenta};
+                    --cyan: ${cyan};
+                    --white: ${white};
+                    --bright-black: ${brightBlack};
+                    --bright-red: ${brightRed};
+                    --bright-green: ${brightGreen};
+                    --bright-yellow: ${brightYellow};
+                    --bright-blue: ${brightBlue};
+                    --bright-magenta: ${brightMagenta};
+                    --bright-cyan: ${brightCyan};
+                    --bright-white: ${brightWhite};
+                    --background: ${background};
+                    --foreground: ${foreground};
+              '')
+              (with config.fontScheme; ''
+                    --sans-serif-font-family: "${sansSerifFont.family}", "${sansSerifFontFallback.family}", sans-serif;
+                    --sans-serif-font-size: ${toString sansSerifFont.size};
+                    --serif-font-family: "${serifFont.family}", "${serifFontFallback.family}", serif;
+                    --serif-font-size: ${toString serifFont.size};
+                    --monospace-font-family: "${monospaceFont.family}", "${monospaceFontFallback.family}", monospace;
+                    --monospace-font-size: ${toString monospaceFont.size};
+                }
+              '')
+              (builtins.readFile css)
+            ];
+        in {
+          id = 0;
+
+          isDefault = true;
+
+          # A way to change the look of the Firefox itself.
+          userChrome = mkCssWithRoot ./userChrome.css;
+
+          # A way to remove annoyances and visual bloat of many webpages.
+          userContent = mkCssWithRoot ./userContent.css;
+
+          # https://github.com/arkenfox/user.js/blob/master/user.js
+          arkenfox = {
+            enable = true;
+            "0000".enable = true;
+            "0100" = {
+              enable = true;
+              "0102" = {
+                enable = true;
+                "browser.startup.page" = {
+                  enable = true;
+                  value = 3;
+                };
+              };
+            };
+            "0200" = {
+              enable = true;
+              "0204" = {
+                enable = true;
+                "browser.search.region" = {
+                  enable = true;
+                  value = "US";
+                };
+              };
+              "0210" = {
+                enable = true;
+                "intl.accept_languages" = {
+                  enable = true;
+                  value = "en-US, en";
+                };
+              };
+            };
+            "0300".enable = true;
+            "0400" = {
+              enable = false;
+              "0401" = {
+                enable = true;
+                "browser.safebrowsing.malware.enabled" = {
+                  enable = true;
+                  value = false;
+                };
+                "browser.safebrowsing.phishing.enabled" = {
+                  enable = true;
+                  value = false;
+                };
+              };
+              "0402" = {
+                enable = true;
+                "browser.safebrowsing.downloads.enabled" = {
+                  enable = true;
+                  value = false;
+                };
+              };
+              "0404" = {
+                enable = true;
+                "browser.safebrowsing.downloads.remote.block_potentially_unwanted" = {
+                  enable = true;
+                  value = false;
+                };
+                "browser.safebrowsing.downloads.remote.block_uncommon" = {
+                  enable = true;
+                  value = false;
+                };
+              };
+            };
+            "0600".enable = true;
+            "0700" = {
+              enable = true;
+              "0701" = {
+                enable = true;
+                "network.dns.disableIPv6" = {
+                  enable = true;
+                  value = false;
+                };
+              };
+              "0710" = {
+                enable = true;
+                "network.trr.mode" = {
+                  enable = true;
+                  value = 5;
+                };
+              };
+            };
+            "0800" = {
+              enable = true;
+              "0801" = {
+                enable = true;
+                "keyword.enabled" = {
+                  enable = true;
+                  value = true;
+                };
+              };
+              "0808" = {
+                enable = true;
+                "browser.urlbar.suggest.engines" = {
+                  enable = true;
+                  value = false;
+                };
+              };
+              "0810" = {
+                enable = true;
+                "browser.formfill.enable" = {
+                  enable = true;
+                  value = true;
+                };
+              };
+            };
+            "0900".enable = true;
+            "1000" = {
+              enable = true;
+              "1001"."browser.cache.disk.enable" = {
+                enable = true;
+                value = true;
+              };
+            };
+            "1200" = {
+              enable = true;
+            };
+            "1700" = {
+              enable = false;
+              "1701" = {
+                enable = true;
+                "privacy.userContext.enabled" = {
+                  enable = true;
+                  value = false;
+                };
+                "privacy.userContext.ui.enabled" = {
+                  enable = true;
+                  value = false;
+                };
+              };
+              "1702" = {
+                enable = true;
+                "privacy.userContext.newTabContainerOnLeftClick.enabled" = {
+                  enable = true;
+                  value = false;
+                };
+              };
+            };
+            "2000".enable = true;
+            "2400".enable = false;
+            "2600" = {
+              enable = true;
+              "2615" = {
+                enable = true;
+                "permissions.default.shortcuts" = {
+                  enable = true;
+                  value = 2;
+                };
+              };
+            };
+            "2700".enable = true;
+            "2800".enable = true;
+          };
+
+          settings = {
+            "app.update.auto" = false;
+            "browser.bookmarks.max_backups" = 1;
+            "browser.disableResetPrompt" = true;
+            "browser.newtabpage.introShown" = true;
+            "browser.onboarding.enabled" = false;
+            "browser.search.update" = false;
+            "browser.startup.homepage_welcome_url" = "";
+            "browser.startup.homepage_welcome_url.additional" = "";
+            "browser.tabs.closeWindowWithLastTab" = true;
+            "browser.tabs.firefox-view" = false;
+            "browser.tabs.inTitlebar" = 1;
+            "browser.tabs.warnOnClose" = false;
+            "browser.tabs.warnOnCloseOtherTabs" = false;
+            "browser.tabs.warnOnOpen" = false;
+            "browser.toolbars.bookmarks.visibility" = "never";
+            "browser.urlbar.decodeURLsOnCopy" = true;
+            "browser.warnOnQuitShortcut" = false;
+            "extensions.pocket.enabled" = false;
+            "extensions.screenshots.disabled" = true;
+            "extensions.update.autoUpdateDefault" = false;
+            "extensions.update.enabled" = false;
+            "full-screen-api.warning.delay" = 0;
+            "full-screen-api.warning.timeout" = 0;
+            "identity.fxaccounts.enabled" = false;
+            "media.autoplay.blocking_policy" = 2;
+            "media.autoplay.default" = 5;
+            "media.autoplay.enabled" = false;
+            "reader.parse-on-load.enabled" = false;
+            "signon.rememberSignons" = false;
+            "toolkit.legacyUserProfileCustomizations.stylesheets" = true;
+          };
+        };
 
         extensions = with pkgs.nur.repos.rycee.firefox-addons;
+        with config.nixfiles.modules;
           [
             bitwarden
             darkreader
-            ipfs-companion
             libredirect
             noscript
-            stylus
             ublock-origin
             violentmonkey
           ]
-          ++ optional config.nixfiles.modules.kde.enable plasma-integration;
+          ++ optional ipfs.enable ipfs-companion;
       };
     };
+
+    services.psd.enable = true;
   };
 }
diff --git a/modules/nixfiles/firefox/profile.nix b/modules/nixfiles/firefox/profile.nix
deleted file mode 100644
index 2649402..0000000
--- a/modules/nixfiles/firefox/profile.nix
+++ /dev/null
@@ -1,480 +0,0 @@
-config: lib:
-with lib; let
-  mkCssWithRoot = css:
-    mkMerge [
-      (with config.colourScheme; ''
-        :root {
-            --black: ${black};
-            --red: ${red};
-            --green: ${green};
-            --yellow: ${yellow};
-            --blue: ${blue};
-            --magenta: ${magenta};
-            --cyan: ${cyan};
-            --white: ${white};
-            --bright-black: ${brightBlack};
-            --bright-red: ${brightRed};
-            --bright-green: ${brightGreen};
-            --bright-yellow: ${brightYellow};
-            --bright-blue: ${brightBlue};
-            --bright-magenta: ${brightMagenta};
-            --bright-cyan: ${brightCyan};
-            --bright-white: ${brightWhite};
-            --background: ${background};
-            --foreground: ${foreground};
-      '')
-      (with config.fontScheme; ''
-            --sans-serif-font-family: "${sansSerifFont.family}", "${sansSerifFontFallback.family}", sans-serif;
-            --sans-serif-font-size: ${toString sansSerifFont.size};
-            --serif-font-family: "${serifFont.family}", "${serifFontFallback.family}", serif;
-            --serif-font-size: ${toString serifFont.size};
-            --monospace-font-family: "${monospaceFont.family}", "${monospaceFontFallback.family}", monospace;
-            --monospace-font-size: ${toString monospaceFont.size};
-        }
-      '')
-      (builtins.readFile css)
-    ];
-in {
-  id = 0;
-
-  isDefault = true;
-
-  # A way to change the look of the Firefox itself.
-  userChrome = mkCssWithRoot ./userChrome.css;
-
-  # A way to remove annoyances and visual bloat of many webpages.
-  userContent = mkCssWithRoot ./userContent.css;
-
-  # Mostly appropriated from https://github.com/arkenfox/user.js
-  settings = {
-    # Updates
-    #
-    "app.update.auto" = false;
-    "browser.search.update" = false;
-    "extensions.update.enabled" = false;
-    "extensions.update.autoUpdateDefault" = false;
-    #
-    "extensions.getAddons.cache.enabled" = false;
-    "extensions.getAddons.showPane" = false;
-
-    # Telemetry
-    #
-    # https://bugzilla.mozilla.org/1195552
-    "datareporting.healthreport.service.enabled" = false;
-    "datareporting.healthreport.uploadEnabled" = false;
-    "datareporting.policy.dataSubmissionEnabled" = false;
-    # https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/internals/preferences.html
-    # https://medium.com/georg-fritzsche/data-preference-changes-in-firefox-58-2d5df9c428b5
-    "toolkit.telemetry.unified" = false;
-    "toolkit.telemetry.server" = "data:,";
-    "toolkit.telemetry.archive.enabled" = false;
-    "toolkit.telemetry.newProfilePing.enabled" = false;
-    "toolkit.telemetry.shutdownPingSender.enabled" = false;
-    "toolkit.telemetry.firstShutdownPing.enabled" = false;
-    "toolkit.telemetry.updatePing.enabled" = false;
-    "toolkit.telemetry.bhrPing.enabled" = false; # Background Hang Reporter
-    # https://blog.mozilla.org/data/2018/08/20/effectively-measuring-search-in-firefox
-    "toolkit.telemetry.coverage.opt-out" = true;
-    "toolkit.coverage.opt-out" = true;
-    "toolkit.coverage.endpoint.base" = "";
-
-    # Studies
-    #
-    # https://support.mozilla.org/en-US/kb/shield/
-    "app.shield.optoutstudies.enabled" = false;
-    # https://mozilla.github.io/normandy/
-    "app.normandy.enabled" = false;
-    "app.normandy.api_url" = "";
-
-    # Crash reports
-    #
-    "browser.tabs.crashReporting.sendReport" = false;
-    "breakpad.reportURL" = "";
-
-    # Captive Portal detection
-    #
-    # https://www.eff.org/deeplinks/2017/08/how-captive-portals-interfere-wireless-security-and-privacy
-    "captivedetect.canonicalURL" = "";
-    "network.captive-portal-service.enabled" = false;
-    # https://bugzilla.mozilla.org/1460537
-    "network.connectivity-service.enabled" = false;
-
-    # Safe browsing
-    #
-    # https://feeding.cloud.geek.nz/posts/how-safe-browsing-works-in-firefox/
-    # https://wiki.mozilla.org/Security/Safe_Browsing
-    # https://support.mozilla.org/kb/how-does-phishing-and-malware-protection-work
-    "browser.safebrowsing.malware.enabled" = false;
-    "browser.safebrowsing.passwords.enabled" = false;
-    "browser.safebrowsing.phishing.enabled" = false;
-    "browser.safebrowsing.downloads.enabled" = false;
-    "browser.safebrowsing.downloads.remote.enabled" = false;
-    "browser.safebrowsing.downloads.remote.url" = "";
-    "browser.safebrowsing.downloads.remote.block_potentially_unwanted" = false;
-    "browser.safebrowsing.downloads.remote.block_uncommon" = false;
-
-    # Implicit outbound
-    #
-    # https://developer.mozilla.org/docs/Web/HTTP/Link_prefetching_FAQ
-    "network.prefetch-next" = false;
-    # https://developer.mozilla.org/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control
-    "network.dns.disablePrefetch" = true;
-    "network.dns.disablePrefetchFromHTTPS" = true;
-    #
-    "network.predictor.enabled" = false;
-    "network.predictor.enable-prefetch" = false;
-    # https://news.slashdot.org/story/15/08/14/2321202/how-to-quash-firefoxs-silent-requests
-    "network.http.speculative-parallel-limit" = 0;
-    # https://www.bleepingcomputer.com/news/software/major-browsers-to-prevent-disabling-of-click-tracking-privacy-risk/
-    "browser.send_pings" = false;
-    # https://trac.torproject.org/projects/tor/wiki/doc/TorifyHOWTO/WebBrowsers
-    "network.proxy.socks_remote_dns" = true;
-    # https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/26424
-    "network.file.disable_unc_paths" = true;
-
-    # Proxy
-    #
-    # https://blog.mozilla.org/security/2021/10/25/securing-the-proxy-api-for-firefox-add-ons/
-    "network.proxy.failover_direct" = false;
-    # https://bugzilla.mozilla.org/buglist.cgi?bug_id=1732792,1733994,1733481
-    "network.proxy.allow_bypass" = false;
-
-    # DNS-over-HTTPS (DoH)
-    #
-    # https://hacks.mozilla.org/2018/05/a-cartoon-intro-to-dns-over-https/
-    # https://wiki.mozilla.org/Security/DOH-resolver-policy
-    # https://blog.mozilla.org/mozilla/news/firefox-by-default-dns-over-https-rollout-in-canada/
-    # https://www.eff.org/deeplinks/2020/12/dns-doh-and-odoh-oh-my-year-review-2020 ***/
-    "network.trr.mode" = 5;
-
-    # Location bar & search
-    #
-    "browser.fixup.alternate.enabled" = false;
-    #
-    "browser.urlbar.trimURLs" = false;
-    #
-    "browser.search.suggest.enabled" = false;
-    "browser.urlbar.suggest.searches" = false;
-    # https://bugzilla.mozilla.org/1348275
-    "browser.urlbar.speculativeConnect.enabled" = false;
-    # https://bugzilla.mozilla.org/1642623
-    "browser.urlbar.dnsResolveSingleWordsAfterSearch" = 0;
-    # https://blog.mozilla.org/data/2021/09/15/data-and-firefox-suggest/
-    "browser.urlbar.suggest.quicksuggest.nonsponsored" = false;
-    "browser.urlbar.suggest.quicksuggest.sponsored" = false;
-
-    # Search & form history
-    # https://blog.mindedsecurity.com/2011/10/autocompleteagain.html
-    # https://bugzilla.mozilla.org/381681
-    "browser.formfill.enable" = false;
-    # https://wiki.mozilla.org/Firefox/Features/Form_Autofill
-    "extensions.formautofill.available" = "off";
-    "extensions.formautofill.addresses.enabled" = false;
-    "extensions.formautofill.creditCards.available" = false;
-    "extensions.formautofill.creditCards.enabled" = false;
-    "extensions.formautofill.heuristics.enabled" = false;
-
-    # Passwords
-    #
-    "signon.rememberSignons" = false;
-
-    # Disk avoidance
-    #
-    # Disable caching to disk.
-    # This is a possible performance hit. Could be removed in favor of PSD?
-    "browser.cache.disk.enable" = false;
-    #
-    "browser.privatebrowsing.forceMediaMemoryCache" = true;
-    "media.memory_cache_max_size" = 65536;
-    # Extra session data
-    "browser.sessionstore.privacy_level" = 2;
-    # Reduce writes
-    "browser.sessionstore.interval" = 30000;
-
-    # SSL/TLS
-    #
-    # Block connections (SSL_ERROR_UNSAFE_NEGOTIATION) to servers that don't support RFC 5746
-    # https://wiki.mozilla.org/Security:Renegotiation
-    # https://datatracker.ietf.org/doc/html/rfc5746
-    # https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-3555
-    # https://www.ssllabs.com/ssl-pulse
-    "security.ssl.require_safe_negotiation" = true;
-    # Disable TLS1.3 0-RTT
-    # https://github.com/tlswg/tls13-spec/issues/1001
-    # https://www.rfc-editor.org/rfc/rfc9001.html#name-replay-attacks-with-0-rtt
-    # https://blog.cloudflare.com/tls-1-3-overview-and-q-and-a/
-    "security.tls.enable_0rtt_data" = false;
-
-    # OCSP (Online Certificate Status Protocol)
-    #
-    # https://en.wikipedia.org/wiki/Ocsp
-    # https://scotthelme.co.uk/revocation-is-broken/
-    # https://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/
-    # https://www.imperialviolet.org/2014/04/19/revchecking.html
-    # "security.OCSP.require" = true;
-
-    # HPKP (HTTP Public Key Pinning)
-    #
-    # https://blog.mozilla.org/security/2016/10/18/phasing-out-sha-1-on-the-public-web/
-    "security.pki.sha1_enforcement_level" = 1;
-    # https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/16206
-    "security.cert_pinning.enforcement_level" = 2;
-    # https://bugzilla.mozilla.org/buglist.cgi?bug_id=1429800,1670985
-    # https://blog.mozilla.org/security/tag/crlite/
-    "security.remote_settings.crlite_filters.enabled" = true;
-    "security.pki.crlite_mode" = 2;
-
-    # Mixed content
-    #
-    "security.mixed_content.block_display_content" = true;
-    # Force HTTPS-only mode
-    # Exceptions are managed on the settings page
-    "dom.security.https_only_mode" = true;
-    "dom.security.https_only_mode_pbm" = true;
-    # https://bugzilla.mozilla.org/buglist.cgi?bug_id=1642387,1660945
-    "dom.security.https_only_mode_send_http_background_request" = false;
-
-    # UI
-    #
-    # Dispaly warning on the padlock for "broken security"
-    # https://wiki.mozilla.org/Security:Renegotiation
-    # https://bugzilla.mozilla.org/1353705
-    "security.ssl.treat_unsafe_negotiation_as_broken" = true;
-    # https://github.com/pyllyukko/user.js/issues/210
-    "browser.ssl_override_behavior" = 1;
-    # Display advanced information on Insecure Connection warning pages
-    "browser.xul.error_pages.expert_bad_cert" = true;
-    # Display "Not Secure" text on HTTP sites
-    "security.insecure_connection_text.enabled" = true;
-    #
-    "browser.privatebrowsing.infoEnabled" = false;
-    "browser.privatebrowsing.infoTitleEnabled" = false;
-    "browser.privatebrowsing.promoEnabled" = false;
-    "browser.privatebrowsing.promoTitleEnabled" = false;
-    "browser.privatebrowsing.vpnpromourl" = "";
-
-    # UX
-    #
-    "browser.urlbar.decodeURLsOnCopy" = true;
-    #
-    "browser.tabs.closeWindowWithLastTab" = true;
-    #
-    "general.autoScroll" = true;
-    "general.smoothScroll" = true;
-
-    # Headers & referers
-    #
-    # "network.http.referer.XOriginPolicy" = 2;
-    # "network.http.referer.XOriginTrimmingPolicy" = 2;
-
-    # Containers
-    #
-    # https://wiki.mozilla.org/Security/Contextual_Identity_Project/Containers
-    # https://addons.mozilla.org/firefox/addon/temporary-containers/
-    # https://medium.com/@stoically/enhance-your-privacy-in-firefox-with-temporary-containers-33925cd6cd21
-    # https://github.com/stoically/temporary-containers/wiki
-    "privacy.userContext.enabled" = true;
-    "privacy.userContext.ui.enabled" = true;
-
-    # WebRTC
-    #
-    # Disable WebRTC
-    # https://browserleaks.com/webrtc
-    # https://groups.google.com/g/discuss-webrtc/c/6stQXi72BEU/m/2FwZd24UAQAJ
-    # https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-mdns-ice-candidates#section-3.1.1
-    # "media.peerconnection.enabled" = false;
-
-    # DRM
-    #
-    # https://www.eff.org/deeplinks/2017/10/drms-dead-canary-how-we-just-lost-web-what-we-learned-it-and-what-we-need-do-next
-    "media.eme.enabled" = false;
-    # https://bugzilla.mozilla.org/show_bug.cgi?id=1451762#c55
-    "browser.eme.ui.enabled" = false;
-
-    # GMP (Gecko Media Plugins)
-    #
-    "media.gmp-provider.enabled" = false;
-
-    # Disable autoplay of HTML5 media
-    "media.autoplay.enabled" = false;
-    "media.autoplay.default" = 5;
-    "media.autoplay.blocking_policy" = 2;
-
-    # DOM (Document Object Model)
-    #
-    # Disable "Confirm you want to leave" dialog on page close
-    # https://developer.mozilla.org/docs/Web/Events/beforeunload
-    "dom.disable_beforeunload" = true;
-    # Prevent scripts from moving and resizing open windows
-    "dom.disable_window_move_resize" = true;
-    # Block popup windows
-    "dom.disable_open_during_load" = true;
-    # Limit events that can cause a popup
-    "dom.popup_allowed_events" = "click dblclick mousedown pointerdown";
-
-    # PDFjs
-    #
-    # "pdfjs.disabled" = true;
-    "pdfjs.enableScripting" = false;
-
-    # Developer Tools
-    #
-    "devtools.accessibility.enabled" = false;
-    "devtools.application.enabled" = false;
-    "devtools.chrome.enabled" = true;
-    "devtools.dom.enabled" = true;
-    "devtools.enabled" = true;
-    "devtools.inspector.enabled" = true;
-    "devtools.jsonview.enabled" = true;
-    "devtools.memory.enabled" = true;
-    "devtools.netmonitor.enabled" = true;
-    "devtools.performance.enabled" = false;
-    "devtools.storage.enabled" = true;
-    "devtools.styleeditor.enabled" = true;
-    # This will prevent working with XUL
-    # https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/16222
-    "devtools.debugger.enabled" = false;
-    "devtools.debugger.remote-enabled" = false;
-
-    # Downloads
-    #
-    "browser.download.useDownloadDir" = false;
-    "browser.download.alwaysOpenPanel" = false;
-    "browser.download.manager.addToRecentDocs" = false;
-    "browser.download.autohideButton" = false;
-
-    # Extensions
-    #
-    # https://mike.kaply.com/2012/02/21/understanding-add-on-scopes/
-    # https://archive.is/DYjAM
-    "extensions.enabledScopes" = 5;
-    "extensions.autoDisableScopes" = 15;
-    # https://bugzilla.mozilla.org/buglist.cgi?bug_id=1659530,1681331
-    "extensions.postDownloadThirdPartyPrompt" = false;
-    # Disable recommendations in about:addons panes
-    "extensions.htmlaboutaddons.recommendations.enabled" = false;
-    # Mozilla's trash
-    "extensions.pocket.enabled" = false;
-    "extensions.screenshots.disabled" = true;
-    "idenitity.fxaccounts.enabled" = false;
-    "reader.parse-on-load.enabled" = false;
-
-    # ETP (Encahnced Tracking Protection)
-    #
-    # https://blog.mozilla.org/security/2021/02/23/total-cookie-protection/
-    "browser.contentblocking.category" = "strict";
-    "privacy.partition.serviceWorkers" = true;
-
-    # Sanitize
-    #
-    "privacy.sanitize.sanitizeOnShutdown" = true;
-    "privacy.sanitize.timeSpan" = 0;
-    "privacy.clearOnShutdown.cache" = true;
-    "privacy.clearOnShutdown.cookies" = false;
-    "privacy.clearOnShutdown.downloads" = true;
-    "privacy.clearOnShutdown.formdata" = true;
-    "privacy.clearOnShutdown.history" = false;
-    "privacy.clearOnShutdown.offlineApps" = false;
-    "privacy.clearOnShutdown.sessions" = false;
-    "privacy.clearOnShutdown.siteSettings" = false;
-    "privacy.cpd.cache" = true;
-    "privacy.cpd.cookies" = false;
-    "privacy.cpd.downloads" = true;
-    "privacy.cpd.formdata" = true;
-    "privacy.cpd.history" = false;
-    "privacy.cpd.offlineApps" = false;
-    "privacy.cpd.passwords" = false;
-    "privacy.cpd.sessions" = false;
-    "privacy.cpd.siteSettings" = false;
-
-    # Fingerprinting
-    #
-    # https://bugzilla.mozilla.org/418986
-    # "privacy.resistFingerprinting" = true;
-    # https://bugzilla.mozilla.org/1448423
-    # "browser.startup.blankWindow" = false;
-
-    # Rice
-    #
-    "toolkit.legacyUserProfileCustomizations.stylesheets" = true;
-    #
-    "browser.startup.page" = 1;
-    "browser.startup.homepage" = "about:blank";
-    "browser.startup.homepage_welcome_url" = "";
-    "browser.startup.homepage_welcome_url.additional" = "";
-    #
-    "browser.toolbars.bookmarks.visibility" = "never";
-    #
-    "browser.tabs.inTitlebar" = 1;
-    #
-    "browser.newtabpage.enabled" = false;
-    "browser.newtabpage.enhanced" = false;
-    "browser.newtabpage.activity-stream.default.sites" = "";
-    "browser.newtabpage.activity-stream.discoverystream.enabled" = false;
-    "browser.newtabpage.activity-stream.feeds.discoverystreamfeed" = false;
-    "browser.newtabpage.activity-stream.feeds.places" = false;
-    "browser.newtabpage.activity-stream.feeds.sections" = false;
-    "browser.newtabpage.activity-stream.feeds.snippets" = false;
-    "browser.newtabpage.activity-stream.feeds.telemetry" = false;
-    "browser.newtabpage.activity-stream.feeds.topsites" = false;
-    "browser.newtabpage.activity-stream.showSearch" = false;
-    "browser.newtabpage.activity-stream.showSponsored" = false;
-    "browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
-    "browser.newtabpage.activity-stream.telemetry" = false;
-    "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons" = false;
-    "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features" = false;
-    #
-    "layout.css.color-mix.enabled" = true;
-    #
-    "svg.context-properties.content.enabled" = true;
-
-    # Annoyances
-    #
-    "browser.aboutConfig.showWarning" = false;
-    "browser.disableResetPrompt" = true;
-    "browser.newtabpage.introShown" = true;
-    "browser.onboarding.enabled" = false;
-    "browser.shell.checkDefaultBrowser" = false;
-    "browser.tabs.warnOnClose" = false;
-    "browser.tabs.warnOnCloseOtherTabs" = false;
-    "browser.tabs.warnOnOpen" = false;
-    "browser.tabs.warnOnQuitShortcut" = false;
-    "full-screen-api.warning.delay" = 0;
-    "full-screen-api.warning.timeout" = 0;
-    "permissions.default.shortcuts" = 2;
-    "security.dialog_enable_delay" = 0;
-
-    # Geo
-    #
-    # Disable OS provider
-    "geo.provider.use_gpsd" = false;
-    # Use the Mozilla provider. Defaults to Google otherwise
-    "geo.provider.network.url" = "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%";
-
-    # Unsorted
-    #
-    "accessibility.force_disabled" = 1;
-    "beacon.enabled" = false;
-    "browser.helperApps.deleteTempFileOnExit" = true;
-    "browser.pagethumbnails.capturing_disabled" = true;
-    "browser.region.network.url" = "";
-    "browser.region.update.enabled" = false;
-    "browser.selfsupport.url" = "";
-    "browser.uitour.enabled" = false;
-    "browser.uitour.url" = "";
-    "intl.accept_languages" = "en-US, en";
-    "layout.spellcheckDefault" = 2;
-    "middlemouse.contentLoadURL" = false;
-    "permissions.delegation.enabled" = false;
-    "permissions.manager.defaultsUrl" = "";
-    "webchannel.allowObject.urlWhitelist" = "";
-    "network.manage-offline-status" = false;
-    "xpinstall.signatures.required" = false;
-
-    # Toolbar
-    #
-    "browser.uiCustomization.state" = ''
-      {"placements":{"widget-overflow-fixed-list":["ublock0_raymondhill_net-browser-action","_73a6fe31-595d-460b-a920-fcc0f8843232_-browser-action","7esoorv3_alefvanoon_anonaddy_me-browser-action","_2e5ff8c8-32fe-46d0-9fc8-6b8986621f3c_-browser-action","_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action","ipfs-firefox-addon_lidel_org-browser-action","addon_darkreader_org-browser-action","_7a7a4a92-a2a0-41d1-9fd7-1e92480d612d_-browser-action","_aecec67f-0d10-4fa7-b7c7-609a2db280cf_-browser-action"],"nav-bar":["back-button","forward-button","urlbar-container","save-to-pocket-button"],"toolbar-menubar":["menubar-items"],"TabsToolbar":["tabbrowser-tabs","new-tab-button","alltabs-button"],"PersonalToolbar":["personal-bookmarks"]},"seen":["addon_darkreader_org-browser-action","ipfs-firefox-addon_lidel_org-browser-action","plasma-browser-integration_kde_org-browser-action","ublock0_raymondhill_net-browser-action","_2e5ff8c8-32fe-46d0-9fc8-6b8986621f3c_-browser-action","_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action","_73a6fe31-595d-460b-a920-fcc0f8843232_-browser-action","_7a7a4a92-a2a0-41d1-9fd7-1e92480d612d_-browser-action","_aecec67f-0d10-4fa7-b7c7-609a2db280cf_-browser-action","_b7f9d2cd-d772-4302-8c3f-eb941af36f76_-browser-action","developer-button","_a4c4eda4-fb84-4a84-b4a1-f7c1cbf2a1ad_-browser-action","7esoorv3_alefvanoon_anonaddy_me-browser-action"],"dirtyAreaCache":["nav-bar","widget-overflow-fixed-list","toolbar-menubar","TabsToolbar","PersonalToolbar"],"currentVersion":17,"newElementCount":8}
-    '';
-  };
-}
diff --git a/modules/nixfiles/firefox/userContent.css b/modules/nixfiles/firefox/userContent.css
index 1dc3add..ff74e01 100644
--- a/modules/nixfiles/firefox/userContent.css
+++ b/modules/nixfiles/firefox/userContent.css
@@ -82,8 +82,29 @@
     }
 }
 
+@-moz-document regexp("https?:\/\/kubernetes\.io\/docs\/.*") {
+    .announcement,
+    .announcement-main,
+    .d-none {
+        display: none !important;
+    }
+}
+
+@-moz-document regexp("https?:\/\/min\.io\/docs\/.*") {
+    #cookie {
+        display: none !important;
+    }
+}
+
+@-moz-document regexp("https?:\/\/werf\.io\/documentation\/.*") {
+    .guides-banner {
+        display: none !important;
+    }
+}
+
 @-moz-document regexp("https:\/\/habr\.com\/(ru|en)\/(article|company\/.*\/blog|post)\/.*") {
     .Vue-Toastification__container,
+    .tm-article-presenter__footer,
     .tm-article-presenter__meta,
     .tm-article-snippet__labels,
     .tm-article-sticky-panel,
@@ -99,6 +120,8 @@
     .tm-notice,
     .tm-page__header,
     .tm-page__sidebar,
+    .tm-placeholder-inset,
+    .tm-placeholder-promo,
     .tm-user-info,
     vue-portal-target {
         display: none !important;
@@ -174,48 +197,6 @@
     }
 }
 
-@-moz-document regexp("https?:\/\/utaten\.com\/lyric/.*") {
-    :root {
-        --kana-font-size: 20px;
-        --furigana-font-size: 14px;
-    }
-
-    body {
-        font-family: var(--sans-serif-font-family) !important;
-        font-size: var(--kana-font-size) !important;
-    }
-
-    .rb {
-        font-size: var(--kana-font-size) !important;
-    }
-
-    .rt {
-        font-size: var(--furigana-font-size) !important;
-    }
-
-    #JP_uta_pc_lyric_footeroverlay,
-    #footer__area,
-    #reviews,
-    #sidebar,
-    .btn_sbs,
-    .gaugeWrap,
-    .lyricData,
-    .movie_contents,
-    .newLyricWorkFooter,
-    .path::before,
-    .recommendAdTag,
-    .shareArea,
-    .sideBySideBanner,
-    .topBanner,
-    header {
-        display: none !important;
-    }
-
-    #contents {
-        width: 100% !important;
-    }
-}
-
 @-moz-document regexp("https?:\/\/www\.songsterr\.com.*") {
     #favorite,
     #fullscreen,
@@ -239,7 +220,6 @@
     #shots,
     a[rel*="noreferrer"],
     a[target="_blank"],
-    button,
     div[class*="SiteWideBanner"],
     footer,
     iframe {
@@ -257,7 +237,7 @@
     }
 }
 
-@-moz-document regexp("https:\/\/\.*\.wikipedia\.org.*") {
+@-moz-document regexp("https:\/\/\.*\.wiki(pedia|less)\.org.*") {
     #footer,
     #mp-topbanner,
     #mw-head,
diff --git a/modules/nixfiles/fonts.nix b/modules/nixfiles/fonts.nix
index 18c6f52..042c0e8 100644
--- a/modules/nixfiles/fonts.nix
+++ b/modules/nixfiles/fonts.nix
@@ -81,7 +81,6 @@ in {
   };
 
   config = mkMerge [
-    {home-manager.users.root.fonts.fontconfig.enable = false;}
     (mkIf cfg.enable {
       hm.fonts.fontconfig.enable = true;
 
diff --git a/modules/nixfiles/games/lutris.nix b/modules/nixfiles/games/lutris.nix
index 0c942a8..e7faef3 100644
--- a/modules/nixfiles/games/lutris.nix
+++ b/modules/nixfiles/games/lutris.nix
@@ -29,9 +29,6 @@ in {
           };
         };
         steamSupport = false;
-        extraPkgs = _: [
-          driversi686Linux.mesa # Battle.net
-        ];
       })
     ];
   };
diff --git a/modules/nixfiles/games/steam-run.nix b/modules/nixfiles/games/steam-run.nix
index bab12f3..4731fd6 100644
--- a/modules/nixfiles/games/steam-run.nix
+++ b/modules/nixfiles/games/steam-run.nix
@@ -63,6 +63,7 @@ in {
       elem (getName p) [
         "steam"
         "steam-original"
+        "steam-run"
       ];
   };
 }
diff --git a/modules/nixfiles/games/steam.nix b/modules/nixfiles/games/steam.nix
index 71e5068..bbd01f6 100644
--- a/modules/nixfiles/games/steam.nix
+++ b/modules/nixfiles/games/steam.nix
@@ -22,6 +22,7 @@ in {
       elem (getName p) [
         "steam"
         "steam-original"
+        "steam-run"
       ];
   };
 }
diff --git a/modules/nixfiles/git.nix b/modules/nixfiles/git.nix
index b121f8f..facff2f 100644
--- a/modules/nixfiles/git.nix
+++ b/modules/nixfiles/git.nix
@@ -130,7 +130,7 @@ in {
               "[._]ss[a-gi-z]"
               "[._]sw[a-p]"
               "\#*\#"
-              "compile_commands.json"
+              "compile_commands*.json"
               "cscope.*"
               "vgcore.*"
             ];
@@ -142,8 +142,14 @@ in {
           };
 
           bash = {
-            shellAliases.gl = "${pkgs.glab}/bin/glab";
-            initExtra = mkAfter "_complete_alias gl __start_glab glab";
+            shellAliases = {
+              gl = "${pkgs.glab}/bin/glab";
+              ht = "${pkgs.hut}/bin/hut";
+            };
+            initExtra = mkAfter ''
+              _complete_alias gl __start_glab glab
+              _complete_alias ht __start_hut hut
+            '';
           };
         };
       };
@@ -202,7 +208,7 @@ in {
         group = "git";
       in {
         gitolite = {
-          # TODO Make configuration purely declarative.
+          # TODO Make the configuration purely declarative.
           enable = true;
           inherit user group;
           adminPubkey = my.ssh.key;
diff --git a/modules/nixfiles/gotify.nix b/modules/nixfiles/gotify.nix
index 8489e93..f21a98d 100644
--- a/modules/nixfiles/gotify.nix
+++ b/modules/nixfiles/gotify.nix
@@ -30,7 +30,14 @@ in {
             extraConfig = nginxInternalOnly;
           };
         };
-        postgresql.enable = true;
+        postgresql = {
+          enable = true;
+          extraPostStart = [
+            ''
+              $PSQL "${db}" -tAc 'GRANT ALL ON SCHEMA "public" TO "${db}"'
+            ''
+          ];
+        };
       };
 
       services = {
@@ -44,7 +51,7 @@ in {
           ensureUsers = [
             {
               name = db;
-              ensurePermissions."DATABASE \"${db}\"" = "ALL PRIVILEGES";
+              ensurePermissions."DATABASE \"${db}\"" = "ALL";
             }
           ];
         };
diff --git a/modules/nixfiles/grafana.nix b/modules/nixfiles/grafana.nix
index c29bf75..807f8fe 100644
--- a/modules/nixfiles/grafana.nix
+++ b/modules/nixfiles/grafana.nix
@@ -23,69 +23,77 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
-    secrets = {
-      grafana-admin-password = {
-        file = "${inputs.self}/secrets/grafana-admin-password";
-        owner = "grafana";
-        group = "grafana";
-      };
-      grafana-key = {
-        file = "${inputs.self}/secrets/grafana-key";
-        owner = "grafana";
-        group = "grafana";
+  config = let
+    db = "grafana";
+  in
+    mkIf cfg.enable {
+      secrets = {
+        grafana-admin-password = {
+          file = "${inputs.self}/secrets/grafana-admin-password";
+          owner = "grafana";
+          group = "grafana";
+        };
+        grafana-key = {
+          file = "${inputs.self}/secrets/grafana-key";
+          owner = "grafana";
+          group = "grafana";
+        };
       };
-    };
 
-    nixfiles.modules = {
-      nginx = {
-        enable = true;
-        upstreams.grafana.servers."127.0.0.1:${toString cfg.port}" = {};
-        virtualHosts.${cfg.domain}.locations."/" = {
-          proxyPass = "http://grafana";
-          proxyWebsockets = true;
-          extraConfig = nginxInternalOnly;
+      nixfiles.modules = {
+        nginx = {
+          enable = true;
+          upstreams.grafana.servers."127.0.0.1:${toString cfg.port}" = {};
+          virtualHosts.${cfg.domain}.locations."/" = {
+            proxyPass = "http://grafana";
+            proxyWebsockets = true;
+            extraConfig = nginxInternalOnly;
+          };
+        };
+        postgresql = {
+          enable = true;
+          extraPostStart = [
+            ''
+              $PSQL "${db}" -tAc 'GRANT ALL ON SCHEMA "public" TO "${db}"'
+            ''
+          ];
         };
       };
-      postgresql.enable = true;
-    };
 
-    services = let
-      db = "grafana";
-    in {
-      grafana = {
-        enable = true;
+      services = {
+        grafana = {
+          enable = true;
 
-        inherit (cfg) domain port;
-        protocol = "http";
-        addr = "127.0.0.1";
+          inherit (cfg) domain port;
+          protocol = "http";
+          addr = "127.0.0.1";
 
-        analytics.reporting.enable = false;
+          analytics.reporting.enable = false;
 
-        database = {
-          type = "postgres";
-          host = "/run/postgresql";
-          name = db;
-          user = db;
-        };
+          database = {
+            type = "postgres";
+            host = "/run/postgresql";
+            name = db;
+            user = db;
+          };
 
-        security = with config.secrets; {
-          secretKeyFile = grafana-key.path;
-          adminPasswordFile = grafana-admin-password.path;
-        };
+          security = with config.secrets; {
+            secretKeyFile = grafana-key.path;
+            adminPasswordFile = grafana-admin-password.path;
+          };
 
-        extraOptions.LOG_LEVEL = "warn";
-      };
+          extraOptions.LOG_LEVEL = "warn";
+        };
 
-      postgresql = {
-        ensureDatabases = [db];
-        ensureUsers = [
-          {
-            name = db;
-            ensurePermissions."DATABASE \"${db}\"" = "ALL PRIVILEGES";
-          }
-        ];
+        postgresql = {
+          ensureDatabases = [db];
+          ensureUsers = [
+            {
+              name = db;
+              ensurePermissions."DATABASE \"${db}\"" = "ALL";
+            }
+          ];
+        };
       };
     };
-  };
 }
diff --git a/modules/nixfiles/hydra.nix b/modules/nixfiles/hydra.nix
index 2168ed5..590fecb 100644
--- a/modules/nixfiles/hydra.nix
+++ b/modules/nixfiles/hydra.nix
@@ -48,7 +48,7 @@ in {
         ensureUsers = [
           {
             name = db;
-            ensurePermissions."DATABASE \"${db}\"" = "ALL PRIVILEGES";
+            ensurePermissions."DATABASE \"${db}\"" = "ALL";
           }
         ];
       };
diff --git a/modules/nixfiles/matrix/dendrite.nix b/modules/nixfiles/matrix/dendrite.nix
index 8dbc318..0fad5f2 100644
--- a/modules/nixfiles/matrix/dendrite.nix
+++ b/modules/nixfiles/matrix/dendrite.nix
@@ -12,138 +12,146 @@ in {
     enable = mkEnableOption "Dendrite Matrix server";
 
     domain = mkOption {
-      description = "Domain name sans protocol scheme.";
-      type = with types; str;
+      type = types.str;
       default = config.networking.domain;
+      description = "Domain name sans protocol scheme.";
     };
   };
 
-  config = mkIf cfg.enable {
-    secrets.dendrite-private-key = {
-      file = "${inputs.self}/secrets/dendrite-private-key";
-      mode = "0444"; # FIXME User is dynamic so the file must be world-readable.
-    };
+  config = let
+    db = "dendrite";
+  in
+    mkIf cfg.enable {
+      secrets.dendrite-private-key = {
+        file = "${inputs.self}/secrets/dendrite-private-key";
+        mode = "0444"; # The user is dynamic so the file must be world-readable.
+      };
+      secrets.dendrite-environment-file = {
+        file = "${inputs.self}/secrets/dendrite-environment-file";
+        mode = "0444"; # The user is dynamic so the file must be world-readable.
+      };
 
-    nixfiles.modules = {
-      nginx = {
-        enable = true;
-        upstreams.dendrite.servers."127.0.0.1:${toString config.services.dendrite.httpPort}" = {};
-        virtualHosts.${cfg.domain}.locations = {
-          "/_matrix".proxyPass = "http://dendrite";
-          "= /.well-known/matrix/server" = {
-            extraConfig = ''
-              add_header Content-Type application/json;
-            '';
-            return = "200 '${
-              generators.toJSON {} {"m.server" = "${cfg.domain}:443";}
-            }'";
-          };
-          "= /.well-known/matrix/client" = {
-            extraConfig = ''
-              add_header Content-Type application/json;
-              add_header Access-Control-Allow-Origin *;
-            '';
-            return = "200 '${
-              generators.toJSON {} {
-                "m.homeserver".base_url = "https://${cfg.domain}";
-              }
-            }'";
+      nixfiles.modules = {
+        nginx = {
+          enable = true;
+          upstreams.dendrite.servers."127.0.0.1:${toString config.services.dendrite.httpPort}" = {};
+          virtualHosts.${cfg.domain}.locations = {
+            "/_matrix".proxyPass = "http://dendrite";
+            "= /.well-known/matrix/server" = {
+              extraConfig = ''
+                add_header Content-Type application/json;
+              '';
+              return = "200 '${
+                generators.toJSON {} {"m.server" = "${cfg.domain}:443";}
+              }'";
+            };
+            "= /.well-known/matrix/client" = {
+              extraConfig = ''
+                add_header Content-Type application/json;
+                add_header Access-Control-Allow-Origin *;
+              '';
+              return = "200 '${
+                generators.toJSON {} {
+                  "m.homeserver".base_url = "https://${cfg.domain}";
+                }
+              }'";
+            };
           };
         };
+        postgresql = {
+          enable = true;
+          extraPostStart = [
+            ''
+              $PSQL "${db}" -tAc 'GRANT ALL ON SCHEMA "public" TO "${db}"'
+            ''
+          ];
+        };
       };
-      postgresql.enable = true;
-    };
-
-    services = let
-      name = "dendrite";
-      prefix = "${name}-";
-      databaseNames = [
-        "account"
-        "appservice"
-        "device"
-        "federation"
-        "key"
-        "media"
-        "mscs"
-        "room"
-        "sync"
-      ];
-      databaseList = forEach databaseNames (x: concatStrings [prefix x]);
-      databaseAttr = genAttrs databaseNames (x: concatStrings [prefix x]);
-
-      mkDatabaseConnection = database: "postgres://${name}@/${database}?sslmode=disable";
-    in {
-      dendrite = {
-        enable = true;
-        httpPort = 8008;
-        settings = {
-          global = {
-            server_name = cfg.domain;
-
-            private_key = config.secrets.dendrite-private-key.path;
-
-            disable_federation = false;
-          };
-
-          app_service_api.database.connection_string =
-            mkDatabaseConnection databaseAttr.appservice;
 
-          client_api = {
-            registration_disabled = true;
-            turn = {}; # TODO
-          };
-
-          federation_api.database.connection_string =
-            mkDatabaseConnection databaseAttr.federation;
-
-          key_server.database.connection_string =
-            mkDatabaseConnection databaseAttr.key;
-
-          media_api = {
-            database.connection_string =
-              mkDatabaseConnection databaseAttr.media;
-            base_path = "./media";
-          };
-
-          mscs.database.connection_string =
-            mkDatabaseConnection databaseAttr.mscs;
-
-          room_server.database.connection_string =
-            mkDatabaseConnection databaseAttr.room;
-
-          sync_api.database.connection_string =
-            mkDatabaseConnection databaseAttr.sync;
-
-          user_api = {
-            account_database.connection_string =
-              mkDatabaseConnection databaseAttr.account;
-            device_database.connection_string =
-              mkDatabaseConnection databaseAttr.device;
+      services = {
+        dendrite = {
+          enable = true;
+          httpPort = 8008;
+          environmentFile = config.secrets.dendrite-environment-file.path;
+          settings = {
+            version = 2;
+            global = {
+              server_name = cfg.domain;
+              private_key = config.secrets.dendrite-private-key.path;
+              database = {
+                connection_string = "postgresql://${db}@/${db}?host=/run/postgresql";
+                max_open_conns = 64;
+                max_idle_connections = 8;
+              };
+              cache = {
+                max_size_estimated = "1gb";
+                max_age = "1h";
+              };
+              trusted_third_party_id_servers = [
+                "matrix.org"
+                "nixos.org"
+                "vector.im"
+              ];
+              presence = {
+                enable_inbound = false;
+                enable_outbound = false;
+              };
+            };
+            client_api = {
+              registration_disabled = true;
+              guests_disabled = true;
+              registration_shared_secret = "$REGISTRATION_SHARED_SECRET";
+            };
+            media_api = {
+              max_file_size_bytes = 0;
+              dynamic_thumbnails = true;
+              max_thumbnail_generators = 8;
+              thumbnail_sizes = [
+                {
+                  width = 32;
+                  height = 32;
+                  method = "crop";
+                }
+                {
+                  width = 96;
+                  height = 96;
+                  method = "crop";
+                }
+                {
+                  width = 640;
+                  height = 480;
+                  method = "scale";
+                }
+              ];
+            };
+            logging = [
+              {
+                type = "std";
+                level = "warn";
+              }
+            ];
           };
+        };
 
-          metrics.enabled = false; # TODO
+        postgresql = {
+          ensureDatabases = [db];
+          ensureUsers = [
+            {
+              name = db;
+              ensurePermissions."DATABASE \"${db}\"" = "ALL";
+            }
+          ];
         };
       };
 
-      postgresql = {
-        ensureDatabases = databaseList;
-        ensureUsers =
-          map (x: {
-            inherit name;
-            ensurePermissions."DATABASE \"${x}\"" = "ALL PRIVILEGES";
-          })
-          databaseList;
-      };
+      systemd.services.dendrite.serviceConfig.ExecStart =
+        mkForce
+        (concatStringsSep " " [
+          "${pkgs.dendrite}/bin/dendrite-monolith-server"
+          "--config /run/dendrite/dendrite.yaml"
+          "--http-bind-address 127.0.0.1:${
+            toString config.services.dendrite.httpPort
+          }"
+        ]);
     };
-
-    systemd.services.dendrite.serviceConfig.ExecStart =
-      mkForce
-      (concatStringsSep " " [
-        "${pkgs.dendrite}/bin/dendrite-monolith-server"
-        "--config /run/dendrite/dendrite.yaml"
-        "--http-bind-address 127.0.0.1:${
-          toString config.services.dendrite.httpPort
-        }"
-      ]);
-  };
 }
diff --git a/modules/nixfiles/matrix/synapse.nix b/modules/nixfiles/matrix/synapse.nix
index 5f16b7d..6ff5e0d 100644
--- a/modules/nixfiles/matrix/synapse.nix
+++ b/modules/nixfiles/matrix/synapse.nix
@@ -79,13 +79,15 @@ in {
           ];
         };
 
-        postgresql.initialScript = pkgs.writeText "init-matrix-synapse.sql" ''
-          CREATE USER "${db}";
-          CREATE DATABASE "${db}" WITH OWNER "${db}"
-            TEMPLATE template0
-            LC_COLLATE = "C"
-            LC_CTYPE = "C";
-        '';
+        postgresql = {
+          ensureDatabases = [db];
+          ensureUsers = [
+            {
+              name = db;
+              ensurePermissions."DATABASE \"${db}\"" = "ALL";
+            }
+          ];
+        };
       };
     };
 }
diff --git a/modules/nixfiles/monitoring/default.nix b/modules/nixfiles/monitoring/default.nix
index 35261e2..d5ed1b5 100644
--- a/modules/nixfiles/monitoring/default.nix
+++ b/modules/nixfiles/monitoring/default.nix
@@ -7,7 +7,9 @@
 with lib; let
   cfg = config.nixfiles.modules.monitoring;
 in {
-  options.nixfiles.modules.monitoring.enable = mkEnableOption "a custom monitoring stack";
+  options.nixfiles.modules.monitoring.enable = mkEnableOption ''
+    a custom monitoring stack bas on the Grafana Labs toolkit
+  '';
 
   config = mkIf cfg.enable {
     nixfiles.modules = {
@@ -60,6 +62,8 @@ in {
             options.path = ./dashboards/postgresql.json;
           }
         ];
+
+        notifiers = []; # TODO Add.
       };
 
       loki.configuration.ruler.alertmanager_url = "https://${config.nixfiles.modules.alertmanager.domain}";
@@ -67,69 +71,96 @@ in {
       prometheus = {
         # It would be nice if these could be generated dynamically. That would
         # require a complete rework of how configurations are defined, though.
-        scrapeConfigs = with my.configurations;
-        with config.services.prometheus.exporters; [
-          {
-            job_name = "endlessh-go";
-            static_configs = [
-              {
-                targets = with config.services.endlessh-go.prometheus; [
-                  "${manwe.hostname}:${toString port}"
-                  "${varda.hostname}:${toString port}"
-                  "${yavanna.hostname}:${toString port}"
-                ];
-              }
-            ];
-          }
-          {
-            job_name = "nginx";
-            static_configs = [
-              {
-                targets = with nginx; [
-                  "${manwe.hostname}:${toString port}"
-                  "${varda.hostname}:${toString port}"
-                  "${yavanna.hostname}:${toString port}"
-                ];
-              }
-            ];
-          }
-          {
-            job_name = "node";
-            static_configs = [
-              {
-                targets = with node; [
-                  "${manwe.hostname}:${toString port}"
-                  "${varda.hostname}:${toString port}"
-                  "${yavanna.hostname}:${toString port}"
-                ];
-              }
-            ];
-          }
-          {
-            job_name = "postgres";
-            static_configs = [
-              {
-                targets = with postgres; ["${manwe.hostname}:${toString port}"];
-              }
-            ];
-          }
-          {
-            job_name = "unbound";
-            static_configs = [
-              {
-                targets = with unbound; ["${manwe.hostname}:${toString port}"];
-              }
-            ];
-          }
-          {
-            job_name = "wireguard";
-            static_configs = [
-              {
-                targets = with wireguard; ["${manwe.hostname}:${toString port}"];
-              }
-            ];
-          }
-        ];
+        scrapeConfigs = let
+          mkTargets = hosts: port: map (host: "${host.hostname}:${toString port}") hosts;
+        in
+          with my.configurations;
+          with config.services.prometheus.exporters; [
+            {
+              job_name = "endlessh-go";
+              static_configs = [
+                {
+                  targets =
+                    mkTargets
+                    [
+                      manwe
+                      varda
+                      yavanna
+                    ]
+                    config.services.endlessh-go.prometheus.port;
+                }
+              ];
+            }
+            {
+              job_name = "nginx";
+              static_configs = [
+                {
+                  targets =
+                    mkTargets
+                    [
+                      manwe
+                      varda
+                      yavanna
+                    ]
+                    nginx.port;
+                }
+              ];
+            }
+            {
+              job_name = "node";
+              static_configs = [
+                {
+                  targets =
+                    mkTargets
+                    [
+                      manwe
+                      varda
+                      yavanna
+                    ]
+                    node.port;
+                }
+              ];
+            }
+            {
+              job_name = "postgres";
+              static_configs = [
+                {
+                  targets =
+                    mkTargets
+                    [
+                      manwe
+                    ]
+                    postgres.port;
+                }
+              ];
+            }
+            {
+              job_name = "unbound";
+              static_configs = [
+                {
+                  targets =
+                    mkTargets
+                    [
+                      manwe
+                    ]
+                    unbound.port;
+                }
+              ];
+            }
+            {
+              job_name = "wireguard";
+              static_configs = [
+                {
+                  targets =
+                    mkTargets
+                    [
+                      manwe
+                    ]
+                    wireguard.port;
+                }
+              ];
+            }
+          ];
 
         alertmanagers = [
           {
diff --git a/modules/nixfiles/nextcloud.nix b/modules/nixfiles/nextcloud.nix
index 11eb8d3..69bea8a 100644
--- a/modules/nixfiles/nextcloud.nix
+++ b/modules/nixfiles/nextcloud.nix
@@ -103,7 +103,7 @@ in {
         ensureUsers = [
           {
             name = db;
-            ensurePermissions."DATABASE \"${db}\"" = "ALL PRIVILEGES";
+            ensurePermissions."DATABASE \"${db}\"" = "ALL";
           }
         ];
       };
diff --git a/modules/nixfiles/nsd.nix b/modules/nixfiles/nsd.nix
index 57973ee..0dade8f 100644
--- a/modules/nixfiles/nsd.nix
+++ b/modules/nixfiles/nsd.nix
@@ -107,6 +107,7 @@ in {
                       # ns2 = varda;
 
                       alertmanager = manwe;
+                      bitwarden = manwe;
                       git = manwe;
                       gotify = manwe;
                       grafana = manwe;
diff --git a/modules/nixfiles/postgresql.nix b/modules/nixfiles/postgresql.nix
index 14bfc68..df05e7e 100644
--- a/modules/nixfiles/postgresql.nix
+++ b/modules/nixfiles/postgresql.nix
@@ -8,17 +8,52 @@
 with lib; let
   cfg = config.nixfiles.modules.postgresql;
 in {
-  options.nixfiles.modules.postgresql.enable = mkEnableOption "PostgeSQL";
+  options.nixfiles.modules.postgresql = {
+    enable = mkEnableOption "PostgreSQL";
+
+    package = mkOption {
+      type = types.package;
+      default = pkgs.postgresql_15;
+      description = "PostgreSQL package to use.";
+    };
+
+    extraPostStart = mkOption {
+      type = with types; listOf str;
+      default = [];
+      description = ''
+        Additional post-startup commands.
+
+        This could be used to provide a crude interface to grant permissions and
+        such.
+      '';
+    };
+  };
 
   config = mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = any (x: x == "en_GB.UTF-8/UTF-8") config.i18n.supportedLocales;
+        message = "The locale must be available";
+      }
+    ];
+
     services = {
       postgresql = {
         enable = true;
-        package = pkgs.postgresql_14; # Pin version to prevent any surprises.
+
+        inherit (cfg) package;
+
+        initdbArgs = [
+          "--encoding=UTF8"
+          "--locale-provider=icu"
+          "--icu-locale=en_GB@collation=posix"
+          "--locale=en_GB.UTF-8"
+          "--lc-collate=C"
+          "--lc-ctype=C"
+        ];
+
         authentication = ''
           local all all trust
-          host all all 127.0.0.1/32 trust
-          host all all ::1/128 trust
         '';
       };
 
@@ -29,6 +64,11 @@ in {
       };
     };
 
+    systemd.services.postgresql.postStart =
+      optionalString (cfg.extraPostStart != [])
+      concatStringsSep "\n"
+      cfg.extraPostStart;
+
     environment.sessionVariables.PSQLRC = toString (pkgs.writeText "psqlrc" ''
       \set QUIET 1
 
diff --git a/modules/nixfiles/profiles/default.nix b/modules/nixfiles/profiles/default.nix
index c236722..356413a 100644
--- a/modules/nixfiles/profiles/default.nix
+++ b/modules/nixfiles/profiles/default.nix
@@ -77,8 +77,8 @@ in {
       vim.enable = true;
     };
 
-    home-manager.users.root.home.file.".bash_history".source =
-      config.hm.lib.file.mkOutOfStoreSymlink "/dev/null";
+    # home-manager.users.root.home.file.".bash_history".source =
+    #   config.hm.lib.file.mkOutOfStoreSymlink "/dev/null";
 
     hm.home.language = {
       collate = "C";
diff --git a/modules/nixfiles/profiles/dev/default.nix b/modules/nixfiles/profiles/dev/default.nix
index 1a0ad07..4656ade 100644
--- a/modules/nixfiles/profiles/dev/default.nix
+++ b/modules/nixfiles/profiles/dev/default.nix
@@ -28,91 +28,9 @@ in {
 
     hm.home = {
       file = {
-        ".editorconfig".text = ''
-          root = true
+        ".editorconfig".source = ./editorconfig.ini;
 
-          [*]
-          charset = utf-8
-          end_of_line = lf
-          indent_size = 4
-          indent_style = space
-          insert_final_newline = true
-          max_line_length = 80
-          trim_trailing_whitespace = true
-
-          [*.nix]
-          indent_size = 2
-          indent_style = space
-
-          [*.{S,s,asm}]
-          indent_size = 4
-          indent_style = tab
-
-          [*.{C,H,c,c++,cc,cpp,cxx,h,h++,hh,hpp,hxx}]
-          indent_size = 4
-          indent_style = tab
-
-          [*.{cl,clj,el,l,lisp,lsp,rkt,scm,ss}]
-          indent_size = 2
-          indent_style = space
-
-          [*.go]
-          indent_size = 4
-          indent_style = tab
-
-          [*.{py,pyx}]
-          indent_size = 4
-          indent_style = space
-
-          [*.{hs,lhs}]
-          indent_size = 2
-          indent_style = space
-
-          [*.{html,xhtml,xml}]
-          indent_size = 4
-          indent_style = tab
-
-          [*.json]
-          indent_size = 2
-          indent_style = space
-
-          [*.{yaml,yml}]
-          indent_size = 2
-          indent_style = space
-
-          [*.{toml,tml}]
-          indent_size = 4
-          indent_style = space
-
-          [*.{py,pyx}]
-          indent_size = 4
-          indent_style = space
-          max_line_length = 72
-
-          [*.zig]
-          indent_size = 4
-          indent_style = tab
-
-          [configure.ac]
-          indent_size = 4
-          indent_style = tab
-
-          [{Makefile*,*.mk}]
-          indent_size = 4
-          indent_style = tab
-
-          [{CMakeLists.txt,*.cmake}]
-          indent_size = 8
-          indent_style = tab
-
-          [*.tex]
-          indent_size = 4
-          indent_style = tab
-
-          [*.{md,adoc,rtf,txt}]
-          indent_size = 4
-          indent_style = tab
-        '';
+        ".gdbinit".source = ./gdbinit;
 
         ".ghc/ghci.conf".source = ./ghci.conf;
 
@@ -125,140 +43,41 @@ in {
           };
         };
 
-        ".clang-format".text = generators.toYAML {} {
-          AccessModifierOffset = -4;
-          AlignAfterOpenBracket = "Align";
-          AlignConsecutiveAssignments = "Consecutive";
-          AlignConsecutiveBitFields = "Consecutive";
-          AlignConsecutiveDeclarations = "Consecutive";
-          AlignConsecutiveMacros = "Consecutive";
-          AlignEscapedNewlines = "Right";
-          AlignOperands = "Align";
-          AlignTrailingComments = false;
-          AllowAllArgumentsOnNextLine = false;
-          AllowAllConstructorInitializersOnNextLine = true;
-          AllowAllParametersOfDeclarationOnNextLine = true;
-          AllowShortBlocksOnASingleLine = "Never";
-          AllowShortCaseLabelsOnASingleLine = false;
-          AllowShortEnumsOnASingleLine = false;
-          AllowShortFunctionsOnASingleLine = "None";
-          AllowShortIfStatementsOnASingleLine = "Never";
-          AllowShortLambdasOnASingleLine = "Inline";
-          AllowShortLoopsOnASingleLine = false;
-          AlwaysBreakAfterDefinitionReturnType = "All";
-          AlwaysBreakAfterReturnType = "AllDefinitions";
-          AlwaysBreakBeforeMultilineStrings = false;
-          AlwaysBreakTemplateDeclarations = "Yes";
-          BinPackArguments = false;
-          BinPackParameters = false;
-          BreakBeforeBinaryOperators = "None";
-          BreakBeforeBraces = "Allman";
-          BreakBeforeTernaryOperators = true;
-          BreakConstructorInitializers = "BeforeComma";
-          BreakInheritanceList = "BeforeComma";
-          BreakStringLiterals = true;
-          ColumnLimit = 80;
-          CommentPragmas = "^ IWYU pragma:";
-          CompactNamespaces = false;
-          ConstructorInitializerAllOnOneLineOrOnePerLine = false;
-          ConstructorInitializerIndentWidth = 4;
-          ContinuationIndentWidth = 4;
-          Cpp11BracedListStyle = true;
-          DeriveLineEnding = false;
-          DerivePointerAlignment = false;
-          DisableFormat = false;
-          ExperimentalAutoDetectBinPacking = false;
-          FixNamespaceComments = true;
-          IncludeBlocks = "Regroup";
-          IndentCaseBlocks = false;
-          IndentCaseLabels = false;
-          IndentExternBlock = "NoIndent";
-          IndentGotoLabels = false;
-          IndentPPDirectives = "None";
-          IndentWidth = 4;
-          IndentWrappedFunctionNames = false;
-          KeepEmptyLinesAtTheStartOfBlocks = false;
-          Language = "Cpp";
-          MaxEmptyLinesToKeep = 1;
-          NamespaceIndentation = "None";
-          PointerAlignment = "Left";
-          ReflowComments = false;
-          SortIncludes = "CaseSensitive";
-          SortUsingDeclarations = true;
-          SpaceAfterCStyleCast = false;
-          SpaceAfterLogicalNot = false;
-          SpaceAfterTemplateKeyword = true;
-          SpaceBeforeAssignmentOperators = true;
-          SpaceBeforeCpp11BracedList = false;
-          SpaceBeforeCtorInitializerColon = true;
-          SpaceBeforeInheritanceColon = true;
-          SpaceBeforeParens = "ControlStatements";
-          SpaceBeforeRangeBasedForLoopColon = true;
-          SpaceInEmptyParentheses = false;
-          SpacesBeforeTrailingComments = 1;
-          SpacesInAngles = false;
-          SpacesInCStyleCastParentheses = false;
-          SpacesInContainerLiterals = false;
-          SpacesInParentheses = false;
-          SpacesInSquareBrackets = false;
-          Standard = "Latest";
-          TabWidth = 4;
-          UseTab = "Always";
+        "${config.dirs.data}/stack/global-project/stack.yaml".text = generators.toYAML {} {
+          packages = [];
+          resolver = "lts-19.28";
         };
+      };
 
-        ".gdbinit".text = ''
-          set confirm off
-          set verbose off
-          set editing off
-
-          set history expansion on
-
-          set height 0
-          set width  0
-
-          handle SIGALRM nostop print nopass
-          handle SIGBUS    stop print nopass
-          handle SIGPIPE nostop print nopass
-          handle SIGSEGV   stop print nopass
-
-          set print address on
-          set print elements 0
-          set print object on
-          set print pretty on
-          set print repeats 0
-          set print static-members on
-          set print vtbl on
-
-          set output-radix 10
+      sessionVariables = with config.dirs; rec {
+        ANDROID_HOME = "${data}/android";
 
-          set demangle-style gnu-v3
+        CABAL_DIR = "${data}/cabal";
+        CABAL_CONFIG = pkgs.writeText "cabal-config" ''
+          repository hackage.haskell.org
+            url: https://hackage.haskell.org/
+            secure: True
 
-          set disassembly-flavor intel
+          jobs: $ncpus
 
-          alias iv=info variables
+          remote-repo-cache: ${CABAL_DIR}/packages
 
-          alias da=disassemble
+          world-file: ${CABAL_DIR}/world
 
-          define fs
-              finish
-              step
-          end
+          logs-dir: ${CABAL_DIR}/logs
+          build-summary: ${CABAL_DIR}/logs/build.log
 
-          define btc
-              backtrace
-              continue
-          end
+          installdir: ${CABAL_DIR}/bin
+          extra-prog-path: ${CABAL_DIR}/bin
         '';
-      };
 
-      sessionVariables = with config.dirs; {
-        ANDROID_HOME = "${data}/android";
-        CABAL_CONFIG = "${data}/cabal/config";
-        CABAL_DIR = "${data}/cabal";
+        STACK_ROOT = "${data}/stack";
+
         CARGO_HOME = "${data}/cargo";
+
         GOPATH = "${data}/go";
+
         PYTHONSTARTUP = ./pystartup.py;
-        STACK_ROOT = "${data}/stack";
       };
 
       packages = with pkgs; [
diff --git a/modules/nixfiles/profiles/dev/editorconfig.ini b/modules/nixfiles/profiles/dev/editorconfig.ini
new file mode 100644
index 0000000..17b0317
--- /dev/null
+++ b/modules/nixfiles/profiles/dev/editorconfig.ini
@@ -0,0 +1,83 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+max_line_length = 80
+trim_trailing_whitespace = true
+
+[*.nix]
+indent_size = 2
+indent_style = space
+
+[*.{S,s,asm}]
+indent_size = 4
+indent_style = tab
+
+[*.{C,H,c,c++,cc,cpp,cxx,h,h++,hh,hpp,hxx}]
+indent_size = 4
+indent_style = tab
+
+[*.{cl,clj,el,l,lisp,lsp,rkt,scm,ss}]
+indent_size = 2
+indent_style = space
+
+[*.go]
+indent_size = 4
+indent_style = tab
+
+[*.{py,pyx}]
+indent_size = 4
+indent_style = space
+
+[*.{hs,lhs}]
+indent_size = 2
+indent_style = space
+
+[*.{html,xhtml,xml}]
+indent_size = 4
+indent_style = tab
+
+[*.json]
+indent_size = 2
+indent_style = space
+
+[*.{yaml,yml}]
+indent_size = 2
+indent_style = space
+
+[*.{toml,tml}]
+indent_size = 4
+indent_style = space
+
+[*.{py,pyx}]
+indent_size = 4
+indent_style = space
+max_line_length = 72
+
+[*.zig]
+indent_size = 4
+indent_style = tab
+
+[configure.ac]
+indent_size = 4
+indent_style = tab
+
+[{Makefile*,*.mk}]
+indent_size = 4
+indent_style = tab
+
+[{CMakeLists.txt,*.cmake}]
+indent_size = 8
+indent_style = tab
+
+[*.tex]
+indent_size = 4
+indent_style = tab
+
+[*.{md,adoc,rtf,txt}]
+indent_size = 4
+indent_style = tab
diff --git a/modules/nixfiles/profiles/dev/gdbinit b/modules/nixfiles/profiles/dev/gdbinit
new file mode 100644
index 0000000..e266236
--- /dev/null
+++ b/modules/nixfiles/profiles/dev/gdbinit
@@ -0,0 +1,41 @@
+set confirm off
+set verbose off
+set editing off
+
+set history expansion on
+
+set height 0
+set width  0
+
+handle SIGALRM nostop print nopass
+handle SIGBUS    stop print nopass
+handle SIGPIPE nostop print nopass
+handle SIGSEGV   stop print nopass
+
+set print address on
+set print elements 0
+set print object on
+set print pretty on
+set print repeats 0
+set print static-members on
+set print vtbl on
+
+set output-radix 10
+
+set demangle-style gnu-v3
+
+set disassembly-flavor intel
+
+alias iv=info variables
+
+alias da=disassemble
+
+define fs
+    finish
+    step
+end
+
+define btc
+    backtrace
+    continue
+end
diff --git a/modules/nixfiles/profiles/headless.nix b/modules/nixfiles/profiles/headless.nix
index 6ac91c1..369f457 100644
--- a/modules/nixfiles/profiles/headless.nix
+++ b/modules/nixfiles/profiles/headless.nix
@@ -44,13 +44,6 @@ in {
       };
     };
 
-    i18n = {
-      # TODO Convert everything including PostgreSQL databases to the "en_US"
-      # locale or probably even the "C" one.
-      defaultLocale = mkForce "C";
-      supportedLocales = mkForce ["en_US.UTF-8/UTF-8" "en_GB.UTF-8/UTF-8"];
-    };
-
     services.udisks2.enable = false;
 
     xdg.sounds.enable = false;
diff --git a/modules/nixfiles/qutebrowser.nix b/modules/nixfiles/qutebrowser.nix
index 186623a..76f9f98 100644
--- a/modules/nixfiles/qutebrowser.nix
+++ b/modules/nixfiles/qutebrowser.nix
@@ -10,534 +10,527 @@ in {
   options.nixfiles.modules.qutebrowser.enable = mkEnableOption "Qutebrowser";
 
   config = mkIf cfg.enable {
-    hm = {
-      # home.sessionVariables.BROWSER = mkOverride 400 "qutebrowser";
+    hm.programs.qutebrowser = with config.nixfiles.modules; {
+      enable = true;
 
-      programs.qutebrowser = with config.nixfiles.modules; {
-        enable = true;
-
-        package = pkgs.qutebrowser.override {
-          withMediaPlayback = false;
-          withPdfReader = false;
-        };
+      package = pkgs.qutebrowser.override {
+        withMediaPlayback = false;
+        withPdfReader = false;
+      };
 
-        keyBindings.normal = mkIf mpv.enable {
-          "z" = let
-            mpv = "${config.hm.programs.mpv.package}/bin/mpv";
-          in "hint links spawn --detach ${mpv} {hint-url}";
-        };
+      keyBindings.normal = mkIf mpv.enable {
+        "z" = let
+          mpv = "${config.hm.programs.mpv.package}/bin/mpv";
+        in "hint links spawn --detach ${mpv} {hint-url}";
+      };
 
-        searchEngines = rec {
-          aliexpress = "https://www.aliexpress.com/wholesale?SearchText={}";
-          ansible = "https://galaxy.ansible.com/search?keywords={}";
-          arch = "https://wiki.archlinux.org/?search={}";
-          crates = "https://crates.io/search?q={}";
-          crawl = "http://crawl.chaosforge.org/index.php?search={}";
-          discogs = "https://www.discogs.com/search/?q={}";
-          dockerdocs = "https://docs.docker.com/search/?q={}";
-          dockerhub = "https://hub.docker.com/search?q={}";
-          doublegis = "https://2gis.ru/search/{}";
-          duckduckgo = "https://duckduckgo.com/?q={}'";
-          dwarffortress = "https://dwarffortresswiki.org/index.php?search={}";
-          ebay = "https://www.ebay.com/sch/i.html?_nkw={}";
-          ecosia = "https://www.ecosia.org/search?q={}";
-          factorio = "https://wiki.factorio.com/index.php?search={}";
-          genius = "https://genius.com/search?q={}";
-          github = "https://github.com/search?q={}";
-          godocs = "https://godocs.io/?q={}";
-          gogdb = "https://www.gogdb.org/products?search={}";
-          google = "https://www.google.com/search?q={}";
-          google-images = "https://www.google.com/search?q={}&tbm=isch";
-          gopkgs = "https://pkg.go.dev/search?q={}";
-          habr = "https://habr.com/ru/search/?q={}";
-          hackage = "https://hackage.haskell.org/packages/search?terms={}";
-          hackernews = "https://hn.algolia.com/?q={}";
-          headhunter = "https://hh.ru/search/vacancy?st=searchVacancy&text={}";
-          hoogle = "https://hoogle.haskell.org/?hoogle={}";
-          jisho = "https://jisho.org/search/{}";
-          kotobank = "https://kotobank.jp/gs/?q={}";
-          kubernetes = "https://kubernetes.io/search/?q={}";
-          lastfm = "https://www.last.fm/search?q={}";
-          lobsters = "https://lobste.rs/search?q=test{}";
-          mdn = "https://developer.mozilla.org/en-US/search?q={}";
-          melpa = "https://melpa.org/#/?q={}";
-          moddb = "https://www.moddb.com/search?q={}";
-          musicbrainz = "https://musicbrainz.org/search?query={}";
-          nix-issues = "https://github.com/NixOS/nix/issues?q={}";
-          nix-prs = "https://github.com/NixOS/nix/pulls?q={}";
-          nixos-flakes = "https://search.nixos.org/flakes?query={}";
-          nixos-options = "https://search.nixos.org/options?query={}";
-          nixos-packages = "https://search.nixos.org/packages?query={}";
-          nixos-wiki = "https://nixos.wiki/index.php?search={}";
-          nixpkgs-issues = "https://github.com/NixOS/nixpkgs/issues?q={}";
-          nixpkgs-prs = "https://github.com/NixOS/nixpkgs/pulls?q={}";
-          openstreetmap = "https://www.openstreetmap.org/search?query={}";
-          ozon = "https://www.ozon.ru/search/?text={}";
-          protondb = "https://www.protondb.com/search?q={}";
-          pypi = "https://pypi.org/search/?q={}";
-          pythondocs = "https://docs.python.org/3/search.html?q={}";
-          rateyourmusic = "https://rateyourmusic.com/search?searchterm={}";
-          riichi = "https://riichi.wiki/index.php?search={}";
-          rustdoc = "https://doc.rust-lang.org/std/?search={}";
-          searx = "https://searx.tiekoetter.com/search?q={}";
-          slashdot = "https://slashdot.org/index2.pl?fhfilter={}";
-          sourcehut = "https://sr.ht/projects?search={}";
-          steam = "https://store.steampowered.com/search/?term={}";
-          steamdb = "https://steamdb.info/search/?a=app&q={}";
-          ubuntu = "https://wiki.ubuntu.com/Home?action=fullsearch&value={}";
-          wikipedia-en = "https://en.wikipedia.org/w/index.php?search={}";
-          wikipedia-ru = "https://ru.wikipedia.org/w/index.php?search={}";
-          wikipedia-ja = "https://ja.wikipedia.org/w/index.php?search={}";
-          wolphramalpha = "https://www.wolframalpha.com/input/?i={}";
-          yahoo = "https://yahoo.com/search/?text={}";
-          yahoo-images = "https://yahoo.com/images/search?text={}";
-          yahoo-market = "https://market.yahoo.com/search?text={}";
-          youtube = "https://yewtu.be/search?q={}";
-
-          aw = arch;
-          d = duckduckgo;
-          do = dockerhub;
-          docker = dockerhub;
-          dod = dockerdocs;
-          g = google;
-          gh = github;
-          h = hoogle;
-          k = kubernetes;
-          mb = musicbrainz;
-          n = nixos-options;
-          nw = nixos-wiki;
-          py = pypi;
-          pyd = pythondocs;
-          rym = rateyourmusic;
-          s = searx;
-          sh = sourcehut;
-          sr = sourcehut;
-          w = wikipedia-en;
-          wen = wikipedia-en;
-          wja = wikipedia-ja;
-          wru = wikipedia-ru;
-          y = yahoo;
-          yt = youtube;
-        };
+      searchEngines = rec {
+        aliexpress = "https://www.aliexpress.com/wholesale?SearchText={}";
+        ansible = "https://galaxy.ansible.com/search?keywords={}";
+        arch = "https://wiki.archlinux.org/?search={}";
+        crates = "https://crates.io/search?q={}";
+        crawl = "http://crawl.chaosforge.org/index.php?search={}";
+        discogs = "https://www.discogs.com/search/?q={}";
+        dockerdocs = "https://docs.docker.com/search/?q={}";
+        dockerhub = "https://hub.docker.com/search?q={}";
+        doublegis = "https://2gis.ru/search/{}";
+        duckduckgo = "https://duckduckgo.com/?q={}'";
+        dwarffortress = "https://dwarffortresswiki.org/index.php?search={}";
+        ebay = "https://www.ebay.com/sch/i.html?_nkw={}";
+        ecosia = "https://www.ecosia.org/search?q={}";
+        factorio = "https://wiki.factorio.com/index.php?search={}";
+        genius = "https://genius.com/search?q={}";
+        github = "https://github.com/search?q={}";
+        godocs = "https://godocs.io/?q={}";
+        gogdb = "https://www.gogdb.org/products?search={}";
+        google = "https://www.google.com/search?q={}";
+        google-images = "https://www.google.com/search?q={}&tbm=isch";
+        gopkgs = "https://pkg.go.dev/search?q={}";
+        habr = "https://habr.com/ru/search/?q={}";
+        hackage = "https://hackage.haskell.org/packages/search?terms={}";
+        hackernews = "https://hn.algolia.com/?q={}";
+        headhunter = "https://hh.ru/search/vacancy?st=searchVacancy&text={}";
+        hoogle = "https://hoogle.haskell.org/?hoogle={}";
+        jisho = "https://jisho.org/search/{}";
+        kotobank = "https://kotobank.jp/gs/?q={}";
+        kubernetes = "https://kubernetes.io/search/?q={}";
+        lastfm = "https://www.last.fm/search?q={}";
+        lobsters = "https://lobste.rs/search?q=test{}";
+        mdn = "https://developer.mozilla.org/en-US/search?q={}";
+        melpa = "https://melpa.org/#/?q={}";
+        moddb = "https://www.moddb.com/search?q={}";
+        musicbrainz = "https://musicbrainz.org/search?query={}";
+        nix-issues = "https://github.com/NixOS/nix/issues?q={}";
+        nix-prs = "https://github.com/NixOS/nix/pulls?q={}";
+        nixos-flakes = "https://search.nixos.org/flakes?query={}";
+        nixos-options = "https://search.nixos.org/options?query={}";
+        nixos-packages = "https://search.nixos.org/packages?query={}";
+        nixos-wiki = "https://nixos.wiki/index.php?search={}";
+        nixpkgs-issues = "https://github.com/NixOS/nixpkgs/issues?q={}";
+        nixpkgs-prs = "https://github.com/NixOS/nixpkgs/pulls?q={}";
+        openstreetmap = "https://www.openstreetmap.org/search?query={}";
+        ozon = "https://www.ozon.ru/search/?text={}";
+        protondb = "https://www.protondb.com/search?q={}";
+        pypi = "https://pypi.org/search/?q={}";
+        pythondocs = "https://docs.python.org/3/search.html?q={}";
+        rateyourmusic = "https://rateyourmusic.com/search?searchterm={}";
+        riichi = "https://riichi.wiki/index.php?search={}";
+        rustdoc = "https://doc.rust-lang.org/std/?search={}";
+        searx = "https://searx.tiekoetter.com/search?q={}";
+        slashdot = "https://slashdot.org/index2.pl?fhfilter={}";
+        sourcehut = "https://sr.ht/projects?search={}";
+        steam = "https://store.steampowered.com/search/?term={}";
+        steamdb = "https://steamdb.info/search/?a=app&q={}";
+        ubuntu = "https://wiki.ubuntu.com/Home?action=fullsearch&value={}";
+        wikipedia-en = "https://en.wikipedia.org/w/index.php?search={}";
+        wikipedia-ru = "https://ru.wikipedia.org/w/index.php?search={}";
+        wikipedia-ja = "https://ja.wikipedia.org/w/index.php?search={}";
+        wolphramalpha = "https://www.wolframalpha.com/input/?i={}";
+        yahoo = "https://yahoo.com/search/?text={}";
+        yahoo-images = "https://yahoo.com/images/search?text={}";
+        yahoo-market = "https://market.yahoo.com/search?text={}";
+        youtube = "https://yewtu.be/search?q={}";
+
+        aw = arch;
+        d = duckduckgo;
+        do = dockerhub;
+        docker = dockerhub;
+        dod = dockerdocs;
+        g = google;
+        gh = github;
+        h = hoogle;
+        k = kubernetes;
+        mb = musicbrainz;
+        n = nixos-options;
+        nw = nixos-wiki;
+        py = pypi;
+        pyd = pythondocs;
+        rym = rateyourmusic;
+        s = searx;
+        sh = sourcehut;
+        sr = sourcehut;
+        w = wikipedia-en;
+        wen = wikipedia-en;
+        wja = wikipedia-ja;
+        wru = wikipedia-ru;
+        y = yahoo;
+        yt = youtube;
+      };
 
-        settings = {
-          changelog_after_upgrade = "never";
-
-          content = {
-            autoplay = false;
-            cookies.accept = "all";
-            default_encoding = "utf-8";
-            desktop_capture = "ask";
-            dns_prefetch = false;
-            geolocation = false;
-            headers.do_not_track = true;
-            javascript.enabled = true;
-            prefers_reduced_motion = true;
-            webgl = true;
-
-            blocking = {
-              enabled = true;
-              method = "adblock";
-              adblock.lists = [
-                "https://easylist.to/easylist/easylist.txt"
-                "https://easylist.to/easylist/easyprivacy.txt"
-                "https://easylist.to/easylist/fanboy-social.txt"
-                "https://secure.fanboy.co.nz/fanboy-annoyance.txt"
-                "https://secure.fanboy.co.nz/fanboy-cookiemonster.txt"
-              ];
-            };
+      settings = {
+        changelog_after_upgrade = "never";
+
+        content = {
+          autoplay = false;
+          cookies.accept = "all";
+          default_encoding = "utf-8";
+          desktop_capture = "ask";
+          dns_prefetch = false;
+          geolocation = false;
+          headers.do_not_track = true;
+          javascript.enabled = true;
+          prefers_reduced_motion = true;
+          webgl = true;
+
+          blocking = {
+            enabled = true;
+            method = "adblock";
+            adblock.lists = [
+              "https://easylist.to/easylist/easylist.txt"
+              "https://easylist.to/easylist/easyprivacy.txt"
+              "https://easylist.to/easylist/fanboy-social.txt"
+              "https://secure.fanboy.co.nz/fanboy-annoyance.txt"
+              "https://secure.fanboy.co.nz/fanboy-cookiemonster.txt"
+            ];
           };
+        };
 
-          completion = {
-            height = "50%";
-            show = "auto";
-            shrink = true;
-            timestamp_format = "%y-%m-%d";
-            min_chars = 3;
-            open_categories = ["bookmarks" "quickmarks" "history"];
-
-            scrollbar = {
-              width = 0;
-              padding = 0;
-            };
+        completion = {
+          height = "50%";
+          show = "auto";
+          shrink = true;
+          timestamp_format = "%y-%m-%d";
+          min_chars = 3;
+          open_categories = ["bookmarks" "quickmarks" "history"];
+
+          scrollbar = {
+            width = 0;
+            padding = 0;
           };
+        };
 
-          downloads = {
-            location = {
-              directory = config.userDirs.download;
-              prompt = true;
-            };
-            remove_finished = 0;
-          };
-
-          editor.command = [
-            (
-              if alacritty.enable
-              then "${pkgs.alacritty}/bin/alacritty"
-              else "${pkgs.xterm}/bin/xterm"
-            )
-            "-e"
-            "${config.programs.vim.package}/bin/vim"
-            "-f"
-            "{}"
-          ];
-
-          hints = {
-            auto_follow = "unique-match";
-            auto_follow_timeout = 0;
-            border = "0px";
-            min_chars = 1;
-            scatter = false;
-            uppercase = false;
+        downloads = {
+          location = {
+            directory = config.userDirs.download;
+            prompt = true;
           };
+          remove_finished = 0;
+        };
 
-          hints.radius = 0;
-          keyhint.radius = 0;
-          prompt.radius = 0;
+        editor.command = [
+          (
+            if alacritty.enable
+            then "${pkgs.alacritty}/bin/alacritty"
+            else "${pkgs.xterm}/bin/xterm"
+          )
+          "-e"
+          "${config.programs.vim.package}/bin/vim"
+          "-f"
+          "{}"
+        ];
+
+        hints = {
+          auto_follow = "unique-match";
+          auto_follow_timeout = 0;
+          border = "0px";
+          min_chars = 1;
+          scatter = false;
+          uppercase = false;
+        };
 
-          scrolling = {
-            bar = "never";
-            smooth = false;
-          };
+        hints.radius = 0;
+        keyhint.radius = 0;
+        prompt.radius = 0;
 
-          spellcheck.languages = ["en-GB" "en-US" "ru-RU"];
+        scrolling = {
+          bar = "never";
+          smooth = false;
+        };
 
-          statusbar.position = "bottom";
+        spellcheck.languages = ["en-US" "en-GB" "ru-RU"];
 
-          tabs = {
-            position = "top";
+        statusbar.position = "bottom";
 
-            title = {
-              alignment = "left";
-              format = "{audio}{index} : {current_title}";
-              format_pinned = "{audio}{index}";
-            };
+        tabs = {
+          position = "top";
 
-            min_width = -1;
-            max_width = -1;
+          title = {
+            alignment = "left";
+            format = "{audio}{index} : {current_title}";
+            format_pinned = "{audio}{index}";
+          };
 
-            indicator.width = 0;
+          min_width = -1;
+          max_width = -1;
 
-            pinned = {
-              shrink = true;
-              frozen = false;
-            };
+          indicator.width = 0;
 
-            close_mouse_button = "middle";
-            mousewheel_switching = false;
+          pinned = {
+            shrink = true;
+            frozen = false;
+          };
 
-            background = true;
-            select_on_remove = "next";
-            new_position = {
-              related = "next";
-              unrelated = "last";
-            };
+          close_mouse_button = "middle";
+          mousewheel_switching = false;
 
-            favicons = {
-              show = "pinned";
-              scale = 0.75;
-            };
+          background = true;
+          select_on_remove = "next";
+          new_position = {
+            related = "next";
+            unrelated = "last";
           };
 
-          url = rec {
-            default_page = "about:blank";
-            start_pages = [default_page];
+          favicons = {
+            show = "pinned";
+            scale = 0.75;
           };
+        };
 
-          window = {
-            hide_decoration = false;
-            title_format = "{perc}{current_title}{title_sep}qutebrowser";
-          };
+        url = rec {
+          default_page = "about:blank";
+          start_pages = [default_page];
+        };
+
+        window = {
+          hide_decoration = false;
+          title_format = "{perc}{current_title}{title_sep}qutebrowser";
+        };
 
-          colors = with config.colourScheme; {
-            completion = rec {
+        colors = with config.colourScheme; {
+          completion = rec {
+            fg = white;
+            match.fg = red;
+            odd.bg = black;
+            even.bg = odd.bg;
+            category = {
               fg = white;
-              match.fg = red;
-              odd.bg = black;
-              even.bg = odd.bg;
-              category = {
-                fg = white;
-                bg = black;
-                border = {
-                  top = black;
-                  bottom = black;
-                };
-              };
-              item.selected = {
-                fg = black;
-                bg = white;
-                border = {
-                  top = white;
-                  bottom = white;
-                };
-              };
-              scrollbar = {
-                fg = white;
-                bg = black;
+              bg = black;
+              border = {
+                top = black;
+                bottom = black;
               };
             };
-            contextmenu = {
-              menu = {
-                fg = white;
-                bg = black;
-              };
-              selected = {
-                fg = black;
-                bg = white;
-              };
-              disabled = {
-                fg = brightBlack;
-                bg = black;
+            item.selected = {
+              fg = black;
+              bg = white;
+              border = {
+                top = white;
+                bottom = white;
               };
             };
-            downloads = {
-              bar.bg = black;
-              start = {
-                fg = green;
-                bg = black;
-              };
-              stop = {
-                fg = yellow;
-                bg = black;
-              };
-              error = {
-                fg = red;
-                bg = black;
-              };
-              system = {
-                fg = "none";
-                bg = "none";
-              };
-            };
-            hints = {
+            scrollbar = {
               fg = white;
-              match.fg = red;
               bg = black;
             };
-            keyhint = {
+          };
+          contextmenu = {
+            menu = {
               fg = white;
-              suffix.fg = red;
               bg = black;
             };
-            messages = {
-              error = rec {
-                bg = black;
-                fg = red;
-                border = bg;
-              };
-              info = rec {
-                fg = blue;
-                bg = black;
-                border = bg;
-              };
-              warning = rec {
-                fg = yellow;
-                bg = black;
-                border = bg;
-              };
+            selected = {
+              fg = black;
+              bg = white;
             };
-            prompts = rec {
-              fg = white;
+            disabled = {
+              fg = brightBlack;
               bg = black;
-              selected = {
-                fg = black;
-                bg = white;
-              };
+            };
+          };
+          downloads = {
+            bar.bg = black;
+            start = {
+              fg = green;
+              bg = black;
+            };
+            stop = {
+              fg = yellow;
+              bg = black;
+            };
+            error = {
+              fg = red;
+              bg = black;
+            };
+            system = {
+              fg = "none";
+              bg = "none";
+            };
+          };
+          hints = {
+            fg = white;
+            match.fg = red;
+            bg = black;
+          };
+          keyhint = {
+            fg = white;
+            suffix.fg = red;
+            bg = black;
+          };
+          messages = {
+            error = rec {
+              bg = black;
+              fg = red;
               border = bg;
             };
-            statusbar = {
-              normal = {
-                bg = black;
-                fg = white;
-              };
-              command = {
-                bg = black;
-                fg = white;
-              };
-              insert = {
-                bg = green;
-                fg = black;
-              };
-              passthrough = {
-                bg = blue;
-                fg = black;
+            info = rec {
+              fg = blue;
+              bg = black;
+              border = bg;
+            };
+            warning = rec {
+              fg = yellow;
+              bg = black;
+              border = bg;
+            };
+          };
+          prompts = rec {
+            fg = white;
+            bg = black;
+            selected = {
+              fg = black;
+              bg = white;
+            };
+            border = bg;
+          };
+          statusbar = {
+            normal = {
+              bg = black;
+              fg = white;
+            };
+            command = {
+              bg = black;
+              fg = white;
+            };
+            insert = {
+              bg = green;
+              fg = black;
+            };
+            passthrough = {
+              bg = blue;
+              fg = black;
+            };
+            private = {
+              bg = magenta;
+              fg = black;
+            };
+            url = {
+              fg = blue;
+              hover.fg = brightBlue;
+              success = {
+                http.fg = brightGreen;
+                https.fg = brightGreen;
               };
-              private = {
-                bg = magenta;
+              warn.fg = brightYellow;
+              error.fg = brightRed;
+            };
+          };
+          tabs = rec {
+            bar.bg = black;
+            even = {
+              bg = black;
+              fg = white;
+            };
+            odd = with even; {inherit bg fg;};
+            selected = rec {
+              even = {
+                bg = white;
                 fg = black;
               };
-              url = {
-                fg = blue;
-                hover.fg = brightBlue;
-                success = {
-                  http.fg = brightGreen;
-                  https.fg = brightGreen;
-                };
-                warn.fg = brightYellow;
-                error.fg = brightRed;
-              };
+              odd = with even; {inherit bg fg;};
             };
-            tabs = rec {
-              bar.bg = black;
+            pinned = rec {
               even = {
-                bg = black;
-                fg = white;
+                bg = brightBlack;
+                fg = brightWhite;
               };
               odd = with even; {inherit bg fg;};
-              selected = rec {
-                even = {
-                  bg = white;
-                  fg = black;
-                };
-                odd = with even; {inherit bg fg;};
-              };
-              pinned = rec {
-                even = {
-                  bg = brightBlack;
-                  fg = brightWhite;
-                };
-                odd = with even; {inherit bg fg;};
+            };
+            indicator = {
+              start = green;
+              stop = yellow;
+              error = red;
+              system = "none";
+            };
+          };
+          webpage = {
+            bg = "white";
+            darkmode = {
+              enabled = false;
+              algorithm = "lightness-cielab";
+              contrast = 0.0;
+              grayscale = {
+                all = false;
+                images = 0.0;
               };
-              indicator = {
-                start = green;
-                stop = yellow;
-                error = red;
-                system = "none";
+              policy = {
+                images = "smart";
+                page = "smart";
               };
-            };
-            webpage = {
-              bg = "white";
-              darkmode = {
-                enabled = false;
-                algorithm = "lightness-cielab";
-                contrast = 0.0;
-                grayscale = {
-                  all = false;
-                  images = 0.0;
-                };
-                policy = {
-                  images = "smart";
-                  page = "smart";
-                };
-                threshold = {
-                  background = 0;
-                  text = 256;
-                };
+              threshold = {
+                background = 0;
+                text = 256;
               };
-              preferred_color_scheme = "auto";
             };
+            preferred_color_scheme = "auto";
           };
+        };
 
-          fonts =
-            (with config.fontScheme.monospaceFont; {
-              default_family = family;
-              default_size = (toString size) + "pt";
-            })
-            // {
-              web = with config.fontScheme; {
-                family = rec {
-                  standard = sans_serif;
-                  fixed = monospaceFont.family;
-                  serif = serifFont.family;
-                  sans_serif = sansSerifFont.family;
-                  cursive = null;
-                  fantasy = null;
-                };
-                size = rec {
-                  default = sansSerifFont.size;
-                  default_fixed = monospaceFont.size;
-                  minimum = 0;
-                  minimum_logical = default / 2;
-                };
+        fonts =
+          (with config.fontScheme.monospaceFont; {
+            default_family = family;
+            default_size = (toString size) + "pt";
+          })
+          // {
+            web = with config.fontScheme; {
+              family = rec {
+                standard = sans_serif;
+                fixed = monospaceFont.family;
+                serif = serifFont.family;
+                sans_serif = sansSerifFont.family;
+                cursive = null;
+                fantasy = null;
               };
-            }
-            // mapListToAttrs (_: "default_size default_family") [
-              "completion.category"
-              "completion.entry"
-              "contextmenu"
-              "debug_console"
-              "downloads"
-              "hints"
-              "keyhint"
-              "messages.error"
-              "messages.info"
-              "messages.warning"
-              "prompts"
-              "statusbar"
-            ];
+              size = rec {
+                default = sansSerifFont.size;
+                default_fixed = monospaceFont.size;
+                minimum = 0;
+                minimum_logical = default / 2;
+              };
+            };
+          }
+          // mapListToAttrs (_: "default_size default_family") [
+            "completion.category"
+            "completion.entry"
+            "contextmenu"
+            "debug_console"
+            "downloads"
+            "hints"
+            "keyhint"
+            "messages.error"
+            "messages.info"
+            "messages.warning"
+            "prompts"
+            "statusbar"
+          ];
 
-          qt = mkIf kde.enable {
-            force_platform = null;
-            force_platformtheme = "KDE";
-          };
+        qt = mkIf kde.enable {
+          force_platform = null;
+          force_platformtheme = "KDE";
         };
+      };
 
-        extraConfig =
-          (let
-            mkPaddingDictionary = {
-              name,
-              bottom,
-              left,
-              right,
-              top,
-            }: let
-              n = "c.${name}.padding";
-              b = "'bottom': ${toString bottom}";
-              l = "'left': ${toString left}";
-              r = "'right': ${toString right}";
-              t = "'top': ${toString top}";
-            in "${n} = {${b}, ${l}, ${r}, ${t}}";
-
-            final = map mkPaddingDictionary [
-              {
-                name = "hints";
-                bottom = 3;
-                left = 3;
-                right = 3;
-                top = 3;
-              }
-              {
-                name = "statusbar";
-                bottom = 1;
-                left = 0;
-                right = 3;
-                top = 1;
-              }
-              {
-                name = "tabs";
-                bottom = 1;
-                left = 6;
-                right = 6;
-                top = 1;
-              }
-            ];
-          in
-            concatStringsSep "\n" final + "\n")
-          + (let
-            allowSetting = setting: url: "config.set('content.${setting}', True, '${url}')";
-
-            allowMediaCaptureSetting = url: [
-              (allowSetting "desktop_capture" url)
-              (allowSetting "media.audio_video_capture" url)
-            ];
-            allowedMediaCapture = flatten (map allowMediaCaptureSetting [
-              "https://discord.com"
-              "https://meet.google.com"
-              "https://web.skype.com"
-            ]);
-
-            allowNotificationsSetting = allowSetting "notifications.enabled";
-            allowedNotifications = map allowNotificationsSetting [
-              "https://discord.com"
-              "https://web.skype.com"
-              "https://web.telegram.org"
-              "https://web.whatsapp.com"
-            ];
+      extraConfig =
+        (let
+          mkPaddingDictionary = {
+            name,
+            bottom,
+            left,
+            right,
+            top,
+          }: let
+            n = "c.${name}.padding";
+            b = "'bottom': ${toString bottom}";
+            l = "'left': ${toString left}";
+            r = "'right': ${toString right}";
+            t = "'top': ${toString top}";
+          in "${n} = {${b}, ${l}, ${r}, ${t}}";
+
+          final = map mkPaddingDictionary [
+            {
+              name = "hints";
+              bottom = 3;
+              left = 3;
+              right = 3;
+              top = 3;
+            }
+            {
+              name = "statusbar";
+              bottom = 1;
+              left = 0;
+              right = 3;
+              top = 1;
+            }
+            {
+              name = "tabs";
+              bottom = 1;
+              left = 6;
+              right = 6;
+              top = 1;
+            }
+          ];
+        in
+          concatStringsSep "\n" final + "\n")
+        + (let
+          allowSetting = setting: url: "config.set('content.${setting}', True, '${url}')";
+
+          allowMediaCaptureSetting = url: [
+            (allowSetting "desktop_capture" url)
+            (allowSetting "media.audio_video_capture" url)
+          ];
+          allowedMediaCapture = flatten (map allowMediaCaptureSetting [
+            "https://discord.com"
+            "https://web.telegram.org"
+          ]);
+
+          allowNotificationsSetting = allowSetting "notifications.enabled";
+          allowedNotifications = map allowNotificationsSetting [
+            "https://discord.com"
+            "https://web.telegram.org"
+          ];
 
-            final = allowedMediaCapture ++ allowedNotifications;
-          in
-            concatStringsSep "\n" final + "\n");
-      };
+          final = allowedMediaCapture ++ allowedNotifications;
+        in
+          concatStringsSep "\n" final + "\n");
     };
 
     services.psd.enable = true;
diff --git a/modules/nixfiles/rtorrent.nix b/modules/nixfiles/rtorrent.nix
index 9f28c61..834e36d 100644
--- a/modules/nixfiles/rtorrent.nix
+++ b/modules/nixfiles/rtorrent.nix
@@ -25,7 +25,7 @@ in {
     user = "rtorrent";
     group = "rtorrent";
     baseDir = "/var/lib/rtorrent";
-    rpcSocket = "/run/rtorrent/rpc.socket";
+    rpcSocket = "${baseDir}/rpc.socket";
   in
     mkIf cfg.enable (mkMerge [
       (let
@@ -40,12 +40,98 @@ in {
               seedDir = "${baseDir}/seed";
               sessionDir = "${baseDir}/session";
               logDir = "${baseDir}/log";
+              configFile = let
+                moveCompleted = let
+                  pkg = pkgs.writeShellApplication {
+                    name = "move-completed";
+                    runtimeInputs = with pkgs; [
+                      coreutils-full
+                      gnused
+                      findutils
+                    ];
+                    text = ''
+                      set -x
+
+                      leech_path="$1"
+                      seed_path="$2"
+                      # seed_path="$(echo "$2" | sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf '%b')"
+
+                      mkdir -pv "$seed_path"
+                      mv -fv "$leech_path" "$seed_path"
+                    '';
+                  };
+                in "${pkg}/bin/move-completed";
+              in
+                pkgs.writeText "rtorrent.rc" ''
+                  method.insert = cfg.leech,     private|const|string, (cat, "${leechDir}")
+                  method.insert = cfg.seed,      private|const|string, (cat, "${seedDir}")
+                  method.insert = cfg.session,   private|const|string, (cat, "${sessionDir}")
+                  method.insert = cfg.log,       private|const|string, (cat, "${logDir}")
+                  method.insert = cfg.rpcsocket, private|const|string, (cat, "${rpcSocket}")
+
+                  directory.default.set = (cat, (cfg.leech))
+                  session.path.set = (cat, (cfg.session))
+
+                  network.port_range.set = ${toString port}-${toString port}
+                  network.port_random.set = no
+
+                  dht.mode.set = disable
+                  protocol.pex.set = no
+
+                  trackers.use_udp.set = no
+
+                  protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
+
+                  pieces.memory.max.set = ${toString (pow 2 11)}M
+                  pieces.preload.type.set = 2
+
+                  network.xmlrpc.size_limit.set = ${toString (pow 2 17)}
+
+                  network.max_open_files.set   = ${toString (pow 2 10)}
+                  network.max_open_sockets.set = ${toString (pow 2 10)}
+
+                  network.http.max_open.set = ${toString (pow 2 8)}
+
+                  throttle.global_down.max_rate.set_kb = 0
+                  throttle.global_up.max_rate.set_kb   = 0
+
+                  encoding.add = UTF-8
+                  system.umask.set = 0027
+                  system.cwd.set = (directory.default)
+
+                  network.scgi.open_local = (cat, (cfg.rpcsocket))
+
+                  method.insert = d.move_completed, simple, "\
+                    d.directory.set=$argument.1=;\
+                    execute=${moveCompleted}, $argument.0=, $argument.1=;\
+                    d.save_full_session=\
+                  "
+                  method.insert = d.leech_path, simple, "\
+                    if=(d.is_multi_file),\
+                    (cat, (d.directory), /),\
+                    (cat, (d.directory), /, (d.name))\
+                  "
+                  method.insert = d.seed_path, simple, "\
+                    cat=$cfg.seed=, /, $d.custom1=\
+                  "
+                  method.set_key = event.download.finished, move_complete, "\
+                    d.move_completed=$d.leech_path=, $d.seed_path=\
+                  "
+
+                  log.open_file = "log", (cat, (cfg.log), "/", "default.log")
+                  log.add_output = "info", "log"
+                  log.execute = (cat, (cfg.log), "/", "execute.log")
+                '';
             in {
-              User = user;
-              Group = group;
-              Type = "simple";
+              Restart = "on-failure";
+              RestartSec = 3;
+
               KillMode = "process";
               KillSignal = "SIGHUP";
+
+              User = user;
+              Group = group;
+
               ExecStartPre = concatStringsSep " " [
                 "${pkgs.coreutils-full}/bin/mkdir -p"
                 leechDir
@@ -53,104 +139,44 @@ in {
                 sessionDir
                 logDir
               ];
-              ExecStart = let
-                configFile = let
-                  moveCompleted = let
-                    pkg = pkgs.writeShellApplication {
-                      name = "move-completed";
-                      runtimeInputs = with pkgs; [
-                        coreutils-full
-                        gnused
-                        findutils
-                      ];
-                      text = ''
-                        set -x
-
-                        leech_path="$1"
-                        seed_path="$2"
-                        # seed_path="$(echo "$2" | sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf '%b')"
-
-                        mkdir -p "$seed_path"
-                        mv -u "$leech_path" "$seed_path"
-                      '';
-                    };
-                  in "${pkg}/bin/move-completed";
-                in
-                  pkgs.writeText "rtorrent.rc" ''
-                    method.insert = cfg.leech,     private|const|string, (cat, "${leechDir}")
-                    method.insert = cfg.seed,      private|const|string, (cat, "${seedDir}")
-                    method.insert = cfg.session,   private|const|string, (cat, "${sessionDir}")
-                    method.insert = cfg.log,       private|const|string, (cat, "${logDir}")
-                    method.insert = cfg.rpcsocket, private|const|string, (cat, "${rpcSocket}")
-
-                    directory.default.set = (cat, (cfg.leech))
-                    session.path.set = (cat, (cfg.session))
-
-                    network.port_range.set = ${toString port}-${toString port}
-                    network.port_random.set = no
-
-                    dht.mode.set = disable
-                    protocol.pex.set = no
-
-                    trackers.use_udp.set = no
-
-                    protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
-
-                    pieces.memory.max.set = 2048M
-                    pieces.preload.type.set = 2
-
-                    network.max_open_files.set   = 1024
-                    network.max_open_sockets.set = 1024
-
-                    network.http.max_open.set = 128
-
-                    throttle.global_down.max_rate.set_kb = 0
-                    throttle.global_up.max_rate.set_kb   = 0
-
-                    encoding.add = UTF-8
-                    system.umask.set = 0027
-                    system.cwd.set = (directory.default)
-
-                    network.scgi.open_local = (cat, (cfg.rpcsocket))
-                    schedule = scgi_group, 0, 0, "\
-                      execute.nothrow=chown, \":${group}\", (cfg.rpcsocket)\
-                    "
-                    schedule = scgi_permission, 0, 0, "\
-                      execute.nothrow=chmod, \"g+w,o=\", (cfg.rpcsocket)\
-                    "
-
-                    method.insert = d.move_completed, simple, "\
-                      d.directory.set=$argument.1=;\
-                      execute=${moveCompleted}, $argument.0=, $argument.1=;\
-                      d.save_full_session=\
-                    "
-                    method.insert = d.leech_path, simple, "\
-                      if=(d.is_multi_file),\
-                      (cat, (d.directory), /),\
-                      (cat, (d.directory), /, (d.name))\
-                    "
-                    method.insert = d.seed_path, simple, "\
-                      cat=$cfg.seed=, /, $d.custom1=\
-                    "
-                    method.set_key = event.download.finished, move_complete, "\
-                      d.move_completed=$d.leech_path=, $d.seed_path=\
-                    "
-
-                    log.open_file = "log", (cat, (cfg.log), "/", "default.log")
-                    log.add_output = "debug", "log"
-                    log.execute = (cat, (cfg.log), "/", "execute.log")
-                  '';
-              in
-                concatStringsSep " " [
-                  "${pkgs.rtorrent}/bin/rtorrent"
-                  "-n"
-                  "-o system.daemon.set=true"
-                  "-o import=${configFile}"
-                ];
-              Restart = "on-failure";
-              RestartSec = 3;
+              ExecStart = concatStringsSep " " [
+                "${pkgs.rtorrent}/bin/rtorrent"
+                "-n"
+                "-o system.daemon.set=true"
+                "-o network.bind_address.set=0.0.0.0"
+                "-o import=${configFile}"
+              ];
+              ExecStop = concatStringsSep " " [
+                "${pkgs.coreutils-full}/bin/rm -rf"
+                rpcSocket
+              ];
+
               RuntimeDirectory = "rtorrent";
-              RuntimeDirectoryMode = 755;
+              RuntimeDirectoryMode = 0750;
+              UMask = 0027;
+              AmbientCapabilities = [""];
+              CapabilityBoundingSet = [""];
+              LockPersonality = true;
+              MemoryDenyWriteExecute = true;
+              NoNewPrivileges = true;
+              PrivateDevices = true;
+              PrivateTmp = true;
+              PrivateUsers = true;
+              ProtectClock = true;
+              ProtectControlGroups = true;
+              ProtectHome = true;
+              ProtectHostname = true;
+              ProtectKernelLogs = true;
+              ProtectKernelModules = true;
+              ProtectKernelTunables = true;
+              ProcSubset = "pid";
+              RemoveIPC = true;
+              RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
+              RestrictNamespaces = true;
+              RestrictRealtime = true;
+              RestrictSUIDSGID = true;
+              SystemCallArchitectures = "native";
+              SystemCallFilter = ["@system-service" "~@resources" "~@privileged"];
             };
             wantedBy = ["multi-user.target"];
           };
@@ -216,10 +242,12 @@ in {
             after = ["network.target" "rtorrent.service"];
             path = with pkgs; [mediainfo];
             serviceConfig = {
+              Restart = "on-failure";
+              RestartSec = 3;
+
               User = user;
               Group = group;
-              Type = "simple";
-              KillMode = "process";
+
               ExecStart = concatStringsSep " " [
                 "${pkg}/bin/flood"
                 "--allowedpath=${baseDir}"
@@ -231,8 +259,40 @@ in {
                 "--ssl=false"
                 "--auth=none"
               ];
-              Restart = "on-failure";
-              RestartSec = 3;
+
+              RuntimeDirectory = "rtorrent";
+              RuntimeDirectoryMode = 0750;
+              UMask = 0027;
+              AmbientCapabilities = [""];
+              CapabilityBoundingSet = [""];
+              LockPersonality = true;
+              NoNewPrivileges = true;
+              PrivateDevices = true;
+              PrivateTmp = true;
+              PrivateUsers = true;
+              ProtectClock = true;
+              ProtectControlGroups = true;
+              ProtectHome = true;
+              ProtectHostname = true;
+              ProtectKernelLogs = true;
+              ProtectKernelModules = true;
+              ProtectKernelTunables = true;
+              ProcSubset = "pid";
+              ProtectProc = "invisible";
+              RemoveIPC = true;
+              RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
+              RestrictNamespaces = true;
+              RestrictRealtime = true;
+              RestrictSUIDSGID = true;
+              SystemCallArchitectures = "native";
+              SystemCallFilter = [
+                "~@cpu-emulation"
+                "~@debug"
+                "~@mount"
+                "~@obsolete"
+                "~@privileged"
+                "~@resources"
+              ];
             };
             wantedBy = ["multi-user.target"];
           };
diff --git a/modules/nixfiles/soju.nix b/modules/nixfiles/soju.nix
index a7d30f7..14faf00 100644
--- a/modules/nixfiles/soju.nix
+++ b/modules/nixfiles/soju.nix
@@ -40,12 +40,21 @@ in {
     db = "soju";
   in
     mkIf cfg.enable {
+      nixfiles.modules.postgresql = {
+        enable = true;
+        extraPostStart = [
+          ''
+            $PSQL "${db}" -tAc 'GRANT ALL ON SCHEMA "public" TO "${db}"'
+          ''
+        ];
+      };
+
       services.postgresql = {
         ensureDatabases = [db];
         ensureUsers = [
           {
             name = db;
-            ensurePermissions."DATABASE \"${db}\"" = "ALL PRIVILEGES";
+            ensurePermissions."DATABASE \"${db}\"" = "ALL";
           }
         ];
       };
@@ -56,16 +65,17 @@ in {
         after = ["network-online.target" "postgresql.service"];
         serviceConfig = {
           ExecStart = let
+            # https://soju.im/doc/soju.1.html
             configFile = pkgs.writeText "soju.conf" ''
               listen ${cfg.protocol}://${cfg.address}:${toString cfg.port}
-              db postgres "${
+              db postgres ${
                 concatStringsSep " " [
                   "host=/run/postgresql"
                   "user=${db}"
                   "dbname=${db}"
                   "sslmode=disable"
                 ]
-              }"
+              }
               hostname ${cfg.domain}
               title ${cfg.domain}
             '';
diff --git a/modules/nixfiles/vaultwarden.nix b/modules/nixfiles/vaultwarden.nix
index dc8bb84..7d51667 100644
--- a/modules/nixfiles/vaultwarden.nix
+++ b/modules/nixfiles/vaultwarden.nix
@@ -17,105 +17,118 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
-    secrets.vaultwarden-environment = {
-      file = "${inputs.self}/secrets/vaultwarden-environment";
-      owner = "vaultwarden";
-      group = "vaultwarden";
-    };
+  config = let
+    db = "vaultwarden";
+  in
+    mkIf cfg.enable {
+      secrets.vaultwarden-environment = {
+        file = "${inputs.self}/secrets/vaultwarden-environment";
+        owner = "vaultwarden";
+        group = "vaultwarden";
+      };
 
-    nixfiles.modules = {
-      nginx = {
-        enable = true;
-        upstreams = with config.services.vaultwarden.config; {
-          vaultwarden_rocket.servers."${ROCKET_ADDRESS}:${toString ROCKET_PORT}" = {};
-          vaultwarden_websocket.servers."${WEBSOCKET_ADDRESS}:${toString WEBSOCKET_PORT}" = {};
-        };
-        virtualHosts.${cfg.domain} = {
-          locations."/" = {
-            proxyPass = "http://vaultwarden_rocket";
-            proxyWebsockets = true;
-          };
-          locations."/notifications/hub" = {
-            proxyPass = "http://vaultwarden_websocket";
-            proxyWebsockets = true;
+      nixfiles.modules = {
+        nginx = {
+          enable = true;
+          upstreams = with config.services.vaultwarden.config; {
+            vaultwarden_rocket.servers."${ROCKET_ADDRESS}:${toString ROCKET_PORT}" = {};
+            vaultwarden_websocket.servers."${WEBSOCKET_ADDRESS}:${toString WEBSOCKET_PORT}" = {};
           };
-          locations."/notifications/hub/negotiate" = {
-            proxyPass = "http://vaultwarden_rocket";
-            proxyWebsockets = true;
+          virtualHosts.${cfg.domain} = {
+            locations."/" = {
+              proxyPass = "http://vaultwarden_rocket";
+              proxyWebsockets = true;
+            };
+            locations."/notifications/hub" = {
+              proxyPass = "http://vaultwarden_websocket";
+              proxyWebsockets = true;
+            };
+            locations."/notifications/hub/negotiate" = {
+              proxyPass = "http://vaultwarden_rocket";
+              proxyWebsockets = true;
+            };
           };
         };
+        postgresql = {
+          enable = true;
+          extraPostStart = [
+            ''
+              $PSQL "${db}" -tAc 'GRANT ALL ON SCHEMA "public" TO "${db}"'
+            ''
+          ];
+        };
       };
-      postgresql.enable = true;
-    };
 
-    services = let
-      db = "vaultwarden";
-    in {
-      vaultwarden = {
-        enable = true;
-        config = {
-          TZ = config.time.timeZone;
+      services = {
+        vaultwarden = {
+          enable = true;
+          config = {
+            TZ = config.time.timeZone;
+
+            WEB_VAULT_ENABLED = true;
+
+            DOMAIN = optionalString (cfg.domain != null) "http://${cfg.domain}";
 
-          WEB_VAULT_ENABLED = true;
+            SIGNUPS_ALLOWED = false;
+            INVITATIONS_ALLOWED = false;
 
-          DOMAIN = optionalString (cfg.domain != null) "http://${cfg.domain}";
+            ORG_CREATION_USERS = "none";
 
-          SIGNUPS_ALLOWED = false;
-          INVITATIONS_ALLOWED = true;
+            PASSWORD_HINTS_ALLOWED = false;
+            SHOW_PASSWORD_HINT = false;
 
-          ROCKET_ADDRESS = "127.0.0.1";
-          ROCKET_PORT = 8812;
+            ROCKET_ADDRESS = "127.0.0.1";
+            ROCKET_PORT = 8812;
 
-          WEBSOCKET_ENABLED = true;
-          WEBSOCKET_ADDRESS = "127.0.0.1";
-          WEBSOCKET_PORT = 8813;
+            WEBSOCKET_ENABLED = true;
+            WEBSOCKET_ADDRESS = "127.0.0.1";
+            WEBSOCKET_PORT = 8813;
 
-          LOG_LEVEL = "error";
+            LOG_LEVEL = "error";
 
-          DATABASE_URL = "postgresql://${db}@/${db}";
+            DATABASE_URL = "postgresql://${db}@/${db}";
+          };
+          dbBackend = "postgresql";
+          environmentFile = config.secrets.vaultwarden-environment.path;
+        };
+
+        postgresql = {
+          ensureDatabases = [db];
+          ensureUsers = [
+            {
+              name = db;
+              ensurePermissions."DATABASE \"${db}\"" = "ALL";
+            }
+          ];
         };
-        dbBackend = "postgresql";
-        environmentFile = config.secrets.vaultwarden-environment.path;
-      };
 
-      postgresql = {
-        ensureDatabases = [db];
-        ensureUsers = [
-          {
-            name = db;
-            ensurePermissions."DATABASE \"${db}\"" = "ALL PRIVILEGES";
-          }
-        ];
+        fail2ban.jails = mkIf config.nixfiles.modules.fail2ban.enable {
+          vaultwarden = ''
+            enabled = true
+            filter = vaultwarden
+            port = http,https
+          '';
+          vaultwarden-admin = ''
+            enabled = true
+            filter = vaultwarden-admin
+            port = http,https
+          '';
+        };
       };
 
-      fail2ban.jails = mkIf config.nixfiles.modules.fail2ban.enable {
-        vaultwarden = ''
-          enabled = true
-          filter = vaultwarden
-          port = http,https
+      environment.etc = mkIf config.nixfiles.modules.fail2ban.enable {
+        "fail2ban/filter.d/vaultwarden.conf".text = ''
+          [Definition]
+          failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
+          ignoreregex =
+          journalmatch = _SYSTEMD_UNIT=vaultwarden.service
         '';
-        vaultwarden-admin = ''
-          enabled = true
-          filter = vaultwarden-admin
-          port = http,https
+        "fail2ban/filter.d/vaultwarden-admin.conf".text = ''
+          [Definition]
+          failregex = ^.*Invalid admin token\. IP: <ADDR>.*$
+          ignoreregex =
+          journalmatch = _SYSTEMD_UNIT=vaultwarden.service
         '';
       };
     };
-
-    environment.etc = mkIf config.nixfiles.modules.fail2ban.enable {
-      "fail2ban/filter.d/vaultwarden.conf".text = ''
-        [Definition]
-        failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
-        ignoreregex =
-        journalmatch = _SYSTEMD_UNIT=vaultwarden.service
-      '';
-      "fail2ban/filter.d/vaultwarden-admin.conf".text = ''
-        [Definition]
-        failregex = ^.*Invalid admin token\. IP: <ADDR>.*$
-        ignoreregex =
-        journalmatch = _SYSTEMD_UNIT=vaultwarden.service
-      '';
-    };
-  };
 }

Consider giving Nix/NixOS a try! <3