This commit is contained in:
2025-12-07 16:41:17 +00:00
parent 438e239fff
commit b8ce965de5
61 changed files with 2373 additions and 2384 deletions

View File

@@ -1 +1 @@
indentation = "Tabs" indentation = "TwoSpaces"

View File

@@ -2,7 +2,7 @@
description = "Configuration for my macOS laptops and NixOS server"; description = "Configuration for my macOS laptops and NixOS server";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/master"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts"; flake-parts.url = "github:hercules-ci/flake-parts";
sops-nix = { sops-nix = {
url = "github:Mic92/sops-nix"; url = "github:Mic92/sops-nix";
@@ -53,8 +53,7 @@
"aarch64-darwin" "aarch64-darwin"
]; ];
flake.darwinConfigurations = flake.darwinConfigurations = inputs.nixpkgs.lib.genAttrs darwinHosts (
inputs.nixpkgs.lib.genAttrs darwinHosts (
hostname: hostname:
inputs.darwin.lib.darwinSystem { inputs.darwin.lib.darwinSystem {
system = "aarch64-darwin"; system = "aarch64-darwin";
@@ -82,8 +81,7 @@
} }
); );
flake.nixosConfigurations = flake.nixosConfigurations = inputs.nixpkgs.lib.genAttrs nixosHosts (
inputs.nixpkgs.lib.genAttrs nixosHosts (
hostname: hostname:
inputs.nixpkgs.lib.nixosSystem { inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
@@ -122,8 +120,7 @@
"rollback" "rollback"
]; ];
in { in {
devShells.default = devShells.default = pkgs.mkShell {
pkgs.mkShell {
nativeBuildInputs = with pkgs; [ nativeBuildInputs = with pkgs; [
bashInteractive bashInteractive
git git
@@ -133,8 +130,7 @@
shellHook = ''export EDITOR=nvim''; shellHook = ''export EDITOR=nvim'';
}; };
apps = apps = builtins.listToAttrs (
builtins.listToAttrs (
map (n: { map (n: {
name = n; name = n;
value = mkApp n; value = mkApp n;

View File

@@ -1,6 +1,5 @@
{pkgs}: let {pkgs}: let
wallpaper = wallpaper = pkgs.fetchurl {
pkgs.fetchurl {
url = "https://misc-assets.raycast.com/wallpapers/bright-rain.png"; url = "https://misc-assets.raycast.com/wallpapers/bright-rain.png";
sha256 = "sha256-wQT4I2X3gS6QFsEb7MdRsn4oX7FNkflukXPGMFbJZ10="; sha256 = "sha256-wQT4I2X3gS6QFsEb7MdRsn4oX7FNkflukXPGMFbJZ10=";
}; };

View File

@@ -10,27 +10,23 @@ with lib; let
in { in {
options = { options = {
local.dock = { local.dock = {
enable = enable = mkOption {
mkOption {
description = "Enable dock"; description = "Enable dock";
default = stdenv.isDarwin; default = stdenv.isDarwin;
example = false; example = false;
}; };
entries = entries = mkOption {
mkOption {
description = "Entries on the Dock"; description = "Entries on the Dock";
type = with types; type = with types;
listOf (submodule { listOf (submodule {
options = { options = {
path = lib.mkOption {type = str;}; path = lib.mkOption {type = str;};
section = section = lib.mkOption {
lib.mkOption {
type = str; type = str;
default = "apps"; default = "apps";
}; };
options = options = lib.mkOption {
lib.mkOption {
type = str; type = str;
default = ""; default = "";
}; };
@@ -39,16 +35,14 @@ in {
readOnly = true; readOnly = true;
}; };
username = username = mkOption {
mkOption {
description = "Username to apply the dock settings to"; description = "Username to apply the dock settings to";
type = types.str; type = types.str;
}; };
}; };
}; };
config = config = mkIf cfg.enable (
mkIf cfg.enable (
let let
normalize = path: normalize = path:
if hasSuffix ".app" path if hasSuffix ".app" path

View File

@@ -12,8 +12,7 @@ in {
home = { home = {
packages = pkgs.callPackage ../packages.nix {}; packages = pkgs.callPackage ../packages.nix {};
activation = { activation = {
"setWallpaper" = "setWallpaper" = lib.hm.dag.entryAfter ["revealHomeLibraryDirectory"] ''
lib.hm.dag.entryAfter ["revealHomeLibraryDirectory"] ''
echo "[+] Setting wallpaper" echo "[+] Setting wallpaper"
${setWallpaperScript}/bin/set-wallpaper-script ${setWallpaperScript}/bin/set-wallpaper-script
''; '';

View File

@@ -19,8 +19,7 @@ with lib; let
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 = folders = mapAttrsToList (_: folder:
mapAttrsToList (_: folder:
folder folder
// { // {
devices = let devices = let
@@ -38,8 +37,7 @@ with lib; let
}) (filterAttrs (_: folder: folder.enable) cfg.settings.folders); }) (filterAttrs (_: folder: folder.enable) cfg.settings.folders);
jq = "${pkgs.jq}/bin/jq"; jq = "${pkgs.jq}/bin/jq";
updateConfig = updateConfig = pkgs.writers.writeBash "merge-syncthing-config" (
pkgs.writers.writeBash "merge-syncthing-config" (
'' ''
set -efu set -efu
umask 0077 umask 0077
@@ -78,8 +76,7 @@ with lib; let
lib.pipe s.conf [ lib.pipe s.conf [
(map ( (map (
new_cfg: let new_cfg: let
jsonPreSecretsFile = jsonPreSecretsFile = pkgs.writeTextFile {
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;
}; };
@@ -88,8 +85,7 @@ with lib; let
"devs" = "${jq} ."; "devs" = "${jq} .";
"dirs" = let "dirs" = let
folder = new_cfg; folder = new_cfg;
devicesWithSecrets = devicesWithSecrets = lib.pipe folder.devices [
lib.pipe folder.devices [
(lib.filter (device: (builtins.isAttrs device) && device ? encryptionPasswordFile)) (lib.filter (device: (builtins.isAttrs device) && device ? encryptionPasswordFile))
(map (device: { (map (device: {
deviceId = device.deviceId; deviceId = device.deviceId;
@@ -155,68 +151,56 @@ in {
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";
cert = cert = mkOption {
mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = "Path to the cert.pem file, which will be copied into Syncthing's configDir."; description = "Path to the cert.pem file, which will be copied into Syncthing's configDir.";
}; };
key = key = mkOption {
mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = "Path to the key.pem file, which will be copied into Syncthing's configDir."; description = "Path to the key.pem file, which will be copied into Syncthing's configDir.";
}; };
overrideDevices = overrideDevices = mkOption {
mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
description = "Whether to delete the devices which are not configured via the devices option."; description = "Whether to delete the devices which are not configured via the devices option.";
}; };
overrideFolders = overrideFolders = mkOption {
mkOption {
type = types.bool; type = types.bool;
default = !anyAutoAccept; default = !anyAutoAccept;
description = "Whether to delete the folders which are not configured via the folders option."; description = "Whether to delete the folders which are not configured via the folders option.";
}; };
settings = settings = mkOption {
mkOption { type = types.submodule {
type =
types.submodule {
freeformType = settingsFormat.type; freeformType = settingsFormat.type;
options = { options = {
options = options = mkOption {
mkOption {
default = {}; default = {};
description = "The options element contains all other global configuration options"; description = "The options element contains all other global configuration options";
type = type = types.submodule {
types.submodule {
freeformType = settingsFormat.type; freeformType = settingsFormat.type;
options = { options = {
localAnnounceEnabled = localAnnounceEnabled = mkOption {
mkOption {
type = types.nullOr types.bool; type = types.nullOr types.bool;
default = null; default = null;
description = "Whether to send announcements to the local LAN."; description = "Whether to send announcements to the local LAN.";
}; };
globalAnnounceEnabled = globalAnnounceEnabled = mkOption {
mkOption {
type = types.nullOr types.bool; type = types.nullOr types.bool;
default = null; default = null;
description = "Whether to send announcements to the global discovery servers."; description = "Whether to send announcements to the global discovery servers.";
}; };
relaysEnabled = relaysEnabled = mkOption {
mkOption {
type = types.nullOr types.bool; type = types.nullOr types.bool;
default = null; default = null;
description = "When true, relays will be connected to and potentially used for device to device connections."; description = "When true, relays will be connected to and potentially used for device to device connections.";
}; };
urAccepted = urAccepted = mkOption {
mkOption {
type = types.nullOr types.int; type = types.nullOr types.int;
default = null; default = null;
description = "Whether the user has accepted to submit anonymous usage data."; description = "Whether the user has accepted to submit anonymous usage data.";
@@ -225,27 +209,22 @@ in {
}; };
}; };
devices = devices = mkOption {
mkOption {
default = {}; default = {};
description = "Peers/devices which Syncthing should communicate with."; description = "Peers/devices which Syncthing should communicate with.";
type = type = types.attrsOf (types.submodule ({name, ...}: {
types.attrsOf (types.submodule ({name, ...}: {
freeformType = settingsFormat.type; freeformType = settingsFormat.type;
options = { options = {
name = name = mkOption {
mkOption {
type = types.str; type = types.str;
default = name; default = name;
description = "The name of the device."; description = "The name of the device.";
}; };
id = id = mkOption {
mkOption {
type = types.str; type = types.str;
description = "The device ID."; description = "The device ID.";
}; };
autoAcceptFolders = autoAcceptFolders = mkOption {
mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = "Automatically create or share folders that this device advertises at the default path."; description = "Automatically create or share folders that this device advertises at the default path.";
@@ -254,59 +233,48 @@ in {
})); }));
}; };
folders = folders = mkOption {
mkOption {
default = {}; default = {};
description = "Folders which should be shared by Syncthing."; description = "Folders which should be shared by Syncthing.";
type = type = types.attrsOf (types.submodule ({name, ...}: {
types.attrsOf (types.submodule ({name, ...}: {
freeformType = settingsFormat.type; freeformType = settingsFormat.type;
options = { options = {
enable = enable = mkOption {
mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
description = "Whether to share this folder."; description = "Whether to share this folder.";
}; };
path = path = mkOption {
mkOption {
type = types.str; type = types.str;
default = name; default = name;
description = "The path to the folder which should be shared."; description = "The path to the folder which should be shared.";
}; };
id = id = mkOption {
mkOption {
type = types.str; type = types.str;
default = name; default = name;
description = "The ID of the folder. Must be the same on all devices."; description = "The ID of the folder. Must be the same on all devices.";
}; };
label = label = mkOption {
mkOption {
type = types.str; type = types.str;
default = name; default = name;
description = "The label of the folder."; description = "The label of the folder.";
}; };
type = type = mkOption {
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.";
}; };
devices = devices = mkOption {
mkOption { type = types.listOf (types.oneOf [
type =
types.listOf (types.oneOf [
types.str types.str
(types.submodule { (types.submodule {
freeformType = settingsFormat.type; freeformType = settingsFormat.type;
options = { options = {
name = name = mkOption {
mkOption {
type = types.str; type = types.str;
description = "The name of a device defined in the devices option."; description = "The name of a device defined in the devices option.";
}; };
encryptionPasswordFile = encryptionPasswordFile = mkOption {
mkOption {
type = types.nullOr types.path; type = types.nullOr types.path;
default = null; default = null;
description = "Path to encryption password file."; description = "Path to encryption password file.";
@@ -326,43 +294,37 @@ in {
description = "Extra configuration options for Syncthing."; description = "Extra configuration options for Syncthing.";
}; };
guiAddress = guiAddress = mkOption {
mkOption {
type = types.str; type = types.str;
default = "127.0.0.1:8384"; default = "127.0.0.1:8384";
description = "The address to serve the web interface at."; description = "The address to serve the web interface at.";
}; };
user = user = mkOption {
mkOption {
type = types.str; type = types.str;
default = "syncthing"; default = "syncthing";
description = "The user to run Syncthing as."; description = "The user to run Syncthing as.";
}; };
group = group = mkOption {
mkOption {
type = types.str; type = types.str;
default = "syncthing"; default = "syncthing";
description = "The group to run Syncthing under."; description = "The group to run Syncthing under.";
}; };
dataDir = dataDir = mkOption {
mkOption {
type = types.path; type = types.path;
default = "/var/lib/syncthing"; default = "/var/lib/syncthing";
description = "The path where synchronised directories will exist."; description = "The path where synchronised directories will exist.";
}; };
configDir = configDir = mkOption {
mkOption {
type = types.path; type = types.path;
default = cfg.dataDir + "/.config/syncthing"; default = cfg.dataDir + "/.config/syncthing";
description = "The path where the settings and keys will exist."; description = "The path where the settings and keys will exist.";
}; };
openDefaultPorts = openDefaultPorts = mkOption {
mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
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).";
@@ -372,8 +334,7 @@ in {
}; };
}; };
config = config = mkIf cfg.enable {
mkIf cfg.enable {
assertions = [ assertions = [
{ {
assertion = !(cfg.overrideFolders && anyAutoAccept); assertion = !(cfg.overrideFolders && anyAutoAccept);
@@ -408,8 +369,7 @@ in {
}; };
}; };
launchd.user.agents.syncthing-init = launchd.user.agents.syncthing-init = mkIf (cleanedConfig != {}) {
mkIf (cleanedConfig != {}) {
serviceConfig = { serviceConfig = {
ProgramArguments = ["${updateConfig}"]; ProgramArguments = ["${updateConfig}"];
RunAtLoad = true; RunAtLoad = true;
@@ -420,8 +380,7 @@ in {
}; };
}; };
system.activationScripts.syncthing = system.activationScripts.syncthing = mkIf (cfg.cert != null || cfg.key != null) ''
mkIf (cfg.cert != null || cfg.key != null) ''
echo "Setting up Syncthing certificates..." echo "Setting up Syncthing certificates..."
mkdir -p ${cfg.configDir} mkdir -p ${cfg.configDir}
${optionalString (cfg.cert != null) '' ${optionalString (cfg.cert != null) ''

View File

@@ -7,8 +7,7 @@
}; };
themes = { themes = {
"Catppuccin Latte" = { "Catppuccin Latte" = {
src = src = pkgs.fetchFromGitHub {
pkgs.fetchFromGitHub {
owner = "catppuccin"; owner = "catppuccin";
repo = "bat"; repo = "bat";
rev = "6810349b28055dce54076712fc05fc68da4b8ec0"; rev = "6810349b28055dce54076712fc05fc68da4b8ec0";

View File

@@ -12,7 +12,7 @@ with pkgs; [
ast-grep ast-grep
bun bun
delta delta
# devenv devenv
dig dig
docker docker
docker-compose docker-compose
@@ -22,6 +22,7 @@ with pkgs; [
git git
gnumake gnumake
gnupg gnupg
hledger
htop htop
hyperfine hyperfine
jq jq

View File

@@ -0,0 +1,43 @@
{
pkgs,
inputs,
...
}:
with pkgs; [
inputs.beads.packages.${pkgs.system}.default
inputs.nix-ai-tools.packages.${pkgs.system}.amp
(callPackage ./bin/open-project.nix {})
age
alejandra
ast-grep
bun
delta
devenv
dig
docker
docker-compose
hledger
fastfetch
fd
gh
git
gnumake
gnupg
htop
hyperfine
jq
killall
lsof
nurl
openssh
postgresql_17
sd
sops
sqlite
tokei
tree
tree-sitter
unzip
vivid
zip
]

View File

@@ -1,7 +1,6 @@
{inputs}: let {inputs}: let
dir = builtins.readDir ./.; dir = builtins.readDir ./.;
overlayNames = overlayNames = builtins.sort builtins.lessThan (builtins.filter (
builtins.sort builtins.lessThan (builtins.filter (
name: name:
name name
!= "default.nix" != "default.nix"