Compare commits
1 Commits
725ba42c78
...
68b58053d4
Author | SHA1 | Date |
---|---|---|
Jaculabilis | 68b58053d4 |
109
flake.lock
109
flake.lock
|
@ -3,11 +3,11 @@
|
||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1673956053,
|
"lastModified": 1668681692,
|
||||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
"narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
"rev": "009399224d5e398d03b22badca40a37ac85412a1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -31,79 +31,12 @@
|
||||||
"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-2305"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
|
@ -120,46 +53,26 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-2305": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1685566663,
|
"lastModified": 1669833724,
|
||||||
"narHash": "sha256-btHN1czJ6rzteeCuE/PNrdssqYD2nIA4w48miQAFloM=",
|
"narHash": "sha256-/HEZNyGbnQecrgJnfE8d0WC5c1xuPSD2LUpB6YXlg4c=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "4ecab3273592f27479a583fb6d975d4aba3486fe",
|
"rev": "4d2b37a84fad1091b9de401eb450aae66f1a741e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "23.05",
|
"ref": "refs/tags/22.11",
|
||||||
"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-2305": "nixpkgs-2305",
|
"nixpkgs": "nixpkgs"
|
||||||
"nixpkgs-2311": "nixpkgs-2311"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
96
flake.nix
96
flake.nix
|
@ -1,103 +1,27 @@
|
||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs-2305.url = "github:NixOS/nixpkgs/23.05";
|
nixpkgs.url = "github:NixOS/nixpkgs?ref=refs/tags/22.11";
|
||||||
nixpkgs-2311.url = "github:NixOS/nixpkgs/23.11";
|
nixos-wsl.url = "github:nix-community/NixOS-WSL";
|
||||||
flake-compat = {
|
nixos-wsl.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
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 = {
|
outputs = { self, nixpkgs, nixos-wsl }: {
|
||||||
self,
|
nixosConfigurations = {
|
||||||
nixpkgs-2305,
|
catacomb = nixpkgs.lib.nixosSystem {
|
||||||
nixpkgs-2311,
|
|
||||||
flake-compat,
|
|
||||||
nixos-wsl,
|
|
||||||
intake,
|
|
||||||
intake-sources,
|
|
||||||
}@inputs: {
|
|
||||||
nixosModules.beatific = import ./modules/beatific.nix;
|
|
||||||
|
|
||||||
nixosConfigurations = let
|
|
||||||
pinNixpkgs = nixpkgs: { ... }: {
|
|
||||||
nix.registry.nixpkgs.to = { type = "path"; path = nixpkgs; };
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
backyard = nixpkgs-2311.lib.nixosSystem {
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
self.nixosModules.beatific
|
|
||||||
(pinNixpkgs nixpkgs-2311)
|
|
||||||
./machine/backyard
|
|
||||||
];
|
|
||||||
};
|
|
||||||
catacomb = nixpkgs-2305.lib.nixosSystem {
|
|
||||||
system = "aarch64-linux";
|
system = "aarch64-linux";
|
||||||
modules = [
|
modules = [ ./machine/catacomb ];
|
||||||
self.nixosModules.beatific
|
|
||||||
(pinNixpkgs nixpkgs-2305)
|
|
||||||
./machine/catacomb
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
centroid = nixpkgs-2311.lib.nixosSystem {
|
empyrean = nixpkgs.lib.nixosSystem {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
modules = [
|
modules = [ ./machine/empyrean ];
|
||||||
self.nixosModules.beatific
|
|
||||||
(pinNixpkgs nixpkgs-2311)
|
|
||||||
./machine/centroid
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
empyrean = nixpkgs-2305.lib.nixosSystem {
|
stagirite = nixpkgs.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
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
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
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -0,0 +1 @@
|
||||||
|
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCzx37PqIaJVWdQs5meVgI4Cg1GRGk6srrix0AUvQeaBS9MOVtJLi+HfnNkcW4GPk9qVlz1E7ciQ7YUw+ny7QbHxcbib2Tawwfk3cx9xiNcN6UI9EzF/rTbNB2Cex8A4sEr5UvoE0BjT5yPaXyrjn8vLksGWq4dlZBM3xeJqe3KP+OxPL0vik3SVGOr/6ZQ7H9cwX5+/p6rCWQuVtwZMcaE6QyXYg5J5FQUaIrFvKbOVklJIkQSbXGzIYQO/QlQC0xWGBapJtGQw/lsQ3YqnFSMkkw8qrKbde07rg8p1FSuqTu+a1ePK+/F4klNel174+39YSobY2/6biPP3Uj/Yhorf4Tw141tIT75e3ebtK5faatQmNOyXcA7LULXK7XemJkZy8PmbNNTeBIKyoI6XQdzk95gpb2C4LEJmV040YMgXhOIiKsHQVgss9FuC+oP5jXWU/JuNXBRHa1IpJjcJhIhg7jnh6ZNZHyK0EpeUs3Zp7usv7mz6CGwb04yvTsWOhZRc+6EoHaHyrNvFPfkPeGsZzxhIbprCyDMtKWsI9GCtztcRhQWBgornUVEs5CurLJBbClQTrZLVv2fn9UnXWPYZTLYL7aFwRIGyKr8ZOOMFxbLOGdeFlqc5TGCP416e8PZvhE+BuDmxiKtQJ/dsQFqVzvOZb2WQRsYRPYvvXbvUw== monitor@isidore
|
|
@ -1 +0,0 @@
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEpvV9dKUVBlv5VU3LU0XIGTQK/McPf3H31HHD/vINGG nix-on-droid@vagrant
|
|
|
@ -1 +0,0 @@
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGYv5vs78+UAeRagopi4BuvmmK1l3zZwQPY3R4rnp7oV tvb@backyard
|
|
|
@ -1 +0,0 @@
|
||||||
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
|
|
|
@ -1 +0,0 @@
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC364peKQVWeqFNzhJJkvHumKerKPkczeX2I/e9FFZyL tvb@centroid
|
|
|
@ -1 +1 @@
|
||||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCuAlVTZ4g7x8Fv3YoHn4KRr5GHfylgJjkC6lujti7Fd3JhZ34OB5L/FuCKLo0rv/1qpIcGHk01FMNT/hDcbyBRPN5QG1s7x39Bt8yBVePoJK0+malGkI90z4zV1b5LEjvRhr7+KuOskt3eVbhKcEXiJpDdqOOgqvppmQZOb6jb03+q01rPLzz0S20jUDLRSdnmlcNDv16lMXTX9zgWDeVIVErTvoLAI8RloqKUgienheLJSS6sdEk4AjL2PKldKE6mIOxZWiYSTS9+2ClqV8u3l1UTZ7+DOw8FWASmMYaaBvJRDEUzDKA/iOAjpfPO7WOn+yjRyiT7IFVFoz2XtXwZD0OEQhbgLZtPlhOHh5wn++YNnvzLYd5cYSWVya0FYzVis24hbaGjrwB5tzD0riL2lRzo3ZjktpL7RlCSLfO/2Cb14hLOxZTZZcgdM6Ef/1YatJiEpRQ7FLP45Di3hKc9QEsqQP1BrhhYQOCWwEHAgVXM8W1ncEBXiCnrelegVy0= tvb@empyrean
|
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
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHGUvJ7Gd1mN2mF/hy12dizwEw64zn+jT0vFpkhGF07s tvb@imperium
|
|
|
@ -1 +0,0 @@
|
||||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCom6c/UrhM6KrzDcm8kJGZJ5ugR4wRfsFUhTJ5F4oLNQcNspvqlUfxT4Hjv4xHA5hCjvPYi7JxVWxBsOEmmIs/LAjFXRNw9Kz8m7TCf/lct+JUpf6eCn6a/orhA0OdUv4c9aiH2Dzp4ob3lR6xYvYUOH3LuffqypSXP0k5zCSetROUgTZibEpa0oE2GevcyjQAExpCjx02ZRIGkGOM20CXtm3EJsTzIs6uk4+2F9hB+HMqePFKCzsgOlFfVCNWiKNywLavXo7Gn0O9pWidufXZ9s8nCBiOEzU1n6T8pNQBat4z7G1uKFKKWNDPL6/HNEmCq0JxUuXSSjg8LIk+uqPH49Ubpf8EORON8z8nVFAAqbuI6rdYc7J9DllQ7hb7EBT9w9w+mcz3XH0BsGzJUOMD9r0P96pWOn+I6A9jPmOqoOZDzGpfYS18+zYWET/ohH4U4pABcW4nwGx0Jz7Fj6iQW3tyjOefuXcz+sJoYKo/9FOh44KYf4pgu3hfoMlGC0M= tvb@unfolder
|
|
|
@ -1,58 +0,0 @@
|
||||||
{ 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";
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
# 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;
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
{ 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,15 +1,13 @@
|
||||||
{ 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)
|
||||||
|
@ -19,26 +17,42 @@
|
||||||
};
|
};
|
||||||
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; } ];
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
console.keyMap = "us";
|
||||||
lsof # list open files
|
i18n.defaultLocale = "en_US.UTF-8";
|
||||||
mkpasswd # used for setting SMB passwords, I think?
|
|
||||||
samba # provides smbpasswd, mostly
|
environment.systemPackages = with pkgs;
|
||||||
smartmontools # provides smartctl
|
let
|
||||||
usbutils # provides lsusb
|
py3-packages = python-packages: with python-packages; [
|
||||||
|
flask
|
||||||
|
];
|
||||||
|
py3-with-packages = python3.withPackages py3-packages;
|
||||||
|
in [
|
||||||
|
wget vim curl git htop bash tmux psmisc man-pages pv lsof
|
||||||
|
zip unzip
|
||||||
|
py3-with-packages
|
||||||
|
usbutils
|
||||||
|
hdparm sdparm smartmontools gptfdisk gnufdisk
|
||||||
|
dosfstools
|
||||||
|
mkpasswd samba
|
||||||
|
tinc_pre
|
||||||
|
#file-rename
|
||||||
|
rsync
|
||||||
|
rclone gnupg
|
||||||
];
|
];
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
hostId = "beeeeee5"; # this must be consistent for ZFS
|
hostName = "catacomb";
|
||||||
|
hostId = "beeeeee5";
|
||||||
firewall = {
|
firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
allowedTCPPorts = [ 139 445 ];
|
allowPing = true;
|
||||||
|
allowedTCPPorts = [ 22 139 445 ];
|
||||||
allowedUDPPorts = [ 137 138 ];
|
allowedUDPPorts = [ 137 138 ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -58,7 +72,15 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.openssh.settings.PasswordAuthentication = true;
|
services.openssh = {
|
||||||
|
enable = true;
|
||||||
|
passwordAuthentication = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.ntp = {
|
||||||
|
enable = true;
|
||||||
|
servers = ["time.nist.gov"];
|
||||||
|
};
|
||||||
|
|
||||||
services.rsyncd.enable = true;
|
services.rsyncd.enable = true;
|
||||||
|
|
||||||
|
@ -140,6 +162,22 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
@ -153,14 +191,19 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.tvb = {
|
users.users.tvb = {
|
||||||
|
isNormalUser = true;
|
||||||
uid = 1001;
|
uid = 1001;
|
||||||
extraGroups = [ "nas" ];
|
password = "badpassword";
|
||||||
packages = [
|
extraGroups = ["wheel" "nas"];
|
||||||
(pkgs.writeShellScriptBin "yt-dlp" ''
|
openssh.authorizedKeys.keyFiles = [
|
||||||
exec $HOME/.env/bin/yt-dlp "$@"
|
../../keys/tvb.palamas.pub
|
||||||
'')
|
../../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;
|
||||||
|
@ -168,4 +211,5 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
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 = "3d6fb16948c377f94d030648849f120c8ada3884";
|
rev = "63574bb39cc777deb56a76548f08789d238fcfec";
|
||||||
};
|
};
|
||||||
catacombServer = pkgs.callPackage catacombServerSource {};
|
catacombServer = pkgs.callPackage catacombServerSource {};
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,6 @@
|
||||||
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";
|
||||||
|
@ -33,6 +28,41 @@
|
||||||
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";
|
||||||
|
@ -43,21 +73,11 @@
|
||||||
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
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
# 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"];
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
{ 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";
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
# 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;
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
{ 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,18 +9,16 @@
|
||||||
[ # 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
|
||||||
./sync-pipeline.nix
|
./inquisitor.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";
|
||||||
};
|
};
|
||||||
|
@ -29,20 +27,42 @@
|
||||||
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; [
|
||||||
tinc_pre
|
vim htop git tinc_pre python3
|
||||||
gitea
|
gitea
|
||||||
];
|
];
|
||||||
|
environment.variables.EDITOR = "vim";
|
||||||
|
|
||||||
services.nginx = let
|
services.nginx = let
|
||||||
static-site = srv-dir: {
|
static-site = srv-dir: {
|
||||||
|
@ -54,36 +74,26 @@
|
||||||
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";
|
||||||
"www.alogoulogoi.com" = static-site "www.alogoulogoi.com";
|
"mirror.alogoulogoi.com" = static-site "mirror.alogoulogoi.com";
|
||||||
"ecumene.alogoulogoi.com" = static-site "ecumene.alogoulogoi.com";
|
"www.alogoulogoi.com" = static-site "www";
|
||||||
# Home service stub domains
|
newtab = {
|
||||||
"mopidy.home.ktvb.site" = service-stub;
|
listen = [ { addr = "10.22.20.1"; port = 80; } ];
|
||||||
"jellyfin.home.ktvb.site" = service-stub;
|
root = "/srv/newtab/";
|
||||||
# mirror revproxy
|
|
||||||
"mirror.alogoulogoi.com" = {
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
access_log /var/log/nginx/access_mirror.alogoulogoi.com.log;
|
access_log /var/log/nginx/access_newtab.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";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -93,9 +103,20 @@
|
||||||
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 = {
|
||||||
settings.PasswordAuthentication = false;
|
enable = true;
|
||||||
settings.PermitRootLogin = "prohibit-password";
|
passwordAuthentication = false;
|
||||||
|
permitRootLogin = "prohibit-password";
|
||||||
};
|
};
|
||||||
|
|
||||||
services.tinc.networks.beatific = {
|
services.tinc.networks.beatific = {
|
||||||
|
@ -103,15 +124,36 @@
|
||||||
chroot = false;
|
chroot = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.intake = {
|
services.nebula.networks.beatific = {
|
||||||
listen = { addr = "10.22.20.1"; };
|
enable = true;
|
||||||
users.tvb.enable = true;
|
|
||||||
users.tvb.extraPackages = [ pkgs.intakeSources pkgs.openssh ];
|
# Network certificate and host credentials
|
||||||
|
ca = "/etc/nebula/beatific/beatific.crt";
|
||||||
|
cert = "/etc/nebula/beatific/empyrean.crt";
|
||||||
|
key = "/etc/nebula/beatific/empyrean.key";
|
||||||
|
|
||||||
|
# This host has a well-known IP at its VPS host, so it can function as a lighthouse/entry node
|
||||||
|
isLighthouse = true;
|
||||||
|
|
||||||
|
# Listen to connection requests from the public Internet
|
||||||
|
listen.port = 4242;
|
||||||
|
listen.host = "vpn.alogoulogoi.com";
|
||||||
|
|
||||||
|
# Don't filter anything at the VPN level
|
||||||
|
firewall.outbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
||||||
|
firewall.inbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
# Enable UDP holepunching both ways, which allows nodes to establish more direct connections with each other
|
||||||
|
punchy = { punch = true; response = true; };
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
||||||
|
@ -121,13 +163,50 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 = {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
users.users.guestbook = let
|
||||||
|
sign-guestbook = pkgs.writeShellScriptBin "sign-guestbook" ''
|
||||||
|
echo "Hello world!"
|
||||||
|
''
|
||||||
|
# Hack the shell path in since writeShellScriptBin doesn't take passthru
|
||||||
|
// { shellPath = "/bin/sign-guestbook"; };
|
||||||
|
in {
|
||||||
|
group = "guestbook";
|
||||||
|
password = "";
|
||||||
|
description = "Guestbook login";
|
||||||
|
shell = sign-guestbook;
|
||||||
|
isNormalUser = true;
|
||||||
|
createHome = false;
|
||||||
|
home = "/var/empty";
|
||||||
|
useDefaultShell = false;
|
||||||
|
};
|
||||||
|
users.groups.guestbook = {};
|
||||||
|
services.openssh.extraConfig = ''
|
||||||
|
Match user guestbook
|
||||||
|
PasswordAuthentication yes
|
||||||
|
PermitEmptyPasswords yes
|
||||||
|
Match all
|
||||||
|
PasswordAuthentication no
|
||||||
|
'';*/
|
||||||
|
|
||||||
# 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 = "23.05"; # Did you read the comment?
|
system.stateVersion = "20.03"; # Did you read the comment?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,12 @@
|
||||||
{
|
{
|
||||||
# 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
|
||||||
|
|
||||||
|
@ -17,13 +22,6 @@
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
@ -39,13 +37,10 @@
|
||||||
"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; # TODO: figure out why this was enabled
|
"cron.archive_cleanup".ENABLED = false;
|
||||||
"cron.sync_external_users".ENABLED = false;
|
"cron.sync_external_users".ENABLED = false;
|
||||||
log.LEVEL = "Info";
|
log.LEVEL = "Info";
|
||||||
# Private server
|
# Private server
|
||||||
|
@ -71,8 +66,5 @@
|
||||||
proxy_pass http://localhost:3300/;
|
proxy_pass http://localhost:3300/;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
# Give tvb group access to gitea config
|
|
||||||
users.users.tvb.extraGroups = [ "gitea" ];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
{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;
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
# 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 ];
|
||||||
|
}
|
|
@ -1,75 +0,0 @@
|
||||||
{ 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"}"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
{ 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";
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
# 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,10 +16,9 @@ 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";
|
||||||
|
|
|
@ -1,103 +0,0 @@
|
||||||
{ 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";
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
# 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;
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
{
|
|
||||||
beatific = ''
|
|
||||||
____ ______ _______ _____ ______ _____ ______ ./|,,/|
|
|
||||||
| _ \| ____| /\ |__ __|_ _| ____|_ _|/ ____/ < o o|
|
|
||||||
| |_) | |__ / \ | | | | | |__ | | | | <\ ( |
|
|
||||||
| _ <| __| / /\ \ | | | | | __| | | | | <\\ |\ |
|
|
||||||
| |_) | |____/ ____ \ | | _| |_| | _| |_| |___<\\\ |(__)
|
|
||||||
|____/|_____/_/ \_\|_| |_____|_| |_____|\_____|\\ |
|
|
||||||
'';
|
|
||||||
|
|
||||||
backyard = ''
|
|
||||||
____ ______ _ ____ __ _____ _____ ./|,,/|
|
|
||||||
| _ \ /\ / ____/| | / /\ \ / / /\ | __ \| __ \ < o o|
|
|
||||||
| |_) | / \ | | | |/ / \ \ / / / \ | |__) | | | |</ ( |
|
|
||||||
| _ < / /\ \| | | < \ V / / /\ \ | _ /| | | |// |\ |
|
|
||||||
| |_) / ____ | |____ | |\ \ | | / ____ \| | \ \| |__| |// |(__)
|
|
||||||
|____/_/ \_\_____\|_| \_\ |_|/_/ \_|_| \_|_____//// |
|
|
||||||
'';
|
|
||||||
|
|
||||||
catacomb = ''
|
|
||||||
______ _______ ______ ____ __ __ ____ ./|,,/|
|
|
||||||
/ ____/ /\ |__ __| /\ / ____// __ \| \ / | _ \ < o o|
|
|
||||||
| | / \ | | / \ | | | | | | . \/ . | |_) | ( |
|
|
||||||
| | / /\ \ | | / /\ \| | | | | | |\ /| | _ <\\ |\ |
|
|
||||||
| |____ / ____ \ | | / ____ | |__ _| |__| | | \/ | | |_) |\ |(__)
|
|
||||||
\_____/_/ \_\|_|/_/ \_\_____\\____/|_| |_|____/\\ |
|
|
||||||
'';
|
|
||||||
|
|
||||||
empyrean = ''
|
|
||||||
______ __ __ _______ _______ ______ _ _ ./|,,/|
|
|
||||||
| ____| \ / | __ \ \ / | __ \| ____| /\ | \ | | < o o|
|
|
||||||
| |__ | . \/ . | |__) \ \ / /| |__) | |__ / \ | \| |</ ( |
|
|
||||||
| __| | |\ /| | ___/ \ V / | _ /| __| / /\ \ | . ' |// |\ |
|
|
||||||
| |____| | \/ | | | | | | | \ \| |____ / ____ \| |\ |// |(__)
|
|
||||||
|______|_| |_|_| |_| |_| \_|______/_/ \_|_| \_|// |
|
|
||||||
'';
|
|
||||||
|
|
||||||
unfolder = ''
|
|
||||||
_ _ _ _ ______ ____ _ _____ ______ _____ ./|,,/|
|
|
||||||
| | | | \ | | ____|/ __ \| | | __ \| ____| __ \ < o o|
|
|
||||||
| | | | \| | |__ | | | | | | | | | |__ | |__) |\ ( |
|
|
||||||
| | | | . ' | __| | | | | | | | | | __| | _ /\\ |\ |
|
|
||||||
| |__| | |\ | | | |__| | |___| |__| | |____| | \ \\\ |(__)
|
|
||||||
\____/|_| \_|_| \____/|_____|_____/|______|_| <\_\\ |
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
# 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,252 +1,23 @@
|
||||||
{ config, lib, pkgs, ... }:
|
# Shared configuration values
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (lib) mkDefault mkIf mkMerge mkOption mkOverride types;
|
nebula-port = 4242;
|
||||||
cfg = config.beatific;
|
empyrean-vpn-ip = "10.22.20.1";
|
||||||
mkFlag = description: mkOption {
|
empyrean-ext-dns = "vpn.alogoulogoi.com";
|
||||||
type = types.bool;
|
|
||||||
inherit description;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
in {
|
in {
|
||||||
options = {
|
nebula-defaults = {
|
||||||
beatific = {
|
listen.port = nebula-port;
|
||||||
# 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 {
|
# Don't filter at the VPN level
|
||||||
type = types.bool;
|
firewall.outbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
||||||
description = "Whether this host is a Nebula lighthouse";
|
firewall.inbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
extraPrograms = mkOption {
|
settings = {
|
||||||
type = types.bool;
|
# Enable UDP holepunching both ways, which allows nodes to establish more direct connections with each other
|
||||||
description = "Additional default programs";
|
punchy = { punch = true; response = true; };
|
||||||
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 [
|
inherit empyrean-vpn-ip;
|
||||||
{
|
empyrean-host-map = { ${empyrean-vpn-ip} = [ "${empyrean-ext-dns}:${toString nebula-port}" ]; };
|
||||||
# Options to always set
|
|
||||||
networking.hostName = cfg.hostName;
|
|
||||||
nix.extraOptions = "experimental-features = nix-command flakes";
|
|
||||||
# Link /etc/nixos to the flake source
|
|
||||||
environment.etc.nixos.source = ./..;
|
|
||||||
environment.etc."bashrc.local".source = ./bashrc;
|
|
||||||
environment.shellAliases = {
|
|
||||||
# Shortcut for nixos-rebuild
|
|
||||||
nr = "sudo nixos-rebuild --fast --flake $HOME/nixos-configs";
|
|
||||||
# Always preserve mode, ownership, ts with copy
|
|
||||||
cp = "cp -rp";
|
|
||||||
xo = "xdg-open";
|
|
||||||
smv = "rsync -v --remove-source-files";
|
|
||||||
".." = "cd ..";
|
|
||||||
"..." = "cd ../..";
|
|
||||||
"...." = "cd ../../..";
|
|
||||||
"....." = "cd ../../../..";
|
|
||||||
};
|
|
||||||
security.sudo.extraRules = [{
|
|
||||||
users = [ "tvb" ];
|
|
||||||
commands = [ { command = "/run/current-system/sw/bin/nixos-rebuild"; options = [ "NOPASSWD" ]; } ];
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
(mkIf cfg.defaults.time {
|
|
||||||
# mkDefault time zone to make it easy to configure it to non-UTC
|
|
||||||
time.timeZone = mkDefault "UTC";
|
|
||||||
services.ntp.enable = true;
|
|
||||||
services.ntp.servers = [ "time.nist.gov" ];
|
|
||||||
})
|
|
||||||
|
|
||||||
(mkIf cfg.defaults.i18n {
|
|
||||||
# en_US.UTF-8
|
|
||||||
i18n.defaultLocale = "en_US.UTF-8";
|
|
||||||
i18n.extraLocaleSettings = {
|
|
||||||
LC_ADDRESS = "en_US.UTF-8";
|
|
||||||
LC_IDENTIFICATION = "en_US.UTF-8";
|
|
||||||
LC_MEASUREMENT = "en_US.UTF-8";
|
|
||||||
LC_MONETARY = "en_US.UTF-8";
|
|
||||||
LC_NAME = "en_US.UTF-8";
|
|
||||||
LC_NUMERIC = "en_US.UTF-8";
|
|
||||||
LC_PAPER = "en_US.UTF-8";
|
|
||||||
LC_TELEPHONE = "en_US.UTF-8";
|
|
||||||
LC_TIME = "en_US.UTF-8";
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(mkIf cfg.defaults.programs {
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
bc # Terminal calculator
|
|
||||||
curl
|
|
||||||
duf
|
|
||||||
exiftool
|
|
||||||
file # File type inspector
|
|
||||||
htmlq # jq for html
|
|
||||||
jq # jq for json
|
|
||||||
nebula
|
|
||||||
psmisc # provides killall
|
|
||||||
python3
|
|
||||||
rsync
|
|
||||||
sqlite
|
|
||||||
tree # Directory tree view
|
|
||||||
unzip
|
|
||||||
vim
|
|
||||||
wget
|
|
||||||
zip
|
|
||||||
(writeShellScriptBin "clip" ''
|
|
||||||
${xclip}/bin/xclip -sel c < $1
|
|
||||||
'')
|
|
||||||
];
|
|
||||||
programs = {
|
|
||||||
git = {
|
|
||||||
enable = true;
|
|
||||||
config.init.defaultBranch = "master";
|
|
||||||
};
|
|
||||||
htop.enable = true;
|
|
||||||
};
|
|
||||||
# The nixpkgs default is "nano", so we go one priority higher
|
|
||||||
environment.variables.EDITOR = mkOverride 999 "vim";
|
|
||||||
})
|
|
||||||
|
|
||||||
(mkIf cfg.extraPrograms {
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
calibre # provides ebook-convert
|
|
||||||
imagemagick # image convertion cli
|
|
||||||
puddletag # mp3 tag editor
|
|
||||||
tesseract # OCR engine
|
|
||||||
];
|
|
||||||
})
|
|
||||||
|
|
||||||
(mkIf cfg.defaults.ssh {
|
|
||||||
services.openssh.enable = true;
|
|
||||||
services.openssh.banner = let
|
|
||||||
ascii = import ./ascii.nix;
|
|
||||||
in ascii.${cfg.hostName} or ascii.beatific;
|
|
||||||
networking.firewall.allowPing = true;
|
|
||||||
networking.firewall.allowedTCPPorts = [ 22 ];
|
|
||||||
})
|
|
||||||
|
|
||||||
(mkIf cfg.defaults.nebula {
|
|
||||||
services.nebula.networks.beatific = let
|
|
||||||
empyreanExternalDns = "vpn.alogoulogoi.com";
|
|
||||||
empyreanInternalIp = "10.22.20.1";
|
|
||||||
nebulaPort = 4242;
|
|
||||||
in {
|
|
||||||
enable = true;
|
|
||||||
|
|
||||||
# The lighthouse only listens on the designated subdomain
|
|
||||||
listen.host = if cfg.isLighthouse then empyreanExternalDns else "0.0.0.0";
|
|
||||||
listen.port = nebulaPort;
|
|
||||||
|
|
||||||
# Standard certificate paths
|
|
||||||
ca = "/etc/nebula/beatific/beatific.crt";
|
|
||||||
cert = "/etc/nebula/beatific/${cfg.hostName}.crt";
|
|
||||||
key = "/etc/nebula/beatific/${cfg.hostName}.key";
|
|
||||||
|
|
||||||
isLighthouse = cfg.isLighthouse;
|
|
||||||
# Non-lighthouses connect to the lighthouse at empyrean
|
|
||||||
# This should be a VPN address in the static host map
|
|
||||||
lighthouses = mkIf (! cfg.isLighthouse) [ empyreanInternalIp ];
|
|
||||||
|
|
||||||
# Currently there is no VPN-level traffic filtering
|
|
||||||
firewall.outbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
|
||||||
firewall.inbound = [ { port = "any"; proto = "any"; host = "any"; } ];
|
|
||||||
|
|
||||||
# Map the lighthouse address to its public address
|
|
||||||
staticHostMap = { ${empyreanInternalIp} = [ "${empyreanExternalDns}:${toString nebulaPort}" ]; };
|
|
||||||
|
|
||||||
settings = {
|
|
||||||
# Enable UDP holepunching both ways, which allows nodes to establish more direct connections with each other
|
|
||||||
punchy = { punch = true; response = true; };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(mkIf cfg.defaults.tvb {
|
|
||||||
users.groups.tvb = {};
|
|
||||||
users.users.tvb = {
|
|
||||||
isNormalUser = true;
|
|
||||||
group = "tvb";
|
|
||||||
extraGroups = [ "wheel" ];
|
|
||||||
initialPassword = "password";
|
|
||||||
openssh.authorizedKeys.keyFiles = (import ../keys).tvb;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(mkIf cfg.defaults.tvbSync {
|
|
||||||
# I haven't gotten user services to work correctly yet,
|
|
||||||
# so for now, tvb monopolizes the system syncthing instance.
|
|
||||||
# Adding users in the future should probably involve multiple
|
|
||||||
# system services so as not to require login to sync.
|
|
||||||
services.syncthing = {
|
|
||||||
enable = true;
|
|
||||||
configDir = "/home/tvb/.config/syncthing";
|
|
||||||
# this doesn't prevent syncthing from putting sync points in other locations, it's just a default
|
|
||||||
# normally it would make sense to put it at ~ but see https://github.com/NixOS/nixpkgs/pull/273693
|
|
||||||
dataDir = "/home/tvb/.config/syncthing";
|
|
||||||
openDefaultPorts = true;
|
|
||||||
user = "tvb";
|
|
||||||
group = "tvb";
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(mkIf cfg.defaults.hosts {
|
|
||||||
# Create *.home host entries for all the beatific members
|
|
||||||
networking.hosts = {
|
|
||||||
"10.22.20.1" = [
|
|
||||||
"empyrean.home"
|
|
||||||
];
|
|
||||||
"10.22.20.2" = [
|
|
||||||
"catacomb.home"
|
|
||||||
"mirror.catacomb.home"
|
|
||||||
];
|
|
||||||
"10.22.20.3" = [
|
|
||||||
"palamas.home"
|
|
||||||
];
|
|
||||||
"10.22.20.4" = [
|
|
||||||
"stagirite.home"
|
|
||||||
];
|
|
||||||
"10.22.20.5" = [
|
|
||||||
"vagrant.home"
|
|
||||||
];
|
|
||||||
"10.22.20.6" = [
|
|
||||||
"unfolder.home"
|
|
||||||
];
|
|
||||||
"10.22.20.7" = [
|
|
||||||
"centroid.home"
|
|
||||||
"mopidy.home.ktvb.site"
|
|
||||||
];
|
|
||||||
"10.22.20.8" = [
|
|
||||||
"backyard.home"
|
|
||||||
"jellyfin.home.ktvb.site"
|
|
||||||
];
|
|
||||||
"10.22.20.9" = [
|
|
||||||
"imperium.home"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,722 +0,0 @@
|
||||||
{ 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