Add sops, setup parsedmarc and forward grafana
diff --git a/.sops.yaml b/.sops.yaml
new file mode 100644
index 0000000..0c67bd5
--- /dev/null
+++ b/.sops.yaml
@@ -0,0 +1,9 @@
+keys:
+  - &clicks_minion age15mv77dpnh5762gk5rsw2u79uza4tg8cu6r3nlwjudlzmdqqck3ss6mg9dy
+  - &server_dc1 age1fxxnmkeuqhhct93c43pwkzhuzzq8857s5hye6pgfpku70kjn4ecqtamfqr
+creation_rules:
+  - path_regex: secrets/.*
+    key_groups:
+    - age:
+      - *clicks_minion
+      - *server_dc1
diff --git a/flake.lock b/flake.lock
index c1c1967..a2bb784 100644
--- a/flake.lock
+++ b/flake.lock
@@ -95,6 +95,38 @@
         "type": "github"
       }
     },
+    "nixpkgs-stable": {
+      "locked": {
+        "lastModified": 1683504292,
+        "narHash": "sha256-jlZbBIKGa6IMGkcJkQ08pbKnouTAPfeq1fD5I7l/rBw=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "ba0086c178d4ed60a7899f739caea553eca2e046",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "release-22.11",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs-unstable": {
+      "locked": {
+        "lastModified": 1683777345,
+        "narHash": "sha256-V2p/A4RpEGqEZussOnHYMU6XglxBJGCODdzoyvcwig8=",
+        "owner": "nixos",
+        "repo": "nixpkgs",
+        "rev": "635a306fc8ede2e34cb3dd0d6d0a5d49362150ed",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nixos",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
     "nixpkgs_2": {
       "locked": {
         "lastModified": 1682817260,
@@ -116,7 +148,30 @@
         "deploy-rs": "deploy-rs",
         "flake-utils": "flake-utils",
         "home-manager": "home-manager",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs_2",
+        "nixpkgs-unstable": "nixpkgs-unstable",
+        "sops-nix": "sops-nix"
+      }
+    },
+    "sops-nix": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "nixpkgs-stable": "nixpkgs-stable"
+      },
+      "locked": {
+        "lastModified": 1683545104,
+        "narHash": "sha256-48wC0zzHAej/wLFWIgV+uj63AvQ2UUk85g7wmXJzTqk=",
+        "owner": "Mic92",
+        "repo": "sops-nix",
+        "rev": "36b062a2c85a0efb37de1300c79c54602a094fab",
+        "type": "github"
+      },
+      "original": {
+        "owner": "Mic92",
+        "repo": "sops-nix",
+        "type": "github"
       }
     },
     "systems": {
diff --git a/flake.nix b/flake.nix
index 99bd1c6..d2be14d 100644
--- a/flake.nix
+++ b/flake.nix
@@ -2,20 +2,28 @@
   description = "A flake to deploy and configure Clicks' NixOS server";
 
   inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11";
+  inputs.nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable";
   inputs.flake-utils.url = "github:numtide/flake-utils";
   inputs.deploy-rs.url = "github:serokell/deploy-rs";
   inputs.home-manager.url = "github:nix-community/home-manager/release-22.11";
+  inputs.sops-nix.url = "github:Mic92/sops-nix";
 
   inputs.home-manager.inputs.nixpkgs.follows = "nixpkgs";
   inputs.home-manager.inputs.utils.follows = "deploy-rs/utils";
 
-  outputs = { self, nixpkgs, deploy-rs, home-manager, ... }@inputs:
+  inputs.sops-nix.inputs.nixpkgs.follows = "nixpkgs";
+
+  outputs = { self, nixpkgs, deploy-rs, home-manager, sops-nix, nixpkgs-unstable, ... }@inputs:
     let
       system = "x86_64-linux";
       pkgs = import nixpkgs {
         inherit system;
         config.allowUnfree = true;
       };
+      pkgs-unstable = import nixpkgs-unstable {
+        inherit system;
+        config.allowUnfree = true;
+      };
     in
     {
       nixosConfigurations.clicks =
@@ -27,6 +35,7 @@
             ./modules/caddy.nix
             ./modules/clamav.nix
             ./modules/code-server.nix
+            ./modules/dmarc.nix
             ./modules/dnsmasq.nix
             ./modules/doas.nix
             ./modules/docker.nix
@@ -41,8 +50,10 @@
             ./modules/node.nix
             ./modules/samba.nix
             ./modules/tesseract.nix
+            sops-nix.nixosModules.sops
             {
               users.mutableUsers = false;
+              _module.args = { inherit pkgs-unstable; };
             }
           ];
         };
diff --git a/modules/caddy/Caddyfile b/modules/caddy/Caddyfile
deleted file mode 100644
index 49fd585..0000000
--- a/modules/caddy/Caddyfile
+++ /dev/null
@@ -1,27 +0,0 @@
-
-http://api.clicks.codes {
-    handle_path /nucleus/* {
-        reverse_proxy http://127.0.0.1:10000 {
-          trusted_proxies 192.168.81.136
-        }
-    }
-    respond 503
-}
-
-http://clicks.codes {
-    reverse_proxy http://127.0.0.1:3000 {
-      trusted_proxies 192.168.81.136
-    }
-}
-
-http://www.clicks.codes {
-    redir https://clicks.codes{uri} {
-      trusted_proxies 192.168.81.136
-    }
-}
-
-http://etherpad.clicks.codes {
-  reverse_proxy http://127.0.0.1:9001 {
-    trusted_proxies 192.168.81.136
-  }
-}
diff --git a/modules/caddy/caddy.json b/modules/caddy/caddy.json
index 8b9726b..686a431 100755
--- a/modules/caddy/caddy.json
+++ b/modules/caddy/caddy.json
@@ -96,6 +96,33 @@
             {
               "match": [
                 {
+                  "host": ["logs.clicks.codes"]
+                }
+              ],
+              "handle": [
+                {
+                  "handler": "subroute",
+                  "routes": [
+                    {
+                      "handle": [
+                        {
+                          "handler": "reverse_proxy",
+                          "upstreams": [
+                            {
+                              "dial": "127.0.0.1:9052"
+                            }
+                          ]
+                        }
+                      ]
+                    }
+                  ]
+                }
+              ],
+              "terminal": true
+            },
+            {
+              "match": [
+                {
                   "host": ["etherpad.clicks.codes"]
                 }
               ],
diff --git a/modules/dmarc.nix b/modules/dmarc.nix
new file mode 100644
index 0000000..7ab2e7a
--- /dev/null
+++ b/modules/dmarc.nix
@@ -0,0 +1,51 @@
+{ config, lib, pkgs, pkgs-unstable, ... }: {
+  users.users.parsedmarc = {
+    isSystemUser = true;
+    createHome = true;
+    home = "/services/parsedmarc";
+    group = config.users.groups.clicks.name;
+    shell = pkgs.bashInteractive;
+  };
+  sops.secrets = lib.pipe [
+    "imap_password"
+    "maxmind_license_key"
+  ] [
+    (map (name: {
+      inherit name;
+      value = {
+        mode = "0400";
+        owner = config.users.users.parsedmarc.name;
+        group = config.users.users.parsedmarc.group;
+        sopsFile = ../secrets/dmarc.json;
+        format = "json";
+      };
+    }))
+    builtins.listToAttrs
+  ];
+
+  services.parsedmarc = {
+    enable = true;
+    settings.imap = {
+      host = "mail.clicks.codes";
+      user = "dmarc@clicks.codes";
+      password = { _secret = config.sops.secrets.imap_password.path; };
+      watch = true;
+      delete = false;
+    };
+  };
+  services.geoipupdate.settings = {
+    AccountID = 863877;
+    LicenseKey = { _secret = config.sops.secrets.maxmind_license_key.path; };
+  };
+  systemd.services.geoipupdate-create-db-dir.script = lib.mkForce ''
+    set -o errexit -o pipefail -o nounset -o errtrace
+    shopt -s inherit_errexit
+
+    mkdir -p ${config.services.geoipupdate.settings.DatabaseDirectory}
+    chmod 0750 ${config.services.geoipupdate.settings.DatabaseDirectory}
+
+    chgrp clicks ${config.services.geoipupdate.settings.DatabaseDirectory}
+    # The license agreement does not allow us to let non-clicks users access the database
+  '';
+  services.elasticsearch.package = pkgs-unstable.elasticsearch;
+}
diff --git a/secrets/dmarc.json b/secrets/dmarc.json
new file mode 100644
index 0000000..d901b27
--- /dev/null
+++ b/secrets/dmarc.json
@@ -0,0 +1,25 @@
+{
+	"imap_password": "ENC[AES256_GCM,data:JbUCqbt5+oeNpKha+wzGjagro3mDIRVJb8Kcr35v6GaCbx9KOP7VCcGhDKjAFJRAPTkBqFYqQHXP06THV/nkvg==,iv:JF5/at0rF5oFsVu6N6ugVbE3l+3RSHtCWecJFJEXTgA=,tag:fp+EfFhxWIQG2tETnuByig==,type:str]",
+	"maxmind_license_key": "ENC[AES256_GCM,data:CsGO8CxV+Uiay4vtIif0u7SIJ4k74BBhW5zv5ESS5B6hX0whsk8LlQ==,iv:ctQbQGADrEvsaq88frTAmIhgbSd15qSsOclJYPzfNRI=,tag:6Pq6pfjPEGeoUDsvBJTY2A==,type:str]",
+	"sops": {
+		"kms": null,
+		"gcp_kms": null,
+		"azure_kv": null,
+		"hc_vault": null,
+		"age": [
+			{
+				"recipient": "age15mv77dpnh5762gk5rsw2u79uza4tg8cu6r3nlwjudlzmdqqck3ss6mg9dy",
+				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZK2ZGNmRYTFdaTHdmVzlv\nR3k0N2ExRzRMTmlJMzY4YUJ5MVVzVXJBamdFClpWYmpnOHo5M29yTitaTW9FS0Er\ndVVwNWZlNU1FdU9vTDBVVDFpQUFNU1kKLS0tIHcraTdWVm5BM1RnYzVxM3ZhQWQr\nUjV6S2s2QS9WaWtkYWh1MTBwbERhejAKY3hnjrF+WYkL2vvAL6CQoKW2VU7KTgAv\njtYYgqkpUjPixLG4V/Pik5b6sDAMiVvySscv8xVLyh+hNt3XG25hoQ==\n-----END AGE ENCRYPTED FILE-----\n"
+			},
+			{
+				"recipient": "age1fxxnmkeuqhhct93c43pwkzhuzzq8857s5hye6pgfpku70kjn4ecqtamfqr",
+				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSByMzUxaWREZ3kwaHFsaEdN\nTmhYK2F5UmlJVUplOUFmUmFiTkkvOElsL1c0Cmd2M3VGNEJwYVFmcjVhWlVZeHlm\nTVFFc1NsVXZTSXQ4N1lBTXh0K094bUkKLS0tIGxwelYxMWJEZ2doNGZxcXYxQlRY\nR1ZyeUJjRmowTFJJNFVPdFVkZDVpZTAK35F1nG0+jyKXlmD7t20KBTkIDriJCeh6\n8jENrMEu/MKMyRXLkNo4v9Y4D27BVT7V7l6JU0Ym0lgTS9uPp9SyIQ==\n-----END AGE ENCRYPTED FILE-----\n"
+			}
+		],
+		"lastmodified": "2023-05-12T00:43:43Z",
+		"mac": "ENC[AES256_GCM,data:u+IfVhGX3DaJvWRuwCFYciEuiUdQuQDNwHtsKPB2gPx5YYJwcqcLzU3ScY+Rz08igiOPh2ji/clmeaBwbMBGIysk+qC1jndPOOT2RbG1QyhOnUR9G0kYyhpKuV4fzUXPCwTLiy8qKy56/VFJwqIcmxMpDbcncgylIMF5DEsqQmE=,iv:x43pcdUfUo6ZnONadEzgjoAHuZb8LUnFAkgKMks9gUs=,tag:0P3+ifSgqUtiEUpqXkW+TQ==,type:str]",
+		"pgp": null,
+		"unencrypted_suffix": "_unencrypted",
+		"version": "3.7.3"
+	}
+}
\ No newline at end of file