Setup a wiki.js instance for TransPlace

Similarly to the redis instance, TransPlace is rather annoying to run
services on. Therefore, I have offered to run this on nix until such a
time as Cleo figures out how to set this up on pterodactyl

Change-Id: Iceff9c46e34201968f8e7b097267641499417b57
Reviewed-on: https://git.clicks.codes/c/Infra/NixFiles/+/632
Reviewed-by: Samuel Shuert <coded@clicks.codes>
Tested-by: Skyler Grey <minion@clicks.codes>
diff --git a/modules/common/nginx-routes.nix b/modules/common/nginx-routes.nix
index 1d231ce..ff2cf0d 100644
--- a/modules/common/nginx-routes.nix
+++ b/modules/common/nginx-routes.nix
@@ -1,5 +1,6 @@
 { pkgs, helpers, config, lib, ... }: {
   clicks.nginx.services = with helpers.nginx; [
+    (Host "guide.trans.gg" (ReverseProxy "generic:1035"))
     (Host "signup.hopescaramels.com" (ReverseProxy "caramels:1024"))
     (Host "freeflowtaekwondo.com" (ReverseProxy "generic:1026"))
     (Host "homebridge.coded.codes" (ReverseProxy "CodedPi:8581"))
diff --git a/modules/common/postgres.nix b/modules/common/postgres.nix
index 7955bc2..5e07c4b 100644
--- a/modules/common/postgres.nix
+++ b/modules/common/postgres.nix
@@ -15,7 +15,17 @@
       log_destination = lib.mkForce "syslog";
     };
 
-    ensureDatabases = [ "vaultwarden" "gerrit" "privatebin" "keycloak" "nextcloud" "synapse" "taiga" "jinx" ];
+    ensureDatabases = [
+      "vaultwarden"
+      "gerrit"
+      "privatebin"
+      "keycloak"
+      "nextcloud"
+      "synapse"
+      "taiga"
+      "jinx"
+      "wiki"
+    ];
 
     ensureUsers = [
       {
@@ -52,6 +62,10 @@
         name = "jinx";
         ensureDBOwnership = true;
       }
+      {
+        name = "wiki";
+        ensureDBOwnership = true;
+      }
     ] ++ (map (name: ({
       inherit name;
     })) [ "minion" "coded" "pineafan" ]);
@@ -107,6 +121,10 @@
         user = "jinx";
         passwordFile = config.sops.secrets.clicks_jinx_db_password.path;
       }
+      {
+        user = "wiki";
+        passwordFile = config.sops.secrets.clicks_wiki_db_password.path;
+      }
     ] [
       (map (userData: ''
         $PSQL -tAc "ALTER USER ${userData.user} PASSWORD '$(cat ${userData.passwordFile})';"
@@ -136,6 +154,7 @@
     "clicks_nextcloud_db_password"
     "clicks_taiga_db_password"
     "clicks_jinx_db_password"
+    "clicks_wiki_db_password"
   ] [
     (map (name: {
       inherit name;
diff --git a/modules/common/wikijs.nix b/modules/common/wikijs.nix
new file mode 100644
index 0000000..506de26
--- /dev/null
+++ b/modules/common/wikijs.nix
@@ -0,0 +1,26 @@
+{ config, ... }: {
+  services.wiki-js = {
+    enable = true;
+  
+    settings = {
+      bindIP = "127.0.0.255";
+      port = 1035;
+
+      db = {
+        host = "standard";
+        user = "wiki";
+        pass = "$(DB_PASS)";
+      };
+    };
+
+    environmentFile = config.sops.secrets.wikijs__env_bin.path;
+  };
+
+  sops.secrets.wikijs__env_bin = {
+    mode = "0600";
+    owner = config.users.users.root.name;
+    group = config.users.users.root.group;
+    sopsFile = ../../secrets/wikijs.env.bin;
+    format = "binary";
+  };
+}
diff --git a/secrets/postgres.json b/secrets/postgres.json
index 40d5f59..0a4c947 100644
--- a/secrets/postgres.json
+++ b/secrets/postgres.json
@@ -6,6 +6,7 @@
 	"clicks_nextcloud_db_password": "ENC[AES256_GCM,data:Tu4BRo0qkpp+RXYlQO7PIfZM40tquvQUt9hbtZdKRotrOg81CGjZLISjNELr8pLCQK4AAfCJ7UPdR0ZztJfhrj5vPnaQM/2nHO4aMuhfnkOX00MDJhum/j1I0Adx/Au9zAaIONaKMBXLmX/g3FU2s6Yp7OtZ7/4FoWAYbG4zSbY=,iv:LjlkKkVNybg9EU9pytsmyYJrFMym0RmSvIFI/KKcpyc=,tag:rPyOh+KtAmo9OeY0Wm1sCQ==,type:str]",
 	"clicks_taiga_db_password": "ENC[AES256_GCM,data:z6XN0q7pGnaevH2WHd8Cjin8HwmhgZUwsZXYBAJBvvDYGWKOZAkkb6uDwdkEF7ZGtRwvjPTxH2VNoncNJJOYDngbRIQz+ntkVTKfmsbdBjKBWDKHbho5+IImeuetMFRkpwsCCyoRgu7r/3JVsW+rzIaOXvw4FjFTknadA+nFN2Q=,iv:KVJdVp3jSiGrpD1bl+S4H+iIklHp7W4zo0niq02mUMc=,tag:g/12Hjro169Kr41WhS0kSg==,type:str]",
 	"clicks_jinx_db_password": "ENC[AES256_GCM,data:uRg4ayNuhQN/udG00jUB93XKwSL6OehmGUY9/QhRugnbscLQSf+Hm6OkawyR9tPrtgROXVXysNMNJ1A27OVPTDf32TP+vz0Lw+dvc1NBM1jWcl4pi9UIcndDifLigVgYWpHL0oUQR+oHVXwnHnykGdPqXYDtycedD94fcmqI6Wg=,iv:TfPQEDvkqt3Jw+ZIWDk/B2elheyRzUpYDIDqpOV7F+I=,tag:DrzwWItSWNY53J/jEbHILw==,type:str]",
+	"clicks_wiki_db_password": "ENC[AES256_GCM,data:71LYoSpWXpsjBFiGu9H2VuqOHIyKTLquTn1nf7Uv9CIk8TOm+NM1nRreofl+e7MBHacZJiTbiiPWTDjVZCxI6IvgBP7uentc9Q7ra982rt4aalQrfYnUe4krV7KOwCqPOZzPIRfuYeR0sPtObH+xACec0arV0W09SlYLEv0EEcM=,iv:INag6EYa3s+U8k/STcmGJCKtVjDxEJI3v/8iLjGuK74=,tag:7/na8UII/4OaWplS+6V3nA==,type:str]",
 	"sops": {
 		"kms": null,
 		"gcp_kms": null,
@@ -29,8 +30,8 @@
 				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3clFVS0JZSkhmNElLa3N2\nNFdkT091dzZPdXUyOXNUNkk1QzNMS0hJengwCjcya01LanZhTXNsaGpQdVIvNlRl\nZnljZkhZYWVUR2xJckJPbUpnOSt4SmMKLS0tIElMcGNRTVJudXFORG4zZ3drdG1C\nYTZPcDh4OGwzUTZDVlhWNk55bDZMd2sK/F5ZGw6Kf8nWRXDobOonFDtPlSSU5c4u\nAEvihsNSDR3MwvQgu5jJCuCeRGLdXaOqBBEYrIamIcAlVKGeT6y/UA==\n-----END AGE ENCRYPTED FILE-----\n"
 			}
 		],
-		"lastmodified": "2024-02-14T19:15:22Z",
-		"mac": "ENC[AES256_GCM,data:sspfUgxhzZQLrTH2uH1PcV0eOoYwFhj6e1KPjLqV14c0UOqmP7h/w/rydZPRTfxH9K/QifRg+fCbcEIVDTfhgSxg++GUJBnmv8kzAWKmrheN4GjuHtKY9SZ6xICLdQd+Jcy7mEGZKOjEJVt8kGEqk1nkKfiF6Q/5VfiZ2iguLSc=,iv:CLq8VCB7NvITHFBpEuBa6dQW0vuR5XKw92GdY9PrJ7E=,tag:nU0b+lt3XZiUYpibgnxjIA==,type:str]",
+		"lastmodified": "2024-04-18T22:32:34Z",
+		"mac": "ENC[AES256_GCM,data:50i4i+g1vOKsskVOmVH5qMp6A6MQwbHl2Xy5U6L7AauWZ218qpgq2/I0kvhdkYLu8szjp2mYCxwOKoZH1cDnQ/SiWpyMTo5t2SToEqby/Fb+LeZSIF1Ynb8Zp7O0/8+cfuU7zUEw4AnMJGA+xc7x4CcweW15gDqJTEcxeNCDwtg=,iv:XwKZmDhjqpifHH6aIZYmFQH7N4m0nxT+z46hzG9fkv8=,tag:bxJNBNeT1CBjT4cIBxlpeg==,type:str]",
 		"pgp": null,
 		"unencrypted_suffix": "_unencrypted",
 		"version": "3.8.1"
diff --git a/secrets/wikijs.env.bin b/secrets/wikijs.env.bin
new file mode 100644
index 0000000..230cb72
--- /dev/null
+++ b/secrets/wikijs.env.bin
@@ -0,0 +1,32 @@
+{
+	"data": "ENC[AES256_GCM,data:AdGY5NNkiFV9djDWpZMYBrG1hTkFU2C7vnMplZuPD1MRIx6un4Cu2+vsQQidPX40+mrrqDMvGFrD8Lk4/fngq2uUmK5y4VmWEUZltYEu+7OdMnW6bqmTx5y+SRqa4e+r62OvQK5S3CgNyC3CWO2n3kQaJ8qfTjr4cS5aar1TZhGQGkPe3hUOw18=,iv:GYxJ9UHin3Hx+SX81L14Jc7urBPiJFvxMOkKku6PGcc=,tag:FdB4ieZFFSfYB0nC3WUlUw==,type:str]",
+	"sops": {
+		"kms": null,
+		"gcp_kms": null,
+		"azure_kv": null,
+		"hc_vault": null,
+		"age": [
+			{
+				"recipient": "age15mv77dpnh5762gk5rsw2u79uza4tg8cu6r3nlwjudlzmdqqck3ss6mg9dy",
+				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6VE4wL0k0S2dxdmg1ckR4\nUVlzdjVsUGtZZUgxNlJ5OTRTaytuNEJlY3hnClVIRTRJTEFaYmttUDhZeWFBZ2h0\nZW5RWkoyUHF2NWRwK0FNcWtsVkpLaGcKLS0tIG42dXdCWStJaEg0ckZFc1EzeHM2\nSkpPYzdIYURKOUpPSjNxTVNRbkIycEUKcOxIKBWhfZ0LijvJGM47TDg06Ptckz5B\n3M4JtVOhGs2xhivBxndIgbi61GR3tl4yyS6Pg0D04zfqtzDWFHZCCg==\n-----END AGE ENCRYPTED FILE-----\n"
+			},
+			{
+				"recipient": "age1m7k864feyuezllp2hj4edkccn36rthrvfw969j6f0l3c0mhh5emsnfx6pd",
+				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEUDFoNFZyMWM5UlJESzJx\nL3dsUStCU0V3bnV4SnhaTGVKZUdmSnF2a1NvCllFYWpEODdjTzdTY0c1aEtEU2Ux\nMXJ5Tm11WUE2MDRNMWZFamhoWTQvZnMKLS0tIHRNNis0UENibEFsWDc5OVBNKzBO\nQU5tdmpsaU5uWHFsWTg4c0VJSy8vRzQKq136ieF65VugtbFRazD/bwRLjvAPl/XT\nAFQ6sUkBHfVJKGLfWbhGkNhUk72J2Uu3heZPAW9gKaKqRHGO/0bdHw==\n-----END AGE ENCRYPTED FILE-----\n"
+			},
+			{
+				"recipient": "age1fxxnmkeuqhhct93c43pwkzhuzzq8857s5hye6pgfpku70kjn4ecqtamfqr",
+				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3Q0RLSjhnMzRDK0hlQ2wz\nMnZlL1dsd2NyZHJtUHVjYjVjMUlVTE4rUFhjCnhTSmFrdzd0bVFPRE41cHZhN0FD\nYXZWYVFsQ0pEZUhBcmZJWkFaOU42Y2cKLS0tIGFyOEdjdFdmVFBkZkNnOU5wd1VJ\ndDIzbnpzaFI4M2pTcnFZVHFwaHA2WUkKKUKbrdZU8WtDbvnGmqW2qy22hqqnvhVT\nmdgZ2EO6KSGr3F2TtC40YU9y37C+XtqvnQGWyZR3Feo+hUYB/nmXsQ==\n-----END AGE ENCRYPTED FILE-----\n"
+			},
+			{
+				"recipient": "age1zunqahfz404x7v8x0gs4hv5kq2xlyvqmukhlwvpymj74805jcunq4r7ugv",
+				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxNVdXWjdWRWdhQXk5cnlu\nck40ankwUzQ5OFJBb1NLRTFFakVBSDdoSG0wCk0vUzVRNGFyV0ZFa0wwUkxXaEJq\nMVF1SFYwSkYvQm9WbThMdE9Jb1FXbzQKLS0tIDNqQ3hwU0xFcEI0ZHowSWFpRHha\nS1pHMytzcmFjclZqME82Sm4yclI5VmMK4n9RAN3D2DlcNPZU1G9PaHNNAPbRy1VQ\n/EKwss1bG7lvJ1x7RyDd6mpdyEpJp2TZLK3HQsx9Fn0BtDsiX0uEXw==\n-----END AGE ENCRYPTED FILE-----\n"
+			}
+		],
+		"lastmodified": "2024-04-18T22:32:56Z",
+		"mac": "ENC[AES256_GCM,data:BZXfY2LKQJdDnbY5oMXrDDERhjWIvcw5m0wMvReo2xvx/zDyeocFyBBbYdQFLe2R7s85s2SJOAe7611crMpmn+COf+FvANbclrNjj3lNq3Jk9fWIyhZez26p9ze83YJAwX09erHW8NYZ323XVa3jKAmYiIwSr22BnY+jAHxcsuA=,iv:lD2Wphq+tpNR83jBBhaoJ4wMAzWV9ZhF2FPSkLAo8/8=,tag:Z5N9a1qIZrAgGFbYeAjr+w==,type:str]",
+		"pgp": null,
+		"unencrypted_suffix": "_unencrypted",
+		"version": "3.8.1"
+	}
+}
\ No newline at end of file