Compare commits
3 Commits
5eec5689f4
...
a4af935e6e
| Author | SHA1 | Date | |
|---|---|---|---|
| a4af935e6e | |||
| cf308a1371 | |||
| 503c1fe9bc |
@@ -35,8 +35,8 @@ In this repo, `flake.nix` imports `./modules` recursively via `inputs.import-tre
|
|||||||
- `modules/hosts/<name>/default.nix`: host features that assemble NixOS aspects into `flake.modules.nixos.<name>`.
|
- `modules/hosts/<name>/default.nix`: host features that assemble NixOS aspects into `flake.modules.nixos.<name>`.
|
||||||
- `modules/secrets/`: secret-related features shared by hosts.
|
- `modules/secrets/`: secret-related features shared by hosts.
|
||||||
- `modules/flake-parts.nix`: flake-parts entrypoint; defines systems, formatter, and `flake.nixosConfigurations`.
|
- `modules/flake-parts.nix`: flake-parts entrypoint; defines systems, formatter, and `flake.nixosConfigurations`.
|
||||||
- `modules/lib.nix`: shared constructors in `config.meta.lib`, especially `mkHost`, `mkHostUser`, and `mkCaddyReverseProxy`.
|
- `modules/lib.nix`: shared constructors and helpers in `config.meta.lib`, especially `mkHost` and `mkCaddyReverseProxy`.
|
||||||
- `modules/users.nix`: canonical user attrsets exposed through `meta.lib.users`.
|
- `modules/data.nix`: canonical shared repo data and account attrsets exposed through `meta.lib.repo` and `meta.lib.accounts`.
|
||||||
- `modules/features/meta.nix`: shared metadata schema for `meta.host` and `meta.user`.
|
- `modules/features/meta.nix`: shared metadata schema for `meta.host` and `meta.user`.
|
||||||
|
|
||||||
## How Features Are Applied Here
|
## How Features Are Applied Here
|
||||||
@@ -45,7 +45,7 @@ In this repo, `flake.nix` imports `./modules` recursively via `inputs.import-tre
|
|||||||
- Reusable Home Manager concerns are published as `flake.modules.homeManager.<name>`.
|
- Reusable Home Manager concerns are published as `flake.modules.homeManager.<name>`.
|
||||||
- Hosts are aspects too. `orion`, `polaris`, and `zenith` are `nixos` aspects assembled from smaller aspects.
|
- Hosts are aspects too. `orion`, `polaris`, and `zenith` are `nixos` aspects assembled from smaller aspects.
|
||||||
- Host modules should use `config.meta.lib.mkHost` to define `meta.host`, base imports, hostname, and state version.
|
- Host modules should use `config.meta.lib.mkHost` to define `meta.host`, base imports, hostname, and state version.
|
||||||
- Per-user Home Manager composition should use `config.meta.lib.mkHostUser` so `meta.host` and `meta.user` stay available to Home Manager features.
|
- Per-host user declarations should stay inline under `users.<name>` using canonical accounts from `meta.lib.accounts`, so host-local defaults stay close to the host and `mkHost` can wire `meta.host` and `meta.user` into Home Manager consistently.
|
||||||
- Features may rely on the `meta` contract. Existing modules already read `config.meta.host`, `config.meta.user`, and `config.meta.lib`.
|
- Features may rely on the `meta` contract. Existing modules already read `config.meta.host`, `config.meta.user`, and `config.meta.lib`.
|
||||||
|
|
||||||
## Preferred Aspect Patterns
|
## Preferred Aspect Patterns
|
||||||
|
|||||||
@@ -0,0 +1,194 @@
|
|||||||
|
{ lib, ... }:
|
||||||
|
let
|
||||||
|
userSpecs = {
|
||||||
|
kiri = {
|
||||||
|
realName = "Jelle Spreeuwenberg";
|
||||||
|
homeDirectory = "/home/kiri";
|
||||||
|
emails = {
|
||||||
|
personal = {
|
||||||
|
address = "mail@jelles.net";
|
||||||
|
primary = true;
|
||||||
|
scope = "personal";
|
||||||
|
type = "mxrouting";
|
||||||
|
};
|
||||||
|
old = {
|
||||||
|
address = "mail@jellespreeuwenberg.nl";
|
||||||
|
scope = null;
|
||||||
|
type = "mxrouting";
|
||||||
|
};
|
||||||
|
uni = {
|
||||||
|
address = "j.spreeuwenberg@student.tue.nl";
|
||||||
|
scope = null;
|
||||||
|
type = "office365";
|
||||||
|
};
|
||||||
|
work = {
|
||||||
|
address = "jelle.spreeuwenberg@yookr.org";
|
||||||
|
scope = "work";
|
||||||
|
type = "office365";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
sourceControl = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
ergon = {
|
||||||
|
realName = "Jelle Spreeuwenberg";
|
||||||
|
homeDirectory = "/home/ergon";
|
||||||
|
emails = {
|
||||||
|
personal = {
|
||||||
|
address = "mail@jelles.net";
|
||||||
|
scope = "personal";
|
||||||
|
type = "mxrouting";
|
||||||
|
};
|
||||||
|
work = {
|
||||||
|
address = "jelle.spreeuwenberg@yookr.org";
|
||||||
|
primary = true;
|
||||||
|
scope = "work";
|
||||||
|
type = "office365";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
sourceControl.projectScope = "work";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
accounts = lib.mapAttrs (name: spec: spec // { inherit name; }) userSpecs;
|
||||||
|
|
||||||
|
repo = {
|
||||||
|
contact.email = "mail@jelles.net";
|
||||||
|
|
||||||
|
desktop = {
|
||||||
|
browser = {
|
||||||
|
command = "vivaldi";
|
||||||
|
packagePath = [ "vivaldi" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
fileManager = {
|
||||||
|
command = "nautilus";
|
||||||
|
packagePath = [ "nautilus" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
terminal = {
|
||||||
|
command = "kitty";
|
||||||
|
desktopId = "kitty.desktop";
|
||||||
|
packagePath = [ "kitty" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
actual = {
|
||||||
|
domain = "finance.jelles.net";
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 3000;
|
||||||
|
url = "https://finance.jelles.net";
|
||||||
|
};
|
||||||
|
|
||||||
|
gitea = {
|
||||||
|
domain = "git.jelles.net";
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 3001;
|
||||||
|
url = "https://git.jelles.net/";
|
||||||
|
};
|
||||||
|
|
||||||
|
radicale = {
|
||||||
|
domain = "radicale.jelles.net";
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 5232;
|
||||||
|
url = "https://radicale.jelles.net/";
|
||||||
|
};
|
||||||
|
|
||||||
|
vaultwarden = {
|
||||||
|
domain = "vault.jelles.net";
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 8100;
|
||||||
|
url = "https://vault.jelles.net";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
theme = {
|
||||||
|
cursor = {
|
||||||
|
name = "phinger-cursors-light";
|
||||||
|
packagePath = [ "phinger-cursors" ];
|
||||||
|
size = 24;
|
||||||
|
};
|
||||||
|
|
||||||
|
kanagawa = {
|
||||||
|
displayName = "Kanagawa Wave";
|
||||||
|
name = "kanagawa-wave";
|
||||||
|
gtkThemeName = "Kanagawa-BL-LB";
|
||||||
|
iconThemeName = "Kanagawa";
|
||||||
|
owner = "Fausto-Korpsvart";
|
||||||
|
repo = "Kanagawa-GKT-Theme";
|
||||||
|
rev = "55ca4ba249eba21f861b9866b71ab41bb8930318";
|
||||||
|
hash = "sha256-UdMoMx2DoovcxSp/zBZ3PRv/Qpj+prd0uPm1gmdak2E=";
|
||||||
|
version = "unstable-2025-10-23";
|
||||||
|
|
||||||
|
palette = {
|
||||||
|
background = "#1F1F28";
|
||||||
|
foreground = "#DCD7BA";
|
||||||
|
secondaryBackground = "#16161D";
|
||||||
|
border = "#2A2A37";
|
||||||
|
selectionBackground = "#2D4F67";
|
||||||
|
selectionForeground = "#C8C093";
|
||||||
|
url = "#72A7BC";
|
||||||
|
cursor = "#C8C093";
|
||||||
|
muted = "#727169";
|
||||||
|
|
||||||
|
accents = {
|
||||||
|
blue = "#7E9CD8";
|
||||||
|
green = "#98BB6C";
|
||||||
|
magenta = "#D27E99";
|
||||||
|
orange = "#FFA066";
|
||||||
|
purple = "#957FB8";
|
||||||
|
red = "#E82424";
|
||||||
|
yellow = "#E6C384";
|
||||||
|
cyan = "#7AA89F";
|
||||||
|
};
|
||||||
|
|
||||||
|
niri.border = {
|
||||||
|
active = "#7E9CD8";
|
||||||
|
inactive = "#54546D";
|
||||||
|
urgent = "#E82424";
|
||||||
|
};
|
||||||
|
|
||||||
|
terminal = {
|
||||||
|
color0 = "#16161D";
|
||||||
|
color1 = "#C34043";
|
||||||
|
color2 = "#76946A";
|
||||||
|
color3 = "#C0A36E";
|
||||||
|
color4 = "#7E9CD8";
|
||||||
|
color5 = "#957FB8";
|
||||||
|
color6 = "#6A9589";
|
||||||
|
color7 = "#C8C093";
|
||||||
|
color8 = "#727169";
|
||||||
|
color9 = "#E82424";
|
||||||
|
color10 = "#98BB6C";
|
||||||
|
color11 = "#E6C384";
|
||||||
|
color12 = "#7FB4CA";
|
||||||
|
color13 = "#938AA9";
|
||||||
|
color14 = "#7AA89F";
|
||||||
|
color15 = "#DCD7BA";
|
||||||
|
color16 = "#FFA066";
|
||||||
|
color17 = "#FF5D62";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.meta.lib.repo = lib.mkOption {
|
||||||
|
type = lib.types.attrs;
|
||||||
|
description = "Internal shared repository metadata.";
|
||||||
|
internal = true;
|
||||||
|
readOnly = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
options.meta.lib.accounts = lib.mkOption {
|
||||||
|
type = lib.types.attrs;
|
||||||
|
description = "Canonical account attrsets shared by host definitions.";
|
||||||
|
internal = true;
|
||||||
|
readOnly = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
config.meta.lib.repo = repo;
|
||||||
|
config.meta.lib.accounts = accounts;
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
metaLib = config.meta.lib;
|
metaRepo = config.meta.lib.repo;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.bitwarden =
|
flake.modules.homeManager.bitwarden =
|
||||||
@@ -19,7 +19,7 @@ in
|
|||||||
programs.rbw = {
|
programs.rbw = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
base_url = metaLib.repo.services.vaultwarden.url;
|
base_url = metaRepo.services.vaultwarden.url;
|
||||||
email = user.primaryEmail.address;
|
email = user.primaryEmail.address;
|
||||||
pinentry = pkgs.pinentry-gnome3;
|
pinentry = pkgs.pinentry-gnome3;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,12 +3,10 @@
|
|||||||
flake.modules.homeManager.git =
|
flake.modules.homeManager.git =
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
user = config.meta.user;
|
user = config.meta.user;
|
||||||
usesScopedIdentity = user != null && user.sourceControl.profiles != { };
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
programs.git = {
|
programs.git = {
|
||||||
@@ -20,8 +18,6 @@
|
|||||||
];
|
];
|
||||||
settings = {
|
settings = {
|
||||||
init.defaultBranch = "main";
|
init.defaultBranch = "main";
|
||||||
}
|
|
||||||
// lib.optionalAttrs (!usesScopedIdentity) {
|
|
||||||
user = {
|
user = {
|
||||||
name = user.realName;
|
name = user.realName;
|
||||||
email = user.primaryEmail.address;
|
email = user.primaryEmail.address;
|
||||||
|
|||||||
@@ -1,20 +1,32 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
let
|
||||||
|
metaRepo = config.meta.lib.repo;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.local-apps =
|
flake.modules.homeManager.local-apps =
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
browserPackage = config.meta.lib.resolvePackagePath {
|
||||||
|
inherit pkgs;
|
||||||
|
path = metaRepo.desktop.browser.packagePath;
|
||||||
|
};
|
||||||
|
in
|
||||||
{
|
{
|
||||||
home.sessionVariables.BROWSER = "vivaldi";
|
home.sessionVariables.BROWSER = metaRepo.desktop.browser.command;
|
||||||
|
|
||||||
home.packages = with pkgs; [
|
home.packages =
|
||||||
brave
|
with pkgs;
|
||||||
vivaldi
|
[
|
||||||
postman
|
brave
|
||||||
spotify
|
postman
|
||||||
calcure
|
spotify
|
||||||
planify
|
calcure
|
||||||
unzip
|
planify
|
||||||
gimp
|
unzip
|
||||||
dbeaver-bin
|
gimp
|
||||||
];
|
dbeaver-bin
|
||||||
|
]
|
||||||
|
++ [ browserPackage ];
|
||||||
|
|
||||||
programs.imv.enable = true;
|
programs.imv.enable = true;
|
||||||
programs.sioyek.enable = true;
|
programs.sioyek.enable = true;
|
||||||
|
|||||||
+87
-32
@@ -1,5 +1,7 @@
|
|||||||
{ lib, ... }:
|
{ lib, ... }:
|
||||||
let
|
let
|
||||||
|
nonEmptyStrType = lib.types.addCheck lib.types.str (value: lib.stringLength value > 0);
|
||||||
|
|
||||||
mkNullableOption =
|
mkNullableOption =
|
||||||
type:
|
type:
|
||||||
lib.mkOption {
|
lib.mkOption {
|
||||||
@@ -10,12 +12,40 @@ let
|
|||||||
hasSinglePrimaryEmail =
|
hasSinglePrimaryEmail =
|
||||||
user: builtins.length (lib.filter (email: email.primary) (builtins.attrValues user.emails)) == 1;
|
user: builtins.length (lib.filter (email: email.primary) (builtins.attrValues user.emails)) == 1;
|
||||||
|
|
||||||
|
scopeEmailCount =
|
||||||
|
scope: user:
|
||||||
|
builtins.length (lib.filter (email: email.scope == scope) (builtins.attrValues user.emails));
|
||||||
|
|
||||||
|
hasAtMostOneScopedEmail = scope: user: scopeEmailCount scope user <= 1;
|
||||||
|
|
||||||
|
requiredSourceControlScopes =
|
||||||
|
user:
|
||||||
|
lib.unique [
|
||||||
|
"personal"
|
||||||
|
user.sourceControl.projectScope
|
||||||
|
];
|
||||||
|
|
||||||
|
hasRequiredScopedEmail = scope: user: scopeEmailCount scope user == 1;
|
||||||
|
|
||||||
|
scopeEmailAddress =
|
||||||
|
scope: user:
|
||||||
|
let
|
||||||
|
emails = lib.filter (email: email.scope == scope) (builtins.attrValues user.emails);
|
||||||
|
in
|
||||||
|
if emails == [ ] then "" else (builtins.head emails).address;
|
||||||
|
|
||||||
primaryEmailFallback = {
|
primaryEmailFallback = {
|
||||||
address = "";
|
address = "";
|
||||||
primary = false;
|
primary = false;
|
||||||
type = "";
|
scope = null;
|
||||||
|
type = "mxrouting";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
emailProviderType = lib.types.enum [
|
||||||
|
"mxrouting"
|
||||||
|
"office365"
|
||||||
|
];
|
||||||
|
|
||||||
sourceControlScopeType = lib.types.enum [
|
sourceControlScopeType = lib.types.enum [
|
||||||
"personal"
|
"personal"
|
||||||
"work"
|
"work"
|
||||||
@@ -48,11 +78,14 @@ let
|
|||||||
|
|
||||||
primary = lib.mkOption {
|
primary = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
type = lib.mkOption {
|
type = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = emailProviderType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
scope = mkNullableOption sourceControlScopeType;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -62,13 +95,11 @@ let
|
|||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
publicKey = lib.mkOption {
|
publicKey = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.nullOr nonEmptyStrType;
|
||||||
};
|
|
||||||
|
|
||||||
privateKeyPath = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.str;
|
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
privateKeyPath = mkNullableOption nonEmptyStrType;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -93,26 +124,30 @@ let
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
sourceControlProfileType = lib.types.submodule (
|
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
options = { };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
sourceControlType = lib.types.submodule (
|
sourceControlType = lib.types.submodule (
|
||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
profiles = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf sourceControlProfileType;
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
projectScope = lib.mkOption {
|
projectScope = lib.mkOption {
|
||||||
type = sourceControlScopeType;
|
type = sourceControlScopeType;
|
||||||
default = "personal";
|
default = "personal";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
scopes = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (
|
||||||
|
lib.types.submodule (
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
options.email = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
readOnly = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
readOnly = true;
|
||||||
|
description = "Derived source-control identities keyed by scope.";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -137,10 +172,6 @@ let
|
|||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
terminalPackagePath = lib.mkOption {
|
|
||||||
type = lib.types.listOf lib.types.str;
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosConfigurationPath = lib.mkOption {
|
nixosConfigurationPath = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = "${config.homeDirectory}/.config/nixos";
|
default = "${config.homeDirectory}/.config/nixos";
|
||||||
@@ -162,7 +193,12 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config.primaryEmail = primaryEmail;
|
config = {
|
||||||
|
primaryEmail = primaryEmail;
|
||||||
|
sourceControl.scopes = lib.genAttrs (requiredSourceControlScopes config) (scope: {
|
||||||
|
email = scopeEmailAddress scope config;
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -293,6 +329,29 @@ let
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
mkUserEmailAssertions =
|
||||||
|
userName: user:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
assertion = hasSinglePrimaryEmail user;
|
||||||
|
message = "User `${userName}` must define exactly one primary email entry.";
|
||||||
|
}
|
||||||
|
]
|
||||||
|
++ (map
|
||||||
|
(scope: {
|
||||||
|
assertion = hasAtMostOneScopedEmail scope user;
|
||||||
|
message = "User `${userName}` may define at most one `${scope}` scoped email entry.";
|
||||||
|
})
|
||||||
|
[
|
||||||
|
"personal"
|
||||||
|
"work"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
++ map (scope: {
|
||||||
|
assertion = hasRequiredScopedEmail scope user;
|
||||||
|
message = "User `${userName}` must define exactly one `${scope}` scoped email entry.";
|
||||||
|
}) (requiredSourceControlScopes user);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.meta =
|
flake.modules.nixos.meta =
|
||||||
@@ -302,10 +361,7 @@ in
|
|||||||
type = hostType;
|
type = hostType;
|
||||||
};
|
};
|
||||||
|
|
||||||
config.assertions = lib.mapAttrsToList (userName: user: {
|
config.assertions = lib.flatten (lib.mapAttrsToList mkUserEmailAssertions config.meta.host.users);
|
||||||
assertion = hasSinglePrimaryEmail user;
|
|
||||||
message = "User `${userName}` must define exactly one primary email entry.";
|
|
||||||
}) config.meta.host.users;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.homeManager.meta =
|
flake.modules.homeManager.meta =
|
||||||
@@ -323,9 +379,8 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config.assertions = lib.optional (config.meta.user != null) {
|
config.assertions = lib.optionals (config.meta.user != null) (
|
||||||
assertion = hasSinglePrimaryEmail config.meta.user;
|
mkUserEmailAssertions config.meta.user.name config.meta.user
|
||||||
message = "User `${config.meta.user.name}` must define exactly one primary email entry.";
|
);
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
{ themeName }:
|
||||||
|
''
|
||||||
|
require("kanagawa").setup({
|
||||||
|
colors = {
|
||||||
|
theme = {
|
||||||
|
all = {
|
||||||
|
ui = {
|
||||||
|
bg_gutter = "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
overrides = function(colors)
|
||||||
|
local theme = colors.theme
|
||||||
|
|
||||||
|
local makeDiagnosticColor = function(color)
|
||||||
|
local c = require("kanagawa.lib.color")
|
||||||
|
return { fg = color, bg = c(color):blend(theme.ui.bg, 0.95):to_hex() }
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
TelescopeTitle = { fg = theme.ui.special, bold = true },
|
||||||
|
TelescopePromptNormal = { bg = theme.ui.bg_p1 },
|
||||||
|
TelescopePromptBorder = { fg = theme.ui.bg_p1, bg = theme.ui.bg_p1 },
|
||||||
|
TelescopeResultsNormal = { fg = theme.ui.fg_dim, bg = theme.ui.bg_m1 },
|
||||||
|
TelescopeResultsBorder = { fg = theme.ui.bg_m1, bg = theme.ui.bg_m1 },
|
||||||
|
TelescopePreviewNormal = { bg = theme.ui.bg_dim },
|
||||||
|
TelescopePreviewBorder = { bg = theme.ui.bg_dim, fg = theme.ui.bg_dim },
|
||||||
|
|
||||||
|
Pmenu = { fg = theme.ui.shade0, bg = theme.ui.bg_p1 }, -- add `blend = vim.o.pumblend` to enable transparency
|
||||||
|
PmenuSel = { fg = "NONE", bg = theme.ui.bg_p2 },
|
||||||
|
PmenuSbar = { bg = theme.ui.bg_m1 },
|
||||||
|
PmenuThumb = { bg = theme.ui.bg_p2 },
|
||||||
|
|
||||||
|
DiagnosticVirtualTextHint = makeDiagnosticColor(theme.diag.hint),
|
||||||
|
DiagnosticVirtualTextInfo = makeDiagnosticColor(theme.diag.info),
|
||||||
|
DiagnosticVirtualTextWarn = makeDiagnosticColor(theme.diag.warning),
|
||||||
|
DiagnosticVirtualTextError = makeDiagnosticColor(theme.diag.error),
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.cmd.colorscheme("${themeName}")
|
||||||
|
''
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
let
|
||||||
|
repoTheme = config.meta.lib.repo.theme.kanagawa;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.neovim =
|
flake.modules.homeManager.neovim =
|
||||||
{
|
{
|
||||||
@@ -109,56 +113,13 @@
|
|||||||
# Hostname/ConfigDir needed for nixd
|
# Hostname/ConfigDir needed for nixd
|
||||||
nixdExtras = {
|
nixdExtras = {
|
||||||
nixpkgs = "import ${pkgs.path} {}";
|
nixpkgs = "import ${pkgs.path} {}";
|
||||||
nixos_options = ''(builtins.getFlake "path://${config.home.homeDirectory}/.config/nixos").nixosConfigurations.${config.meta.host.name}.options'';
|
nixos_options = ''(builtins.getFlake "path://${config.meta.user.nixosConfigurationPath}").nixosConfigurations.${config.meta.host.name}.options'';
|
||||||
home_manager_options = ''(builtins.getFlake "path://${config.home.homeDirectory}/.config/nixos").nixosConfigurations.${config.meta.host.name}.options.home-manager.users.type.getSubOptions []'';
|
home_manager_options = ''(builtins.getFlake "path://${config.meta.user.nixosConfigurationPath}").nixosConfigurations.${config.meta.host.name}.options.home-manager.users.type.getSubOptions []'';
|
||||||
};
|
};
|
||||||
|
|
||||||
# TODO: Put in separate theme file
|
themeSetup = import ./_kanagawa-theme.nix {
|
||||||
themeSetup = # lua
|
themeName = repoTheme.name;
|
||||||
''
|
};
|
||||||
require("kanagawa").setup({
|
|
||||||
colors = {
|
|
||||||
theme = {
|
|
||||||
all = {
|
|
||||||
ui = {
|
|
||||||
bg_gutter = "none"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
overrides = function(colors)
|
|
||||||
local theme = colors.theme
|
|
||||||
|
|
||||||
local makeDiagnosticColor = function(color)
|
|
||||||
local c = require("kanagawa.lib.color")
|
|
||||||
return { fg = color, bg = c(color):blend(theme.ui.bg, 0.95):to_hex() }
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
TelescopeTitle = { fg = theme.ui.special, bold = true },
|
|
||||||
TelescopePromptNormal = { bg = theme.ui.bg_p1 },
|
|
||||||
TelescopePromptBorder = { fg = theme.ui.bg_p1, bg = theme.ui.bg_p1 },
|
|
||||||
TelescopeResultsNormal = { fg = theme.ui.fg_dim, bg = theme.ui.bg_m1 },
|
|
||||||
TelescopeResultsBorder = { fg = theme.ui.bg_m1, bg = theme.ui.bg_m1 },
|
|
||||||
TelescopePreviewNormal = { bg = theme.ui.bg_dim },
|
|
||||||
TelescopePreviewBorder = { bg = theme.ui.bg_dim, fg = theme.ui.bg_dim },
|
|
||||||
|
|
||||||
Pmenu = { fg = theme.ui.shade0, bg = theme.ui.bg_p1 }, -- add `blend = vim.o.pumblend` to enable transparency
|
|
||||||
PmenuSel = { fg = "NONE", bg = theme.ui.bg_p2 },
|
|
||||||
PmenuSbar = { bg = theme.ui.bg_m1 },
|
|
||||||
PmenuThumb = { bg = theme.ui.bg_p2 },
|
|
||||||
|
|
||||||
DiagnosticVirtualTextHint = makeDiagnosticColor(theme.diag.hint),
|
|
||||||
DiagnosticVirtualTextInfo = makeDiagnosticColor(theme.diag.info),
|
|
||||||
DiagnosticVirtualTextWarn = makeDiagnosticColor(theme.diag.warning),
|
|
||||||
DiagnosticVirtualTextError = makeDiagnosticColor(theme.diag.error),
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
vim.cmd.colorscheme("kanagawa-wave")
|
|
||||||
'';
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
networking = {
|
networking = {
|
||||||
firewall.enable = true;
|
firewall.enable = true;
|
||||||
firewall.allowPing = false;
|
firewall.allowPing = false;
|
||||||
nftables.enable = true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
browserCommand,
|
||||||
lib,
|
lib,
|
||||||
terminalPackage,
|
terminalPackage,
|
||||||
}:
|
}:
|
||||||
@@ -8,7 +9,7 @@
|
|||||||
hotkey-overlay.title = "Terminal";
|
hotkey-overlay.title = "Terminal";
|
||||||
};
|
};
|
||||||
"Mod+B" = {
|
"Mod+B" = {
|
||||||
action.spawn = "vivaldi";
|
action.spawn = browserCommand;
|
||||||
hotkey-overlay.title = "Browser";
|
hotkey-overlay.title = "Browser";
|
||||||
};
|
};
|
||||||
"Mod+Space" = {
|
"Mod+Space" = {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
|
metaRepo = metaLib.repo;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.niri =
|
flake.modules.nixos.niri =
|
||||||
@@ -30,6 +31,12 @@ in
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
repoTheme = metaRepo.theme.kanagawa;
|
||||||
|
browserCommand = metaRepo.desktop.browser.command;
|
||||||
|
fileManagerPackage = metaLib.resolvePackagePath {
|
||||||
|
inherit pkgs;
|
||||||
|
path = metaRepo.desktop.fileManager.packagePath;
|
||||||
|
};
|
||||||
outputs = lib.mapAttrs (
|
outputs = lib.mapAttrs (
|
||||||
_: display:
|
_: display:
|
||||||
{
|
{
|
||||||
@@ -41,23 +48,21 @@ in
|
|||||||
// lib.optionalAttrs (display.primary or false) {
|
// lib.optionalAttrs (display.primary or false) {
|
||||||
"focus-at-startup" = true;
|
"focus-at-startup" = true;
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (display ? scale) {
|
// lib.optionalAttrs (display.scale != null) {
|
||||||
inherit (display) scale;
|
inherit (display) scale;
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (display ? mode) {
|
// lib.optionalAttrs (display.mode != null) {
|
||||||
inherit (display) mode;
|
inherit (display) mode;
|
||||||
}
|
}
|
||||||
) config.meta.host.displays;
|
) config.meta.host.displays;
|
||||||
inputProfiles = metaLib.mkInputProfiles config.meta.host.input;
|
inputProfiles = metaLib.mkInputProfiles config.meta.host.input;
|
||||||
terminal = metaLib.resolveUserTerminal {
|
terminal = metaLib.resolveRepoTerminal {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
user = config.meta.user;
|
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assertions = metaLib.mkTerminalAssertions {
|
assertions = metaLib.mkTerminalAssertions {
|
||||||
inherit terminal;
|
inherit terminal;
|
||||||
user = config.meta.user;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
home.sessionVariables.NIXOS_OZONE_WL = "1";
|
home.sessionVariables.NIXOS_OZONE_WL = "1";
|
||||||
@@ -68,12 +73,14 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
home.packages = with pkgs; [
|
home.packages =
|
||||||
playerctl
|
with pkgs;
|
||||||
nautilus
|
[
|
||||||
brightnessctl
|
playerctl
|
||||||
xwayland-satellite
|
brightnessctl
|
||||||
];
|
xwayland-satellite
|
||||||
|
]
|
||||||
|
++ [ fileManagerPackage ];
|
||||||
|
|
||||||
programs.niri.settings = {
|
programs.niri.settings = {
|
||||||
inherit outputs;
|
inherit outputs;
|
||||||
@@ -81,7 +88,6 @@ in
|
|||||||
spawn-at-startup = [
|
spawn-at-startup = [
|
||||||
{ command = [ "xwayland-satellite" ]; }
|
{ command = [ "xwayland-satellite" ]; }
|
||||||
{ command = [ "noctalia-shell" ]; }
|
{ command = [ "noctalia-shell" ]; }
|
||||||
{ command = [ "qbittorrent" ]; }
|
|
||||||
];
|
];
|
||||||
prefer-no-csd = true;
|
prefer-no-csd = true;
|
||||||
hotkey-overlay.skip-at-startup = true;
|
hotkey-overlay.skip-at-startup = true;
|
||||||
@@ -106,9 +112,9 @@ in
|
|||||||
border = {
|
border = {
|
||||||
enable = true;
|
enable = true;
|
||||||
width = 3;
|
width = 3;
|
||||||
active.color = "#7E9CD8";
|
active.color = repoTheme.palette.niri.border.active;
|
||||||
inactive.color = "#54546D";
|
inactive.color = repoTheme.palette.niri.border.inactive;
|
||||||
urgent.color = "#E82424";
|
urgent.color = repoTheme.palette.niri.border.urgent;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -146,9 +152,10 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
binds =
|
binds =
|
||||||
if terminal.hasMainProgram then
|
if terminal.hasPackage then
|
||||||
import ./_bindings.nix {
|
import ./_bindings.nix {
|
||||||
inherit
|
inherit
|
||||||
|
browserCommand
|
||||||
lib
|
lib
|
||||||
;
|
;
|
||||||
terminalPackage = terminal.package;
|
terminalPackage = terminal.package;
|
||||||
|
|||||||
@@ -6,6 +6,17 @@
|
|||||||
let
|
let
|
||||||
homeModules = config.flake.modules.homeManager;
|
homeModules = config.flake.modules.homeManager;
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
|
mkNoctaliaSettings =
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
terminalPackage,
|
||||||
|
}:
|
||||||
|
import ./_noctalia-config.nix {
|
||||||
|
inherit
|
||||||
|
lib
|
||||||
|
terminalPackage
|
||||||
|
;
|
||||||
|
};
|
||||||
mkPortableSettings =
|
mkPortableSettings =
|
||||||
baseSettings:
|
baseSettings:
|
||||||
lib.recursiveUpdate baseSettings {
|
lib.recursiveUpdate baseSettings {
|
||||||
@@ -29,38 +40,56 @@ let
|
|||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.noctalia =
|
flake.modules.homeManager.noctalia-base =
|
||||||
{
|
{
|
||||||
inputs,
|
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
terminal = metaLib.resolveUserTerminal {
|
terminal = metaLib.resolveRepoTerminal {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
user = config.meta.user;
|
|
||||||
};
|
};
|
||||||
baseSettings =
|
baseSettings =
|
||||||
if terminal.hasMainProgram then
|
if terminal.hasPackage then
|
||||||
import ./_noctalia-config.nix {
|
mkNoctaliaSettings {
|
||||||
inherit
|
inherit lib;
|
||||||
lib
|
|
||||||
;
|
|
||||||
terminalPackage = terminal.package;
|
terminalPackage = terminal.package;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ };
|
{ };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ inputs.noctalia.homeModules.default ];
|
options.meta.lib.noctaliaBaseSettings = lib.mkOption {
|
||||||
|
type = lib.types.attrs;
|
||||||
assertions = metaLib.mkTerminalAssertions {
|
internal = true;
|
||||||
inherit terminal;
|
readOnly = true;
|
||||||
user = config.meta.user;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
meta.lib.noctaliaBaseSettings = baseSettings;
|
||||||
|
|
||||||
|
assertions = metaLib.mkTerminalAssertions {
|
||||||
|
inherit terminal;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
flake.modules.homeManager.noctalia =
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
inputs,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
homeModules.noctalia-base
|
||||||
|
inputs.noctalia.homeModules.default
|
||||||
|
];
|
||||||
|
|
||||||
programs.noctalia-shell = {
|
programs.noctalia-shell = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = lib.mkForce (
|
package = lib.mkForce (
|
||||||
@@ -69,7 +98,7 @@ in
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
settings = baseSettings;
|
settings = config.meta.lib.noctaliaBaseSettings;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -77,29 +106,15 @@ in
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
|
||||||
terminal = metaLib.resolveUserTerminal {
|
|
||||||
inherit pkgs;
|
|
||||||
user = config.meta.user;
|
|
||||||
};
|
|
||||||
baseSettings =
|
|
||||||
if terminal.hasMainProgram then
|
|
||||||
import ./_noctalia-config.nix {
|
|
||||||
inherit
|
|
||||||
lib
|
|
||||||
;
|
|
||||||
terminalPackage = terminal.package;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ };
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = [ homeModules.noctalia ];
|
imports = [ homeModules.noctalia ];
|
||||||
programs.noctalia-shell.settings = lib.mkForce (
|
programs.noctalia-shell.settings = lib.mkForce (
|
||||||
if terminal.hasMainProgram then mkPortableSettings baseSettings else { }
|
if config.meta.lib.noctaliaBaseSettings == { } then
|
||||||
|
{ }
|
||||||
|
else
|
||||||
|
mkPortableSettings config.meta.lib.noctaliaBaseSettings
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
metaLib = config.meta.lib;
|
metaRepo = config.meta.lib.repo;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.pim =
|
flake.modules.homeManager.pim =
|
||||||
@@ -51,7 +51,7 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
remote = {
|
remote = {
|
||||||
url = metaLib.repo.services.radicale.url;
|
url = metaRepo.services.radicale.url;
|
||||||
type = "caldav";
|
type = "caldav";
|
||||||
userName = config.home.username;
|
userName = config.home.username;
|
||||||
passwordCommand = [
|
passwordCommand = [
|
||||||
|
|||||||
@@ -7,8 +7,16 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
flake.modules.homeManager.qbittorrent-client =
|
flake.modules.homeManager.qbittorrent-client =
|
||||||
{ pkgs, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
home.packages = [ pkgs.qbittorrent ];
|
home.packages = [ pkgs.qbittorrent ];
|
||||||
|
|
||||||
|
programs.niri.settings.spawn-at-startup = lib.mkAfter [
|
||||||
|
{ command = [ "qbittorrent" ]; }
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
|
metaRepo = config.meta.lib.repo;
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
service = metaLib.repo.services.actual;
|
service = metaRepo.services.actual;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.actual =
|
flake.modules.nixos.actual =
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
metaLib = config.meta.lib;
|
metaRepo = config.meta.lib.repo;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.caddy = {
|
flake.modules.nixos.caddy = {
|
||||||
services.caddy = {
|
services.caddy = {
|
||||||
enable = true;
|
enable = true;
|
||||||
email = metaLib.repo.contact.email;
|
email = metaRepo.contact.email;
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
|
metaRepo = config.meta.lib.repo;
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
service = metaLib.repo.services.gitea;
|
service = metaRepo.services.gitea;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.gitea =
|
flake.modules.nixos.gitea =
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
|
metaRepo = config.meta.lib.repo;
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
service = metaLib.repo.services.radicale;
|
service = metaRepo.services.radicale;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.radicale =
|
flake.modules.nixos.radicale =
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
|
metaRepo = config.meta.lib.repo;
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
service = metaLib.repo.services.vaultwarden;
|
service = metaRepo.services.vaultwarden;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.vaultwarden =
|
flake.modules.nixos.vaultwarden =
|
||||||
|
|||||||
@@ -13,51 +13,26 @@ in
|
|||||||
host = config.meta.host;
|
host = config.meta.host;
|
||||||
user = config.meta.user;
|
user = config.meta.user;
|
||||||
sourceControl = user.sourceControl;
|
sourceControl = user.sourceControl;
|
||||||
|
sourceControlScopes = sourceControl.scopes;
|
||||||
hostSourceControlUsers = host.sourceControl.users;
|
hostSourceControlUsers = host.sourceControl.users;
|
||||||
hostUserSourceControl =
|
hostUserSourceControl = hostSourceControlUsers.${user.name} or { };
|
||||||
if lib.hasAttr user.name hostSourceControlUsers then hostSourceControlUsers.${user.name} else { };
|
|
||||||
profileNames = builtins.attrNames sourceControl.profiles;
|
|
||||||
|
|
||||||
parsedProfiles = map (
|
scopeConfig = scope: hostUserSourceControl.${scope} or null;
|
||||||
name:
|
scopeIdentity = scope: sourceControlScopes.${scope} or null;
|
||||||
let
|
|
||||||
matches = builtins.match "(github|gitlab)-(personal|work)" name;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
inherit matches name;
|
|
||||||
isValid = matches != null;
|
|
||||||
scope = if matches == null then null else builtins.elemAt matches 1;
|
|
||||||
}
|
|
||||||
) profileNames;
|
|
||||||
|
|
||||||
validProfiles = builtins.filter (profile: profile.isValid) parsedProfiles;
|
|
||||||
invalidProfileNames = map (profile: profile.name) (
|
|
||||||
builtins.filter (profile: !profile.isValid) parsedProfiles
|
|
||||||
);
|
|
||||||
|
|
||||||
emailNamesForScope = {
|
|
||||||
personal = [
|
|
||||||
"personal"
|
|
||||||
"main"
|
|
||||||
];
|
|
||||||
work = [ "work" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
scopeEmails =
|
|
||||||
scope:
|
|
||||||
map (name: user.emails.${name}) (
|
|
||||||
builtins.filter (name: lib.hasAttr name user.emails) emailNamesForScope.${scope}
|
|
||||||
);
|
|
||||||
|
|
||||||
emailForScope =
|
emailForScope =
|
||||||
scope:
|
scope:
|
||||||
let
|
let
|
||||||
emails = scopeEmails scope;
|
identity = scopeIdentity scope;
|
||||||
in
|
in
|
||||||
if builtins.length emails == 1 then (builtins.head emails).address else null;
|
if identity == null then null else identity.email;
|
||||||
|
|
||||||
scopeConfig =
|
scopeHasSigningKey =
|
||||||
scope: if lib.hasAttr scope hostUserSourceControl then hostUserSourceControl.${scope} else null;
|
scope:
|
||||||
|
let
|
||||||
|
keyConfig = scopeConfig scope;
|
||||||
|
in
|
||||||
|
keyConfig != null && keyConfig.publicKey != null;
|
||||||
|
|
||||||
privateKeyPathForScope =
|
privateKeyPathForScope =
|
||||||
scope:
|
scope:
|
||||||
@@ -69,35 +44,34 @@ in
|
|||||||
else
|
else
|
||||||
keyConfig.privateKeyPath;
|
keyConfig.privateKeyPath;
|
||||||
|
|
||||||
scopePublicKey =
|
publicKeyForScope =
|
||||||
scope:
|
scope:
|
||||||
let
|
let
|
||||||
keyConfig = scopeConfig scope;
|
keyConfig = scopeConfig scope;
|
||||||
in
|
in
|
||||||
if keyConfig == null then null else keyConfig.publicKey;
|
if keyConfig == null then null else keyConfig.publicKey;
|
||||||
|
|
||||||
scopesInUse = lib.unique (
|
scopesInUse = builtins.attrNames sourceControlScopes;
|
||||||
[
|
|
||||||
"personal"
|
allowedSignersLines = map (scope: "${emailForScope scope} ${publicKeyForScope scope}") (
|
||||||
sourceControl.projectScope
|
builtins.filter (scope: emailForScope scope != null && scopeHasSigningKey scope) scopesInUse
|
||||||
]
|
|
||||||
++ map (profile: profile.scope) validProfiles
|
|
||||||
);
|
);
|
||||||
|
|
||||||
missingKeyScopes = builtins.filter (scope: scopePublicKey scope == null) scopesInUse;
|
gitConfigForScope =
|
||||||
invalidEmailScopes = builtins.filter (scope: emailForScope scope == null) scopesInUse;
|
scope:
|
||||||
allowedSignersLines = map (scope: "${emailForScope scope} ${scopePublicKey scope}") (
|
lib.recursiveUpdate
|
||||||
builtins.filter (scope: emailForScope scope != null && scopePublicKey scope != null) scopesInUse
|
{
|
||||||
);
|
user = {
|
||||||
|
name = user.realName;
|
||||||
gitConfigForScope = scope: {
|
email = emailForScope scope;
|
||||||
gpg.ssh.allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers";
|
};
|
||||||
user = {
|
}
|
||||||
name = user.realName;
|
(
|
||||||
email = emailForScope scope;
|
lib.optionalAttrs (scopeHasSigningKey scope) {
|
||||||
signingKey = "${privateKeyPathForScope scope}.pub";
|
gpg.ssh.allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers";
|
||||||
};
|
user.signingKey = "${privateKeyPathForScope scope}.pub";
|
||||||
};
|
}
|
||||||
|
);
|
||||||
|
|
||||||
gitRoots = [
|
gitRoots = [
|
||||||
{
|
{
|
||||||
@@ -113,21 +87,6 @@ in
|
|||||||
{
|
{
|
||||||
imports = [ homeModules.git ];
|
imports = [ homeModules.git ];
|
||||||
|
|
||||||
assertions = [
|
|
||||||
{
|
|
||||||
assertion = invalidProfileNames == [ ];
|
|
||||||
message = "Invalid source control profiles for `${user.name}`: ${lib.concatStringsSep ", " invalidProfileNames}. Expected `<service>-<scope>` using github/gitlab and personal/work.";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
assertion = missingKeyScopes == [ ];
|
|
||||||
message = "Missing source control keys for `${user.name}` scopes: ${lib.concatStringsSep ", " missingKeyScopes}.";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
assertion = invalidEmailScopes == [ ];
|
|
||||||
message = "Expected exactly one email selected by name for `${user.name}` scopes: ${lib.concatStringsSep ", " invalidEmailScopes}. Personal uses `personal` or `main`; work uses `work`.";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" (
|
xdg.configFile."git/allowed_signers".text = lib.concatStringsSep "\n" (
|
||||||
allowedSignersLines ++ [ "" ]
|
allowedSignersLines ++ [ "" ]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
let
|
let
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
|
metaRepo = metaLib.repo;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.terminal =
|
flake.modules.homeManager.terminal =
|
||||||
@@ -11,17 +12,16 @@ in
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
terminal = metaLib.resolveUserTerminal {
|
repoTheme = metaRepo.theme.kanagawa;
|
||||||
|
palette = repoTheme.palette;
|
||||||
|
terminal = metaLib.resolveRepoTerminal {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
user = config.meta.user;
|
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assertions = metaLib.mkTerminalAssertions {
|
assertions = metaLib.mkTerminalAssertions {
|
||||||
inherit terminal;
|
inherit terminal;
|
||||||
user = config.meta.user;
|
|
||||||
requireDesktopEntry = true;
|
requireDesktopEntry = true;
|
||||||
requireKitty = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
xdg.terminal-exec = {
|
xdg.terminal-exec = {
|
||||||
@@ -44,43 +44,43 @@ in
|
|||||||
update_check_interval = 0;
|
update_check_interval = 0;
|
||||||
};
|
};
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
## name: Kanagawa
|
## name: ${repoTheme.displayName}
|
||||||
## license: MIT
|
## license: MIT
|
||||||
## author: Tommaso Laurenzi
|
## author: Tommaso Laurenzi
|
||||||
## upstream: https://github.com/rebelot/kanagawa.nvim/
|
## upstream: https://github.com/rebelot/kanagawa.nvim/
|
||||||
|
|
||||||
background #1F1F28
|
background ${palette.background}
|
||||||
foreground #DCD7BA
|
foreground ${palette.foreground}
|
||||||
selection_background #2D4F67
|
selection_background ${palette.selectionBackground}
|
||||||
selection_foreground #C8C093
|
selection_foreground ${palette.selectionForeground}
|
||||||
url_color #72A7BC
|
url_color ${palette.url}
|
||||||
cursor #C8C093
|
cursor ${palette.cursor}
|
||||||
|
|
||||||
active_tab_background #1F1F28
|
active_tab_background ${palette.background}
|
||||||
active_tab_foreground #C8C093
|
active_tab_foreground ${palette.selectionForeground}
|
||||||
inactive_tab_background #1F1F28
|
inactive_tab_background ${palette.background}
|
||||||
inactive_tab_foreground #727169
|
inactive_tab_foreground ${palette.muted}
|
||||||
|
|
||||||
color0 #16161D
|
color0 ${palette.terminal.color0}
|
||||||
color1 #C34043
|
color1 ${palette.terminal.color1}
|
||||||
color2 #76946A
|
color2 ${palette.terminal.color2}
|
||||||
color3 #C0A36E
|
color3 ${palette.terminal.color3}
|
||||||
color4 #7E9CD8
|
color4 ${palette.terminal.color4}
|
||||||
color5 #957FB8
|
color5 ${palette.terminal.color5}
|
||||||
color6 #6A9589
|
color6 ${palette.terminal.color6}
|
||||||
color7 #C8C093
|
color7 ${palette.terminal.color7}
|
||||||
|
|
||||||
color8 #727169
|
color8 ${palette.terminal.color8}
|
||||||
color9 #E82424
|
color9 ${palette.terminal.color9}
|
||||||
color10 #98BB6C
|
color10 ${palette.terminal.color10}
|
||||||
color11 #E6C384
|
color11 ${palette.terminal.color11}
|
||||||
color12 #7FB4CA
|
color12 ${palette.terminal.color12}
|
||||||
color13 #938AA9
|
color13 ${palette.terminal.color13}
|
||||||
color14 #7AA89F
|
color14 ${palette.terminal.color14}
|
||||||
color15 #DCD7BA
|
color15 ${palette.terminal.color15}
|
||||||
|
|
||||||
color16 #FFA066
|
color16 ${palette.terminal.color16}
|
||||||
color17 #FF5D62
|
color17 ${palette.terminal.color17}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
|
metaRepo = metaLib.repo;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.theme =
|
flake.modules.nixos.theme =
|
||||||
@@ -12,7 +13,7 @@ in
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
repoTheme = metaLib.repo.theme;
|
repoTheme = metaRepo.theme;
|
||||||
cursorTheme = repoTheme.cursor // {
|
cursorTheme = repoTheme.cursor // {
|
||||||
package = metaLib.resolvePackagePath {
|
package = metaLib.resolvePackagePath {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
@@ -34,7 +35,7 @@ in
|
|||||||
flake.modules.homeManager.theme =
|
flake.modules.homeManager.theme =
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
let
|
let
|
||||||
repoTheme = metaLib.repo.theme;
|
repoTheme = metaRepo.theme;
|
||||||
cursorTheme = repoTheme.cursor // {
|
cursorTheme = repoTheme.cursor // {
|
||||||
package = metaLib.resolvePackagePath {
|
package = metaLib.resolvePackagePath {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
|||||||
@@ -1,44 +1,58 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
let
|
||||||
|
metaRepo = config.meta.lib.repo;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.vicinae =
|
flake.modules.homeManager.vicinae =
|
||||||
{ pkgs, inputs, ... }:
|
{
|
||||||
|
pkgs,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
repoTheme = metaRepo.theme.kanagawa;
|
||||||
|
palette = repoTheme.palette;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
programs.vicinae = {
|
programs.vicinae = {
|
||||||
enable = true;
|
enable = true;
|
||||||
systemd.enable = true;
|
systemd.enable = true;
|
||||||
|
|
||||||
themes.kanagawa-wave = {
|
themes.${repoTheme.name} = {
|
||||||
meta = {
|
meta = {
|
||||||
version = 1;
|
version = 1;
|
||||||
name = "Kanagawa Wave";
|
name = repoTheme.displayName;
|
||||||
description = "A dark theme inspired by the colors of the famous painting by Katsushika Hokusai.";
|
description = "A dark theme inspired by the colors of the famous painting by Katsushika Hokusai.";
|
||||||
variant = "dark";
|
variant = "dark";
|
||||||
inherits = "vicinae-dark";
|
inherits = "vicinae-dark";
|
||||||
};
|
};
|
||||||
colors = {
|
colors = {
|
||||||
core = {
|
core = {
|
||||||
background = "#1F1F28";
|
background = palette.background;
|
||||||
foreground = "#DCD7BA";
|
foreground = palette.foreground;
|
||||||
secondary_background = "#16161D";
|
secondary_background = palette.secondaryBackground;
|
||||||
border = "#2A2A37";
|
border = palette.border;
|
||||||
accent = "#7E9CD8";
|
accent = palette.accents.blue;
|
||||||
};
|
};
|
||||||
accents = {
|
accents = {
|
||||||
blue = "#7E9CD8";
|
inherit (palette.accents)
|
||||||
green = "#98BB6C";
|
blue
|
||||||
magenta = "#D27E99";
|
cyan
|
||||||
orange = "#FFA066";
|
green
|
||||||
purple = "#957FB8";
|
magenta
|
||||||
red = "#E82424";
|
orange
|
||||||
yellow = "#E6C384";
|
purple
|
||||||
cyan = "#7AA89F";
|
red
|
||||||
|
yellow
|
||||||
|
;
|
||||||
};
|
};
|
||||||
input.border_focus = "colors.core.accent";
|
input.border_focus = "colors.core.accent";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
settings.theme = {
|
settings.theme = {
|
||||||
light.name = "kanagawa-wave";
|
light.name = repoTheme.name;
|
||||||
dark.name = "kanagawa-wave";
|
dark.name = repoTheme.name;
|
||||||
};
|
};
|
||||||
|
|
||||||
extensions = with inputs.vicinae-extensions.packages.${pkgs.stdenv.hostPlatform.system}; [
|
extensions = with inputs.vicinae-extensions.packages.${pkgs.stdenv.hostPlatform.system}; [
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ in
|
|||||||
nixosModules.networking
|
nixosModules.networking
|
||||||
nixosModules.niri
|
nixosModules.niri
|
||||||
nixosModules.printing
|
nixosModules.printing
|
||||||
nixosModules.qbittorrent-client
|
|
||||||
nixosModules.sddm
|
nixosModules.sddm
|
||||||
nixosModules.sops-admin-key-file
|
nixosModules.sops-admin-key-file
|
||||||
nixosModules.standard-boot
|
nixosModules.standard-boot
|
||||||
@@ -30,6 +29,13 @@ in
|
|||||||
environment.localBinInPath = true;
|
environment.localBinInPath = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
flake.modules.nixos.workstation-host = {
|
||||||
|
imports = [
|
||||||
|
nixosModules.workstation-base
|
||||||
|
nixosModules.qbittorrent-client
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
flake.modules.homeManager.workstation-base = {
|
flake.modules.homeManager.workstation-base = {
|
||||||
imports = [
|
imports = [
|
||||||
homeModules.ai
|
homeModules.ai
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
let
|
||||||
|
metaLib = config.meta.lib;
|
||||||
|
metaRepo = metaLib.repo;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
flake.modules.homeManager.xdg =
|
flake.modules.homeManager.xdg =
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
let
|
let
|
||||||
|
browserPackage = metaLib.resolvePackagePath {
|
||||||
|
inherit pkgs;
|
||||||
|
path = metaRepo.desktop.browser.packagePath;
|
||||||
|
};
|
||||||
|
fileManagerPackage = metaLib.resolvePackagePath {
|
||||||
|
inherit pkgs;
|
||||||
|
path = metaRepo.desktop.fileManager.packagePath;
|
||||||
|
};
|
||||||
homeDir = config.home.homeDirectory;
|
homeDir = config.home.homeDirectory;
|
||||||
localDir = "${homeDir}/.local";
|
localDir = "${homeDir}/.local";
|
||||||
mediaDir = "${homeDir}/media";
|
mediaDir = "${homeDir}/media";
|
||||||
@@ -33,13 +46,17 @@
|
|||||||
|
|
||||||
mimeApps = {
|
mimeApps = {
|
||||||
enable = true;
|
enable = true;
|
||||||
defaultApplicationPackages = with pkgs; [
|
defaultApplicationPackages =
|
||||||
sioyek
|
with pkgs;
|
||||||
imv
|
[
|
||||||
vivaldi
|
sioyek
|
||||||
neovim
|
imv
|
||||||
nautilus
|
neovim
|
||||||
];
|
]
|
||||||
|
++ [
|
||||||
|
browserPackage
|
||||||
|
fileManagerPackage
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,15 +4,16 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
hostNames = [
|
hostNames = builtins.attrNames (
|
||||||
"orion"
|
inputs.nixpkgs.lib.filterAttrs (_: type: type == "directory") (builtins.readDir ./hosts)
|
||||||
"polaris"
|
);
|
||||||
"zenith"
|
|
||||||
];
|
|
||||||
nixosModules = config.flake.modules.nixos;
|
nixosModules = config.flake.modules.nixos;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ inputs.flake-parts.flakeModules.modules ];
|
imports = [
|
||||||
|
inputs.flake-parts.flakeModules.modules
|
||||||
|
./data.nix
|
||||||
|
];
|
||||||
|
|
||||||
systems = [ "x86_64-linux" ];
|
systems = [ "x86_64-linux" ];
|
||||||
|
|
||||||
|
|||||||
@@ -17,15 +17,13 @@ in
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
terminal = metaLib.resolveUserTerminal {
|
terminal = metaLib.resolveRepoTerminal {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
user = config.meta.host.users.kiri;
|
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assertions = metaLib.mkTerminalAssertions {
|
assertions = metaLib.mkTerminalAssertions {
|
||||||
inherit terminal;
|
inherit terminal;
|
||||||
user = config.meta.host.users.kiri;
|
|
||||||
requireTerminfo = true;
|
requireTerminfo = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -45,7 +43,7 @@ in
|
|||||||
name = "orion";
|
name = "orion";
|
||||||
users = {
|
users = {
|
||||||
kiri = {
|
kiri = {
|
||||||
account = metaLib.users.kiri;
|
account = metaLib.accounts.kiri;
|
||||||
homeImports = [
|
homeImports = [
|
||||||
homeModules.shell
|
homeModules.shell
|
||||||
homeModules.git
|
homeModules.git
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ let
|
|||||||
nixosModules = config.flake.modules.nixos;
|
nixosModules = config.flake.modules.nixos;
|
||||||
homeModules = config.flake.modules.homeManager;
|
homeModules = config.flake.modules.homeManager;
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
|
workstationHomeImports = [ homeModules.workstation-base ];
|
||||||
|
kiriHomeImports = workstationHomeImports ++ [
|
||||||
|
homeModules.syncthing
|
||||||
|
homeModules.qbittorrent-client
|
||||||
|
homeModules.noctalia
|
||||||
|
];
|
||||||
|
ergonHomeImports = workstationHomeImports ++ [ homeModules.noctalia ];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.polaris = metaLib.mkHost {
|
flake.modules.nixos.polaris = metaLib.mkHost {
|
||||||
@@ -29,39 +36,22 @@ in
|
|||||||
mouse.accelSpeed = 0.4;
|
mouse.accelSpeed = 0.4;
|
||||||
};
|
};
|
||||||
|
|
||||||
sourceControl.users = {
|
|
||||||
kiri.personal.publicKey = "";
|
|
||||||
|
|
||||||
ergon = {
|
|
||||||
personal.publicKey = "";
|
|
||||||
work.publicKey = "";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
users = {
|
users = {
|
||||||
kiri = {
|
kiri = {
|
||||||
account = metaLib.users.kiri;
|
account = metaLib.accounts.kiri;
|
||||||
needsPassword = true;
|
needsPassword = true;
|
||||||
homeImports = [
|
homeImports = kiriHomeImports;
|
||||||
homeModules.workstation-base
|
|
||||||
homeModules.syncthing
|
|
||||||
homeModules.qbittorrent-client
|
|
||||||
homeModules.noctalia
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ergon = {
|
ergon = {
|
||||||
account = metaLib.users.ergon;
|
account = metaLib.accounts.ergon;
|
||||||
needsPassword = true;
|
needsPassword = true;
|
||||||
homeImports = [
|
homeImports = ergonHomeImports;
|
||||||
homeModules.workstation-base
|
|
||||||
homeModules.noctalia
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
nixosModules.workstation-base
|
nixosModules.workstation-host
|
||||||
nixosModules.steam
|
nixosModules.steam
|
||||||
./_hardware.nix
|
./_hardware.nix
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -7,6 +7,14 @@ let
|
|||||||
nixosModules = config.flake.modules.nixos;
|
nixosModules = config.flake.modules.nixos;
|
||||||
homeModules = config.flake.modules.homeManager;
|
homeModules = config.flake.modules.homeManager;
|
||||||
metaLib = config.meta.lib;
|
metaLib = config.meta.lib;
|
||||||
|
workstationHomeImports = [ homeModules.workstation-base ];
|
||||||
|
portableNoctalia = homeModules.noctalia-portable;
|
||||||
|
kiriHomeImports = workstationHomeImports ++ [
|
||||||
|
homeModules.syncthing
|
||||||
|
homeModules.qbittorrent-client
|
||||||
|
portableNoctalia
|
||||||
|
];
|
||||||
|
ergonHomeImports = workstationHomeImports ++ [ portableNoctalia ];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.zenith = metaLib.mkHost {
|
flake.modules.nixos.zenith = metaLib.mkHost {
|
||||||
@@ -31,8 +39,6 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
sourceControl.users = {
|
sourceControl.users = {
|
||||||
kiri.personal.publicKey = "";
|
|
||||||
|
|
||||||
ergon = {
|
ergon = {
|
||||||
personal.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPdR3KP2U84i7f7MlRqcML/3YyMw8JL3hdm637SkMUwO ergon@zenith#personal";
|
personal.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPdR3KP2U84i7f7MlRqcML/3YyMw8JL3hdm637SkMUwO ergon@zenith#personal";
|
||||||
work.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHJz5uHKm0/TiMNh/cmzrODHNZ8NgEEZe+47XnJwQGk ergon@zenith#work";
|
work.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHJz5uHKm0/TiMNh/cmzrODHNZ8NgEEZe+47XnJwQGk ergon@zenith#work";
|
||||||
@@ -41,28 +47,20 @@ in
|
|||||||
|
|
||||||
users = {
|
users = {
|
||||||
kiri = {
|
kiri = {
|
||||||
account = metaLib.users.kiri;
|
account = metaLib.accounts.kiri;
|
||||||
needsPassword = true;
|
needsPassword = true;
|
||||||
homeImports = [
|
homeImports = kiriHomeImports;
|
||||||
homeModules.workstation-base
|
|
||||||
homeModules.syncthing
|
|
||||||
homeModules.qbittorrent-client
|
|
||||||
homeModules.noctalia-portable
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ergon = {
|
ergon = {
|
||||||
account = metaLib.users.ergon;
|
account = metaLib.accounts.ergon;
|
||||||
needsPassword = true;
|
needsPassword = true;
|
||||||
homeImports = [
|
homeImports = ergonHomeImports;
|
||||||
homeModules.workstation-base
|
|
||||||
homeModules.noctalia-portable
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
nixosModules.workstation-base
|
nixosModules.workstation-host
|
||||||
nixosModules.laptop-power
|
nixosModules.laptop-power
|
||||||
{
|
{
|
||||||
hardware.enableRedistributableFirmware = true;
|
hardware.enableRedistributableFirmware = true;
|
||||||
|
|||||||
+39
-120
@@ -4,6 +4,15 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
normalizeHostUser =
|
||||||
|
spec:
|
||||||
|
{
|
||||||
|
homeImports = [ ];
|
||||||
|
needsPassword = false;
|
||||||
|
stateVersion = null;
|
||||||
|
}
|
||||||
|
// spec;
|
||||||
|
|
||||||
mkHost =
|
mkHost =
|
||||||
{
|
{
|
||||||
name,
|
name,
|
||||||
@@ -20,26 +29,11 @@ let
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
hostUsers = lib.mapAttrs (_: spec: spec.account) users;
|
hostUserSpecs = lib.mapAttrs (_: spec: normalizeHostUser spec) users;
|
||||||
|
hostUsers = lib.mapAttrs (_: spec: spec.account) hostUserSpecs;
|
||||||
userAssertions = lib.flatten (
|
passwordUserSpecs = lib.filterAttrs (_: spec: spec.needsPassword) hostUserSpecs;
|
||||||
lib.mapAttrsToList (userName: spec: [
|
|
||||||
{
|
|
||||||
assertion = userName == spec.account.name;
|
|
||||||
message = "Host `${name}` declares user `${userName}` with mismatched account name `${spec.account.name}`.";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
assertion = builtins.isList spec.homeImports;
|
|
||||||
message = "Host `${name}` user `${userName}` must define `homeImports` as a list.";
|
|
||||||
}
|
|
||||||
]) users
|
|
||||||
);
|
|
||||||
|
|
||||||
passwordUserSpecs = lib.filterAttrs (_: spec: spec.needsPassword or false) users;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assertions = userAssertions;
|
|
||||||
|
|
||||||
meta.host = {
|
meta.host = {
|
||||||
inherit
|
inherit
|
||||||
displays
|
displays
|
||||||
@@ -67,7 +61,7 @@ let
|
|||||||
users.users = lib.mapAttrs (
|
users.users = lib.mapAttrs (
|
||||||
userName: spec:
|
userName: spec:
|
||||||
{
|
{
|
||||||
name = spec.account.name;
|
name = userName;
|
||||||
home = spec.account.homeDirectory;
|
home = spec.account.homeDirectory;
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
shell = pkgs.zsh;
|
shell = pkgs.zsh;
|
||||||
@@ -76,10 +70,10 @@ let
|
|||||||
"networkmanager"
|
"networkmanager"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (spec.needsPassword or false) {
|
// lib.optionalAttrs spec.needsPassword {
|
||||||
hashedPasswordFile = config.sops.secrets."hashed-password-${userName}".path;
|
hashedPasswordFile = config.sops.secrets."hashed-password-${userName}".path;
|
||||||
}
|
}
|
||||||
) users;
|
) hostUserSpecs;
|
||||||
|
|
||||||
home-manager.users = lib.mapAttrs (_: spec: {
|
home-manager.users = lib.mapAttrs (_: spec: {
|
||||||
imports = spec.homeImports;
|
imports = spec.homeImports;
|
||||||
@@ -90,9 +84,9 @@ let
|
|||||||
home = {
|
home = {
|
||||||
username = spec.account.name;
|
username = spec.account.name;
|
||||||
homeDirectory = spec.account.homeDirectory;
|
homeDirectory = spec.account.homeDirectory;
|
||||||
stateVersion = spec.stateVersion or stateVersion;
|
stateVersion = if spec.stateVersion == null then stateVersion else spec.stateVersion;
|
||||||
};
|
};
|
||||||
}) users;
|
}) hostUserSpecs;
|
||||||
};
|
};
|
||||||
|
|
||||||
mkCaddyReverseProxy =
|
mkCaddyReverseProxy =
|
||||||
@@ -129,119 +123,59 @@ let
|
|||||||
}:
|
}:
|
||||||
lib.attrByPath path null pkgs;
|
lib.attrByPath path null pkgs;
|
||||||
|
|
||||||
repo = {
|
resolveRepoTerminal =
|
||||||
contact.email = "mail@jelles.net";
|
|
||||||
|
|
||||||
services = {
|
|
||||||
actual = {
|
|
||||||
domain = "finance.jelles.net";
|
|
||||||
host = "127.0.0.1";
|
|
||||||
port = 3000;
|
|
||||||
url = "https://finance.jelles.net";
|
|
||||||
};
|
|
||||||
|
|
||||||
gitea = {
|
|
||||||
domain = "git.jelles.net";
|
|
||||||
host = "127.0.0.1";
|
|
||||||
port = 3001;
|
|
||||||
url = "https://git.jelles.net/";
|
|
||||||
};
|
|
||||||
|
|
||||||
radicale = {
|
|
||||||
domain = "radicale.jelles.net";
|
|
||||||
host = "127.0.0.1";
|
|
||||||
port = 5232;
|
|
||||||
url = "https://radicale.jelles.net/";
|
|
||||||
};
|
|
||||||
|
|
||||||
vaultwarden = {
|
|
||||||
domain = "vault.jelles.net";
|
|
||||||
host = "127.0.0.1";
|
|
||||||
port = 8100;
|
|
||||||
url = "https://vault.jelles.net";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
theme = {
|
|
||||||
cursor = {
|
|
||||||
name = "phinger-cursors-light";
|
|
||||||
packagePath = [ "phinger-cursors" ];
|
|
||||||
size = 24;
|
|
||||||
};
|
|
||||||
|
|
||||||
kanagawa = {
|
|
||||||
gtkThemeName = "Kanagawa-BL-LB";
|
|
||||||
iconThemeName = "Kanagawa";
|
|
||||||
owner = "Fausto-Korpsvart";
|
|
||||||
repo = "Kanagawa-GKT-Theme";
|
|
||||||
rev = "55ca4ba249eba21f861b9866b71ab41bb8930318";
|
|
||||||
hash = "sha256-UdMoMx2DoovcxSp/zBZ3PRv/Qpj+prd0uPm1gmdak2E=";
|
|
||||||
version = "unstable-2025-10-23";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
resolveUserTerminal =
|
|
||||||
{
|
{
|
||||||
pkgs,
|
pkgs,
|
||||||
user,
|
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
terminal = config.meta.lib.repo.desktop.terminal;
|
||||||
package = resolvePackagePath {
|
package = resolvePackagePath {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
path = user.terminalPackagePath;
|
path = terminal.packagePath;
|
||||||
};
|
};
|
||||||
hasPackage = package != null;
|
|
||||||
hasMainProgram = hasPackage && package ? meta.mainProgram;
|
|
||||||
mainProgram = if hasMainProgram then package.meta.mainProgram else null;
|
|
||||||
desktopId = if mainProgram == null then null else "${mainProgram}.desktop";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
inherit
|
inherit
|
||||||
desktopId
|
|
||||||
hasMainProgram
|
|
||||||
hasPackage
|
|
||||||
mainProgram
|
|
||||||
package
|
package
|
||||||
;
|
;
|
||||||
|
inherit (terminal)
|
||||||
|
command
|
||||||
|
desktopId
|
||||||
|
packagePath
|
||||||
|
;
|
||||||
|
|
||||||
|
hasPackage = package != null;
|
||||||
|
|
||||||
hasDesktopEntry =
|
hasDesktopEntry =
|
||||||
desktopId != null && builtins.pathExists "${package}/share/applications/${desktopId}";
|
package != null && builtins.pathExists "${package}/share/applications/${terminal.desktopId}";
|
||||||
|
|
||||||
hasTerminfo = hasPackage && lib.elem "terminfo" package.outputs;
|
hasTerminfo = package != null && lib.elem "terminfo" package.outputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
mkTerminalAssertions =
|
mkTerminalAssertions =
|
||||||
{
|
{
|
||||||
terminal,
|
terminal,
|
||||||
user,
|
|
||||||
requireDesktopEntry ? false,
|
requireDesktopEntry ? false,
|
||||||
requireKitty ? false,
|
|
||||||
requireMainProgram ? true,
|
|
||||||
requireTerminfo ? false,
|
requireTerminfo ? false,
|
||||||
}:
|
}:
|
||||||
lib.flatten [
|
lib.flatten [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
assertion = terminal.hasPackage;
|
assertion = terminal.hasPackage;
|
||||||
message = "Unknown terminal package `${lib.showAttrPath user.terminalPackagePath}` for user `${user.name}`.";
|
message = "Unknown terminal package `${lib.showAttrPath terminal.packagePath}` in `meta.lib.repo.desktop.terminal`.";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = terminal.command == "kitty";
|
||||||
|
message = "The repo terminal is currently expected to be kitty.";
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
(lib.optional requireMainProgram {
|
|
||||||
assertion = terminal.hasMainProgram;
|
|
||||||
message = "Terminal package `${lib.showAttrPath user.terminalPackagePath}` must define `meta.mainProgram`.";
|
|
||||||
})
|
|
||||||
(lib.optional requireDesktopEntry {
|
(lib.optional requireDesktopEntry {
|
||||||
assertion = terminal.hasDesktopEntry;
|
assertion = terminal.hasDesktopEntry;
|
||||||
message = "Terminal package `${lib.showAttrPath user.terminalPackagePath}` must provide `${terminal.desktopId}`.";
|
message = "Terminal package `${lib.showAttrPath terminal.packagePath}` must provide `${terminal.desktopId}`.";
|
||||||
})
|
|
||||||
(lib.optional requireKitty {
|
|
||||||
assertion = terminal.hasMainProgram && terminal.mainProgram == "kitty";
|
|
||||||
message = "The terminal feature currently only supports kitty-specific Home Manager configuration.";
|
|
||||||
})
|
})
|
||||||
(lib.optional requireTerminfo {
|
(lib.optional requireTerminfo {
|
||||||
assertion = terminal.hasTerminfo;
|
assertion = terminal.hasTerminfo;
|
||||||
message = "Terminal package `${lib.showAttrPath user.terminalPackagePath}` must provide a `terminfo` output.";
|
message = "Terminal package `${lib.showAttrPath terminal.packagePath}` must provide a `terminfo` output.";
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -406,9 +340,9 @@ in
|
|||||||
readOnly = true;
|
readOnly = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
options.meta.lib.resolveUserTerminal = lib.mkOption {
|
options.meta.lib.resolveRepoTerminal = lib.mkOption {
|
||||||
type = lib.types.raw;
|
type = lib.types.raw;
|
||||||
description = "Internal helper to resolve and validate user terminal metadata.";
|
description = "Internal helper to resolve and validate the repo-standard terminal.";
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
};
|
};
|
||||||
@@ -427,29 +361,14 @@ in
|
|||||||
readOnly = true;
|
readOnly = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
options.meta.lib.users = lib.mkOption {
|
|
||||||
type = lib.types.attrs;
|
|
||||||
description = "Canonical user attrsets shared by host definitions.";
|
|
||||||
internal = true;
|
|
||||||
readOnly = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
options.meta.lib.repo = lib.mkOption {
|
|
||||||
type = lib.types.attrs;
|
|
||||||
description = "Internal shared repository metadata.";
|
|
||||||
internal = true;
|
|
||||||
readOnly = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
config.meta.lib = {
|
config.meta.lib = {
|
||||||
inherit
|
inherit
|
||||||
mkInputProfiles
|
mkInputProfiles
|
||||||
mkCaddyReverseProxy
|
mkCaddyReverseProxy
|
||||||
mkTerminalAssertions
|
mkTerminalAssertions
|
||||||
mkHost
|
mkHost
|
||||||
repo
|
|
||||||
resolvePackagePath
|
resolvePackagePath
|
||||||
resolveUserTerminal
|
resolveRepoTerminal
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
let
|
|
||||||
kiri = {
|
|
||||||
name = "kiri";
|
|
||||||
realName = "Jelle Spreeuwenberg";
|
|
||||||
homeDirectory = "/home/kiri";
|
|
||||||
terminalPackagePath = [ "kitty" ];
|
|
||||||
emails = {
|
|
||||||
personal = {
|
|
||||||
address = "mail@jelles.net";
|
|
||||||
primary = true;
|
|
||||||
type = "mxrouting";
|
|
||||||
};
|
|
||||||
old = {
|
|
||||||
address = "mail@jellespreeuwenberg.nl";
|
|
||||||
primary = false;
|
|
||||||
type = "mxrouting";
|
|
||||||
};
|
|
||||||
uni = {
|
|
||||||
address = "j.spreeuwenberg@student.tue.nl";
|
|
||||||
primary = false;
|
|
||||||
type = "office365";
|
|
||||||
};
|
|
||||||
work = {
|
|
||||||
address = "jelle.spreeuwenberg@yookr.org";
|
|
||||||
primary = false;
|
|
||||||
type = "office365";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
sourceControl = {
|
|
||||||
profiles = {
|
|
||||||
github-personal = { };
|
|
||||||
gitlab-personal = { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
ergon = {
|
|
||||||
name = "ergon";
|
|
||||||
realName = "Jelle Spreeuwenberg";
|
|
||||||
homeDirectory = "/home/ergon";
|
|
||||||
terminalPackagePath = [ "kitty" ];
|
|
||||||
emails = {
|
|
||||||
personal = {
|
|
||||||
address = "mail@jelles.net";
|
|
||||||
primary = false;
|
|
||||||
type = "mxrouting";
|
|
||||||
};
|
|
||||||
work = {
|
|
||||||
address = "jelle.spreeuwenberg@yookr.org";
|
|
||||||
primary = true;
|
|
||||||
type = "office365";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
sourceControl = {
|
|
||||||
profiles = {
|
|
||||||
github-personal = { };
|
|
||||||
github-work = { };
|
|
||||||
gitlab-personal = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
projectScope = "work";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
meta.lib.users = {
|
|
||||||
inherit
|
|
||||||
ergon
|
|
||||||
kiri
|
|
||||||
;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user