This commit is contained in:
Felix Bargfeldt 2025-02-21 18:44:13 +01:00
parent 4f5022bfdd
commit 1abbd2aae0
Signed by: Defelo
GPG key ID: 2A05272471204DD3
79 changed files with 1375 additions and 1070 deletions

View file

@ -9,8 +9,14 @@ permissions:
contents: read
jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@v16
- run: nix fmt -- --ci
checks:
name: checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

View file

@ -4,9 +4,9 @@ keys:
creation_rules:
- path_regex: hosts/neon/secrets/.+$
key_groups:
- pgp: [ *defelo ]
age: [ *neon ]
- pgp: [*defelo]
age: [*neon]
- path_regex: secrets/.+$
key_groups:
- pgp: [ *defelo ]
age: [ *neon ]
- pgp: [*defelo]
age: [*neon]

37
flake.lock generated
View file

@ -394,6 +394,22 @@
"type": "github"
}
},
"nixpkgs_6": {
"locked": {
"lastModified": 1735554305,
"narHash": "sha256-zExSA1i/b+1NMRhGGLtNfFGXgLtgo+dcuzHzaWA6w3Q=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "0e82ab234249d8eee3e8c91437802b32c74bb3fd",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks-nix": {
"inputs": {
"flake-compat": [
@ -432,7 +448,8 @@
"nix-index-database": "nix-index-database",
"nix-vscode-extensions": "nix-vscode-extensions",
"nixpkgs": "nixpkgs_4",
"sops-nix": "sops-nix"
"sops-nix": "sops-nix",
"treefmt-nix": "treefmt-nix"
}
},
"rust-analyzer-src": {
@ -541,6 +558,24 @@
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": "nixpkgs_6"
},
"locked": {
"lastModified": 1739829690,
"narHash": "sha256-mL1szCeIsjh6Khn3nH2cYtwO5YXG6gBiTw1A30iGeDU=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "3d0579f5cc93436052d94b73925b48973a104204",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",

235
flake.nix
View file

@ -24,112 +24,155 @@
url = "github:nix-community/lanzaboote/v0.4.2";
inputs.nixpkgs.follows = "nixpkgs";
};
treefmt-nix.url = "github:numtide/treefmt-nix";
};
outputs = {
self,
nixpkgs,
home-manager,
...
} @ inputs: let
inherit (nixpkgs) lib;
outputs =
{
self,
nixpkgs,
home-manager,
treefmt-nix,
...
}@inputs:
let
inherit (nixpkgs) lib;
eachDefaultSystem = lib.genAttrs [
"x86_64-linux"
"aarch64-linux"
];
importNixpkgs = system: nixpkgs: let
config.allowUnfreePredicate = pkg:
builtins.elem (lib.getName pkg) [
"discord-canary"
"obsidian"
"steam"
"steam-unwrapped"
"steam-original"
"steam-run"
"spotify"
];
in
import nixpkgs {
inherit system config;
overlays = [
(final: prev: {
linuxPackages_latest = prev.linuxPackages_latest.extend (lpfinal: lpprev: {
rtl8821ce = lpprev.rtl8821ce.overrideAttrs (
{patches ? [], ...}: {
patches =
[
(final.fetchpatch {
name = "rtl8821ce-linux613";
url = "https://github.com/tomaspinho/rtl8821ce/commit/4c0f3cf7aec51c8d842f8df130227a69dbfb74a0.patch";
hash = "sha256-ms5S9KkulCAmWNl2SSyQs18QxIWFh8iwcaxwI74X2Uk=";
})
]
++ patches;
}
);
});
})
];
};
extra-pkgs = system:
lib.pipe inputs [
(lib.filterAttrs (k: _: lib.hasPrefix "nixpkgs-" k))
(lib.mapAttrs' (k: v: {
name = lib.removePrefix "nix" k;
value = importNixpkgs system v;
}))
eachDefaultSystem = lib.genAttrs [
"x86_64-linux"
"aarch64-linux"
];
getSystemFromHardwareConfiguration = hostName: let
f = import ./hosts/${hostName}/hardware-configuration.nix;
args = builtins.functionArgs f // {lib.mkDefault = lib.id;};
in
(f args).nixpkgs.hostPlatform;
importNixpkgs =
system: nixpkgs:
let
config.allowUnfreePredicate =
pkg:
builtins.elem (lib.getName pkg) [
"discord-canary"
"obsidian"
"steam"
"steam-unwrapped"
"steam-original"
"steam-run"
"spotify"
];
in
import nixpkgs {
inherit system config;
overlays = [
(final: prev: {
linuxPackages_latest = prev.linuxPackages_latest.extend (
lpfinal: lpprev: {
rtl8821ce = lpprev.rtl8821ce.overrideAttrs (
{
patches ? [ ],
...
}:
{
patches = [
(final.fetchpatch {
name = "rtl8821ce-linux613";
url = "https://github.com/tomaspinho/rtl8821ce/commit/4c0f3cf7aec51c8d842f8df130227a69dbfb74a0.patch";
hash = "sha256-ms5S9KkulCAmWNl2SSyQs18QxIWFh8iwcaxwI74X2Uk=";
})
] ++ patches;
}
);
}
);
})
];
};
mkHost = name: system:
lib.nixosSystem {
inherit system;
pkgs = importNixpkgs system nixpkgs;
specialArgs = inputs // (extra-pkgs system);
modules = [
./hosts/${name}
./hosts/${name}/hardware-configuration.nix
./system
{networking.hostName = name;}
extra-pkgs =
system:
lib.pipe inputs [
(lib.filterAttrs (k: _: lib.hasPrefix "nixpkgs-" k))
(lib.mapAttrs' (
k: v: {
name = lib.removePrefix "nix" k;
value = importNixpkgs system v;
}
))
];
};
in {
nixosConfigurations = lib.pipe ./hosts [
builtins.readDir
(lib.filterAttrs (_: type: type == "directory"))
(builtins.mapAttrs (name: _: mkHost name (getSystemFromHardwareConfiguration name)))
];
packages = eachDefaultSystem (
system: let
pkgs = importNixpkgs system nixpkgs;
in
getSystemFromHardwareConfiguration =
hostName:
let
f = import ./hosts/${hostName}/hardware-configuration.nix;
args = builtins.functionArgs f // {
lib.mkDefault = lib.id;
};
in
(f args).nixpkgs.hostPlatform;
mkHost =
name: system:
lib.nixosSystem {
inherit system;
pkgs = importNixpkgs system nixpkgs;
specialArgs = inputs // (extra-pkgs system);
modules = [
./hosts/${name}
./hosts/${name}/hardware-configuration.nix
./system
{ networking.hostName = name; }
];
};
in
{
nixosConfigurations = lib.pipe ./hosts [
builtins.readDir
(lib.filterAttrs (_: type: type == "directory"))
(builtins.mapAttrs (name: _: mkHost name (getSystemFromHardwareConfiguration name)))
];
packages = eachDefaultSystem (
system:
let
pkgs = importNixpkgs system nixpkgs;
in
import ./scripts pkgs
// {
checks = let
packages = pkgs.linkFarm "nixos-checks-packages" (lib.removeAttrs self.packages.${system} ["checks"]);
hosts = pkgs.linkFarm "nixos-checks-hosts" (lib.mapAttrs (_: v: v.config.system.build.toplevel) self.nixosConfigurations);
in
pkgs.linkFarmFromDrvs "nixos-checks" [packages hosts];
checks =
let
packages = pkgs.linkFarm "nixos-checks-packages" (
lib.removeAttrs self.packages.${system} [ "checks" ]
);
hosts = pkgs.linkFarm "nixos-checks-hosts" (
lib.mapAttrs (_: v: v.config.system.build.toplevel) self.nixosConfigurations
);
in
pkgs.linkFarmFromDrvs "nixos-checks" [
packages
hosts
];
}
);
);
checks = let
packages = lib.mapAttrs (_: v: lib.removeAttrs v ["ci" "checks"]) self.packages;
nixosConfigurations =
lib.mapAttrsToList (name: config: {
${getSystemFromHardwareConfiguration name}.${name} = config.config.system.build.toplevel;
})
self.nixosConfigurations;
in
builtins.foldl' lib.recursiveUpdate {} ([packages] ++ nixosConfigurations);
};
checks =
let
packages = lib.mapAttrs (
_: v:
lib.removeAttrs v [
"ci"
"checks"
]
) self.packages;
nixosConfigurations = lib.mapAttrsToList (name: config: {
${getSystemFromHardwareConfiguration name}.${name} = config.config.system.build.toplevel;
}) self.nixosConfigurations;
in
builtins.foldl' lib.recursiveUpdate { } ([ packages ] ++ nixosConfigurations);
formatter = eachDefaultSystem (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix;
in
treefmtEval.config.build.wrapper
);
};
}

View file

@ -1,4 +1,5 @@
{conf, ...}: {
{ conf, ... }:
{
programs.aerc = {
enable = true;
extraConfig = {
@ -21,7 +22,7 @@
".headers" = "colorize";
};
};
extraBinds = {};
extraBinds = { };
};
sops.secrets."aerc/accounts" = {

View file

@ -1,4 +1,4 @@
{...}: {
{
programs.alacritty = {
enable = true;
settings = {

View file

@ -1,9 +1,6 @@
{ pkgs, cheatsheets, ... }:
{
pkgs,
cheatsheets,
...
}: {
home.packages = [pkgs.cheat];
home.packages = [ pkgs.cheat ];
home.file.cheat = {
target = ".config/cheat/conf.yml";
text = builtins.toJSON {
@ -16,7 +13,7 @@
{
name = "community";
path = cheatsheets;
tags = ["community"];
tags = [ "community" ];
readonly = true;
}
];

View file

@ -1,12 +1,13 @@
{pkgs, ...}: {
home.packages = [pkgs.clipman];
{ pkgs, ... }:
{
home.packages = [ pkgs.clipman ];
# https://github.com/nix-community/home-manager/blob/master/modules/services/clipman.nix
systemd.user.services.clipman = {
Unit = {
Description = "Clipboard management daemon";
PartOf = ["graphical-session.target"];
After = ["graphical-session.target"];
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
@ -16,6 +17,6 @@
KillMode = "mixed";
};
Install.WantedBy = ["graphical-session.target"];
Install.WantedBy = [ "graphical-session.target" ];
};
}

View file

@ -1,5 +1,8 @@
{
home.sessionPath = ["$HOME/.local/bin" "$HOME/.cargo/bin"];
home.sessionPath = [
"$HOME/.local/bin"
"$HOME/.cargo/bin"
];
home.sessionVariables = {
EDITOR = "hx";

View file

@ -11,39 +11,38 @@ let
./zoxide.nix
./zsh
];
in {
user =
common
++ [
./aerc.nix
./alacritty.nix
./clipman.nix
./dunst.nix
# ./fcitx5.nix
./gammastep.nix
./git.nix
./gpg.nix
./helix/full.nix
./hyfetch.nix
# ./libreoffice.nix
./niri
./ntfy.nix
./packages.nix
./pass.nix
./playerctld.nix
./programming
./rofi
./sops.nix
./ssh.nix
./syncthing.nix
./theme.nix
./thunderbird
./vscodium.nix
./waybar.nix
./xournalpp
./yubikey.nix
./zsh/full.nix
];
in
{
user = common ++ [
./aerc.nix
./alacritty.nix
./clipman.nix
./dunst.nix
# ./fcitx5.nix
./gammastep.nix
./git.nix
./gpg.nix
./helix/full.nix
./hyfetch.nix
# ./libreoffice.nix
./niri
./ntfy.nix
./packages.nix
./pass.nix
./playerctld.nix
./programming
./rofi
./sops.nix
./ssh.nix
./syncthing.nix
./theme.nix
./thunderbird
./vscodium.nix
./waybar.nix
./xournalpp
./yubikey.nix
./zsh/full.nix
];
root = common;
}

View file

@ -1,4 +1,4 @@
{...}: {
{
programs.direnv = {
enable = true;
nix-direnv.enable = true;

View file

@ -1,78 +1,81 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
services.dunst = {
enable = true;
settings = let
transparency = "DD";
in {
global = {
follow = "mouse";
width = 300;
height = 300;
origin = "top-right";
offset = "10x50";
scale = 0;
notification_limit = 0;
settings =
let
transparency = "DD";
in
{
global = {
follow = "mouse";
width = 300;
height = 300;
origin = "top-right";
offset = "10x50";
scale = 0;
notification_limit = 0;
indicate_hidden = true;
separator_height = 2;
padding = 6;
horizontal_padding = 6;
text_icon_padding = 0;
frame_width = 3;
frame_color = "#8EC07C${transparency}";
sort = true;
idle_threshold = 0;
indicate_hidden = true;
separator_height = 2;
padding = 6;
horizontal_padding = 6;
text_icon_padding = 0;
frame_width = 3;
frame_color = "#8EC07C${transparency}";
sort = true;
idle_threshold = 0;
font = "Meslo Nerd Font 11";
line_height = 3;
markup = "full";
format = "<b>%s</b>\\n%b";
alignment = "center";
vertical_alignment = "top";
show_age_threshold = 10;
ellipsize = "middle";
ignore_newline = false;
stack_duplicates = true;
hide_duplicate_count = false;
show_indicators = true;
font = "Meslo Nerd Font 11";
line_height = 3;
markup = "full";
format = "<b>%s</b>\\n%b";
alignment = "center";
vertical_alignment = "top";
show_age_threshold = 10;
ellipsize = "middle";
ignore_newline = false;
stack_duplicates = true;
hide_duplicate_count = false;
show_indicators = true;
icon_position = "left";
min_icon_size = 0;
max_icon_size = 32;
icon_position = "left";
min_icon_size = 0;
max_icon_size = 32;
sticky_history = true;
history_length = 10000;
sticky_history = true;
history_length = 10000;
dmenu = "${pkgs.rofi}/bin/rofi -dmenu";
browser = "xdg-open";
always_run_script = true;
title = "Dunst";
class = "Dunst";
corner_radius = 0;
dmenu = "${pkgs.rofi}/bin/rofi -dmenu";
browser = "xdg-open";
always_run_script = true;
title = "Dunst";
class = "Dunst";
corner_radius = 0;
mouse_left_click = "close_current";
mouse_middle_click = "do_action, close_current";
mouse_right_click = "close_all";
mouse_left_click = "close_current";
mouse_middle_click = "do_action, close_current";
mouse_right_click = "close_all";
};
urgency_low = {
background = "#191311${transparency}";
foreground = "#3B7C87${transparency}";
frame_color = "#3B7C87${transparency}";
timeout = 10;
};
urgency_normal = {
background = "#191311${transparency}";
foreground = "#5B8234${transparency}";
frame_color = "#5B8234${transparency}";
timeout = 10;
};
urgency_critical = {
background = "#191311${transparency}";
foreground = "#B7472A${transparency}";
frame_color = "#B7472A${transparency}";
timeout = 0;
};
};
urgency_low = {
background = "#191311${transparency}";
foreground = "#3B7C87${transparency}";
frame_color = "#3B7C87${transparency}";
timeout = 10;
};
urgency_normal = {
background = "#191311${transparency}";
foreground = "#5B8234${transparency}";
frame_color = "#5B8234${transparency}";
timeout = 10;
};
urgency_critical = {
background = "#191311${transparency}";
foreground = "#B7472A${transparency}";
frame_color = "#B7472A${transparency}";
timeout = 0;
};
};
};
}

View file

@ -1,7 +1,8 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
i18n.inputMethod = {
enabled = "fcitx5";
fcitx5.addons = with pkgs; [fcitx5-mozc fcitx5-gtk];
fcitx5.addons = builtins.attrValues { inherit (pkgs) fcitx5-mozc fcitx5-gtk; };
};
home.sessionVariables = {
XMODIFIERS = "@im=fcitx";

View file

@ -1,4 +1,4 @@
{...}: {
{
programs.fzf = {
enable = true;
};

View file

@ -1,4 +1,4 @@
{...}: {
{
services.gammastep = {
enable = true;
provider = "geoclue2";

View file

@ -1,4 +1,5 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
programs.git = {
enable = true;
package = pkgs.gitFull;
@ -27,11 +28,17 @@
rerere.enabled = true;
diff.algorithm = "histogram";
diff.submodule = "log";
diff.sopsdiffer.textconv = let
conf = builtins.toFile "sops.yaml" (builtins.toJSON {
creation_rules = [{key_groups = [{pgp = ["61303BBAD7D1BF74EFA44E3BE7FE2087E4380E64"];}];}];
});
in "${pkgs.sops}/bin/sops --config ${conf} -d";
diff.sopsdiffer.textconv =
let
conf = builtins.toFile "sops.yaml" (
builtins.toJSON {
creation_rules = [
{ key_groups = [ { pgp = [ "61303BBAD7D1BF74EFA44E3BE7FE2087E4380E64" ]; } ]; }
];
}
);
in
"${pkgs.sops}/bin/sops --config ${conf} -d";
sendemail = {
smtpserver = "mail.defelo.de";
smtpuser = "mail@defelo.de";
@ -39,13 +46,15 @@
smtpserverport = 465;
annotate = true;
};
credential."smtp://mail.defelo.de:465".helper = let
helper = pkgs.writeShellScript "git-credential-helper" ''
[[ "$1" = get ]] || exit 1
pw=$(pass email/mail@defelo.de)
echo "password=$pw"
'';
in ''!${helper} "$@"'';
credential."smtp://mail.defelo.de:465".helper =
let
helper = pkgs.writeShellScript "git-credential-helper" ''
[[ "$1" = get ]] || exit 1
pw=$(pass email/mail@defelo.de)
echo "password=$pw"
'';
in
''!${helper} "$@"'';
};
};
}

View file

@ -1,4 +1,5 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
programs.gpg = {
enable = true;
settings.trust-model = "tofu+pgp";
@ -14,7 +15,7 @@
enable = true;
pinentryPackage = pkgs.pinentry-gnome3;
enableSshSupport = true;
sshKeys = ["D2277B1C3C924964972148EF590B9F083697F9A8"];
sshKeys = [ "D2277B1C3C924964972148EF590B9F083697F9A8" ];
enableExtraSocket = true;
};
}

View file

@ -1,8 +1,5 @@
{ pkgs, helix, ... }:
{
pkgs,
helix,
...
}: {
programs.helix = {
enable = true;
package = helix.packages.${pkgs.system}.default;
@ -17,10 +14,19 @@
normal = "block";
select = "underline";
};
file-picker = {hidden = false;};
file-picker = {
hidden = false;
};
statusline = {
left = ["mode" "spinner"];
center = ["file-name" "read-only-indicator" "file-modification-indicator"];
left = [
"mode"
"spinner"
];
center = [
"file-name"
"read-only-indicator"
"file-modification-indicator"
];
right = [
"version-control"
"diagnostics"
@ -38,7 +44,9 @@
display-messages = true;
display-inlay-hints = true;
};
indent-guides = {render = true;};
indent-guides = {
render = true;
};
idle-timeout = 0;
bufferline = "always";
soft-wrap = {

View file

@ -1,5 +1,6 @@
{pkgs, ...}: {
imports = [./.];
{ lib, pkgs, ... }:
{
imports = [ ./. ];
programs.helix.languages = {
language-server = {
@ -7,43 +8,49 @@
config = {
checkOnSave.command = "clippy";
cargo.features = "all";
cargo.unsetTest = [];
cargo.unsetTest = [ ];
};
};
pyright = {
command = "${pkgs.pyright}/bin/pyright-langserver";
args = ["--stdio"];
config = {};
args = [ "--stdio" ];
config = { };
};
nil.command = "${pkgs.nil}/bin/nil";
bash-language-server = {
command = "${pkgs.bash-language-server}/bin/bash-language-server";
args = ["start"];
args = [ "start" ];
};
uiua = {
command = "${pkgs.uiua}/bin/uiua";
args = ["lsp"];
args = [ "lsp" ];
};
haskell = {
command = "${pkgs.haskell-language-server}/bin/haskell-language-server-wrapper";
args = ["lsp"];
args = [ "lsp" ];
};
};
language = [
{
name = "python";
auto-format = true;
language-servers = [{name = "pyright";}];
language-servers = [ { name = "pyright"; } ];
formatter = {
command = "/bin/sh";
args = ["-c" "${pkgs.isort}/bin/isort - | ${pkgs.black}/bin/black -q -l 120 -C -"];
args = [
"-c"
"${pkgs.isort}/bin/isort - | ${pkgs.black}/bin/black -q -l 120 -C -"
];
};
}
{
name = "nix";
auto-format = true;
language-servers = [{name = "nil";}];
formatter.command = "${pkgs.alejandra}/bin/alejandra";
language-servers = [ { name = "nil"; } ];
formatter = {
command = lib.getExe pkgs.nixfmt-rfc-style;
args = [ "-s" ];
};
}
# {
# name = "latex";
@ -58,24 +65,24 @@
name = "uiua";
scope = "source.uiua";
injection-regex = "uiua";
file-types = ["ua"];
roots = [];
file-types = [ "ua" ];
roots = [ ];
auto-format = true;
comment-token = "#";
language-servers = [{name = "uiua";}];
language-servers = [ { name = "uiua"; } ];
indent = {
tab-width = 2;
unit = " ";
};
shebangs = ["uiua"];
shebangs = [ "uiua" ];
}
{
name = "haskell";
auto-format = true;
language-servers = [{name = "haskell";}];
language-servers = [ { name = "haskell"; } ];
formatter = {
command = "${pkgs.ormolu}/bin/ormolu";
args = ["--no-cabal"];
args = [ "--no-cabal" ];
};
}
];

View file

@ -1,11 +1,7 @@
{pkgs, ...}: {
home.packages = with pkgs;
[
libreoffice
hunspell
]
++ (with pkgs.hunspellDicts; [
en_US
de_DE
]);
{ pkgs, ... }:
{
home.packages = builtins.attrValues {
inherit (pkgs) libreoffice hunspell;
inherit (pkgs.hunspellDicts) en_US de_DE;
};
}

View file

@ -3,7 +3,8 @@
lib,
pkgs,
...
}: let
}:
let
lock-command = map (x: ''"${x}"'') [
(lib.getExe pkgs.swaylock-effects)
"--screenshots"
@ -14,12 +15,25 @@
"--fade-in=0.5"
];
rofipass-command = pkgs.writeShellScript "rofipass-wrapped.sh" ''
export PASSWORD_STORE_DIR=${lib.escapeShellArg config.programs.password-store.settings.PASSWORD_STORE_DIR}
export PATH=${lib.escapeShellArg (lib.makeBinPath (with pkgs; [pass wl-clipboard rofi-wayland dunst clipman]))}:$PATH
exec -a rofipass.sh ${../scripts/rofipass.sh} "$@"
'';
in {
rofipass-command =
let
runtimeDependencies = lib.attrValues {
inherit (pkgs)
pass
wl-clipboard
rofi-wayland
dunst
clipman
;
};
in
pkgs.writeShellScript "rofipass-wrapped.sh" ''
export PASSWORD_STORE_DIR=${lib.escapeShellArg config.programs.password-store.settings.PASSWORD_STORE_DIR}
export PATH=${lib.makeBinPath runtimeDependencies}:$PATH
exec -a rofipass.sh ${../scripts/rofipass.sh} "$@"
'';
in
{
home.file.".config/niri/config.kdl".source = pkgs.replaceVars ./config.kdl {
inherit lock-command rofipass-command;
DEFAULT_AUDIO_SINK = null;
@ -28,8 +42,8 @@ in {
systemd.user.services.swaybg = {
Unit = {
PartOf = ["graphical-session.target"];
After = ["graphical-session.target"];
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
@ -37,7 +51,7 @@ in {
Restart = "on-failure";
};
Install.WantedBy = ["graphical-session.target"];
Install.WantedBy = [ "graphical-session.target" ];
};
xdg.autostart.enable = false;

View file

@ -1,7 +1,6 @@
{nix-index-database, ...}: {
imports = [
nix-index-database.hmModules.nix-index
];
{ nix-index-database, ... }:
{
imports = [ nix-index-database.hmModules.nix-index ];
programs.nix-index = {
enable = true;
enableZshIntegration = false;

View file

@ -3,17 +3,33 @@
config,
pkgs,
...
}: {
}:
{
systemd.user.services.ntfy-sub = {
Install.WantedBy = ["default.target"];
Unit.After = ["sops-nix.service" "dunst.service"];
Install.WantedBy = [ "default.target" ];
Unit.After = [
"sops-nix.service"
"dunst.service"
];
Service = {
ExecStart = "${pkgs.bash}/bin/bash ${./scripts/ntfy-sub.sh} ${config.sops.secrets.ntfy.path}";
Environment = "PATH=${pkgs.lib.makeBinPath (with pkgs; [coreutils jq dunst xdg-utils ntfy-sh])}";
Environment =
let
runtimeDependencies = builtins.attrValues {
inherit (pkgs)
coreutils
jq
dunst
xdg-utils
ntfy-sh
;
};
in
"PATH=${pkgs.lib.makeBinPath runtimeDependencies}";
};
};
home.packages = [pkgs.ntfy-sh];
home.packages = [ pkgs.ntfy-sh ];
programs.zsh.shellAliases.ny = "ntfy pub defelo";
sops.secrets.ntfy = {

View file

@ -1,63 +1,69 @@
{pkgs, ...}: {
home.packages = with pkgs; [
# programming
gcc
gnumake
git-crypt
just
{ pkgs, ... }:
{
home.packages = builtins.attrValues {
inherit (pkgs)
# programming
gcc
gnumake
git-crypt
just
# browsers
brave
tor-browser-bundle-bin
# browsers
brave
tor-browser-bundle-bin
# communication
discord-canary
element-desktop
signal-desktop
# communication
discord-canary
element-desktop
signal-desktop
# games
prismlauncher
mindustry-wayland
# games
prismlauncher
mindustry-wayland
# system
pulsemixer
pavucontrol
playerctl
nix-output-monitor
wl-clipboard
xdg-utils
virt-manager
wdisplays
slurp
grim
swappy
wl-mirror
(networkmanagerapplet.overrideAttrs (attrs: {
# system
pulsemixer
pavucontrol
playerctl
nix-output-monitor
wl-clipboard
xdg-utils
virt-manager
wdisplays
slurp
grim
swappy
wl-mirror
# utils
feh
eog
speedtest-cli
pwgen
xkcdpass
gh
imagemagick
termshot
bc
inotify-tools
obsidian
vlc
okular
anki-bin
spotify
rnote
zotero_7
;
tex = pkgs.texlive.combined.scheme-full;
networkmanagerapplet = pkgs.networkmanagerapplet.overrideAttrs (attrs: {
postFixup = ''
${attrs.postFixup or ""}
rm -r $out/etc/xdg/autostart
'';
}))
# utils
feh
eog
speedtest-cli
pwgen
xkcdpass
gh
imagemagick
termshot
bc
inotify-tools
obsidian
vlc
texlive.combined.scheme-full
okular
anki-bin
spotify
rnote
zotero_7
];
});
};
}

View file

@ -1,4 +1,5 @@
{conf, ...}: {
{ conf, ... }:
{
programs.password-store = {
enable = true;
settings = {

View file

@ -20,7 +20,7 @@
"Persistent"
"Zotero"
];
files = [];
files = [ ];
};
cache = {
@ -42,6 +42,6 @@
".thunderbird"
"Downloads"
];
files = [];
files = [ ];
};
}

View file

@ -1,4 +1,4 @@
{...}: {
{
services.playerctld = {
enable = true;
};

View file

@ -1,4 +1,5 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
imports = [
./nix.nix
./python.nix
@ -6,11 +7,8 @@
./uiua.nix
];
home.packages = with pkgs; [
nodejs
nodePackages."@angular/cli"
nodePackages.live-server
lean4
];
home.packages = builtins.attrValues {
inherit (pkgs) nodejs lean4;
inherit (pkgs.nodePackages) "@angular/cli" live-server;
};
}

View file

@ -1,7 +1,10 @@
{pkgs, ...}: {
home.packages = with pkgs; [
# rnix-lsp
alejandra
nixfmt-rfc-style
];
{ pkgs, ... }:
{
home.packages = builtins.attrValues {
inherit (pkgs)
# rnix-lsp
alejandra
nixfmt-rfc-style
;
};
}

View file

@ -1,13 +1,13 @@
{pkgs, ...}: {
home.packages = with pkgs; [
(python311.withPackages (p:
with p; [
numpy
requests
]))
poetry
poethepoet
pyright
ruff
];
{ pkgs, ... }:
{
home.packages = builtins.attrValues {
python = pkgs.python311.withPackages (p: builtins.attrValues { inherit (p) numpy requests; });
inherit (pkgs)
poetry
poethepoet
pyright
ruff
;
};
}

View file

@ -3,21 +3,27 @@
pkgs,
fenix,
...
}: {
home.packages = with pkgs; [
(
with fenix.packages.${pkgs.system};
combine [
complete.toolchain
targets.x86_64-unknown-linux-musl.latest.rust-std
targets.wasm32-unknown-unknown.latest.rust-std
]
)
bacon
cargo-audit
cargo-expand
cargo-hack
];
}:
{
home.packages = builtins.attrValues {
rust =
let
inherit (fenix.packages.${pkgs.system}) combine complete targets;
in
combine [
complete.toolchain
targets.x86_64-unknown-linux-musl.latest.rust-std
targets.wasm32-unknown-unknown.latest.rust-std
];
inherit (pkgs)
bacon
cargo-audit
cargo-expand
cargo-hack
;
};
home.file.cargo = {
text = ''
[target.x86_64-unknown-linux-gnu]

View file

@ -1,5 +1,4 @@
{pkgs, ...}: {
home.packages = with pkgs; [
uiua
];
{ pkgs, ... }:
{
home.packages = [ pkgs.uiua ];
}

View file

@ -1,4 +1,5 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
programs.rofi = {
enable = true;
package = pkgs.rofi-wayland;

View file

@ -3,23 +3,23 @@
set -e
download_from_rss() {
d=$(curl -s "$1" | xq -r ".rss.channel.item[${3:-0}]")
jq -r .title <<< "$d"
url=$(jq -r '.enclosure."@url"' <<< "$d")
echo "$url"
pub=$(jq -r '.pubDate' <<< "$d")
name=$(date -d "$pub" +"$2_%Y_%m_%d.mp4")
wget --continue -O "$name" "$url"
d=$(curl -s "$1" | xq -r ".rss.channel.item[${3:-0}]")
jq -r .title <<<"$d"
url=$(jq -r '.enclosure."@url"' <<<"$d")
echo "$url"
pub=$(jq -r '.pubDate' <<<"$d")
name=$(date -d "$pub" +"$2_%Y_%m_%d.mp4")
wget --continue -O "$name" "$url"
}
future=$3
declare -A urls=(
["x3"]="https://mediathekviewweb.de/feed?query=extra%203%20vom&future=$future"
["hs"]="https://mediathekviewweb.de/feed?query=heute-show%20!ZDF&future=$future"
["zmr"]="https://mediathekviewweb.de/feed?query=zdf%20magazin%20royale%20!ZDF&future=$future"
["m"]="https://mediathekviewweb.de/feed?query=!zdf%20wir%20sind%20die%20meiers&future=$future"
["zcs"]="https://mediathekviewweb.de/feed?query=!zdf%20zdf%20comedy%20sommer&future=$future"
["anstalt"]="https://mediathekviewweb.de/feed?query=!zdf%20die%20anstalt&future=$future"
["x3"]="https://mediathekviewweb.de/feed?query=extra%203%20vom&future=$future"
["hs"]="https://mediathekviewweb.de/feed?query=heute-show%20!ZDF&future=$future"
["zmr"]="https://mediathekviewweb.de/feed?query=zdf%20magazin%20royale%20!ZDF&future=$future"
["m"]="https://mediathekviewweb.de/feed?query=!zdf%20wir%20sind%20die%20meiers&future=$future"
["zcs"]="https://mediathekviewweb.de/feed?query=!zdf%20zdf%20comedy%20sommer&future=$future"
["anstalt"]="https://mediathekviewweb.de/feed?query=!zdf%20die%20anstalt&future=$future"
)
download_from_rss "${urls[$1]}" "$1" ${2:-0}

View file

@ -1,45 +1,42 @@
#!/bin/zsh
usage() {
echo "usage: mnt <device> <mnt>"
echo "usage: mnt <device> <mnt>"
}
if ! (return 0 2>/dev/null)
then
usage
exit 1
if ! (return 0 2>/dev/null); then
usage
exit 1
fi
if [[ $# -ne 2 ]]
then
usage
return 1
if [[ $# -ne 2 ]]; then
usage
return 1
fi
uid=$(id -u)
gid=$(id -g)
if ! lsblk $1 &> /dev/null
then
echo "'$1' is not a block device"
return 3
if ! lsblk $1 &>/dev/null; then
echo "'$1' is not a block device"
return 3
fi
fs=$(lsblk -f $1 | tail -1 | awk '{print $2}')
case $fs in
ext4 )
sudo mount -m $1 $2
;;
ext4)
sudo mount -m $1 $2
;;
vfat | exfat )
sudo mount -m -o uid=$uid,gid=$gid $1 $2
;;
vfat | exfat)
sudo mount -m -o uid=$uid,gid=$gid $1 $2
;;
* )
echo "filesystem '$fs' is not supported"
return 2
;;
*)
echo "filesystem '$fs' is not supported"
return 2
;;
esac
sudo chown $uid:$gid $2

View file

@ -1,36 +1,36 @@
#!/usr/bin/env bash
handle() {
line="$1"
message=$(jq -r .message <<< "$line")
if ! title=$(jq -e -r .title <<< "$line"); then
title="$message"
message=""
fi
prio=$(jq -e -r .priority <<< "$line") || prio=3
if [[ $prio -lt 3 ]]; then
prio=0
elif [[ $prio -eq 3 ]]; then
prio=1
else
prio=2
fi
line="$1"
message=$(jq -r .message <<<"$line")
if ! title=$(jq -e -r .title <<<"$line"); then
title="$message"
message=""
fi
prio=$(jq -e -r .priority <<<"$line") || prio=3
if [[ $prio -lt 3 ]]; then
prio=0
elif [[ $prio -eq 3 ]]; then
prio=1
else
prio=2
fi
actions=()
while read act; do
id=$(jq -r .id <<< "$act")
action=$(jq -r .action <<< "$act")
[[ "$action" = "view" ]] || continue
label=$(jq -r .label <<< "$act")
actions+=("-A" "$id,$label")
done < <(jq -c '.actions//[]|.[]' <<< "$line")
actions=()
while read act; do
id=$(jq -r .id <<<"$act")
action=$(jq -r .action <<<"$act")
[[ $action == "view" ]] || continue
label=$(jq -r .label <<<"$act")
actions+=("-A" "$id,$label")
done < <(jq -c '.actions//[]|.[]' <<<"$line")
id=$(dunstify "${actions[@]}" -u $prio "$title" "$message")
if url=$(jq -e --arg id "$id" -r '.actions//[]|.[]|select(.id==$id)|.url' <<< "$line"); then
xdg-open "$url"
fi
id=$(dunstify "${actions[@]}" -u $prio "$title" "$message")
if url=$(jq -e --arg id "$id" -r '.actions//[]|.[]|select(.id==$id)|.url' <<<"$line"); then
xdg-open "$url"
fi
}
while read -r line; do
handle "$line" &
handle "$line" &
done < <(ntfy sub -C -c "$1")

View file

@ -3,17 +3,20 @@
shopt -s globstar
cd $PASSWORD_STORE_DIR
if x=$((for f in $(find * -type f -name '*.gpg'); do echo "${f%.gpg}"; done) | rofi -dmenu -i -no-custom -matching fuzzy); then
password=$(pass show "$x" | head -1)
if x=$( (for f in $(find * -type f -name '*.gpg'); do echo "${f%.gpg}"; done) | rofi -dmenu -i -no-custom -matching fuzzy); then
password=$(pass show "$x" | head -1)
# prevent clipman from storing the password
[[ -f ~/.local/share/clipman.json ]] || echo -n '[]' > ~/.local/share/clipman.json
chmod u-w ~/.local/share/clipman.json
wl-copy -n <<< "$password"
(sleep 1; chmod u+w ~/.local/share/clipman.json)
# prevent clipman from storing the password
[[ -f ~/.local/share/clipman.json ]] || echo -n '[]' >~/.local/share/clipman.json
chmod u-w ~/.local/share/clipman.json
wl-copy -n <<<"$password"
(
sleep 1
chmod u+w ~/.local/share/clipman.json
)
dunstify -t 5000 'Password copied to clipboard'
sleep 5
wl-copy -c
clipman pick -t CUSTOM -T "head -1" # restore last clipboard entry
dunstify -t 5000 'Password copied to clipboard'
sleep 5
wl-copy -c
clipman pick -t CUSTOM -T "head -1" # restore last clipboard entry
fi

View file

@ -4,192 +4,195 @@ export GIT_DIR=$HOME/.timetracker/.git
export GIT_WORK_TREE=$HOME/.timetracker
_usage() {
echo "Usage: tt <name> [start|stop|list|show|edit|config|delete|save] [<args>]"
echo " tt list"
echo " tt git [<args>]"
exit 1
echo "Usage: tt <name> [start|stop|list|show|edit|config|delete|save] [<args>]"
echo " tt list"
echo " tt git [<args>]"
exit 1
}
if [[ "$1" = git ]]; then
shift
exec git "$@"
elif [[ "$1" = list ]]; then
[[ $# = 1 ]] || _usage
for file in $(cd $GIT_WORK_TREE; ls); do
echo $file
done
exit
elif [[ $# -lt 1 ]] || ! [[ "$2" =~ ^(|start|stop|list|show|edit|config|delete|save)$ ]]; then
_usage
if [[ $1 == git ]]; then
shift
exec git "$@"
elif [[ $1 == list ]]; then
[[ $# == 1 ]] || _usage
for file in $(
cd $GIT_WORK_TREE
ls
); do
echo $file
done
exit
elif [[ $# -lt 1 ]] || ! [[ $2 =~ ^(|start|stop|list|show|edit|config|delete|save)$ ]]; then
_usage
fi
if ! git status &> /dev/null; then
git init
if ! git status &>/dev/null; then
git init
fi
NAME="$1"
FILE="$HOME/.timetracker/$1"
CONF="$HOME/.timetracker/.$1.yml"
if [[ "$2" != delete ]]; then
mkdir -p $(dirname "$FILE")
[[ -e "$FILE" ]] || touch "$FILE"
[[ -e "$CONF" ]] || cat << EOF > "$CONF"
if [[ $2 != delete ]]; then
mkdir -p $(dirname "$FILE")
[[ -e $FILE ]] || touch "$FILE"
[[ -e $CONF ]] || cat <<EOF >"$CONF"
regular: 0 # per week
start: 0
bonus: [] # hours
salary: 0 # €/month
EOF
PER_WEEK=$(yq -r .regular "$CONF")
START=$(yq -r .start "$CONF")
BONUS=$(yq -r '.bonus+[0]|add*60*60|round' "$CONF")
SALARY=$(yq -r .salary "$CONF")
PER_WEEK=$(yq -r .regular "$CONF")
START=$(yq -r .start "$CONF")
BONUS=$(yq -r '.bonus+[0]|add*60*60|round' "$CONF")
SALARY=$(yq -r .salary "$CONF")
fi
_fmt_ts() {
date -d @$1 +"%a %d %b %Y %T"
date -d @$1 +"%a %d %b %Y %T"
}
_fmt_delta() {
x=$1
echo $((x/3600))h $((x/60%60))m $((x%60))s
x=$1
echo $((x / 3600))h $((x / 60 % 60))m $((x % 60))s
}
_week() {
date -d @$1 +"%G-%V"
date -d @$1 +"%G-%V"
}
_now() {
date +"%s"
date +"%s"
}
_running() {
grep -E '^([0-9]+)$' "$FILE"
grep -E '^([0-9]+)$' "$FILE"
}
_overtime() {
[[ $PER_WEEK -gt 0 ]] || return
[[ $PER_WEEK -gt 0 ]] || return
t=$(($(_now)-$START))
regular=$(jq -n "$PER_WEEK*$t/(24*7)|round-($BONUS)")
until=$(jq -n "$START+($1+($BONUS))/$PER_WEEK*24*7|round")
money=$(jq -n "$SALARY*($1-$regular)/3600/$PER_WEEK/52*12*100|round/100")
echo "Overtime: $(_fmt_delta $(($1-$regular))) (until $(_fmt_ts $until); ${money}€)"
t=$(($(_now) - START))
regular=$(jq -n "$PER_WEEK*$t/(24*7)|round-($BONUS)")
until=$(jq -n "$START+($1+($BONUS))/$PER_WEEK*24*7|round")
money=$(jq -n "$SALARY*($1-$regular)/3600/$PER_WEEK/52*12*100|round/100")
echo "Overtime: $(_fmt_delta $(($1 - regular))) (until $(_fmt_ts $until); ${money}€)"
}
start() {
if x=$(_running); then
echo "Already running (started at $(_fmt_ts $x))"
return 1
fi
now=$(_now | tee -a "$FILE")
echo "Started at $(_fmt_ts $now)"
if x=$(_running); then
echo "Already running (started at $(_fmt_ts $x))"
return 1
fi
now=$(_now | tee -a "$FILE")
echo "Started at $(_fmt_ts $now)"
}
stop() {
if ! x=$(_running); then
echo "Not running"
return 1
fi
now=$(_now)
sed -i -E "s/^([0-9]+)$/\1 $now/" "$FILE"
echo "Stopped at $(_fmt_ts $now) ($(_fmt_delta $((now-x))))"
save
if ! x=$(_running); then
echo "Not running"
return 1
fi
now=$(_now)
sed -i -E "s/^([0-9]+)$/\1 $now/" "$FILE"
echo "Stopped at $(_fmt_ts $now) ($(_fmt_delta $((now - x))))"
save
}
list() {
cnt=${1:-all}
last=""
w=0
s=0
r=""
lines=$(wc -l < "$FILE")
l=${#lines}
i=1
while read begin end; do
[[ "$cnt" = all ]] || [[ $i -gt $(($lines - $cnt)) ]]
out=$?
ln=$(printf "%0${l}d" $i)
i=$((i+1))
if [[ -z "$end" ]]; then
end=$(_now)
end_fmt="NOW"
r="(running)"
else
end_fmt=$(_fmt_ts $end)
fi
week=$(_week $begin)
if [[ "$last" != "$week" ]]; then
[[ $out = 0 ]] && [[ -n "$last" ]] && echo "=> $(_fmt_delta $w)"
[[ $out = 0 ]] && echo -e "\n$week"
w=0
fi
last="$week"
[[ $out = 0 ]] && echo "#$ln $(_fmt_ts $begin) - $end_fmt ($(_fmt_delta $((end-begin))))"
w=$((w+end-begin))
s=$((s+end-begin))
done < "$FILE"
[[ -n "$last" ]] && echo "=> $(_fmt_delta $w)"
echo -e "\nTOTAL: $(_fmt_delta $s) $r"
_overtime $s
cnt=${1:-all}
last=""
w=0
s=0
r=""
lines=$(wc -l <"$FILE")
l=${#lines}
i=1
while read begin end; do
[[ $cnt == all ]] || [[ $i -gt $((lines - cnt)) ]]
out=$?
ln=$(printf "%0${l}d" $i)
i=$((i + 1))
if [[ -z $end ]]; then
end=$(_now)
end_fmt="NOW"
r="(running)"
else
end_fmt=$(_fmt_ts $end)
fi
week=$(_week $begin)
if [[ $last != "$week" ]]; then
[[ $out == 0 ]] && [[ -n $last ]] && echo "=> $(_fmt_delta $w)"
[[ $out == 0 ]] && echo -e "\n$week"
w=0
fi
last="$week"
[[ $out == 0 ]] && echo "#$ln $(_fmt_ts $begin) - $end_fmt ($(_fmt_delta $((end - begin))))"
w=$((w + end - begin))
s=$((s + end - begin))
done <"$FILE"
[[ -n $last ]] && echo "=> $(_fmt_delta $w)"
echo -e "\nTOTAL: $(_fmt_delta $s) $r"
_overtime $s
}
show() {
sum=0
r=""
while read begin end; do
if [[ -z "$end" ]]; then
end=$(_now)
r="(running)"
fi
sum=$((sum+end-begin))
done < "$FILE"
echo "TOTAL: $(_fmt_delta $sum) $r"
_overtime $sum
sum=0
r=""
while read begin end; do
if [[ -z $end ]]; then
end=$(_now)
r="(running)"
fi
sum=$((sum + end - begin))
done <"$FILE"
echo "TOTAL: $(_fmt_delta $sum) $r"
_overtime $sum
}
interactive() {
_running>/dev/null || start
x=$(_running)
f=1
trap f=0 SIGINT
first=1
while [[ $f = 1 ]]; do
printf "${new}Current: $(_fmt_delta $(($(_now)-x)))\n$(show) (Ctrl+C to stop) "
sleep 1
if [[ $first = 1 ]]; then
new=$(tput dl1 cuu1 dl1 cuu1 dl1 hpa 0)
first=0
fi
done
trap - SIGINT
printf "$new"
stop
_running >/dev/null || start
x=$(_running)
f=1
trap f=0 SIGINT
first=1
while [[ $f == 1 ]]; do
printf "${new}Current: $(_fmt_delta $(($(_now) - x)))\n$(show) (Ctrl+C to stop) "
sleep 1
if [[ $first == 1 ]]; then
new=$(tput dl1 cuu1 dl1 cuu1 dl1 hpa 0)
first=0
fi
done
trap - SIGINT
printf "$new"
stop
}
edit() {
${EDITOR:-vi} "$FILE"
save
${EDITOR:-vi} "$FILE"
save
}
config() {
${EDITOR:-vi} "$CONF"
save
${EDITOR:-vi} "$CONF"
save
}
delete() {
for file in "$FILE" "$CONF"; do
[[ -e "$file" ]] && rm -i "$file" || echo "$file does not exist"
done
save
for file in "$FILE" "$CONF"; do
[[ -e $file ]] && rm -i "$file" || echo "$file does not exist"
done
save
}
save() {
git add "$FILE" "$CONF"
if ! git diff --staged --exit-code --quiet; then
git commit -m "Update $NAME"
git push
fi
git add "$FILE" "$CONF"
if ! git diff --staged --exit-code --quiet; then
git commit -m "Update $NAME"
git push
fi
}
cmd=${2:-interactive}

View file

@ -3,10 +3,12 @@
sops-nix,
system-config,
...
}: let
}:
let
inherit (system-config.users.users.${conf.user}) uid;
in {
imports = [sops-nix.homeManagerModules.sops];
in
{
imports = [ sops-nix.homeManagerModules.sops ];
sops = {
age.keyFile = "/persistent/data/home/${conf.user}/.config/sops/age/keys.txt";
defaultSymlinkPath = "/run/user/${toString uid}/secrets";

View file

@ -1,4 +1,5 @@
{config, ...}: {
{ config, ... }:
{
programs.ssh = {
enable = true;
serverAliveInterval = 20;
@ -8,7 +9,7 @@
extraConfig = ''
TCPKeepAlive no
'';
includes = [config.sops.secrets."ssh/hosts".path];
includes = [ config.sops.secrets."ssh/hosts".path ];
};
sops.secrets = {

View file

@ -1,4 +1,4 @@
{...}: {
{
services.syncthing = {
enable = true;
};

View file

@ -1,8 +1,5 @@
{ pkgs, conf, ... }:
{
pkgs,
conf,
...
}: {
gtk = {
enable = true;
theme.name = "Adapta-Nokto";

View file

@ -47,7 +47,9 @@ for acc in config["email"]["accounts"]:
smtp.setdefault("port", 587)
if imap := acc.get("imap"):
out[f"mail.server.server_{id}.directory"] = f".thunderbird/default/ImapMail/{id}"
out[f"mail.server.server_{id}.directory"] = (
f".thunderbird/default/ImapMail/{id}"
)
out[f"mail.server.server_{id}.directory-rel"] = f"[ProfD]ImapMail/{id}"
out[f"mail.server.server_{id}.hostname"] = imap["host"]
out[f"mail.server.server_{id}.login_at_startup"] = True
@ -77,11 +79,19 @@ out["mail.smtpservers"] = ",".join(servers)
calendars = []
for cal in config["calendars"]:
id = hashlib.sha256("\n".join([cal["uri"], cal.get("username", ""), cal["name"]]).encode()).hexdigest()
id = hashlib.sha256(
"\n".join([cal["uri"], cal.get("username", ""), cal["name"]]).encode()
).hexdigest()
calendars.append(id)
for k, v in (
{"type": "caldav", "readOnly": False, "cache.enabled": True, "calendar-main-in-composite": True} | cal
{
"type": "caldav",
"readOnly": False,
"cache.enabled": True,
"calendar-main-in-composite": True,
}
| cal
).items():
out[f"calendar.registry.{id}.{k}"] = v

View file

@ -1,9 +1,6 @@
{ config, pkgs, ... }:
{
config,
pkgs,
...
}: {
home.packages = with pkgs; [thunderbird gpgme];
home.packages = builtins.attrValues { inherit (pkgs) thunderbird gpgme; };
sops.secrets = {
"thunderbird" = {
@ -13,15 +10,19 @@
};
systemd.user.services.thunderbird-config = {
Install.WantedBy = ["default.target"];
Unit.After = ["sops-nix.service"];
Install.WantedBy = [ "default.target" ];
Unit.After = [ "sops-nix.service" ];
Service = {
ExecStart = toString (pkgs.writeShellScript "thunderbird-config.sh" ''
${pkgs.coreutils}/bin/mkdir -p ~/.thunderbird/default
${pkgs.coreutils}/bin/rm -f ~/.thunderbird/default/user.js
${pkgs.python311}/bin/python ${./activate.py} ${config.sops.secrets."thunderbird".path} > ~/.thunderbird/default/user.js
${pkgs.coreutils}/bin/chmod 400 ~/.thunderbird/default/user.js
'');
ExecStart = toString (
pkgs.writeShellScript "thunderbird-config.sh" ''
${pkgs.coreutils}/bin/mkdir -p ~/.thunderbird/default
${pkgs.coreutils}/bin/rm -f ~/.thunderbird/default/user.js
${pkgs.python311}/bin/python ${./activate.py} ${
config.sops.secrets."thunderbird".path
} > ~/.thunderbird/default/user.js
${pkgs.coreutils}/bin/chmod 400 ~/.thunderbird/default/user.js
''
);
Type = "oneshot";
};
};

View file

@ -1,4 +1,5 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
programs.tmux = {
enable = true;
aggressiveResize = true;
@ -11,10 +12,7 @@
resizeAmount = 5;
secureSocket = false;
terminal = "tmux-256color";
plugins = with pkgs.tmuxPlugins; [
tmux-fzf
onedark-theme
];
plugins = builtins.attrValues { inherit (pkgs.tmuxPlugins) tmux-fzf onedark-theme; };
extraConfig = ''
set -ag terminal-overrides ",xterm-256color:RGB"

View file

@ -1,10 +1,8 @@
{
pkgs,
nix-vscode-extensions,
...
}: let
{ pkgs, nix-vscode-extensions, ... }:
let
extensions = nix-vscode-extensions.extensions.${pkgs.system};
in {
in
{
programs.vscode = {
enable = true;
package = pkgs.vscodium;
@ -43,9 +41,9 @@ in {
"editor.wordWrap" = "on";
"workbench.startupEditor" = "newUntitledFile";
"files.autoSave" = "afterDelay";
"python.autoComplete.extraPaths" = [];
"python.autoComplete.extraPaths" = [ ];
"editor.lineNumbers" = "on";
"vim.commandLineModeKeyBindings" = [];
"vim.commandLineModeKeyBindings" = [ ];
"rust-analyzer.checkOnSave.command" = "clippy";
"files.associations" = {
"*.toml" = "toml";

View file

@ -3,198 +3,249 @@
pkgs,
lib,
...
}: {
}:
{
programs.waybar = {
enable = true;
systemd.enable = true;
settings = let
mkDisk = name: path: {
inherit path;
interval = 5;
format = "${name} {percentage_used}%";
states = {
critical = 90;
warning = 80;
};
};
base = {
layer = "top";
position = "top";
height = 20;
fixed-center = false;
"custom/yk" = let
script = builtins.toFile "yktd.py" ''
import json, socket, os
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(f"/run/user/{os.getuid()}/yubikey-touch-detector.socket")
def update(touch):
print(json.dumps({
"text": "",
"tooltip": "YubiKey is waiting for a touch",
} if touch else {}), flush=True)
update(False)
while True: update(s.recv(5).decode().endswith("1"))
'';
in {
exec = "${pkgs.python311}/bin/python ${script}";
return-type = "json";
};
"custom/screenshot" = {
format = "";
on-click = pkgs.writeShellScript "screenshot.sh" ''
export PATH=${pkgs.lib.makeBinPath (with pkgs; [coreutils grim slurp wl-clipboard])}:$PATH
grim -g "$(slurp)" - | wl-copy -t image/png
'';
};
"custom/github" = {
interval = 10;
on-click = "${pkgs.xdg-utils}/bin/xdg-open https://github.com/notifications";
exec = pkgs.writeShellScript "github-notifications" ''
export PATH=${lib.makeBinPath (with pkgs; [coreutils gh])}
set -euo pipefail
cnt=$(gh api /notifications -q length)
if [[ $cnt -gt 0 ]]; then
echo " $cnt"
fi
'';
};
"custom/dunst" = {
exec = pkgs.writeShellScript "dunst-is-paused" ''
export PATH=${lib.makeBinPath (with pkgs; [coreutils dunst dbus])}
set -euo pipefail
readonly ENABLED=''
readonly DISABLED=''
dbus-monitor path='/org/freedesktop/Notifications',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged' --profile |
while read -r _; do
PAUSED="$(dunstctl is-paused)"
if [ "$PAUSED" == 'false' ]; then
CLASS="enabled"
TEXT="$ENABLED"
else
CLASS="disabled"
TEXT="$DISABLED"
COUNT="$(dunstctl count waiting)"
if [ "$COUNT" != '0' ]; then
TEXT="$DISABLED ($COUNT)"
fi
fi
printf '{"text": "%s", "class": "%s"}\n' "$TEXT" "$CLASS"
done
'';
return-type = "json";
on-click = pkgs.writeShellScript "dunst-toggle-paused.sh" ''
dunstctl set-paused toggle
'';
};
"tray" = {
spacing = 8;
};
"backlight" = {
format = "󰌵 {percent}%";
};
"battery" = {
format = "{icon} {capacity}%{time}";
format-charging = "󰂄 {capacity}%{time}";
format-icons = ["󰁺" "󰁻" "󰁼" "󰁽" "󰁾" "󰁿" "󰂀" "󰂁" "󰂂" "󰁹"];
format-plugged = "󰚥 {capacity}%";
format-time = " ({H}:{m})";
settings =
let
icons = lib.splitString " ";
mkDisk = name: path: {
inherit path;
interval = 5;
format = "${name} {percentage_used}%";
states = {
critical = 15;
warning = 30;
critical = 90;
warning = 80;
};
};
base = {
layer = "top";
position = "top";
height = 20;
fixed-center = false;
"clock" = {
interval = 1;
format = "󰃭 {:%a, %d.%m.%Y 󰥔 %H:%M:%S}";
tooltip-format = "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>";
};
"custom/yk" =
let
script = builtins.toFile "yktd.py" ''
import json, socket, os
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(f"/run/user/{os.getuid()}/yubikey-touch-detector.socket")
def update(touch):
print(json.dumps({
"text": "",
"tooltip": "YubiKey is waiting for a touch",
} if touch else {}), flush=True)
update(False)
while True: update(s.recv(5).decode().endswith("1"))
'';
in
{
exec = "${pkgs.python311}/bin/python ${script}";
return-type = "json";
};
"cpu" = {
interval = 2;
format = "󰘚 {usage}%";
tooltip = false;
};
"custom/screenshot" = {
format = "";
on-click = pkgs.writeShellScript "screenshot.sh" ''
export PATH=${
lib.makeBinPath (
lib.attrValues {
inherit (pkgs)
coreutils
grim
slurp
wl-clipboard
;
}
)
}:$PATH
grim -g "$(slurp)" - | wl-copy -t image/png
'';
};
"memory" = {
interval = 2;
format = "󰍛 {avail} GB";
};
"memory#swap" = {
interval = 2;
format = "󰍛 {swapUsed} GB";
};
"custom/github" = {
interval = 10;
on-click = "${pkgs.xdg-utils}/bin/xdg-open https://github.com/notifications";
exec = pkgs.writeShellScript "github-notifications" ''
export PATH=${lib.makeBinPath (lib.attrValues { inherit (pkgs) coreutils gh; })}
"disk" = mkDisk "/" "/";
"disk#persistent" = mkDisk "/persistent" "/persistent/data";
set -euo pipefail
"network" = {
interval = 2;
format-disconnected = "󰀦 Disconnected";
format-ethernet = " {bandwidthTotalBytes} ({ipaddr})";
format-wifi = " {essid} {signalStrength}% {bandwidthTotalBytes} ({ipaddr})";
};
cnt=$(gh api /notifications -q length)
if [[ $cnt -gt 0 ]]; then
echo " $cnt"
fi
'';
};
"pulseaudio" = {
format = "{icon} {volume}%";
format-muted = "󰖁";
format-bluetooth = "{icon} 󰂯 {volume}%";
format-bluetooth-muted = "󰖁 󰂯";
format-icons = ["󰕿" "󰖀" "󰕾"];
};
"custom/dunst" = {
exec = pkgs.writeShellScript "dunst-is-paused" ''
export PATH=${lib.makeBinPath (lib.attrValues { inherit (pkgs) coreutils dunst dbus; })}
"pulseaudio#mic" = {
format = "{format_source}";
format-muted = "{format_source}";
format-bluetooth = "{format_source}";
format-bluetooth-muted = "{format_source}";
format-source = "󰍬 {volume}%";
format-source-muted = "󰍭";
};
set -euo pipefail
"niri/language" = {
format = "{short}";
tooltip-format = "{long}";
};
readonly ENABLED=''
readonly DISABLED=''
dbus-monitor path='/org/freedesktop/Notifications',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged' --profile |
while read -r _; do
PAUSED="$(dunstctl is-paused)"
if [ "$PAUSED" == 'false' ]; then
CLASS="enabled"
TEXT="$ENABLED"
else
CLASS="disabled"
TEXT="$DISABLED"
COUNT="$(dunstctl count waiting)"
if [ "$COUNT" != '0' ]; then
TEXT="$DISABLED ($COUNT)"
fi
fi
printf '{"text": "%s", "class": "%s"}\n' "$TEXT" "$CLASS"
done
'';
return-type = "json";
on-click = pkgs.writeShellScript "dunst-toggle-paused.sh" ''
dunstctl set-paused toggle
'';
};
"niri/window" = {
separate-outputs = true;
"tray" = {
spacing = 8;
};
"backlight" = {
format = "󰌵 {percent}%";
};
"battery" = {
format = "{icon} {capacity}%{time}";
format-charging = "󰂄 {capacity}%{time}";
format-icons = icons "󰁺 󰁻 󰁼 󰁽 󰁾 󰁿 󰂀 󰂁 󰂂 󰁹";
format-plugged = "󰚥 {capacity}%";
format-time = " ({H}:{m})";
states = {
critical = 15;
warning = 30;
};
};
"clock" = {
interval = 1;
format = "󰃭 {:%a, %d.%m.%Y 󰥔 %H:%M:%S}";
tooltip-format = "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>";
};
"cpu" = {
interval = 2;
format = "󰘚 {usage}%";
tooltip = false;
};
"memory" = {
interval = 2;
format = "󰍛 {avail} GB";
};
"memory#swap" = {
interval = 2;
format = "󰍛 {swapUsed} GB";
};
"disk" = mkDisk "/" "/";
"disk#persistent" = mkDisk "/persistent" "/persistent/data";
"network" = {
interval = 2;
format-disconnected = "󰀦 Disconnected";
format-ethernet = " {bandwidthTotalBytes} ({ipaddr})";
format-wifi = " {essid} {signalStrength}% {bandwidthTotalBytes} ({ipaddr})";
};
"pulseaudio" = {
format = "{icon} {volume}%";
format-muted = "󰖁";
format-bluetooth = "{icon} 󰂯 {volume}%";
format-bluetooth-muted = "󰖁 󰂯";
format-icons = icons "󰕿 󰖀 󰕾";
};
"pulseaudio#mic" = {
format = "{format_source}";
format-muted = "{format_source}";
format-bluetooth = "{format_source}";
format-bluetooth-muted = "{format_source}";
format-source = "󰍬 {volume}%";
format-source-muted = "󰍭";
};
"niri/language" = {
format = "{short}";
tooltip-format = "{long}";
};
"niri/window" = {
separate-outputs = true;
};
};
};
in
in
{
default =
base
// {
output = lib.mkIf (conf.wayland.outputs.default.name != null) conf.wayland.outputs.default.name;
default = base // {
output = lib.mkIf (conf.wayland.outputs.default.name != null) conf.wayland.outputs.default.name;
modules-left = ["niri/workspaces"];
modules-center = ["niri/window"];
modules-right = ["custom/yk" "custom/screenshot" "memory" "memory#swap" "disk" "disk#persistent" "cpu" "custom/dunst" "custom/github" "backlight" "pulseaudio" "pulseaudio#mic" "custom/webcam" "niri/language" "battery" "network" "clock" "tray"];
};
modules-left = [ "niri/workspaces" ];
modules-center = [ "niri/window" ];
modules-right = [
"custom/yk"
"custom/screenshot"
"memory"
"memory#swap"
"disk"
"disk#persistent"
"cpu"
"custom/dunst"
"custom/github"
"backlight"
"pulseaudio"
"pulseaudio#mic"
"custom/webcam"
"niri/language"
"battery"
"network"
"clock"
"tray"
];
};
}
// (builtins.mapAttrs (k: v:
// (builtins.mapAttrs (
k: v:
base
// {
name = k;
height = 25;
output = v.name;
modules-left = ["niri/workspaces"];
modules-center = ["niri/window"];
modules-right = ["custom/yk" "memory" "memory#swap" "disk" "disk#persistent" "cpu" "custom/dunst" "backlight" "pulseaudio" "pulseaudio#mic" "custom/webcam" "niri/language" "battery" "network" "clock"];
}) (builtins.removeAttrs conf.wayland.outputs ["default"]));
modules-left = [ "niri/workspaces" ];
modules-center = [ "niri/window" ];
modules-right = [
"custom/yk"
"memory"
"memory#swap"
"disk"
"disk#persistent"
"cpu"
"custom/dunst"
"backlight"
"pulseaudio"
"pulseaudio#mic"
"custom/webcam"
"niri/language"
"battery"
"network"
"clock"
];
}
) (builtins.removeAttrs conf.wayland.outputs [ "default" ]));
style = ''
* {

View file

@ -1,5 +1,6 @@
{pkgs, ...}: {
home.packages = [pkgs.xournalpp];
{ pkgs, ... }:
{
home.packages = [ pkgs.xournalpp ];
home.file.xournalpp = {
source = ./settings;
target = ".config/xournalpp";

View file

@ -1,43 +1,44 @@
{pkgs, ...}: {
home.packages = with pkgs; [
yubikey-manager
yubikey-manager-qt
yubioath-flutter
];
systemd.user = let
yktd = pkgs.yubikey-touch-detector;
in {
services = {
yubikey-touch-detector = {
Unit = {
Description = "Detects when your YubiKey is waiting for a touch";
Requires = "yubikey-touch-detector.socket";
};
Service = {
ExecStart = "${yktd}/bin/yubikey-touch-detector --libnotify";
Environment = "PATH=${pkgs.lib.makeBinPath (with pkgs; [gnupg])}";
EnvironmentFile = "-%E/yubikey-touch-detector/service.conf";
};
Install = {
Also = "yubikey-touch-detector.socket";
WantedBy = ["default.target"];
};
};
};
sockets = {
yubikey-touch-detector = {
Unit = {
Description = "Unix socket activation for YubiKey touch detector service";
};
Socket = {
ListenStream = "%t/yubikey-touch-detector.socket";
RemoveOnStop = "yes";
};
Install = {
WantedBy = ["sockets.target"];
};
};
};
{ pkgs, ... }:
{
home.packages = builtins.attrValues {
inherit (pkgs) yubikey-manager yubikey-manager-qt yubioath-flutter;
};
systemd.user =
let
yktd = pkgs.yubikey-touch-detector;
in
{
services = {
yubikey-touch-detector = {
Unit = {
Description = "Detects when your YubiKey is waiting for a touch";
Requires = "yubikey-touch-detector.socket";
};
Service = {
ExecStart = "${yktd}/bin/yubikey-touch-detector --libnotify";
Environment = "PATH=${pkgs.lib.makeBinPath [ pkgs.gnupg ]}";
EnvironmentFile = "-%E/yubikey-touch-detector/service.conf";
};
Install = {
Also = "yubikey-touch-detector.socket";
WantedBy = [ "default.target" ];
};
};
};
sockets = {
yubikey-touch-detector = {
Unit = {
Description = "Unix socket activation for YubiKey touch detector service";
};
Socket = {
ListenStream = "%t/yubikey-touch-detector.socket";
RemoveOnStop = "yes";
};
Install = {
WantedBy = [ "sockets.target" ];
};
};
};
};
}

View file

@ -1,8 +1,6 @@
{
programs.zoxide = {
enable = true;
options = [
"--cmd=cd"
];
options = [ "--cmd=cd" ];
};
}

View file

@ -1,8 +1,5 @@
{
pkgs,
lib,
...
}: let
{ pkgs, lib, ... }:
let
aliases = {
"." = "source";
ls = "EXA_COLORS='xx=2;37' ${pkgs.eza}/bin/eza -g --git --group-directories-first";
@ -64,7 +61,8 @@
[[ "$(stat -f --format=%T $dir)" = "btrfs" ]] && [[ "$(stat --format=%i $dir)" =~ ^(2|256)$ ]]
'';
};
in {
in
{
programs.zsh = {
enable = true;
autosuggestion.enable = true;

View file

@ -3,7 +3,8 @@
pkgs,
lib,
...
}: let
}:
let
aliases = {
bt = "bluetoothctl";
vlc = "vlc -I ncurses";
@ -15,7 +16,7 @@
c = lib.mkForce "clear; is_split || hyfetch";
};
impure = system-config.system.replaceDependencies.replacements != [];
impure = system-config.system.replaceDependencies.replacements != [ ];
functions = {
_rebuild = ''
@ -62,21 +63,24 @@
done
'';
};
in {
imports = [./.];
in
{
imports = [ ./. ];
programs.zsh = {
initExtra = let
ng-completion = pkgs.runCommand "ng-completion" {} ''
SHELL=zsh ${pkgs.nodePackages."@angular/cli"}/bin/ng completion script > $out
initExtra =
let
ng-completion = pkgs.runCommand "ng-completion" { } ''
SHELL=zsh ${pkgs.nodePackages."@angular/cli"}/bin/ng completion script > $out
'';
in
''
${builtins.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k}() {\n${v}\n}") functions)}
# Load Angular CLI autocompletion.
source ${ng-completion}
is_split || hyfetch
'';
in ''
${builtins.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k}() {\n${v}\n}") functions)}
# Load Angular CLI autocompletion.
source ${ng-completion}
is_split || hyfetch
'';
shellAliases = aliases;
};
}

View file

@ -28,7 +28,7 @@
mode = "1280x1024";
scale = "1";
touch = false;
workspaces = ["0"];
workspaces = [ "0" ];
};
};
};
@ -39,41 +39,60 @@
"/" = {
device = "tmpfs";
fsType = "tmpfs";
options = ["defaults" "size=100%" "mode=755"];
options = [
"defaults"
"size=100%"
"mode=755"
];
};
"/nix" = {
device = "/dev/disk/by-uuid/5ad67c07-d42c-4871-b2ea-f4ea30121666";
fsType = "btrfs";
neededForBoot = true;
options = ["compress=zstd" "noatime" "subvol=@nix"];
options = [
"compress=zstd"
"noatime"
"subvol=@nix"
];
};
"/persistent/data" = {
device = "/dev/disk/by-uuid/5ad67c07-d42c-4871-b2ea-f4ea30121666";
fsType = "btrfs";
neededForBoot = true;
options = ["compress=zstd" "noatime" "subvol=@data"];
options = [
"compress=zstd"
"noatime"
"subvol=@data"
];
};
"/persistent/cache" = {
device = "/dev/disk/by-uuid/5ad67c07-d42c-4871-b2ea-f4ea30121666";
fsType = "btrfs";
neededForBoot = true;
options = ["compress=zstd" "noatime" "subvol=@cache"];
options = [
"compress=zstd"
"noatime"
"subvol=@cache"
];
};
"/swap" = {
device = "/dev/disk/by-uuid/5ad67c07-d42c-4871-b2ea-f4ea30121666";
fsType = "btrfs";
neededForBoot = true;
options = ["noatime" "subvol=@swap"];
options = [
"noatime"
"subvol=@swap"
];
};
"/boot" = {
device = "/dev/disk/by-uuid/6B80-B69E";
fsType = "vfat";
options = ["umask=0077"];
options = [ "umask=0077" ];
};
};
@ -84,7 +103,7 @@
}
];
boot.resumeDevice = "/dev/disk/by-uuid/5ad67c07-d42c-4871-b2ea-f4ea30121666";
boot.kernelParams = ["resume_offset=14754000"];
boot.kernelParams = [ "resume_offset=14754000" ];
# https://forums.lenovo.com/t5/Ubuntu/Yoga-7i-sound-card-issue-on-Linux/m-p/5183746?page=1#5807792
boot.extraModprobeConfig = ''

View file

@ -1,19 +1,24 @@
pkgs: let
mkScripts = builtins.mapAttrs (name: deps:
pkgs:
let
mkScripts = builtins.mapAttrs (
name: deps:
pkgs.writeShellApplication {
inherit name;
runtimeInputs = deps;
text = builtins.readFile ./${name}.sh;
});
}
);
scripts = mkScripts {
easyroam-setup = with pkgs; [
coreutils
openssl
gnused
util-linux # uuidgen
pwgen
];
easyroam-setup = builtins.attrValues {
inherit (pkgs)
coreutils
openssl
gnused
util-linux # uuidgen
pwgen
;
};
};
in
scripts
scripts

View file

@ -3,7 +3,7 @@
set -e
if [[ $# -lt 1 ]]; then
cat << EOF
cat <<EOF
Setup instructions:
1. Go to https://www.easyroam.de/User/Generate
2. Select 'Manual options' > 'PKCS12', enter your device name and generate the profile
@ -15,18 +15,18 @@ fi
profile=$(realpath "$1")
if [[ -n "$2" ]]; then
if [[ -n $2 ]]; then
mkdir -p "$2"
cd "$2"
fi
pkpass=$(pwgen -s 32 1)
openssl pkcs12 -in "$profile" -legacy -nokeys -password pass: | openssl x509 > easyroam_client_cert.pem
openssl pkcs12 -in "$profile" -legacy -nokeys -password pass: | openssl x509 >easyroam_client_cert.pem
openssl pkcs12 -legacy -in "$profile" -nodes -nocerts -password pass: | openssl rsa -aes256 -out easyroam_client_key.pem -passout "pass:$pkpass"
openssl pkcs12 -in "$profile" -legacy -cacerts -nokeys -password pass: > easyroam_root_ca.pem
openssl pkcs12 -in "$profile" -legacy -cacerts -nokeys -password pass: >easyroam_root_ca.pem
cn=$(openssl x509 -noout -subject -in easyroam_client_cert.pem -legacy | sed 's/.*CN = \(.*\), C.*/\1/')
cat << EOF
cat <<EOF
[connection]
id=easyroam
uuid=$(uuidgen)

View file

@ -1,4 +1,4 @@
{...}: {
{
security.rtkit.enable = true;
services.pipewire = {
enable = true;

View file

@ -1,3 +1 @@
{...}: {
programs.light.enable = true;
}
{ programs.light.enable = true; }

View file

@ -3,7 +3,8 @@
lib,
pkgs,
...
}: let
}:
let
targets = {
srv = "rest:https://backup.defelo.de";
# home = "rest:https://backup.home.defelo.de";
@ -12,24 +13,28 @@
hostname = config.networking.hostName;
scriptConfig = let
script = pkgs.writeShellScriptBin "backup" ''
if [[ $UID -ne 0 ]]; then
exec sudo $0 $@
fi
scriptConfig =
let
script = pkgs.writeShellScriptBin "backup" ''
if [[ $UID -ne 0 ]]; then
exec sudo $0 $@
fi
systemctl start prepare-backup.service
journalctl -f${lib.concatMapStrings (target: " -u restic-backups-${target}.service") (builtins.attrNames targets)}
'';
in {
environment.systemPackages = [script];
};
systemctl start prepare-backup.service
journalctl -f${
lib.concatMapStrings (target: " -u restic-backups-${target}.service") (builtins.attrNames targets)
}
'';
in
{
environment.systemPackages = [ script ];
};
prepareConfig = {
systemd.services.prepare-backup = {
onSuccess = lib.mapAttrsToList (target: _: "restic-backups-${target}.service") targets;
restartIfChanged = false;
path = with pkgs; [coreutils btrfs-progs];
path = lib.attrValues { inherit (pkgs) coreutils btrfs-progs; };
script = ''
set -e
@ -50,23 +55,27 @@
};
groupConfig = {
users.groups.restic = {};
users.groups.restic = { };
};
backupConfigs =
lib.mapAttrsToList (target: repo: let
backupConfigs = lib.mapAttrsToList (
target: repo:
let
isRest = lib.hasPrefix "rest:" repo;
isSftp = lib.hasPrefix "sftp:" repo;
in {
in
{
services.restic.backups.${target} = {
timerConfig = null;
repository = "${repo}/${hostname}";
environmentFile = lib.mkIf isRest config.sops.templates."backup/${target}".path;
passwordFile = config.sops.secrets."backup/${target}/repository-password".path;
extraOptions = lib.optional isSftp "sftp.args='-i ${config.sops.secrets."backup/${target}/ssh-key".path}'";
extraOptions = lib.optional isSftp "sftp.args='-i ${
config.sops.secrets."backup/${target}/ssh-key".path
}'";
initialize = true;
paths = ["/persistent/data/.snapshots/backup"];
paths = [ "/persistent/data/.snapshots/backup" ];
exclude = [
"node_modules"
".venv"
@ -75,23 +84,20 @@
};
sops = {
secrets = let
s = {
sopsFile = ../hosts/${hostname}/secrets/default.yml;
owner = "root";
group = "restic";
mode = "0440";
};
in
secrets =
let
s = {
sopsFile = ../hosts/${hostname}/secrets/default.yml;
owner = "root";
group = "restic";
mode = "0440";
};
in
{
"backup/${target}/repository-password" = s;
}
// (lib.optionalAttrs isRest {
"backup/${target}/rest-password" = s;
})
// (lib.optionalAttrs isSftp {
"backup/${target}/ssh-key" = {inherit (s) sopsFile;};
});
// (lib.optionalAttrs isRest { "backup/${target}/rest-password" = s; })
// (lib.optionalAttrs isSftp { "backup/${target}/ssh-key" = { inherit (s) sopsFile; }; });
templates = lib.optionalAttrs isRest {
"backup/${target}" = {
content = ''
@ -104,7 +110,14 @@
};
};
};
})
targets;
}
) targets;
in
lib.mkMerge ([scriptConfig prepareConfig groupConfig] ++ backupConfigs)
lib.mkMerge (
[
scriptConfig
prepareConfig
groupConfig
]
++ backupConfigs
)

View file

@ -1,10 +1,8 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
users.mutableUsers = false;
users.users.root.password = "nixos";
services.getty.autologinUser = "root";
environment.systemPackages = with pkgs; [
vim
git
];
environment.systemPackages = builtins.attrValues { inherit (pkgs) vim git; };
}

View file

@ -1,4 +1,5 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
hardware.bluetooth = {
enable = true;
settings.General.Experimental = true;

View file

@ -4,10 +4,9 @@
lanzaboote,
lib,
...
}: {
imports = [
lanzaboote.nixosModules.lanzaboote
];
}:
{
imports = [ lanzaboote.nixosModules.lanzaboote ];
boot.loader.systemd-boot.enable = lib.mkForce false;
boot.loader.timeout = 2;
@ -19,19 +18,27 @@
pkiBundle = "/var/lib/sbctl";
};
environment.systemPackages = with pkgs; [efibootmgr sbctl];
environment.systemPackages = lib.attrValues { inherit (pkgs) efibootmgr sbctl; };
boot.kernel.sysctl = {
"kernel.sysrq" = 1;
"vm.swappiness" = 1;
};
boot.supportedFilesystems = ["ntfs"];
boot.supportedFilesystems = [ "ntfs" ];
boot.kernelPackages = pkgs.linuxPackages_latest;
boot.extraModulePackages = [config.boot.kernelPackages.rtl8821ce];
boot.extraModulePackages = [ config.boot.kernelPackages.rtl8821ce ];
boot.initrd.kernelModules = ["vfat" "nls_cp437" "nls_iso8859-1" "usbhid"];
boot.initrd.kernelModules = [
"vfat"
"nls_cp437"
"nls_iso8859-1"
"usbhid"
];
boot.blacklistedKernelModules = ["uvcvideo" "rtw88_8821ce"];
boot.blacklistedKernelModules = [
"uvcvideo"
"rtw88_8821ce"
];
}

View file

@ -2,8 +2,6 @@
services.btrfs.autoScrub = {
enable = true;
interval = "Fri 07:00";
fileSystems = [
"/dev/mapper/root"
];
fileSystems = [ "/dev/mapper/root" ];
};
}

View file

@ -4,7 +4,8 @@
pkgs,
lib,
...
}: {
}:
{
boot.tmp.useTmpfs = true;
time.timeZone = "Europe/Berlin";
@ -22,41 +23,43 @@
programs.zsh.enable = true;
users.defaultUserShell = pkgs.zsh;
environment.systemPackages = with pkgs; [
attic-client
age
btdu
comma
# compsize
dig
duf
eza
file
htop
iw
jq
ncdu
nix-tree
nvd
ranger
renameutils
ripgrep
sd
sops
unp
wget
wireguard-tools
wirelesstools
xxd
yq
zip
];
environment.systemPackages = lib.attrValues {
inherit (pkgs)
attic-client
age
btdu
comma
# compsize
dig
duf
eza
file
htop
iw
jq
ncdu
nix-tree
nvd
ranger
renameutils
ripgrep
sd
sops
unp
wget
wireguard-tools
wirelesstools
xxd
yq
zip
;
};
environment.pathsToLink = ["/share/zsh"];
environment.pathsToLink = [ "/share/zsh" ];
nix = {
package = pkgs.nixVersions.latest;
nixPath = ["nixpkgs=${nixpkgs}"];
nixPath = [ "nixpkgs=${nixpkgs}" ];
gc = {
automatic = true;
dates = "05:30";
@ -65,8 +68,14 @@
settings = {
keep-outputs = true;
auto-optimise-store = true;
experimental-features = ["nix-command" "flakes"];
trusted-users = ["root" "@wheel"];
experimental-features = [
"nix-command"
"flakes"
];
trusted-users = [
"root"
"@wheel"
];
substituters = lib.mkAfter [
"https://nix-community.cachix.org"
"https://attic.defelo.de/nixos"
@ -106,7 +115,7 @@
'';
environment.shellAliases.needrestart = "sh -c 'diff <(readlink /run/booted-system/{initrd,kernel,kernel-modules}) <(readlink /run/current-system/{initrd,kernel,kernel-modules})'";
systemd.suppressedSystemUnits = ["systemd-machine-id-commit.service"];
systemd.suppressedSystemUnits = [ "systemd-machine-id-commit.service" ];
system.stateVersion = "23.11";

View file

@ -3,7 +3,8 @@
home-manager,
specialArgs,
...
}: {
}:
{
imports = [
./common.nix
@ -37,6 +38,6 @@
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = config._module.args // specialArgs // {system-config = config;};
extraSpecialArgs = config._module.args // specialArgs // { system-config = config; };
};
}

View file

@ -1,15 +1,18 @@
{pkgs, ...}: {
fonts.packages = with pkgs; [
dejavu_fonts
# ipafont
meslo-lgs-nf
fantasque-sans-mono
material-icons
font-awesome_5
noto-fonts
noto-fonts-cjk-sans
noto-fonts-emoji
];
{ pkgs, ... }:
{
fonts.packages = builtins.attrValues {
inherit (pkgs)
dejavu_fonts
# ipafont
meslo-lgs-nf
fantasque-sans-mono
material-icons
font-awesome_5
noto-fonts
noto-fonts-cjk-sans
noto-fonts-emoji
;
};
# fonts.fontconfig.defaultFonts = {
# monospace = [
# "DejaVu Sans Mono"

View file

@ -1,3 +1 @@
{...}: {
services.geoclue2.enable = true;
}
{ services.geoclue2.enable = true; }

View file

@ -3,16 +3,22 @@
pkgs,
lib,
...
}: {
}:
{
networking.networkmanager.dispatcherScripts = [
{
type = "basic";
source = let
inherit (conf.networking) vpn;
wifi.trusted = builtins.toFile "wifi-trusted" (builtins.foldl' (acc: x: "${acc}${x}\n") "" conf.networking.wifi.trusted);
in
source =
let
inherit (conf.networking) vpn;
wifi.trusted = builtins.toFile "wifi-trusted" (
builtins.foldl' (acc: x: "${acc}${x}\n") "" conf.networking.wifi.trusted
);
in
pkgs.writeText "trusted-networks" ''
export PATH=${pkgs.lib.makeBinPath (with pkgs; [coreutils gnugrep networkmanager])}
export PATH=${
pkgs.lib.makeBinPath (lib.attrValues { inherit (pkgs) coreutils gnugrep networkmanager; })
}
if [[ -z "$1" ]] || [[ "$1" = "vpn" ]]; then
exit
@ -33,8 +39,8 @@
allowedTCPPorts = [
22000 # syncthing
];
allowedUDPPorts = [];
trustedInterfaces = ["vpn"];
allowedUDPPorts = [ ];
trustedInterfaces = [ "vpn" ];
# disable rpfilter for wireguard
# if packets are still dropped, they will show up in dmesg
@ -50,23 +56,26 @@
'';
};
sops.secrets = let
connections = /${conf.networking.secrets}/nm-connections;
secrets = /${conf.networking.secrets}/networking;
in
builtins.listToAttrs (map (name: {
sops.secrets =
let
connections = /${conf.networking.secrets}/nm-connections;
secrets = /${conf.networking.secrets}/networking;
in
builtins.listToAttrs (
map (name: {
name = "networking/nm-connection-${name}.nmconnection";
value = {
format = "binary";
sopsFile = /${connections}/${name};
path = "/etc/NetworkManager/system-connections/${name}.nmconnection";
};
}) (builtins.attrNames (builtins.removeAttrs (builtins.readDir connections) [".gitkeep"]))
}) (builtins.attrNames (builtins.removeAttrs (builtins.readDir connections) [ ".gitkeep" ]))
++ (map (file: {
name = "networking${lib.removePrefix (toString secrets) (toString file)}";
value = {
format = "binary";
sopsFile = file;
};
}) (lib.remove /${secrets}/.gitkeep (lib.filesystem.listFilesRecursive secrets))));
}) (lib.remove /${secrets}/.gitkeep (lib.filesystem.listFilesRecursive secrets)))
);
}

View file

@ -1,3 +1 @@
{
programs.nix-ld.enable = true;
}
{ programs.nix-ld.enable = true; }

View file

@ -1,9 +1,6 @@
{ conf, impermanence, ... }:
{
conf,
impermanence,
...
}: {
imports = [impermanence.nixosModule];
imports = [ impermanence.nixosModule ];
environment.persistence."/persistent/data" = {
hideMounts = true;
@ -12,7 +9,7 @@
"/root/.ssh"
"/var/lib/bluetooth"
];
files = [];
files = [ ];
users.${conf.user} = (import ../home/persistence.nix).data;
};
@ -30,9 +27,7 @@
# "/var/lib/waydroid"
"/var/log"
];
files = [
"/etc/machine-id"
];
files = [ "/etc/machine-id" ];
users.${conf.user} = (import ../home/persistence.nix).cache;
};

View file

@ -1,4 +1,5 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
services.upower = {
enable = true;
};
@ -23,7 +24,5 @@
done
'';
environment.systemPackages = with pkgs; [
powertop
];
environment.systemPackages = [ pkgs.powertop ];
}

View file

@ -1,4 +1,5 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
virtualisation.podman = {
enable = true;
};
@ -9,7 +10,7 @@
programs.dconf.enable = true;
services.udev.packages = [pkgs.yubikey-personalization];
services.udev.packages = [ pkgs.yubikey-personalization ];
programs.mtr.enable = true;
}

View file

@ -1,5 +1,6 @@
{sops-nix, ...}: {
imports = [sops-nix.nixosModules.sops];
{ sops-nix, ... }:
{
imports = [ sops-nix.nixosModules.sops ];
sops = {
age.keyFile = "/persistent/data/root/.config/sops/age/keys.txt";
};

View file

@ -1,7 +1,7 @@
{
programs.ssh.knownHosts = {
"*.your-storagebox.de" = {
extraHostNames = ["[*.your-storagebox.de]:23"];
extraHostNames = [ "[*.your-storagebox.de]:23" ];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIICf9svRenC/PLKIL9nk6K/pxQgoiFC41wTNvoIncOxs";
};
};

View file

@ -1,4 +1,4 @@
{...}: {
{
programs.steam = {
enable = true;
remotePlay.openFirewall = true;

View file

@ -1,32 +1,37 @@
{ conf, config, ... }:
{
conf,
config,
...
}: {
users.mutableUsers = false;
users.users = {
${conf.user} = {
isNormalUser = true;
uid = 1000;
extraGroups = ["wheel" "networkmanager" "video" "libvirtd" "restic"];
extraGroups = [
"wheel"
"networkmanager"
"video"
"libvirtd"
"restic"
];
hashedPasswordFile = config.sops.secrets."user/hashedPassword".path;
};
};
home-manager.users = let
hm = import ../home;
in {
${conf.user} = {
imports = hm.user;
home.username = conf.user;
home.homeDirectory = "/home/${conf.user}";
home-manager.users =
let
hm = import ../home;
in
{
${conf.user} = {
imports = hm.user;
home.username = conf.user;
home.homeDirectory = "/home/${conf.user}";
};
root = {
imports = hm.root;
home.username = "root";
home.homeDirectory = "/root";
};
};
root = {
imports = hm.root;
home.username = "root";
home.homeDirectory = "/root";
};
};
# security.sudo.wheelNeedsPassword = false;
security.pam.u2f = {

View file

@ -1,4 +1,5 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
virtualisation.libvirtd = {
enable = true;
qemu = {
@ -10,8 +11,7 @@
(pkgs.OVMF.override {
secureBoot = true;
tpmSupport = true;
})
.fd
}).fd
];
};
};

View file

@ -4,12 +4,13 @@
lib,
pkgs,
...
}: {
}:
{
security.polkit.enable = true;
security.pam.services.swaylock = {};
security.pam.services.swaylock = { };
services.dbus.enable = true;
services.dbus.packages = [pkgs.gcr];
services.dbus.packages = [ pkgs.gcr ];
xdg.portal = {
enable = true;
config.common.default = "*";
@ -17,9 +18,7 @@
hardware.graphics.enable = true;
environment.systemPackages = with pkgs; [
qt5.qtwayland
];
environment.systemPackages = [ pkgs.qt5.qtwayland ];
programs.niri.enable = true;
@ -31,9 +30,11 @@
services.greetd = {
enable = true;
settings = {
default_session.command = let
shell = config.users.defaultUserShell;
in "${pkgs.greetd.greetd}/bin/agreety --cmd ${shell}${shell.shellPath}";
default_session.command =
let
shell = config.users.defaultUserShell;
in
"${pkgs.greetd.greetd}/bin/agreety --cmd ${shell}${shell.shellPath}";
initial_session = {
user = conf.user;
command = "niri-session";

View file

@ -1,4 +1,4 @@
{...}: {
{
zramSwap = {
enable = true;
priority = 5;

30
treefmt.nix Normal file
View file

@ -0,0 +1,30 @@
{
settings.global.excludes = [
# no formatter available
".gitattributes"
"LICENSE"
"*.kdl"
"*.md"
"*.rasi"
# generated/managed by other programs
"home/xournalpp/settings/*"
"home/zsh/p10k.zsh"
"hosts/*/hardware-configuration.nix"
"secrets/*"
"*/secrets/*"
# not text
"*.jpg"
"*.png"
];
programs.black.enable = true;
programs.nixfmt.enable = true;
programs.nixfmt.strict = true;
programs.prettier.enable = true;
programs.shfmt.enable = true;
}