Compare commits
161 Commits
68b58053d4
...
725ba42c78
Author | SHA1 | Date |
---|---|---|
Tim Van Baak | 725ba42c78 | |
Tim Van Baak | c2a45ec1bb | |
Tim Van Baak | e550e73d5d | |
Tim Van Baak | d6da7b5306 | |
Tim Van Baak | e8239a9960 | |
Tim Van Baak | 5680da15c0 | |
Jaculabilis | 17a863831e | |
Tim Van Baak | 8841ab5c5a | |
Tim Van Baak | 7e983774cd | |
Jaculabilis | 0543198e6b | |
Tim Van Baak | cd76ffcd5a | |
Tim Van Baak | 982ec72e6b | |
Jaculabilis | fbf96fd83a | |
Jaculabilis | c74cb1d16d | |
Tim Van Baak | 981ba9f6a5 | |
Tim Van Baak | b416859153 | |
Tim Van Baak | 726e0fd9b6 | |
Tim Van Baak | bf4b31f4fc | |
Tim Van Baak | 265ed5b9e7 | |
Tim Van Baak | 6a9cd5b5d2 | |
Tim Van Baak | d162e2262b | |
Tim Van Baak | 7d927ede86 | |
Tim Van Baak | 8043cd2a93 | |
Tim Van Baak | 1956c75a61 | |
Tim Van Baak | 89e1752d0e | |
Tim Van Baak | 612fcb7dce | |
Tim Van Baak | 75a6b01fc6 | |
Tim Van Baak | 46c862085f | |
Tim Van Baak | af0918603d | |
Tim Van Baak | d8628b33cc | |
Tim Van Baak | d4a34ffe19 | |
Tim Van Baak | a13d098d4e | |
Tim Van Baak | 5afdd69a2f | |
Tim Van Baak | 6f3c75e53c | |
Tim Van Baak | 22ec014c38 | |
Tim Van Baak | 87da6efaed | |
Tim Van Baak | 1c8603fd8e | |
Tim Van Baak | 969cc2ecec | |
Tim Van Baak | 51f72d2d55 | |
Tim Van Baak | c86cf48127 | |
Tim Van Baak | 9befa8bb16 | |
Jaculabilis | 8335a93596 | |
Tim Van Baak | 471930cb64 | |
Jaculabilis | a5b364fbc1 | |
Tim Van Baak | 12117f37bb | |
Jaculabilis | 46c6157fab | |
Jaculabilis | c9242c0bea | |
Tim Van Baak | 84fa63493f | |
Jaculabilis | 44583f670f | |
Jaculabilis | ba3c46b8f4 | |
Jaculabilis | fa46c83f46 | |
Tim Van Baak | 48f36f5d9e | |
Tim Van Baak | 17b87e606c | |
Tim Van Baak | b4a32f04b5 | |
Tim Van Baak | e71acea928 | |
Tim Van Baak | d47d87d91f | |
Tim Van Baak | 0fce9564f5 | |
Tim Van Baak | 96d6e73346 | |
Tim Van Baak | f8e09d26d1 | |
Tim Van Baak | 3a954c35c1 | |
Tim Van Baak | a8730b3a13 | |
Tim Van Baak | 5b752f7cfa | |
Tim Van Baak | 40087d26be | |
Tim Van Baak | c9f65b73d7 | |
Tim Van Baak | 6b5dcb6e1d | |
Tim Van Baak | e381001f0a | |
Tim Van Baak | 741a0bc340 | |
Tim Van Baak | 49d864839a | |
Tim Van Baak | 532e7a5c6b | |
Tim Van Baak | 7afcfbac2b | |
Tim Van Baak | c0cbd43411 | |
Tim Van Baak | 4676c9e91d | |
Jaculabilis | 05357d5423 | |
Tim Van Baak | 6804636ce5 | |
Tim Van Baak | 267b3d3898 | |
Tim Van Baak | 9d2ac1f8ec | |
Tim Van Baak | ed5fee36ed | |
Tim Van Baak | bdffba6351 | |
Jaculabilis | 9d964dd7f7 | |
Jaculabilis | 43a14b2bec | |
Tim Van Baak | 311aba7975 | |
Tim Van Baak | 4d5227f51b | |
Tim Van Baak | 14842e99a1 | |
Tim Van Baak | eeb694b08c | |
Tim Van Baak | d553d80270 | |
Tim Van Baak | 23e9af7564 | |
Tim Van Baak | 721e5a3ca1 | |
Tim Van Baak | 33b50d12d9 | |
Tim Van Baak | a0979abb57 | |
Tim Van Baak | 298b91f83f | |
Tim Van Baak | 0b5ac640b8 | |
Jaculabilis | 1e740188e6 | |
Jaculabilis | f2feb22a86 | |
Jaculabilis | ba9bfa01f3 | |
Jaculabilis | 092250889a | |
Tim Van Baak | 0fc5aaa8c0 | |
Jaculabilis | 8a3e01091c | |
Tim Van Baak | a6b52340af | |
Tim Van Baak | 57dcaf1f07 | |
Tim Van Baak | 06b632ec68 | |
Jaculabilis | 820417819f | |
Tim Van Baak | f5faefb5e5 | |
Jaculabilis | 72c5619671 | |
Tim Van Baak | ce4a568809 | |
Jaculabilis | de253930e3 | |
Jaculabilis | 6215ce2961 | |
Jaculabilis | 637fea3bbd | |
Jaculabilis | c13fabbdbc | |
Jaculabilis | 43c19146a9 | |
Jaculabilis | 071cb4774d | |
Jaculabilis | 8ef887a4f0 | |
Jaculabilis | c431fb3ca5 | |
Jaculabilis | a718222744 | |
Tim Van Baak | 0b8ef01e5e | |
Tim Van Baak | 5470f2672d | |
Tim Van Baak | 504d1a4283 | |
Tim Van Baak | a4089b030f | |
Tim Van Baak | 83cbd95c95 | |
Tim Van Baak | 72720464ec | |
Tim Van Baak | 13090dd594 | |
Tim Van Baak | bda35d7da4 | |
Tim Van Baak | db33f88300 | |
Tim Van Baak | 1d515f416a | |
Tim Van Baak | dd265429be | |
Tim Van Baak | 35247f7b4a | |
Tim Van Baak | b9c6e20ef6 | |
Tim Van Baak | d87f127954 | |
Tim Van Baak | ec88265631 | |
Tim Van Baak | 2a618ce67f | |
Tim Van Baak | 656fdeef49 | |
Tim Van Baak | 7feec36673 | |
Tim Van Baak | 4e8a2bb7e4 | |
Tim Van Baak | 9948b73eff | |
Tim Van Baak | d63efc38b9 | |
Tim Van Baak | b216c2acd9 | |
Tim Van Baak | a78c36b871 | |
Tim Van Baak | 733679c944 | |
Tim Van Baak | 3ba86c1115 | |
Jaculabilis | 852304140a | |
Jaculabilis | c3494644cc | |
Jaculabilis | 041c17bfb3 | |
Jaculabilis | 9c990c13a7 | |
Jaculabilis | 35d9393733 | |
Jaculabilis | d982e1c4cd | |
Jaculabilis | 79d941b343 | |
Jaculabilis | c0887179ce | |
Jaculabilis | ca79e62268 | |
Jaculabilis | 7e43cd2efa | |
Jaculabilis | ff1ed94c3f | |
Jaculabilis | ba5486e372 | |
Jaculabilis | 63c50d5c67 | |
Jaculabilis | 986c2d4674 | |
Jaculabilis | 6587d70066 | |
Jaculabilis | f134165737 | |
Jaculabilis | cd4cf9107c | |
Jaculabilis | 4f9b51a94b | |
Jaculabilis | b3a1f104ff | |
Jaculabilis | f252a38b1b | |
Jaculabilis | e8a7aae12e | |
Jaculabilis | bbe12a24d3 | |
Jaculabilis | 741d6a7d95 |
109
flake.lock
109
flake.lock
|
@ -3,11 +3,11 @@
|
|||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1668681692,
|
||||
"narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "009399224d5e398d03b22badca40a37ac85412a1",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -31,12 +31,79 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"intake": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"flake-compat"
|
||||
],
|
||||
"nixos-shell": "nixos-shell",
|
||||
"nixpkgs": [
|
||||
"nixpkgs-2305"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1696904526,
|
||||
"narHash": "sha256-VbPMkzZBNhRB5fj2cEBnTRP1LRJHOWX1d8KGuAqtezQ=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "8fd6f3b751fd46c0d4571d1cf4f330dc38b8270e",
|
||||
"revCount": 79,
|
||||
"type": "git",
|
||||
"url": "ssh://gitea@git.alogoulogoi.com/Jaculabilis/intake.git"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "ssh://gitea@git.alogoulogoi.com/Jaculabilis/intake.git"
|
||||
}
|
||||
},
|
||||
"intake-sources": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs-2305"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1700115142,
|
||||
"narHash": "sha256-EuLKiCD8AVQUEADh+TJoePc6GR+TKVvmbOb4Duld2gI=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "327a79479d80dc7c1760f32887b7f07723529d66",
|
||||
"revCount": 26,
|
||||
"type": "git",
|
||||
"url": "ssh://gitea@git.alogoulogoi.com/Jaculabilis/intake-sources.git"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "ssh://gitea@git.alogoulogoi.com/Jaculabilis/intake-sources.git"
|
||||
}
|
||||
},
|
||||
"nixos-shell": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"intake",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1686216465,
|
||||
"narHash": "sha256-0A4K6xVIyxUi2YZu4+156WwzAO1GDWGcKiMvsXpBQDQ=",
|
||||
"owner": "Mic92",
|
||||
"repo": "nixos-shell",
|
||||
"rev": "65489e7eeef8eeea43e1e4218ad1b99d58852c7c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"repo": "nixos-shell",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-wsl": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-compat": [
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
"nixpkgs-2305"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
|
@ -53,26 +120,46 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"nixpkgs-2305": {
|
||||
"locked": {
|
||||
"lastModified": 1669833724,
|
||||
"narHash": "sha256-/HEZNyGbnQecrgJnfE8d0WC5c1xuPSD2LUpB6YXlg4c=",
|
||||
"lastModified": 1685566663,
|
||||
"narHash": "sha256-btHN1czJ6rzteeCuE/PNrdssqYD2nIA4w48miQAFloM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4d2b37a84fad1091b9de401eb450aae66f1a741e",
|
||||
"rev": "4ecab3273592f27479a583fb6d975d4aba3486fe",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "refs/tags/22.11",
|
||||
"ref": "23.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-2311": {
|
||||
"locked": {
|
||||
"lastModified": 1701282334,
|
||||
"narHash": "sha256-MxCVrXY6v4QmfTwIysjjaX0XUhqBbxTWWB4HXtDYsdk=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "057f9aecfb71c4437d2b27d3323df7f93c010b7e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "23.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"intake": "intake",
|
||||
"intake-sources": "intake-sources",
|
||||
"nixos-wsl": "nixos-wsl",
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs-2305": "nixpkgs-2305",
|
||||
"nixpkgs-2311": "nixpkgs-2311"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
98
flake.nix
98
flake.nix
|
@ -1,27 +1,103 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs?ref=refs/tags/22.11";
|
||||
nixos-wsl.url = "github:nix-community/NixOS-WSL";
|
||||
nixos-wsl.inputs.nixpkgs.follows = "nixpkgs";
|
||||
nixpkgs-2305.url = "github:NixOS/nixpkgs/23.05";
|
||||
nixpkgs-2311.url = "github:NixOS/nixpkgs/23.11";
|
||||
flake-compat = {
|
||||
url = "github:edolstra/flake-compat";
|
||||
flake = false;
|
||||
};
|
||||
nixos-wsl = {
|
||||
url = "github:nix-community/NixOS-WSL";
|
||||
inputs.nixpkgs.follows = "nixpkgs-2305";
|
||||
inputs.flake-compat.follows = "flake-compat";
|
||||
};
|
||||
intake = {
|
||||
url = "git+ssh://gitea@git.alogoulogoi.com/Jaculabilis/intake.git";
|
||||
inputs.nixpkgs.follows = "nixpkgs-2305";
|
||||
inputs.flake-compat.follows = "flake-compat";
|
||||
};
|
||||
intake-sources = {
|
||||
url = "git+ssh://gitea@git.alogoulogoi.com/Jaculabilis/intake-sources.git";
|
||||
inputs.nixpkgs.follows = "nixpkgs-2305";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, nixos-wsl }: {
|
||||
nixosConfigurations = {
|
||||
catacomb = nixpkgs.lib.nixosSystem {
|
||||
system = "aarch64-linux";
|
||||
modules = [ ./machine/catacomb ];
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs-2305,
|
||||
nixpkgs-2311,
|
||||
flake-compat,
|
||||
nixos-wsl,
|
||||
intake,
|
||||
intake-sources,
|
||||
}@inputs: {
|
||||
nixosModules.beatific = import ./modules/beatific.nix;
|
||||
|
||||
nixosConfigurations = let
|
||||
pinNixpkgs = nixpkgs: { ... }: {
|
||||
nix.registry.nixpkgs.to = { type = "path"; path = nixpkgs; };
|
||||
};
|
||||
empyrean = nixpkgs.lib.nixosSystem {
|
||||
in {
|
||||
backyard = nixpkgs-2311.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [ ./machine/empyrean ];
|
||||
modules = [
|
||||
self.nixosModules.beatific
|
||||
(pinNixpkgs nixpkgs-2311)
|
||||
./machine/backyard
|
||||
];
|
||||
};
|
||||
stagirite = nixpkgs.lib.nixosSystem {
|
||||
catacomb = nixpkgs-2305.lib.nixosSystem {
|
||||
system = "aarch64-linux";
|
||||
modules = [
|
||||
self.nixosModules.beatific
|
||||
(pinNixpkgs nixpkgs-2305)
|
||||
./machine/catacomb
|
||||
];
|
||||
};
|
||||
centroid = nixpkgs-2311.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
self.nixosModules.beatific
|
||||
(pinNixpkgs nixpkgs-2311)
|
||||
./machine/centroid
|
||||
];
|
||||
};
|
||||
empyrean = nixpkgs-2305.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
self.nixosModules.beatific
|
||||
intake.nixosModules.default
|
||||
intake-sources.nixosModules.default
|
||||
(pinNixpkgs nixpkgs-2305)
|
||||
./machine/empyrean
|
||||
];
|
||||
};
|
||||
imperium = nixpkgs-2311.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
self.nixosModules.beatific
|
||||
(pinNixpkgs nixpkgs-2311)
|
||||
({ ... }: {
|
||||
environment.systemPackages = [ nixpkgs-2311.legacyPackages."i686-linux".gperftools ];
|
||||
})
|
||||
./machine/imperium
|
||||
];
|
||||
};
|
||||
stagirite = nixpkgs-2305.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
nixos-wsl.nixosModules.wsl
|
||||
./machine/stagirite
|
||||
];
|
||||
};
|
||||
unfolder = nixpkgs-2305.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
self.nixosModules.beatific
|
||||
(pinNixpkgs nixpkgs-2305)
|
||||
./machine/unfolder
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
tvb = [
|
||||
./nix-on-droid.vagrant.pub
|
||||
./tvb.backyard.pub
|
||||
./tvb.catacomb.pub
|
||||
./tvb.centroid.pub
|
||||
./tvb.empyrean.pub
|
||||
./tvb.imperium.pub
|
||||
./tvb.palamas.pub
|
||||
./tvb.stagirite.pub
|
||||
./tvb.unfolder.pub
|
||||
./tvb.vagrant.pub
|
||||
];
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCzx37PqIaJVWdQs5meVgI4Cg1GRGk6srrix0AUvQeaBS9MOVtJLi+HfnNkcW4GPk9qVlz1E7ciQ7YUw+ny7QbHxcbib2Tawwfk3cx9xiNcN6UI9EzF/rTbNB2Cex8A4sEr5UvoE0BjT5yPaXyrjn8vLksGWq4dlZBM3xeJqe3KP+OxPL0vik3SVGOr/6ZQ7H9cwX5+/p6rCWQuVtwZMcaE6QyXYg5J5FQUaIrFvKbOVklJIkQSbXGzIYQO/QlQC0xWGBapJtGQw/lsQ3YqnFSMkkw8qrKbde07rg8p1FSuqTu+a1ePK+/F4klNel174+39YSobY2/6biPP3Uj/Yhorf4Tw141tIT75e3ebtK5faatQmNOyXcA7LULXK7XemJkZy8PmbNNTeBIKyoI6XQdzk95gpb2C4LEJmV040YMgXhOIiKsHQVgss9FuC+oP5jXWU/JuNXBRHa1IpJjcJhIhg7jnh6ZNZHyK0EpeUs3Zp7usv7mz6CGwb04yvTsWOhZRc+6EoHaHyrNvFPfkPeGsZzxhIbprCyDMtKWsI9GCtztcRhQWBgornUVEs5CurLJBbClQTrZLVv2fn9UnXWPYZTLYL7aFwRIGyKr8ZOOMFxbLOGdeFlqc5TGCP416e8PZvhE+BuDmxiKtQJ/dsQFqVzvOZb2WQRsYRPYvvXbvUw== monitor@isidore
|
|
@ -0,0 +1 @@
|
|||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEpvV9dKUVBlv5VU3LU0XIGTQK/McPf3H31HHD/vINGG nix-on-droid@vagrant
|
|
@ -0,0 +1 @@
|
|||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGYv5vs78+UAeRagopi4BuvmmK1l3zZwQPY3R4rnp7oV tvb@backyard
|
|
@ -0,0 +1 @@
|
|||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDitOuQeddhGh3Zg/fnawTrIdomMhgR6rJchbfAAEUz7JDWyrwZoU0/kMBcn9qZZBFE0MDeUSbQbF+voA7/dwZKB+3GBOurg75KSxtwDLHw4urC5U9VCZnbOrFnl5K51oopduxE7vqZdtTzJztcDVKwJILSFPS2hDC3Zt7+pnB1z0aMOJIMyqfogSk29dxREHO130tbrRWI6bCrAJKXWMFSEx6N1pGoOvOKZu4YVdiDSqTPdSYW4D4ivC5Wtt74rGz8/su5xvZKHgNf/d/hILlg/zhnGzH5gn8HvN5pqRksh2fiteGxDQoXgaRGEb93RLe6KV7XPy60vmI+uE06lsow0C7hLrSWorhLQOuLG1J5JzzF0SmFRUOYQoc6BbOLLVXVBa1VcmpupHMJiw6ldJv9yD410bXd+IwIDS9IkW1MIfvN5j35AvnaJCEHVUSrkEjgqCpkNxNPl7V3h7YRw6F/AljTvgEER91mPUvwfJrC0sMo/+DWNwIbnK+jjioD2szHXz2EpXlVhkMSwey/rNZffQpzFHWsm3Za/+4KxWBUO/2MRz2x1haDvvD37hN2kC5w0DSC6MsJucDVlyEjgDQkVEBKujkBv4fpYLpN4VoqVDYytpgnRTm0QIb+ISStG19Fq1uj3UtHFyWI5d8P3jiev4DTtqCpQo9NWa4zu/mbCw== tvb@catacomb
|
|
@ -0,0 +1 @@
|
|||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC364peKQVWeqFNzhJJkvHumKerKPkczeX2I/e9FFZyL tvb@centroid
|
|
@ -1 +1 @@
|
|||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC1h/6CedtyFIjFTT7M5e0dEKJkhPbCQ1RLhtj/83H//AK6bzRbWfnKzSH0VXpsHjaU/Ipc1Jl2fQ23r8i/QyKHUKK7xPeGcY5J7oIHVggkEKW2n9R27Ml9BriKxx6ltButnwSOVYk7dyNhz93GYTTEF3ydh4X7HP2Cv7rh5fbca3s69GXRjOVGmIuuVbaJiaMmiWhBI4LYtqwpo1zGXMjfNlXcMFw7VA4EG2UpkJkcWeyN/AI3ZS/YybcTQNCAg+Xnk94CVys/b5wTuGWRplDrRlNR00MUWpr94+u/xk+sC4/6vT7je2W4GjA1jTq4XmewTEV4cxOu+l1jtHZBgvHho5X0fOogdN52MkjuaXzByZB/Br5xTkBRv0tDf5haX4HzuBC29yU9rt62SEQRzvZxObCCGDcIYR/1HTgjDZkRuwgO/1RoRh5SvwbptvPwpBMvx25S//ZJESLO++lqxjgRZSr/05YpZ5diffEIGd1J0Jz0NGv4XBPcMBnSMKFmdwOy+5jnBbW2OjPQaPslXHEKYTfOByzCA8LgppkxvmL08GIjxYfEljioHR5by+Z6SjG1VvifMFA6FN/+DN6ZH0LmeOMa5YM1Zl3bx5RaANpnSNvi6rmxkQa1oMaK0l482FvpVkg6o1h9si/AeNTEbiX9ozHdjekfuzBSk6Jfo6xw+Q== tvb@empyrean
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCuAlVTZ4g7x8Fv3YoHn4KRr5GHfylgJjkC6lujti7Fd3JhZ34OB5L/FuCKLo0rv/1qpIcGHk01FMNT/hDcbyBRPN5QG1s7x39Bt8yBVePoJK0+malGkI90z4zV1b5LEjvRhr7+KuOskt3eVbhKcEXiJpDdqOOgqvppmQZOb6jb03+q01rPLzz0S20jUDLRSdnmlcNDv16lMXTX9zgWDeVIVErTvoLAI8RloqKUgienheLJSS6sdEk4AjL2PKldKE6mIOxZWiYSTS9+2ClqV8u3l1UTZ7+DOw8FWASmMYaaBvJRDEUzDKA/iOAjpfPO7WOn+yjRyiT7IFVFoz2XtXwZD0OEQhbgLZtPlhOHh5wn++YNnvzLYd5cYSWVya0FYzVis24hbaGjrwB5tzD0riL2lRzo3ZjktpL7RlCSLfO/2Cb14hLOxZTZZcgdM6Ef/1YatJiEpRQ7FLP45Di3hKc9QEsqQP1BrhhYQOCWwEHAgVXM8W1ncEBXiCnrelegVy0= tvb@empyrean
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHGUvJ7Gd1mN2mF/hy12dizwEw64zn+jT0vFpkhGF07s tvb@imperium
|
|
@ -0,0 +1 @@
|
|||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCom6c/UrhM6KrzDcm8kJGZJ5ugR4wRfsFUhTJ5F4oLNQcNspvqlUfxT4Hjv4xHA5hCjvPYi7JxVWxBsOEmmIs/LAjFXRNw9Kz8m7TCf/lct+JUpf6eCn6a/orhA0OdUv4c9aiH2Dzp4ob3lR6xYvYUOH3LuffqypSXP0k5zCSetROUgTZibEpa0oE2GevcyjQAExpCjx02ZRIGkGOM20CXtm3EJsTzIs6uk4+2F9hB+HMqePFKCzsgOlFfVCNWiKNywLavXo7Gn0O9pWidufXZ9s8nCBiOEzU1n6T8pNQBat4z7G1uKFKKWNDPL6/HNEmCq0JxUuXSSjg8LIk+uqPH49Ubpf8EORON8z8nVFAAqbuI6rdYc7J9DllQ7hb7EBT9w9w+mcz3XH0BsGzJUOMD9r0P96pWOn+I6A9jPmOqoOZDzGpfYS18+zYWET/ohH4U4pABcW4nwGx0Jz7Fj6iQW3tyjOefuXcz+sJoYKo/9FOh44KYf4pgu3hfoMlGC0M= tvb@unfolder
|
|
@ -0,0 +1,58 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
./jellyfin.nix
|
||||
];
|
||||
|
||||
boot.loader.grub = {
|
||||
enable = true;
|
||||
device = "/dev/sda";
|
||||
};
|
||||
|
||||
beatific.hostName = "backyard";
|
||||
beatific.defaults.tvbSync = false;
|
||||
|
||||
# Enable networking
|
||||
networking.networkmanager.enable = true;
|
||||
users.users.tvb.extraGroups = [ "networkmanager" ];
|
||||
|
||||
networking.firewall = {
|
||||
enable = false;
|
||||
};
|
||||
|
||||
#
|
||||
users.users.guest = {
|
||||
group = "guest";
|
||||
description = "gueSSHtbook sshd user";
|
||||
};
|
||||
users.groups.guest = {};
|
||||
systemd.services.guesshd = let
|
||||
nssModulesPath = config.system.nssModules.path;
|
||||
in {
|
||||
enable = false;
|
||||
description = "gueSSHtbook SSH daemon";
|
||||
wantedBy = "multi-user.target";
|
||||
after = [ "network.target" ];
|
||||
stopIfChanged = false;
|
||||
path = [ config.programs.ssh.package pkgs.gawk ];
|
||||
environment.LD_LIBRARY_PATH = nssModulesPath;
|
||||
#restartTriggers = [ config path goes here ];
|
||||
# need keys to exist, see prestart in sshd.nix
|
||||
serviceConfig = {
|
||||
ExecStart = "${config.programs.ssh.package}/bin/sshd -D -f /path/to/config";
|
||||
KillMode = "process";
|
||||
Restart = "always";
|
||||
Type = "simple";
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 2345 ];
|
||||
#
|
||||
|
||||
# This value governs how some stateful data, like databases, are handled
|
||||
# across different versions of NixOS. This should not be changed to a new
|
||||
# release unless the sysadmin has determined that no services would be
|
||||
# adversely affected by changing this.
|
||||
system.stateVersion = "23.05";
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/798089ca-f249-431d-aa08-65909b85a184";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-uuid/5d55f9b7-cde3-403d-9c91-61c4b68c71f9"; }
|
||||
];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||
# still possible to use this option, but it's recommended to use it in conjunction
|
||||
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
# Enable jellyfin
|
||||
services.jellyfin.enable = true;
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts = {
|
||||
# Create a default vhost to deny traffic, so traffic has to actually match a vhost
|
||||
default = {
|
||||
default = true;
|
||||
locations."/".return = "444";
|
||||
};
|
||||
"jellyfin" = {
|
||||
listen = [
|
||||
# Available on the local network (host managed by router)
|
||||
{ addr = "jellyfin.backyard.lan"; port = 80; }
|
||||
# Available by name on beatific (host managed by beatific module)
|
||||
{ addr = "jellyfin.backyard.home"; port = 80; }
|
||||
# Available by port on beatific until I solve DNS for non-NixOS hosts
|
||||
{ addr = "10.22.20.8"; port = 8096; }
|
||||
];
|
||||
locations."/".extraConfig = ''
|
||||
proxy_buffering off;
|
||||
proxy_pass http://localhost:8096/;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
80 # http
|
||||
8096 # jellyfin
|
||||
];
|
||||
|
||||
users.users.tvb.extraGroups = [ "jellyfin" ];
|
||||
}
|
|
@ -1,13 +1,15 @@
|
|||
{ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
beatific = import ../../modules/beatific.nix;
|
||||
in {
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
./fileserver.nix
|
||||
./mirror.nix
|
||||
];
|
||||
|
||||
beatific.hostName = "catacomb";
|
||||
beatific.defaults.tvbSync = true;
|
||||
|
||||
boot = {
|
||||
loader = {
|
||||
# Use the extlinux boot loader. (NixOS wants to enable GRUB by default)
|
||||
|
@ -17,42 +19,26 @@ in {
|
|||
};
|
||||
supportedFilesystems = ["zfs"];
|
||||
zfs.enableUnstable = true;
|
||||
kernelParams = [ "zfs.zfs_dmu_offset_next_sync=0" ];
|
||||
};
|
||||
|
||||
system.stateVersion = "22.11"; # Read the usual warning
|
||||
|
||||
swapDevices = [ { device = "/swap"; size = 1024; } ];
|
||||
|
||||
console.keyMap = "us";
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
environment.systemPackages = with pkgs;
|
||||
let
|
||||
py3-packages = python-packages: with python-packages; [
|
||||
flask
|
||||
];
|
||||
py3-with-packages = python3.withPackages py3-packages;
|
||||
in [
|
||||
wget vim curl git htop bash tmux psmisc man-pages pv lsof
|
||||
zip unzip
|
||||
py3-with-packages
|
||||
usbutils
|
||||
hdparm sdparm smartmontools gptfdisk gnufdisk
|
||||
dosfstools
|
||||
mkpasswd samba
|
||||
tinc_pre
|
||||
#file-rename
|
||||
rsync
|
||||
rclone gnupg
|
||||
environment.systemPackages = with pkgs; [
|
||||
lsof # list open files
|
||||
mkpasswd # used for setting SMB passwords, I think?
|
||||
samba # provides smbpasswd, mostly
|
||||
smartmontools # provides smartctl
|
||||
usbutils # provides lsusb
|
||||
];
|
||||
|
||||
networking = {
|
||||
hostName = "catacomb";
|
||||
hostId = "beeeeee5";
|
||||
hostId = "beeeeee5"; # this must be consistent for ZFS
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowPing = true;
|
||||
allowedTCPPorts = [ 22 139 445 ];
|
||||
allowedTCPPorts = [ 139 445 ];
|
||||
allowedUDPPorts = [ 137 138 ];
|
||||
};
|
||||
};
|
||||
|
@ -72,15 +58,7 @@ in {
|
|||
];
|
||||
};
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
passwordAuthentication = true;
|
||||
};
|
||||
|
||||
services.ntp = {
|
||||
enable = true;
|
||||
servers = ["time.nist.gov"];
|
||||
};
|
||||
services.openssh.settings.PasswordAuthentication = true;
|
||||
|
||||
services.rsyncd.enable = true;
|
||||
|
||||
|
@ -162,22 +140,6 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
services.nebula.networks.beatific = lib.recursiveUpdate beatific.nebula-defaults {
|
||||
enable = true;
|
||||
|
||||
# Network certificate and host credentials
|
||||
ca = "/etc/nebula/beatific/beatific.crt";
|
||||
cert = "/etc/nebula/beatific/catacomb.crt";
|
||||
key = "/etc/nebula/beatific/catacomb.key";
|
||||
|
||||
# Connect to the lighthouse at empyrean
|
||||
# Note that this is a VPN address, not a public address
|
||||
lighthouses = [ beatific.empyrean-vpn-ip ];
|
||||
|
||||
# Map the lighthouse address to its public address
|
||||
staticHostMap = beatific.empyrean-host-map;
|
||||
};
|
||||
|
||||
services.zfs = {
|
||||
autoScrub = {
|
||||
enable = true;
|
||||
|
@ -191,19 +153,14 @@ in {
|
|||
};
|
||||
|
||||
users.users.tvb = {
|
||||
isNormalUser = true;
|
||||
uid = 1001;
|
||||
password = "badpassword";
|
||||
extraGroups = ["wheel" "nas"];
|
||||
openssh.authorizedKeys.keyFiles = [
|
||||
../../keys/tvb.palamas.pub
|
||||
../../keys/tvb.stagirite.pub
|
||||
../../keys/tvb.vagrant.pub
|
||||
../../keys/monitor.isidore.pub
|
||||
../../keys/inquisitor.conduit.pub
|
||||
extraGroups = [ "nas" ];
|
||||
packages = [
|
||||
(pkgs.writeShellScriptBin "yt-dlp" ''
|
||||
exec $HOME/.env/bin/yt-dlp "$@"
|
||||
'')
|
||||
];
|
||||
};
|
||||
#./keys/tvb.empyrean.pub
|
||||
|
||||
users.users.katydid = {
|
||||
isNormalUser = true;
|
||||
|
@ -211,5 +168,4 @@ in {
|
|||
};
|
||||
|
||||
nix.settings.cores = 4;
|
||||
nix.extraOptions = "experimental-features = nix-command flakes";
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ let
|
|||
catacombServerSource = builtins.fetchGit {
|
||||
url = "https://git.alogoulogoi.com/Jaculabilis/catacomb-server.git";
|
||||
ref = "develop-nix";
|
||||
rev = "63574bb39cc777deb56a76548f08789d238fcfec";
|
||||
rev = "3d6fb16948c377f94d030648849f120c8ada3884";
|
||||
};
|
||||
catacombServer = pkgs.callPackage catacombServerSource {};
|
||||
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/backup" =
|
||||
{ device = "catapool/backup";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/home/katydid" =
|
||||
{ device = "catapool/user/katydid";
|
||||
fsType = "zfs";
|
||||
|
@ -28,41 +33,6 @@
|
|||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/backup" =
|
||||
{ device = "catapool/backup";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/home/katydid/audio" =
|
||||
{ device = "catapool/user/katydid/audio";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/home/katydid/doc" =
|
||||
{ device = "catapool/user/katydid/doc";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/home/katydid/image" =
|
||||
{ device = "catapool/user/katydid/image";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/home/katydid/video" =
|
||||
{ device = "catapool/user/katydid/video";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/nas/video" =
|
||||
{ device = "catapool/nas/video";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/nas/doc" =
|
||||
{ device = "catapool/nas/doc";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/nas/image" =
|
||||
{ device = "catapool/nas/image";
|
||||
fsType = "zfs";
|
||||
|
@ -73,11 +43,21 @@
|
|||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/nas/doc" =
|
||||
{ device = "catapool/nas/doc";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/nas/game" =
|
||||
{ device = "catapool/nas/game";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/nas/video" =
|
||||
{ device = "catapool/nas/video";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
swapDevices = [ ];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
# Configure nginx to serve /nas/doc/website/mirror/
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts."mirror.catacomb.home" = {
|
||||
listen = [
|
||||
{ addr = "10.22.20.2"; }
|
||||
# Binding to 10.22.20.2:80 here confuses the empyrean revproxy, even when the revproxy
|
||||
# is configured with the same hostname, and it serves from fileserver.nix instead.
|
||||
# This nonstandard port supports the revproxy use case.
|
||||
{ addr = "10.22.20.2"; port = 7474; }
|
||||
];
|
||||
root = "/nas/doc/website/mirror";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 7474 ];
|
||||
|
||||
users.users.nginx.extraGroups = ["nas"];
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
boot.loader.grub = {
|
||||
efiSupport = true;
|
||||
efiInstallAsRemovable = true;
|
||||
device = "nodev";
|
||||
};
|
||||
|
||||
beatific.hostName = "centroid";
|
||||
beatific.defaults = {
|
||||
tvbSync = false;
|
||||
};
|
||||
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
# To avoid needing an active user session, run a single system instance
|
||||
systemWide = true;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
mpv # cli media player
|
||||
];
|
||||
|
||||
users.users.tvb.extraGroups = [
|
||||
"mopidy"
|
||||
"networkmanager"
|
||||
"pipewire"
|
||||
];
|
||||
|
||||
users.groups.mopidy = {}; # rw group for media directory
|
||||
users.users.mopidy.extraGroups = [
|
||||
"mopidy"
|
||||
"pipewire" # necessary to allow the system service to play sound
|
||||
];
|
||||
services.mopidy = let
|
||||
mopidy-ytdlp = pkgs.callPackage ./mopidy-youtube.nix { };
|
||||
in {
|
||||
enable = true;
|
||||
extensionPackages = with pkgs; [
|
||||
mopidy-jellyfin
|
||||
mopidy-musicbox-webclient
|
||||
# Replace the default mopidy-youtube, which doesn't have yt-dlp or a way to inject it
|
||||
mopidy-ytdlp
|
||||
];
|
||||
configuration = ''
|
||||
[file]
|
||||
media_dirs =
|
||||
/media/music|Music
|
||||
|
||||
[jellyfin]
|
||||
hostname = jellyfin.backyard.lan
|
||||
username = mopidy
|
||||
password = mopidy
|
||||
libraries = Music,Weird Song Halftime
|
||||
album_format = {Name} ({ProductionYear})
|
||||
|
||||
[youtube]
|
||||
youtube_dl_package = yt_dlp
|
||||
'';
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts = {
|
||||
default = {
|
||||
default = true;
|
||||
locations."/".return = "444";
|
||||
};
|
||||
"mopidy.home.ktvb.site" = {
|
||||
listen = [
|
||||
{ addr = "10.22.20.7"; }
|
||||
{ addr = "centroid.lan"; }
|
||||
];
|
||||
locations."/" = {
|
||||
proxyWebsockets = true;
|
||||
proxyPass = "http://localhost:6680";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
|
||||
system.stateVersion = "23.11";
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/a08e9b3c-8ac7-433e-bf2c-6da234a2fb4a";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/5D60-DD0E";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-uuid/6dce2950-f8dd-49eb-b4d3-fdcf06cf920b"; }
|
||||
];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||
# still possible to use this option, but it's recommended to use it in conjunction
|
||||
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
|
||||
# networking.interfaces.wlp0s20f0u1.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
{ lib
|
||||
, fetchFromGitHub
|
||||
, python3
|
||||
, mopidy
|
||||
}:
|
||||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "mopidy-youtube";
|
||||
version = "3.6";
|
||||
format = "setuptools";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "natumbri";
|
||||
repo = pname;
|
||||
rev = "refs/tags/v${version}";
|
||||
hash = "sha256-Mp8eCVNGokJRwmYiZYCYRwV1QVDV02Uqfh6fGcPgJss=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with python3.pkgs; [
|
||||
beautifulsoup4
|
||||
cachetools
|
||||
pykka
|
||||
requests
|
||||
youtube-dl # this no longer works
|
||||
yt-dlp # <- added
|
||||
ytmusicapi
|
||||
] ++ [
|
||||
mopidy
|
||||
];
|
||||
|
||||
nativeCheckInputs = with python3.pkgs; [
|
||||
vcrpy
|
||||
pytestCheckHook
|
||||
];
|
||||
|
||||
disabledTests = [
|
||||
# Test requires a YouTube API key
|
||||
"test_get_default_config"
|
||||
];
|
||||
|
||||
disabledTestPaths = [
|
||||
# Disable tests which interact with Youtube
|
||||
"tests/test_api.py"
|
||||
"tests/test_backend.py"
|
||||
"tests/test_youtube.py"
|
||||
];
|
||||
|
||||
pythonImportsCheck = [
|
||||
"mopidy_youtube"
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Mopidy extension for playing music from YouTube";
|
||||
homepage = "https://github.com/natumbri/mopidy-youtube";
|
||||
license = licenses.asl20;
|
||||
maintainers = with maintainers; [ ];
|
||||
};
|
||||
}
|
|
@ -9,16 +9,18 @@
|
|||
[ # Include the results of the hardware scan.
|
||||
./hardware-configuration.nix
|
||||
#./amanuensis.nix
|
||||
#./redstring.nix
|
||||
./catacomb.nix
|
||||
./gitea.nix
|
||||
./inquisitor.nix
|
||||
./sync-pipeline.nix
|
||||
];
|
||||
|
||||
beatific.hostName = "empyrean";
|
||||
beatific.isLighthouse = true;
|
||||
beatific.defaults.tvbSync = true;
|
||||
|
||||
# Use the GRUB 2 boot loader.
|
||||
boot.loader.grub = {
|
||||
enable = true;
|
||||
version = 2;
|
||||
device = "/dev/xvda";
|
||||
extraConfig = "serial --unit=0 --speed=115200 ; terminal_input serial console ; terminal_output serial console";
|
||||
};
|
||||
|
@ -27,42 +29,20 @@
|
|||
nix = {
|
||||
package = pkgs.nixFlakes;
|
||||
settings.max-jobs = 2;
|
||||
extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
};
|
||||
|
||||
swapDevices = [ { device = "/swap"; size = 1024; } ];
|
||||
|
||||
networking.hostName = "empyrean";
|
||||
|
||||
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
|
||||
# Per-interface useDHCP will be mandatory in the future, so this generated config
|
||||
# replicates the default behaviour.
|
||||
networking.useDHCP = false;
|
||||
networking.interfaces.eth0.useDHCP = true;
|
||||
|
||||
# Configure network proxy if necessary
|
||||
# networking.proxy.default = "http://user:password@proxy:port/";
|
||||
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
|
||||
|
||||
# Select internationalisation properties.
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
console = {
|
||||
font = "Lat2-Terminus16";
|
||||
keyMap = "us";
|
||||
};
|
||||
|
||||
# Set your time zone.
|
||||
time.timeZone = "UTC";
|
||||
|
||||
# List packages installed in system profile. To search, run:
|
||||
# $ nix search wget
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim htop git tinc_pre python3
|
||||
tinc_pre
|
||||
gitea
|
||||
];
|
||||
environment.variables.EDITOR = "vim";
|
||||
|
||||
services.nginx = let
|
||||
static-site = srv-dir: {
|
||||
|
@ -74,26 +54,36 @@
|
|||
index index.html;
|
||||
'';
|
||||
};
|
||||
service-stub = {
|
||||
rejectSSL = true;
|
||||
locations."/".return = "403";
|
||||
};
|
||||
in {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts = {
|
||||
# Static pages
|
||||
"home.ktvb.site" = static-site "home.ktvb.site";
|
||||
"wedding.ktvb.site" = static-site "wedding.ktvb.site";
|
||||
"www.ktvb.site" = static-site "www.ktvb.site";
|
||||
"mirror.alogoulogoi.com" = static-site "mirror.alogoulogoi.com";
|
||||
"www.alogoulogoi.com" = static-site "www";
|
||||
newtab = {
|
||||
listen = [ { addr = "10.22.20.1"; port = 80; } ];
|
||||
root = "/srv/newtab/";
|
||||
"www.alogoulogoi.com" = static-site "www.alogoulogoi.com";
|
||||
"ecumene.alogoulogoi.com" = static-site "ecumene.alogoulogoi.com";
|
||||
# Home service stub domains
|
||||
"mopidy.home.ktvb.site" = service-stub;
|
||||
"jellyfin.home.ktvb.site" = service-stub;
|
||||
# mirror revproxy
|
||||
"mirror.alogoulogoi.com" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
extraConfig = ''
|
||||
access_log /var/log/nginx/access_newtab.log;
|
||||
index index.html;
|
||||
access_log /var/log/nginx/access_mirror.alogoulogoi.com.log;
|
||||
'';
|
||||
locations."/".proxyPass = "http://mirror.catacomb.home:7474/";
|
||||
};
|
||||
# Deny all other subdomains
|
||||
"alogoulogoi.com" = {
|
||||
default = true;
|
||||
rejectSSL = true;
|
||||
locations."/".return = "444";
|
||||
};
|
||||
};
|
||||
|
@ -103,20 +93,9 @@
|
|||
acceptTerms = true;
|
||||
};
|
||||
|
||||
services.gitolite = {
|
||||
enable = true;
|
||||
adminPubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDkSvOcY0eFuYqewc73MNHGP/Owzfnt+BZDSOCwr4h+gJenOBmXol695sRKdIw8phgshb6LsNyWeEAr3YISwzjdOvWNKpSsdyH/79VFIffC+/RBhPFhIPHn1zpHIwgthXji8FMmnO6B1bhJvbJxD5bUqhdBLnUeMhNgUkDj4Qi42S8yK1VZkgWRuPOTGqlzkODEdzG6OST7ndL58jEQaK8R2KRC2cZfrjingmPL+ORyf1/lGwyF6MEAmbQuE6UdspMs8FWt2e8jQJS+ZQ8dl+NDFrC1QfPRFpBJWnQceBcfAVZTtDaJpRhc4ClZstBy/bVRjiKeQiNv5NasjKRvvIvot4+LXmBKrXJs81enExtMSHMPuqPRlyVZLMMCVmdLDP/HUYOASDzlUhV/v5Wp0jjY4Wy0IWC7nm7P8EKsp1ZofwU6rJ9XPLpQJt7UUURX71h1FMaqi+lylW6xkD3LqD8oT5Bdp+Vs0bUbPQVRw1Fenjc6G1URU94GOAggyNgsWms= root@empyrean";
|
||||
};
|
||||
|
||||
services.ntp = {
|
||||
enable = true;
|
||||
servers = ["time.nist.gov"];
|
||||
};
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
passwordAuthentication = false;
|
||||
permitRootLogin = "prohibit-password";
|
||||
settings.PasswordAuthentication = false;
|
||||
settings.PermitRootLogin = "prohibit-password";
|
||||
};
|
||||
|
||||
services.tinc.networks.beatific = {
|
||||
|
@ -124,36 +103,15 @@
|
|||
chroot = false;
|
||||
};
|
||||
|
||||
services.nebula.networks.beatific = {
|
||||
enable = true;
|
||||
|
||||
# Network certificate and host credentials
|
||||
ca = "/etc/nebula/beatific/beatific.crt";
|
||||
cert = "/etc/nebula/beatific/empyrean.crt";
|
||||
key = "/etc/nebula/beatific/empyrean.key";
|
||||
|
||||
# This host has a well-known IP at its VPS host, so it can function as a lighthouse/entry node
|
||||
isLighthouse = true;
|
||||
|
||||
# Listen to connection requests from the public Internet
|
||||
listen.port = 4242;
|
||||
listen.host = "vpn.alogoulogoi.com";
|
||||
|
||||
# Don't filter anything at the VPN level
|
||||
firewall.outbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
||||
firewall.inbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
||||
|
||||
settings = {
|
||||
# Enable UDP holepunching both ways, which allows nodes to establish more direct connections with each other
|
||||
punchy = { punch = true; response = true; };
|
||||
};
|
||||
services.intake = {
|
||||
listen = { addr = "10.22.20.1"; };
|
||||
users.tvb.enable = true;
|
||||
users.tvb.extraPackages = [ pkgs.intakeSources pkgs.openssh ];
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
allowPing = true;
|
||||
allowedTCPPorts = [
|
||||
22 # ssh
|
||||
80 # http
|
||||
443 # https
|
||||
655 # tinc
|
||||
|
@ -163,24 +121,13 @@
|
|||
];
|
||||
};
|
||||
|
||||
users.users.tvb = {
|
||||
isNormalUser = true;
|
||||
group = "tvb";
|
||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||
openssh.authorizedKeys.keyFiles = [
|
||||
../../keys/tvb.palamas.pub
|
||||
../../keys/tvb.stagirite.pub
|
||||
];
|
||||
};
|
||||
users.groups.tvb = {};
|
||||
|
||||
# This value determines the NixOS release from which the default
|
||||
# settings for stateful data, like file locations and database versions
|
||||
# on your system were taken. It‘s perfectly fine and recommended to leave
|
||||
# this value at the release version of the first install of this system.
|
||||
# Before changing this value read the documentation for this option
|
||||
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||
system.stateVersion = "20.03"; # Did you read the comment?
|
||||
system.stateVersion = "23.05"; # Did you read the comment?
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,7 @@
|
|||
{
|
||||
# Gitea configuration
|
||||
services.gitea = {
|
||||
# Enable Gitea and configure for reverse proxy
|
||||
enable = true;
|
||||
httpAddress = "127.0.0.1";
|
||||
httpPort = 3300;
|
||||
domain = "git.alogoulogoi.com";
|
||||
rootUrl = "https://git.alogoulogoi.com/";
|
||||
|
||||
#useWizard = true; # Needed for first-time building
|
||||
|
||||
|
@ -22,6 +17,13 @@
|
|||
interval = "weekly";
|
||||
};
|
||||
settings = {
|
||||
"server" = {
|
||||
# Configuration for reverse proxy
|
||||
ROOT_URL = "https://git.alogoulogoi.com/";
|
||||
HTTP_ADDR = "127.0.0.1";
|
||||
HTTP_PORT = 3300;
|
||||
DOMAIN = "git.alogoulogoi.com";
|
||||
};
|
||||
"repository" = {
|
||||
DEFAULT_PRIVATE = true;
|
||||
};
|
||||
|
@ -37,10 +39,13 @@
|
|||
"security" = {
|
||||
INSTALL_LOCK = true;
|
||||
};
|
||||
"session" = {
|
||||
SESSION_LIFE_TIME = 86400 * 7; # 1 week
|
||||
};
|
||||
"picture" = {
|
||||
DISABLE_GRAVATAR = true;
|
||||
};
|
||||
"cron.archive_cleanup".ENABLED = false;
|
||||
#"cron.archive_cleanup".ENABLED = false; # TODO: figure out why this was enabled
|
||||
"cron.sync_external_users".ENABLED = false;
|
||||
log.LEVEL = "Info";
|
||||
# Private server
|
||||
|
@ -66,5 +71,8 @@
|
|||
proxy_pass http://localhost:3300/;
|
||||
'';
|
||||
};
|
||||
|
||||
# Give tvb group access to gitea config
|
||||
users.users.tvb.extraGroups = [ "gitea" ];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
{pkgs, ...}:
|
||||
|
||||
let
|
||||
# Import the inquisitor package and build it
|
||||
inquisitorSource = pkgs.fetchFromGitHub {
|
||||
owner = "Jaculabilis";
|
||||
repo = "Inquisitor";
|
||||
rev = "addcb4f1a56c878b58f2e1c38dfd485761b31306";
|
||||
sha256 = "0jjl92nf1y40acdly1kls0mppcadvmgbfr6qwczxni1f1zphw3as";
|
||||
};
|
||||
inquisitor = pkgs.callPackage inquisitorSource { inherit pkgs; };
|
||||
|
||||
# Define the inquisitor data directory
|
||||
inquisiDir = "/var/lib/inquisitor";
|
||||
|
||||
# Define an scp helper for executing in cron jobs
|
||||
scp-helper = pkgs.writeShellScriptBin "scp-helper" ''
|
||||
${pkgs.openssh}/bin/scp -i ${inquisiDir}/inquisitor.key -oStrictHostKeyChecking=no "$@"
|
||||
'';
|
||||
|
||||
# Define the inquisitor service user
|
||||
inquisitorUser = {
|
||||
name = "inquisitor";
|
||||
group = "inquisitor";
|
||||
description = "Inquisitor service user";
|
||||
isSystemUser = true;
|
||||
shell = pkgs.bashInteractive;
|
||||
packages = [ inquisitor pkgs.cron ];
|
||||
};
|
||||
|
||||
# Create the inquisitor config file in the nix store, pointing to /var/lib/
|
||||
inquisitorConfig = pkgs.writeTextFile {
|
||||
name = "inquisitor.conf";
|
||||
text = ''
|
||||
DataPath = ${inquisiDir}/data/
|
||||
SourcePath = ${inquisiDir}/sources/
|
||||
CachePath = ${inquisiDir}/cache/
|
||||
Verbose = false
|
||||
LogFile = ${inquisiDir}/inquisitor.log
|
||||
'';
|
||||
};
|
||||
|
||||
# Create a setup script to ensure the service directory state
|
||||
inquisitorSetup = pkgs.writeShellScriptBin "inquisitor-setup.sh" ''
|
||||
# Ensure the service directory and the default source directory
|
||||
${pkgs.coreutils}/bin/mkdir -p ${inquisiDir}/data/inquisitor/
|
||||
${pkgs.coreutils}/bin/mkdir -p ${inquisiDir}/sources/
|
||||
${pkgs.coreutils}/bin/mkdir -p ${inquisiDir}/cache/
|
||||
if [ ! -f ${inquisiDir}/data/inquisitor/state ]; then
|
||||
${pkgs.coreutils}/bin/echo "{}" > ${inquisiDir}/data/inquisitor/state
|
||||
fi
|
||||
|
||||
# Ensure the service owns the folders
|
||||
chown -R ${inquisitorUser.name} ${inquisiDir}
|
||||
|
||||
# Ensure the scp helper is present
|
||||
if [ -f ${inquisiDir}/scp-helper ]; then
|
||||
rm ${inquisiDir}/scp-helper
|
||||
fi
|
||||
ln -s -t ${inquisiDir} ${scp-helper}/bin/scp-helper
|
||||
'';
|
||||
|
||||
# Create a run script for the server
|
||||
inquisitorRun = pkgs.writeShellScriptBin "inquisitor-run.sh" ''
|
||||
cd ${inquisiDir}
|
||||
${inquisitor}/bin/gunicorn \
|
||||
--bind=localhost:24133 \
|
||||
--workers=4 \
|
||||
--timeout 120 \
|
||||
--log-level debug \
|
||||
"inquisitor.app:wsgi()"
|
||||
'';
|
||||
|
||||
# Create a wrapper to execute the cli as the service user
|
||||
inquisitorWrapper = pkgs.writeShellScriptBin "inq" ''
|
||||
sudo --user=inquisitor ${inquisitor}/bin/inquisitor "$@"
|
||||
'';
|
||||
in
|
||||
{
|
||||
users.users.inquisitor = inquisitorUser;
|
||||
users.groups.inquisitor = {};
|
||||
|
||||
# Link the config in /etc to avoid envvar shenanigans
|
||||
environment.etc."inquisitor.conf".source = "${inquisitorConfig}";
|
||||
|
||||
# Give all users the inq wrapper
|
||||
environment.systemPackages = [ inquisitorWrapper ];
|
||||
|
||||
# Allow the sudo in the cli wrapper without password
|
||||
security.sudo.extraRules = [{
|
||||
commands = [{
|
||||
command = "${inquisitor}/bin/inquisitor";
|
||||
options = [ "NOPASSWD" ];
|
||||
}];
|
||||
runAs = "${inquisitorUser.name}";
|
||||
groups = [ "users" ];
|
||||
}];
|
||||
|
||||
# Run the setup script on activation
|
||||
system.activationScripts.inquisitorSetup = "${inquisitorSetup}/bin/inquisitor-setup.sh";
|
||||
|
||||
# Set up the inquisitor service
|
||||
systemd.services.inquisitor =
|
||||
{
|
||||
description = "Inquisitor server";
|
||||
script = "${inquisitorRun}/bin/inquisitor-run.sh";
|
||||
serviceConfig = {
|
||||
User = "${inquisitorUser.name}";
|
||||
Type = "simple";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# Set up nginx to reverse proxy from the beatific url to the inq server
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts.inquisitorHost = {
|
||||
listen = [ { addr = "10.22.20.1"; port = 80; } ];
|
||||
locations."/".extraConfig = ''
|
||||
access_log /var/log/nginx/access.inquisitor.log;
|
||||
proxy_buffering off;
|
||||
proxy_pass http://localhost:24133/;
|
||||
'';
|
||||
};
|
||||
|
||||
# Allow nginx through the firewall
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [
|
||||
80 # http
|
||||
443 # https
|
||||
];
|
||||
};
|
||||
|
||||
# Enable cron, but don't set up any system cron jobs
|
||||
# Inquisitor updates will be managed manually
|
||||
services.cron.enable = true;
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
# redstring server module
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
# Import package
|
||||
redstringSource = builtins.fetchGit {
|
||||
url = "https://git.alogoulogoi.com/Jaculabilis/redstring.git";
|
||||
ref = "master";
|
||||
rev = "91dd353ad1d48118452a949b15e100b3035bf297";
|
||||
};
|
||||
redstring = pkgs.callPackage redstringSource {};
|
||||
|
||||
# Define the data directory
|
||||
redstringDir = "/var/lib/redstring/";
|
||||
redstringData = "${redstringDir}docs/";
|
||||
|
||||
# Define the service user
|
||||
redstringUser = {
|
||||
name = "redstring";
|
||||
description = "redstring service user";
|
||||
group = "redstring";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
# Create the public server config file in the nix store
|
||||
publicConfigAttrs = {
|
||||
root = redstringData;
|
||||
edit = false;
|
||||
};
|
||||
publicConfig = pkgs.writeTextFile { name = "redstring-config-external.json"; text = (builtins.toJSON publicConfigAttrs); };
|
||||
|
||||
# Create the private server config file in the nix store
|
||||
privateConfig = pkgs.writeTextFile {
|
||||
name = "redstring-config-internal.json";
|
||||
text = (builtins.toJSON {
|
||||
root = redstringData;
|
||||
edit = true;
|
||||
});
|
||||
};
|
||||
|
||||
# Create a setup script to ensure the data directory exists
|
||||
redstringSetup = pkgs.writeShellScriptBin "redstring-setup.sh" ''
|
||||
# Ensure the service directory
|
||||
${pkgs.coreutils}/bin/mkdir -p ${redstringData}
|
||||
|
||||
# Ensure ownership
|
||||
chown -R ${redstringUser.name} ${redstringDir}
|
||||
chmod 700 ${redstringDir}
|
||||
'';
|
||||
|
||||
# Create a run script for the public server
|
||||
publicRun = pkgs.writeShellScriptBin "redstring-run-external.sh" ''
|
||||
cd ${redstringDir}
|
||||
${redstring}/bin/gunicorn \
|
||||
--bind=localhost:24144 \
|
||||
--workers=3 \
|
||||
--log-level debug \
|
||||
--env REDSTRING_CONFIG=${publicConfig} \
|
||||
"redstring.server:wsgi()"
|
||||
'';
|
||||
|
||||
# Create a run script for the private server
|
||||
privateRun = pkgs.writeShellScriptBin "redstring-run-internal.sh" ''
|
||||
cd ${redstringDir};
|
||||
${redstring}/bin/gunicorn \
|
||||
--bind=10.7.3.1:24145 \
|
||||
--workers=3 \
|
||||
--log-level debug \
|
||||
--env REDSTRING_CONFIG=${privateConfig} \
|
||||
"redstring.server:wsgi()"
|
||||
'';
|
||||
in
|
||||
{
|
||||
users.users.redstring = redstringUser;
|
||||
users.groups.redstring = {};
|
||||
|
||||
# Run the setup script on activation
|
||||
system.activationScripts.redstringSetup = "${redstringSetup}/bin/redstring-setup.sh";
|
||||
|
||||
# Set up the public redstring service
|
||||
systemd.services."redstring-public" =
|
||||
{
|
||||
description = "redstring public read-only server";
|
||||
script = "${publicRun}/bin/redstring-run-external.sh";
|
||||
serviceConfig = {
|
||||
User = "${redstringUser.name}";
|
||||
Type = "simple";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# Set up the private redstring service
|
||||
systemd.services."redstring-private" =
|
||||
{
|
||||
description = "redstring private editable server";
|
||||
script = "${privateRun}/bin/redstring-run-internal.sh";
|
||||
serviceConfig = {
|
||||
User = redstringUser.name;
|
||||
Type = "simple";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# Configure nginx to forward to the public server at the docs subdomain
|
||||
services.nginx.virtualHosts."docs.alogoulogoi.com" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
extraConfig = ''
|
||||
access_log /var/log/nginx/access.docs.log;
|
||||
'';
|
||||
locations."/".proxyPass = "http://localhost:24144";
|
||||
};
|
||||
|
||||
# Open the firewall to the private server's port
|
||||
networking.firewall.allowedTCPPorts = [ 24145 ];
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
# exiftool config and script based on that of @numinit
|
||||
|
||||
let
|
||||
# An exiftool config that adds the OriginTimestamp property containing the best guess for file creation time
|
||||
exiftool-config = pkgs.writeText "exiftool.config" ''
|
||||
%Image::ExifTool::UserDefined = (
|
||||
'Image::ExifTool::Composite' => {
|
||||
OriginTimestamp => {
|
||||
Desire => {
|
||||
0 => 'CreateDate',
|
||||
1 => 'DateTimeOriginal',
|
||||
2 => 'FileModifyDate'
|
||||
},
|
||||
ValueConv => '$val[0] || $val[1] || $val[2] || undef',
|
||||
PrintConv => '$self->ConvertDateTime($val)',
|
||||
PrintConvInv => '$self->InverseDateTime($val)'
|
||||
}
|
||||
}
|
||||
)
|
||||
'';
|
||||
|
||||
# A tool to use `find` and `exiftool` to sort images into YMD folders
|
||||
sibd = pkgs.writeShellScriptBin "sort-images-by-date" ''
|
||||
set -euo pipefail
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "Usage: $0 [prefix] [src] [dest] [exiftool args...]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
prefix="$1"
|
||||
src="$2"
|
||||
dest="$3"
|
||||
# Remove $1, $2, $3 from $@ so the remainder can be passed to exiftool
|
||||
shift; shift; shift
|
||||
|
||||
# This find expression matches .jpg/.png modified 14+ days ago.
|
||||
# The -not (-name -prune) expressions exclude directories from the results by name.
|
||||
# The exiftool command will move matched files to $dest/$prefix/year/month/day/filename.ext.
|
||||
# -config loads the config defined above, which adds the OriginTimestamp composite property
|
||||
# -filename tells exiftool to move each file to a new filename, $OriginTimestamp
|
||||
# -d defines how the timestamp will be converted to a string, which ends up handling the pathing
|
||||
${pkgs.findutils}/bin/find $src \
|
||||
-not \( -name FalseKnees -prune \) \
|
||||
-not \( -name Background -prune \) \
|
||||
-type f \
|
||||
-mtime +14 \
|
||||
\( -name "*.jpg" -or -name "*.png" \) \
|
||||
-exec ${pkgs.exiftool}/bin/exiftool \
|
||||
-config ${exiftool-config} \
|
||||
-api largefilesupport=1 \
|
||||
-progress \
|
||||
-filename'<OriginTimestamp' \
|
||||
-d "''${dest}/''${prefix}/%Y-%m-%d/%%f%%-c.%%le" \
|
||||
"$@" \
|
||||
{} +
|
||||
'';
|
||||
|
||||
# Script for cron jobs that sends output to journalctl -t sync-pipeline
|
||||
sibd-cron = prefix: src: dest: pkgs.writeShellScript "sibd-cron" ''
|
||||
${pkgs.systemd}/bin/systemd-cat -t sync-pipeline ${sibd}/bin/sort-images-by-date ${prefix} ${src} ${dest}
|
||||
'';
|
||||
in {
|
||||
environment.systemPackages = [ sibd ];
|
||||
|
||||
services.cron = {
|
||||
enable = true;
|
||||
systemCronJobs = [
|
||||
"0 0 * * 1 tvb ${sibd-cron "nokia" "/home/tvb/phone-sync/DCIM" "/home/tvb/phone-sync/staging"}"
|
||||
"0 0 * * 1 tvb ${sibd-cron "nokia" "/home/tvb/phone-sync/Pictures" "/home/tvb/phone-sync/staging"}"
|
||||
];
|
||||
};
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
beatific.hostName = "imperium";
|
||||
|
||||
# Use the systemd-boot EFI boot loader.
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
time.timeZone = "America/Los_Angeles";
|
||||
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
displayManager.gdm.enable = true;
|
||||
desktopManager.gnome.enable = true;
|
||||
|
||||
# keyboard
|
||||
layout = "us";
|
||||
xkbVariant = "";
|
||||
};
|
||||
|
||||
# Enable sound with pipewire.
|
||||
sound.enable = true;
|
||||
hardware.pulseaudio.enable = false;
|
||||
security.rtkit.enable = true;
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
|
||||
# This seems to be sufficient to autodetect the printing functionality of HP OfficeJet 6950
|
||||
services.printing.enable = true;
|
||||
services.printing.drivers = [ pkgs.hplip ];
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
nssmdns = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
users.users.tvb = {
|
||||
extraGroups = [ "networkmanager" ];
|
||||
};
|
||||
|
||||
# Configs needed to run TF2 on integrated graphics
|
||||
programs.steam.enable = true;
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
services.xserver.videoDrivers = [ "i915" ];
|
||||
hardware.opengl.enable = true;
|
||||
hardware.opengl.driSupport32Bit = true;
|
||||
|
||||
beatific.extraPrograms = true;
|
||||
environment.systemPackages = with pkgs; [
|
||||
comic-mono
|
||||
firefox
|
||||
gnome.gnome-terminal
|
||||
libreoffice
|
||||
mpv
|
||||
obsidian
|
||||
unzip
|
||||
];
|
||||
|
||||
networking.firewall = {
|
||||
enable = false;
|
||||
};
|
||||
|
||||
# This value governs how some stateful data, like databases, are handled
|
||||
# across different versions of NixOS. This should not be changed to a new
|
||||
# release unless the sysadmin has determined that no services would be
|
||||
# adversely affected by changing this.
|
||||
system.stateVersion = "23.11";
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/75addc56-2a0d-431e-a0c5-f6ee0e370e61";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/610F-1EB7";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-uuid/cc464bb4-e1c8-46c0-adbb-ea1a3cfa5b03"; }
|
||||
];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||
# still possible to use this option, but it's recommended to use it in conjunction
|
||||
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
|
@ -16,9 +16,10 @@ in
|
|||
startMenuLaunchers = false;
|
||||
};
|
||||
|
||||
system.stateVersion = "21.11";
|
||||
#system.stateVersion = "21.11";
|
||||
|
||||
networking.hostName = "stagirite";
|
||||
beatific.defaults.tvbSync = false;
|
||||
|
||||
fileSystems.winssh = {
|
||||
device = "C:/Users/tvb/.ssh";
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
beatific.hostName = "unfolder";
|
||||
beatific.extraPrograms = true;
|
||||
|
||||
# Bootloader.
|
||||
boot.loader.grub = {
|
||||
enable = true;
|
||||
device = "/dev/sda";
|
||||
};
|
||||
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
# Override time zone to PST
|
||||
time.timeZone = "America/Los_Angeles";
|
||||
|
||||
# Enable Gnome because it has a virtual keyboard for tablet mode
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
displayManager.gdm.enable = true;
|
||||
desktopManager.gnome.enable = true;
|
||||
|
||||
# keymap configuration
|
||||
layout = "us";
|
||||
xkbVariant = "";
|
||||
};
|
||||
|
||||
# Enable sound with pipewire.
|
||||
sound.enable = true;
|
||||
hardware.pulseaudio.enable = false;
|
||||
security.rtkit.enable = true;
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
|
||||
systemd.user.services.yoga-rotate = {
|
||||
enable = false; # TODO
|
||||
description = "ThinkPad Yoga display rotation";
|
||||
#wantedBy = ["multi-user.target"];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
#requires = ["display-manager.service"];
|
||||
partOf = [ "graphical-session.target" ];
|
||||
#after = ["display-manager.service"];
|
||||
path = [ pkgs.gnome-randr ];
|
||||
serviceConfig = {
|
||||
#Type = "simple";
|
||||
ExecStart = "${pkgs.python3}/bin/python /home/tvb/rotate.py";
|
||||
#KillMode = "process";
|
||||
#User = "tvb";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
};
|
||||
#environment = {
|
||||
# DISPLAY = ":0";
|
||||
# XAUTHORITY = "/home/tvb/.Xauthority";
|
||||
#};
|
||||
};
|
||||
|
||||
users.users.tvb = {
|
||||
extraGroups = [ "networkmanager" ];
|
||||
packages = with pkgs; [
|
||||
gnome-randr python3
|
||||
];
|
||||
};
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
environment.systemPackages = with pkgs; [
|
||||
comic-mono
|
||||
firefox
|
||||
gnome.gnome-terminal
|
||||
libreoffice
|
||||
obsidian
|
||||
mpv
|
||||
];
|
||||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# This seems to be sufficient to autodetect the printing functionality of HP OfficeJet 6950
|
||||
services.printing.enable = true;
|
||||
services.printing.drivers = [ pkgs.hplip ];
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
nssmdns = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
# This value governs how some stateful data, like databases, are handled
|
||||
# across different versions of NixOS. This should not be changed to a new
|
||||
# release unless the sysadmin has determined that no services would be
|
||||
# adversely affected by changing this.
|
||||
system.stateVersion = "22.11";
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/3a4363d6-c437-45ab-9f35-6831eb4a2cd8";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-uuid/4a083b38-322e-4d35-9877-a8dc1cda21d5"; }
|
||||
];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||
# still possible to use this option, but it's recommended to use it in conjunction
|
||||
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
# networking.interfaces.wlp4s0.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
beatific = ''
|
||||
____ ______ _______ _____ ______ _____ ______ ./|,,/|
|
||||
| _ \| ____| /\ |__ __|_ _| ____|_ _|/ ____/ < o o|
|
||||
| |_) | |__ / \ | | | | | |__ | | | | <\ ( |
|
||||
| _ <| __| / /\ \ | | | | | __| | | | | <\\ |\ |
|
||||
| |_) | |____/ ____ \ | | _| |_| | _| |_| |___<\\\ |(__)
|
||||
|____/|_____/_/ \_\|_| |_____|_| |_____|\_____|\\ |
|
||||
'';
|
||||
|
||||
backyard = ''
|
||||
____ ______ _ ____ __ _____ _____ ./|,,/|
|
||||
| _ \ /\ / ____/| | / /\ \ / / /\ | __ \| __ \ < o o|
|
||||
| |_) | / \ | | | |/ / \ \ / / / \ | |__) | | | |</ ( |
|
||||
| _ < / /\ \| | | < \ V / / /\ \ | _ /| | | |// |\ |
|
||||
| |_) / ____ | |____ | |\ \ | | / ____ \| | \ \| |__| |// |(__)
|
||||
|____/_/ \_\_____\|_| \_\ |_|/_/ \_|_| \_|_____//// |
|
||||
'';
|
||||
|
||||
catacomb = ''
|
||||
______ _______ ______ ____ __ __ ____ ./|,,/|
|
||||
/ ____/ /\ |__ __| /\ / ____// __ \| \ / | _ \ < o o|
|
||||
| | / \ | | / \ | | | | | | . \/ . | |_) | ( |
|
||||
| | / /\ \ | | / /\ \| | | | | | |\ /| | _ <\\ |\ |
|
||||
| |____ / ____ \ | | / ____ | |__ _| |__| | | \/ | | |_) |\ |(__)
|
||||
\_____/_/ \_\|_|/_/ \_\_____\\____/|_| |_|____/\\ |
|
||||
'';
|
||||
|
||||
empyrean = ''
|
||||
______ __ __ _______ _______ ______ _ _ ./|,,/|
|
||||
| ____| \ / | __ \ \ / | __ \| ____| /\ | \ | | < o o|
|
||||
| |__ | . \/ . | |__) \ \ / /| |__) | |__ / \ | \| |</ ( |
|
||||
| __| | |\ /| | ___/ \ V / | _ /| __| / /\ \ | . ' |// |\ |
|
||||
| |____| | \/ | | | | | | | \ \| |____ / ____ \| |\ |// |(__)
|
||||
|______|_| |_|_| |_| |_| \_|______/_/ \_|_| \_|// |
|
||||
'';
|
||||
|
||||
unfolder = ''
|
||||
_ _ _ _ ______ ____ _ _____ ______ _____ ./|,,/|
|
||||
| | | | \ | | ____|/ __ \| | | __ \| ____| __ \ < o o|
|
||||
| | | | \| | |__ | | | | | | | | | |__ | |__) |\ ( |
|
||||
| | | | . ' | __| | | | | | | | | | __| | _ /\\ |\ |
|
||||
| |__| | |\ | | | |__| | |___| |__| | |____| | \ \\\ |(__)
|
||||
\____/|_| \_|_| \____/|_____|_____/|______|_| <\_\\ |
|
||||
'';
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
# Set the title bar to user@host: pwd
|
||||
_TITLE_BAR="\u@\h: \w"
|
||||
_SET_TITLE_BAR="\[\e]0;$_TITLE_BAR\a\]"
|
||||
# Shorten $HOME to ~ in PWD
|
||||
_pwd_home () {
|
||||
if [[ "$PWD" =~ ^"$HOME"(/|$) ]]; then
|
||||
echo "~${PWD#$HOME}"
|
||||
else
|
||||
echo $PWD
|
||||
fi
|
||||
}
|
||||
# Shorten path dir names
|
||||
_pwd () {
|
||||
DIR=$(_pwd_home)
|
||||
[ "$DIR" != "/" ] && [ "$DIR" != "~" ] && printf '%s/' $(dirname "$DIR" | tr / '\n' | cut -c-1)
|
||||
printf "$(basename "$DIR")"
|
||||
}
|
||||
_DIR='$(_pwd)'
|
||||
# Color codes
|
||||
_GREEN="\[\033[32;1m\]"
|
||||
_DIM="\[\e[32;2m\]"
|
||||
_OLIVE="\[\e[33;2m\]"
|
||||
_RESET="\[\e[0m\]"
|
||||
_HOST=$(if [ -z "$SSH_CLIENT" ]; then echo $_DIM; else echo $_OLIVE; fi)
|
||||
# Nested shell level
|
||||
_SHLVL=$(printf '\$%.0s' $(seq 1 $SHLVL))
|
||||
# SSH detection
|
||||
_SSH='$([ ! -z "$SSH_CLIENT" ] && echo "=>")'
|
||||
# Build prompt
|
||||
export PS1="$_SET_TITLE_BAR$_DIM[\A \u@$_RESET$_HOST\h$_DIM:$_RESET$_GREEN$_DIR$_RESET$_DIM]$_SHLVL$_RESET "
|
||||
|
||||
export HISTCONTROL=ignoreboth
|
|
@ -1,23 +1,252 @@
|
|||
# Shared configuration values
|
||||
let
|
||||
nebula-port = 4242;
|
||||
empyrean-vpn-ip = "10.22.20.1";
|
||||
empyrean-ext-dns = "vpn.alogoulogoi.com";
|
||||
in {
|
||||
nebula-defaults = {
|
||||
listen.port = nebula-port;
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
# Don't filter at the VPN level
|
||||
let
|
||||
inherit (lib) mkDefault mkIf mkMerge mkOption mkOverride types;
|
||||
cfg = config.beatific;
|
||||
mkFlag = description: mkOption {
|
||||
type = types.bool;
|
||||
inherit description;
|
||||
default = true;
|
||||
};
|
||||
in {
|
||||
options = {
|
||||
beatific = {
|
||||
# The host name is reused for beatific-specific configuration.
|
||||
# The bulk of common config is handled in beatific.defaults below, but
|
||||
# having one option without a default ensures that the module cannot be
|
||||
# imported accidentally.
|
||||
hostName = mkOption {
|
||||
type = types.str;
|
||||
description = "Hostname";
|
||||
};
|
||||
|
||||
isLighthouse = mkOption {
|
||||
type = types.bool;
|
||||
description = "Whether this host is a Nebula lighthouse";
|
||||
default = false;
|
||||
};
|
||||
|
||||
extraPrograms = mkOption {
|
||||
type = types.bool;
|
||||
description = "Additional default programs";
|
||||
default = false;
|
||||
};
|
||||
|
||||
# Groups of related defaults can be disabled by flipping off the switches here:
|
||||
# beatific.defaults.${category} = false;
|
||||
# They default to true because the point is to do these things by default.
|
||||
defaults = {
|
||||
time = mkFlag "Default time zone and NTP";
|
||||
i18n = mkFlag "Default locale settings";
|
||||
programs = mkFlag "Default installed programs";
|
||||
ssh = mkFlag "Default sshd settings";
|
||||
nebula = mkFlag "Default beatific nebula settings";
|
||||
tvb = mkFlag "Default tvb account";
|
||||
tvbSync = mkFlag "Configure system syncthing for tvb";
|
||||
hosts = mkFlag "Default 10.22.20.* DNS host entries";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
{
|
||||
# Options to always set
|
||||
networking.hostName = cfg.hostName;
|
||||
nix.extraOptions = "experimental-features = nix-command flakes";
|
||||
# Link /etc/nixos to the flake source
|
||||
environment.etc.nixos.source = ./..;
|
||||
environment.etc."bashrc.local".source = ./bashrc;
|
||||
environment.shellAliases = {
|
||||
# Shortcut for nixos-rebuild
|
||||
nr = "sudo nixos-rebuild --fast --flake $HOME/nixos-configs";
|
||||
# Always preserve mode, ownership, ts with copy
|
||||
cp = "cp -rp";
|
||||
xo = "xdg-open";
|
||||
smv = "rsync -v --remove-source-files";
|
||||
".." = "cd ..";
|
||||
"..." = "cd ../..";
|
||||
"...." = "cd ../../..";
|
||||
"....." = "cd ../../../..";
|
||||
};
|
||||
security.sudo.extraRules = [{
|
||||
users = [ "tvb" ];
|
||||
commands = [ { command = "/run/current-system/sw/bin/nixos-rebuild"; options = [ "NOPASSWD" ]; } ];
|
||||
}];
|
||||
}
|
||||
|
||||
(mkIf cfg.defaults.time {
|
||||
# mkDefault time zone to make it easy to configure it to non-UTC
|
||||
time.timeZone = mkDefault "UTC";
|
||||
services.ntp.enable = true;
|
||||
services.ntp.servers = [ "time.nist.gov" ];
|
||||
})
|
||||
|
||||
(mkIf cfg.defaults.i18n {
|
||||
# en_US.UTF-8
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
i18n.extraLocaleSettings = {
|
||||
LC_ADDRESS = "en_US.UTF-8";
|
||||
LC_IDENTIFICATION = "en_US.UTF-8";
|
||||
LC_MEASUREMENT = "en_US.UTF-8";
|
||||
LC_MONETARY = "en_US.UTF-8";
|
||||
LC_NAME = "en_US.UTF-8";
|
||||
LC_NUMERIC = "en_US.UTF-8";
|
||||
LC_PAPER = "en_US.UTF-8";
|
||||
LC_TELEPHONE = "en_US.UTF-8";
|
||||
LC_TIME = "en_US.UTF-8";
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.defaults.programs {
|
||||
environment.systemPackages = with pkgs; [
|
||||
bc # Terminal calculator
|
||||
curl
|
||||
duf
|
||||
exiftool
|
||||
file # File type inspector
|
||||
htmlq # jq for html
|
||||
jq # jq for json
|
||||
nebula
|
||||
psmisc # provides killall
|
||||
python3
|
||||
rsync
|
||||
sqlite
|
||||
tree # Directory tree view
|
||||
unzip
|
||||
vim
|
||||
wget
|
||||
zip
|
||||
(writeShellScriptBin "clip" ''
|
||||
${xclip}/bin/xclip -sel c < $1
|
||||
'')
|
||||
];
|
||||
programs = {
|
||||
git = {
|
||||
enable = true;
|
||||
config.init.defaultBranch = "master";
|
||||
};
|
||||
htop.enable = true;
|
||||
};
|
||||
# The nixpkgs default is "nano", so we go one priority higher
|
||||
environment.variables.EDITOR = mkOverride 999 "vim";
|
||||
})
|
||||
|
||||
(mkIf cfg.extraPrograms {
|
||||
environment.systemPackages = with pkgs; [
|
||||
calibre # provides ebook-convert
|
||||
imagemagick # image convertion cli
|
||||
puddletag # mp3 tag editor
|
||||
tesseract # OCR engine
|
||||
];
|
||||
})
|
||||
|
||||
(mkIf cfg.defaults.ssh {
|
||||
services.openssh.enable = true;
|
||||
services.openssh.banner = let
|
||||
ascii = import ./ascii.nix;
|
||||
in ascii.${cfg.hostName} or ascii.beatific;
|
||||
networking.firewall.allowPing = true;
|
||||
networking.firewall.allowedTCPPorts = [ 22 ];
|
||||
})
|
||||
|
||||
(mkIf cfg.defaults.nebula {
|
||||
services.nebula.networks.beatific = let
|
||||
empyreanExternalDns = "vpn.alogoulogoi.com";
|
||||
empyreanInternalIp = "10.22.20.1";
|
||||
nebulaPort = 4242;
|
||||
in {
|
||||
enable = true;
|
||||
|
||||
# The lighthouse only listens on the designated subdomain
|
||||
listen.host = if cfg.isLighthouse then empyreanExternalDns else "0.0.0.0";
|
||||
listen.port = nebulaPort;
|
||||
|
||||
# Standard certificate paths
|
||||
ca = "/etc/nebula/beatific/beatific.crt";
|
||||
cert = "/etc/nebula/beatific/${cfg.hostName}.crt";
|
||||
key = "/etc/nebula/beatific/${cfg.hostName}.key";
|
||||
|
||||
isLighthouse = cfg.isLighthouse;
|
||||
# Non-lighthouses connect to the lighthouse at empyrean
|
||||
# This should be a VPN address in the static host map
|
||||
lighthouses = mkIf (! cfg.isLighthouse) [ empyreanInternalIp ];
|
||||
|
||||
# Currently there is no VPN-level traffic filtering
|
||||
firewall.outbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
||||
firewall.inbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
||||
|
||||
# Map the lighthouse address to its public address
|
||||
staticHostMap = { ${empyreanInternalIp} = [ "${empyreanExternalDns}:${toString nebulaPort}" ]; };
|
||||
|
||||
settings = {
|
||||
# Enable UDP holepunching both ways, which allows nodes to establish more direct connections with each other
|
||||
punchy = { punch = true; response = true; };
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
inherit empyrean-vpn-ip;
|
||||
empyrean-host-map = { ${empyrean-vpn-ip} = [ "${empyrean-ext-dns}:${toString nebula-port}" ]; };
|
||||
(mkIf cfg.defaults.tvb {
|
||||
users.groups.tvb = {};
|
||||
users.users.tvb = {
|
||||
isNormalUser = true;
|
||||
group = "tvb";
|
||||
extraGroups = [ "wheel" ];
|
||||
initialPassword = "password";
|
||||
openssh.authorizedKeys.keyFiles = (import ../keys).tvb;
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.defaults.tvbSync {
|
||||
# I haven't gotten user services to work correctly yet,
|
||||
# so for now, tvb monopolizes the system syncthing instance.
|
||||
# Adding users in the future should probably involve multiple
|
||||
# system services so as not to require login to sync.
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
configDir = "/home/tvb/.config/syncthing";
|
||||
# this doesn't prevent syncthing from putting sync points in other locations, it's just a default
|
||||
# normally it would make sense to put it at ~ but see https://github.com/NixOS/nixpkgs/pull/273693
|
||||
dataDir = "/home/tvb/.config/syncthing";
|
||||
openDefaultPorts = true;
|
||||
user = "tvb";
|
||||
group = "tvb";
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.defaults.hosts {
|
||||
# Create *.home host entries for all the beatific members
|
||||
networking.hosts = {
|
||||
"10.22.20.1" = [
|
||||
"empyrean.home"
|
||||
];
|
||||
"10.22.20.2" = [
|
||||
"catacomb.home"
|
||||
"mirror.catacomb.home"
|
||||
];
|
||||
"10.22.20.3" = [
|
||||
"palamas.home"
|
||||
];
|
||||
"10.22.20.4" = [
|
||||
"stagirite.home"
|
||||
];
|
||||
"10.22.20.5" = [
|
||||
"vagrant.home"
|
||||
];
|
||||
"10.22.20.6" = [
|
||||
"unfolder.home"
|
||||
];
|
||||
"10.22.20.7" = [
|
||||
"centroid.home"
|
||||
"mopidy.home.ktvb.site"
|
||||
];
|
||||
"10.22.20.8" = [
|
||||
"backyard.home"
|
||||
"jellyfin.home.ktvb.site"
|
||||
];
|
||||
"10.22.20.9" = [
|
||||
"imperium.home"
|
||||
];
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,722 @@
|
|||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.syncthing;
|
||||
opt = options.services.syncthing;
|
||||
defaultUser = "syncthing";
|
||||
defaultGroup = defaultUser;
|
||||
settingsFormat = pkgs.formats.json { };
|
||||
cleanedConfig = converge (filterAttrsRecursive (_: v: v != null && v != {})) cfg.settings;
|
||||
|
||||
isUnixGui = (builtins.substring 0 1 cfg.guiAddress) == "/";
|
||||
|
||||
# Syncthing supports serving the GUI over Unix sockets. If that happens, the
|
||||
# API is served over the Unix socket as well. This function returns the correct
|
||||
# curl arguments for the address portion of the curl command for both network
|
||||
# and Unix socket addresses.
|
||||
curlAddressArgs = path: if isUnixGui
|
||||
# if cfg.guiAddress is a unix socket, tell curl explicitly about it
|
||||
# note that the dot in front of `${path}` is the hostname, which is
|
||||
# required.
|
||||
then "--unix-socket ${cfg.guiAddress} http://.${path}"
|
||||
# no adjustements are needed if cfg.guiAddress is a network address
|
||||
else "${cfg.guiAddress}${path}"
|
||||
;
|
||||
|
||||
devices = mapAttrsToList (_: device: device // {
|
||||
deviceID = device.id;
|
||||
}) cfg.settings.devices;
|
||||
|
||||
folders = mapAttrsToList (_: folder: folder //
|
||||
throwIf (folder?rescanInterval || folder?watch || folder?watchDelay) ''
|
||||
The options services.syncthing.settings.folders.<name>.{rescanInterval,watch,watchDelay}
|
||||
were removed. Please use, respectively, {rescanIntervalS,fsWatcherEnabled,fsWatcherDelayS} instead.
|
||||
'' {
|
||||
devices = map (device:
|
||||
if builtins.isString device then
|
||||
{ deviceId = cfg.settings.devices.${device}.id; }
|
||||
else
|
||||
device
|
||||
) folder.devices;
|
||||
}) (filterAttrs (_: folder:
|
||||
folder.enable
|
||||
) cfg.settings.folders);
|
||||
|
||||
jq = "${pkgs.jq}/bin/jq";
|
||||
updateConfig = pkgs.writers.writeBash "merge-syncthing-config" (''
|
||||
set -efu
|
||||
|
||||
# be careful not to leak secrets in the filesystem or in process listings
|
||||
umask 0077
|
||||
|
||||
curl() {
|
||||
# get the api key by parsing the config.xml
|
||||
while
|
||||
! ${pkgs.libxml2}/bin/xmllint \
|
||||
--xpath 'string(configuration/gui/apikey)' \
|
||||
${cfg.configDir}/config.xml \
|
||||
>"$RUNTIME_DIRECTORY/api_key"
|
||||
do sleep 1; done
|
||||
(printf "X-API-Key: "; cat "$RUNTIME_DIRECTORY/api_key") >"$RUNTIME_DIRECTORY/headers"
|
||||
${pkgs.curl}/bin/curl -sSLk -H "@$RUNTIME_DIRECTORY/headers" \
|
||||
--retry 1000 --retry-delay 1 --retry-all-errors \
|
||||
"$@"
|
||||
}
|
||||
'' +
|
||||
|
||||
/* Syncthing's rest API for the folders and devices is almost identical.
|
||||
Hence we iterate them using lib.pipe and generate shell commands for both at
|
||||
the sime time. */
|
||||
(lib.pipe {
|
||||
# The attributes below are the only ones that are different for devices /
|
||||
# folders.
|
||||
devs = {
|
||||
new_conf_IDs = map (v: v.id) devices;
|
||||
GET_IdAttrName = "deviceID";
|
||||
override = cfg.overrideDevices;
|
||||
conf = devices;
|
||||
baseAddress = curlAddressArgs "/rest/config/devices";
|
||||
};
|
||||
dirs = {
|
||||
new_conf_IDs = map (v: v.id) folders;
|
||||
GET_IdAttrName = "id";
|
||||
override = cfg.overrideFolders;
|
||||
conf = folders;
|
||||
baseAddress = curlAddressArgs "/rest/config/folders";
|
||||
};
|
||||
} [
|
||||
# Now for each of these attributes, write the curl commands that are
|
||||
# identical to both folders and devices.
|
||||
(mapAttrs (conf_type: s:
|
||||
# We iterate the `conf` list now, and run a curl -X POST command for each, that
|
||||
# should update that device/folder only.
|
||||
lib.pipe s.conf [
|
||||
# Quoting https://docs.syncthing.net/rest/config.html:
|
||||
#
|
||||
# > PUT takes an array and POST a single object. In both cases if a
|
||||
# given folder/device already exists, it’s replaced, otherwise a new
|
||||
# one is added.
|
||||
#
|
||||
# What's not documented, is that using PUT will remove objects that
|
||||
# don't exist in the array given. That's why we use here `POST`, and
|
||||
# only if s.override == true then we DELETE the relevant folders
|
||||
# afterwards.
|
||||
(map (new_cfg: ''
|
||||
curl -d ${lib.escapeShellArg (builtins.toJSON new_cfg)} -X POST ${s.baseAddress}
|
||||
''))
|
||||
(lib.concatStringsSep "\n")
|
||||
]
|
||||
/* If we need to override devices/folders, we iterate all currently configured
|
||||
IDs, via another `curl -X GET`, and we delete all IDs that are not part of
|
||||
the Nix configured list of IDs
|
||||
*/
|
||||
+ lib.optionalString s.override ''
|
||||
stale_${conf_type}_ids="$(curl -X GET ${s.baseAddress} | ${jq} \
|
||||
--argjson new_ids ${lib.escapeShellArg (builtins.toJSON s.new_conf_IDs)} \
|
||||
--raw-output \
|
||||
'[.[].${s.GET_IdAttrName}] - $new_ids | .[]'
|
||||
)"
|
||||
for id in ''${stale_${conf_type}_ids}; do
|
||||
curl -X DELETE ${s.baseAddress}/$id
|
||||
done
|
||||
''
|
||||
))
|
||||
builtins.attrValues
|
||||
(lib.concatStringsSep "\n")
|
||||
]) +
|
||||
/* Now we update the other settings defined in cleanedConfig which are not
|
||||
"folders" or "devices". */
|
||||
(lib.pipe cleanedConfig [
|
||||
builtins.attrNames
|
||||
(lib.subtractLists ["folders" "devices"])
|
||||
(map (subOption: ''
|
||||
curl -X PUT -d ${lib.escapeShellArg (builtins.toJSON cleanedConfig.${subOption})} ${curlAddressArgs "/rest/config/${subOption}"}
|
||||
''))
|
||||
(lib.concatStringsSep "\n")
|
||||
]) + ''
|
||||
# restart Syncthing if required
|
||||
if curl ${curlAddressArgs "/rest/config/restart-required"} |
|
||||
${jq} -e .requiresRestart > /dev/null; then
|
||||
curl -X POST ${curlAddressArgs "/rest/system/restart"}
|
||||
fi
|
||||
'');
|
||||
in {
|
||||
###### interface
|
||||
options = {
|
||||
services.syncthing = {
|
||||
|
||||
enable = mkEnableOption
|
||||
(lib.mdDoc "Syncthing, a self-hosted open-source alternative to Dropbox and Bittorrent Sync");
|
||||
|
||||
cert = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = mdDoc ''
|
||||
Path to the `cert.pem` file, which will be copied into Syncthing's
|
||||
[configDir](#opt-services.syncthing.configDir).
|
||||
'';
|
||||
};
|
||||
|
||||
key = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = mdDoc ''
|
||||
Path to the `key.pem` file, which will be copied into Syncthing's
|
||||
[configDir](#opt-services.syncthing.configDir).
|
||||
'';
|
||||
};
|
||||
|
||||
overrideDevices = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = mdDoc ''
|
||||
Whether to delete the devices which are not configured via the
|
||||
[devices](#opt-services.syncthing.settings.devices) option.
|
||||
If set to `false`, devices added via the web
|
||||
interface will persist and will have to be deleted manually.
|
||||
'';
|
||||
};
|
||||
|
||||
overrideFolders = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = mdDoc ''
|
||||
Whether to delete the folders which are not configured via the
|
||||
[folders](#opt-services.syncthing.settings.folders) option.
|
||||
If set to `false`, folders added via the web
|
||||
interface will persist and will have to be deleted manually.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
# global options
|
||||
options = mkOption {
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
The options element contains all other global configuration options
|
||||
'';
|
||||
type = types.submodule ({ name, ... }: {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
localAnnounceEnabled = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Whether to send announcements to the local LAN, also use such announcements to find other devices.
|
||||
'';
|
||||
};
|
||||
|
||||
localAnnouncePort = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
The port on which to listen and send IPv4 broadcast announcements to.
|
||||
'';
|
||||
};
|
||||
|
||||
relaysEnabled = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
When true, relays will be connected to and potentially used for device to device connections.
|
||||
'';
|
||||
};
|
||||
|
||||
urAccepted = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Whether the user has accepted to submit anonymous usage data.
|
||||
The default, 0, mean the user has not made a choice, and Syncthing will ask at some point in the future.
|
||||
"-1" means no, a number above zero means that that version of usage reporting has been accepted.
|
||||
'';
|
||||
};
|
||||
|
||||
limitBandwidthInLan = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Whether to apply bandwidth limits to devices in the same broadcast domain as the local device.
|
||||
'';
|
||||
};
|
||||
|
||||
maxFolderConcurrency = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
This option controls how many folders may concurrently be in I/O-intensive operations such as syncing or scanning.
|
||||
The mechanism is described in detail in a [separate chapter](https://docs.syncthing.net/advanced/option-max-concurrency.html).
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
# device settings
|
||||
devices = mkOption {
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
Peers/devices which Syncthing should communicate with.
|
||||
|
||||
Note that you can still add devices manually, but those changes
|
||||
will be reverted on restart if [overrideDevices](#opt-services.syncthing.overrideDevices)
|
||||
is enabled.
|
||||
'';
|
||||
example = {
|
||||
bigbox = {
|
||||
id = "7CFNTQM-IMTJBHJ-3UWRDIU-ZGQJFR6-VCXZ3NB-XUH3KZO-N52ITXR-LAIYUAU";
|
||||
addresses = [ "tcp://192.168.0.10:51820" ];
|
||||
};
|
||||
};
|
||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The name of the device.
|
||||
'';
|
||||
};
|
||||
|
||||
id = mkOption {
|
||||
type = types.str;
|
||||
description = mdDoc ''
|
||||
The device ID. See <https://docs.syncthing.net/dev/device-ids.html>.
|
||||
'';
|
||||
};
|
||||
|
||||
autoAcceptFolders = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = mdDoc ''
|
||||
Automatically create or share folders that this device advertises at the default path.
|
||||
See <https://docs.syncthing.net/users/config.html?highlight=autoaccept#config-file-format>.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
# folder settings
|
||||
folders = mkOption {
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
Folders which should be shared by Syncthing.
|
||||
|
||||
Note that you can still add folders manually, but those changes
|
||||
will be reverted on restart if [overrideFolders](#opt-services.syncthing.overrideFolders)
|
||||
is enabled.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
"/home/user/sync" = {
|
||||
id = "syncme";
|
||||
devices = [ "bigbox" ];
|
||||
};
|
||||
}
|
||||
'';
|
||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Whether to share this folder.
|
||||
This option is useful when you want to define all folders
|
||||
in one place, but not every machine should share all folders.
|
||||
'';
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
# TODO for release 23.05: allow relative paths again and set
|
||||
# working directory to cfg.dataDir
|
||||
type = types.str // {
|
||||
check = x: types.str.check x && (substring 0 1 x == "/" || substring 0 2 x == "~/");
|
||||
description = types.str.description + " starting with / or ~/";
|
||||
};
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The path to the folder which should be shared.
|
||||
Only absolute paths (starting with `/`) and paths relative to
|
||||
the [user](#opt-services.syncthing.user)'s home directory
|
||||
(starting with `~/`) are allowed.
|
||||
'';
|
||||
};
|
||||
|
||||
id = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The ID of the folder. Must be the same on all devices.
|
||||
'';
|
||||
};
|
||||
|
||||
label = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The label of the folder.
|
||||
'';
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = mdDoc ''
|
||||
The devices this folder should be shared with. Each device must
|
||||
be defined in the [devices](#opt-services.syncthing.settings.devices) option.
|
||||
'';
|
||||
};
|
||||
|
||||
versioning = mkOption {
|
||||
default = null;
|
||||
description = mdDoc ''
|
||||
How to keep changed/deleted files with Syncthing.
|
||||
There are 4 different types of versioning with different parameters.
|
||||
See <https://docs.syncthing.net/users/versioning.html>.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
{
|
||||
versioning = {
|
||||
type = "simple";
|
||||
params.keep = "10";
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "trashcan";
|
||||
params.cleanoutDays = "1000";
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "staggered";
|
||||
fsPath = "/syncthing/backup";
|
||||
params = {
|
||||
cleanInterval = "3600";
|
||||
maxAge = "31536000";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "external";
|
||||
params.versionsPath = pkgs.writers.writeBash "backup" '''
|
||||
folderpath="$1"
|
||||
filepath="$2"
|
||||
rm -rf "$folderpath/$filepath"
|
||||
''';
|
||||
};
|
||||
}
|
||||
]
|
||||
'';
|
||||
type = with types; nullOr (submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
type = mkOption {
|
||||
type = enum [ "external" "simple" "staggered" "trashcan" ];
|
||||
description = mdDoc ''
|
||||
The type of versioning.
|
||||
See <https://docs.syncthing.net/users/versioning.html>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
copyOwnershipFromParent = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = mdDoc ''
|
||||
On Unix systems, tries to copy file/folder ownership from the parent directory (the directory it’s located in).
|
||||
Requires running Syncthing as a privileged user, or granting it additional capabilities (e.g. CAP_CHOWN on Linux).
|
||||
'';
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
Extra configuration options for Syncthing.
|
||||
See <https://docs.syncthing.net/users/config.html>.
|
||||
Note that this attribute set does not exactly match the documented
|
||||
xml format. Instead, this is the format of the json rest api. There
|
||||
are slight differences. For example, this xml:
|
||||
```xml
|
||||
<options>
|
||||
<listenAddress>default</listenAddress>
|
||||
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
||||
</options>
|
||||
```
|
||||
corresponds to the json:
|
||||
```json
|
||||
{
|
||||
options: {
|
||||
listenAddresses = [
|
||||
"default"
|
||||
];
|
||||
minHomeDiskFree = {
|
||||
unit = "%";
|
||||
value = 1;
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
'';
|
||||
example = {
|
||||
options.localAnnounceEnabled = false;
|
||||
gui.theme = "black";
|
||||
};
|
||||
};
|
||||
|
||||
guiAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1:8384";
|
||||
description = lib.mdDoc ''
|
||||
The address to serve the web interface at.
|
||||
'';
|
||||
};
|
||||
|
||||
systemService = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Whether to auto-launch Syncthing as a system service.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = defaultUser;
|
||||
example = "yourUser";
|
||||
description = mdDoc ''
|
||||
The user to run Syncthing as.
|
||||
By default, a user named `${defaultUser}` will be created whose home
|
||||
directory is [dataDir](#opt-services.syncthing.dataDir).
|
||||
'';
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = defaultGroup;
|
||||
example = "yourGroup";
|
||||
description = mdDoc ''
|
||||
The group to run Syncthing under.
|
||||
By default, a group named `${defaultGroup}` will be created.
|
||||
'';
|
||||
};
|
||||
|
||||
all_proxy = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "socks5://address.com:1234";
|
||||
description = mdDoc ''
|
||||
Overwrites the all_proxy environment variable for the Syncthing process to
|
||||
the given value. This is normally used to let Syncthing connect
|
||||
through a SOCKS5 proxy server.
|
||||
See <https://docs.syncthing.net/users/proxying.html>.
|
||||
'';
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/syncthing";
|
||||
example = "/home/yourUser";
|
||||
description = lib.mdDoc ''
|
||||
The path where synchronised directories will exist.
|
||||
'';
|
||||
};
|
||||
|
||||
configDir = let
|
||||
cond = versionAtLeast config.system.stateVersion "19.03";
|
||||
in mkOption {
|
||||
type = types.path;
|
||||
description = lib.mdDoc ''
|
||||
The path where the settings and keys will exist.
|
||||
'';
|
||||
default = cfg.dataDir + optionalString cond "/.config/syncthing";
|
||||
defaultText = literalMD ''
|
||||
* if `stateVersion >= 19.03`:
|
||||
|
||||
config.${opt.dataDir} + "/.config/syncthing"
|
||||
* otherwise:
|
||||
|
||||
config.${opt.dataDir}
|
||||
'';
|
||||
};
|
||||
|
||||
databaseDir = mkOption {
|
||||
type = types.path;
|
||||
description = lib.mdDoc ''
|
||||
The directory containing the database and logs.
|
||||
'';
|
||||
default = cfg.configDir;
|
||||
defaultText = literalExpression "config.${opt.configDir}";
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "--reset-deltas" ];
|
||||
description = lib.mdDoc ''
|
||||
Extra flags passed to the syncthing command in the service definition.
|
||||
'';
|
||||
};
|
||||
|
||||
openDefaultPorts = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = lib.mdDoc ''
|
||||
Whether to open the default ports in the firewall: TCP/UDP 22000 for transfers
|
||||
and UDP 21027 for discovery.
|
||||
|
||||
If multiple users are running Syncthing on this machine, you will need
|
||||
to manually open a set of ports for each instance and leave this disabled.
|
||||
Alternatively, if you are running only a single instance on this machine
|
||||
using the default ports, enable this.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.syncthing;
|
||||
defaultText = literalExpression "pkgs.syncthing";
|
||||
description = lib.mdDoc ''
|
||||
The Syncthing package to use.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "services" "syncthing" "useInotify" ] ''
|
||||
This option was removed because Syncthing now has the inotify functionality included under the name "fswatcher".
|
||||
It can be enabled on a per-folder basis through the web interface.
|
||||
'')
|
||||
(mkRenamedOptionModule [ "services" "syncthing" "extraOptions" ] [ "services" "syncthing" "settings" ])
|
||||
(mkRenamedOptionModule [ "services" "syncthing" "folders" ] [ "services" "syncthing" "settings" "folders" ])
|
||||
(mkRenamedOptionModule [ "services" "syncthing" "devices" ] [ "services" "syncthing" "settings" "devices" ])
|
||||
(mkRenamedOptionModule [ "services" "syncthing" "options" ] [ "services" "syncthing" "settings" "options" ])
|
||||
] ++ map (o:
|
||||
mkRenamedOptionModule [ "services" "syncthing" "declarative" o ] [ "services" "syncthing" o ]
|
||||
) [ "cert" "key" "devices" "folders" "overrideDevices" "overrideFolders" "extraOptions"];
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
networking.firewall = mkIf cfg.openDefaultPorts {
|
||||
allowedTCPPorts = [ 22000 ];
|
||||
allowedUDPPorts = [ 21027 22000 ];
|
||||
};
|
||||
|
||||
systemd.packages = [ pkgs.syncthing ];
|
||||
|
||||
users.users = mkIf (cfg.systemService && cfg.user == defaultUser) {
|
||||
${defaultUser} =
|
||||
{ group = cfg.group;
|
||||
home = cfg.dataDir;
|
||||
createHome = true;
|
||||
uid = config.ids.uids.syncthing;
|
||||
description = "Syncthing daemon user";
|
||||
};
|
||||
};
|
||||
|
||||
users.groups = mkIf (cfg.systemService && cfg.group == defaultGroup) {
|
||||
${defaultGroup}.gid =
|
||||
config.ids.gids.syncthing;
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
# upstream reference:
|
||||
# https://github.com/syncthing/syncthing/blob/main/etc/linux-systemd/system/syncthing%40.service
|
||||
syncthing = mkIf cfg.systemService {
|
||||
description = "Syncthing service";
|
||||
after = [ "network.target" ];
|
||||
environment = {
|
||||
STNORESTART = "yes";
|
||||
STNOUPGRADE = "yes";
|
||||
inherit (cfg) all_proxy;
|
||||
} // config.networking.proxy.envVars;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Restart = "on-failure";
|
||||
SuccessExitStatus = "3 4";
|
||||
RestartForceExitStatus="3 4";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStartPre = mkIf (cfg.cert != null || cfg.key != null)
|
||||
"+${pkgs.writers.writeBash "syncthing-copy-keys" ''
|
||||
install -dm700 -o ${cfg.user} -g ${cfg.group} ${cfg.configDir}
|
||||
${optionalString (cfg.cert != null) ''
|
||||
install -Dm400 -o ${cfg.user} -g ${cfg.group} ${toString cfg.cert} ${cfg.configDir}/cert.pem
|
||||
''}
|
||||
${optionalString (cfg.key != null) ''
|
||||
install -Dm400 -o ${cfg.user} -g ${cfg.group} ${toString cfg.key} ${cfg.configDir}/key.pem
|
||||
''}
|
||||
''}"
|
||||
;
|
||||
ExecStart = ''
|
||||
${cfg.package}/bin/syncthing \
|
||||
-no-browser \
|
||||
-gui-address=${if isUnixGui then "unix://" else ""}${cfg.guiAddress} \
|
||||
-config=${cfg.configDir} \
|
||||
-data=${cfg.databaseDir} \
|
||||
${escapeShellArgs cfg.extraFlags}
|
||||
'';
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
CapabilityBoundingSet = [
|
||||
"~CAP_SYS_PTRACE" "~CAP_SYS_ADMIN"
|
||||
"~CAP_SETGID" "~CAP_SETUID" "~CAP_SETPCAP"
|
||||
"~CAP_SYS_TIME" "~CAP_KILL"
|
||||
];
|
||||
};
|
||||
};
|
||||
syncthing-init = mkIf (cleanedConfig != {}) {
|
||||
description = "Syncthing configuration updater";
|
||||
requisite = [ "syncthing.service" ];
|
||||
after = [ "syncthing.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
RemainAfterExit = true;
|
||||
RuntimeDirectory = "syncthing-init";
|
||||
Type = "oneshot";
|
||||
ExecStart = updateConfig;
|
||||
};
|
||||
};
|
||||
|
||||
syncthing-resume = {
|
||||
wantedBy = [ "suspend.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue