diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b2be92b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+result
diff --git a/.sops.yaml b/.sops.yaml
new file mode 100644
index 0000000..220f3a7
--- /dev/null
+++ b/.sops.yaml
@@ -0,0 +1,14 @@
+keys:
+  # Hosts keys are age keys derived from the host ssh key.
+  - &two age1zlpu6qum5xcl07hnsndp78tllqph5jz7q8fr5ntxr88202xq9u9s9r2y7x
+  # Nounous keys.
+  - &_aeltheos 0xDF6D6CE9E95E26E8
+
+creation_rules:
+  # Secrets that are shared accross all hosts.
+  - path_regex: secrets/common.yaml
+    key_groups:
+    - pgp :
+      - *_aeltheos
+      age :
+      - *two
diff --git a/devshells/default.nix b/devshells/default.nix
index 8f0d443..19101ee 100644
--- a/devshells/default.nix
+++ b/devshells/default.nix
@@ -6,5 +6,6 @@ pkgs.mkShell {
   packages = with pkgs; [
     nil
     nixpkgs-fmt
+    sops
   ];
 }
diff --git a/flake.lock b/flake.lock
index 12a41a0..f569c24 100644
--- a/flake.lock
+++ b/flake.lock
@@ -52,13 +52,51 @@
         "type": "github"
       }
     },
+    "nixpkgs-stable": {
+      "locked": {
+        "lastModified": 1705957679,
+        "narHash": "sha256-Q8LJaVZGJ9wo33wBafvZSzapYsjOaNjP/pOnSiKVGHY=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "9a333eaa80901efe01df07eade2c16d183761fa3",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "release-23.05",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
     "root": {
       "inputs": {
         "flake-parts": "flake-parts",
         "nixpkgs": "nixpkgs",
+        "sops-nix": "sops-nix",
         "treefmt-nix": "treefmt-nix"
       }
     },
+    "sops-nix": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "nixpkgs-stable": "nixpkgs-stable"
+      },
+      "locked": {
+        "lastModified": 1707015547,
+        "narHash": "sha256-YZr0OrqWPdbwBhxpBu69D32ngJZw8AMgZtJeaJn0e94=",
+        "owner": "Mic92",
+        "repo": "sops-nix",
+        "rev": "23f61b897c00b66855074db471ba016e0cda20dd",
+        "type": "github"
+      },
+      "original": {
+        "owner": "Mic92",
+        "repo": "sops-nix",
+        "type": "github"
+      }
+    },
     "treefmt-nix": {
       "inputs": {
         "nixpkgs": [
diff --git a/flake.nix b/flake.nix
index f0279bf..f57956e 100644
--- a/flake.nix
+++ b/flake.nix
@@ -10,6 +10,12 @@
       url = "github:numtide/treefmt-nix";
       inputs.nixpkgs.follows = "nixpkgs";
     };
+
+    # Secret management
+    sops-nix = {
+      url = "github:Mic92/sops-nix";
+      inputs.nixpkgs.follows = "nixpkgs";
+    };
   };
 
   outputs = inputs @ { self, nixpkgs, flake-parts, ... }:
@@ -23,10 +29,12 @@
       flake = with nixpkgs.lib; {
         nixosConfigurations = {
           neo = nixosSystem {
+            specialArgs = inputs;
             modules = [ ./hosts/vm/neo ];
           };
 
           two = nixosSystem {
+            specialArgs = inputs;
             modules = [ ./hosts/vm/two ];
           };
         };
diff --git a/modules/crans/default.nix b/modules/crans/default.nix
index d4fbfbe..85a4f47 100644
--- a/modules/crans/default.nix
+++ b/modules/crans/default.nix
@@ -7,6 +7,7 @@
     ./ntp.nix
     ./users.nix
     ./home.nix
+    ./sops.nix
   ];
 
   services.qemuGuest.enable = true;
diff --git a/modules/crans/sops.nix b/modules/crans/sops.nix
new file mode 100644
index 0000000..201ca20
--- /dev/null
+++ b/modules/crans/sops.nix
@@ -0,0 +1,8 @@
+{ sops-nix, ... }: {
+  imports = [
+    sops-nix.nixosModules.sops
+  ];
+
+  # This will automatically import host ssh key as age key for secret description.
+  sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
+}
diff --git a/modules/crans/users.nix b/modules/crans/users.nix
index b2a9f39..9a7352a 100644
--- a/modules/crans/users.nix
+++ b/modules/crans/users.nix
@@ -1,4 +1,4 @@
-{ ... }:
+{ config, ... }:
 
 {
   users.ldap = {
@@ -34,8 +34,13 @@
     ];
   };
 
-  users.users.root = {
-    hashedPassword = "$6$aKmj69cplAKoeR9z$BVNUsPz3sNWFdxJkDaYBsLlbdSUdsn42Rok6Ozsd8dbE8E36RX54/tuaPM2bW6/0SletzEmIAGFdf4kIWNy3O1";
+  sops.secrets.root-passwd-hash = {
+    sopsFile = ../../secrets/common.yaml;
   };
+
+  users.users.root = {
+    hashedPasswordFile = config.sops.secrets.root-passwd-hash.path;
+  };
+
   services.openssh.settings.PermitRootLogin = "yes";
 }
diff --git a/secrets/common.yaml b/secrets/common.yaml
new file mode 100644
index 0000000..7030af0
--- /dev/null
+++ b/secrets/common.yaml
@@ -0,0 +1,41 @@
+root-passwd-hash: ENC[AES256_GCM,data:TueFl3zXBTnpVtduQTLIzYCn2cNnxECiFEf7F+zBeq1A+lghV2ZUf82ZU+fajI/fcjMij9xMcLOZchksUkRRZ9SNHsoDTamiChC3ecOsxcndR/SElN8Wpr2yqsV3NNAt/4EF4leNyEdrJg==,iv:Lo6/odISnTOVd+dO3tRJZVYNzivyXuPowJWk+d8C+Ck=,tag:1zEh8Umy1tgM+SnqOLxvig==,type:str]
+sops:
+    kms: []
+    gcp_kms: []
+    azure_kv: []
+    hc_vault: []
+    age:
+        - recipient: age1zlpu6qum5xcl07hnsndp78tllqph5jz7q8fr5ntxr88202xq9u9s9r2y7x
+          enc: |
+            -----BEGIN AGE ENCRYPTED FILE-----
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMdXIrWnZiZS9HczV3Z1ZQ
+            aGlsSnU3ZVhaeE9XTm8wYUtOQ0NTdG9Na25FCjdnVlJwU1hzUFJhSlB0OXN4dzRu
+            Q2hpQ1ZtR05nQ0V4Z2Y5NzF3eXJIZzQKLS0tIHN0NjBHME5HeGFYdHVsbkkzK2tI
+            dGt4OU5PRTh5UXdLS0JqOUtUZ2llSEEKH4K/9rxiceIeRrnz60rz8oq119tr5E9Y
+            q6uOplUCKZjp2bdcjJGnXU0u0TvV6HG2r2nb6kT4TAdhPF1EJqKQtw==
+            -----END AGE ENCRYPTED FILE-----
+    lastmodified: "2024-02-05T21:38:50Z"
+    mac: ENC[AES256_GCM,data:ZUA6Ij81846B2xumn9YjrlRufj9KfoItf2MCViVbIlQO97or1rJAz+iWxmf/I0YNzhOKzuchyG0X6669fUkePk0qNKrk9HBQLX7BM+O51qgEijrqq2SXlo8hyNTC7zUFL202yT1ATL8uD7lgBZpqgxBOcYp9D7+dkvotzFTOAco=,iv:2o7OGekocDF3Lj8OCnLOwGBBs/k13R1/a0CH+GTFsyQ=,tag:FqPF0Vvbuc5/D5tRLA+r9Q==,type:str]
+    pgp:
+        - created_at: "2024-02-05T21:36:08Z"
+          enc: |-
+            -----BEGIN PGP MESSAGE-----
+
+            hQIMAwEdD9k5IbiyAQ/+LOOq+WUEh/8BTPfqCRgEmsSNbCWGsoXAT5IIjHOnbnaN
+            UkPgkEA/HiLo1TYPCgDzqyiEa7hwsDNwdzzRv+Lj6KEnVQBK+zNHfgo2HDyCCqzy
+            NzPQWT0soC0kWvuXMPgzlfjV+wc7fqrDd1/Ub6RjgDuhsJp4RKZeqaN6ptt4ObUV
+            AzWS96RBA1+FEc14/UXPcFQxqJdoy0SBIjyeygF1r8XiRt2H+OBJLw98Orspz7j7
+            cUhDW+jkZoCzYBy2M3gGYild4ox92eUp11OCI9LOcHhgAvLrst54AVFsUWJDIsLv
+            kOSok5+JjuXeue9jH2rq7owkU4RVpJ4qjTTJrcdc0yhTMJEyrNXqKLO4bm6RVgmX
+            IdCfvdBvhZahQSpd1kO01atP/M+Bk1Kq6JbdAoSGwZpbrlgFUZsXC/AOtPdEpoMH
+            NmFIO6mbUDGrCIrBARGSFnk/nGOfjdZqZzz5x85GWWWM7sfK+jIOI+ABH2+iL3q7
+            R8t0TRr16IFLHvQylWvKZ9sNKM4o6Phl0L3WVtWMVQD73uPCY8L07cd2sNose2SD
+            eIhscCoKCOT06yHnPAw4uksK3YzWTH4sO5KpE2OjoVkrAWfp7R1xtHTBWbX5iGpG
+            0bDE4BEWiX+rhl+OOvKcFq/LDd8ieIInkRl8s39GR00cb3VfZDQTEs/CDEoeeZ7S
+            XgH3eMCG0F/z3L5LWsVmM5KhKLW2VBpKIbpwphUiTZdnBQQiWj/QwGE+CJsQ38uh
+            2vv9oUiZNNhq0jbdyxnamusfaZPjUjkKSkiYm5ZIXLe04yT4bRWCYaX8Af838hE=
+            =hPoG
+            -----END PGP MESSAGE-----
+          fp: "0xDF6D6CE9E95E26E8"
+    unencrypted_suffix: _unencrypted
+    version: 3.8.1