Compare commits

...

12 commits

30 changed files with 871 additions and 164 deletions

View file

@ -1,8 +1,16 @@
{ config, pkgs, ... }:
{
config,
pkgs,
lib,
...
}:
{
# Enable the X11 windowing system.
services.xserver.enable = true;
services.xserver.xkb.layout = "gb";
services.xserver.xkb.options = "eurosign:e";
services.xserver.xkb.options = lib.concatStringsSep "," [
"eurosign:e"
"compose:ralt"
];
}

42
flake.lock generated
View file

@ -72,11 +72,11 @@
]
},
"locked": {
"lastModified": 1727447169,
"narHash": "sha256-3KyjMPUKHkiWhwR91J1YchF6zb6gvckCAY1jOE+ne0U=",
"lastModified": 1749105467,
"narHash": "sha256-hXh76y/wDl15almBcqvjryB50B0BaiXJKk20f314RoE=",
"owner": "serokell",
"repo": "deploy-rs",
"rev": "aa07eb05537d4cd025e2310397a6adcedfe72c76",
"rev": "6bc76b872374845ba9d645a2f012b764fecd765f",
"type": "github"
},
"original": {
@ -129,11 +129,11 @@
},
"locked": {
"dir": "pkgs/firefox-addons",
"lastModified": 1749009805,
"narHash": "sha256-eRv4m89aPJvIAX9mZQcJM+l3sYG+OJvcLsiHvAvXalg=",
"lastModified": 1749143092,
"narHash": "sha256-IrVT37SUU8/B3X53rwEzDrx3djGLIfa8tmsyqVJxpR4=",
"owner": "rycee",
"repo": "nur-expressions",
"rev": "622c38d004cdded682d9a5ab7323181dc6efb0c1",
"rev": "d62d10f250ca6a37cbbe05a35a0e1e7ae3b4b5c2",
"type": "gitlab"
},
"original": {
@ -146,11 +146,11 @@
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"lastModified": 1733328505,
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"type": "github"
},
"original": {
@ -299,11 +299,11 @@
]
},
"locked": {
"lastModified": 1748665073,
"narHash": "sha256-RMhjnPKWtCoIIHiuR9QKD7xfsKb3agxzMfJY8V9MOew=",
"lastModified": 1749154018,
"narHash": "sha256-gjN3j7joRvT3a8Zgcylnd4NFsnXeDBumqiu4HmY1RIg=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "282e1e029cb6ab4811114fc85110613d72771dea",
"rev": "7aae0ee71a17b19708b93b3ed448a1a0952bf111",
"type": "github"
},
"original": {
@ -353,11 +353,11 @@
},
"nixos-hardware": {
"locked": {
"lastModified": 1748942041,
"narHash": "sha256-HEu2gTct7nY0tAPRgBtqYepallryBKR1U8B4v2zEEqA=",
"lastModified": 1749195551,
"narHash": "sha256-W5GKQHgunda/OP9sbKENBZhMBDNu2QahoIPwnsF6CeM=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "fc7c4714125cfaa19b048e8aaf86b9c53e04d853",
"rev": "4602f7e1d3f197b3cb540d5accf5669121629628",
"type": "github"
},
"original": {
@ -368,11 +368,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1749024892,
"narHash": "sha256-OGcDEz60TXQC+gVz5sdtgGJdKVYr6rwdzQKuZAJQpCA=",
"lastModified": 1749086602,
"narHash": "sha256-DJcgJMekoxVesl9kKjfLPix2Nbr42i7cpEHJiTnBUwU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8f1b52b04f2cb6e5ead50bd28d76528a2f0380ef",
"rev": "4792576cb003c994bd7cc1edada3129def20b27d",
"type": "github"
},
"original": {
@ -423,11 +423,11 @@
"systems": "systems_3"
},
"locked": {
"lastModified": 1749025503,
"narHash": "sha256-Me3mk/wLz4msOQAASCaf2+mQizje1Q37rgNfExJse6M=",
"lastModified": 1749198233,
"narHash": "sha256-5YEDpGF46A5pnHX52ALqmFMlAB1orI0SnZhI6LQiw9w=",
"owner": "astro",
"repo": "nix-openwrt-imagebuilder",
"rev": "1b157ee2f34fc67f365a62c5a4fca63ba86040c6",
"rev": "7eb902386112129be892e06cd5a51ffdfeb2517e",
"type": "github"
},
"original": {

View file

@ -104,6 +104,7 @@ rec {
flakeDefaults = import ./modules/flakeDefaults.nix;
systemdNotify = import ./modules/systemdNotify.nix;
inadyn = import ./modules/inadyn.nix;
nginx-authelia = import ./modules/nginx-authelia.nix;
};
};
perSystem =

View file

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

View file

@ -1,58 +0,0 @@
{ config, lib, ... }:
{
boot.initrd.availableKernelModules = [
"xhci_pci"
"ahci"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
"sdhci_pci"
"rtsx_usb_sdmmc"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.kernelParams = [ "i915.enable_guc=3" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/70f03d67-e248-42f6-a204-c02e4f180531";
fsType = "btrfs";
options = [
"subvol=@"
"compress-force=zstd:1"
"noatime"
];
};
boot.initrd.luks.devices."enc".device = "/dev/disk/by-uuid/d3b12d0e-7e8e-4130-9a8f-680abcdc9682";
fileSystems."/home" = {
device = "/dev/disk/by-uuid/70f03d67-e248-42f6-a204-c02e4f180531";
fsType = "btrfs";
options = [
"subvol=@home"
"compress-force=zstd:1"
"noatime"
];
};
fileSystems."/.snapshots" = {
device = "/dev/disk/by-uuid/70f03d67-e248-42f6-a204-c02e4f180531";
fsType = "btrfs";
options = [
"subvol=@snapshots"
"compress-force=zstd:1"
"noatime"
];
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/95FC-D4E5";
fsType = "vfat";
};
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

5
home/base.nix Normal file
View file

@ -0,0 +1,5 @@
_:
{
imports = [ ./nixpkgs.nix ];
}

32
home/desktop/cosmic.nix Normal file
View file

@ -0,0 +1,32 @@
_:
{
imports = [ ../modules/cosmic ];
programs.cosmic = {
enable = true;
settings = {
"com.system76.CosmicTk".v1 = {
icon_theme = "Cosmic";
};
"com.system76.CosmicFiles".v1 = {
tab.show_hidden = true;
favorites = [
"Home"
"Documents"
"Downloads"
"Music"
"Pictures"
"Videos"
''Path("/home/felschr/dev")''
''Path("/home/felschr/dev/work")''
''Path("/home/felschr/dev/mscs")''
''Path("/home/felschr/Documents/CU Boulder MSCS")''
];
};
"com.system76.CosmicAppletAudio".v1 = {
show_media_controls_in_top_panel = true;
};
};
};
}

View file

@ -4,6 +4,7 @@
imports = [
./gtk.nix
./gnome.nix
./cosmic.nix
./mimeapps.nix
];
}

View file

@ -7,6 +7,7 @@
{
imports = [
./base.nix
./shell
./editors/lsp.nix
./editors/helix

View file

@ -3,6 +3,7 @@
with pkgs;
{
imports = [
./base.nix
./shell
./tailscale.nix
./editors

View file

@ -2,6 +2,7 @@
{
imports = [
./base.nix
./shell
./tailscale.nix
./editors

View file

@ -16,15 +16,12 @@ let
pkgs = self.pkgsFor system;
extraSpecialArgs = { inherit inputs; };
modules =
(with self.homeModules; [ nixpkgs ])
++ [
{
home.username = user;
home.homeDirectory = "/home/${user}";
}
]
++ modules;
modules = [
{
home.username = user;
home.homeDirectory = "/home/${user}";
}
] ++ modules;
};
in
{
@ -32,11 +29,11 @@ in
flake = {
homeModules = {
nixpkgs = import ./modules/nixpkgs.nix;
git = import ./modules/git.nix;
firefox = import ./modules/firefox/firefox.nix;
tor-browser = import ./modules/firefox/tor-browser.nix;
mullvad-browser = import ./modules/firefox/mullvad-browser.nix;
cosmic = import ./modules/cosmic;
# users
felschr = import ./felschr.nix;

View file

@ -0,0 +1,53 @@
{ config, lib, ... }:
# Based on:
# https://github.com/tristanbeedell/home-manager/tree/efa4d272f6c2b14d4a3b67b0b1e4b38ae46e5588/modules/programs/cosmic
let
cfg = config.programs.cosmic;
ron = import ./ron.nix { inherit lib; };
in
{
imports = [ ./settings.nix ];
options.programs.cosmic = {
enable = lib.mkEnableOption "COSMIC Desktop";
settings = lib.mkOption {
default = { };
type = lib.types.submodule {
freeformType = lib.types.submodule {
freeformType = lib.types.attrsOf lib.types.anything;
};
};
description = ''
An attrset of explicit settings for COSMIC apps, using their full config path.
'';
example = lib.literalExpression ''
{
"com.system76.CosmicPanel.Dock".v1 = {
opacity = 0.8;
};
};
'';
};
};
config = lib.mkIf cfg.enable {
xdg.configFile = lib.concatMapAttrs (
component:
lib.concatMapAttrs (
version:
lib.concatMapAttrs (
option: value:
lib.optionalAttrs (value != null) {
"cosmic/${component}/${version}/${option}" = {
enable = true;
text = ron.serialise value;
};
}
)
)
) cfg.settings;
};
}

129
home/modules/cosmic/ron.nix Normal file
View file

@ -0,0 +1,129 @@
{ lib }:
let
inherit (lib)
filterAttrs
concatStrings
concatStringsSep
mapAttrsToList
concatLists
foldlAttrs
boolToString
;
inherit (builtins) typeOf toString stringLength;
# list -> array
array = a: "[${concatStringsSep "," (map serialise a)}]";
# attrset -> hashmap
_assoc = a: mapAttrsToList (name: val: "${name}: ${val},") a;
assoc = a: ''
{
${concatStringsSep "\n " (concatLists (map _assoc a))}
}
'';
stringArray = a: array (map toQuotedString a);
tuple = a: "(${concatStringsSep "," (map serialise a)})";
enum =
s:
if isNull s.value then
s.name
else
concatStrings [
s.name
"("
(serialise s.value)
")"
];
option =
value:
if isNull value then
"None"
else
enum {
name = "Some";
inherit value;
};
# attrset -> struct
_struct_kv =
k: v:
if v == null then
""
else
(concatStringsSep ": " [
k
(serialise v)
]);
_struct_concat =
s:
foldlAttrs (
acc: k: v:
if stringLength acc > 0 then
concatStringsSep ", " [
acc
(_struct_kv k v)
]
else
_struct_kv k v
) "" s;
_struct_filt = s: _struct_concat (filterAttrs (k: v: v != null) s);
struct = s: "(${_struct_filt s})";
toQuotedString = s: ''"${toString s}"'';
# this is an enum, but use string interp to make sure it's put in the nix store
path = p: ''Path("${p}")'';
# attrset for best-effort serialisation of nix types
# currently, no way to differentiate between enums and structs
serialisers = {
int = toString;
float = toString;
bool = boolToString;
# can't assume quoted string, sometimes it's a Rust enum
string = toString;
path = path;
null = _: "None";
set = struct;
list = array;
};
serialise = v: serialisers.${typeOf v} v;
in
{
inherit
array
assoc
tuple
stringArray
serialise
option
path
struct
toQuotedString
enum
;
# some handy wrapper types, to reduce transformation effort in modules producing Ron
types = {
# string type, but implicitly wraps in quote marks for usage in Ron
str = (lib.types.coercedTo lib.types.str toQuotedString lib.types.str) // {
description = "string";
};
# takes a (non submodule) type, and implicitly wraps in Rust Option<> type
option =
type:
let
wantedType = lib.types.nullOr (type);
in
(lib.types.coercedTo (wantedType) (option) lib.types.str)
// {
description = wantedType.description;
};
};
}

View file

@ -0,0 +1,108 @@
{ lib, ... }:
# Known definitions for settings options
let
inherit (lib) types;
ron = import ./ron.nix { inherit lib; };
cosmic = {
types = import ./types.nix { inherit lib ron; };
};
in
{
options.programs.cosmic.settings = {
# https://github.com/pop-os/libcosmic/blob/1fce5df160f595d1b1e5a8e2bb2a24775419f82d/src/config/mod.rs#L85
"com.system76.CosmicTk".v1 = {
apply_theme_global = lib.mkOption {
type = types.nullOr types.bool;
default = null;
description = "Apply the theme to other toolkits.";
};
show_minimize = lib.mkOption {
type = types.nullOr types.bool;
default = null;
description = "Show minimize button in window header.";
};
show_maximize = lib.mkOption {
type = types.nullOr types.bool;
default = null;
description = "Show maximize button in window header.";
};
icon_theme = lib.mkOption {
type = types.nullOr ron.types.str;
default = null;
description = "Preferred icon theme.";
};
header_size = lib.mkOption {
type = types.nullOr cosmic.types.density;
default = null;
description = "Density of CSD/SSD header bars.";
};
interface_density = lib.mkOption {
type = types.nullOr cosmic.types.density;
default = null;
description = "Interface density.";
};
interface_font = lib.mkOption {
type = types.nullOr cosmic.types.font_config;
default = null;
description = "Interface font family";
};
monospace_font = lib.mkOption {
type = types.nullOr cosmic.types.font_config;
default = null;
description = "Mono font family";
};
};
# https://github.com/pop-os/cosmic-files/blob/1a5a4501ee501b3155295cbfccc1c992b5ec9c01/src/config.rs#L106
"com.system76.CosmicFiles".v1 = {
app_theme = lib.mkOption {
type = types.nullOr cosmic.types.theme;
default = null;
description = "";
};
desktop = lib.mkOption {
type = types.nullOr cosmic.types.files_desktop;
default = null;
description = "";
};
favorites = lib.mkOption {
type = types.nullOr cosmic.types.files_favorites;
default = null;
description = "";
};
show_details = lib.mkOption {
type = types.nullOr types.bool;
default = null;
description = "";
};
tab = lib.mkOption {
type = types.nullOr cosmic.types.files_tab_config;
default = null;
description = "";
};
type_to_search = lib.mkOption {
type = types.nullOr (
types.enum [
"Recursive"
"EnterPath"
]
);
default = null;
description = "";
};
};
# https://github.com/pop-os/cosmic-applets/blob/b4b465712218be8d26b6772a382d19f4c3ff97f8/cosmic-applet-audio/src/config.rs#L9
"com.system76.CosmicAppletAudio".v1 = {
show_media_controls_in_top_panel = lib.mkOption {
type = types.nullOr types.bool;
default = null;
description = "";
};
};
# ...
};
}

View file

@ -0,0 +1,145 @@
{ lib, ron }:
let
inherit (lib) types;
in
lib.fix (self: {
theme = types.enum [
"Dark"
"Light"
"System"
];
density = types.enum [
"Compact"
"Spacious"
"Standard"
];
weight = types.enum [
"Thin"
"ExtraLight"
"Light"
"Normal"
"Medium"
"Semibold"
"Bold"
"ExtraBold"
"Black"
];
stretch = types.enum [
"UltraCondensed"
"ExtraCondensed"
"Condensed"
"SemiCondensed"
"Normal"
"SemiExpanded"
"Expanded"
"ExtraExpanded"
"UltraExpanded"
];
style = types.enum [
"Normal"
"Italic"
"Oblique"
];
# libcosmic
font_config = types.submodule {
options = {
family = lib.mkOption {
type = ron.types.str;
default = null;
};
weight = lib.mkOption {
type = types.nullOr self.weight;
default = null;
};
stretch = lib.mkOption {
type = types.nullOr self.stretch;
default = null;
};
style = lib.mkOption {
type = types.nullOr self.style;
default = null;
};
};
};
# Files
files_desktop = types.submodule {
options = {
grid_spacing = lib.mkOption {
type = types.nullOr types.int;
default = null;
};
icon_size = lib.mkOption {
type = types.nullOr types.int;
default = null;
};
show_content = lib.mkOption {
type = types.nullOr types.bool;
default = null;
};
show_mounted_drives = lib.mkOption {
type = types.nullOr types.bool;
default = null;
};
show_trash = lib.mkOption {
type = types.nullOr types.bool;
default = null;
};
};
};
files_favorites = types.listOf (
types.oneOf [
(types.enum [
"Home"
"Documents"
"Downloads"
"Music"
"Pictures"
"Videos"
])
(lib.types.strMatching ''^Path\(".*"\)$'')
]
);
files_view = types.enum [
"Grid"
"List"
];
files_icon_sizes = types.submodule {
options = {
list = lib.mkOption {
type = types.nullOr types.int;
default = null;
};
grid = lib.mkOption {
type = types.nullOr types.int;
default = null;
};
};
};
files_tab_config = types.submodule {
options = {
view = lib.mkOption {
type = types.nullOr self.files_view;
default = null;
};
folders_first = lib.mkOption {
type = types.nullOr types.bool;
default = null;
};
show_hidden = lib.mkOption {
type = types.nullOr types.bool;
default = null;
};
icon_sizes = lib.mkOption {
type = types.nullOr self.files_icon_sizes;
default = null;
};
single_click = lib.mkOption {
type = types.nullOr types.bool;
default = null;
};
};
};
})

View file

@ -2,19 +2,22 @@
{
flake = {
diskoConfigurations = {
home-pc = import ./home-pc/disk-config.nix;
home-server = import ./home-server/disk-config.nix;
cmdframe = import ./cmdframe/disk-config.nix;
};
nixosConfigurations = {
home-pc = inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
inputs.disko.nixosModules.disko
inputs.nixpkgs.nixosModules.notDetected
inputs.nixos-hardware.nixosModules.common-pc
inputs.nixos-hardware.nixosModules.common-pc-ssd
inputs.nixos-hardware.nixosModules.common-cpu-amd-pstate
inputs.nixos-hardware.nixosModules.common-gpu-amd
(self.lib.createSystemModule "home-pc" {
hardwareConfig = ../hardware/home-pc.nix;
hardwareConfig = ../hosts/home-pc/hardware.nix;
config = ../hosts/home-pc/default.nix;
})
self.lib.createMediaGroup
@ -35,7 +38,7 @@
(
{ pkgs, ... }:
{
environment.systemPackages = [ inputs.deploy-rs.defaultPackage.x86_64-linux ];
environment.systemPackages = [ inputs.deploy-rs.packages.x86_64-linux.default ];
}
)
];
@ -46,6 +49,7 @@
home-server = inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
inputs.disko.nixosModules.disko
inputs.nixpkgs.nixosModules.notDetected
inputs.nixos-hardware.nixosModules.common-pc
inputs.nixos-hardware.nixosModules.common-pc-ssd
@ -53,7 +57,7 @@
inputs.nixos-hardware.nixosModules.common-gpu-intel-kaby-lake
inputs.matrix-appservices.nixosModule
(self.lib.createSystemModule "home-server" {
hardwareConfig = ../hardware/lattepanda.nix;
hardwareConfig = ../hosts/home-server/hardware.nix;
config = ../hosts/home-server/default.nix;
})
self.lib.createMediaGroup

View file

@ -2,6 +2,7 @@
{
imports = [
./disk-config.nix
../../hardware/base.nix
../../hardware/bluetooth.nix
../../hardware/xbox.nix

View file

@ -0,0 +1,62 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "enc";
settings = {
allowDiscards = true;
};
content = {
type = "btrfs";
extraArgs = [ "-f" ];
subvolumes = {
"@" = {
mountpoint = "/";
mountOptions = [
"compress-force=zstd:1"
"noatime"
];
};
"@home" = {
mountpoint = "/home";
mountOptions = [
"compress-force=zstd:1"
"noatime"
];
};
"@snapshots" = {
mountpoint = "/.snapshots";
mountOptions = [
"compress-force=zstd:1"
"noatime"
];
};
};
};
};
};
};
};
};
};
};
}

View file

@ -0,0 +1,26 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
boot.initrd.availableKernelModules = [
"nvme"
"ahci"
"xhci_pci"
"usb_storage"
"usbhid"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -18,6 +18,7 @@ let
in
{
imports = [
./disk-config.nix
../../hardware/base.nix
../../desktop/x11.nix
../../system/server.nix

View file

@ -0,0 +1,62 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "enc";
settings = {
allowDiscards = true;
};
content = {
type = "btrfs";
extraArgs = [ "-f" ];
subvolumes = {
"@" = {
mountpoint = "/";
mountOptions = [
"compress-force=zstd:1"
"noatime"
];
};
"@home" = {
mountpoint = "/home";
mountOptions = [
"compress-force=zstd:1"
"noatime"
];
};
"@snapshots" = {
mountpoint = "/.snapshots";
mountOptions = [
"compress-force=zstd:1"
"noatime"
];
};
};
};
};
};
};
};
};
};
};
}

View file

@ -0,0 +1,21 @@
{ config, lib, ... }:
{
boot.initrd.availableKernelModules = [
"xhci_pci"
"ahci"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
"sdhci_pci"
"rtsx_usb_sdmmc"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.kernelParams = [ "i915.enable_guc=3" ];
boot.extraModulePackages = [ ];
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

145
modules/nginx-authelia.nix Normal file
View file

@ -0,0 +1,145 @@
{ config, lib, ... }:
let
cfg = config.services.nginx-authelia;
vhostOptionsAuth =
{ config, ... }:
{
options = {
enableAutheliaAuth = lib.mkEnableOption "Enable authelia auth";
};
config = lib.mkIf config.enableAutheliaAuth {
locations."/authelia".extraConfig = ''
set $upstream_authelia http://${cfg.host}:${toString cfg.port}/api/verify;
## Essential Proxy Configuration
internal;
proxy_pass $upstream_authelia;
## Headers
## The headers starting with X-* are required.
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Forwarded-Method $request_method;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Content-Length "";
proxy_set_header Connection "";
## Basic Proxy Configuration
proxy_pass_request_body off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
proxy_redirect http:// $scheme://;
proxy_http_version 1.1;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 4 32k;
client_body_buffer_size 128k;
## Advanced Proxy Configuration
send_timeout 5m;
proxy_read_timeout 240;
proxy_send_timeout 240;
proxy_connect_timeout 240;
'';
locations."/".extraConfig = ''
## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource.
auth_request /authelia;
## Set the $target_url variable based on the original request.
## Requires nginx http_set_misc module.
set_escape_uri $target_url $scheme://$http_host$request_uri;
## Save the upstream response headers from Authelia to variables.
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
## Inject the response headers from the variables into the request made to the backend.
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-Email $email;
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
error_page 401 =302 https://auth.zx.dev/?rd=$target_url;
'';
};
};
vhostOptionsProxy =
{ config, ... }:
{
options = {
useAutheliaProxyConf = lib.mkEnableOption "Use recommended authelia proxy configuration";
};
config = lib.mkIf config.useAutheliaProxyConf {
locations."/".extraConfig = ''
## Headers
proxy_set_header Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Connection "";
## Basic Proxy Configuration
client_body_buffer_size 128k;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; ## Timeout if the real server is dead.
proxy_redirect http:// $scheme://;
proxy_http_version 1.1;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 64 256k;
## Trusted Proxies Configuration
## Please read the following documentation before configuring this:
## https://www.authelia.com/integration/proxies/nginx/#trusted-proxies
# set_real_ip_from 10.0.0.0/8;
# set_real_ip_from 172.16.0.0/12;
# set_real_ip_from 192.168.0.0/16;
# set_real_ip_from fc00::/7;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
## Advanced Proxy Configuration
send_timeout 5m;
proxy_read_timeout 360;
proxy_send_timeout 360;
proxy_connect_timeout 360;
'';
};
};
in
{
options = {
services.nginx-authelia = {
host = lib.mkOption {
type = lib.types.str;
default = "localhost";
};
port = lib.mkOption {
type = lib.types.int;
default = 9091;
};
};
services.nginx.virtualHosts = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule [
vhostOptionsAuth
vhostOptionsProxy
]
);
};
};
config = { };
}

View file

@ -3,7 +3,7 @@ let
felschr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbQpMo1JOGk59Rzl6pVoOcMHOoqezph+aIlEXZP4rBu";
users = [ felschr ];
# `ssh-keygen -t ed25519 -N "" -f /etc/secrets/initrd/ssh_host_ed25519_key`
# `ssh-keygen -t ed25519 -N "" -f /etc/ssh/ssh_host_ed25519_key`
home-pc = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBFTQvIcSdhEKl/Kq+pcS/cPCyyZ1ygj+djfuaXzaRMx";
home-server = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILO+OLPr8zdOMYyKtm98AFJai7zbaxw7JhVWgOwu7K3C";
cmdframe = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAMcPrg69IqmH3V+7lgoXif/J6z4/aEi7w7p5jRn/lkp";

View file

@ -37,9 +37,6 @@ in
certificate_path = "${config.security.acme.certs."${host}".directory}/fullchain.pem";
private_key_path = "${config.security.acme.certs."${host}".directory}/key.pem";
};
# HINT: users needs to be set up manually:
# https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration#password-reset
# users = [ { name = "felschr"; } ];
querylog = {
enabled = true;
interval = "24h";
@ -104,6 +101,7 @@ in
services.nginx = {
virtualHosts."${host}" = {
enableAutheliaAuth = true;
enableACME = true;
forceSSL = true;
http3 = true;

View file

@ -63,6 +63,8 @@ let
smtpAccount = config.programs.msmtp.accounts.default;
in
{
imports = [ ../modules/nginx-authelia.nix ];
age.secrets.authelia-jwt = {
file = ../secrets/authelia/jwt.age;
owner = cfg.user;
@ -208,6 +210,10 @@ in
"lldap.service"
];
services.nginx-authelia = {
inherit port;
};
services.postgresql = {
enable = true;
ensureDatabases = [ cfg.user ];

View file

@ -1,4 +1,9 @@
{ config, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
isAdguardHost = config.services.adguardhome.enable;
@ -10,7 +15,7 @@ let
lan = rec {
IPv4Prefix = "192.168.1";
IPv4CIDR = "${IPv4Prefix}.1/24";
IPv4CIDR = "${IPv4Prefix}.0/24";
IPv6ULAPrefix = "fd1c:ca95:d74d";
IPv6ULACIDR = "${IPv6ULAPrefix}::/48";
};
@ -83,4 +88,12 @@ in
# mDNS already handled by systemd-resolved
services.avahi.enable = false;
programs.mtr.enable = true;
programs.mosh.enable = true;
environment.systemPackages = with pkgs; [
dig
wireguard-tools
];
}

View file

@ -1,4 +1,9 @@
{ inputs, config, ... }:
{
inputs,
config,
pkgs,
...
}:
let
inherit (inputs.self.outputs) nixConfig;
@ -6,6 +11,8 @@ in
{
nixpkgs.config.allowUnfree = true;
nix.package = pkgs.lix;
nix.gc = {
automatic = true;
dates = "04:00";