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-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1668681692,
|
"lastModified": 1673956053,
|
||||||
"narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
|
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "009399224d5e398d03b22badca40a37ac85412a1",
|
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -31,12 +31,79 @@
|
||||||
"type": "github"
|
"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": {
|
"nixos-wsl": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": [
|
||||||
|
"flake-compat"
|
||||||
|
],
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs-2305"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
|
@ -53,26 +120,46 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs-2305": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1669833724,
|
"lastModified": 1685566663,
|
||||||
"narHash": "sha256-/HEZNyGbnQecrgJnfE8d0WC5c1xuPSD2LUpB6YXlg4c=",
|
"narHash": "sha256-btHN1czJ6rzteeCuE/PNrdssqYD2nIA4w48miQAFloM=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "4d2b37a84fad1091b9de401eb450aae66f1a741e",
|
"rev": "4ecab3273592f27479a583fb6d975d4aba3486fe",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"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",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"intake": "intake",
|
||||||
|
"intake-sources": "intake-sources",
|
||||||
"nixos-wsl": "nixos-wsl",
|
"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 = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs?ref=refs/tags/22.11";
|
nixpkgs-2305.url = "github:NixOS/nixpkgs/23.05";
|
||||||
nixos-wsl.url = "github:nix-community/NixOS-WSL";
|
nixpkgs-2311.url = "github:NixOS/nixpkgs/23.11";
|
||||||
nixos-wsl.inputs.nixpkgs.follows = "nixpkgs";
|
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 }: {
|
outputs = {
|
||||||
nixosConfigurations = {
|
self,
|
||||||
catacomb = nixpkgs.lib.nixosSystem {
|
nixpkgs-2305,
|
||||||
system = "aarch64-linux";
|
nixpkgs-2311,
|
||||||
modules = [ ./machine/catacomb ];
|
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";
|
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";
|
system = "x86_64-linux";
|
||||||
modules = [
|
modules = [
|
||||||
nixos-wsl.nixosModules.wsl
|
nixos-wsl.nixosModules.wsl
|
||||||
./machine/stagirite
|
./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, ... }:
|
{ pkgs, lib, ... }:
|
||||||
|
|
||||||
let
|
{
|
||||||
beatific = import ../../modules/beatific.nix;
|
|
||||||
in {
|
|
||||||
imports = [
|
imports = [
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./fileserver.nix
|
./fileserver.nix
|
||||||
|
./mirror.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
beatific.hostName = "catacomb";
|
||||||
|
beatific.defaults.tvbSync = true;
|
||||||
|
|
||||||
boot = {
|
boot = {
|
||||||
loader = {
|
loader = {
|
||||||
# Use the extlinux boot loader. (NixOS wants to enable GRUB by default)
|
# Use the extlinux boot loader. (NixOS wants to enable GRUB by default)
|
||||||
|
@ -17,42 +19,26 @@ in {
|
||||||
};
|
};
|
||||||
supportedFilesystems = ["zfs"];
|
supportedFilesystems = ["zfs"];
|
||||||
zfs.enableUnstable = true;
|
zfs.enableUnstable = true;
|
||||||
|
kernelParams = [ "zfs.zfs_dmu_offset_next_sync=0" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
system.stateVersion = "22.11"; # Read the usual warning
|
system.stateVersion = "22.11"; # Read the usual warning
|
||||||
|
|
||||||
swapDevices = [ { device = "/swap"; size = 1024; } ];
|
swapDevices = [ { device = "/swap"; size = 1024; } ];
|
||||||
|
|
||||||
console.keyMap = "us";
|
environment.systemPackages = with pkgs; [
|
||||||
i18n.defaultLocale = "en_US.UTF-8";
|
lsof # list open files
|
||||||
|
mkpasswd # used for setting SMB passwords, I think?
|
||||||
environment.systemPackages = with pkgs;
|
samba # provides smbpasswd, mostly
|
||||||
let
|
smartmontools # provides smartctl
|
||||||
py3-packages = python-packages: with python-packages; [
|
usbutils # provides lsusb
|
||||||
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
|
|
||||||
];
|
];
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
hostName = "catacomb";
|
hostId = "beeeeee5"; # this must be consistent for ZFS
|
||||||
hostId = "beeeeee5";
|
|
||||||
firewall = {
|
firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
allowPing = true;
|
allowedTCPPorts = [ 139 445 ];
|
||||||
allowedTCPPorts = [ 22 139 445 ];
|
|
||||||
allowedUDPPorts = [ 137 138 ];
|
allowedUDPPorts = [ 137 138 ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -72,15 +58,7 @@ in {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.openssh = {
|
services.openssh.settings.PasswordAuthentication = true;
|
||||||
enable = true;
|
|
||||||
passwordAuthentication = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.ntp = {
|
|
||||||
enable = true;
|
|
||||||
servers = ["time.nist.gov"];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.rsyncd.enable = 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 = {
|
services.zfs = {
|
||||||
autoScrub = {
|
autoScrub = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -191,19 +153,14 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.tvb = {
|
users.users.tvb = {
|
||||||
isNormalUser = true;
|
|
||||||
uid = 1001;
|
uid = 1001;
|
||||||
password = "badpassword";
|
extraGroups = [ "nas" ];
|
||||||
extraGroups = ["wheel" "nas"];
|
packages = [
|
||||||
openssh.authorizedKeys.keyFiles = [
|
(pkgs.writeShellScriptBin "yt-dlp" ''
|
||||||
../../keys/tvb.palamas.pub
|
exec $HOME/.env/bin/yt-dlp "$@"
|
||||||
../../keys/tvb.stagirite.pub
|
'')
|
||||||
../../keys/tvb.vagrant.pub
|
|
||||||
../../keys/monitor.isidore.pub
|
|
||||||
../../keys/inquisitor.conduit.pub
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
#./keys/tvb.empyrean.pub
|
|
||||||
|
|
||||||
users.users.katydid = {
|
users.users.katydid = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
|
@ -211,5 +168,4 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
nix.settings.cores = 4;
|
nix.settings.cores = 4;
|
||||||
nix.extraOptions = "experimental-features = nix-command flakes";
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ let
|
||||||
catacombServerSource = builtins.fetchGit {
|
catacombServerSource = builtins.fetchGit {
|
||||||
url = "https://git.alogoulogoi.com/Jaculabilis/catacomb-server.git";
|
url = "https://git.alogoulogoi.com/Jaculabilis/catacomb-server.git";
|
||||||
ref = "develop-nix";
|
ref = "develop-nix";
|
||||||
rev = "63574bb39cc777deb56a76548f08789d238fcfec";
|
rev = "3d6fb16948c377f94d030648849f120c8ada3884";
|
||||||
};
|
};
|
||||||
catacombServer = pkgs.callPackage catacombServerSource {};
|
catacombServer = pkgs.callPackage catacombServerSource {};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,11 @@
|
||||||
fsType = "ext4";
|
fsType = "ext4";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fileSystems."/backup" =
|
||||||
|
{ device = "catapool/backup";
|
||||||
|
fsType = "zfs";
|
||||||
|
};
|
||||||
|
|
||||||
fileSystems."/home/katydid" =
|
fileSystems."/home/katydid" =
|
||||||
{ device = "catapool/user/katydid";
|
{ device = "catapool/user/katydid";
|
||||||
fsType = "zfs";
|
fsType = "zfs";
|
||||||
|
@ -28,41 +33,6 @@
|
||||||
fsType = "zfs";
|
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" =
|
fileSystems."/nas/image" =
|
||||||
{ device = "catapool/nas/image";
|
{ device = "catapool/nas/image";
|
||||||
fsType = "zfs";
|
fsType = "zfs";
|
||||||
|
@ -73,11 +43,21 @@
|
||||||
fsType = "zfs";
|
fsType = "zfs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fileSystems."/nas/doc" =
|
||||||
|
{ device = "catapool/nas/doc";
|
||||||
|
fsType = "zfs";
|
||||||
|
};
|
||||||
|
|
||||||
fileSystems."/nas/game" =
|
fileSystems."/nas/game" =
|
||||||
{ device = "catapool/nas/game";
|
{ device = "catapool/nas/game";
|
||||||
fsType = "zfs";
|
fsType = "zfs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fileSystems."/nas/video" =
|
||||||
|
{ device = "catapool/nas/video";
|
||||||
|
fsType = "zfs";
|
||||||
|
};
|
||||||
|
|
||||||
swapDevices = [ ];
|
swapDevices = [ ];
|
||||||
|
|
||||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
# 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.
|
[ # Include the results of the hardware scan.
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
#./amanuensis.nix
|
#./amanuensis.nix
|
||||||
#./redstring.nix
|
|
||||||
./catacomb.nix
|
./catacomb.nix
|
||||||
./gitea.nix
|
./gitea.nix
|
||||||
./inquisitor.nix
|
./sync-pipeline.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
beatific.hostName = "empyrean";
|
||||||
|
beatific.isLighthouse = true;
|
||||||
|
beatific.defaults.tvbSync = true;
|
||||||
|
|
||||||
# Use the GRUB 2 boot loader.
|
# Use the GRUB 2 boot loader.
|
||||||
boot.loader.grub = {
|
boot.loader.grub = {
|
||||||
enable = true;
|
enable = true;
|
||||||
version = 2;
|
|
||||||
device = "/dev/xvda";
|
device = "/dev/xvda";
|
||||||
extraConfig = "serial --unit=0 --speed=115200 ; terminal_input serial console ; terminal_output serial console";
|
extraConfig = "serial --unit=0 --speed=115200 ; terminal_input serial console ; terminal_output serial console";
|
||||||
};
|
};
|
||||||
|
@ -27,42 +29,20 @@
|
||||||
nix = {
|
nix = {
|
||||||
package = pkgs.nixFlakes;
|
package = pkgs.nixFlakes;
|
||||||
settings.max-jobs = 2;
|
settings.max-jobs = 2;
|
||||||
extraOptions = ''
|
|
||||||
experimental-features = nix-command flakes
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
swapDevices = [ { device = "/swap"; size = 1024; } ];
|
swapDevices = [ { device = "/swap"; size = 1024; } ];
|
||||||
|
|
||||||
networking.hostName = "empyrean";
|
|
||||||
|
|
||||||
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
|
# 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
|
# Per-interface useDHCP will be mandatory in the future, so this generated config
|
||||||
# replicates the default behaviour.
|
# replicates the default behaviour.
|
||||||
networking.useDHCP = false;
|
networking.useDHCP = false;
|
||||||
networking.interfaces.eth0.useDHCP = true;
|
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; [
|
environment.systemPackages = with pkgs; [
|
||||||
vim htop git tinc_pre python3
|
tinc_pre
|
||||||
gitea
|
gitea
|
||||||
];
|
];
|
||||||
environment.variables.EDITOR = "vim";
|
|
||||||
|
|
||||||
services.nginx = let
|
services.nginx = let
|
||||||
static-site = srv-dir: {
|
static-site = srv-dir: {
|
||||||
|
@ -74,26 +54,36 @@
|
||||||
index index.html;
|
index index.html;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
service-stub = {
|
||||||
|
rejectSSL = true;
|
||||||
|
locations."/".return = "403";
|
||||||
|
};
|
||||||
in {
|
in {
|
||||||
enable = true;
|
enable = true;
|
||||||
recommendedProxySettings = true;
|
recommendedProxySettings = true;
|
||||||
virtualHosts = {
|
virtualHosts = {
|
||||||
# Static pages
|
# Static pages
|
||||||
|
"home.ktvb.site" = static-site "home.ktvb.site";
|
||||||
"wedding.ktvb.site" = static-site "wedding.ktvb.site";
|
"wedding.ktvb.site" = static-site "wedding.ktvb.site";
|
||||||
"www.ktvb.site" = static-site "www.ktvb.site";
|
"www.ktvb.site" = static-site "www.ktvb.site";
|
||||||
"mirror.alogoulogoi.com" = static-site "mirror.alogoulogoi.com";
|
"www.alogoulogoi.com" = static-site "www.alogoulogoi.com";
|
||||||
"www.alogoulogoi.com" = static-site "www";
|
"ecumene.alogoulogoi.com" = static-site "ecumene.alogoulogoi.com";
|
||||||
newtab = {
|
# Home service stub domains
|
||||||
listen = [ { addr = "10.22.20.1"; port = 80; } ];
|
"mopidy.home.ktvb.site" = service-stub;
|
||||||
root = "/srv/newtab/";
|
"jellyfin.home.ktvb.site" = service-stub;
|
||||||
|
# mirror revproxy
|
||||||
|
"mirror.alogoulogoi.com" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
access_log /var/log/nginx/access_newtab.log;
|
access_log /var/log/nginx/access_mirror.alogoulogoi.com.log;
|
||||||
index index.html;
|
|
||||||
'';
|
'';
|
||||||
|
locations."/".proxyPass = "http://mirror.catacomb.home:7474/";
|
||||||
};
|
};
|
||||||
# Deny all other subdomains
|
# Deny all other subdomains
|
||||||
"alogoulogoi.com" = {
|
"alogoulogoi.com" = {
|
||||||
default = true;
|
default = true;
|
||||||
|
rejectSSL = true;
|
||||||
locations."/".return = "444";
|
locations."/".return = "444";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -103,20 +93,9 @@
|
||||||
acceptTerms = true;
|
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 = {
|
services.openssh = {
|
||||||
enable = true;
|
settings.PasswordAuthentication = false;
|
||||||
passwordAuthentication = false;
|
settings.PermitRootLogin = "prohibit-password";
|
||||||
permitRootLogin = "prohibit-password";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.tinc.networks.beatific = {
|
services.tinc.networks.beatific = {
|
||||||
|
@ -124,36 +103,15 @@
|
||||||
chroot = false;
|
chroot = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nebula.networks.beatific = {
|
services.intake = {
|
||||||
enable = true;
|
listen = { addr = "10.22.20.1"; };
|
||||||
|
users.tvb.enable = true;
|
||||||
# Network certificate and host credentials
|
users.tvb.extraPackages = [ pkgs.intakeSources pkgs.openssh ];
|
||||||
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; };
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall = {
|
networking.firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
allowPing = true;
|
|
||||||
allowedTCPPorts = [
|
allowedTCPPorts = [
|
||||||
22 # ssh
|
|
||||||
80 # http
|
80 # http
|
||||||
443 # https
|
443 # https
|
||||||
655 # tinc
|
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
|
# This value determines the NixOS release from which the default
|
||||||
# settings for stateful data, like file locations and database versions
|
# settings for stateful data, like file locations and database versions
|
||||||
# on your system were taken. It‘s perfectly fine and recommended to leave
|
# 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.
|
# this value at the release version of the first install of this system.
|
||||||
# Before changing this value read the documentation for this option
|
# Before changing this value read the documentation for this option
|
||||||
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
# (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
|
# Gitea configuration
|
||||||
services.gitea = {
|
services.gitea = {
|
||||||
# Enable Gitea and configure for reverse proxy
|
|
||||||
enable = true;
|
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
|
#useWizard = true; # Needed for first-time building
|
||||||
|
|
||||||
|
@ -22,6 +17,13 @@
|
||||||
interval = "weekly";
|
interval = "weekly";
|
||||||
};
|
};
|
||||||
settings = {
|
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" = {
|
"repository" = {
|
||||||
DEFAULT_PRIVATE = true;
|
DEFAULT_PRIVATE = true;
|
||||||
};
|
};
|
||||||
|
@ -37,10 +39,13 @@
|
||||||
"security" = {
|
"security" = {
|
||||||
INSTALL_LOCK = true;
|
INSTALL_LOCK = true;
|
||||||
};
|
};
|
||||||
|
"session" = {
|
||||||
|
SESSION_LIFE_TIME = 86400 * 7; # 1 week
|
||||||
|
};
|
||||||
"picture" = {
|
"picture" = {
|
||||||
DISABLE_GRAVATAR = true;
|
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;
|
"cron.sync_external_users".ENABLED = false;
|
||||||
log.LEVEL = "Info";
|
log.LEVEL = "Info";
|
||||||
# Private server
|
# Private server
|
||||||
|
@ -66,5 +71,8 @@
|
||||||
proxy_pass http://localhost:3300/;
|
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;
|
startMenuLaunchers = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
system.stateVersion = "21.11";
|
#system.stateVersion = "21.11";
|
||||||
|
|
||||||
networking.hostName = "stagirite";
|
networking.hostName = "stagirite";
|
||||||
|
beatific.defaults.tvbSync = false;
|
||||||
|
|
||||||
fileSystems.winssh = {
|
fileSystems.winssh = {
|
||||||
device = "C:/Users/tvb/.ssh";
|
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
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
|
||||||
nebula-port = 4242;
|
|
||||||
empyrean-vpn-ip = "10.22.20.1";
|
|
||||||
empyrean-ext-dns = "vpn.alogoulogoi.com";
|
|
||||||
in {
|
|
||||||
nebula-defaults = {
|
|
||||||
listen.port = nebula-port;
|
|
||||||
|
|
||||||
# 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.outbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
||||||
firewall.inbound = [ { 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 = {
|
settings = {
|
||||||
# Enable UDP holepunching both ways, which allows nodes to establish more direct connections with each other
|
# Enable UDP holepunching both ways, which allows nodes to establish more direct connections with each other
|
||||||
punchy = { punch = true; response = true; };
|
punchy = { punch = true; response = true; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
})
|
||||||
|
|
||||||
inherit empyrean-vpn-ip;
|
(mkIf cfg.defaults.tvb {
|
||||||
empyrean-host-map = { ${empyrean-vpn-ip} = [ "${empyrean-ext-dns}:${toString nebula-port}" ]; };
|
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