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, ... }: { pkgs, ... }:
{ {
environment.systemPackages = with pkgs; environment.systemPackages =
with gnomeExtensions; [ with pkgs;
with gnomeExtensions;
[
gnome.dconf-editor gnome.dconf-editor
gnome.gnome-tweaks gnome.gnome-tweaks
gnome.zenity 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; } { inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ "x86_64-linux" "aarch64-linux" ]; systems = [
"x86_64-linux"
"aarch64-linux"
];
imports = [ imports = [
./pkgs/flake-module.nix ./pkgs/flake-module.nix
./lib/flake-module.nix ./lib/flake-module.nix
@ -102,27 +111,33 @@ rec {
mullvad-browser = import ./home/modules/firefox/mullvad-browser.nix; mullvad-browser = import ./home/modules/firefox/mullvad-browser.nix;
}; };
}; };
perSystem = { system, config, pkgs, ... }: { perSystem =
{
system,
config,
pkgs,
...
}:
{
_module.args.pkgs = import nixpkgs { _module.args.pkgs = import nixpkgs {
inherit system; inherit system;
config.allowUnfree = true; config.allowUnfree = true;
}; };
devShells.default = devShells.default = pkgs.mkShell { inherit (config.checks.pre-commit) shellHook; };
pkgs.mkShell { inherit (config.checks.pre-commit) shellHook; };
checks = { checks = {
pre-commit = inputs.pre-commit-hooks.lib.${system}.run { pre-commit = inputs.pre-commit-hooks.lib.${system}.run {
src = ./.; src = ./.;
hooks = { hooks = {
nixfmt.enable = true; nixfmt.enable = true;
nixfmt.package = pkgs.nixfmt-classic; nixfmt.package = pkgs.nixfmt-rfc-style;
shellcheck.enable = true; shellcheck.enable = true;
}; };
}; };
}; };
formatter = pkgs.nixfmt-classic; formatter = pkgs.nixfmt-rfc-style;
}; };
}; };
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,9 @@
{ inputs, pkgs, lib, ... }: {
inputs,
pkgs,
lib,
...
}:
let let
firefox-addons = inputs.firefox-addons.packages.${pkgs.system}; firefox-addons = inputs.firefox-addons.packages.${pkgs.system};
@ -42,7 +47,8 @@ let
libredirect libredirect
zotero-connector zotero-connector
]; ];
in { in
{
imports = [ ../modules/firefox/mullvad-browser.nix ]; imports = [ ../modules/firefox/mullvad-browser.nix ];
programs.mullvad-browser = { programs.mullvad-browser = {
@ -57,8 +63,13 @@ in {
work = { work = {
id = 1; id = 1;
settings = commonSettings; settings = commonSettings;
extensions = commonExtensions extensions =
++ (with firefox-addons; [ bitwarden react-devtools reduxdevtools ]); 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"; down = "j";
up = "k"; up = "k";
right = "l"; right = "l";
in { in
{
dconf.settings = with lib.hm.gvariant; { dconf.settings = with lib.hm.gvariant; {
"org/gnome/shell" = { "org/gnome/shell" = {
disable-user-extensions = false; disable-user-extensions = false;
@ -30,15 +31,31 @@ in {
show-title = false; show-title = false;
active-hint = false; active-hint = false;
}; };
"org/gnome/desktop/interface" = { color-scheme = "prefer-dark"; }; "org/gnome/desktop/interface" = {
"org/gnome/desktop/sound" = { theme-name = "freedesktop"; }; color-scheme = "prefer-dark";
};
"org/gnome/desktop/sound" = {
theme-name = "freedesktop";
};
"org/gnome/desktop/input-sources" = { "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" ]; xkb-options = [ "compose:ralt" ];
}; };
"org/gnome/desktop/app-folders" = { "org/gnome/desktop/app-folders" = {
folder-children = [ "Office" "Utilities" ]; folder-children = [
"Office"
"Utilities"
];
}; };
"org/gnome/desktop/app-folders/folders/Office" = { "org/gnome/desktop/app-folders/folders/Office" = {
name = "Office"; name = "Office";
@ -48,11 +65,17 @@ in {
"org/gnome/desktop/app-folders/folders/Utilities" = { "org/gnome/desktop/app-folders/folders/Utilities" = {
name = "Utilities"; name = "Utilities";
translate = true; translate = true;
categories = [ "Utility" "X-GNOME-Utilities" "System" ]; categories = [
"Utility"
"X-GNOME-Utilities"
"System"
];
}; };
# key bindings for pop-shell # key bindings for pop-shell
"org/gnome/mutter/wayland/keybindings" = { restore-shortcuts = [ ]; }; "org/gnome/mutter/wayland/keybindings" = {
restore-shortcuts = [ ];
};
"org/gnome/shell/keybindings" = { "org/gnome/shell/keybindings" = {
open-application-menu = [ ]; open-application-menu = [ ];
toggle-message-tray = [ "<Super>v" ]; toggle-message-tray = [ "<Super>v" ];
@ -67,16 +90,25 @@ in {
toggle-fullscreen = [ "<Super>f" ]; toggle-fullscreen = [ "<Super>f" ];
toggle-on-all-workspaces = [ "<Super>p" ]; toggle-on-all-workspaces = [ "<Super>p" ];
switch-to-workspace-left = switch-to-workspace-left = [
[ "<Primary><Super>Left" "<Primary><Super>${left}" ]; "<Primary><Super>Left"
switch-to-workspace-right = "<Primary><Super>${left}"
[ "<Primary><Super>Right" "<Primary><Super>${right}" ]; ];
switch-to-workspace-right = [
"<Primary><Super>Right"
"<Primary><Super>${right}"
];
switch-to-workspace-down = [ ]; switch-to-workspace-down = [ ];
switch-to-workspace-up = [ ]; switch-to-workspace-up = [ ];
move-to-workspace-left = [ "<Shift><Super>Left" "<Shift><Super>${left}" ]; move-to-workspace-left = [
move-to-workspace-right = "<Shift><Super>Left"
[ "<Shift><Super>Right" "<Shift><Super>${right}" ]; "<Shift><Super>${left}"
];
move-to-workspace-right = [
"<Shift><Super>Right"
"<Shift><Super>${right}"
];
move-to-workspace-down = [ ]; move-to-workspace-down = [ ];
move-to-workspace-up = [ ]; move-to-workspace-up = [ ];
@ -91,7 +123,10 @@ in {
}; };
"org/gnome/settings-daemon/plugins/color" = { "org/gnome/settings-daemon/plugins/color" = {
night-light-enabled = true; 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; night-light-temperature = mkUint32 3700;
}; };
"org/gnome/settings-daemon/plugins/media-keys" = { "org/gnome/settings-daemon/plugins/media-keys" = {

View file

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

View file

@ -1,9 +1,17 @@
{ config, pkgs, ... }: { 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"; home.sessionVariables.EDITOR = "hx";

View file

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

View file

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

View file

@ -13,11 +13,11 @@ let
>"$out/share/applications/element-desktop.desktop" >"$out/share/applications/element-desktop.desktop"
''; '';
}; };
in { in
{
home.packages = [ element-desktop ]; home.packages = [ element-desktop ];
xdg.configFile."autostart/element-desktop.desktop".text = xdg.configFile."autostart/element-desktop.desktop".text =
builtins.replaceStrings [ "Exec=element-desktop" ] builtins.replaceStrings [ "Exec=element-desktop" ] [ "Exec=element-desktop --hidden" ]
[ "Exec=element-desktop --hidden" ] (builtins.readFile (builtins.readFile "${element-desktop}/share/applications/element-desktop.desktop");
"${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; programs.gpg.enable = true;
services.gpg-agent = { services.gpg-agent = {

View file

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

View file

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

View file

@ -1,7 +1,13 @@
{ pkgs, ... }: { 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 # 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 = { home.file = {
proton-ge = let version = "GE-Proton7-54"; proton-ge =
in { let
version = "GE-Proton7-54";
in
{
recursive = true; recursive = true;
source = builtins.fetchTarball { source = builtins.fetchTarball {
url = url = "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/${version}/${version}.tar.gz";
"https://github.com/GloriousEggroll/proton-ge-custom/releases/download/${version}/${version}.tar.gz";
sha256 = "1iy14s1d48wxnnmw45jh5w2yadkrvwip8k91xljwg066aprb00vi"; sha256 = "1iy14s1d48wxnnmw45jh5w2yadkrvwip8k91xljwg066aprb00vi";
}; };
target = ".local/share/Steam/compatibilitytools.d/Proton-${version}/"; target = ".local/share/Steam/compatibilitytools.d/Proton-${version}/";

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,14 +1,21 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with pkgs; with pkgs;
with lib; { with lib;
{
# kitty terminal # kitty terminal
programs.kitty = { programs.kitty = {
enable = true; enable = true;
keybindings = let keybindings =
vimKittyBinding = bind: let
''kitten pass_keys.py neighboring_window ${bind} "^.* - nvim$"''; vimKittyBinding = bind: ''kitten pass_keys.py neighboring_window ${bind} "^.* - nvim$"'';
in { in
{
"ctrl+h" = vimKittyBinding "left ctrl+h"; "ctrl+h" = vimKittyBinding "left ctrl+h";
"ctrl+j" = vimKittyBinding "bottom ctrl+j"; "ctrl+j" = vimKittyBinding "bottom ctrl+j";
"ctrl+k" = vimKittyBinding "top ctrl+k"; "ctrl+k" = vimKittyBinding "top ctrl+k";
@ -18,13 +25,10 @@ with lib; {
allow_remote_control = "yes"; allow_remote_control = "yes";
# single_instance = "yes"; # single_instance = "yes";
listen_on = "unix:@mykitty"; listen_on = "unix:@mykitty";
scrollback_pager = '' 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" -'';
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 = xdg.configFile."kitty/pass_keys.py".source = "${vimPlugins.nvim-kitty-navigator}/kitty/pass_keys.py";
"${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/neighboring_window.py".source =
"${vimPlugins.nvim-kitty-navigator}/kitty/neighboring_window.py";
} }

View file

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

View file

@ -7,7 +7,9 @@
programs.zellij.settings = { programs.zellij.settings = {
default_layout = "compact"; # or default default_layout = "compact"; # or default
default_mode = "locked"; default_mode = "locked";
ui.pane_frames = { hide_session_name = true; }; ui.pane_frames = {
hide_session_name = true;
};
plugins = { plugins = {
tab-bar.path = "tab-bar"; tab-bar.path = "tab-bar";
status-bar.path = "status-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, ... }: { config, pkgs, ... }:
let shellAliases = import ./aliases.nix; let
in { shellAliases = import ./aliases.nix;
in
{
programs.zsh = { programs.zsh = {
enable = true; enable = true;
# TODO is being renamed again in later 24.05 release # TODO is being renamed again in later 24.05 release
@ -24,8 +26,7 @@ in {
{ {
name = "zsh-history-substring-search"; name = "zsh-history-substring-search";
src = zsh-history-substring-search; src = zsh-history-substring-search;
file = file = "share/zsh-history-substring-search/zsh-history-substring-search.zsh";
"share/zsh-history-substring-search/zsh-history-substring-search.zsh";
} }
]; ];
initExtra = '' initExtra = ''

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
with lib; with lib;
@ -21,7 +26,8 @@ let
$(systemctl status --full "$1") $(systemctl status --full "$1")
ERRMAIL ERRMAIL
''; '';
in { in
{
options = { options = {
systemd.notify = { systemd.notify = {
enable = mkOption { enable = mkOption {
@ -31,7 +37,10 @@ in {
}; };
method = mkOption { method = mkOption {
type = types.enum [ "libnotify" "email" ]; type = types.enum [
"libnotify"
"email"
];
default = "libnotify"; default = "libnotify";
description = "The method for sending notifications."; description = "The method for sending notifications.";
}; };
@ -45,20 +54,19 @@ in {
email.mailTo = mkOption { email.mailTo = mkOption {
type = types.str; type = types.str;
default = null; default = null;
description = description = "Email address to which the service status will be mailed.";
"Email address to which the service status will be mailed.";
}; };
email.mailFrom = mkOption { email.mailFrom = mkOption {
type = types.str; type = types.str;
default = null; default = null;
description = description = "Email address from which the service status will be mailed.";
"Email address from which the service status will be mailed.";
}; };
}; };
systemd.services = mkOption { systemd.services = mkOption {
type = with types; type =
with types;
attrsOf (submodule { attrsOf (submodule {
config.onFailure = optional cfg.enable "notify@%n.service"; config.onFailure = optional cfg.enable "notify@%n.service";
}); });
@ -72,15 +80,16 @@ in {
message = "You need to specify a user"; message = "You need to specify a user";
} }
{ {
assertion = cfg.method != "email" assertion = cfg.method != "email" || (cfg.email.mailTo != null && cfg.email.mailFrom != null);
|| (cfg.email.mailTo != null && cfg.email.mailFrom != null);
message = "You need to specify a sender and a receiver"; message = "You need to specify a sender and a receiver";
} }
]; ];
systemd.services."notify@" = { systemd.services."notify@" =
{
onFailure = lib.mkForce [ ]; onFailure = lib.mkForce [ ];
} // optionalAttrs (cfg.method == "libnotify") { }
// optionalAttrs (cfg.method == "libnotify") {
description = "Desktop notifications for %i service failure"; description = "Desktop notifications for %i service failure";
environment = { environment = {
DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/${ DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/${
@ -97,7 +106,8 @@ in {
Type = "oneshot"; Type = "oneshot";
User = cfg.libnotify.user; User = cfg.libnotify.user;
}; };
} // optionalAttrs (cfg.method == "email") { }
// optionalAttrs (cfg.method == "email") {
description = "E-Mail notifications for %i service failure"; description = "E-Mail notifications for %i service failure";
serviceConfig = { serviceConfig = {
ExecStart = "${sendmail} %i"; 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) # maintained fork of brlaser with newer drivers (including Brother HL-L2370DN)
stdenv.mkDerivation (finalAttrs: { stdenv.mkDerivation (finalAttrs: {
@ -13,9 +21,15 @@ stdenv.mkDerivation (finalAttrs: {
}; };
nativeBuildInputs = [ cmake ]; 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; { meta = with lib; {
description = "A CUPS driver for Brother laser printers"; description = "A CUPS driver for Brother laser printers";
@ -100,7 +114,6 @@ stdenv.mkDerivation (finalAttrs: {
license = licenses.gpl2; license = licenses.gpl2;
platforms = platforms.linux; platforms = platforms.linux;
maintainers = with maintainers; [ felschr ]; maintainers = with maintainers; [ felschr ];
changelog = changelog = "https://github.com/Owl-Maintain/brlaser/releases/tag/${finalAttrs.src.rStijnDWev}";
"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 let
version = "2.17.01"; version = "2.17.01";
srcs = { srcs = {
x86_64-linux = fetchurl { x86_64-linux = fetchurl {
url = url = "https://deconz.dresden-elektronik.de/ubuntu/beta/deconz-${version}-qt5.deb";
"https://deconz.dresden-elektronik.de/ubuntu/beta/deconz-${version}-qt5.deb";
sha256 = "sha256-c2G3oOnSXlivO9KXRBZIe2DEuq7vPVlNDKF6T/pZLps="; sha256 = "sha256-c2G3oOnSXlivO9KXRBZIe2DEuq7vPVlNDKF6T/pZLps=";
}; };
aarch64-linux = fetchurl { aarch64-linux = fetchurl {
url = url = "https://deconz.dresden-elektronik.de/debian/stable/deconz_${version}-debian-buster-stable_arm64.deb";
"https://deconz.dresden-elektronik.de/debian/stable/deconz_${version}-debian-buster-stable_arm64.deb";
sha256 = "sha256-zuy4e9bzcRqDeXP6mfzZLCDK/3we25LH6xktnO6HXps="; sha256 = "sha256-zuy4e9bzcRqDeXP6mfzZLCDK/3we25LH6xktnO6HXps=";
}; };
}; };
in
in mkDerivation { mkDerivation {
pname = "deCONZ"; pname = "deCONZ";
inherit version; inherit version;
src = srcs.${stdenv.hostPlatform.system}; 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 ."; unpackPhase = "dpkg-deb -x $src .";
@ -38,18 +57,24 @@ in mkDerivation {
wrapProgram "$out/bin/deCONZ" \ wrapProgram "$out/bin/deCONZ" \
--set LD_PRELOAD "${libredirect}/lib/libredirect.so" \ --set LD_PRELOAD "${libredirect}/lib/libredirect.so" \
--set NIX_REDIRECTS "/usr/share=$out/share:/usr/bin=$out/bin" \ --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; { meta = with lib; {
description = description = "Manage ZigBee network with ConBee, ConBee II or RaspBee hardware";
"Manage ZigBee network with ConBee, ConBee II or RaspBee hardware";
# 2019-08-19: The homepage links to old software that doesn't even work -- # 2019-08-19: The homepage links to old software that doesn't even work --
# it fails to detect ConBee2. # it fails to detect ConBee2.
homepage = homepage = "https://www.dresden-elektronik.de/funktechnik/products/software/pc-software/deconz/?L=1";
"https://www.dresden-elektronik.de/funktechnik/products/software/pc-software/deconz/?L=1";
license = licenses.unfree; license = licenses.unfree;
platforms = [ "x86_64-linux" "aarch64-linux" ]; platforms = [
"x86_64-linux"
"aarch64-linux"
];
maintainers = with maintainers; [ felschr ]; maintainers = with maintainers; [ felschr ];
}; };
} }

View file

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

View file

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

View file

@ -1,45 +1,143 @@
let let
# age-specific key in ~/.ssh/id_ed25519: `ssh-keygen -t ed25519` # age-specific key in ~/.ssh/id_ed25519: `ssh-keygen -t ed25519`
felschr = felschr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbQpMo1JOGk59Rzl6pVoOcMHOoqezph+aIlEXZP4rBu";
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbQpMo1JOGk59Rzl6pVoOcMHOoqezph+aIlEXZP4rBu";
users = [ felschr ]; users = [ felschr ];
# `ssh-keygen -t ed25519 -N "" -f /etc/secrets/initrd/ssh_host_ed25519_key` # `ssh-keygen -t ed25519 -N "" -f /etc/secrets/initrd/ssh_host_ed25519_key`
home-pc = home-pc = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBFTQvIcSdhEKl/Kq+pcS/cPCyyZ1ygj+djfuaXzaRMx";
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBFTQvIcSdhEKl/Kq+pcS/cPCyyZ1ygj+djfuaXzaRMx"; home-server = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILO+OLPr8zdOMYyKtm98AFJai7zbaxw7JhVWgOwu7K3C";
home-server = pilot1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHEucfNzPbDRdDjTaLG3PzN4lAzDAq3QUkaLvaRjjsCY";
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILO+OLPr8zdOMYyKtm98AFJai7zbaxw7JhVWgOwu7K3C"; systems = [
pilot1 = home-pc
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHEucfNzPbDRdDjTaLG3PzN4lAzDAq3QUkaLvaRjjsCY"; home-server
systems = [ home-pc home-server pilot1 ]; pilot1
in { ];
"restic/b2.age".publicKeys = [ felschr home-pc home-server pilot1 ]; in
"restic/password.age".publicKeys = [ felschr home-pc home-server pilot1 ]; {
"smtp.age".publicKeys = [ felschr home-pc home-server ]; "restic/b2.age".publicKeys = [
"samba.age".publicKeys = [ felschr home-pc home-server ]; felschr
"cloudflare.age".publicKeys = [ felschr home-pc home-server ]; home-pc
"etebase-server.age".publicKeys = [ felschr home-pc home-server ]; home-server
"calibre-web/htpasswd.age".publicKeys = [ felschr home-pc home-server ]; pilot1
"miniflux/admin.age".publicKeys = [ felschr home-pc home-server ]; ];
"miniflux/oidc.age".publicKeys = [ felschr home-pc home-server ]; "restic/password.age".publicKeys = [
"paperless.age".publicKeys = [ felschr home-pc home-server ]; felschr
"nextcloud/admin.age".publicKeys = [ felschr home-pc home-server ]; home-pc
"immich/.env.age".publicKeys = [ felschr home-pc home-server ]; home-server
"immich/db-password.age".publicKeys = [ felschr home-pc home-server ]; pilot1
"immich/typesense/.env.age".publicKeys = [ felschr home-pc home-server ]; ];
"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
"home-server/hostKey.age".publicKeys = [ felschr home-server ]; "home-server/hostKey.age".publicKeys = [
"lldap/key-seed.age".publicKeys = [ felschr home-server ]; felschr
"lldap/jwt.age".publicKeys = [ felschr home-server ]; home-server
"lldap/password.age".publicKeys = [ felschr home-server ]; ];
"authelia/jwt.age".publicKeys = [ felschr home-server ]; "lldap/key-seed.age".publicKeys = [
"authelia/session.age".publicKeys = [ felschr home-server ]; felschr
"authelia/storage.age".publicKeys = [ felschr home-server ]; home-server
"authelia/oidc-hmac.age".publicKeys = [ felschr home-server ]; ];
"authelia/oidc-issuer.age".publicKeys = [ felschr home-server ]; "lldap/jwt.age".publicKeys = [
"hass/secrets.age".publicKeys = [ felschr home-server ]; felschr
"esphome/password.age".publicKeys = [ felschr home-server ]; home-server
"dendrite/.env.age".publicKeys = [ felschr home-server ]; ];
"dendrite/privateKey.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 let
domain = "auth.felschr.com"; domain = "auth.felschr.com";
@ -8,19 +13,25 @@ let
redis = config.services.redis.servers.authelia; redis = config.services.redis.servers.authelia;
cfg = config.services.authelia.instances.main; cfg = config.services.authelia.instances.main;
mkWebfinger = config: file: mkWebfinger = config: file: pkgs.writeTextDir file (lib.generators.toJSON { } config);
pkgs.writeTextDir file (lib.generators.toJSON { } config); mkWebfingers =
mkWebfingers = { subject, ... }@config: { subject, ... }@config:
map (mkWebfinger config) [ subject (lib.escapeURL subject) ]; map (mkWebfinger config) [
subject
(lib.escapeURL subject)
];
webfingerRoot = pkgs.symlinkJoin { webfingerRoot = pkgs.symlinkJoin {
name = "felschr.com-webfinger"; name = "felschr.com-webfinger";
paths = lib.flatten (builtins.map mkWebfingers [ paths = lib.flatten (
builtins.map mkWebfingers [
{ {
subject = "acct:me@felschr.com"; subject = "acct:me@felschr.com";
links = [{ links = [
{
rel = "http://openid.net/specs/connect/1.0/issuer"; rel = "http://openid.net/specs/connect/1.0/issuer";
href = "https://auth.felschr.com"; href = "https://auth.felschr.com";
}]; }
];
} }
{ {
subject = "acct:felschr@fosstodon.org"; subject = "acct:felschr@fosstodon.org";
@ -45,11 +56,13 @@ let
} }
]; ];
} }
]); ]
);
}; };
smtpAccount = config.programs.msmtp.accounts.default; smtpAccount = config.programs.msmtp.accounts.default;
in { in
{
age.secrets.authelia-jwt = { age.secrets.authelia-jwt = {
file = ../secrets/authelia/jwt.age; file = ../secrets/authelia/jwt.age;
owner = cfg.user; owner = cfg.user;
@ -81,8 +94,7 @@ in {
oidcIssuerPrivateKeyFile = config.age.secrets.authelia-oidc-issuer.path; oidcIssuerPrivateKeyFile = config.age.secrets.authelia-oidc-issuer.path;
}; };
environmentVariables = { environmentVariables = {
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = config.age.secrets.lldap-password.path;
config.age.secrets.lldap-password.path;
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = config.age.secrets.smtp.path; AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = config.age.secrets.smtp.path;
}; };
settings = { settings = {
@ -105,8 +117,7 @@ in {
base_dn = "dc=felschr,dc=com"; base_dn = "dc=felschr,dc=com";
username_attribute = "uid"; username_attribute = "uid";
additional_users_dn = "ou=people"; additional_users_dn = "ou=people";
users_filter = users_filter = "(&({username_attribute}={input})(objectClass=person))";
"(&({username_attribute}={input})(objectClass=person))";
additional_groups_dn = "ou=groups"; additional_groups_dn = "ou=groups";
groups_filter = "(member={dn})"; groups_filter = "(member={dn})";
group_name_attribute = "cn"; group_name_attribute = "cn";
@ -117,10 +128,12 @@ in {
}; };
access_control = { access_control = {
default_policy = "deny"; default_policy = "deny";
rules = [{ rules = [
{
domain = [ "*.felschr.com" ]; domain = [ "*.felschr.com" ];
policy = "two_factor"; policy = "two_factor";
}]; }
];
}; };
session = { session = {
domain = "felschr.com"; domain = "felschr.com";
@ -152,43 +165,59 @@ in {
{ {
id = "miniflux"; id = "miniflux";
description = "Miniflux RSS"; description = "Miniflux RSS";
secret = secret = "$pbkdf2-sha512$310000$uDoutefLT0wyfye.kBEyZw$tX7nwcRVo0LpPPS63Oh9MIeOLkdPRnXX/0JBwMd.aitFIxKDxU.rlywn/WqLVgpIllyFttMl5OnZzjMTbGKZ0A";
"$pbkdf2-sha512$310000$uDoutefLT0wyfye.kBEyZw$tX7nwcRVo0LpPPS63Oh9MIeOLkdPRnXX/0JBwMd.aitFIxKDxU.rlywn/WqLVgpIllyFttMl5OnZzjMTbGKZ0A";
redirect_uris = [ "https://news.felschr.com/oauth2/oidc/callback" ]; redirect_uris = [ "https://news.felschr.com/oauth2/oidc/callback" ];
scopes = [ "openid" "email" "profile" ]; scopes = [
"openid"
"email"
"profile"
];
} }
{ {
id = "tailscale"; id = "tailscale";
description = "Tailscale"; description = "Tailscale";
# The digest of "insecure_secret" # The digest of "insecure_secret"
secret = secret = "$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng";
"$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng";
redirect_uris = [ "https://login.tailscale.com/a/oauth_response" ]; redirect_uris = [ "https://login.tailscale.com/a/oauth_response" ];
scopes = [ "openid" "email" "profile" ]; scopes = [
"openid"
"email"
"profile"
];
} }
{ {
id = "jellyfin"; id = "jellyfin";
description = "Jellyfin"; description = "Jellyfin";
secret = secret = "$pbkdf2-sha512$310000$X7amOzLsURvZSwdLmSstlQ$/WK4lZ9KvEEuotOxUJkeTo0ZAa.rD7VVdkAPFcUQmr2WzkCXmXXJbYYy7vx0hc4nqLgBVeo8q/71R3rvfl9BFQ";
"$pbkdf2-sha512$310000$X7amOzLsURvZSwdLmSstlQ$/WK4lZ9KvEEuotOxUJkeTo0ZAa.rD7VVdkAPFcUQmr2WzkCXmXXJbYYy7vx0hc4nqLgBVeo8q/71R3rvfl9BFQ"; redirect_uris = [ "https://media.felschr.com/sso/OID/redirect/Authelia" ];
redirect_uris = scopes = [
[ "https://media.felschr.com/sso/OID/redirect/Authelia" ]; "openid"
scopes = [ "openid" "email" "profile" ]; "email"
"profile"
];
} }
]; ];
}; };
}; };
systemd.services.authelia.requires = [ "postgresql.service" "lldap.service" ]; systemd.services.authelia.requires = [
systemd.services.authelia.after = [ "postgresql.service" "lldap.service" ]; "postgresql.service"
"lldap.service"
];
systemd.services.authelia.after = [
"postgresql.service"
"lldap.service"
];
services.postgresql = { services.postgresql = {
enable = true; enable = true;
ensureDatabases = [ cfg.user ]; ensureDatabases = [ cfg.user ];
ensureUsers = [{ ensureUsers = [
{
name = cfg.user; name = cfg.user;
ensureDBOwnership = true; ensureDBOwnership = true;
}]; }
];
}; };
services.redis.servers.authelia = { 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, ... }: { config, pkgs, ... }:
let port = 8088; let
in { port = 8088;
in
{
age.secrets.calibre-web-htpasswd = { age.secrets.calibre-web-htpasswd = {
file = ../secrets/calibre-web/htpasswd.age; file = ../secrets/calibre-web/htpasswd.age;
owner = config.services.nginx.user; owner = config.services.nginx.user;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,8 @@ let
domain = "ldap.felschr.com"; domain = "ldap.felschr.com";
cfg = config.services.lldap; cfg = config.services.lldap;
port = cfg.settings.http_port; port = cfg.settings.http_port;
in { in
{
age.secrets.lldap-key-seed.file = ../secrets/lldap/key-seed.age; age.secrets.lldap-key-seed.file = ../secrets/lldap/key-seed.age;
age.secrets.lldap-jwt.file = ../secrets/lldap/jwt.age; age.secrets.lldap-jwt.file = ../secrets/lldap/jwt.age;
age.secrets.lldap-password = { age.secrets.lldap-password = {
@ -34,13 +35,15 @@ in {
]; ];
}; };
services.nginx = { services.nginx.virtualHosts = {
virtualHosts.${domain} = { ${domain} = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
locations."/".proxyPass = "http://[::1]:${toString port}"; 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; allow_key_sharing = true;
delete_keys.delete_outdated_inbound = false; delete_keys.delete_outdated_inbound = false;
}; };
in { in
{
# Mautrix-signal settings # Mautrix-signal settings
services.signald.enable = true; services.signald.enable = true;
systemd.services.matrix-as-signal = { systemd.services.matrix-as-signal = {

View file

@ -3,14 +3,19 @@
let let
server_name = "felschr.com"; server_name = "felschr.com";
domain = "matrix.${server_name}"; domain = "matrix.${server_name}";
in { in
{
services.matrix-conduit = { services.matrix-conduit = {
enable = true; enable = true;
package = pkgs.unstable.matrix-conduit; package = pkgs.unstable.matrix-conduit;
settings.global = { settings.global = {
inherit server_name; inherit server_name;
database_backend = "rocksdb"; 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; enableACME = true;
forceSSL = true; forceSSL = true;
locations."/_matrix/" = { locations."/_matrix/" = {
proxyPass = "http://[::1]:${ proxyPass = "http://[::1]:${toString config.services.matrix-conduit.settings.global.port}";
toString config.services.matrix-conduit.settings.global.port
}";
proxyWebsockets = true; proxyWebsockets = true;
extraConfig = '' extraConfig = ''
proxy_buffering off; proxy_buffering off;
@ -31,14 +34,18 @@ in {
services.nginx.virtualHosts.${server_name} = { services.nginx.virtualHosts.${server_name} = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
locations = let locations =
server = { "m.server" = "${domain}:443"; }; let
server = {
"m.server" = "${domain}:443";
};
client = { client = {
"m.homeserver"."base_url" = "https://${domain}"; "m.homeserver"."base_url" = "https://${domain}";
"org.matrix.msc3575.proxy"."url" = "https://${domain}"; "org.matrix.msc3575.proxy"."url" = "https://${domain}";
"m.identity_server"."base_url" = "https://vector.im"; "m.identity_server"."base_url" = "https://vector.im";
}; };
in { in
{
"= /.well-known/matrix/server".extraConfig = '' "= /.well-known/matrix/server".extraConfig = ''
add_header Content-Type application/json; add_header Content-Type application/json;
return 200 '${builtins.toJSON server}'; 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; max_idle_conns = 2;
conn_max_lifetime = -1; conn_max_lifetime = -1;
}; };
in { in
{
age.secrets.dendrite-private-key = { age.secrets.dendrite-private-key = {
file = ../../secrets/dendrite/privateKey.age; file = ../../secrets/dendrite/privateKey.age;
mode = "755"; mode = "755";
@ -41,7 +42,8 @@ in {
"msc2946" # space summaries "msc2946" # space summaries
]; ];
federation_api.key_perspectives = [{ federation_api.key_perspectives = [
{
server_name = "matrix.org"; server_name = "matrix.org";
keys = [ keys = [
{ {
@ -53,7 +55,8 @@ in {
public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ"; public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ";
} }
]; ];
}]; }
];
global = { global = {
inherit server_name; inherit server_name;
@ -69,10 +72,12 @@ in {
}; };
services.postgresql = { services.postgresql = {
ensureUsers = [{ ensureUsers = [
{
name = "dendrite"; name = "dendrite";
ensureDBOwnership = true; ensureDBOwnership = true;
}]; }
];
ensureDatabases = [ "dendrite" ]; ensureDatabases = [ "dendrite" ];
}; };
@ -82,14 +87,18 @@ in {
${server_name} = { ${server_name} = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
locations = let locations =
server = { "m.server" = "${domain}:443"; }; let
server = {
"m.server" = "${domain}:443";
};
client = { client = {
"m.homeserver"."base_url" = "https://${domain}"; "m.homeserver"."base_url" = "https://${domain}";
"org.matrix.msc3575.proxy"."url" = "https://${domain}"; "org.matrix.msc3575.proxy"."url" = "https://${domain}";
"m.identity_server"."base_url" = "https://vector.im"; "m.identity_server"."base_url" = "https://vector.im";
}; };
in { in
{
"= /.well-known/matrix/server".extraConfig = '' "= /.well-known/matrix/server".extraConfig = ''
add_header Content-Type application/json; add_header Content-Type application/json;
return 200 '${builtins.toJSON server}'; return 200 '${builtins.toJSON server}';
@ -108,8 +117,7 @@ in {
"/".extraConfig = '' "/".extraConfig = ''
return 404; return 404;
''; '';
"/_matrix".proxyPass = "/_matrix".proxyPass = "http://127.0.0.1:${toString config.services.dendrite.httpPort}";
"http://127.0.0.1:${toString config.services.dendrite.httpPort}";
}; };
}; };
}; };

View file

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

View file

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

View file

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

View file

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

View file

@ -3,5 +3,8 @@
{ {
# for reader used with AusweisApp2 # for reader used with AusweisApp2
services.pcscd.enable = true; 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 ]; imports = [ ../../modules/restic.nix ];

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,19 @@
{ config, pkgs, ... }: { 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, ... }: { 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 fira-code
]; ];
fonts.fontconfig.defaultFonts = { fonts.fontconfig.defaultFonts = {
serif = [ "Noto Serif" "emoji" ]; serif = [
sansSerif = [ "Noto Sans" "emoji" ]; "Noto Serif"
monospace = [ "Fira Code" "emoji" ]; "emoji"
emoji = [ "Noto Color Emoji" "Symbols Nerd Font Mono" ]; ];
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.enable = true;
programs.steam.package = pkgs.steam.override { programs.steam.package = pkgs.steam.override {
# https://github.com/NixOS/nixpkgs/blob/master/pkgs/games/steam/fhsenv.nix # https://github.com/NixOS/nixpkgs/blob/master/pkgs/games/steam/fhsenv.nix
extraLibraries = pkgs: extraLibraries =
with pkgs; pkgs: with pkgs; [
[
libxcrypt-legacy # Life Is Strange libxcrypt-legacy # Life Is Strange
]; ];
}; };

View file

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

View file

@ -13,7 +13,10 @@
}; };
supportedLocales = [ "all" ]; supportedLocales = [ "all" ];
inputMethod.enabled = "ibus"; 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"; time.timeZone = "Europe/Berlin";

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
{ {
hardware.pulseaudio.enable = false; hardware.pulseaudio.enable = false;
@ -16,7 +21,12 @@
"bluez5.enable-sbc-xq" = true; "bluez5.enable-sbc-xq" = true;
"bluez5.enable-msbc" = true; "bluez5.enable-msbc" = true;
"bluez5.enable-hw-volume" = 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 let
cfg = config.services.tailscale; cfg = config.services.tailscale;
tailscaleInterface = cfg.interfaceName; tailscaleInterface = cfg.interfaceName;
inherit (config.networking) hostName; inherit (config.networking) hostName;
tailnetHost = "${hostName}.tail05275.ts.net"; tailnetHost = "${hostName}.tail05275.ts.net";
in { in
{
networking.wireguard.enable = true; networking.wireguard.enable = true;
networking.firewall.trustedInterfaces = [ tailscaleInterface ]; networking.firewall.trustedInterfaces = [ tailscaleInterface ];
@ -22,8 +28,7 @@ in {
]; ];
}; };
systemd.services.tailscaled.serviceConfig.Environment = systemd.services.tailscaled.serviceConfig.Environment = [ "TS_DEBUG_FIREWALL_MODE=auto" ];
[ "TS_DEBUG_FIREWALL_MODE=auto" ];
# call taiscale up without --auth-key # call taiscale up without --auth-key
systemd.services.tailscaled-autoconnect = lib.mkIf (cfg.authKeyFile == null) { systemd.services.tailscaled-autoconnect = lib.mkIf (cfg.authKeyFile == null) {
@ -31,7 +36,8 @@ in {
wants = [ "tailscaled.service" ]; wants = [ "tailscaled.service" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot"; serviceConfig.Type = "oneshot";
script = '' script =
''
status=$(${config.systemd.package}/bin/systemctl show -P StatusText tailscaled.service) status=$(${config.systemd.package}/bin/systemctl show -P StatusText tailscaled.service)
if [[ $status != Connected* ]]; then if [[ $status != Connected* ]]; then
${cfg.package}/bin/tailscale up ${cfg.package}/bin/tailscale up
@ -41,7 +47,8 @@ in {
${cfg.package}/bin/tailscale up ${lib.escapeShellArgs cfg.extraUpFlags} ${cfg.package}/bin/tailscale up ${lib.escapeShellArgs cfg.extraUpFlags}
${cfg.package}/bin/tailscale cert ${tailnetHost} ${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} 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.enable = mkDefault true;
zramSwap.memoryPercent = mkDefault 100; zramSwap.memoryPercent = mkDefault 100;
zramSwap.memoryMax = mkDefault (16 * 1024 * 1024 * 1024); zramSwap.memoryMax = mkDefault (16 * 1024 * 1024 * 1024);

View file

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

View file

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

View file

@ -1,7 +1,10 @@
{ pkgs, ... }: { 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" ]; environment.sessionVariables.LIBVIRT_DEFAULT_URI = [ "qemu:///system" ];