up
This commit is contained in:
24
flake.lock
generated
24
flake.lock
generated
@@ -100,11 +100,11 @@
|
|||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1755107032,
|
"lastModified": 1755121891,
|
||||||
"narHash": "sha256-ckb/RX9rJ/FslBA3K4hYAXgVW/7JdQ50Z+28XZT96zg=",
|
"narHash": "sha256-UtYkukiGnPRJ5rpd4W/wFVrLMh8fqtNkqHTPgHEtrqU=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "4b6dd06c6a92308c06da5e0e55f2c505237725c9",
|
"rev": "279ca5addcdcfa31ac852b3ecb39fc372684f426",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -132,11 +132,11 @@
|
|||||||
"homebrew-cask": {
|
"homebrew-cask": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1755104931,
|
"lastModified": 1755147939,
|
||||||
"narHash": "sha256-jtXcymAnYH/hCvEGaUlt5vpFwqx00/r5Wly9UCqy7vQ=",
|
"narHash": "sha256-PD93pCq6q6xtWxtFwK9WCugELrcy50Om7/VLgpV0raM=",
|
||||||
"owner": "homebrew",
|
"owner": "homebrew",
|
||||||
"repo": "homebrew-cask",
|
"repo": "homebrew-cask",
|
||||||
"rev": "53dc289ce38d2561d853b482d0f03914a7f2f985",
|
"rev": "5fd00a85f58743b2ac654bfbdda762b8e7d4fbcb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -148,11 +148,11 @@
|
|||||||
"homebrew-core": {
|
"homebrew-core": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1755104716,
|
"lastModified": 1755152577,
|
||||||
"narHash": "sha256-6jp9InEQfaVJR4kSdwb0+D6603DanSUEFF3uYYPIQVM=",
|
"narHash": "sha256-ix1DIoJEn4V0dOErK12AkIL/iPHtGmGR+/HjyNLwnXQ=",
|
||||||
"owner": "homebrew",
|
"owner": "homebrew",
|
||||||
"repo": "homebrew-core",
|
"repo": "homebrew-core",
|
||||||
"rev": "8aa4cd22422bcb03de07c08c24773257d928e988",
|
"rev": "b3da0366f58c2f89d8c0d1cabdc7cd5bdc732313",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -240,11 +240,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1755109924,
|
"lastModified": 1755154419,
|
||||||
"narHash": "sha256-2xroOWuRFMLvqknLQJ8gmpdXuvg9t5qDUJ3KQKq5/GE=",
|
"narHash": "sha256-m8tJUveXe6y73A2wvXRomSC5WwBsNfLgZI3qteAAqyU=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "b7f46264dd0a1891d52c9a8b919c2eebbc527638",
|
"rev": "1a58620315b9d6d3c8110ec35ee46bbacb2fe633",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -43,8 +43,7 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
flake.darwinConfigurations = inputs.nixpkgs.lib.genAttrs darwinHosts (
|
flake.darwinConfigurations = inputs.nixpkgs.lib.genAttrs darwinHosts (
|
||||||
hostname:
|
hostname: let
|
||||||
let
|
|
||||||
syncthingOverlay = import ./overlays/syncthing-darwin.nix;
|
syncthingOverlay = import ./overlays/syncthing-darwin.nix;
|
||||||
syncthingModule = (syncthingOverlay null {}).darwinSyncthingModule;
|
syncthingModule = (syncthingOverlay null {}).darwinSyncthingModule;
|
||||||
in
|
in
|
||||||
@@ -61,7 +60,7 @@
|
|||||||
syncthingModule
|
syncthingModule
|
||||||
|
|
||||||
{
|
{
|
||||||
nixpkgs.overlays = [ syncthingOverlay ];
|
nixpkgs.overlays = [syncthingOverlay];
|
||||||
|
|
||||||
nix-homebrew = {
|
nix-homebrew = {
|
||||||
inherit user;
|
inherit user;
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
{
|
{user, ...}: {
|
||||||
user,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
imports = [
|
||||||
../shared.nix
|
../shared.nix
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -65,7 +65,6 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
services.postgresql = {
|
services.postgresql = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.postgresql_17;
|
package = pkgs.postgresql_17;
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
{ pkgs, lib, ... }:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
services.tailscale = {
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
services.tailscale =
|
||||||
|
{
|
||||||
enable = true;
|
enable = true;
|
||||||
} // lib.optionalAttrs pkgs.stdenv.isLinux {
|
}
|
||||||
useRoutingFeatures = "server";
|
// lib.optionalAttrs pkgs.stdenv.isLinux {
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
|
useRoutingFeatures = "server";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
final: prev: {
|
final: prev: {
|
||||||
darwinSyncthingModule = { config, lib, pkgs, ... }:
|
darwinSyncthingModule = {
|
||||||
with lib;
|
config,
|
||||||
let
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
cfg = config.services.syncthing;
|
cfg = config.services.syncthing;
|
||||||
defaultUser = "syncthing";
|
defaultUser = "syncthing";
|
||||||
defaultGroup = defaultUser;
|
defaultGroup = defaultUser;
|
||||||
settingsFormat = pkgs.formats.json { };
|
settingsFormat = pkgs.formats.json {};
|
||||||
cleanedConfig = converge (filterAttrsRecursive (_: v: v != null && v != { })) cfg.settings;
|
cleanedConfig = converge (filterAttrsRecursive (_: v: v != null && v != {})) cfg.settings;
|
||||||
|
|
||||||
isUnixGui = (builtins.substring 0 1 cfg.guiAddress) == "/";
|
isUnixGui = (builtins.substring 0 1 cfg.guiAddress) == "/";
|
||||||
|
|
||||||
@@ -15,21 +19,24 @@ final: prev: {
|
|||||||
then "--unix-socket ${cfg.guiAddress} http://.${path}"
|
then "--unix-socket ${cfg.guiAddress} http://.${path}"
|
||||||
else "${cfg.guiAddress}${path}";
|
else "${cfg.guiAddress}${path}";
|
||||||
|
|
||||||
devices = mapAttrsToList (_: device: device // { deviceID = device.id; }) cfg.settings.devices;
|
devices = mapAttrsToList (_: device: device // {deviceID = device.id;}) cfg.settings.devices;
|
||||||
anyAutoAccept = builtins.any (dev: dev.autoAcceptFolders) devices;
|
anyAutoAccept = builtins.any (dev: dev.autoAcceptFolders) devices;
|
||||||
|
|
||||||
folders = mapAttrsToList (_: folder: folder // {
|
folders = mapAttrsToList (_: folder:
|
||||||
|
folder
|
||||||
|
// {
|
||||||
devices = let
|
devices = let
|
||||||
folderDevices = folder.devices;
|
folderDevices = folder.devices;
|
||||||
in
|
in
|
||||||
map (device:
|
map (
|
||||||
if builtins.isString device then
|
device:
|
||||||
{ deviceId = cfg.settings.devices.${device}.id; }
|
if builtins.isString device
|
||||||
else if builtins.isAttrs device then
|
then {deviceId = cfg.settings.devices.${device}.id;}
|
||||||
{ deviceId = cfg.settings.devices.${device.name}.id; } // device
|
else if builtins.isAttrs device
|
||||||
else
|
then {deviceId = cfg.settings.devices.${device.name}.id;} // device
|
||||||
throw "Invalid type for devices in folder; expected list or attrset."
|
else throw "Invalid type for devices in folder; expected list or attrset."
|
||||||
) folderDevices;
|
)
|
||||||
|
folderDevices;
|
||||||
}) (filterAttrs (_: folder: folder.enable) cfg.settings.folders);
|
}) (filterAttrs (_: folder: folder.enable) cfg.settings.folders);
|
||||||
|
|
||||||
jq = "${pkgs.jq}/bin/jq";
|
jq = "${pkgs.jq}/bin/jq";
|
||||||
@@ -67,15 +74,17 @@ final: prev: {
|
|||||||
baseAddress = curlAddressArgs "/rest/config/folders";
|
baseAddress = curlAddressArgs "/rest/config/folders";
|
||||||
};
|
};
|
||||||
} [
|
} [
|
||||||
(mapAttrs (conf_type: s:
|
(mapAttrs (
|
||||||
|
conf_type: s:
|
||||||
lib.pipe s.conf [
|
lib.pipe s.conf [
|
||||||
(map (new_cfg:
|
(map (
|
||||||
let
|
new_cfg: let
|
||||||
jsonPreSecretsFile = pkgs.writeTextFile {
|
jsonPreSecretsFile = pkgs.writeTextFile {
|
||||||
name = "${conf_type}-${new_cfg.id}-conf-pre-secrets.json";
|
name = "${conf_type}-${new_cfg.id}-conf-pre-secrets.json";
|
||||||
text = builtins.toJSON new_cfg;
|
text = builtins.toJSON new_cfg;
|
||||||
};
|
};
|
||||||
injectSecretsJqCmd = {
|
injectSecretsJqCmd =
|
||||||
|
{
|
||||||
"devs" = "${jq} .";
|
"devs" = "${jq} .";
|
||||||
"dirs" = let
|
"dirs" = let
|
||||||
folder = new_cfg;
|
folder = new_cfg;
|
||||||
@@ -87,7 +96,8 @@ final: prev: {
|
|||||||
secretPath = device.encryptionPasswordFile;
|
secretPath = device.encryptionPasswordFile;
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
jqUpdates = map (device: ''
|
jqUpdates =
|
||||||
|
map (device: ''
|
||||||
.devices[] |= (
|
.devices[] |= (
|
||||||
if .deviceId == "${device.deviceId}" then
|
if .deviceId == "${device.deviceId}" then
|
||||||
del(.encryptionPasswordFile) |
|
del(.encryptionPasswordFile) |
|
||||||
@@ -96,13 +106,14 @@ final: prev: {
|
|||||||
.
|
.
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
'') devicesWithSecrets;
|
'')
|
||||||
|
devicesWithSecrets;
|
||||||
jqRawFiles = map (device: "--rawfile ${device.variableName} ${lib.escapeShellArg device.secretPath}") devicesWithSecrets;
|
jqRawFiles = map (device: "--rawfile ${device.variableName} ${lib.escapeShellArg device.secretPath}") devicesWithSecrets;
|
||||||
in
|
in "${jq} ${lib.concatStringsSep " " jqRawFiles} ${lib.escapeShellArg (lib.concatStringsSep "|" (["."] ++ jqUpdates))}";
|
||||||
"${jq} ${lib.concatStringsSep " " jqRawFiles} ${lib.escapeShellArg (lib.concatStringsSep "|" ([ "." ] ++ jqUpdates))}";
|
}.${
|
||||||
}.${conf_type};
|
conf_type
|
||||||
in
|
};
|
||||||
''
|
in ''
|
||||||
${injectSecretsJqCmd} ${jsonPreSecretsFile} | curl --json @- -X POST ${s.baseAddress}
|
${injectSecretsJqCmd} ${jsonPreSecretsFile} | curl --json @- -X POST ${s.baseAddress}
|
||||||
''
|
''
|
||||||
))
|
))
|
||||||
@@ -125,7 +136,7 @@ final: prev: {
|
|||||||
])
|
])
|
||||||
+ (lib.pipe cleanedConfig [
|
+ (lib.pipe cleanedConfig [
|
||||||
builtins.attrNames
|
builtins.attrNames
|
||||||
(lib.subtractLists [ "folders" "devices" ])
|
(lib.subtractLists ["folders" "devices"])
|
||||||
(map (subOption: ''
|
(map (subOption: ''
|
||||||
curl -X PUT -d ${lib.escapeShellArg (builtins.toJSON cleanedConfig.${subOption})} ${curlAddressArgs "/rest/config/${subOption}"}
|
curl -X PUT -d ${lib.escapeShellArg (builtins.toJSON cleanedConfig.${subOption})} ${curlAddressArgs "/rest/config/${subOption}"}
|
||||||
''))
|
''))
|
||||||
@@ -138,8 +149,7 @@ final: prev: {
|
|||||||
fi
|
fi
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
services.syncthing = {
|
services.syncthing = {
|
||||||
enable = mkEnableOption "Syncthing, a self-hosted open-source alternative to Dropbox and Bittorrent Sync";
|
enable = mkEnableOption "Syncthing, a self-hosted open-source alternative to Dropbox and Bittorrent Sync";
|
||||||
@@ -173,7 +183,7 @@ final: prev: {
|
|||||||
freeformType = settingsFormat.type;
|
freeformType = settingsFormat.type;
|
||||||
options = {
|
options = {
|
||||||
options = mkOption {
|
options = mkOption {
|
||||||
default = { };
|
default = {};
|
||||||
description = "The options element contains all other global configuration options";
|
description = "The options element contains all other global configuration options";
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
freeformType = settingsFormat.type;
|
freeformType = settingsFormat.type;
|
||||||
@@ -203,9 +213,9 @@ final: prev: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
devices = mkOption {
|
devices = mkOption {
|
||||||
default = { };
|
default = {};
|
||||||
description = "Peers/devices which Syncthing should communicate with.";
|
description = "Peers/devices which Syncthing should communicate with.";
|
||||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
type = types.attrsOf (types.submodule ({name, ...}: {
|
||||||
freeformType = settingsFormat.type;
|
freeformType = settingsFormat.type;
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
@@ -227,9 +237,9 @@ final: prev: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
folders = mkOption {
|
folders = mkOption {
|
||||||
default = { };
|
default = {};
|
||||||
description = "Folders which should be shared by Syncthing.";
|
description = "Folders which should be shared by Syncthing.";
|
||||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
type = types.attrsOf (types.submodule ({name, ...}: {
|
||||||
freeformType = settingsFormat.type;
|
freeformType = settingsFormat.type;
|
||||||
options = {
|
options = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
@@ -253,7 +263,7 @@ final: prev: {
|
|||||||
description = "The label of the folder.";
|
description = "The label of the folder.";
|
||||||
};
|
};
|
||||||
type = mkOption {
|
type = mkOption {
|
||||||
type = types.enum [ "sendreceive" "sendonly" "receiveonly" "receiveencrypted" ];
|
type = types.enum ["sendreceive" "sendonly" "receiveonly" "receiveencrypted"];
|
||||||
default = "sendreceive";
|
default = "sendreceive";
|
||||||
description = "Controls how the folder is handled by Syncthing.";
|
description = "Controls how the folder is handled by Syncthing.";
|
||||||
};
|
};
|
||||||
@@ -275,7 +285,7 @@ final: prev: {
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
default = [ ];
|
default = [];
|
||||||
description = "The devices this folder should be shared with.";
|
description = "The devices this folder should be shared with.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -283,7 +293,7 @@ final: prev: {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
default = { };
|
default = {};
|
||||||
description = "Extra configuration options for Syncthing.";
|
description = "Extra configuration options for Syncthing.";
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -323,7 +333,7 @@ final: prev: {
|
|||||||
description = "Whether to open the default ports in the firewall (not applicable on Darwin).";
|
description = "Whether to open the default ports in the firewall (not applicable on Darwin).";
|
||||||
};
|
};
|
||||||
|
|
||||||
package = mkPackageOption pkgs "syncthing" { };
|
package = mkPackageOption pkgs "syncthing" {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -335,14 +345,18 @@ final: prev: {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
environment.systemPackages = [ cfg.package ];
|
environment.systemPackages = [cfg.package];
|
||||||
|
|
||||||
launchd.user.agents.syncthing = {
|
launchd.user.agents.syncthing = {
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ProgramArguments = [
|
ProgramArguments = [
|
||||||
"${cfg.package}/bin/syncthing"
|
"${cfg.package}/bin/syncthing"
|
||||||
"-no-browser"
|
"-no-browser"
|
||||||
"-gui-address=${if isUnixGui then "unix://" else ""}${cfg.guiAddress}"
|
"-gui-address=${
|
||||||
|
if isUnixGui
|
||||||
|
then "unix://"
|
||||||
|
else ""
|
||||||
|
}${cfg.guiAddress}"
|
||||||
"-config=${cfg.configDir}"
|
"-config=${cfg.configDir}"
|
||||||
"-data=${cfg.configDir}"
|
"-data=${cfg.configDir}"
|
||||||
];
|
];
|
||||||
@@ -358,9 +372,9 @@ final: prev: {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
launchd.user.agents.syncthing-init = mkIf (cleanedConfig != { }) {
|
launchd.user.agents.syncthing-init = mkIf (cleanedConfig != {}) {
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ProgramArguments = [ "${updateConfig}" ];
|
ProgramArguments = ["${updateConfig}"];
|
||||||
RunAtLoad = true;
|
RunAtLoad = true;
|
||||||
KeepAlive = false;
|
KeepAlive = false;
|
||||||
ProcessType = "Background";
|
ProcessType = "Background";
|
||||||
|
|||||||
Reference in New Issue
Block a user