style: reformat with nixfmt-rfc-style

This commit is contained in:
Felix Schröter 2024-05-26 16:45:38 +02:00
parent 5ad8bc1d56
commit 1c5d83d81e
Signed by: felschr
GPG key ID: 671E39E6744C807D
99 changed files with 2247 additions and 1334 deletions

View file

@ -1,5 +1,10 @@
{ ... }:
{
imports = [ ./x11.nix ./wayland.nix ./gtk.nix ./gnome.nix ];
imports = [
./x11.nix
./wayland.nix
./gtk.nix
./gnome.nix
];
}

View file

@ -1,8 +1,10 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs;
with gnomeExtensions; [
environment.systemPackages =
with pkgs;
with gnomeExtensions;
[
gnome.dconf-editor
gnome.gnome-tweaks
gnome.zenity

View file

@ -77,9 +77,18 @@ rec {
};
};
outputs = { self, nixpkgs, nixpkgs-unstable, ... }@inputs:
outputs =
{
self,
nixpkgs,
nixpkgs-unstable,
...
}@inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ "x86_64-linux" "aarch64-linux" ];
systems = [
"x86_64-linux"
"aarch64-linux"
];
imports = [
./pkgs/flake-module.nix
./lib/flake-module.nix
@ -102,27 +111,33 @@ rec {
mullvad-browser = import ./home/modules/firefox/mullvad-browser.nix;
};
};
perSystem = { system, config, pkgs, ... }: {
perSystem =
{
system,
config,
pkgs,
...
}:
{
_module.args.pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
};
devShells.default =
pkgs.mkShell { inherit (config.checks.pre-commit) shellHook; };
devShells.default = pkgs.mkShell { inherit (config.checks.pre-commit) shellHook; };
checks = {
pre-commit = inputs.pre-commit-hooks.lib.${system}.run {
src = ./.;
hooks = {
nixfmt.enable = true;
nixfmt.package = pkgs.nixfmt-classic;
nixfmt.package = pkgs.nixfmt-rfc-style;
shellcheck.enable = true;
};
};
};
formatter = pkgs.nixfmt-classic;
formatter = pkgs.nixfmt-rfc-style;
};
};
}

View file

@ -1,7 +1,11 @@
{ lib, pkgs, ... }:
{
imports = [ ./firmware.nix ./solokeys.nix ./zsa.nix ];
imports = [
./firmware.nix
./solokeys.nix
./zsa.nix
];
boot.supportedFilesystems = lib.mkDefault [ "btrfs" ];
boot.kernelPackages = lib.mkOverride 800 pkgs.linuxPackages_latest;

View file

@ -1,8 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
{
hardware.bluetooth.enable = true;
hardware.bluetooth.settings = {
General = { Enable = "Source,Sink,Media,Socket"; };
General = {
Enable = "Source,Sink,Media,Socket";
};
};
}

View file

@ -1,11 +1,23 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
boot.initrd.availableKernelModules =
[ "nvme" "ahci" "xhci_pci" "usb_storage" "usbhid" "sd_mod" ];
boot.initrd.availableKernelModules = [
"nvme"
"ahci"
"xhci_pci"
"usb_storage"
"usbhid"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
@ -13,22 +25,33 @@
fileSystems."/" = {
device = "/dev/disk/by-uuid/5830e9b3-260b-451c-bfee-2028c64c6199";
fsType = "btrfs";
options = [ "subvol=@" "compress-force=zstd:1" "noatime" ];
options = [
"subvol=@"
"compress-force=zstd:1"
"noatime"
];
};
boot.initrd.luks.devices."enc".device =
"/dev/disk/by-uuid/1dd848b6-cd7f-4959-8500-a03ffdaeae66";
boot.initrd.luks.devices."enc".device = "/dev/disk/by-uuid/1dd848b6-cd7f-4959-8500-a03ffdaeae66";
fileSystems."/home" = {
device = "/dev/disk/by-uuid/5830e9b3-260b-451c-bfee-2028c64c6199";
fsType = "btrfs";
options = [ "subvol=@home" "compress-force=zstd:1" "noatime" ];
options = [
"subvol=@home"
"compress-force=zstd:1"
"noatime"
];
};
fileSystems."/.snapshots" = {
device = "/dev/disk/by-uuid/5830e9b3-260b-451c-bfee-2028c64c6199";
fsType = "btrfs";
options = [ "subvol=@snapshots" "compress-force=zstd:1" "noatime" ];
options = [
"subvol=@snapshots"
"compress-force=zstd:1"
"noatime"
];
};
fileSystems."/boot" = {
@ -36,6 +59,5 @@
fsType = "vfat";
};
hardware.cpu.amd.updateMicrocode =
lib.mkDefault config.hardware.enableRedistributableFirmware;
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -19,22 +19,33 @@
fileSystems."/" = {
device = "/dev/disk/by-uuid/70f03d67-e248-42f6-a204-c02e4f180531";
fsType = "btrfs";
options = [ "subvol=@" "compress-force=zstd:1" "noatime" ];
options = [
"subvol=@"
"compress-force=zstd:1"
"noatime"
];
};
boot.initrd.luks.devices."enc".device =
"/dev/disk/by-uuid/d3b12d0e-7e8e-4130-9a8f-680abcdc9682";
boot.initrd.luks.devices."enc".device = "/dev/disk/by-uuid/d3b12d0e-7e8e-4130-9a8f-680abcdc9682";
fileSystems."/home" = {
device = "/dev/disk/by-uuid/70f03d67-e248-42f6-a204-c02e4f180531";
fsType = "btrfs";
options = [ "subvol=@home" "compress-force=zstd:1" "noatime" ];
options = [
"subvol=@home"
"compress-force=zstd:1"
"noatime"
];
};
fileSystems."/.snapshots" = {
device = "/dev/disk/by-uuid/70f03d67-e248-42f6-a204-c02e4f180531";
fsType = "btrfs";
options = [ "subvol=@snapshots" "compress-force=zstd:1" "noatime" ];
options = [
"subvol=@snapshots"
"compress-force=zstd:1"
"noatime"
];
};
fileSystems."/boot" = {
@ -51,6 +62,5 @@
# networking.interfaces.wlo1.useDHCP = lib.mkDefault true;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.intel.updateMicrocode =
lib.mkDefault config.hardware.enableRedistributableFirmware;
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,8 +1,19 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
{
boot.initrd.availableKernelModules =
[ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ];
boot.initrd.availableKernelModules = [
"xhci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
"rtsx_pci_sdmmc"
];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
@ -17,11 +28,9 @@
fsType = "vfat";
};
swapDevices =
[{ device = "/dev/disk/by-uuid/397a1a92-596f-421b-99e1-c9b2cb821309"; }];
swapDevices = [ { device = "/dev/disk/by-uuid/397a1a92-596f-421b-99e1-c9b2cb821309"; } ];
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.intel.updateMicrocode =
lib.mkDefault config.hardware.enableRedistributableFirmware;
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,5 +1,6 @@
{ config, pkgs, ... }:
with pkgs; {
with pkgs;
{
home.packages = [ AusweisApp2 ];
}

View file

@ -1,7 +1,11 @@
{ pkgs, ... }:
{
imports = [ ./mullvad-browser.nix ./tor-browser.nix ./firefox.nix ];
imports = [
./mullvad-browser.nix
./tor-browser.nix
./firefox.nix
];
home.packages = with pkgs; [ chromium ];

View file

@ -1,11 +1,16 @@
{ inputs, config, pkgs, lib, ... }:
{
inputs,
config,
pkgs,
lib,
...
}:
with lib;
let
firefox-addons = inputs.firefox-addons.packages.${pkgs.system};
inherit (import ../modules/firefox/common.nix { inherit config lib pkgs; })
mkConfig;
inherit (import ../modules/firefox/common.nix { inherit config lib pkgs; }) mkConfig;
arkenfoxConfig = builtins.readFile "${inputs.arkenfox-userjs}/user.js";
@ -52,7 +57,8 @@ let
libredirect
zotero-connector
];
in {
in
{
programs.firefox = {
enable = true;
profiles = {
@ -64,20 +70,28 @@ in {
work = {
id = 1;
extraConfig = sharedExtraConfig;
extensions = commonExtensions
++ (with firefox-addons; [ bitwarden react-devtools reduxdevtools ]);
extensions =
commonExtensions
++ (with firefox-addons; [
bitwarden
react-devtools
reduxdevtools
]);
};
};
};
home.packages = let
makeFirefoxProfileBin = args@{ profile, ... }:
home.packages =
let
makeFirefoxProfileBin =
args@{ profile, ... }:
let
name = "firefox-${profile}";
scriptBin = pkgs.writeScriptBin name ''
firefox -P "${profile}" --name="${name}" $@
'';
desktopFile = pkgs.makeDesktopItem ((removeAttrs args [ "profile" ])
desktopFile = pkgs.makeDesktopItem (
(removeAttrs args [ "profile" ])
// {
inherit name;
exec = "${scriptBin}/bin/${name} %U";
@ -91,14 +105,20 @@ in {
"x-scheme-handler/http"
"x-scheme-handler/https"
];
categories = [ "Network" "WebBrowser" ];
});
in pkgs.runCommand name { } ''
categories = [
"Network"
"WebBrowser"
];
}
);
in
pkgs.runCommand name { } ''
mkdir -p $out/{bin,share}
cp -r ${scriptBin}/bin/${name} $out/bin/${name}
cp -r ${desktopFile}/share/applications $out/share/applications
'';
in [
in
[
(makeFirefoxProfileBin {
profile = "work";
desktopName = "Firefox (Work)";

View file

@ -1,4 +1,9 @@
{ inputs, pkgs, lib, ... }:
{
inputs,
pkgs,
lib,
...
}:
let
firefox-addons = inputs.firefox-addons.packages.${pkgs.system};
@ -42,7 +47,8 @@ let
libredirect
zotero-connector
];
in {
in
{
imports = [ ../modules/firefox/mullvad-browser.nix ];
programs.mullvad-browser = {
@ -57,8 +63,13 @@ in {
work = {
id = 1;
settings = commonSettings;
extensions = commonExtensions
++ (with firefox-addons; [ bitwarden react-devtools reduxdevtools ]);
extensions =
commonExtensions
++ (with firefox-addons; [
bitwarden
react-devtools
reduxdevtools
]);
};
};
};

View file

@ -1,5 +1,9 @@
{ ... }:
{
imports = [ ./gtk.nix ./gnome.nix ./mimeapps.nix ];
imports = [
./gtk.nix
./gnome.nix
./mimeapps.nix
];
}

View file

@ -5,7 +5,8 @@ let
down = "j";
up = "k";
right = "l";
in {
in
{
dconf.settings = with lib.hm.gvariant; {
"org/gnome/shell" = {
disable-user-extensions = false;
@ -30,15 +31,31 @@ in {
show-title = false;
active-hint = false;
};
"org/gnome/desktop/interface" = { color-scheme = "prefer-dark"; };
"org/gnome/desktop/sound" = { theme-name = "freedesktop"; };
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
};
"org/gnome/desktop/sound" = {
theme-name = "freedesktop";
};
"org/gnome/desktop/input-sources" = {
sources = map mkTuple [ [ "xkb" "gb" ] [ "ibus" "mozc-jp" ] ];
sources = map mkTuple [
[
"xkb"
"gb"
]
[
"ibus"
"mozc-jp"
]
];
xkb-options = [ "compose:ralt" ];
};
"org/gnome/desktop/app-folders" = {
folder-children = [ "Office" "Utilities" ];
folder-children = [
"Office"
"Utilities"
];
};
"org/gnome/desktop/app-folders/folders/Office" = {
name = "Office";
@ -48,11 +65,17 @@ in {
"org/gnome/desktop/app-folders/folders/Utilities" = {
name = "Utilities";
translate = true;
categories = [ "Utility" "X-GNOME-Utilities" "System" ];
categories = [
"Utility"
"X-GNOME-Utilities"
"System"
];
};
# key bindings for pop-shell
"org/gnome/mutter/wayland/keybindings" = { restore-shortcuts = [ ]; };
"org/gnome/mutter/wayland/keybindings" = {
restore-shortcuts = [ ];
};
"org/gnome/shell/keybindings" = {
open-application-menu = [ ];
toggle-message-tray = [ "<Super>v" ];
@ -67,16 +90,25 @@ in {
toggle-fullscreen = [ "<Super>f" ];
toggle-on-all-workspaces = [ "<Super>p" ];
switch-to-workspace-left =
[ "<Primary><Super>Left" "<Primary><Super>${left}" ];
switch-to-workspace-right =
[ "<Primary><Super>Right" "<Primary><Super>${right}" ];
switch-to-workspace-left = [
"<Primary><Super>Left"
"<Primary><Super>${left}"
];
switch-to-workspace-right = [
"<Primary><Super>Right"
"<Primary><Super>${right}"
];
switch-to-workspace-down = [ ];
switch-to-workspace-up = [ ];
move-to-workspace-left = [ "<Shift><Super>Left" "<Shift><Super>${left}" ];
move-to-workspace-right =
[ "<Shift><Super>Right" "<Shift><Super>${right}" ];
move-to-workspace-left = [
"<Shift><Super>Left"
"<Shift><Super>${left}"
];
move-to-workspace-right = [
"<Shift><Super>Right"
"<Shift><Super>${right}"
];
move-to-workspace-down = [ ];
move-to-workspace-up = [ ];
@ -91,7 +123,10 @@ in {
};
"org/gnome/settings-daemon/plugins/color" = {
night-light-enabled = true;
night-light-last-coordinates = mkTuple [ 53.2593 10.4 ];
night-light-last-coordinates = mkTuple [
53.2593
10.4
];
night-light-temperature = mkUint32 3700;
};
"org/gnome/settings-daemon/plugins/media-keys" = {

View file

@ -15,7 +15,10 @@ let
image = [ "org.gnome.Loupe.desktop" ];
audio = [ "io.github.celluloid_player.Celluloid.desktop" ];
video = [ "io.github.celluloid_player.Celluloid.desktop" ];
directory = [ "nautilus.desktop" "org.gnome.Nautilus.desktop" ];
directory = [
"nautilus.desktop"
"org.gnome.Nautilus.desktop"
];
mail = [ "re.sonny.Junction.desktop" ] ++ browsers;
calendar = [ "re.sonny.Junction.desktop" ] ++ browsers;
browser = [ "re.sonny.Junction.desktop" ] ++ browsers;
@ -60,7 +63,10 @@ let
];
directory = [ "inode/directory" ];
mail = [ "x-scheme-handler/mailto" ];
calendar = [ "text/calendar" "x-scheme-handler/webcal" ];
calendar = [
"text/calendar"
"x-scheme-handler/webcal"
];
browser = [
"text/html"
"x-scheme-handler/about"
@ -86,12 +92,14 @@ let
signal = [ "signal-desktop.desktop" ];
};
associations = with lists;
listToAttrs (flatten (mapAttrsToList
(key: map (type: attrsets.nameValuePair type defaultApps."${key}"))
mimeMap));
associations =
with lists;
listToAttrs (
flatten (mapAttrsToList (key: map (type: attrsets.nameValuePair type defaultApps."${key}")) mimeMap)
);
noCalibre = let
noCalibre =
let
mimeTypes = [
"application/pdf"
"application/vnd.oasis.opendocument.text"
@ -104,8 +112,10 @@ let
"calibre-ebook-viewer.desktop"
"calibre-gui.desktop"
];
in lib.zipAttrs (map (d: lib.genAttrs mimeTypes (_: d)) desktopFiles);
in {
in
lib.zipAttrs (map (d: lib.genAttrs mimeTypes (_: d)) desktopFiles);
in
{
xdg.configFile."mimeapps.list".force = true;
xdg.mimeApps.enable = true;
xdg.mimeApps.associations.added = associations;

View file

@ -1,9 +1,17 @@
{ config, pkgs, ... }:
{
imports = [ ./lsp.nix ./dap.nix ./helix ./neovim ];
imports = [
./lsp.nix
./dap.nix
./helix
./neovim
];
home.packages = with pkgs; [ fzf ripgrep ];
home.packages = with pkgs; [
fzf
ripgrep
];
home.sessionVariables.EDITOR = "hx";

View file

@ -3,7 +3,10 @@
let
prettier = parser: {
command = "prettier";
args = [ "--parser" parser ];
args = [
"--parser"
parser
];
};
typescriptLanguageServers = [
{
@ -12,7 +15,8 @@ let
}
"vscode-eslint-language-server"
];
in {
in
{
# HINT for direnv to work needs to be started from project folder
programs.helix = {
enable = true;
@ -52,7 +56,10 @@ in {
name = "nix";
# `nix fmt` does not support stdin
formatter.command = "nixfmt";
language-servers = [ "nixd" "statix" ];
language-servers = [
"nixd"
"statix"
];
auto-format = true;
}
{
@ -63,7 +70,10 @@ in {
{
name = "protobuf";
formatter.command = "buf format -w";
language-servers = [ "bufls" "buf-lint" ];
language-servers = [
"bufls"
"buf-lint"
];
}
{
name = "graphql";
@ -103,7 +113,11 @@ in {
name = "bash";
formatter = {
command = "shfmt";
args = [ "-i" "2" "-" ];
args = [
"-i"
"2"
"-"
];
};
auto-format = true;
}
@ -125,23 +139,31 @@ in {
command = "efm-langserver";
config = {
languages = {
nix = [{
nix = [
{
# https://github.com/creativenull/efmls-configs-nvim/blob/ddc7c542aaad21da594edba233c15ae3fad01ea0/lua/efmls-configs/linters/statix.lua
lintCommand = "statix check --stdin --format=errfmt";
lintStdIn = true;
lintIgnoreExitCode = true;
lintFormats = [ "<stdin>>%l:%c:%t:%n:%m" ];
rootMarkers = [ "flake.nix" "shell.nix" "default.nix" ];
}];
rootMarkers = [
"flake.nix"
"shell.nix"
"default.nix"
];
}
];
};
};
};
buf-lint = {
command = "efm-langserver";
config.languages.protobuf = [{
config.languages.protobuf = [
{
lintCommand = "buf lint --path";
rootMarkers = [ "buf.yaml" ];
}];
}
];
};
nixd.command = "nixd";
# does not support formatting
@ -177,7 +199,10 @@ in {
config = {
runtime = {
version = "LuaJIT";
path = [ "?.lua" "?/init.lua" ];
path = [
"?.lua"
"?/init.lua"
];
};
};
};
@ -216,7 +241,9 @@ in {
"H" = "goto_line_start";
"L" = "goto_line_end";
};
insert = { "C-space" = "completion"; };
insert = {
"C-space" = "completion";
};
};
};
};

View file

@ -6,8 +6,12 @@ let
${lua}
EOF
'';
in {
home.packages = with pkgs; [ neovide graphviz ];
in
{
home.packages = with pkgs; [
neovide
graphviz
];
programs.neovim = {
enable = true;
@ -65,8 +69,10 @@ in {
neorg
];
extraConfig = with builtins;
vimLua (lib.foldl (r: f: r + "\n" + readFile f) "" [
extraConfig =
with builtins;
vimLua (
lib.foldl (r: f: r + "\n" + readFile f) "" [
./init.lua
./alpha.lua
./auto-session.lua
@ -84,7 +90,8 @@ in {
./treesitter.lua
./telescope.lua
./neorg.lua
]);
]
);
withNodeJs = false;
withPython3 = false;
};

View file

@ -13,11 +13,11 @@ let
>"$out/share/applications/element-desktop.desktop"
'';
};
in {
in
{
home.packages = [ element-desktop ];
xdg.configFile."autostart/element-desktop.desktop".text =
builtins.replaceStrings [ "Exec=element-desktop" ]
[ "Exec=element-desktop --hidden" ] (builtins.readFile
"${element-desktop}/share/applications/element-desktop.desktop");
builtins.replaceStrings [ "Exec=element-desktop" ] [ "Exec=element-desktop --hidden" ]
(builtins.readFile "${element-desktop}/share/applications/element-desktop.desktop");
}

View file

@ -1,9 +1,22 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
{
imports = [ ./shell ./editors/lsp.nix ./editors/helix ./git.nix ];
imports = [
./shell
./editors/lsp.nix
./editors/helix
./git.nix
];
home.packages = with pkgs; [ fh ncurses ];
home.packages = with pkgs; [
fh
ncurses
];
programs.gpg.enable = true;
services.gpg-agent = {

View file

@ -1,6 +1,12 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
with pkgs; {
with pkgs;
{
imports = [
./shell
./tailscale.nix
@ -31,7 +37,9 @@ with pkgs; {
programs.ssh.enable = true;
programs.git = { defaultProfile = "work"; };
programs.git = {
defaultProfile = "work";
};
xdg.configFile."nixpkgs/config.nix".text = ''
{

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
{
imports = [

View file

@ -1,7 +1,13 @@
{ pkgs, ... }:
{
imports = [ ./steam.nix ./lutris.nix ];
imports = [
./steam.nix
./lutris.nix
];
home.packages = with pkgs; [ gamescope mangohud ];
home.packages = with pkgs; [
gamescope
mangohud
];
}

View file

@ -1,6 +1,15 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
{
# TODO move into heroic.nix or rename lutris.nix
home.packages = with pkgs; [ unstable.wineWowPackages.stable lutris heroic ];
home.packages = with pkgs; [
unstable.wineWowPackages.stable
lutris
heroic
];
}

View file

@ -2,12 +2,14 @@
{
home.file = {
proton-ge = let version = "GE-Proton7-54";
in {
proton-ge =
let
version = "GE-Proton7-54";
in
{
recursive = true;
source = builtins.fetchTarball {
url =
"https://github.com/GloriousEggroll/proton-ge-custom/releases/download/${version}/${version}.tar.gz";
url = "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/${version}/${version}.tar.gz";
sha256 = "1iy14s1d48wxnnmw45jh5w2yadkrvwip8k91xljwg066aprb00vi";
};
target = ".local/share/Steam/compatibilitytools.d/Proton-${version}/";

View file

@ -10,7 +10,10 @@
email = "dev@felschr.com";
# use sign subkey's fingerprint: gpg2 -K --with-subkey-fingerprint
signingKey = "7E08 6842 0934 AA1D 6821 1F2A 671E 39E6 744C 807D";
dirs = [ "~/dev/private/" "/etc/nixos" ];
dirs = [
"~/dev/private/"
"/etc/nixos"
];
};
work = {
name = "Felix Schröter";
@ -22,10 +25,16 @@
};
ignores = [ ".direnv" ];
signing = { signByDefault = true; };
signing = {
signByDefault = true;
};
extraConfig = {
init = { defaultBranch = "main"; };
pull = { rebase = true; };
init = {
defaultBranch = "main";
};
pull = {
rebase = true;
};
rebase = {
autoStash = true;
autoSquash = true;
@ -35,14 +44,12 @@
};
aliases = {
# usage: git mr <source> <MR number> (git mr origin 1010)
mr =
"!sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -";
mr = "!sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -";
# usage: git pr <source> <PR number> (git pr origin 1010)
pr = "!sh -c 'git fetch $1 pull/$2/head:pr/$2 && git checkout pr/$2' -";
# delete branches locally that have already been merged
# usage: git clean-branches <branch> (branch to check against, defaults to main)
clean-branches = ''
!sh -c 'git branch --merged "''${1:-main}" | egrep -v "(^\*|master|main|staging|production)" | xargs git branch -d' -'';
clean-branches = ''!sh -c 'git branch --merged "''${1:-main}" | egrep -v "(^\*|master|main|staging|production)" | xargs git branch -d' -'';
};
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
with lib;
@ -9,24 +14,29 @@ let
# by future Firefox versions.
extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
userPrefValue = pref:
builtins.toJSON (if isBool pref || isInt pref || isString pref then
pref
else
builtins.toJSON pref);
userPrefValue =
pref:
builtins.toJSON (if isBool pref || isInt pref || isString pref then pref else builtins.toJSON pref);
mkConfig = prefs:
concatStrings (mapAttrsToList (name: value: ''
mkConfig =
prefs:
concatStrings (
mapAttrsToList (name: value: ''
user_pref("${name}", ${userPrefValue value});
'') prefs);
'') prefs
);
mkUserJs = prefs: extraPrefs: bookmarks:
mkUserJs =
prefs: extraPrefs: bookmarks:
let
prefs' = lib.optionalAttrs ([ ] != bookmarks) {
prefs' =
lib.optionalAttrs ([ ] != bookmarks) {
"browser.bookmarks.file" = toString (firefoxBookmarksFile bookmarks);
"browser.places.importBookmarksHTML" = true;
} // prefs;
in ''
}
// prefs;
in
''
// Generated by Home Manager.
${mkConfig prefs'}
@ -34,18 +44,15 @@ let
${extraPrefs}
'';
firefoxBookmarksFile = bookmarks:
firefoxBookmarksFile =
bookmarks:
let
indent = level:
lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level));
indent = level: lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level));
bookmarkToHTML = indentLevel: bookmark:
''
${indent indentLevel}<DT><A HREF="${
escapeXML bookmark.url
}" ADD_DATE="0" LAST_MODIFIED="0"${
lib.optionalString (bookmark.keyword != null)
" SHORTCUTURL=\"${escapeXML bookmark.keyword}\""
bookmarkToHTML =
indentLevel: bookmark:
''${indent indentLevel}<DT><A HREF="${escapeXML bookmark.url}" ADD_DATE="0" LAST_MODIFIED="0"${
lib.optionalString (bookmark.keyword != null) " SHORTCUTURL=\"${escapeXML bookmark.keyword}\""
}>${escapeXML bookmark.name}</A>'';
directoryToHTML = indentLevel: directory: ''
@ -59,18 +66,16 @@ let
${allItemsToHTML (indentLevel + 1) directory.bookmarks}
${indent indentLevel}</p></DL>'';
itemToHTMLOrRecurse = indentLevel: item:
if item ? "url" then
bookmarkToHTML indentLevel item
else
directoryToHTML indentLevel item;
itemToHTMLOrRecurse =
indentLevel: item:
if item ? "url" then bookmarkToHTML indentLevel item else directoryToHTML indentLevel item;
allItemsToHTML = indentLevel: bookmarks:
lib.concatStringsSep "\n"
(map (itemToHTMLOrRecurse indentLevel) bookmarks);
allItemsToHTML =
indentLevel: bookmarks: lib.concatStringsSep "\n" (map (itemToHTMLOrRecurse indentLevel) bookmarks);
bookmarkEntries = allItemsToHTML 1 bookmarks;
in pkgs.writeText "firefox-bookmarks.html" ''
in
pkgs.writeText "firefox-bookmarks.html" ''
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!-- This is an automatically generated file.
It will be read and overwritten.
@ -82,30 +87,44 @@ let
${bookmarkEntries}
</p></DL>
'';
in {
in
{
inherit mkConfig;
mkModule = browser:
mkModule =
browser:
let
cfg = config.programs.${browser.name};
inherit (browser)
displayName dataConfigPath defaultPackage defaultPackageName isSecure;
displayName
dataConfigPath
defaultPackage
defaultPackageName
isSecure
;
profilesPath = dataConfigPath;
profiles = flip mapAttrs' cfg.profiles (_: profile:
profiles =
flip mapAttrs' cfg.profiles (
_: profile:
nameValuePair "Profile${toString profile.id}" {
Name = profile.name;
Path = profile.path;
IsRelative = 1;
Default = if profile.isDefault then 1 else 0;
}) // {
General = { StartWithLastProfile = 1; };
}
)
// {
General = {
StartWithLastProfile = 1;
};
};
profilesIni = generators.toINI { } profiles;
mkProfileBin = profile:
mkProfileBin =
profile:
let
name = "${browser.name}-${profile}";
scriptBin = pkgs.writeScriptBin name ''
@ -118,15 +137,19 @@ in {
extraConfig.StartupWMClass = name;
desktopName = "${displayName} (${profile})";
genericName = "Web Browser";
categories = [ "Network" "WebBrowser" ]
++ optional isSecure "Security";
categories = [
"Network"
"WebBrowser"
] ++ optional isSecure "Security";
};
in pkgs.runCommand name { } ''
in
pkgs.runCommand name { } ''
mkdir -p $out/{bin,share}
cp -r ${scriptBin}/bin/${name} $out/bin/${name}
cp -r ${desktopFile}/share/applications $out/share/applications
'';
in {
in
{
options = {
programs.${browser.name} = {
enable = mkEnableOption displayName;
@ -154,7 +177,10 @@ in {
};
profiles = mkOption {
type = types.attrsOf (types.submodule ({ config, name, ... }: {
type = types.attrsOf (
types.submodule (
{ config, name, ... }:
{
options = {
name = mkOption {
type = types.str;
@ -171,10 +197,12 @@ in {
};
settings = mkOption {
type = types.attrsOf (jsonFormat.type // {
description =
"Firefox preference (int, bool, string, and also attrs, list, float as a JSON string)";
});
type = types.attrsOf (
jsonFormat.type
// {
description = "Firefox preference (int, bool, string, and also attrs, list, float as a JSON string)";
}
);
default = { };
example = literalExpression ''
{
@ -237,9 +265,12 @@ in {
};
bookmarks = mkOption {
type = let
bookmarkSubmodule = types.submodule
({ config, name, ... }: {
type =
let
bookmarkSubmodule =
types.submodule (
{ config, name, ... }:
{
options = {
name = mkOption {
type = types.str;
@ -255,18 +286,21 @@ in {
url = mkOption {
type = types.str;
description =
"Bookmark url, use %s for search terms.";
description = "Bookmark url, use %s for search terms.";
};
};
}) // {
}
)
// {
description = "bookmark submodule";
};
bookmarkType =
types.addCheck bookmarkSubmodule (x: x ? "url");
bookmarkType = types.addCheck bookmarkSubmodule (x: x ? "url");
directoryType = types.submodule ({ config, name, ... }: {
directoryType =
types.submodule (
{ config, name, ... }:
{
options = {
name = mkOption {
type = types.str;
@ -283,16 +317,18 @@ in {
toolbar = mkOption {
type = types.bool;
default = false;
description =
"If directory should be shown in toolbar.";
description = "If directory should be shown in toolbar.";
};
};
}) // {
}
)
// {
description = "directory submodule";
};
nodeType = types.either bookmarkType directoryType;
in with types;
in
with types;
coercedTo (attrsOf nodeType) attrValues (listOf nodeType);
default = [ ];
example = literalExpression ''
@ -365,7 +401,10 @@ in {
order = mkOption {
type = with types; uniq (listOf str);
default = [ ];
example = [ "DuckDuckGo" "Google" ];
example = [
"DuckDuckGo"
"Google"
];
description = ''
The order the search engines are listed in. Any engines
that aren't included in this list will be listed after
@ -447,9 +486,10 @@ in {
inside Firefox after the first installation.
'';
};
};
}));
}
)
);
default = { };
description = "Attribute set of Firefox profiles.";
};
@ -458,29 +498,36 @@ in {
config = mkIf cfg.enable {
assertions = [
(let
defaults = catAttrs "name"
(filter (a: a.isDefault) (attrValues cfg.profiles));
in {
(
let
defaults = catAttrs "name" (filter (a: a.isDefault) (attrValues cfg.profiles));
in
{
assertion = cfg.profiles == { } || length defaults == 1;
message = "Must have exactly one default Firefox profile but found "
message =
"Must have exactly one default Firefox profile but found "
+ toString (length defaults)
+ optionalString (length defaults > 1)
(", namely " + concatStringsSep ", " defaults);
})
+ optionalString (length defaults > 1) (", namely " + concatStringsSep ", " defaults);
}
)
(let
duplicates = filterAttrs (_: v: length v != 1) (zipAttrs
(mapAttrsToList (n: v: { "${toString v.id}" = n; })
(cfg.profiles)));
(
let
duplicates = filterAttrs (_: v: length v != 1) (
zipAttrs (mapAttrsToList (n: v: { "${toString v.id}" = n; }) (cfg.profiles))
);
mkMsg = n: v: " - ID ${n} is used by ${concatStringsSep ", " v}";
in {
in
{
assertion = duplicates == { };
message = ''
message =
''
Must not have Firefox profiles with duplicate IDs but
'' + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates);
})
''
+ concatStringsSep "\n" (mapAttrsToList mkMsg duplicates);
}
)
];
warnings = optional (cfg.enableGnomeExtensions or false) ''
@ -490,42 +537,51 @@ in {
its example for how to do this.
'';
home.packages = [ cfg.package ] ++ (if cfg.createProfileBins then
(mapAttrsToList (name: profile: (mkProfileBin name))
(filterAttrs (_: p: !p.isDefault) cfg.profiles))
home.packages =
[ cfg.package ]
++ (
if cfg.createProfileBins then
(mapAttrsToList (name: profile: (mkProfileBin name)) (
filterAttrs (_: p: !p.isDefault) cfg.profiles
))
else
[ ]);
[ ]
);
home.file = mkMerge ([{
"${dataConfigPath}/profiles.ini" =
mkIf (cfg.profiles != { }) { text = profilesIni; };
}] ++ flip mapAttrsToList cfg.profiles (_: profile: {
home.file = mkMerge (
[ { "${dataConfigPath}/profiles.ini" = mkIf (cfg.profiles != { }) { text = profilesIni; }; } ]
++ flip mapAttrsToList cfg.profiles (
_: profile: {
"${profilesPath}/${profile.path}/.keep".text = "";
"${profilesPath}/${profile.path}/chrome/userChrome.css" =
mkIf (profile.userChrome != "") { text = profile.userChrome; };
"${profilesPath}/${profile.path}/chrome/userContent.css" =
mkIf (profile.userContent != "") { text = profile.userContent; };
"${profilesPath}/${profile.path}/user.js" = mkIf (profile.settings
!= { } || profile.extraConfig != "" || profile.bookmarks != [ ]) {
text =
mkUserJs profile.settings profile.extraConfig profile.bookmarks;
"${profilesPath}/${profile.path}/chrome/userChrome.css" = mkIf (profile.userChrome != "") {
text = profile.userChrome;
};
"${profilesPath}/${profile.path}/search.json.mozlz4" = mkIf
(profile.search.default != null || profile.search.order != [ ]
|| profile.search.engines != { }) {
"${profilesPath}/${profile.path}/chrome/userContent.css" = mkIf (profile.userContent != "") {
text = profile.userContent;
};
"${profilesPath}/${profile.path}/user.js" = mkIf (
profile.settings != { } || profile.extraConfig != "" || profile.bookmarks != [ ]
) { text = mkUserJs profile.settings profile.extraConfig profile.bookmarks; };
"${profilesPath}/${profile.path}/search.json.mozlz4" =
mkIf
(profile.search.default != null || profile.search.order != [ ] || profile.search.engines != { })
{
force = profile.search.force;
source = let
source =
let
settings = {
version = 6;
engines = let
engines =
let
# Map of nice field names to internal field names.
# This is intended to be exhaustive and should be
# updated at every version bump.
internalFieldNames = (genAttrs [
internalFieldNames =
(genAttrs [
"name"
"isAppProvided"
"loadPath"
@ -539,84 +595,96 @@ in {
"orderHint"
"definedAliases"
"urls"
] (name: "_${name}")) // {
] (name: "_${name}"))
// {
searchForm = "__searchForm";
};
processCustomEngineInput = input:
processCustomEngineInput =
input:
(removeAttrs input [ "icon" ])
// optionalAttrs (input ? icon) {
# Convenience to specify absolute path to icon
iconURL = "file://${input.icon}";
} // (optionalAttrs (input ? iconUpdateURL) {
}
// (
optionalAttrs (input ? iconUpdateURL) {
# Convenience to default iconURL to iconUpdateURL so
# the icon is immediately downloaded from the URL
iconURL = input.iconURL or input.iconUpdateURL;
} // {
}
// {
# Required for custom engine configurations, loadPaths
# are unique identifiers that are generally formatted
# like: [source]/path/to/engine.xml
loadPath = ''
[home-manager]/programs.${browser.name}.profiles.${profile.name}.search.engines."${
loadPath = ''[home-manager]/programs.${browser.name}.profiles.${profile.name}.search.engines."${
replaceStrings [ "\\" ] [ "\\\\" ] input.name
}"'';
});
}
);
processEngineInput = name: input:
processEngineInput =
name: input:
let
requiredInput = {
inherit name;
isAppProvided =
input.isAppProvided or removeAttrs input
[ "metaData" ] == { };
isAppProvided = input.isAppProvided or removeAttrs input [ "metaData" ] == { };
metaData = input.metaData or { };
};
in if requiredInput.isAppProvided then
in
if requiredInput.isAppProvided then
requiredInput
else
processCustomEngineInput (input // requiredInput);
buildEngineConfig = name: input:
buildEngineConfig =
name: input:
mapAttrs' (name: value: {
name = internalFieldNames.${name} or name;
inherit value;
}) (processEngineInput name input);
sortEngineConfigs = configs:
sortEngineConfigs =
configs:
let
buildEngineConfigWithOrder = order: name:
buildEngineConfigWithOrder =
order: name:
let
config = configs.${name} or {
config =
configs.${name} or {
_name = name;
_isAppProvided = true;
_metaData = { };
};
in config // {
in
config
// {
_metaData = config._metaData // {
inherit order;
};
};
engineConfigsWithoutOrder = attrValues
(removeAttrs configs profile.search.order);
engineConfigsWithoutOrder = attrValues (removeAttrs configs profile.search.order);
sortedEngineConfigs = (imap buildEngineConfigWithOrder
profile.search.order) ++ engineConfigsWithoutOrder;
in sortedEngineConfigs;
sortedEngineConfigs =
(imap buildEngineConfigWithOrder profile.search.order) ++ engineConfigsWithoutOrder;
in
sortedEngineConfigs;
engineInput = profile.search.engines // {
# Infer profile.search.default as an app provided
# engine if it's not in profile.search.engines
${profile.search.default} =
profile.search.engines.${profile.search.default} or { };
${profile.search.default} = profile.search.engines.${profile.search.default} or { };
};
in sortEngineConfigs
(mapAttrs buildEngineConfig engineInput);
in
sortEngineConfigs (mapAttrs buildEngineConfig engineInput);
metaData = optionalAttrs (profile.search.default != null) {
metaData =
optionalAttrs (profile.search.default != null) {
current = profile.search.default;
hash = "@hash@";
} // {
}
// {
useSavedOrder = profile.search.order != [ ];
};
};
@ -625,7 +693,8 @@ in {
# maliciously. We're modifying the search outside of Firefox, but
# a claim by Mozilla to remove this would be very anti-user, and
# is unlikely to be an issue for our use case.
disclaimer = appName:
disclaimer =
appName:
"By modifying this file, I agree that I am doing so "
+ "only within ${appName} itself, using official, user-driven search "
+ "engine selection processes, and in a way which does not circumvent "
@ -633,15 +702,22 @@ in {
+ "from outside of ${appName} is a malicious act, and will be responded "
+ "to accordingly.";
salt = if profile.search.default != null then
salt =
if profile.search.default != null then
profile.path + profile.search.default + disclaimer "Firefox"
else
null;
in pkgs.runCommand "search.json.mozlz4" {
nativeBuildInputs = with pkgs; [ mozlz4a openssl ];
in
pkgs.runCommand "search.json.mozlz4"
{
nativeBuildInputs = with pkgs; [
mozlz4a
openssl
];
json = builtins.toJSON settings;
inherit salt;
} ''
}
''
if [[ -n $salt ]]; then
export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64)
mozlz4a <(substituteStream json search.json.in --subst-var hash) "$out"
@ -651,14 +727,15 @@ in {
'';
};
"${profilesPath}/${profile.path}/extensions" =
mkIf (profile.extensions != [ ]) {
source = let
"${profilesPath}/${profile.path}/extensions" = mkIf (profile.extensions != [ ]) {
source =
let
extensionsEnvPkg = pkgs.buildEnv {
name = "hm-${browser.name}-extensions";
paths = profile.extensions;
};
in "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
in
"${extensionsEnvPkg}/share/mozilla/${extensionPath}";
recursive = true;
force = true;
onChange = ''
@ -666,7 +743,9 @@ in {
rm -f "${profilesPath}/${profile.path}/extensions.json"
'';
};
}));
}
)
);
};
};
}

View file

@ -1,7 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let common = import ./common.nix { inherit config lib pkgs; };
in common.mkModule {
let
common = import ./common.nix { inherit config lib pkgs; };
in
common.mkModule {
name = "firefox";
displayName = "Firefox";
dataConfigPath = ".mozilla/firefox";

View file

@ -1,7 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let common = import ./common.nix { inherit config lib pkgs; };
in common.mkModule {
let
common = import ./common.nix { inherit config lib pkgs; };
in
common.mkModule {
name = "mullvad-browser";
displayName = "Mullvad Browser";
dataConfigPath = ".mullvad/mullvadbrowser";

View file

@ -1,7 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let common = import ./common.nix { inherit config lib pkgs; };
in common.mkModule {
let
common = import ./common.nix { inherit config lib pkgs; };
in
common.mkModule {
name = "tor-browser";
displayName = "Tor Browser";
dataConfigPath = ".tor project/firefox";

View file

@ -1,36 +1,59 @@
{ lib, pkgs, config, ... }:
{
lib,
pkgs,
config,
...
}:
with lib;
let cfg = config.programs.git;
in {
let
cfg = config.programs.git;
in
{
options.programs.git = {
profiles = mkOption {
type = types.attrsOf (types.submodule ({ name, config, ... }: {
type = types.attrsOf (
types.submodule (
{ name, config, ... }:
{
options = {
name = mkOption { type = types.str; };
email = mkOption { type = types.str; };
signingKey = mkOption { type = types.str; };
dirs = mkOption { type = types.listOf types.str; };
};
}));
}
)
);
};
defaultProfile = mkOption { type = types.str; };
};
config = let inherit (cfg) profiles;
in {
config =
let
inherit (cfg) profiles;
in
{
programs.git = {
# fix/workaround for https://github.com/NixOS/nixpkgs/issues/169193
extraConfig.safe.directory = "/etc/nixos";
userName = profiles."${cfg.defaultProfile}".name;
userEmail = profiles."${cfg.defaultProfile}".email;
signing = { key = profiles."${cfg.defaultProfile}".signingKey; };
includes = flatten (mapAttrsToList (name: profile:
signing = {
key = profiles."${cfg.defaultProfile}".signingKey;
};
includes = flatten (
mapAttrsToList (
name: profile:
map (dir: {
condition = "gitdir:${dir}";
contents.user = { inherit (profile) name email signingKey; };
}) profile.dirs) profiles);
contents.user = {
inherit (profile) name email signingKey;
};
}) profile.dirs
) profiles
);
};
};
}

View file

@ -1,5 +1,6 @@
{ config, pkgs, ... }:
with pkgs; {
with pkgs;
{
home.packages = [ wally-cli ];
}

View file

@ -4,14 +4,19 @@
services.easyeffects.enable = true;
services.easyeffects.package = pkgs.easyeffects.override {
# easyeffects speex integration doesn't work otherwise
speexdsp = pkgs.speexdsp.overrideAttrs (old: { configureFlags = [ ]; });
speexdsp = pkgs.speexdsp.overrideAttrs (old: {
configureFlags = [ ];
});
};
# based on https://gist.github.com/MateusRodCosta/a10225eb132cdcb97d7c458526f93085
xdg.configFile."easyeffects/input/optimised.json".text = builtins.toJSON {
input = {
blocklist = [ ];
plugins_order = [ "rnnoise#0" "speex#0" ];
plugins_order = [
"rnnoise#0"
"speex#0"
];
"rnnoise#0" = {
bypass = false;
enable-vad = false;
@ -40,9 +45,9 @@
};
xdg.configFile."easyeffects/autoload/input/alsa_input.usb-Blue_Microphones_Yeti_Stereo_Microphone_REV8-00.analog-stereo:analog-input-mic.json".text =
builtins.toJSON {
device =
"alsa_input.usb-Blue_Microphones_Yeti_Stereo_Microphone_REV8-00.analog-stereo";
builtins.toJSON
{
device = "alsa_input.usb-Blue_Microphones_Yeti_Stereo_Microphone_REV8-00.analog-stereo";
device-description = "Yeti Stereo Microphone Analog Stereo";
device-profile = "analog-input-mic";
preset-name = "optimised";

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let shellAliases = import ./aliases.nix;
in {
let
shellAliases = import ./aliases.nix;
in
{
programs.bash = {
enable = true;
inherit shellAliases;

View file

@ -12,7 +12,9 @@
./direnv.nix
];
programs.fzf = { enable = true; };
programs.fzf = {
enable = true;
};
home.file."dev/work/.env".text = ''
BROWSER=mullvad-browser-work

View file

@ -1,14 +1,21 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
with pkgs;
with lib; {
with lib;
{
# kitty terminal
programs.kitty = {
enable = true;
keybindings = let
vimKittyBinding = bind:
''kitten pass_keys.py neighboring_window ${bind} "^.* - nvim$"'';
in {
keybindings =
let
vimKittyBinding = bind: ''kitten pass_keys.py neighboring_window ${bind} "^.* - nvim$"'';
in
{
"ctrl+h" = vimKittyBinding "left ctrl+h";
"ctrl+j" = vimKittyBinding "bottom ctrl+j";
"ctrl+k" = vimKittyBinding "top ctrl+k";
@ -18,13 +25,10 @@ with lib; {
allow_remote_control = "yes";
# single_instance = "yes";
listen_on = "unix:@mykitty";
scrollback_pager = ''
nvim -u NONE -c "syntax on" -c 'set ft=man nonumber nolist showtabline=0 foldcolumn=0 laststatus=0' -c "autocmd VimEnter * normal G" -c "map q :qa!<CR>" -c "set clipboard+=unnamedplus" -'';
scrollback_pager = ''nvim -u NONE -c "syntax on" -c 'set ft=man nonumber nolist showtabline=0 foldcolumn=0 laststatus=0' -c "autocmd VimEnter * normal G" -c "map q :qa!<CR>" -c "set clipboard+=unnamedplus" -'';
};
};
xdg.configFile."kitty/pass_keys.py".source =
"${vimPlugins.nvim-kitty-navigator}/kitty/pass_keys.py";
xdg.configFile."kitty/neighboring_window.py".source =
"${vimPlugins.nvim-kitty-navigator}/kitty/neighboring_window.py";
xdg.configFile."kitty/pass_keys.py".source = "${vimPlugins.nvim-kitty-navigator}/kitty/pass_keys.py";
xdg.configFile."kitty/neighboring_window.py".source = "${vimPlugins.nvim-kitty-navigator}/kitty/neighboring_window.py";
}

View file

@ -2,9 +2,11 @@
let
shellAliases = import ./aliases.nix;
aliasesStr = builtins.concatStringsSep "\n"
(pkgs.lib.mapAttrsToList (k: v: "alias ${k} = ${v}") shellAliases);
in {
aliasesStr = builtins.concatStringsSep "\n" (
pkgs.lib.mapAttrsToList (k: v: "alias ${k} = ${v}") shellAliases
);
in
{
programs.nushell = {
enable = true;
package = pkgs.unstable.nushell;

View file

@ -7,7 +7,9 @@
programs.zellij.settings = {
default_layout = "compact"; # or default
default_mode = "locked";
ui.pane_frames = { hide_session_name = true; };
ui.pane_frames = {
hide_session_name = true;
};
plugins = {
tab-bar.path = "tab-bar";
status-bar.path = "status-bar";
@ -15,5 +17,7 @@
};
};
home.sessionVariables = { ZELLIJ_AUTO_EXIT = "true"; };
home.sessionVariables = {
ZELLIJ_AUTO_EXIT = "true";
};
}

View file

@ -1,5 +1,3 @@
_:
{
programs.zoxide.enable = true;
}
{ programs.zoxide.enable = true; }

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let shellAliases = import ./aliases.nix;
in {
let
shellAliases = import ./aliases.nix;
in
{
programs.zsh = {
enable = true;
# TODO is being renamed again in later 24.05 release
@ -24,8 +26,7 @@ in {
{
name = "zsh-history-substring-search";
src = zsh-history-substring-search;
file =
"share/zsh-history-substring-search/zsh-history-substring-search.zsh";
file = "share/zsh-history-substring-search/zsh-history-substring-search.zsh";
}
];
initExtra = ''

View file

@ -4,7 +4,6 @@
home.packages = with pkgs; [ signal-desktop ];
xdg.configFile."autostart/signal-desktop.desktop".text =
builtins.replaceStrings [ "bin/signal-desktop" ]
[ "bin/signal-desktop --start-in-tray" ] (builtins.readFile
"${pkgs.signal-desktop}/share/applications/signal-desktop.desktop");
builtins.replaceStrings [ "bin/signal-desktop" ] [ "bin/signal-desktop --start-in-tray" ]
(builtins.readFile "${pkgs.signal-desktop}/share/applications/signal-desktop.desktop");
}

View file

@ -1,5 +1,13 @@
{ self, ... }: {
perSystem = { self', pkgs, lib, ... }: {
{ self, ... }:
{
perSystem =
{
self',
pkgs,
lib,
...
}:
{
packages.doctr = self.lib.mkOpenwrtImage {
inherit pkgs;
hostname = "doctr";

View file

@ -1,4 +1,5 @@
{ self, inputs, ... }: {
{ self, inputs, ... }:
{
flake = {
nixosConfigurations = {
home-pc = inputs.nixpkgs.lib.nixosSystem {
@ -28,12 +29,16 @@
config = ../home/felschr.nix;
usesContainers = true;
})
({ pkgs, ... }: {
environment.systemPackages =
[ inputs.deploy-rs.defaultPackage.x86_64-linux ];
})
(
{ pkgs, ... }:
{
environment.systemPackages = [ inputs.deploy-rs.defaultPackage.x86_64-linux ];
}
)
];
specialArgs = { inherit inputs; };
specialArgs = {
inherit inputs;
};
};
pilot1 = inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
@ -47,13 +52,19 @@
config = ../hosts/work-pc.nix;
})
(self.lib.createUser "felschr" {
user.extraGroups = [ "wheel" "audio" "disk" ];
user.extraGroups = [
"wheel"
"audio"
"disk"
];
modules = [ self.homeManagerModules.git ];
config = ../home/felschr-work.nix;
usesContainers = true;
})
];
specialArgs = { inherit inputs; };
specialArgs = {
inherit inputs;
};
};
home-server = inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
@ -70,7 +81,12 @@
self.lib.createMediaGroup
(self.lib.createUser "felschr" {
user = {
extraGroups = [ "wheel" "audio" "disk" "media" ];
extraGroups = [
"wheel"
"audio"
"disk"
"media"
];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP751vlJUnB7Pfe1KNr6weWkx/rkP4J3lTYpAekHdOgV"
];
@ -79,7 +95,9 @@
config = ../home/felschr-server.nix;
})
];
specialArgs = { inherit inputs; };
specialArgs = {
inherit inputs;
};
};
};
@ -89,13 +107,19 @@
sshUser = "felschr";
sshOpts = [ "-t" ];
user = "root";
path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos
self.nixosConfigurations.home-server;
path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.home-server;
magicRollback = false; # otherwise password prompt won't work
};
};
};
perSystem = { system, config, pkgs, ... }: {
perSystem =
{
system,
config,
pkgs,
...
}:
{
checks = inputs.deploy-rs.lib.${system}.deployChecks self.deploy;
};
}

View file

@ -1,4 +1,4 @@
{ ... }:
{ lib, ... }:
{
imports = [
@ -40,8 +40,10 @@
};
};
services.tailscale.extraUpFlags =
[ "--operator=felschr" "--advertise-routes=192.168.1.0/24" ];
services.tailscale.extraUpFlags = [
"--operator=felschr"
"--advertise-routes=192.168.1.0/24"
];
networking.firewall.allowedUDPPorts = [
24727 # AusweisApp2

View file

@ -1,14 +1,22 @@
{ config, pkgs, ... }:
{
inputs,
config,
pkgs,
...
}:
let
# mkdir /etc/secrets/initrd -p
# chmod 700 -R /etc/secrets/
# ssh-keygen -t ed25519 -N "" -f /etc/secrets/initrd/ssh_host_ed25519_key
hostKeys = [{
hostKeys = [
{
path = "/etc/secrets/initrd/ssh_host_ed25519_key";
type = "ed25519";
}];
in {
}
];
in
{
imports = [
../hardware/base.nix
../desktop/x11.nix
@ -44,8 +52,14 @@ in {
networking.domain = "home.felschr.com";
networking.firewall.allowedTCPPorts = [ 80 443 ];
networking.firewall.allowedUDPPorts = [ 80 443 ];
networking.firewall.allowedTCPPorts = [
80
443
];
networking.firewall.allowedUDPPorts = [
80
443
];
security.acme.acceptTerms = true;
security.acme.defaults.email = "dev@felschr.com";
@ -134,8 +148,7 @@ in {
enable = true;
method = "email";
email.mailTo = "admin@felschr.com";
email.mailFrom =
"${config.networking.hostName} <${config.programs.msmtp.accounts.default.from}>";
email.mailFrom = "${config.networking.hostName} <${config.programs.msmtp.accounts.default.from}>";
};
# only change this when specified in release notes

View file

@ -1,5 +1,13 @@
{ self, ... }: {
perSystem = { self', pkgs, lib, ... }: {
{ self, ... }:
{
perSystem =
{
self',
pkgs,
lib,
...
}:
{
packages.penguin = self.lib.mkOpenwrtImage {
inherit pkgs;
hostname = "penguin";

View file

@ -1,7 +1,21 @@
name:
{ user ? { }, hm ? { }, modules ? [ ], config, usesContainers ? false, ... }:
{
user ? { },
hm ? { },
modules ? [ ],
config,
usesContainers ? false,
...
}:
{ inputs, pkgs, lib, home-manager, ... }: {
{
inputs,
pkgs,
lib,
home-manager,
...
}:
{
imports = [ home-manager.nixosModules.home-manager ];
users.users."${name}" = {
@ -9,21 +23,30 @@ name:
shell = pkgs.zsh;
# increase sub{u,g}id range for container user namespaces
subUidRanges = lib.optionals usesContainers [{
subUidRanges = lib.optionals usesContainers [
{
startUid = 100000;
count = 60000000;
}];
subGidRanges = lib.optionals usesContainers [{
}
];
subGidRanges = lib.optionals usesContainers [
{
startGid = 100000;
count = 60000000;
}];
}
];
} // user;
home-manager = {
useUserPackages = true;
useGlobalPkgs = true;
backupFileExtension = "backup";
users."${name}" = lib.mkMerge [ { imports = modules; } (import config) ];
extraSpecialArgs = { inherit inputs; };
users."${name}" = lib.mkMerge [
{ imports = modules; }
(import config)
];
extraSpecialArgs = {
inherit inputs;
};
} // hm;
}

View file

@ -1,20 +1,30 @@
{ inputs, lib, ... }:
let createUser' = import ./createUser.nix;
in {
let
createUser' = import ./createUser.nix;
in
{
imports = [ ./openwrt.nix ];
options.flake.lib = lib.mkOption { type = with lib.types; lazyAttrsOf raw; };
config.flake.lib = {
createSystem = hostName:
createSystem =
hostName:
{ hardwareConfig, config }:
({ pkgs, lib, ... }: {
(
{ pkgs, lib, ... }:
{
networking.hostName = hostName;
imports = [ ../modules/common.nix hardwareConfig config ];
});
createUser = name: args:
({ pkgs, ... }@args2:
(createUser' name args) ({ inherit (inputs) home-manager; } // args2));
imports = [
../modules/common.nix
hardwareConfig
config
];
}
);
createUser =
name: args:
({ pkgs, ... }@args2: (createUser' name args) ({ inherit (inputs) home-manager; } // args2));
createMediaGroup = _: { users.groups.media.gid = 600; };
};
}

View file

@ -1,15 +1,25 @@
{ inputs, ... }:
let
getProfiles = pkgs:
getProfiles =
pkgs:
inputs.openwrt-imagebuilder.lib.profiles {
inherit pkgs;
release = "snapshot";
};
in {
in
{
flake.lib.mkOpenwrtImage =
{ pkgs, hostname, timezone, ipaddr, packages ? [ ], uci ? "" }:
inputs.openwrt-imagebuilder.lib.build
((getProfiles pkgs).identifyProfile "glinet_gl-mt6000" // {
{
pkgs,
hostname,
timezone,
ipaddr,
packages ? [ ],
uci ? "",
}:
inputs.openwrt-imagebuilder.lib.build (
(getProfiles pkgs).identifyProfile "glinet_gl-mt6000"
// {
packages = [
# TODO does this include everything that the web firmware builder includes?
"auc"
@ -22,6 +32,7 @@ in {
"tailscale"
] ++ packages;
# TODO set up SSH config (register public keys, disable password login, ...)
files = pkgs.runCommand "image-files" { } ''
mkdir -p $out/etc/uci-defaults
cat > $out/etc/uci-defaults/99-custom <<EOF
@ -56,5 +67,6 @@ in {
# cat "0 3 * * * /path/to/gist/script" >>/etc/crontabs/root
EOF
'';
});
}
);
}

View file

@ -1,9 +1,15 @@
{ pkgs, lib, inputs, ... }:
{
pkgs,
lib,
inputs,
...
}:
let
flakes = lib.filterAttrs (name: value: value ? outputs) inputs;
nixRegistry = builtins.mapAttrs (name: v: { flake = v; }) flakes;
in {
in
{
# Let 'nixos-version --json' know about the Git revision
# of this flake.
system.configurationRevision = lib.mkIf (inputs.self ? rev) inputs.self.rev;

View file

@ -1,7 +1,17 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkEnableOption mkOption types mkIf;
inherit (lib)
mkEnableOption
mkOption
types
mkIf
;
cfg = config.services.inadyn;
mkConfig = ipCfg: domain: ''
@ -17,7 +27,8 @@ let
${cfg.extraConfig}
${ipCfg.extraConfig}
'';
in {
in
{
# NixOS 24.05 introduced an official module, but it works somewhat differently.
# For now I'll continue using my own module.
disabledModules = [ "services/networking/inadyn.nix" ];
@ -132,8 +143,9 @@ in {
startAt = "*:0/5";
serviceConfig = rec {
Type = "simple";
LoadCredential = lib.optionalString (cfg.passwordFile != null)
"INADYN_PASSWORD:${cfg.passwordFile}";
LoadCredential = lib.optionalString (
cfg.passwordFile != null
) "INADYN_PASSWORD:${cfg.passwordFile}";
ExecStart = pkgs.writeScript "run-inadyn.sh" ''
#!${pkgs.bash}/bin/bash
export PATH=$PATH:${pkgs.bash}/bin/bash # idk if that helps
@ -148,18 +160,23 @@ in {
${lib.optionalString cfg.ipv6.enable ''
allow-ipv6 = true
''}
${lib.concatImapStrings (i: domain:
(lib.optionalString cfg.ipv4.enable ''
${lib.concatImapStrings (
i: domain:
(
lib.optionalString cfg.ipv4.enable ''
# ipv4
provider ${cfg.provider}:${toString (i * 2)} {
${mkConfig cfg.ipv4 domain}
}
'' + lib.optionalString cfg.ipv6.enable ''
''
+ lib.optionalString cfg.ipv6.enable ''
# ipv6
provider ${cfg.provider}:${toString (i * 2 + 1)} {
${mkConfig cfg.ipv6 domain}
}
'')) cfg.domains}
''
)
) cfg.domains}
EOF
exec ${cfg.package}/bin/inadyn -n ${cfg.cacheDir} -f /run/${RuntimeDirectory}/inadyn.cfg
'';

View file

@ -1,10 +1,16 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
with lib;
{
config = {
systemd.services = mapAttrs' (name: backup:
systemd.services = mapAttrs' (
name: backup:
nameValuePair "restic-backups-${name}" {
serviceConfig = {
CPUWeight = 25;
@ -14,6 +20,7 @@ with lib;
IOSchedulingClass = "idle";
IOSchedulingPriority = 7;
};
}) config.services.restic.backups;
}
) config.services.restic.backups;
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
with lib;
@ -21,7 +26,8 @@ let
$(systemctl status --full "$1")
ERRMAIL
'';
in {
in
{
options = {
systemd.notify = {
enable = mkOption {
@ -31,7 +37,10 @@ in {
};
method = mkOption {
type = types.enum [ "libnotify" "email" ];
type = types.enum [
"libnotify"
"email"
];
default = "libnotify";
description = "The method for sending notifications.";
};
@ -45,20 +54,19 @@ in {
email.mailTo = mkOption {
type = types.str;
default = null;
description =
"Email address to which the service status will be mailed.";
description = "Email address to which the service status will be mailed.";
};
email.mailFrom = mkOption {
type = types.str;
default = null;
description =
"Email address from which the service status will be mailed.";
description = "Email address from which the service status will be mailed.";
};
};
systemd.services = mkOption {
type = with types;
type =
with types;
attrsOf (submodule {
config.onFailure = optional cfg.enable "notify@%n.service";
});
@ -72,15 +80,16 @@ in {
message = "You need to specify a user";
}
{
assertion = cfg.method != "email"
|| (cfg.email.mailTo != null && cfg.email.mailFrom != null);
assertion = cfg.method != "email" || (cfg.email.mailTo != null && cfg.email.mailFrom != null);
message = "You need to specify a sender and a receiver";
}
];
systemd.services."notify@" = {
systemd.services."notify@" =
{
onFailure = lib.mkForce [ ];
} // optionalAttrs (cfg.method == "libnotify") {
}
// optionalAttrs (cfg.method == "libnotify") {
description = "Desktop notifications for %i service failure";
environment = {
DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/${
@ -97,7 +106,8 @@ in {
Type = "oneshot";
User = cfg.libnotify.user;
};
} // optionalAttrs (cfg.method == "email") {
}
// optionalAttrs (cfg.method == "email") {
description = "E-Mail notifications for %i service failure";
serviceConfig = {
ExecStart = "${sendmail} %i";

View file

@ -1,4 +1,12 @@
{ lib, stdenv, fetchFromGitHub, cmake, zlib, cups, ... }:
{
lib,
stdenv,
fetchFromGitHub,
cmake,
zlib,
cups,
...
}:
# maintained fork of brlaser with newer drivers (including Brother HL-L2370DN)
stdenv.mkDerivation (finalAttrs: {
@ -13,9 +21,15 @@ stdenv.mkDerivation (finalAttrs: {
};
nativeBuildInputs = [ cmake ];
buildInputs = [ zlib cups ];
buildInputs = [
zlib
cups
];
cmakeFlags = [ "-DCUPS_SERVER_BIN=lib/cups" "-DCUPS_DATA_DIR=share/cups" ];
cmakeFlags = [
"-DCUPS_SERVER_BIN=lib/cups"
"-DCUPS_DATA_DIR=share/cups"
];
meta = with lib; {
description = "A CUPS driver for Brother laser printers";
@ -100,7 +114,6 @@ stdenv.mkDerivation (finalAttrs: {
license = licenses.gpl2;
platforms = platforms.linux;
maintainers = with maintainers; [ felschr ];
changelog =
"https://github.com/Owl-Maintain/brlaser/releases/tag/${finalAttrs.src.rStijnDWev}";
changelog = "https://github.com/Owl-Maintain/brlaser/releases/tag/${finalAttrs.src.rStijnDWev}";
};
})

View file

@ -1,31 +1,50 @@
{ lib, stdenv, fetchurl, mkDerivation, dpkg, autoPatchelfHook, libxcrypt-legacy
, qtserialport, qtwebsockets, libredirect, makeWrapper, gzip, gnutar }:
{
lib,
stdenv,
fetchurl,
mkDerivation,
dpkg,
autoPatchelfHook,
libxcrypt-legacy,
qtserialport,
qtwebsockets,
libredirect,
makeWrapper,
gzip,
gnutar,
}:
let
version = "2.17.01";
srcs = {
x86_64-linux = fetchurl {
url =
"https://deconz.dresden-elektronik.de/ubuntu/beta/deconz-${version}-qt5.deb";
url = "https://deconz.dresden-elektronik.de/ubuntu/beta/deconz-${version}-qt5.deb";
sha256 = "sha256-c2G3oOnSXlivO9KXRBZIe2DEuq7vPVlNDKF6T/pZLps=";
};
aarch64-linux = fetchurl {
url =
"https://deconz.dresden-elektronik.de/debian/stable/deconz_${version}-debian-buster-stable_arm64.deb";
url = "https://deconz.dresden-elektronik.de/debian/stable/deconz_${version}-debian-buster-stable_arm64.deb";
sha256 = "sha256-zuy4e9bzcRqDeXP6mfzZLCDK/3we25LH6xktnO6HXps=";
};
};
in mkDerivation {
in
mkDerivation {
pname = "deCONZ";
inherit version;
src = srcs.${stdenv.hostPlatform.system};
nativeBuildInputs = [ dpkg autoPatchelfHook makeWrapper ];
nativeBuildInputs = [
dpkg
autoPatchelfHook
makeWrapper
];
buildInputs = [ libxcrypt-legacy qtserialport qtwebsockets ];
buildInputs = [
libxcrypt-legacy
qtserialport
qtwebsockets
];
unpackPhase = "dpkg-deb -x $src .";
@ -38,18 +57,24 @@ in mkDerivation {
wrapProgram "$out/bin/deCONZ" \
--set LD_PRELOAD "${libredirect}/lib/libredirect.so" \
--set NIX_REDIRECTS "/usr/share=$out/share:/usr/bin=$out/bin" \
--prefix PATH : "${lib.makeBinPath [ gzip gnutar ]}"
--prefix PATH : "${
lib.makeBinPath [
gzip
gnutar
]
}"
'';
meta = with lib; {
description =
"Manage ZigBee network with ConBee, ConBee II or RaspBee hardware";
description = "Manage ZigBee network with ConBee, ConBee II or RaspBee hardware";
# 2019-08-19: The homepage links to old software that doesn't even work --
# it fails to detect ConBee2.
homepage =
"https://www.dresden-elektronik.de/funktechnik/products/software/pc-software/deconz/?L=1";
homepage = "https://www.dresden-elektronik.de/funktechnik/products/software/pc-software/deconz/?L=1";
license = licenses.unfree;
platforms = [ "x86_64-linux" "aarch64-linux" ];
platforms = [
"x86_64-linux"
"aarch64-linux"
];
maintainers = with maintainers; [ felschr ];
};
}

View file

@ -1,5 +1,8 @@
{ inputs, ... }: {
perSystem = { self', pkgs, ... }: {
{ inputs, ... }:
{
perSystem =
{ self', pkgs, ... }:
{
packages = {
brlaser = pkgs.callPackage ./brlaser { };
deconz = pkgs.qt5.callPackage ./deconz { };

View file

@ -1,6 +1,5 @@
{ inputs, pkgs, ... }:
{
nvim-kitty-navigator =
pkgs.callPackage ./nvim-kitty-navigator { inherit inputs; };
nvim-kitty-navigator = pkgs.callPackage ./nvim-kitty-navigator { inherit inputs; };
}

View file

@ -1,45 +1,143 @@
let
# age-specific key in ~/.ssh/id_ed25519: `ssh-keygen -t ed25519`
felschr =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbQpMo1JOGk59Rzl6pVoOcMHOoqezph+aIlEXZP4rBu";
felschr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbQpMo1JOGk59Rzl6pVoOcMHOoqezph+aIlEXZP4rBu";
users = [ felschr ];
# `ssh-keygen -t ed25519 -N "" -f /etc/secrets/initrd/ssh_host_ed25519_key`
home-pc =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBFTQvIcSdhEKl/Kq+pcS/cPCyyZ1ygj+djfuaXzaRMx";
home-server =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILO+OLPr8zdOMYyKtm98AFJai7zbaxw7JhVWgOwu7K3C";
pilot1 =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHEucfNzPbDRdDjTaLG3PzN4lAzDAq3QUkaLvaRjjsCY";
systems = [ home-pc home-server pilot1 ];
in {
"restic/b2.age".publicKeys = [ felschr home-pc home-server pilot1 ];
"restic/password.age".publicKeys = [ felschr home-pc home-server pilot1 ];
"smtp.age".publicKeys = [ felschr home-pc home-server ];
"samba.age".publicKeys = [ felschr home-pc home-server ];
"cloudflare.age".publicKeys = [ felschr home-pc home-server ];
"etebase-server.age".publicKeys = [ felschr home-pc home-server ];
"calibre-web/htpasswd.age".publicKeys = [ felschr home-pc home-server ];
"miniflux/admin.age".publicKeys = [ felschr home-pc home-server ];
"miniflux/oidc.age".publicKeys = [ felschr home-pc home-server ];
"paperless.age".publicKeys = [ felschr home-pc home-server ];
"nextcloud/admin.age".publicKeys = [ felschr home-pc home-server ];
"immich/.env.age".publicKeys = [ felschr home-pc home-server ];
"immich/db-password.age".publicKeys = [ felschr home-pc home-server ];
"immich/typesense/.env.age".publicKeys = [ felschr home-pc home-server ];
home-pc = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBFTQvIcSdhEKl/Kq+pcS/cPCyyZ1ygj+djfuaXzaRMx";
home-server = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILO+OLPr8zdOMYyKtm98AFJai7zbaxw7JhVWgOwu7K3C";
pilot1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHEucfNzPbDRdDjTaLG3PzN4lAzDAq3QUkaLvaRjjsCY";
systems = [
home-pc
home-server
pilot1
];
in
{
"restic/b2.age".publicKeys = [
felschr
home-pc
home-server
pilot1
];
"restic/password.age".publicKeys = [
felschr
home-pc
home-server
pilot1
];
"smtp.age".publicKeys = [
felschr
home-pc
home-server
];
"samba.age".publicKeys = [
felschr
home-pc
home-server
];
"cloudflare.age".publicKeys = [
felschr
home-pc
home-server
];
"etebase-server.age".publicKeys = [
felschr
home-pc
home-server
];
"calibre-web/htpasswd.age".publicKeys = [
felschr
home-pc
home-server
];
"miniflux/admin.age".publicKeys = [
felschr
home-pc
home-server
];
"miniflux/oidc.age".publicKeys = [
felschr
home-pc
home-server
];
"paperless.age".publicKeys = [
felschr
home-pc
home-server
];
"nextcloud/admin.age".publicKeys = [
felschr
home-pc
home-server
];
"immich/.env.age".publicKeys = [
felschr
home-pc
home-server
];
"immich/db-password.age".publicKeys = [
felschr
home-pc
home-server
];
"immich/typesense/.env.age".publicKeys = [
felschr
home-pc
home-server
];
# home-server
"home-server/hostKey.age".publicKeys = [ felschr home-server ];
"lldap/key-seed.age".publicKeys = [ felschr home-server ];
"lldap/jwt.age".publicKeys = [ felschr home-server ];
"lldap/password.age".publicKeys = [ felschr home-server ];
"authelia/jwt.age".publicKeys = [ felschr home-server ];
"authelia/session.age".publicKeys = [ felschr home-server ];
"authelia/storage.age".publicKeys = [ felschr home-server ];
"authelia/oidc-hmac.age".publicKeys = [ felschr home-server ];
"authelia/oidc-issuer.age".publicKeys = [ felschr home-server ];
"hass/secrets.age".publicKeys = [ felschr home-server ];
"esphome/password.age".publicKeys = [ felschr home-server ];
"dendrite/.env.age".publicKeys = [ felschr home-server ];
"dendrite/privateKey.age".publicKeys = [ felschr home-server ];
"home-server/hostKey.age".publicKeys = [
felschr
home-server
];
"lldap/key-seed.age".publicKeys = [
felschr
home-server
];
"lldap/jwt.age".publicKeys = [
felschr
home-server
];
"lldap/password.age".publicKeys = [
felschr
home-server
];
"authelia/jwt.age".publicKeys = [
felschr
home-server
];
"authelia/session.age".publicKeys = [
felschr
home-server
];
"authelia/storage.age".publicKeys = [
felschr
home-server
];
"authelia/oidc-hmac.age".publicKeys = [
felschr
home-server
];
"authelia/oidc-issuer.age".publicKeys = [
felschr
home-server
];
"hass/secrets.age".publicKeys = [
felschr
home-server
];
"esphome/password.age".publicKeys = [
felschr
home-server
];
"dendrite/.env.age".publicKeys = [
felschr
home-server
];
"dendrite/privateKey.age".publicKeys = [
felschr
home-server
];
}

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
domain = "auth.felschr.com";
@ -8,19 +13,25 @@ let
redis = config.services.redis.servers.authelia;
cfg = config.services.authelia.instances.main;
mkWebfinger = config: file:
pkgs.writeTextDir file (lib.generators.toJSON { } config);
mkWebfingers = { subject, ... }@config:
map (mkWebfinger config) [ subject (lib.escapeURL subject) ];
mkWebfinger = config: file: pkgs.writeTextDir file (lib.generators.toJSON { } config);
mkWebfingers =
{ subject, ... }@config:
map (mkWebfinger config) [
subject
(lib.escapeURL subject)
];
webfingerRoot = pkgs.symlinkJoin {
name = "felschr.com-webfinger";
paths = lib.flatten (builtins.map mkWebfingers [
paths = lib.flatten (
builtins.map mkWebfingers [
{
subject = "acct:me@felschr.com";
links = [{
links = [
{
rel = "http://openid.net/specs/connect/1.0/issuer";
href = "https://auth.felschr.com";
}];
}
];
}
{
subject = "acct:felschr@fosstodon.org";
@ -45,11 +56,13 @@ let
}
];
}
]);
]
);
};
smtpAccount = config.programs.msmtp.accounts.default;
in {
in
{
age.secrets.authelia-jwt = {
file = ../secrets/authelia/jwt.age;
owner = cfg.user;
@ -81,8 +94,7 @@ in {
oidcIssuerPrivateKeyFile = config.age.secrets.authelia-oidc-issuer.path;
};
environmentVariables = {
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE =
config.age.secrets.lldap-password.path;
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = config.age.secrets.lldap-password.path;
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = config.age.secrets.smtp.path;
};
settings = {
@ -105,8 +117,7 @@ in {
base_dn = "dc=felschr,dc=com";
username_attribute = "uid";
additional_users_dn = "ou=people";
users_filter =
"(&({username_attribute}={input})(objectClass=person))";
users_filter = "(&({username_attribute}={input})(objectClass=person))";
additional_groups_dn = "ou=groups";
groups_filter = "(member={dn})";
group_name_attribute = "cn";
@ -117,10 +128,12 @@ in {
};
access_control = {
default_policy = "deny";
rules = [{
rules = [
{
domain = [ "*.felschr.com" ];
policy = "two_factor";
}];
}
];
};
session = {
domain = "felschr.com";
@ -152,43 +165,59 @@ in {
{
id = "miniflux";
description = "Miniflux RSS";
secret =
"$pbkdf2-sha512$310000$uDoutefLT0wyfye.kBEyZw$tX7nwcRVo0LpPPS63Oh9MIeOLkdPRnXX/0JBwMd.aitFIxKDxU.rlywn/WqLVgpIllyFttMl5OnZzjMTbGKZ0A";
secret = "$pbkdf2-sha512$310000$uDoutefLT0wyfye.kBEyZw$tX7nwcRVo0LpPPS63Oh9MIeOLkdPRnXX/0JBwMd.aitFIxKDxU.rlywn/WqLVgpIllyFttMl5OnZzjMTbGKZ0A";
redirect_uris = [ "https://news.felschr.com/oauth2/oidc/callback" ];
scopes = [ "openid" "email" "profile" ];
scopes = [
"openid"
"email"
"profile"
];
}
{
id = "tailscale";
description = "Tailscale";
# The digest of "insecure_secret"
secret =
"$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng";
secret = "$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng";
redirect_uris = [ "https://login.tailscale.com/a/oauth_response" ];
scopes = [ "openid" "email" "profile" ];
scopes = [
"openid"
"email"
"profile"
];
}
{
id = "jellyfin";
description = "Jellyfin";
secret =
"$pbkdf2-sha512$310000$X7amOzLsURvZSwdLmSstlQ$/WK4lZ9KvEEuotOxUJkeTo0ZAa.rD7VVdkAPFcUQmr2WzkCXmXXJbYYy7vx0hc4nqLgBVeo8q/71R3rvfl9BFQ";
redirect_uris =
[ "https://media.felschr.com/sso/OID/redirect/Authelia" ];
scopes = [ "openid" "email" "profile" ];
secret = "$pbkdf2-sha512$310000$X7amOzLsURvZSwdLmSstlQ$/WK4lZ9KvEEuotOxUJkeTo0ZAa.rD7VVdkAPFcUQmr2WzkCXmXXJbYYy7vx0hc4nqLgBVeo8q/71R3rvfl9BFQ";
redirect_uris = [ "https://media.felschr.com/sso/OID/redirect/Authelia" ];
scopes = [
"openid"
"email"
"profile"
];
}
];
};
};
systemd.services.authelia.requires = [ "postgresql.service" "lldap.service" ];
systemd.services.authelia.after = [ "postgresql.service" "lldap.service" ];
systemd.services.authelia.requires = [
"postgresql.service"
"lldap.service"
];
systemd.services.authelia.after = [
"postgresql.service"
"lldap.service"
];
services.postgresql = {
enable = true;
ensureDatabases = [ cfg.user ];
ensureUsers = [{
ensureUsers = [
{
name = cfg.user;
ensureDBOwnership = true;
}];
}
];
};
services.redis.servers.authelia = {
@ -220,5 +249,8 @@ in {
};
};
users.users.${cfg.user}.extraGroups = [ "smtp" "ldap" ];
users.users.${cfg.user}.extraGroups = [
"smtp"
"ldap"
];
}

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let port = 8088;
in {
let
port = 8088;
in
{
age.secrets.calibre-web-htpasswd = {
file = ../secrets/calibre-web/htpasswd.age;
owner = config.services.nginx.user;

View file

@ -3,15 +3,16 @@
let
inherit (config.users.users.collabora-office) uid;
inherit (config.users.groups.collabora-office) gid;
in {
in
{
virtualisation.oci-containers.containers.collabora-office = {
image = "docker.io/collabora/code";
ports = [ "9980:9980" ];
environment = let
mkAlias = domain:
"https://" + (builtins.replaceStrings [ "." ] [ "\\." ] domain)
+ ":443";
in {
environment =
let
mkAlias = domain: "https://" + (builtins.replaceStrings [ "." ] [ "\\." ] domain) + ":443";
in
{
server_name = "office.felschr.com";
aliasgroup1 = mkAlias "office.felschr.com";
aliasgroup2 = mkAlias "cloud.felschr.com";
@ -50,5 +51,7 @@ in {
uid = 982;
};
users.groups.collabora-office = { gid = 982; };
users.groups.collabora-office = {
gid = 982;
};
}

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let etebaseHost = "etebase.felschr.com";
in {
let
etebaseHost = "etebase.felschr.com";
in
{
# TODO etebase-server doesn't support newer django version yet
nixpkgs.config.permittedInsecurePackages = [ "python3.11-django-3.2.25" ];
@ -14,8 +16,12 @@ in {
services.etebase-server.enable = true;
services.etebase-server.openFirewall = true;
services.etebase-server.settings = {
global = { secret_file = config.age.secrets.etebase-server.path; };
allowed_hosts = { allowed_host1 = etebaseHost; };
global = {
secret_file = config.age.secrets.etebase-server.path;
};
allowed_hosts = {
allowed_host1 = etebaseHost;
};
};
services.nginx = {

View file

@ -1,7 +1,14 @@
{ config, pkgs, inputs, ... }:
{
config,
pkgs,
inputs,
...
}:
let port = config.services.home-assistant.config.http.server_port;
in {
let
port = config.services.home-assistant.config.http.server_port;
in
{
disabledModules = [ "services/home-automation/home-assistant.nix" ];
imports = [
@ -29,8 +36,9 @@ in {
services.home-assistant = {
enable = true;
package = pkgs.unstable.home-assistant.overrideAttrs
(oldAttrs: { doInstallCheck = false; });
package = pkgs.unstable.home-assistant.overrideAttrs (oldAttrs: {
doInstallCheck = false;
});
openFirewall = true;
extraComponents = [
"default_config"
@ -53,8 +61,8 @@ in {
"local_todo"
"shopping_list"
];
extraPackages = ps:
with ps; [
extraPackages =
ps: with ps; [
pyqrcode
# HACS
@ -72,7 +80,10 @@ in {
external_url = "https://home.felschr.com";
internal_url = "http://192.168.1.102:8123";
media_dirs.media = "/media";
allowlist_external_dirs = [ "/tmp" "/media" ];
allowlist_external_dirs = [
"/tmp"
"/media"
];
};
default_config = { };
http = {
@ -86,8 +97,7 @@ in {
zha = {
database_path = "/var/lib/hass/zigbee.db";
enable_quirks = true;
custom_quirks_path =
"${config.services.home-assistant.configDir}/zha_quirks/";
custom_quirks_path = "${config.services.home-assistant.configDir}/zha_quirks/";
zigpy_config.ota = {
ikea_provider = true;
sonoff_provider = true;
@ -95,7 +105,9 @@ in {
};
};
zha_toolkit = { };
conversation = { intents = { }; };
conversation = {
intents = { };
};
};
# configWritable = true; # doesn't work atm
};

View file

@ -6,7 +6,8 @@ let
port = 6052;
inherit (config.services.home-assistant) configDir;
passwordFile = config.age.secrets.esphome-password.path;
in {
in
{
age.secrets.esphome-password.file = ../../secrets/esphome/password.age;
services.nginx = {

View file

@ -27,6 +27,5 @@
};
# needs access to /proc/cpuinfo
systemd.services."wyoming-faster-whisper-en".serviceConfig.ProcSubset =
lib.mkForce "all";
systemd.services."wyoming-faster-whisper-en".serviceConfig.ProcSubset = lib.mkForce "all";
}

View file

@ -50,7 +50,8 @@ let
"--label=io.containers.autoupdate=registry"
];
};
in {
in
{
age.secrets.immich-env.file = ../secrets/immich/.env.age;
age.secrets.immich-db-password.file = ../secrets/immich/db-password.age;
age.secrets.immich-typesense-env.file = ../secrets/immich/typesense/.env.age;
@ -59,10 +60,12 @@ in {
enable = true;
enableTCPIP = true;
ensureDatabases = [ dbname ];
ensureUsers = [{
ensureUsers = [
{
name = dbuser;
ensureDBOwnership = true;
}];
}
];
};
services.redis.servers.immich = {
@ -134,13 +137,25 @@ in {
systemd.services = {
"${ociBackend}-immich-server" = {
requires = [ "postgresql.service" "redis-immich.service" ];
after = [ "postgresql.service" "redis-immich.service" ];
requires = [
"postgresql.service"
"redis-immich.service"
];
after = [
"postgresql.service"
"redis-immich.service"
];
};
"${ociBackend}-immich-microservices" = {
requires = [ "postgresql.service" "redis-immich.service" ];
after = [ "postgresql.service" "redis-immich.service" ];
requires = [
"postgresql.service"
"redis-immich.service"
];
after = [
"postgresql.service"
"redis-immich.service"
];
};
"${ociBackend}-immich-machine-learning" = {
@ -166,5 +181,7 @@ in {
uid = 980;
};
users.groups.immich = { gid = 977; };
users.groups.immich = {
gid = 977;
};
}

View file

@ -6,14 +6,16 @@
services.jellyfin.openFirewall = true;
# for hardware acceleration
users.users.${config.services.jellyfin.user}.extraGroups =
[ "video" "render" ];
users.users.${config.services.jellyfin.user}.extraGroups = [
"video"
"render"
];
systemd.services.jellyfin.serviceConfig = {
DeviceAllow = lib.mkForce [ "/dev/dri/renderD128" ];
};
services.nginx = {
virtualHosts."media.felschr.com" = {
services.nginx.virtualHosts = {
"media.felschr.com" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://localhost:8096";

View file

@ -4,7 +4,8 @@ let
domain = "ldap.felschr.com";
cfg = config.services.lldap;
port = cfg.settings.http_port;
in {
in
{
age.secrets.lldap-key-seed.file = ../secrets/lldap/key-seed.age;
age.secrets.lldap-jwt.file = ../secrets/lldap/jwt.age;
age.secrets.lldap-password = {
@ -34,13 +35,15 @@ in {
];
};
services.nginx = {
virtualHosts.${domain} = {
services.nginx.virtualHosts = {
${domain} = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://[::1]:${toString port}";
};
};
users.groups.ldap = { gid = 979; };
users.groups.ldap = {
gid = 979;
};
}

View file

@ -25,5 +25,7 @@
};
};
users.groups.smtp = { gid = 983; };
users.groups.smtp = {
gid = 983;
};
}

View file

@ -15,7 +15,8 @@ let
allow_key_sharing = true;
delete_keys.delete_outdated_inbound = false;
};
in {
in
{
# Mautrix-signal settings
services.signald.enable = true;
systemd.services.matrix-as-signal = {

View file

@ -3,14 +3,19 @@
let
server_name = "felschr.com";
domain = "matrix.${server_name}";
in {
in
{
services.matrix-conduit = {
enable = true;
package = pkgs.unstable.matrix-conduit;
settings.global = {
inherit server_name;
database_backend = "rocksdb";
trusted_servers = [ "matrix.org" "libera.chat" "nixos.org" ];
trusted_servers = [
"matrix.org"
"libera.chat"
"nixos.org"
];
};
};
@ -18,9 +23,7 @@ in {
enableACME = true;
forceSSL = true;
locations."/_matrix/" = {
proxyPass = "http://[::1]:${
toString config.services.matrix-conduit.settings.global.port
}";
proxyPass = "http://[::1]:${toString config.services.matrix-conduit.settings.global.port}";
proxyWebsockets = true;
extraConfig = ''
proxy_buffering off;
@ -31,14 +34,18 @@ in {
services.nginx.virtualHosts.${server_name} = {
enableACME = true;
forceSSL = true;
locations = let
server = { "m.server" = "${domain}:443"; };
locations =
let
server = {
"m.server" = "${domain}:443";
};
client = {
"m.homeserver"."base_url" = "https://${domain}";
"org.matrix.msc3575.proxy"."url" = "https://${domain}";
"m.identity_server"."base_url" = "https://vector.im";
};
in {
in
{
"= /.well-known/matrix/server".extraConfig = ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';

View file

@ -1,5 +1,9 @@
{ ... }:
{
imports = [ ./conduit.nix ./element.nix ./appservices.nix ];
imports = [
./conduit.nix
./element.nix
./appservices.nix
];
}

View file

@ -9,7 +9,8 @@ let
max_idle_conns = 2;
conn_max_lifetime = -1;
};
in {
in
{
age.secrets.dendrite-private-key = {
file = ../../secrets/dendrite/privateKey.age;
mode = "755";
@ -41,7 +42,8 @@ in {
"msc2946" # space summaries
];
federation_api.key_perspectives = [{
federation_api.key_perspectives = [
{
server_name = "matrix.org";
keys = [
{
@ -53,7 +55,8 @@ in {
public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ";
}
];
}];
}
];
global = {
inherit server_name;
@ -69,10 +72,12 @@ in {
};
services.postgresql = {
ensureUsers = [{
ensureUsers = [
{
name = "dendrite";
ensureDBOwnership = true;
}];
}
];
ensureDatabases = [ "dendrite" ];
};
@ -82,14 +87,18 @@ in {
${server_name} = {
enableACME = true;
forceSSL = true;
locations = let
server = { "m.server" = "${domain}:443"; };
locations =
let
server = {
"m.server" = "${domain}:443";
};
client = {
"m.homeserver"."base_url" = "https://${domain}";
"org.matrix.msc3575.proxy"."url" = "https://${domain}";
"m.identity_server"."base_url" = "https://vector.im";
};
in {
in
{
"= /.well-known/matrix/server".extraConfig = ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
@ -108,8 +117,7 @@ in {
"/".extraConfig = ''
return 404;
'';
"/_matrix".proxyPass =
"http://127.0.0.1:${toString config.services.dendrite.httpPort}";
"/_matrix".proxyPass = "http://127.0.0.1:${toString config.services.dendrite.httpPort}";
};
};
};

View file

@ -3,7 +3,8 @@
let
inherit (config.services.matrix-conduit.settings.global) server_name;
matrix_host = "matrix.${server_name}";
in {
in
{
services.nginx.virtualHosts."element.felschr.com" = {
forceSSL = true;
enableACME = true;

View file

@ -3,7 +3,8 @@
let
domain = "news.felschr.com";
port = 8002;
in {
in
{
age.secrets.miniflux.file = ../secrets/miniflux/admin.age;
age.secrets.miniflux-oidc = {
file = ../secrets/miniflux/oidc.age;
@ -26,8 +27,7 @@ in {
};
};
systemd.services.miniflux.serviceConfig.SupplementaryGroups =
[ "miniflux-secrets" ];
systemd.services.miniflux.serviceConfig.SupplementaryGroups = [ "miniflux-secrets" ];
services.nginx = {
virtualHosts."news.felschr.com" = {

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let host = "cloud.felschr.com";
in {
let
host = "cloud.felschr.com";
in
{
age.secrets.nextcloud-admin = {
file = ../secrets/nextcloud/admin.age;
owner = "nextcloud";
@ -31,10 +33,12 @@ in {
services.postgresql = with config.services.nextcloud.config; {
enable = true;
ensureDatabases = [ dbname ];
ensureUsers = [{
ensureUsers = [
{
name = dbuser;
ensureDBOwnership = true;
}];
}
];
};
# ensure that postgres is running *before* running the setup

View file

@ -1,7 +1,9 @@
{ config, pkgs, ... }:
let port = 28981;
in {
let
port = 28981;
in
{
age.secrets.paperless = {
file = ../secrets/paperless.age;
owner = config.services.paperless.user;
@ -28,5 +30,4 @@ in {
};
};
};
}

View file

@ -3,5 +3,8 @@
{
# for reader used with AusweisApp2
services.pcscd.enable = true;
services.pcscd.plugins = with pkgs; [ ccid pcsc-cyberjack ];
services.pcscd.plugins = with pkgs; [
ccid
pcsc-cyberjack
];
}

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
{
imports = [ ../../modules/restic.nix ];

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
# using the restic cli:
# load credentials into shell by adding B2 secrets to .env (see .env.example).
@ -6,15 +11,21 @@
with lib;
with builtins;
let resticLib = import ./lib.nix { inherit config lib pkgs; };
in {
let
resticLib = import ./lib.nix { inherit config lib pkgs; };
in
{
imports = [ ./common.nix ];
environment.systemPackages = with pkgs; [ restic ];
services.restic.backups.full = resticLib.resticConfig {
name = "home-pc";
paths = [ "/etc/nixos" "/var/lib" "/home" ];
paths = [
"/etc/nixos"
"/var/lib"
"/home"
];
# inspiration: https://github.com/rubo77/rsync-homedir-excludes
ignorePatterns = [
"/var/lib/systemd"

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
# using the restic cli:
# load credentials into shell by adding B2 secrets to .env (see .env.example).
@ -6,15 +11,21 @@
with lib;
with builtins;
let resticLib = import ./lib.nix { inherit config lib pkgs; };
in {
let
resticLib = import ./lib.nix { inherit config lib pkgs; };
in
{
imports = [ ./common.nix ];
environment.systemPackages = with pkgs; [ restic ];
services.restic.backups.full = resticLib.resticConfig {
name = "home-server";
paths = [ "/etc/nixos" "/var/lib" "/home" ];
paths = [
"/etc/nixos"
"/var/lib"
"/home"
];
ignorePatterns = [
"/var/lib/systemd"
"/var/lib/containers"

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
# using the restic cli:
# load credentials into shell by adding B2 secrets to .env (see .env.example).
@ -6,11 +11,21 @@
with lib;
with builtins;
let hasAnyAttr = flip (attrset: any (flip hasAttr attrset));
in {
resticConfig = args@{ name, paths ? [ ], ignorePatterns ? [ ]
, extraBackupArgs ? [ ], extraPruneOpts ? [ ], ... }:
assert !hasAnyAttr [
let
hasAnyAttr = flip (attrset: any (flip hasAttr attrset));
in
{
resticConfig =
args@{
name,
paths ? [ ],
ignorePatterns ? [ ],
extraBackupArgs ? [ ],
extraPruneOpts ? [ ],
...
}:
assert
!hasAnyAttr [
"initialize"
"repository"
"s3CredentialsFile"
@ -25,10 +40,11 @@ in {
passwordFile = config.age.secrets.restic-password.path;
timerConfig.OnCalendar = "daily";
inherit paths;
extraBackupArgs = let
ignoreFile = builtins.toFile "ignore"
(foldl (a: b: a + "\n" + b) "" ignorePatterns);
in [ "--exclude-file=${ignoreFile}" ] ++ extraBackupArgs;
extraBackupArgs =
let
ignoreFile = builtins.toFile "ignore" (foldl (a: b: a + "\n" + b) "" ignorePatterns);
in
[ "--exclude-file=${ignoreFile}" ] ++ extraBackupArgs;
pruneOpts = [
"--keep-daily 7"
"--keep-weekly 4"
@ -38,7 +54,8 @@ in {
"--max-unused 10%"
"--repack-cacheable-only"
] ++ extraPruneOpts;
} // (removeAttrs args [
}
// (removeAttrs args [
"name"
"paths"
"ignorePatterns"

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
{
age.secrets.samba.file = ../../secrets/samba.age;

View file

@ -1,7 +1,19 @@
{ config, pkgs, ... }:
{
imports = [ ./zram.nix ./i18n.nix ./nix.nix ./networking.nix ./hardened.nix ];
imports = [
./zram.nix
./i18n.nix
./nix.nix
./networking.nix
./hardened.nix
];
environment.systemPackages = with pkgs; [ wget curl openssl rage neovim ];
environment.systemPackages = with pkgs; [
wget
curl
openssl
rage
neovim
];
}

View file

@ -1,5 +1,11 @@
{ config, pkgs, ... }:
{
imports = [ ./common.nix ./fonts.nix ./sound.nix ./vpn.nix ./printing ];
imports = [
./common.nix
./fonts.nix
./sound.nix
./vpn.nix
./printing
];
}

View file

@ -10,9 +10,21 @@
fira-code
];
fonts.fontconfig.defaultFonts = {
serif = [ "Noto Serif" "emoji" ];
sansSerif = [ "Noto Sans" "emoji" ];
monospace = [ "Fira Code" "emoji" ];
emoji = [ "Noto Color Emoji" "Symbols Nerd Font Mono" ];
serif = [
"Noto Serif"
"emoji"
];
sansSerif = [
"Noto Sans"
"emoji"
];
monospace = [
"Fira Code"
"emoji"
];
emoji = [
"Noto Color Emoji"
"Symbols Nerd Font Mono"
];
};
}

View file

@ -14,9 +14,8 @@
programs.steam.enable = true;
programs.steam.package = pkgs.steam.override {
# https://github.com/NixOS/nixpkgs/blob/master/pkgs/games/steam/fhsenv.nix
extraLibraries = pkgs:
with pkgs;
[
extraLibraries =
pkgs: with pkgs; [
libxcrypt-legacy # Life Is Strange
];
};

View file

@ -1,4 +1,10 @@
{ config, modulesPath, pkgs, lib, ... }:
{
config,
modulesPath,
pkgs,
lib,
...
}:
{
imports = [ "${modulesPath}/profiles/hardened.nix" ];

View file

@ -13,7 +13,10 @@
};
supportedLocales = [ "all" ];
inputMethod.enabled = "ibus";
inputMethod.ibus.engines = with pkgs.ibus-engines; [ uniemoji mozc ];
inputMethod.ibus.engines = with pkgs.ibus-engines; [
uniemoji
mozc
];
};
time.timeZone = "Europe/Berlin";

View file

@ -1,7 +1,10 @@
{ config, ... }:
{
networking.nameservers = [ "127.0.0.1" "::1" ];
networking.nameservers = [
"127.0.0.1"
"::1"
];
networking.networkmanager.dns = "systemd-resolved";
services.dnsmasq.enable = false;
@ -13,6 +16,9 @@
services.nextdns = {
enable = true;
arguments = [ "-config" "b8e2f7" ];
arguments = [
"-config"
"b8e2f7"
];
};
}

View file

@ -3,7 +3,8 @@
let
flakes = lib.filterAttrs (name: value: value ? outputs) inputs;
inherit (inputs.self.outputs) nixConfig;
in {
in
{
nix.gc = {
automatic = true;
dates = "04:00";
@ -21,7 +22,13 @@ in {
enable = true;
dates = "03:00";
flake = "/etc/nixos";
flags = with lib;
flatten (mapAttrsToList (n: _: [ "--update-input" n ]) flakes);
flags =
with lib;
flatten (
mapAttrsToList (n: _: [
"--update-input"
n
]) flakes
);
};
}

View file

@ -5,13 +5,14 @@
hardware.printers = {
ensureDefaultPrinter = "Brother_HL-L2370DN";
ensurePrinters = [{
ensurePrinters = [
{
name = "Brother_HL-L2370DN";
description = "Brother HL-L2370DN";
deviceUri =
"dnssd://Brother%20HL-L2370DN%20series._ipp._tcp.local/?uuid=e3248000-80ce-11db-8000-b422007e1490";
deviceUri = "dnssd://Brother%20HL-L2370DN%20series._ipp._tcp.local/?uuid=e3248000-80ce-11db-8000-b422007e1490";
model = "drv:///brlaser.drv/brl2370d.ppd";
# model = "everywhere";
}];
}
];
};
}

View file

@ -1,7 +1,10 @@
{ ... }:
{
imports = [ ./common.nix ./vpn.nix ];
imports = [
./common.nix
./vpn.nix
];
# use xserver without display manager
services.xserver.displayManager.startx.enable = true;

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
{
hardware.pulseaudio.enable = false;
@ -16,7 +21,12 @@
"bluez5.enable-sbc-xq" = true;
"bluez5.enable-msbc" = true;
"bluez5.enable-hw-volume" = true;
"bluez5.roles" = [ "hsp_hs" "hsp_ag" "hfp_hf" "hfp_ag" ];
"bluez5.roles" = [
"hsp_hs"
"hsp_ag"
"hfp_hf"
"hfp_ag"
];
};
};
}

View file

@ -1,11 +1,17 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.tailscale;
tailscaleInterface = cfg.interfaceName;
inherit (config.networking) hostName;
tailnetHost = "${hostName}.tail05275.ts.net";
in {
in
{
networking.wireguard.enable = true;
networking.firewall.trustedInterfaces = [ tailscaleInterface ];
@ -22,8 +28,7 @@ in {
];
};
systemd.services.tailscaled.serviceConfig.Environment =
[ "TS_DEBUG_FIREWALL_MODE=auto" ];
systemd.services.tailscaled.serviceConfig.Environment = [ "TS_DEBUG_FIREWALL_MODE=auto" ];
# call taiscale up without --auth-key
systemd.services.tailscaled-autoconnect = lib.mkIf (cfg.authKeyFile == null) {
@ -31,7 +36,8 @@ in {
wants = [ "tailscaled.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot";
script = ''
script =
''
status=$(${config.systemd.package}/bin/systemctl show -P StatusText tailscaled.service)
if [[ $status != Connected* ]]; then
${cfg.package}/bin/tailscale up
@ -41,7 +47,8 @@ in {
${cfg.package}/bin/tailscale up ${lib.escapeShellArgs cfg.extraUpFlags}
${cfg.package}/bin/tailscale cert ${tailnetHost}
'' + lib.optionalString config.services.nginx.enable ''
''
+ lib.optionalString config.services.nginx.enable ''
chown nginx:nginx /var/lib/tailscale/certs/${tailnetHost}.{key,crt}
'';
};

View file

@ -1,6 +1,12 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
with lib; {
with lib;
{
zramSwap.enable = mkDefault true;
zramSwap.memoryPercent = mkDefault 100;
zramSwap.memoryMax = mkDefault (16 * 1024 * 1024 * 1024);

View file

@ -6,7 +6,8 @@ let
dotnetRoot = "${dotnet-combined}";
dotnetSdk = "${dotnet-combined}/sdk";
dotnetBinary = "${dotnetRoot}/bin/dotnet";
in {
in
{
home.packages = [ dotnet-combined ];
home.sessionVariables = {

View file

@ -28,14 +28,18 @@
users.users."containers" = {
isSystemUser = true;
group = "containers";
subUidRanges = [{
subUidRanges = [
{
startUid = 60100000;
count = 60000000;
}];
subGidRanges = [{
}
];
subGidRanges = [
{
startGid = 60100000;
count = 60000000;
}];
}
];
};
users.groups.containers = { };

View file

@ -1,7 +1,10 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ virt-manager gnome.gnome-boxes ];
environment.systemPackages = with pkgs; [
virt-manager
gnome.gnome-boxes
];
environment.sessionVariables.LIBVIRT_DEFAULT_URI = [ "qemu:///system" ];