created module

This commit is contained in:
Leyla Becker 2025-03-13 01:31:34 -05:00
commit 8a8fe8cfc6
11 changed files with 351 additions and 0 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
result
.direnv
.vscode/*
!.vscode/settings.json

3
base-module.nix Normal file
View file

@ -0,0 +1,3 @@
config: {
options = (import ./configuration-type.nix) config;
}

120
configuration-type.nix Normal file
View file

@ -0,0 +1,120 @@
{lib, ...}: let
folderType = lib.types.submodule ({name, ...}: {
options = {
id = lib.mkOption {
type = lib.types.string;
};
label = lib.mkOption {
type = lib.types.string;
default = name;
};
};
});
in {
folders = lib.mkOption {
type = lib.types.attrsOf folderType;
default = {};
};
devices = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
options = {
name = lib.mkOption {
type = lib.types.string;
default = name;
};
id = lib.mkOption {
type = lib.types.string;
};
folders = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule (
{config, ...}: {
options = {
folder = lib.mkOption {
type = folderType;
};
path = lib.mkOption {
type = lib.types.string;
};
type = lib.mkOption {
type = lib.types.enum ["sendreceive" "sendonly" "receiveonly" "receiveencrypted"];
default = "sendreceive";
};
versioning = {
simple = {
enable = lib.mkEnableOption "should this folder use simple versioning";
keep = lib.mkOption {
type = lib.types.string;
default = "10";
};
};
trashcan = {
enable = lib.mkEnableOption "should this folder use trashcan versioning";
cleanoutDays = lib.mkOption {
type = lib.types.string;
default = "1000";
};
};
staggered = {
enable = lib.mkEnableOption "should this folder use staggard versioning";
cleanInterval = lib.mkOption {
type = lib.types.string;
default = "3600";
};
maxAge = lib.mkOption {
type = lib.types.string;
default = "31536000";
};
};
external = {
enable = lib.mkEnableOption "should this folder use external versioning";
};
};
};
# TODO: figure out how to make assertions for submodules
# config = {
# assertions =
# (lib.lists.optionals config.versioning.simple.enable [
# {
# assertion = !config.versioning.trashcan.enable;
# message = "Can not use both simple and trashcan versioning at the same time.";
# }
# {
# assertion = !config.versioning.staggered.enable;
# message = "Can not use both simple and staggered versioning at the same time.";
# }
# {
# assertion = !config.versioning.external.enable;
# message = "Can not use both simple and external versioning at the same time.";
# }
# ])
# ++ (lib.lists.optionals config.versioning.trashcan.enable [
# {
# assertion = !config.versioning.staggered.enable;
# message = "Can not use both trashcan and staggered versioning at the same time.";
# }
# {
# assertion = !config.versioning.external.enable;
# message = "Can not use both trashcan and external versioning at the same time.";
# }
# ])
# ++ (lib.lists.optionals config.versioning.staggered.enable [
# {
# assertion = !config.versioning.external.enable;
# message = "Can not use both staggered and external versioning at the same time.";
# }
# ])
# ++ [
# {
# assertion = !config.versioning.external.enable;
# message = "External versioning currently not implemented.";
# }
# ];
# };
}
));
};
};
}));
default = {};
};
}

9
eval-config.nix Normal file
View file

@ -0,0 +1,9 @@
{
lib,
modules,
}: let
result = lib.evalModules {
inherit modules;
};
in
result.config

47
example-module.nix Normal file
View file

@ -0,0 +1,47 @@
{config, ...}: {
folders = {
documents = {
id = "aaaaa-aaaaa";
};
photos = {
id = "bbbbb-bbbbb";
};
};
devices = {
desktop = {
id = "AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA";
folders = {
documents = {
folder = config.folders.documents;
path = "/sync/user/documents";
};
photos = {
folder = config.folders.photos;
path = "/sync/user/photos";
};
};
};
laptop = {
id = "BBBBBBB-BBBBBBB-BBBBBBB-BBBBBBB-BBBBBBB-BBBBBBB-BBBBBBB-BBBBBBB";
folders = {
documents = {
folder = config.folders.documents;
path = "/sync/documents";
};
photos = {
folder = config.folders.photos;
path = "/sync/photos";
};
};
};
phone = {
id = "CCCCCCC-CCCCCCC-CCCCCCC-CCCCCCC-CCCCCCC-CCCCCCC-CCCCCCC-CCCCCCC";
folders = {
photos = {
folder = config.folders.photos;
path = "/sync/photos";
};
};
};
};
}

11
example-nixos-module.nix Normal file
View file

@ -0,0 +1,11 @@
{
lib,
self,
...
}: {
services.syncthing = {
configuration = self.outputs.syncthingConfiguration;
deviceName = "laptop";
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

27
flake.lock Normal file
View file

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1741037377,
"narHash": "sha256-SvtvVKHaUX4Owb+PasySwZsoc5VUeTf1px34BByiOxw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "02032da4af073d0f6110540c8677f16d4be0117f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

72
flake.nix Normal file
View file

@ -0,0 +1,72 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
};
outputs = {
self,
nixpkgs,
...
}: let
systems = [
"aarch64-darwin"
"aarch64-linux"
"x86_64-darwin"
"x86_64-linux"
];
pkgsFor = system: nixpkgs.legacyPackages.${system};
forEachSystem = nixpkgs.lib.genAttrs systems;
forEachPkgs = lambda: forEachSystem (system: lambda (pkgsFor system));
in {
devShells = forEachPkgs (pkgs: {
default = pkgs.mkShell {
packages = with pkgs; [
# for version controlling this repo
git
# for formatting code in this repo
alejandra
# for viewing configuration options defined in this repo
nix-inspect
];
};
});
nixosModules.default = self.nixosModules.syncthing;
nixosModules.syncthing = import ./nixos.nix;
# TODO: figure out if I need modules for these projects
# homeManagerModules.syncthing = null;
# darwinModules.syncthing = null;
lib = {
evalConfig = import ./eval-config.nix;
syncthingConfiguration = {modules, ...}:
self.lib.evalConfig (
{inherit (nixpkgs) lib;}
// {
modules =
modules
++ [
(import ./base-module.nix)
];
}
);
};
nixosConfigurations = {
default = nixpkgs.lib.nixosSystem {
specialArgs = {inherit self;};
modules = [
self.nixosModules.syncthing
./example-nixos-module.nix
];
};
};
syncthingConfiguration = self.lib.syncthingConfiguration {
modules = [
(import ./example-module.nix)
];
};
};
}

43
nixos.nix Normal file
View file

@ -0,0 +1,43 @@
{
lib,
config,
...
} @ input: {
options = {
services.syncthing = {
configuration = (import ./configuration-type.nix) input;
deviceName = lib.mkOption {
type = lib.types.string;
};
};
};
config = {
services.syncthing.settings = {
devices =
lib.attrsets.mapAttrs (name: deviceConfig: {
id = deviceConfig.id;
})
config.services.syncthing.configuration.devices;
folders =
lib.attrsets.mapAttrs (folderName: folder: {
id = folder.folder.id;
label = folder.folder.label;
path = folder.path;
devices = lib.attrsets.mapAttrsToList (_: device: device.name) (
lib.attrsets.filterAttrs (
deviceName: device:
lib.lists.any
(
deviceFolder: deviceFolder.folder.id == folder.folder.id
) (
lib.attrsets.mapAttrsToList (_: deviceFolder: deviceFolder) device.folders
)
)
config.services.syncthing.configuration.devices
);
})
config.services.syncthing.configuration.devices.${config.services.syncthing.deviceName}.folders;
};
};
}

14
shell.nix Normal file
View file

@ -0,0 +1,14 @@
(
import
(
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{src = ./.;}
)
.shellNix