.dotfiles/Nix.org
2024-05-05 02:30:14 +02:00

5342 lines
154 KiB
Org Mode

#+title: Nix Configuration
This file holds the entirety of all configuration files for both NixOS as well as home manager across all machines that I currently use.
The only exception is my Emacs configuration which is held in its own .org file - this is done because that allows for upon-switch parsing of that file and installation of all emacs-packages through home-manager. The init.el file cannot be used there as it contains UTF-8 characters that would break the nix function responsible for handling the emacs-package building process.
* Noweb-Ref blocks
These blocks are used in several places throughout the configurations, but not on all machines necessarily. For example, the themeing section needs to be in a NixOS block on NixOS machines but in a home-manager block on non-NixOS. This serves to reduce code duplication.
** All systems
*** Themeing
This is where the theme for the whole OS is defined. This noweb-ref section cannot be copied to the general NixOS config for now since they are on different levels in the config, which would make the flake impure.
#+begin_src nix :noweb-ref theme
stylix = {
base16Scheme = ../../wallpaper/swarsel.yaml;
# base16Scheme = "${pkgs.base16-schemes}/share/themes/shapeshifter.yaml";
polarity = "dark";
opacity.popups = 0.5;
cursor = {
package = pkgs.capitaine-cursors;
name = "capitaine-cursors";
size = 16;
};
fonts = {
sizes = {
terminal = 10;
applications = 11;
};
serif = {
# package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; });
package = pkgs.cantarell-fonts;
# package = pkgs.montserrat;
name = "Cantarell";
# name = "FiraCode Nerd Font Propo";
# name = "Montserrat";
};
sansSerif = {
# package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; });
package = pkgs.cantarell-fonts;
# package = pkgs.montserrat;
name = "Cantarell";
# name = "FiraCode Nerd Font Propo";
# name = "Montserrat";
};
monospace = {
package = (pkgs.nerdfonts.override { fonts = [ "FiraCode"]; });
name = "FiraCode Nerd Font Mono";
};
emoji = {
package = pkgs.noto-fonts-emoji;
name = "Noto Color Emoji";
};
};
};
#+end_src
*** Waybar items - LAPTOPS
#+begin_src nix :noweb-ref waybarlaptop
programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark"
"mpris"
"custom/left-arrow-light"
"network"
"custom/left-arrow-dark"
"pulseaudio"
"custom/left-arrow-light"
"custom/pseudobat"
"battery"
"custom/left-arrow-dark"
"group/hardware"
"custom/left-arrow-light"
"clock#2"
"custom/left-arrow-dark"
"clock#1"
];
#+end_src
*** Waybar items - PC
#+begin_src nix :noweb-ref waybarpc
programs.waybar.settings.mainBar."custom/pseudobat"= {
format= "";
on-click-right= "wlogout -p layer-shell";
};
programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark"
"mpris"
"custom/left-arrow-light"
"network"
"custom/left-arrow-dark"
"pulseaudio"
"custom/left-arrow-light"
"custom/pseudobat"
"battery"
"custom/left-arrow-dark"
"group/hardware"
"custom/left-arrow-light"
"clock#2"
"custom/left-arrow-dark"
"clock#1"
];
#+end_src
** NixOS
*** Sway Startup commands
#+begin_src nix :noweb-ref startupnixos
{ command = "nextcloud --background";}
{ command = "spotify";}
{ command = "discord --start-minimized";}
{ command = "schildichat-desktop --disable-gpu-driver-bug-workarounds --hidden";}
{ command = "ANKI_WAYLAND=1 anki";}
{ command = "OBSIDIAN_USE_WAYLAND=1 obsidian";}
{ command = "nm-applet";}
#+end_src
*** gpg-agent
#+begin_src nix :noweb-ref gpgagent
services.gpg-agent = {
enable = true;
enableSshSupport = true;
};
#+end_src
*** Wrap with hardware-configuration
#+begin_src nix :noweb-ref wrap
imports =
[
./hardware-configuration.nix
];
#+end_src
*** Virtual hosts init
#+begin_src nix :noweb-ref vminitbare
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
nix.settings.experimental-features = ["nix-command" "flakes"];
proxmoxLXC.manageNetwork = true; # manage network myself
proxmoxLXC.manageHostName = false; # manage hostname myself
networking.useDHCP = true;
networking.enableIPv6 = false;
services.openssh = {
enable = true;
settings.PermitRootLogin = "yes";
listenAddresses = [{
port = 22;
addr = "0.0.0.0";
}];
};
users.users.root.openssh.authorizedKeys.keyFiles = [
../../../secrets/keys/authorized_keys
];
system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change
environment.shellAliases = {
nswitch = "cd /.dotfiles; git pull; nixos-rebuild --flake .#$(hostname) switch; cd -;";
};
#+end_src
#+begin_src nix :noweb yes :noweb-ref vminit
imports = [
(modulesPath + "/virtualisation/proxmox-lxc.nix")
./hardware-configuration.nix
];
<<vminitbare>>
#+end_src
** flake.nix
*** Inputs & Inputs@Outputs
#+begin_src nix :noweb-ref flakeinputsatoutputs
nixpkgs,
home-manager,
nix-on-droid,
nixos-generators,
emacs-overlay,
nur,
nixgl,
stylix,
sops-nix,
lanzaboote,
pia,
nixpkgs-mautrix-signal,
#+end_src
#+begin_src nix :noweb-ref flakeinputs
nixpkgs.url = github:nixos/nixpkgs/nixos-unstable;
# user-level configuration
home-manager = {
url = github:nix-community/home-manager;
inputs.nixpkgs.follows = "nixpkgs";
};
# overlay to access bleeding edge emacs
emacs-overlay = {
url = github:nix-community/emacs-overlay;
inputs.nixpkgs.follows = "nixpkgs";
};
# nix user repository
# i use this mainly to not have to build all firefox extensions
# myself as well as for the emacs-init package (tbd)
nur.url = github:nix-community/NUR;
# provides GL to non-NixOS hosts
nixgl.url = github:guibou/nixGL;
# manages all themeing using Home-Manager
stylix.url = github:danth/stylix;
# nix secrets management
sops-nix.url = github:Mic92/sops-nix;
# enable secure boot on NixOS
lanzaboote.url = github:nix-community/lanzaboote;
# nix for android
nix-on-droid = {
url = github:t184256/nix-on-droid/release-23.05;
inputs.nixpkgs.follows = "nixpkgs";
};
# generate NixOS images
nixos-generators = {
url = github:nix-community/nixos-generators;
inputs.nixpkgs.follows = "nixpkgs";
};
# privateinternetaccess nixos integration - not sure if I will keep using
pia = {
url = "git+https://git.sr.ht/~rprospero/nixos-pia?ref=development";
inputs.nixpkgs.follows = "nixpkgs";
};
# provides expressions for mautrix-signal
nixpkgs-mautrix-signal ={
url = github:niklaskorz/nixpkgs/nixos-23.11-mautrix-signal;
};
#+end_src
*** let
#+begin_src nix :noweb-ref flakelet
system = "x86_64-linux"; # not very portable, but I do not use other architectures at the moment
pkgs = import nixpkgs { inherit system;
overlays = [ emacs-overlay.overlay
nur.overlay
nixgl.overlay
];
config.allowUnfree = true;
};
# for ovm arm hosts
armpkgs = import nixpkgs { system = "aarch64-linux";
overlays = [ emacs-overlay.overlay
nur.overlay
nixgl.overlay
];
config.allowUnfree = true;
};
pkgsmautrix = import nixpkgs-mautrix-signal { inherit system;
config.allowUnfree = true;
};
# NixOS modules that can only be used on NixOS systems
nixModules = [ stylix.nixosModules.stylix
./profiles/common/nixos.nix
];
# Home-Manager modules wanted on non-NixOS systems
homeModules = [ stylix.homeManagerModules.stylix
];
# Home-Manager modules wanted on both NixOS and non-NixOS systems
mixedModules = [ sops-nix.homeManagerModules.sops
./profiles/common/home.nix
];
#+end_src
*** nixosConfigurations
#+begin_src nix :noweb-ref flakenixosconf
onett = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = nixModules ++ [
./profiles/onett/nixos.nix
home-manager.nixosModules.home-manager
{
home-manager.users.swarsel.imports = mixedModules ++ [
./profiles/onett/home.nix
];
}
];
};
twoson = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = nixModules ++ [
./profiles/twoson/nixos.nix
home-manager.nixosModules.home-manager
{
home-manager.users.swarsel.imports = mixedModules ++ [
./profiles/twoson/home.nix
];
}
];
};
threed = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = nixModules ++ [
lanzaboote.nixosModules.lanzaboote
./profiles/threed/nixos.nix
home-manager.nixosModules.home-manager
{
home-manager.users.swarsel.imports = mixedModules ++ [
./profiles/threed/home.nix
];
}
];
};
fourside = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = nixModules ++ [
./profiles/fourside/nixos.nix
home-manager.nixosModules.home-manager
{
home-manager.users.swarsel.imports = mixedModules ++ [
./profiles/fourside/home.nix
];
}
];
};
stand = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = nixModules ++ [
./profiles/stand/nixos.nix
home-manager.nixosModules.home-manager
{
home-manager.users.homelen.imports = mixedModules ++ [
./profiles/stand/home.nix
];
}
];
};
nginx = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = [
sops-nix.nixosModules.sops
./profiles/server1/nginx/nixos.nix
];
};
calibre = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = [
sops-nix.nixosModules.sops
./profiles/server1/calibre/nixos.nix
];
};
jellyfin = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = [
# sops-nix.nixosModules.sops
./profiles/server1/jellyfin/nixos.nix
];
};
transmission = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = [
sops-nix.nixosModules.sops
pia.nixosModule
./profiles/server1/transmission/nixos.nix
];
};
matrix = nixpkgs.lib.nixosSystem {
# specialArgs = {inherit pkgsmautrix; };
pkgs = pkgsmautrix;
# this is to import a service module that is not on nixpkgs
# this way avoids infinite recursion errors
specialArgs.unstable = nixpkgs-mautrix-signal;
modules = [
sops-nix.nixosModules.sops
./profiles/server1/matrix/nixos.nix
];
};
sound = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = [
sops-nix.nixosModules.sops
./profiles/server1/sound/nixos.nix
];
};
spotifyd = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = [
sops-nix.nixosModules.sops
./profiles/server1/spotifyd/nixos.nix
];
};
paperless = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = [
sops-nix.nixosModules.sops
./profiles/server1/paperless/nixos.nix
];
};
#ovm swarsel
sync = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = [
sops-nix.nixosModules.sops
./profiles/remote/oracle/sync/nixos.nix
];
};
#ovm swarsel
backup = nixpkgs.lib.nixosSystem {
specialArgs = {inherit inputs pkgs; };
modules = [
sops-nix.nixosModules.sops
./profiles/remote/oracle/backup/nixos.nix
];
};
#+end_src
*** homeConfigurations
#+begin_src nix :noweb-ref flakehomeconf
"leons@PCisLee" = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
modules = homeModules ++ mixedModules ++ [
./profiles/surface/home.nix
];
};
#+end_src
*** nixOnDroidConfigurations
#+begin_src nix :noweb-ref flakedroidconf
default = nix-on-droid.lib.nixOnDroidConfiguration {
modules = [
./profiles/mysticant/configuration.nix
];
};
#+end_src
*** nixos-generators
#+begin_src nix :noweb-ref flakenixosgenerators
proxmox-lxc = nixos-generators.nixosGenerate {
inherit system;
modules = [
./profiles/server1/TEMPLATE/nixos.nix
];
format = "proxmox-lxc";
};
#+end_src
* TODO System specific configuration
This section mainly exists house different `configuration.nix` files for system level configurations of NixOS systems as well as `home.nix` for user level configurations on all systems.
Important: Think about if a settings really needs to go into this area - chances are that the settings can also go to the general settings.
** Template (for new machines)
This section holds the minimum configuration that is needed on a new host. These assume a NixOS machine (so not standalone home-manager on a non-NixOS host), as this is the setting that I will most likely use in the future now. All of these blocks need to be updated, with entries called TEMPLATE mostly needed to be filled with host-/user-specific values or other inputs. If TEMPLATE is given in a comment section, see the provided values as likely defaults. The TEMPLATE comments should afterwards be deleted for clarity.
If a non-NixOS host must be used, check the Surface configuration for pointers. Most likely the waybar settings need to be adjusted, since non-NixOS (as of writing this) fails to display drawers in the waybar properly.
No matter what you do, check the initial /etc/nixos/configuration.nix for notable changes that might emerge in future versions of nix.
*** NixOS
#+begin_src nix :noweb yes :tangle profiles/TEMPLATE/nixos.nix
{ config, lib, pkgs, inputs, ... }:
{
<<wrap>>
services = {
getty.autologinUser = "TEMPLATE";
greetd.settings.initial_session.user="TEMPLATE";
};
# Bootloader
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/sda"; # TEMPLATE - if only one disk, this will work
boot.loader.grub.useOSProber = true;
# --------------------------------------
# you might need a configuration like this instead:
# Bootloader
# boot.loader.grub.enable = true;
# boot.loader.grub.devices = ["nodev" ];
# boot.loader.grub.useOSProber = true;
# boot.kernelPackages = pkgs.linuxPackages_latest;
# --------------------------------------
networking.hostName = "TEMPLATE"; # Define your hostname.
stylix.image = ../../wallpaper/TEMPLATEwp.png;
<<theme>>
# Configure keymap in X11 (only used for login)
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
users.users.TEMPLATE = {
isNormalUser = true;
description = "TEMPLATE";
extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ];
packages = with pkgs; [];
};
environment.systemPackages = with pkgs; [
];
system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change
}
#+end_src
*** Home Manager
#+begin_src nix :noweb yes :tangle profiles/TEMPLATE/home.nix
{ config, pkgs, lib, fetchFromGitHub, ... }:
{
<<gpgconf>>
home = {
username = "TEMPLATE";
homeDirectory = "/home/TEMPLATE";
stateVersion = "23.05"; # TEMPLATE -- Please read the comment before changing.
keyboard.layout = "us"; # TEMPLATE
home.packages = with pkgs; [
# ---------------------------------------------------------------
# if schildichat works on this machine, use it, otherwise go for element
# element-desktop
# ---------------------------------------------------------------
];
};
# update path if the sops private key is stored somewhere else
sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ];
# waybar config - TEMPLATE - update for cores and temp
programs.waybar.settings.mainBar = {
#cpu.format = "{icon0} {icon1} {icon2} {icon3}";
cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}";
temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input";
};
# -----------------------------------------------------------------
# is this machine always connected to power? If yes, use this block:
# <<waybarpc>>
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# if not always connected to power (laptop), use this (default):
<<waybarlaptop>>
# -----------------------------------------------------------------
wayland.windowManager.sway= {
config = rec {
# update for actual inputs here,
input = {
"36125:53060:splitkb.com_Kyria_rev3" = {
xkb_layout = "us";
xkb_variant = "altgr-intl";
};
"1:1:AT_Translated_Set_2_keyboard" = { # TEMPLATE
xkb_layout = "us";
xkb_options = "grp:win_space_toggle";
# xkb_options = "ctrl:nocaps,grp:win_space_toggle";
xkb_variant = "altgr-intl";
};
"type:touchpad" = {
dwt = "enabled";
tap = "enabled";
natural_scroll = "enabled";
middle_emulation = "enabled";
};
};
output = {
DP-1 = {
mode = "2560x1440"; # TEMPLATE
scale = "1";
bg = "~/.dotfiles/wallpaper/TEMPLATE.png fill";
};
};
keybindings = let
modifier = config.wayland.windowManager.sway.config.modifier;
in {
# TEMPLATE
"${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\"";
# "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkelement.sh\"";
};
startup = [
<<startupnixos>>
];
};
};
}
#+end_src
** Physical hosts
*** TODO Surface
My Surface Pro 3, only used for on-the-go university work. Be careful when pushing largechanges to this machine, as it easily runs out of memory on large switches. At the moment the only machine running non-NixOS, so special care must be taken not to break this one during updates.
**** TODO Channel setup
This installs nixGL, which is needed to run GL apps installed through home-manager, since this machine is not using NixOS.
- TODO: move this to flake.nix by using an overlay
1) Install nixGL:
#+begin_src nix
nix-channel --add https://github.com/guibou/nixGL/archive/main.tar.gz nixgl && nix-channel --update
nix-env -iA nixgl.auto.nixGLDefault # or replace `nixGLDefault` with your desired wrapper
#+end_src
This is needed in order to use EGL. Prefix programs that use it with `nixGL`
**** Home manager
#+begin_src nix :noweb yes :tangle profiles/surface/home.nix
{ config, pkgs, lib, fetchFromGitHub, ... }:
{
programs.home-manager.enable = true;
home.username = "leons";
home.homeDirectory = "/home/leons";
home.stateVersion = "23.05"; # Please read the comment before changing.
stylix.image = ../../wallpaper/surfacewp.png;
<<theme>>
nixpkgs = {
config = {
allowUnfree = true;
allowUnfreePredicate = (_: true);
};
};
services.xcape = {
enable = true;
mapExpression = {
Control_L = "Escape";
};
};
#keyboard config
home.keyboard.layout = "us";
sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ];
# waybar config
programs.waybar.settings.mainBar.cpu.format = "{icon0} {icon1} {icon2} {icon3}";
programs.waybar.settings.mainBar.temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon3/temp3_input";
programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" "mpris" "custom/left-arrow-light"
"network"
"custom/left-arrow-dark"
"pulseaudio"
"custom/left-arrow-light"
"battery"
"custom/left-arrow-dark"
"temperature"
"custom/left-arrow-light"
"disk"
"custom/left-arrow-dark"
"memory"
"custom/left-arrow-light"
"cpu"
"custom/left-arrow-dark"
"tray"
"custom/left-arrow-light"
"clock#2"
"custom/left-arrow-dark"
"clock#1" ];
services.blueman-applet.enable = true;
home.packages = with pkgs; [
# nixgl.auto.nixGLDefault
evince
# nodejs_20
# messaging
# we use gomuks for RAM preservation, but keep schildi around for files and images
];
programs.zsh.initExtra = "
export GPG_TTY=\"$(tty)\"
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
gpgconf --launch gpg-agent
";
# sway config
wayland.windowManager.sway= {
config = rec {
input = {
"*" = {
xkb_layout = "us";
xkb_options = "ctrl:nocaps,grp:win_space_toggle";
xkb_variant = "altgr-intl";
};
"type:touchpad" = {
dwt = "enabled";
tap = "enabled";
natural_scroll = "enabled";
middle_emulation = "enabled";
};
};
output = {
eDP-1 = {
mode = "2160x1440@59.955Hz";
scale = "1";
bg = "~/.dotfiles/wallpaper/surfacewp.png fill";
};
};
keybindings = let
modifier = config.wayland.windowManager.sway.config.modifier;
in {
"${modifier}+F2" = "exec brightnessctl set +5%";
"${modifier}+F1"= "exec brightnessctl set 5%-";
"${modifier}+n" = "exec sway output eDP-1 transform normal, splith";
"${modifier}+Ctrl+p" = "exec nixGL wl-mirror eDP-1";
"${modifier}+t" = "exec sway output eDP-1 transform 90, splitv";
"${modifier}+XF86AudioLowerVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png";
"${modifier}+XF86AudioRaiseVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png";
"${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkgomuks.sh\"";
};
startup = [
{ command = "sleep 60 && nixGL nextcloud --background";}
# { command = "sleep 60 && nixGL spotify";}
{ command = "sleep 60 && nixGL discord --start-minimized -enable-features=UseOzonePlatform -ozone-platform=wayland";}
# { command = "sleep 60 && nixGL schildichat-desktop --hidden";}
{ command = "sleep 60 && nixGL syncthingtray --wait"; }
{ command = "sleep 60 && ANKI_WAYLAND=1 nixGL anki";}
{ command = "nm-applet --indicator";}
{ command = "sleep 60 && OBSIDIAN_USE_WAYLAND=1 nixGL obsidian -enable-features=UseOzonePlatform -ozone-platform=wayland";}
];
keycodebindings = {
"124" = "exec systemctl suspend";
};
};
extraConfig = "
exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05 map_to_output eDP-1
exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05_Stylus map_to_output eDP-1
";
};
}
#+end_src
*** Onett (Lenovo Y510P)
My laptop, sadly soon to be replaced by a new one, since most basic functions are stopping to work lately.
**** NixOS
#+begin_src nix :noweb yes :tangle profiles/onett/nixos.nix
{ config, lib, pkgs, inputs, ... }:
{
<<wrap>>
services = {
greetd.settings.initial_session.user ="swarsel";
xserver.videoDrivers = ["nvidia"];
};
hardware = {
nvidia = {
modesetting.enable = true;
powerManagement.enable = true;
prime = {
intelBusId = "PCI:0:2:0";
nvidiaBusId = "PCI:1:0:0";
sync.enable = true;
};
};
pulseaudio.configFile = pkgs.runCommand "default.pa" {} ''
sed 's/module-udev-detect$/module-udev-detect tsched=0/' \
${pkgs.pulseaudio}/etc/pulse/default.pa > $out
'';
bluetooth.enable = true;
};
stylix.image = ../../wallpaper/lenovowp.png;
<<theme>>
boot.loader.grub = {
enable = true;
device = "/dev/sda";
useOSProber = true;
};
networking.hostName = "onett"; # Define your hostname.
networking.enableIPv6 = false;
users.users.swarsel = {
isNormalUser = true;
description = "Leon S";
extraGroups = [ "networkmanager" "wheel" "lp"];
packages = with pkgs; [];
};
system.stateVersion = "23.05"; # Did you read the comment?
environment.systemPackages = with pkgs; [
];
}
#+end_src
**** Home Manager
#+begin_src nix :noweb yes :tangle profiles/onett/home.nix
{ config, pkgs, lib, fetchFromGitHub, ... }:
{
<<gpgagent>>
home = {
username = "swarsel";
homeDirectory = "/home/swarsel";
stateVersion = "23.05"; # Please read the comment before changing.
keyboard.layout = "de";
packages = with pkgs; [
];
};
sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ];
# # waybar config
programs.waybar.settings.mainBar = {
cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}";
temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon3/temp3_input";
};
<<waybarlaptop>>
services.blueman-applet.enable = true;
wayland.windowManager.sway= {
config = rec {
input = {
"1:1:AT_Translated_Set_2_keyboard" = {
xkb_layout = "us";
xkb_options = "grp:win_space_toggle";
# xkb_options = "ctrl:nocaps,grp:win_space_toggle";
xkb_variant = "altgr-intl";
};
"2362:33538:ipad_keyboard_Keyboard" = {
xkb_layout = "us";
xkb_options = "altwin:swap_lalt_lwin,ctrl:nocaps,grp:win_space_toggle";
xkb_variant = "colemak_dh";
};
"36125:53060:splitkb.com_Kyria_rev3" = {
xkb_layout = "us";
xkb_variant = "altgr-intl";
};
"type:touchpad" = {
dwt = "enabled";
tap = "enabled";
natural_scroll = "enabled";
middle_emulation = "enabled";
};
};
output = {
eDP-1 = {
mode = "1920x1080";
scale = "1";
bg = "~/.dotfiles/wallpaper/lenovowp.png fill";
position = "1920,0";
};
VGA-1 = {
mode = "1920x1080";
scale = "1";
bg = "~/.dotfiles/wallpaper/lenovowp.png fill";
position = "0,0";
};
};
keybindings = let
modifier = config.wayland.windowManager.sway.config.modifier;
in {
"${modifier}+F2" = "exec brightnessctl set +5%";
"${modifier}+F1"= "exec brightnessctl set 5%-";
"XF86MonBrightnessUp" = "exec brightnessctl set +5%";
"XF86MonBrightnessDown"= "exec brightnessctl set 5%-";
"${modifier}+Ctrl+p" = "exec wl-mirror eDP-1";
"XF86HomePage" = "exec wtype -P Escape -p Escape";
"${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\"";
};
keycodebindings = {
"94" = "exec wtype c";
"Shift+94" = "exec wtype C";
"Ctrl+94" = "exec wtype -M ctrl c -m ctrl";
"Ctrl+Shift+94" = "exec wtype -M ctrl -M shift c -m ctrl -m shift";
};
startup = [
<<startupnixos>>
];
};
extraConfig = "
";
};
}
#+end_src
*** Twoson (Lenovo Thinkpad T14s Gen3)
**** NixOS
#+begin_src nix :noweb yes :tangle profiles/twoson/nixos.nix
{ config, lib, pkgs, inputs, ... }:
{
<<wrap>>
services = {
getty.autologinUser = "swarsel";
greetd.settings.initial_session.user="swarsel";
};
# Bootloader
# boot.loader.grub.enable = true;
# boot.loader.grub.device = "/dev/sda"; # TEMPLATE - if only one disk, this will work
# boot.loader.grub.useOSProber = true;
# --------------------------------------
# you might need a configuration like this instead:
# Bootloader
# boot.loader.grub.enable = true;
# boot.loader.grub.devices = ["nodev" ];
# boot.loader.grub.useOSProber = true;
# boot.kernelPackages = pkgs.linuxPackages_latest;
# --------------------------------------
networking.hostName = "twoson"; # Define your hostname.
stylix.image = ../../wallpaper/t14swp.png;
<<theme>>
# Configure keymap in X11 (only used for login)
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
users.users.swarsel = {
isNormalUser = true;
description = "TEMPLATE";
extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ];
packages = with pkgs; [];
};
environment.systemPackages = with pkgs; [
];
system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change
}
#+end_src
**** Home Manager
#+begin_src nix :noweb yes :tangle profiles/twoson/home.nix
{ config, pkgs, lib, fetchFromGitHub, ... }:
{
<<gpgconf>>
home = {
username = "swarsel";
homeDirectory = "/home/swarsel";
stateVersion = "23.05"; # TEMPLATE -- Please read the comment before changing.
keyboard.layout = "us"; # TEMPLATE
home.packages = with pkgs; [
# ---------------------------------------------------------------
# if schildichat works on this machine, use it, otherwise go for element
# element-desktop
# ---------------------------------------------------------------
];
};
# update path if the sops private key is stored somewhere else
sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ];
# waybar config - TEMPLATE - update for cores and temp
programs.waybar.settings.mainBar = {
#cpu.format = "{icon0} {icon1} {icon2} {icon3}";
cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}";
temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input";
};
# -----------------------------------------------------------------
# is this machine always connected to power? If yes, use this block:
# <<waybarpc>>
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# if not always connected to power (laptop), use this (default):
<<waybarlaptop>>
# -----------------------------------------------------------------
wayland.windowManager.sway= {
config = rec {
# update for actual inputs here,
input = {
"36125:53060:splitkb.com_Kyria_rev3" = {
xkb_layout = "us";
xkb_variant = "altgr-intl";
};
# "1:1:AT_Translated_Set_2_keyboard" = { # TEMPLATE
# xkb_layout = "us";
# xkb_options = "grp:win_space_toggle";
# # xkb_options = "ctrl:nocaps,grp:win_space_toggle";
# xkb_variant = "altgr-intl";
# };
"type:touchpad" = {
dwt = "enabled";
tap = "enabled";
natural_scroll = "enabled";
middle_emulation = "enabled";
};
};
output = {
DP-1 = {
mode = "1920x1280"; # TEMPLATE
scale = "1";
bg = "~/.dotfiles/wallpaper/t14swp.png fill";
};
};
keybindings = let
modifier = config.wayland.windowManager.sway.config.modifier;
in {
# TEMPLATE
"${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\"";
# "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkelement.sh\"";
};
startup = [
<<startupnixos>>
];
};
};
}
#+end_src
*** Threed (Surface Pro 3)
New setup for the SP3, this time using NixOS - another machine will take over the HM-only config for compatibility in the future.
**** NixOS
#+begin_src nix :noweb yes :tangle profiles/threed/nixos.nix
{ config, lib, pkgs, inputs, ... }:
{
<<wrap>>
services = {
getty.autologinUser = "swarsel";
greetd.settings.initial_session.user="swarsel";
};
hardware.bluetooth.enable = true;
# Bootloader
boot = {
loader.systemd-boot.enable = lib.mkForce false;
lanzaboote = {
enable = true;
pkiBundle = "/etc/secureboot";
};
loader.efi.canTouchEfiVariables = true;
# use bootspec instead of lzbt for secure boot. This is not a generally needed setting
bootspec.enable = true;
# kernelPackages = pkgs.linuxPackages_latest;
};
networking = {
hostName = "threed";
enableIPv6 = false;
firewall.enable = false;
};
stylix.image = ../../wallpaper/surfacewp.png;
<<theme>>
users.users.swarsel = {
isNormalUser = true;
description = "Leon S";
extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ];
packages = with pkgs; [];
};
environment.systemPackages = with pkgs; [
];
system.stateVersion = "23.05";
}
#+end_src
**** Home Manager
#+begin_src nix :noweb yes :tangle profiles/threed/home.nix
{ config, pkgs, lib, fetchFromGitHub, ... }:
{
<<gpgagent>>
home = {
username = "swarsel";
homeDirectory = "/home/swarsel";
stateVersion = "23.05"; # Please read the comment before changing.
keyboard.layout = "us";
packages = with pkgs; [
];
};
sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ];
programs.waybar.settings.mainBar = {
cpu.format = "{icon0} {icon1} {icon2} {icon3}";
temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input";
};
<<waybarlaptop>>
wayland.windowManager.sway= {
config = rec {
input = {
"*" = {
xkb_layout = "us";
xkb_options = "grp:win_space_toggle";
xkb_variant = "altgr-intl";
};
"type:touchpad" = {
dwt = "enabled";
tap = "enabled";
natural_scroll = "enabled";
middle_emulation = "enabled";
};
};
output = {
eDP-1 = {
mode = "2160x1440@59.955Hz";
scale = "1";
bg = "~/.dotfiles/wallpaper/surfacewp.png fill";
};
};
keybindings = let
modifier = config.wayland.windowManager.sway.config.modifier;
in {
"${modifier}+F2" = "exec brightnessctl set +5%";
"${modifier}+F1"= "exec brightnessctl set 5%-";
"${modifier}+n" = "exec sway output eDP-1 transform normal, splith";
"${modifier}+Ctrl+p" = "exec wl-mirror eDP-1";
"${modifier}+t" = "exec sway output eDP-1 transform 90, splitv";
"${modifier}+XF86AudioLowerVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png";
"${modifier}+XF86AudioRaiseVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png";
"${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\"";
};
startup = [
<<startupnixos>>
];
keycodebindings = {
"124" = "exec systemctl suspend";
};
};
extraConfig = "
exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05 map_to_output eDP-1
exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05_Stylus map_to_output eDP-1
";
};
}
#+end_src
*** Fourside (Lenovo Thinkpad P14s Gen2)
**** NixOS
#+begin_src nix :noweb yes :tangle profiles/fourside/nixos.nix
{ config, lib, pkgs, inputs, ... }:
{
<<wrap>>
services = {
getty.autologinUser = "swarsel";
greetd.settings.initial_session.user="swarsel";
};
boot = {
loader.systemd-boot.enable = true;
loader.efi.canTouchEfiVariables = true;
};
networking.hostName = "fourside"; # Define your hostname.
stylix.image = ../../wallpaper/lenovowp.png;
<<theme>>
hardware = {
bluetooth.enable = true;
};
# Configure keymap in X11 (only used for login)
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
users.users.swarsel = {
isNormalUser = true;
description = "Leon S";
extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ];
packages = with pkgs; [];
};
environment.systemPackages = with pkgs; [
];
system.stateVersion = "23.05";
}
#+end_src
**** Home Manager
#+begin_src nix :noweb yes :tangle profiles/fourside/home.nix
{ config, pkgs, lib, fetchFromGitHub, ... }:
{
<<gpgagent>>
home = {
username = "swarsel";
homeDirectory = "/home/swarsel";
stateVersion = "23.05"; # TEMPLATE -- Please read the comment before changing.
keyboard.layout = "us"; # TEMPLATE
home.packages = with pkgs; [
];
};
sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ];
# waybar config - TEMPLATE - update for cores and temp
programs.waybar.settings.mainBar = {
cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}";
temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input";
};
<<waybarlaptop>>
wayland.windowManager.sway= {
config = rec {
# update for actual inputs here,
input = {
"36125:53060:splitkb.com_Kyria_rev3" = {
xkb_layout = "us";
xkb_variant = "altgr-intl";
};
# "1:1:AT_Translated_Set_2_keyboard" = { # TEMPLATE
# xkb_layout = "us";
# xkb_options = "grp:win_space_toggle";
# # xkb_options = "ctrl:nocaps,grp:win_space_toggle";
# xkb_variant = "altgr-intl";
# };
"type:touchpad" = {
dwt = "enabled";
tap = "enabled";
natural_scroll = "enabled";
middle_emulation = "enabled";
};
};
output = {
DP-1 = {
mode = "2560x1440"; # TEMPLATE
scale = "1";
bg = "~/.dotfiles/wallpaper/lenovowp.png fill";
};
};
keybindings = let
modifier = config.wayland.windowManager.sway.config.modifier;
in {
"${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\"";
};
startup = [
<<startupnixos>>
];
};
};
}
#+end_src
*** Stand
My home PC, the most powerful machine. Sadly Sway cannot make good use out of it's NVIDIA card, so it runs a dual boot setup with a kind of broken GRUB that does not autodetect the windows partition.
**** NixOS
#+begin_src nix :noweb yes :tangle profiles/stand/nixos.nix
{ config, lib, pkgs, inputs, ... }:
{
<<wrap>>
services = {
getty.autologinUser = "homelen";
greetd.settings.initial_session.user="homelen";
};
stylix.image = ../../wallpaper/standwp.png;
<<theme>>
# Bootloader.
boot.loader.grub = {
enable = true;
devices = ["nodev" ];
useOSProber = true;
};
# boot.kernelPackages = pkgs.linuxPackages_latest;
networking = {
hostName = "stand"; # Define your hostname.
enableIPv6 = false;
firewall.enable = false;
# networkmanager.enable = true;
};
hardware = {
bluetooth.enable = true;
};
users.users.homelen = {
isNormalUser = true;
description = "Leon S";
extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ];
packages = with pkgs; [];
};
environment.systemPackages = with pkgs; [
];
system.stateVersion = "23.05"; # Did you read the comment? Dont change this basically
}
#+end_src
**** Home Manager
#+begin_src nix :noweb yes :tangle profiles/stand/home.nix
{ config, pkgs, lib, fetchFromGitHub, ... }:
{
<<gpgagent>>
home = {
username = "homelen";
homeDirectory = "/home/homelen";
stateVersion = "23.05"; # Please read the comment before changing.
keyboard.layout = "us";
packages = with pkgs; [
];
};
sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ];
services.blueman-applet.enable = true;
# waybar config
programs.waybar.settings.mainBar = {
cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}";
temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input";
};
<<waybarpc>>
wayland.windowManager.sway= {
config = rec {
input = {
"36125:53060:splitkb.com_Kyria_rev3" = {
xkb_layout = "us";
xkb_variant = "altgr-intl";
};
};
output = {
DP-1 = {
mode = "2560x1440";
scale = "1";
bg = "~/.dotfiles/wallpaper/standwp.png fill";
};
};
keybindings = let
modifier = config.wayland.windowManager.sway.config.modifier;
in {
"${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\"";
};
startup = [
<<startupnixos>>
];
};
};
}
#+end_src
** Virtual hosts
My server setup is built on Proxmox VE; back when I started, I created all kinds of wild Debian/Ubuntu/etc. KVMs and LXCs on there. However, the root disk has suffered a weird failure where it has become unable to be cloned, but it is still functional for now. I am currently rewriting all machines on there to use NixOS instead; this is a ongoing process.
In the long run, I am thinking about a transition to kubernetes or using just a server running NixOS and using the built-in container functionality. For now however, I like the network management provided by Proxmox, as I am a bit intimidated by doing that from scratch.
*** TEMPLATE
**** NixOS
#+begin_src nix :tangle profiles/server1/TEMPLATE/nixos.nix
{ pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/virtualisation/proxmox-lxc.nix")
];
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
];
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
nix.settings.experimental-features = ["nix-command" "flakes"];
proxmoxLXC.manageNetwork = true; # manage network myself
proxmoxLXC.manageHostName = false; # manage hostname myself
networking.hostName = "TEMPLATE"; # Define your hostname.
networking.useDHCP = true;
networking.enableIPv6 = false;
networking.firewall.enable = false;
services.openssh = {
enable = true;
settings.PermitRootLogin = "yes";
};
users.users.root.openssh.authorizedKeys.keyFiles = [
../../../secrets/keys/authorized_keys
];
# users.users.root.password = "TEMPLATE";
system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change
}
#+end_src
*** NGINX
**** NixOS
#+begin_src nix :tangle profiles/server1/nginx/nixos.nix
{ config, pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/virtualisation/proxmox-lxc.nix")
./hardware-configuration.nix
];
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
lego
nginx
];
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
nix.settings.experimental-features = ["nix-command" "flakes"];
sops.age.sshKeyPaths = [ "/etc/ssh/sops" ];
sops.defaultSopsFile = "/.dotfiles/secrets/nginx/secrets.yaml";
sops.validateSopsFiles = false;
sops.secrets.dnstokenfull = {owner="acme";};
sops.templates."certs.secret".content = ''
CF_DNS_API_TOKEN=${config.sops.placeholder.dnstokenfull}
'';
proxmoxLXC.manageNetwork = true; # manage network myself
proxmoxLXC.manageHostName = false; # manage hostname myself
networking.hostName = "nginx"; # Define your hostname.
networking.useDHCP = true;
networking.enableIPv6 = false;
networking.firewall.enable = false;
services.openssh = {
enable = true;
settings.PermitRootLogin = "yes";
};
users.users.root.openssh.authorizedKeys.keyFiles = [
../../../secrets/keys/authorized_keys
];
# users.users.root.password = "TEMPLATE";
system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change
security.acme = {
acceptTerms = true;
preliminarySelfsigned = false;
defaults.email = "mrswarsel@gmail.com";
defaults.dnsProvider = "cloudflare";
defaults.environmentFile = "${config.sops.templates."certs.secret".path}";
};
environment.shellAliases = {
nswitch = "cd /.dotfiles; git pull; nixos-rebuild --flake .#$(hostname) switch; cd -;";
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts = {
"stash.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "https://192.168.2.5";
extraConfig = ''
client_max_body_size 0;
'';
};
# "/push/" = {
# proxyPass = "http://192.168.2.5:7867";
# };
"/.well-known/carddav" = {
return = "301 $scheme://$host/remote.php/dav";
};
"/.well-known/caldav" = {
return = "301 $scheme://$host/remote.php/dav";
};
};
};
"matrix2.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"~ ^(/_matrix|/_synapse/client)" = {
proxyPass = "http://192.168.2.23:8008";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
# "sound.swarsel.win" = {
# enableACME = true;
# forceSSL = true;
# acmeRoot = null;
# locations = {
# "/" = {
# proxyPass = "https://192.168.2.13";
# extraConfig = ''
# client_max_body_size 0;
# '';
# };
# };
# };
# "sound.swarsel.win" = {
# enableACME = true;
# forceSSL = true;
# acmeRoot = null;
# locations = {
# "/" = {
# proxyPass = "http://192.168.2.13:4040";
# recommendedProxySettings = false;
# # proxyWebsockets = true;
# extraConfig = ''
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "Upgrade";
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto https;
# proxy_set_header X-Forwarded-Host $host;
# proxy_set_header X-Forwarded-Port $server_port;
# proxy_set_header Host $host;
# proxy_max_temp_file_size 0;
# proxy_redirect http:// https://;
# proxy_buffering off;
# proxy_request_buffering off;
# client_max_body_size 0;
# '';
# };
# };
# };
"sound.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://192.168.2.13:4040";
proxyWebsockets = true;
extraConfig = ''
proxy_redirect http:// https://;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_buffering off;
proxy_request_buffering off;
client_max_body_size 0;
'';
};
};
};
"scan.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://192.168.2.24:28981";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
"screen.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://192.168.2.16:8096";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
"matrix.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"~ ^(/_matrix|/_synapse/client)" = {
proxyPass = "http://192.168.2.20:8008";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
"scroll.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://192.168.2.22:8080";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
# "books.swarsel.win" = {
# enableACME = true;
# forceSSL = true;
# acmeRoot = null;
# locations = {
# "/" = {
# proxyPass = "http://192.168.2.22:8083";
# extraConfig = ''
# client_max_body_size 0;
# '';
# };
# };
# };
"blog.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "https://192.168.2.7";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
}
#+end_src
*** [Manual steps required] Calibre
This machine requires manual setup:
1) Set up calibre-web:
- Create metadata.db with 664 permissions, make sure parent directory is writeable
- Login @ books.swarsel.win using initial creds:
- user: admin
- pw: admin123
- point to metadata.db file, make sure you can upload
- Change pw, create normal user
2) Setup kavita:
- Login @ scrolls.swarsel.win
- Create admin user
- Import Libraries
- Create normal user
In general, I am not amazed by this setup; Kavita is the reader of choice, calibre-web mostly is there to have a convenient way to fullfill the opinionated folder structure when uploading ebooks (calibre-web does not work on its own since it forces sqlite which does not work nicely with my NFS book store). I hope that in the future Kavita will implement ebook upload, or that calibre-web will ditch the sqlite constraints.
**** NixOS
#+begin_src nix :tangle profiles/server1/calibre/nixos.nix
{ config, pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/virtualisation/proxmox-lxc.nix")
./hardware-configuration.nix
];
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
calibre
];
users.groups.lxc_shares = {
gid = 10000;
members = [
"kavita"
"calibre-web"
"root"
];
};
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
nix.settings.experimental-features = ["nix-command" "flakes"];
sops.age.sshKeyPaths = [ "/etc/ssh/sops" ];
sops.defaultSopsFile = "/.dotfiles/secrets/calibre/secrets.yaml";
sops.validateSopsFiles = false;
sops.secrets.kavita = { owner = "kavita";};
# sops.secrets.smbuser = { };
# sops.secrets.smbpassword = { };
# sops.secrets.smbdomain = { };
# sops.templates."smb.cred".content = ''
# user=${config.sops.placeholder.smbuser}
# password=${config.sops.placeholder.smbpassword}
# domain=${config.sops.placeholder.smbdomain}
# '';
proxmoxLXC.manageNetwork = true; # manage network myself
proxmoxLXC.manageHostName = false; # manage hostname myself
networking.hostName = "calibre"; # Define your hostname.
networking.useDHCP = true;
networking.enableIPv6 = false;
networking.firewall.enable = false;
services.openssh = {
enable = true;
settings.PermitRootLogin = "yes";
};
users.users.root.openssh.authorizedKeys.keyFiles = [
../../../secrets/keys/authorized_keys
];
system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change
environment.shellAliases = {
nswitch = "cd /.dotfiles; git pull; nixos-rebuild --flake .#$(hostname) switch; cd -;";
};
# services.calibre-server = {
# enable = true;
# user = "calibre-server";
# auth.enable = true;
# auth.userDb = "/srv/calibre/users.sqlite";
# libraries = [
# /media/Books/main
# /media/Books/diverse
# /media/Books/language
# /media/Books/science
# /media/Books/sport
# /media/Books/novels
# ];
# };
# services.calibre-web = {
# enable = true;
# user = "calibre-web";
# group = "calibre-web";
# listen.port = 8083;
# listen.ip = "0.0.0.0";
# options = {
# enableBookUploading = true;
# enableKepubify = true;
# enableBookConversion = true;
# };
# };
services.kavita = {
enable = true;
user = "kavita";
port = 8080;
tokenKeyFile = config.sops.secrets.kavita.path;
};
}
#+end_src
*** Jellyfin
**** NixOS
#+begin_src nix :tangle profiles/server1/jellyfin/nixos.nix
{ config, pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/virtualisation/proxmox-lxc.nix")
./hardware-configuration.nix
];
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
];
users.groups.lxc_shares = {
gid = 10000;
members = [
"jellyfin"
"root"
];
};
users.users.jellyfin = {
extraGroups = [ "video" "render" ];
};
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
nix.settings.experimental-features = ["nix-command" "flakes"];
# sops.age.sshKeyPaths = [ "/etc/ssh/sops" ];
# sops.defaultSopsFile = "/.dotfiles/secrets/jellyfin/secrets.yaml";
# sops.validateSopsFiles = false;
proxmoxLXC.manageNetwork = true; # manage network myself
proxmoxLXC.manageHostName = false; # manage hostname myself
networking.hostName = "jellyfin"; # Define your hostname.
networking.useDHCP = true;
networking.enableIPv6 = false;
networking.firewall.enable = false;
services.openssh = {
enable = true;
settings.PermitRootLogin = "yes";
};
users.users.root.openssh.authorizedKeys.keyFiles = [
../../../secrets/keys/authorized_keys
];
system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change
environment.shellAliases = {
nswitch = "cd /.dotfiles; git pull; nixos-rebuild --flake .#$(hostname) switch; cd -;";
};
nixpkgs.config.packageOverrides = pkgs: {
vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; };
};
hardware.opengl = {
enable = true;
extraPackages = with pkgs; [
intel-media-driver # LIBVA_DRIVER_NAME=iHD
vaapiIntel # LIBVA_DRIVER_NAME=i965 (older but works better for Firefox/Chromium)
vaapiVdpau
libvdpau-va-gl
];
};
services.jellyfin = {
enable = true;
user = "jellyfin";
# openFirewall = true; # this works only for the default ports
};
}
#+end_src
*** [WIP/Incomplete/Untested] Transmission
This stuff just does not work, I seem to be unable to create a working VPN Split Tunneling on NixOS. Maybe this is introduced by the wonky Proxmox-NixOS container interaction, I am not sure. For now, this machine does not work at all and I am stuck with my Debian Container that does this for me ...
**** NixOS
#+begin_src nix :tangle profiles/server1/transmission/nixos.nix
{ config, pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/virtualisation/proxmox-lxc.nix")
./hardware-configuration.nix
# ./openvpn.nix #this file holds the vpn login data
];
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
openvpn
jq
iptables
busybox
wireguard-tools
];
users.groups.lxc_shares = {
gid = 10000;
members = [
"vpn"
"radarr"
"sonarr"
"lidarr"
"readarr"
"root"
];
};
users.groups.vpn = {};
users.users.vpn = {
isNormalUser = true;
group = "vpn";
home = "/home/vpn";
};
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
nix.settings.experimental-features = ["nix-command" "flakes"];
sops.age.sshKeyPaths = [ "/etc/ssh/sops" ];
sops.defaultSopsFile = "/.dotfiles/secrets/transmission/secrets.yaml";
sops.validateSopsFiles = false;
boot.kernelModules = [ "tun" ];
proxmoxLXC.manageNetwork = true; # manage network myself
proxmoxLXC.manageHostName = false; # manage hostname myself
networking.hostName = "transmission"; # Define your hostname.
networking.useDHCP = true;
networking.enableIPv6 = false;
networking.firewall.enable = false;
services.radarr = {
enable = true;
};
services.readarr = {
enable = true;
};
services.sonarr = {
enable = true;
};
services.lidarr = {
enable = true;
};
services.prowlarr = {
enable = true;
};
# networking.interfaces = {
# lo = {
# useDHCP = false;
# ipv4.addresses = [
# { address = "127.0.0.1"; prefixLength = 8; }
# ];
# };
#
# eth0 = {
# useDHCP = true;
# };
# };
# networking.firewall.extraCommands = ''
# sudo iptables -A OUTPUT ! -o lo -m owner --uid-owner vpn -j DROP
# '';
networking.iproute2 = {
enable = true;
rttablesExtraConfig = ''
200 vpn
'';
};
# boot.kernel.sysctl = {
# "net.ipv4.conf.all.rp_filter" = 2;
# "net.ipv4.conf.default.rp_filter" = 2;
# "net.ipv4.conf.eth0.rp_filter" = 2;
# };
environment.etc = {
"openvpn/iptables.sh" =
{ source = ../../../scripts/server1/iptables.sh;
mode = "0755";
};
"openvpn/update-resolv-conf" =
{ source = ../../../scripts/server1/update-resolv-conf;
mode = "0755";
};
"openvpn/routing.sh" =
{ source = ../../../scripts/server1/routing.sh;
mode = "0755";
};
"openvpn/ca.rsa.2048.crt" =
{ source = ../../../secrets/certs/ca.rsa.2048.crt;
mode = "0644";
};
"openvpn/crl.rsa.2048.pem" =
{ source = ../../../secrets/certs/crl.rsa.2048.pem;
mode = "0644";
};
};
services.openssh = {
enable = true;
settings.PermitRootLogin = "yes";
listenAddresses = [{
port = 22;
addr = "0.0.0.0";
}];
};
users.users.root.openssh.authorizedKeys.keyFiles = [
../../../secrets/keys/authorized_keys
];
system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change
# users.users.root.password = "TEMPLATE";
environment.shellAliases = {
nswitch = "cd /.dotfiles; git pull; nixos-rebuild --flake .#$(hostname) switch; cd -;";
};
sops.secrets.vpnuser = {};
sops.secrets.rpcuser = {owner="vpn";};
sops.secrets.vpnpass = {};
sops.secrets.rpcpass = {owner="vpn";};
sops.secrets.vpnprot = {};
sops.secrets.vpnloc = {};
# sops.secrets.crlpem = {};
# sops.secrets.capem = {};
sops.templates."transmission-rpc".owner = "vpn";
sops.templates."transmission-rpc".content = builtins.toJSON {
rpc-username = config.sops.placeholder.rpcuser;
rpc-password = config.sops.placeholder.rpcpass;
};
sops.templates.pia.content = ''
${config.sops.placeholder.vpnuser}
${config.sops.placeholder.vpnpass}
'';
sops.templates.vpn.content = ''
client
dev tun
proto ${config.sops.placeholder.vpnprot}
remote ${config.sops.placeholder.vpnloc}
resolv-retry infinite
nobind
persist-key
persist-tun
cipher aes-128-cbc
auth sha1
tls-client
remote-cert-tls server
auth-user-pass ${config.sops.templates.pia.path}
compress
verb 1
reneg-sec 0
crl-verify /etc/openvpn/crl.rsa.2048.pem
ca /etc/openvpn/ca.rsa.2048.crt
disable-occ
dhcp-option DNS 209.222.18.222
dhcp-option DNS 209.222.18.218
dhcp-option DNS 8.8.8.8
route-noexec
'';
# services.pia.enable = true;
# services.pia.authUserPass.username = "na";
# services.pia.authUserPass.password = "na";
# systemd.services.openvpn-vpn = {
# wantedBy = [ "multi-user.target" ];
# after = [ "network.target" ];
# description = "OpenVPN connection to pia";
# serviceConfig = {
# Type = "forking";
# RuntimeDirectory="openvpn";
# PrivateTmp=true;
# KillMode="mixed";
# ExecStart = ''@${pkgs.openvpn}/sbin/openvpn openvpn --daemon ovpn-pia --status /run/openvpn/pia.status 10 --cd /etc/openvpn --script-security 2 --config ${config.sops.templates.vpn.path} --writepid /run/openvpn/pia.pid'';
# PIDFile=''/run/openvpn/pia.pid'';
# ExecReload=''/run/current-system/sw/bin/kill -HUP $MAINPID'';
# WorkingDirectory="/etc/openvpn";
# Restart="on-failure";
# RestartSec=30;
# ProtectSystem="yes";
# DeviceAllow=["/dev/null rw" "/dev/net/tun rw"];
# };
# };
services.openvpn.servers = {
pia = {
autoStart = false;
updateResolvConf = true;
# up = ''
# export INTERFACE="tun0"
# export VPNUSER="vpn"
# export LOCALIP="192.168.1.191"
# export NETIF="eth0"
# export VPNIF="tun0"
# export GATEWAYIP=$(ifconfig $VPNIF | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}' | egrep -v '255|(127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})' | tail -n1)
# iptables -F -t nat
# iptables -F -t mangle
# iptables -F -t filter
# iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
# iptables -t mangle -A OUTPUT ! --dest $LOCALIP -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
# iptables -t mangle -A OUTPUT --dest $LOCALIP -p udp --dport 53 -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
# iptables -t mangle -A OUTPUT --dest $LOCALIP -p tcp --dport 53 -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
# iptables -t mangle -A OUTPUT ! --src $LOCALIP -j MARK --set-mark 0x1
# iptables -t mangle -A OUTPUT -j CONNMARK --save-mark
# iptables -A INPUT -i $INTERFACE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -A INPUT -i $INTERFACE -j REJECT
# iptables -A OUTPUT -o lo -m owner --uid-owner $VPNUSER -j ACCEPT
# iptables -A OUTPUT -o $INTERFACE -m owner --uid-owner $VPNUSER -j ACCEPT
# iptables -t nat -A POSTROUTING -o $INTERFACE -j MASQUERADE
# iptables -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT ! --src $LOCALIP -o $NETIF -j REJECT
# if [[ `ip rule list | grep -c 0x1` == 0 ]]; then
# ip rule add from all fwmark 0x1 lookup $VPNUSER
# fi
# ip route replace default via $GATEWAYIP table $VPNUSER
# ip route append default via 127.0.0.1 dev lo table $VPNUSER
# ip route flush cache
# '';
# down = "bash /etc/openvpn/update-resolv-conf";
# these are outsourced to a local file, I am not sure if it can be done with sops-nix
# authUserPass = {
# username = "TODO:secrets";
# password = "TODO:secrets";
# };
config = "config ${config.sops.templates.vpn.path}";
};
};
services.transmission = {
enable = true;
credentialsFile = config.sops.templates."transmission-rpc".path;
user = "vpn";
group = "lxc_shares";
settings = {
alt-speed-down= 8000;
alt-speed-enabled= false;
alt-speed-time-begin= 0;
alt-speed-time-day= 127;
alt-speed-time-enabled= true;
alt-speed-time-end= 360;
alt-speed-up= 2000;
bind-address-ipv4= "0.0.0.0";
bind-address-ipv6= "::";
blocklist-enabled= false;
blocklist-url= "http://www.example.com/blocklist";
cache-size-mb= 4;
dht-enabled= false;
download-dir= "/media/Eternor/New";
download-limit= 100;
download-limit-enabled= 0;
download-queue-enabled= true;
download-queue-size= 5;
encryption= 2;
idle-seeding-limit= 30;
idle-seeding-limit-enabled= false;
incomplete-dir= "/var/lib/transmission-daemon/Downloads";
incomplete-dir-enabled= false;
lpd-enabled= false;
max-peers-global= 200;
message-level= 1;
peer-congestion-algorithm= "";
peer-id-ttl-hours= 6;
peer-limit-global= 100;
peer-limit-per-torrent= 40;
peer-port= 22371;
peer-port-random-high= 65535;
peer-port-random-low= 49152;
peer-port-random-on-start= false;
peer-socket-tos= "default";
pex-enabled= false;
port-forwarding-enabled= false;
preallocation= 1;
prefetch-enabled= true;
queue-stalled-enabled= true;
queue-stalled-minutes= 30;
ratio-limit= 2;
ratio-limit-enabled= false;
rename-partial-files= true;
rpc-authentication-required= true;
rpc-bind-address= "0.0.0.0";
rpc-enabled= true;
rpc-host-whitelist= "";
rpc-host-whitelist-enabled= true;
rpc-port= 9091;
rpc-url= "/transmission/";
rpc-whitelist= "127.0.0.1,192.168.3.2";
rpc-whitelist-enabled= true;
scrape-paused-torrents-enabled= true;
script-torrent-done-enabled= false;
seed-queue-enabled= false;
seed-queue-size= 10;
speed-limit-down= 6000;
speed-limit-down-enabled= true;
speed-limit-up= 500;
speed-limit-up-enabled= true;
start-added-torrents= true;
trash-original-torrent-files= false;
umask= 2;
upload-limit= 100;
upload-limit-enabled= 0;
upload-slots-per-torrent= 14;
utp-enabled= false;
};
};
# services.nginx = {
# enable = true;
# virtualHosts = {
# "192.168.1.192" = {
# locations = {
# "/transmission" = {
# proxyPass = "http://127.0.0.1:9091";
# extraConfig = ''
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# '';
# };
# };
# };
# };
# };
}
#+end_src
*** [Manual steps needed] Matrix
1) After the initial setup, run the
- /run/secrets-generated/matrix_user_register.sh
command to register a new admin user.
2) All bridges will fail on first start, copy the registration files using:
- cp /var/lib/mautrix-telegram/telegram-registration.yaml /var/lib/matrix-synapse/
- chown matrix-synapse:matrix-synapse var/lib/matrix-synapse/telegram-registration.yaml
Make sure to also do this for doublepuppet.yaml
3) Restart postgresql.service, matrix-synapse.service, mautrix-whatsapp.service, mautrix-telegram.service
**** NixOS
#+begin_src nix :noweb yes :tangle profiles/server1/matrix/nixos.nix
{ config, pkgs, modulesPath, unstable, sops, ... }: let
matrixDomain = "matrix2.swarsel.win";
in {
<<vminitbare>>
imports = [
(modulesPath + "/virtualisation/proxmox-lxc.nix")
./hardware-configuration.nix
# we import here a service that is not available yet on normal nixpkgs
# this module is hence not in the modules list, we add it ourselves
(unstable + "/nixos/modules/services/matrix/mautrix-signal.nix")
];
networking.hostName = "matrix"; # Define your hostname.
networking.firewall.enable = false;
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
matrix-synapse
lottieconverter
ffmpeg
];
sops.age.sshKeyPaths = [ "/etc/ssh/sops" ];
sops.defaultSopsFile = "/.dotfiles/secrets/matrix/secrets.yaml";
sops.validateSopsFiles = false;
sops.secrets.matrixsharedsecret = {owner="matrix-synapse";};
sops.templates."matrix_user_register.sh".content = ''
register_new_matrix_user -k ${config.sops.placeholder.matrixsharedsecret} http://localhost:8008
'';
sops.templates.matrixshared.owner = "matrix-synapse";
sops.templates.matrixshared.content = ''
registration_shared_secret: ${config.sops.placeholder.matrixsharedsecret}
'';
sops.secrets.mautrixtelegram_as = {owner="matrix-synapse";};
sops.secrets.mautrixtelegram_hs = {owner="matrix-synapse";};
sops.secrets.mautrixtelegram_api_id = {owner="matrix-synapse";};
sops.secrets.mautrixtelegram_api_hash = {owner="matrix-synapse";};
sops.templates.mautrixtelegram.owner = "matrix-synapse";
sops.templates.mautrixtelegram.content = ''
MAUTRIX_TELEGRAM_APPSERVICE_AS_TOKEN=${config.sops.placeholder.mautrixtelegram_as}
MAUTRIX_TELEGRAM_APPSERVICE_HS_TOKEN=${config.sops.placeholder.mautrixtelegram_hs}
MAUTRIX_TELEGRAM_TELEGRAM_API_ID=${config.sops.placeholder.mautrixtelegram_api_id}
MAUTRIX_TELEGRAM_TELEGRAM_API_HASH=${config.sops.placeholder.mautrixtelegram_api_hash}
'';
# sops.secrets.mautrixwhatsapp_shared = {owner="matrix-synapse";};
# sops.templates.mautrixwhatsapp.owner = "matrix-synapse";
# sops.templates.mautrixwhatsapp.content = ''
# MAUTRIX_WHATSAPP_BRIDGE_LOGIN_SHARED_SECRET=${config.sops.placeholder.mautrixwhatsapp_shared}
# '';
services.postgresql.enable = true;
services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
CREATE ROLE "mautrix-telegram" WITH LOGIN PASSWORD 'telegram';
CREATE DATABASE "mautrix-telegram" WITH OWNER "mautrix-telegram"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
CREATE ROLE "mautrix-whatsapp" WITH LOGIN PASSWORD 'whatsapp';
CREATE DATABASE "mautrix-whatsapp" WITH OWNER "mautrix-whatsapp"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
CREATE ROLE "mautrix-signal" WITH LOGIN PASSWORD 'signal';
CREATE DATABASE "mautrix-signal" WITH OWNER "mautrix-signal"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
'';
services.matrix-synapse = {
settings.app_service_config_files = [
"/var/lib/matrix-synapse/telegram-registration.yaml"
"/var/lib/matrix-synapse/whatsapp-registration.yaml"
"/var/lib/matrix-synapse/signal-registration.yaml"
"/var/lib/matrix-synapse/doublepuppet.yaml"
];
enable = true;
settings.server_name = matrixDomain;
settings.public_baseurl = "https://${matrixDomain}";
extraConfigFiles = [
config.sops.templates.matrixshared.path
];
settings.listeners = [
{ port = 8008;
bind_addresses = [ "0.0.0.0" ];
type = "http";
tls = false;
x_forwarded = true;
resources = [
{
names = [ "client" "federation" ];
compress = true;
}
];
}
];
};
services.mautrix-telegram = {
enable = true;
environmentFile = config.sops.templates.mautrixtelegram.path;
settings = {
homeserver = {
address = "http://localhost:8008";
domain = matrixDomain;
};
appservice = {
address= "http://localhost:29317";
hostname = "0.0.0.0";
port = "29317";
provisioning.enabled = true;
id = "telegram";
# ephemeral_events = true; # not needed due to double puppeting
public = {
enabled = false;
};
database = "postgresql:///mautrix-telegram?host=/run/postgresql";
};
bridge = {
# login_shared_secret_map = {
# matrixDomain = "as_token:doublepuppet";
# };
relaybot.authless_portals = true;
allow_avatar_remove = true;
allow_contact_info = true;
sync_channel_members = true;
startup_sync = true;
sync_create_limit = 0;
sync_direct_chats = true;
telegram_link_preview = true;
permissions = {
"*" = "relaybot";
"@swarsel:${matrixDomain}" = "admin";
};
# Animated stickers conversion requires additional packages in the
# service's path.
# If this isn't a fresh installation, clearing the bridge's uploaded
# file cache might be necessary (make a database backup first!):
# delete from telegram_file where \
# mime_type in ('application/gzip', 'application/octet-stream')
animated_sticker = {
target = "gif";
args = {
width = 256;
height = 256;
fps = 30; # only for webm
background = "020202"; # only for gif, transparency not supported
};
};
};
};
};
systemd.services.mautrix-telegram.path = with pkgs; [
lottieconverter # for animated stickers conversion, unfree package
ffmpeg # if converting animated stickers to webm (very slow!)
];
services.mautrix-whatsapp = {
enable = true;
# environmentFile = config.sops.templates.mautrixwhatsapp.path;
settings = {
homeserver = {
address = "http://localhost:8008";
domain = matrixDomain;
};
appservice = {
address= "http://localhost:29318";
hostname = "0.0.0.0";
port = 29318;
database = {
type = "postgres";
uri = "postgresql:///mautrix-whatsapp?host=/run/postgresql";
};
};
bridge = {
displayname_template = "{{or .FullName .PushName .JID}} (WA)";
history_sync = {
backfill = true;
max_initial_conversations = -1;
message_count = -1;
request_full_sync = true;
full_sync_config = {
days_limit = 900;
size_mb_limit = 5000;
storage_quota_mb = 5000;
};
};
login_shared_secret_map = {
matrixDomain = "as_token:doublepuppet";
};
sync_manual_marked_unread = true;
send_presence_on_typing = true;
parallel_member_sync = true;
url_previews = true;
caption_in_message = true;
extev_polls = true;
permissions = {
"*" = "relaybot";
"@swarsel:${matrixDomain}" = "admin";
};
};
};
};
services.mautrix-signal = {
enable = true;
# environmentFile = config.sops.templates.mautrixwhatsapp.path;
settings = {
homeserver = {
address = "http://localhost:8008";
domain = matrixDomain;
};
appservice = {
address= "http://localhost:29328";
hostname = "0.0.0.0";
port = 29328;
database = {
type = "postgres";
uri = "postgresql:///mautrix-signal?host=/run/postgresql";
};
};
bridge = {
displayname_template = "{{or .ContactName .ProfileName .PhoneNumber}} (Signal)";
login_shared_secret_map = {
matrixDomain = "as_token:doublepuppet";
};
caption_in_message = true;
permissions = {
"*" = "relaybot";
"@swarsel:${matrixDomain}" = "admin";
};
};
};
};
# restart the bridges daily. this is done for the signal bridge mainly which stops carrying
# messages out after a while.
systemd.timers."restart-bridges" = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "1d";
OnUnitActiveSec = "1d";
Unit = "restart-bridges.service";
};
};
systemd.services."restart-bridges" = {
script = ''
systemctl restart mautrix-whatsapp.service
systemctl restart mautrix-signal.service
systemctl restart mautrix-telegram.service
'';
serviceConfig = {
Type = "oneshot";
User = "root";
};
};
}
#+end_src
*** Sound
**** NixOS
#+begin_src nix :noweb yes :tangle profiles/server1/sound/nixos.nix
{ config, pkgs, modulesPath, ... }:
{
<<vminit>>
proxmoxLXC.privileged = true; # manage hostname myself
users.groups.lxc_pshares = {
gid = 110000;
members = [
"navidrome"
"mpd"
"root"
];
};
users.groups.navidrome = {
gid = 61593;
};
users.groups.mpd = {};
users.users.navidrome = {
isSystemUser = true;
uid = 61593;
group = "navidrome";
extraGroups = [ "audio" "utmp" ];
};
users.users.mpd = {
isSystemUser = true;
group = "mpd";
extraGroups = [ "audio" "utmp" ];
};
sound = {
enable = true;
};
hardware.enableAllFirmware = true;
networking.hostName = "sound"; # Define your hostname.
networking.firewall.enable = false;
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
pciutils
alsa-utils
mpv
];
sops.age.sshKeyPaths = [ "/etc/ssh/sops" ];
sops.defaultSopsFile = "/.dotfiles/secrets/sound/secrets.yaml";
sops.validateSopsFiles = false;
sops.secrets.mpdpass = { owner = "mpd";};
services.navidrome = {
enable = true;
settings = {
Address = "0.0.0.0";
Port = 4040;
MusicFolder = "/media";
EnableSharing = true;
EnableTranscodingConfig = true;
Scanner.GroupAlbumReleases = true;
ScanSchedule = "@every 1d";
# Insert these values locally as sops-nix does not work for them
LastFM.ApiKey = TEMPLATE;
LastFM.Secret = TEMPLATE;
Spotify.ID = TEMPLATE;
Spotify.Secret = TEMPLATE;
UILoginBackgroundUrl = "https://i.imgur.com/OMLxi7l.png";
UIWelcomeMessage = "~SwarselSound~";
};
};
services.mpd = {
enable = true;
musicDirectory = "/media";
user = "mpd";
group = "mpd";
network = {
port = 3254;
listenAddress = "any";
};
credentials = [
{
passwordFile = config.sops.secrets.mpdpass.path;
permissions = [
"read"
"add"
"control"
"admin"
];
}
];
};
}
#+end_src
*** Spotifyd
**** NixOS
#+begin_src nix :noweb yes :tangle profiles/server1/spotifyd/nixos.nix
{ config, pkgs, modulesPath, ... }:
{
<<vminit>>
proxmoxLXC.privileged = true; # manage hostname myself
users.groups.spotifyd = {
gid = 65136;
};
users.users.spotifyd = {
isSystemUser = true;
uid = 65136;
group = "spotifyd";
extraGroups = [ "audio" "utmp" ];
};
sound = {
enable = true;
};
hardware.enableAllFirmware = true;
networking.hostName = "spotifyd"; # Define your hostname.
networking.firewall.enable = false;
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
];
# sops.age.sshKeyPaths = [ "/etc/ssh/sops" ];
# sops.defaultSopsFile = "/.dotfiles/secrets/spotifyd/secrets.yaml";
# sops.validateSopsFiles = false;
services.spotifyd = {
enable = true;
settings = {
global = {
dbus_type = "session";
use_mpris = false;
device = "default:CARD=PCH";
device_name = "SwarselSpot";
mixer = "alsa";
zeroconf_port = 1025;
};
};
};
}
#+end_src
*** Sync
**** NixOS
#+begin_src nix :tangle profiles/remote/oracle/sync/nixos.nix
{ config, pkgs, modulesPath, ... }:
{
imports = [
./hardware-configuration.nix
];
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
];
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
nix.settings.experimental-features = ["nix-command" "flakes"];
sops.age.sshKeyPaths = [ "/etc/ssh/sops" ];
sops.defaultSopsFile = "/root/.dotfiles/secrets/sync/secrets.yaml";
sops.validateSopsFiles = false;
sops.secrets.swarsel = { owner = "root";};
sops.secrets.dnstokenfull = {owner="acme";};
sops.templates."certs.secret".content = ''
CF_DNS_API_TOKEN=${config.sops.placeholder.dnstokenfull}
'';
security.acme = {
acceptTerms = true;
preliminarySelfsigned = false;
defaults.email = "mrswarsel@gmail.com";
defaults.dnsProvider = "cloudflare";
defaults.environmentFile = "${config.sops.templates."certs.secret".path}";
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts = {
"synki.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:27701";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
"sync.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:8384/";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
"swagit.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:3000";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
boot.tmp.cleanOnBoot = true;
zramSwap.enable = false;
networking.hostName = "sync";
networking.enableIPv6 = false;
networking.domain = "subnet03112148.vcn03112148.oraclevcn.com";
networking.firewall.extraCommands = ''
iptables -I INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -m state --state NEW -p tcp --dport 443 -j ACCEPT
iptables -I INPUT -m state --state NEW -p tcp --dport 27701 -j ACCEPT
iptables -I INPUT -m state --state NEW -p tcp --dport 8384 -j ACCEPT
iptables -I INPUT -m state --state NEW -p tcp --dport 3000 -j ACCEPT
iptables -I INPUT -m state --state NEW -p tcp --dport 22000 -j ACCEPT
iptables -I INPUT -m state --state NEW -p udp --dport 22000 -j ACCEPT
iptables -I INPUT -m state --state NEW -p udp --dport 21027 -j ACCEPT
'';
services.openssh = {
enable = true;
settings.PermitRootLogin = "yes";
};
users.users.root.openssh.authorizedKeys.keyFiles = [
../../../../secrets/keys/authorized_keys
];
system.stateVersion = "23.11"; # TEMPLATE - but probably no need to change
environment.shellAliases = {
nswitch = "cd ~/.dotfiles; git pull; nixos-rebuild --flake .#$(hostname) switch; cd -;";
};
boot.loader.grub.device = "nodev";
services.anki-sync-server = {
enable = true;
port = 27701;
address = "0.0.0.0";
openFirewall = true;
users = [
{
username = "Swarsel";
passwordFile = config.sops.secrets.swarsel.path;
}
];
};
services.syncthing = {
enable = true;
guiAddress = "0.0.0.0:8384";
openDefaultPorts = true;
};
services.forgejo = {
enable = true;
settings = {
DEFAULT = {
APP_NAME = "~SwaGit~";
};
server = {
PROTOCOL = "http";
HTTP_PORT = 3000;
HTTP_ADDR = "0.0.0.0";
DOMAIN = "swagit.swarsel.win";
ROOT_URL = "https://swagit.swarsel.win";
};
service = {
DISABLE_REGISTRATION = true;
SHOW_REGISTRATION_BUTTON = false;
};
};
};
}
#+end_src
*** Paperless
**** NixOS
#+begin_src nix :noweb yes :tangle profiles/server1/paperless/nixos.nix
{ config, pkgs, modulesPath, ... }:
{
<<vminit>>
users.groups.lxc_shares = {
gid = 10000;
members = [
"paperless"
"root"
];
};
environment.systemPackages = with pkgs; [
git
gnupg
ssh-to-age
];
networking.hostName = "paperless"; # Define your hostname.
networking.firewall.enable = false;
sops.age.sshKeyPaths = [ "/etc/ssh/sops" ];
sops.defaultSopsFile = "/root/.dotfiles/secrets/paperless/secrets.yaml";
sops.validateSopsFiles = false;
sops.secrets.admin = { owner = "paperless";};
services.paperless = {
enable = true;
mediaDir = "/media";
user = "paperless";
port = 28981;
passwordFile = config.sops.secrets.admin.path;
address = "0.0.0.0";
extraConfig = {
PAPERLESS_OCR_LANGUAGE = "deu+eng";
PAPERLESS_URL = "scan.swarsel.win";
PAPERLESS_OCR_USER_ARGS = builtins.toJSON {
optimize = 1;
pdfa_image_compression = "lossless";
};
};
};
}
#+end_src
* Common NixOS
These are system-level settings specific to NixOS machines. All settings that are required on all machines go here.
** General
Section for all settings that are not really deserving of their own section.
#+begin_src nix :tangle profiles/common/nixos.nix
{ config, lib, pkgs, inputs, ... }:
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
# login keymap
services.xserver = {
layout = "us";
xkbVariant = "altgr-intl";
};
# mount NAS drive
# works only at home, but w/e
fileSystems."/mnt/smb" = {
device = "//192.168.1.3/Eternor";
fsType = "cifs";
options = let
# this line prevents hanging on network split
automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
in ["${automount_opts},credentials=/etc/nixos/smb-secrets,uid=1000,gid=100"];
};
# enable flakes - urgent line!!
nix.settings.experimental-features = ["nix-command" "flakes"];
environment.sessionVariables.NIXOS_OZONE_WL = "1";
# correct time between linux and windows
time.hardwareClockInLocalTime = true;
# dont style GRUB with stylix
stylix.targets.grub.enable = false; # the styling makes grub more ugly
# cura fix
# xdg.portal = {
# enable = true;
# extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
# wlr.enable = true;
# config = {
# common = {
# default = [
# "*"
# ];
# };
# };
# };
# wayland-related
security.polkit.enable = true;
hardware.opengl = {
enable = true;
driSupport = true;
driSupport32Bit = true;
};
# audio
sound.enable = true;
# nixpkgs.config.pulseaudio = true;
hardware.pulseaudio= {
enable = true;
package = pkgs.pulseaudioFull;
};
hardware.enableAllFirmware = true;
hardware.bluetooth.powerOnBoot = true;
hardware.bluetooth.settings = {
General = {
Enable = "Source,Sink,Media,Socket";
};
};
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
networking.networkmanager.enable = true;
time.timeZone = "Europe/Vienna";
i18n.defaultLocale = "en_US.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "de_AT.UTF-8";
LC_IDENTIFICATION = "de_AT.UTF-8";
LC_MEASUREMENT = "de_AT.UTF-8";
LC_MONETARY = "de_AT.UTF-8";
LC_NAME = "de_AT.UTF-8";
LC_NUMERIC = "de_AT.UTF-8";
LC_PAPER = "de_AT.UTF-8";
LC_TELEPHONE = "de_AT.UTF-8";
LC_TIME = "de_AT.UTF-8";
};
#+end_src
** System Packages
Mostly used to install some compilers and lps's that I want to have available when not using a devShell flake.
#+begin_src nix :tangle profiles/common/nixos.nix
environment.systemPackages = with pkgs; [
# yubikey packages
gnupg
yubikey-personalization
yubikey-personalization-gui
yubico-pam
yubioath-flutter
yubikey-manager
yubikey-manager-qt
yubico-piv-tool
pinentry
# theme related
gnome.adwaita-icon-theme
# kde-connect
xdg-desktop-portal
# bluetooth
bluez
# lsp-related -------------------------------
# nix
rnix-lsp
# latex
texlab
ghostscript_headless
# rust
rust-analyzer
clippy
rustfmt
# cpp
clang-tools
# + cuda
cudatoolkit
#lsp-bridge / python
gcc
gdb
(python3.withPackages(ps: with ps; [ jupyter ipython pyqt5 epc orjson sexpdata six setuptools paramiko numpy pandas scipy matplotlib requests debugpy flake8 gnureadline python-lsp-server]))
# (python3.withPackages(ps: with ps; [ jupyter ipython pyqt5 numpy pandas scipy matplotlib requests debugpy flake8 gnureadline python-lsp-server]))
# --------------------------------------------
];
#+end_src
** Programs (including zsh setup)
Some programs profit from being installed through dedicated NixOS settings on system-level; these go here. Notably the zsh setup goes here and cannot be deleted under any circumstances.
#+begin_src nix :tangle profiles/common/nixos.nix
programs.dconf.enable = true;
programs.evince.enable = true;
programs.kdeconnect.enable = true;
# zsh section, do not delete ------
programs.zsh.enable = true;
users.defaultUserShell = pkgs.zsh;
environment.shells = with pkgs; [ zsh ];
environment.pathsToLink = [ "/share/zsh" ];
# ---------------------------------
#+end_src
** Services
Setting up some hardware services as well as keyboard related settings. Here we make sure that we can use the CAPS key as a ESC/CTRL double key, which is a lifesaver.
#+begin_src nix :tangle profiles/common/nixos.nix
services.blueman.enable = true;
# enable discovery and usage of network devices (esp. printers)
services.printing.enable = true;
services.avahi = {
enable = true;
nssmdns = true;
openFirewall = true;
};
# nautilus file manager
services.gvfs.enable = true;
# Make CAPS work as a dual function ESC/CTRL key
services.interception-tools = {
enable = true;
udevmonConfig = let
dualFunctionKeysConfig = builtins.toFile "dual-function-keys.yaml" ''
TIMING:
TAP_MILLISEC: 200
DOUBLE_TAP_MILLISEC: 0
MAPPINGS:
- KEY: KEY_CAPSLOCK
TAP: KEY_ESC
HOLD: KEY_LEFTCTRL
'';
in ''
- JOB: |
${pkgs.interception-tools}/bin/intercept -g $DEVNODE \
| ${pkgs.interception-tools-plugins.dual-function-keys}/bin/dual-function-keys -c ${dualFunctionKeysConfig} \
| ${pkgs.interception-tools}/bin/uinput -d $DEVNODE
DEVICE:
EVENTS:
EV_KEY: [KEY_CAPSLOCK]
'';
};
#+end_src
** Yubikey settings
It makes sense to house these settings in their own section, since they are all needed really. Note that the starting of the gpg-agent is done in the sway settings, to also perform this step of the setup for non NixOS-machines at the same time.
The exception is the system packages, since that cannot be defined twice in the same file (common.nix). The comment is left in as a remider for that.
#+begin_src nix :tangle profiles/common/nixos.nix
programs.ssh.startAgent = false;
services.pcscd.enable = true;
# environment.systemPackages = with pkgs; [
# --- IN SYSTEM PACKAGES SECTION ---
# ];
services.udev.packages = with pkgs; [
yubikey-personalization
];
#+end_src
** System Login
This section houses the greetd related settings. I do not really want to use a display manager, but it is useful to have setup in some ways - in my case for starting sway on system startup. Notably the default user login setting that is commented out here goes into the *system specific* settings, make sure to update it there
#+begin_src nix :tangle profiles/common/nixos.nix
services.greetd = {
enable = true;
settings = {
initial_session.command = "sway";
# initial_session.user ="swarsel";
default_session.command = ''
${pkgs.greetd.tuigreet}/bin/tuigreet \
--time \
--asterisks \
--user-menu \
--cmd sway
'';
};
};
environment.etc."greetd/environments".text = ''
sway
'';
#+end_src
* Common Home-Manager
** Installed packages
Here are defined some packages that I would like to use across all my machines. Most of these should not require further setup. Notably the cura package is severely outdated on nixpkgs, so I just fetch a more recent AppImage and run that instead.
Also, I define some useful shell scripts here.
#+begin_src nix :tangle profiles/common/home.nix
{ config, pkgs, lib, fetchFromGitHub , ... }:
{
home.packages = with pkgs; [
# audio stuff
spek # spectrum analyzer
losslessaudiochecker
ffmpeg_5-full
flac
# "big" programs
filebot
gimp
zoom-us
# nomacs
libreoffice-qt
xournalpp
obsidian
spotify
discord
nextcloud-client
spotify-tui
schildichat-desktop
# kyria
qmk
qmk-udev-rules
# games
lutris
wine
# firefox related
tridactyl-native
# mako related
mako
libnotify
# general utilities
unrar
samba
cifs-utils
zbar # qr codes
readline
autotiling
brightnessctl
libappindicator-gtk3
sqlite
speechd
networkmanagerapplet
psmisc # kill etc
# jq # used for searching the i3 tree in check<xxx>.sh files
# specifically needed for anki
# mpv
anki-bin
# dirvish file previews
fd
imagemagick
poppler
ffmpegthumbnailer
mediainfo
gnutar
unzip
#nautilus
gnome.nautilus
xfce.tumbler
libgsf
# wayland stuff
wtype
wl-clipboard
wl-mirror
# screenshotting tools
grim
slurp
# the following packages are used (in some way) by waybar
playerctl
pavucontrol
pamixer
# gnome.gnome-clocks
# wlogout
# jdiskreport
syncthingtray
# monitor
#keychain
qalculate-gtk
gcr # needed for gnome-secrets to work
gnome.seahorse
# sops-related
sops
ssh-to-age
# mail related packages
mu
# latex and related packages
(pkgs.texlive.combine {
inherit (pkgs.texlive) scheme-full
dvisvgm dvipng # for preview and export as html
wrapfig amsmath ulem hyperref capt-of;
})
# font stuff
(nerdfonts.override { fonts = [ "FiraMono" "FiraCode" "NerdFontsSymbolsOnly"]; })
noto-fonts-emoji
font-awesome_5
noto-fonts
noto-fonts-cjk-sans
# cura
(let cura5 = appimageTools.wrapType2 rec {
name = "cura5";
version = "5.4.0";
src = fetchurl {
url = "https://github.com/Ultimaker/Cura/releases/download/${version}/UltiMaker-Cura-${version}-linux-modern.AppImage";
hash = "sha256-QVv7Wkfo082PH6n6rpsB79st2xK2+Np9ivBg/PYZd74=";
};
extraPkgs = pkgs: with pkgs; [ ];
}; in writeScriptBin "cura" ''
#! ${pkgs.bash}/bin/bash
# AppImage version of Cura loses current working directory and treats all paths relateive to $HOME.
# So we convert each of the files passed as argument to an absolute path.
# This fixes use cases like `cd /path/to/my/files; cura mymodel.stl anothermodel.stl`.
args=()
for a in "$@"; do
if [ -e "$a" ]; then
a="$(realpath "$a")"
fi
args+=("$a")
done
exec "${cura5}/bin/cura5" "''${args[@]}"
'')
#E: hides scratchpad depending on state, calls emacsclient for edit and then restores the scratchpad state
(pkgs.writeShellScriptBin "e" ''
bash ~/.dotfiles/scripts/editor_nowait.sh "$@"
'')
(pkgs.writeShellScriptBin "timer" ''
sleep "$1"; while true; do spd-say "$2"; sleep 0.5; done;
'')
(pkgs.writeScriptBin "project" ''
#! ${pkgs.bash}/bin/bash
if [ "$1" == "rust" ]; then
cp ~/.dotfiles/templates/rust_flake.nix ./flake.nix
cp ~/.dotfiles/templates/toolchain.toml .
elif [ "$1" == "cpp" ]; then
cp ~/.dotfiles/templates/cpp_flake.nix ./flake.nix
elif [ "$1" == "python" ]; then
cp ~/.dotfiles/templates/py_flake.nix ./flake.nix
elif [ "$1" == "cuda" ]; then
cp ~/.dotfiles/templates/cu_flake.nix ./flake.nix
elif [ "$1" == "latex" ]; then
if [ "$2" == "" ]; then
echo "No filename specified, usage: 'project latex <NAME>'"
exit 0
fi
cp ~/.dotfiles/templates/tex_standard.tex ./"$2".tex
exit 0
else
echo "No valid argument given. Valid arguments are rust cpp python, cuda"
exit 0
fi
echo "use flake" >> .envrc
direnv allow
'')
(pkgs.writeShellApplication {
name = "pass-fuzzel";
runtimeInputs = [ pkgs.pass pkgs.fuzzel ];
text = ''
shopt -s nullglob globstar
typeit=0
if [[ $# -ge 1 && $1 == "--type" ]]; then
typeit=1
shift
fi
export PASSWORD_STORE_DIR=~/.local/share/password-store
prefix=''${PASSWORD_STORE_DIR-~/.local/share/password-store}
password_files=( "$prefix"/**/*.gpg )
password_files=( "''${password_files[@]#"$prefix"/}" )
password_files=( "''${password_files[@]%.gpg}" )
password=$(printf '%s\n' "''${password_files[@]}" | fuzzel --dmenu "$@")
[[ -n $password ]] || exit
if [[ $typeit -eq 0 ]]; then
pass show -c "$password" &>/tmp/pass-fuzzel
else
pass show "$password" | { IFS= read -r pass; printf %s "$pass"; } | wtype -
fi
notify-send -u critical -a pass -t 1000 "Copied/Typed Password"
'';
})
];
# MIGHT NEED TO ENABLE THIS ON SURFACE!!
#+end_src
** sops
I use sops-nix to handle secrets that I want to have available on my machines at all times. Procedure to add a new machine:
- `ssh-keygen -t ed25519 -C "NAME sops"` in .ssh directory (or wherever) - name e.g. "sops"
- cat ~/.ssh/sops.pub | ssh-to-age | wl-copy
- add the output to .sops.yaml
- cp ~/.ssh/sops.pub ~/.dotfiles/secrets/keys/NAME.pub
- update entry for sops.age.sshKeyPaths
#+begin_src nix :tangle profiles/common/home.nix
sops.defaultSopsFile = "${config.home.homeDirectory}/.dotfiles/secrets/general/secrets.yaml";
sops.validateSopsFiles = false;
# sops.age.keyFile = "${config.home.homeDirectory}/.ssh/key.txt";
# This will generate a new key if the key specified above does not exist
# sops.age.generateKey = true;
# sops.gnupg.home = "/home/swarsel/.dotfiles/secrets/keys";
# since we are using the home-manager implementation, we need to specify the runtime path for each secret
sops.secrets.mrswarsel = {path = "/run/user/1000/secrets/mrswarsel";};
sops.secrets.nautilus = {path = "/run/user/1000/secrets/nautilus";};
sops.secrets.leon = {path = "/run/user/1000/secrets/leon";};
sops.secrets.caldav = {path = "${config.home.homeDirectory}/.emacs.d/.caldav";};
# sops.secrets.leon = { };
# sops.secrets.nautilus = { };
# sops.secrets.mrswarsel = { };
#+end_src
** SSH Machines
It is very convenient to have SSH aliases in place for machines that I use. This is mainly used for some server machines and some university clusters.
#+begin_src nix :tangle profiles/common/home.nix
programs.ssh= {
enable = true;
extraConfig = "SetEnv TERM=xterm-256color";
matchBlocks = {
"nginx" = {
hostname = "192.168.2.14";
port = 22;
user = "root";
};
"jellyfin" = {
hostname = "192.168.2.16";
port = 22;
user = "root";
};
"pfsense" = {
hostname = "192.168.1.1";
port = 22;
user = "root";
};
"proxmox" = {
hostname = "192.168.1.2";
port = 22;
user = "root";
};
"transmission" = {
hostname = "192.168.1.6";
port = 22;
user = "root";
};
"fetcher" = {
hostname = "192.168.1.192";
port = 22;
user = "root";
};
"omv" = {
hostname = "192.168.1.3";
port = 22;
user = "root";
};
"webbot" = {
hostname = "192.168.1.11";
port = 22;
user = "root";
};
"plex" = {
hostname = "192.168.1.16";
port = 22;
user = "root";
};
"nextcloud" = {
hostname = "192.168.2.5";
port = 22;
user = "root";
};
"subsonic" = {
hostname = "192.168.2.13";
port = 22;
user = "root";
};
"spotify" = {
hostname = "192.168.1.17";
port = 22;
user = "root";
};
"wordpress" = {
hostname = "192.168.2.7";
port = 22;
user = "root";
};
"turn" = {
hostname = "192.168.2.17";
port = 22;
user = "root";
};
"hugo" = {
hostname = "192.168.2.19";
port = 22;
user = "root";
};
"matrix" = {
hostname = "192.168.2.20";
port = 22;
user = "root";
};
"matrix2" = {
hostname = "192.168.2.20";
port = 22;
user = "root";
};
"database" = {
hostname = "192.168.2.21";
port = 22;
user = "root";
};
"minecraft" = {
hostname = "130.61.119.129";
port = 22;
user = "opc";
};
"sync" = {
hostname = "193.122.53.173";
port = 22;
user = "root"; #this is a oracle vm server but needs root due to nixos-infect
};
"pkv" = {
hostname = "46.232.248.161";
port = 22;
user = "root";
};
"calibre" = {
hostname = "192.168.2.22";
port = 22;
user = "root";
};
"nebula" = {
hostname = "128.131.171.15";
port = 22;
user = "amp23s56";
compression = true;
identityFile = "~/.ssh/id_ed25519";
proxyCommand = "ssh -p 1022 -i ~/.ssh/id_ed25519 -q -W %h:%p %r@venus.par.tuwien.ac.at";
extraOptions = {
"TCPKeepAlive" = "yes";
};
};
"efficient" = {
hostname = "g0.complang.tuwien.ac.at";
port = 22;
forwardAgent = true;
user = "ep01427399";
# leaving the below lines in for future reference
# remoteForwards = [
# {
# bind.address = "/run/user/21217/gnupg/S.gpg-agent";
# host.address = "/run/user/1000/gnupg/S.gpg-agent.extra";
# }
# {
# bind.address = "/run/user/21217/gnupg/S.gpg-agent.ssh";
# host.address = "/run/user/1000/gnupg/S.gpg-agent.ssh";
# }
# ];
# extraOptions = {
# "RemoteForward" = "/run/user/21217/gnupg/S.gpg-agent /run/user/1000/gnupg/S.gpg-agent.extra";
# "StreamLocalBindUnlink" = "yes";
# "RemoteForward" = "/run/user/21217/gnupg/S.gpg-agent.ssh /run/user/1000/gnupg/S.gpg-agent.ssh";
# };
# setEnv = {
# "TERM" = "xterm";
# };
};
"hydra" = {
hostname = "128.131.171.215";
port = 22;
user = "hpc23w33";
compression = true;
forwardAgent = true;
# identityFile = "~/.ssh/id_tuwien_hpc";
# proxyCommand = "ssh -p 1022 -i ~/.ssh/id_tuwien_hpc -q -W %h:%p %r@venus.par.tuwien.ac.at";
proxyCommand = "ssh -p 1022 -q -W %h:%p %r@venus.par.tuwien.ac.at";
extraOptions = {
"TCPKeepAlive" = "yes";
};
};
};
};
#+end_src
** Fonts + Theme
These section allows home-manager to allow theme settings, and handles some other appearance-related settings like cursor styles. Interestingly, system icons (adwaita) still need to be setup on system-level, and will break if defined here.
#+begin_src nix :tangle profiles/common/home.nix
stylix.targets.emacs.enable = false;
# fonts.fontconfig.enable = true;
# gtk = {
# enable = true;
# theme = {
# name = "Arc-Dark";
# package = pkgs.arc-theme;
# };
# cursorTheme = {
# name = "capitaine-cursors";
# package = pkgs.capitaine-cursors;
# };
# gtk3.extraConfig = {
# Settings = ''
# gtk-application-prefer-dark-theme=1
# '';
# };
# gtk4.extraConfig = {
# Settings = ''
# gtk-application-prefer-dark-theme=1
# '';
# };
# };
#+end_src
** TODO Desktop Entries
Some programs lack a dmenu launcher - I define them myself here.
TODO: Non-NixOS machines (=sp3) should not use these by default, but instead the programs prefixed with "nixGL". I need to figure out how to automate this process, as it is not feasible to write desktop entries for all programs installed on that machine.
#+begin_src nix :tangle profiles/common/home.nix
xdg.desktopEntries = {
cura = {
name = "Ultimaker Cura";
genericName = "Cura";
exec = "cura";
terminal = false;
categories = [ "Application"];
};
anki = {
name = "Anki Flashcards";
genericName = "Anki";
exec = "anki";
terminal = false;
categories = [ "Application"];
};
schlidichat = {
name = "SchildiChat Matrix Client";
genericName = "SchildiChat";
exec = "schildichat-desktop -enable-features=UseOzonePlatform -ozone-platform=wayland --disable-gpu-driver-bug-workarounds";
terminal = false;
categories = [ "Application"];
};
# currently unused but kept for possible future use-case
# not needed as long as schildichat is working properly
# element = {
# name = "Element Matrix Client";
# genericName = "Element";
# exec = "element-desktop";
# terminal = false;
# categories = [ "Application"];
# };
};
#+end_src
** TODO Sourcing dotfiles and environment variables
This section should be used in order to symlink already existing configuration files using `home.file` and setting session variables using `home.sessionVariables`.
TODO At the moment this is only used for emacs' init.el and early-init.el - I plan to migrate them to a NUR emacs-init setup at some point in the future, but that is a lot of work and will take possibly more time than I am able to spend on this right now
As for the `home.sessionVariables`, it should be noted that environment variables that are needed at system start should NOT be loaded here, but instead in `programs.zsh.config.extraSessionCommands` (in the home-manager programs section). This is also where all the wayland related variables are stored.
#+begin_src nix :tangle profiles/common/home.nix
home.file = {
"init.el" = {
source = ../../programs/emacs/init.el;
target = ".emacs.d/init.el";
};
"early-init.el" = {
source = ../../programs/emacs/early-init.el;
target = ".emacs.d/early-init.el";
};
};
home.sessionVariables = {
EDITOR = "bash ~/.dotfiles/scripts/editor.sh";
EDITORBAK = "bash ~/.dotfiles/scripts/editor.sh";
# GTK_THEME = "Arc-Dark";
};
#+end_src
** Programs
*** General
#+begin_src nix :tangle profiles/common/home.nix
programs.password-store = {
enable = true;
package = pkgs.pass.withExtensions (exts: [exts.pass-otp]);
};
# zsh Integration is enabled by default for these
programs.bottom.enable = true;
programs.imv.enable = true;
programs.sioyek.enable = true;
programs.bat.enable = true;
programs.carapace.enable = true;
programs.wlogout.enable = true;
programs.swayr.enable = true;
programs.yt-dlp.enable = true;
programs.mpv.enable = true;
programs.jq.enable = true;
programs.nix-index.enable = true;
programs.ripgrep.enable = true;
programs.pandoc.enable = true;
programs.fzf.enable = true;
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
programs.zoxide.enable = true;
programs.eza = {
enable = true;
enableAliases = true;
icons = true;
git = true;
extraOptions = [
"-l"
"--group-directories-first"
];
};
programs.git = {
enable = true;
aliases = {
a = "add";
c = "commit";
cl = "clone";
co = "checkout";
b = "branch";
i = "init";
m = "merge";
s = "status";
r = "restore";
p = "pull";
pp = "push";
};
signing = {
key = "0x76FD3810215AE097";
signByDefault = true;
};
userEmail = "leon.schwarzaeugl@gmail.com";
userName = "Swarsel";
};
#+end_src
*** Fuzzel
#+begin_src nix :tangle profiles/common/home.nix
programs.fuzzel = {
enable = true;
settings = {
main = {
layer = "overlay";
# font = "Monospace:size=8";
lines = "10";
width = "40";
};
colors = {
# background="293744dd";
# text="f8f8f2ff";
# match="8be9fdff";
# selection-match="8be9fdff";
# selection="44475add";
# selection-text="f8f8f2ff";
# border="ffd700ff";
};
border.radius = "0";
};
};
#+end_src
*** Starship
#+begin_src nix :tangle profiles/common/home.nix
programs.starship = {
enable = true;
enableZshIntegration = true;
settings = {
add_newline = false;
format = "$character";
right_format = "$all";
command_timeout = 3000;
directory.substitutions = {
"Documents" = "󰈙 ";
"Downloads" = " ";
"Music" = " ";
"Pictures" = " ";
};
git_status = {
style = "bg:#394260";
format = "[[($all_status$ahead_behind )](fg:#769ff0 bg:#394260)]($style)";
};
character = {
success_symbol = "[λ](bold green)";
error_symbol = "[λ](bold red)";
};
aws.symbol = " ";
buf.symbol = " ";
c.symbol = " ";
conda.symbol = " ";
dart.symbol = " ";
directory.read_only = " 󰌾";
docker_context.symbol = " ";
elixir.symbol = " ";
elm.symbol = " ";
fossil_branch.symbol = " ";
git_branch.symbol = " ";
golang.symbol = " ";
guix_shell.symbol = " ";
haskell.symbol = " ";
haxe.symbol = " ";
hg_branch.symbol = " ";
hostname.ssh_symbol = " ";
java.symbol = " ";
julia.symbol = " ";
lua.symbol = " ";
memory_usage.symbol = "󰍛 ";
meson.symbol = "󰔷 ";
nim.symbol = "󰆥 ";
nix_shell.symbol = " ";
nodejs.symbol = " ";
os.symbols = {
Alpaquita = " ";
Alpine = " ";
Amazon = " ";
Android = " ";
Arch = " ";
Artix = " ";
CentOS = " ";
Debian = " ";
DragonFly = " ";
Emscripten = " ";
EndeavourOS = " ";
Fedora = " ";
FreeBSD = " ";
Garuda = "󰛓 ";
Gentoo = " ";
HardenedBSD = "󰞌 ";
Illumos = "󰈸 ";
Linux = " ";
Mabox = " ";
Macos = " ";
Manjaro = " ";
Mariner = " ";
MidnightBSD = " ";
Mint = " ";
NetBSD = " ";
NixOS = " ";
OpenBSD = "󰈺 ";
openSUSE = " ";
OracleLinux = "󰌷 ";
Pop = " ";
Raspbian = " ";
Redhat = " ";
RedHatEnterprise = " ";
Redox = "󰀘 ";
Solus = "󰠳 ";
SUSE = " ";
Ubuntu = " ";
Unknown = " ";
Windows = "󰍲 ";
};
package.symbol = "󰏗 ";
pijul_channel.symbol = " ";
python.symbol = " ";
rlang.symbol = "󰟔 ";
ruby.symbol = " ";
rust.symbol = " ";
scala.symbol = " ";
};
};
#+end_src
*** Kitty
Kitty is the terminal emulator of choice for me, it is nice to configure using nix, fast, and has a nice style.
#+begin_src nix :tangle profiles/common/home.nix
programs.kitty = {
enable = true;
keybindings = {
"ctrl+shift+left" = "no_op";
"ctrl+shift+right" = "no_op";
"ctrl+shift+home" = "no_op";
"ctrl+shift+end" = "no_op";
};
# theme = "citylights";
};
#+end_src
*** zsh
zsh is clearly the most convenient shell for me and it happens to be super neat to configure within home manager.
#+begin_src nix :tangle profiles/common/home.nix
programs.zsh = {
enable = true;
shellAliases = {
hg = "history | grep";
hmswitch = "cd ~/.dotfiles; home-manager --flake .#$(whoami)@$(hostname) switch; cd -;";
nswitch = "cd ~/.dotfiles; sudo nixos-rebuild --flake .#$(hostname) switch; cd -;";
edithome = "bash ~/.dotfiles/scripts/editor.sh ~/.dotfiles/Nix.org";
magit = "emacsclient -nc -e \"(magit-status)\"";
config="git --git-dir=$HOME/.cfg/ --work-tree=$HOME";
g="git";
c="git --git-dir=$HOME/.dotfiles/.git --work-tree=$HOME/.dotfiles/";
passpush = "cd ~/.local/share/password-store; git add .; git commit -m 'pass file changes'; git push; cd -;";
passpull = "cd ~/.local/share/password-store; git pull; cd -;";
};
enableAutosuggestions = true;
enableCompletion = true;
syntaxHighlighting.enable = true;
autocd = false;
cdpath = [
"~/.dotfiles"
# "~/Documents/GitHub"
];
defaultKeymap = "emacs";
dirHashes = {
dl = "$HOME/Downloads";
};
history = {
expireDuplicatesFirst = true;
path = "$HOME/.histfile";
save = 10000;
size = 10000;
};
historySubstringSearch.enable = true;
initExtra = ''
bindkey "^[[1;5D" backward-word
bindkey "^[[1;5C" forward-word
'';
};
#+end_src
*** Mail
#+begin_src nix :tangle profiles/common/home.nix
programs.mbsync = {
enable = true;
};
# this is needed so that mbsync can use the passwords from sops
systemd.user.services.mbsync.Unit.After = [ "sops-nix.service" ];
programs.msmtp = {
enable = true;
};
programs.mu = {
enable = true;
};
accounts.email = {
maildirBasePath = "Mail";
accounts.leon = {
primary = true;
address = "leon.schwarzaeugl@gmail.com";
userName = "leon.schwarzaeugl@gmail.com";
realName = "Leon Schwarzäugl";
passwordCommand = "cat ${config.sops.secrets.leon.path}";
# passwordCommand = "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.local/share/password-store/mail/mbsync/leon.schwarzaeugl@gmail.com.gpg";
gpg = {
key = "0x76FD3810215AE097";
signByDefault = true;
};
imap.host = "imap.gmail.com";
smtp.host = "smtp.gmail.com";
mu.enable = true;
msmtp = {
enable = true;
};
mbsync = {
enable = true;
create= "maildir";
expunge = "both";
patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"];
extraConfig = {
channel = {
Sync = "All";
};
account = {
Timeout = 120;
PipelineDepth = 1;
};
};
};
};
accounts.nautilus = {
primary = false;
address = "nautilus.dw@gmail.com";
userName = "nautilus.dw@gmail.com";
realName = "Nautilus";
passwordCommand = "cat ${config.sops.secrets.nautilus.path}";
# passwordCommand = "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.local/share/password-store/mail/mbsync/nautilus.dw@gmail.com.gpg";
imap.host = "imap.gmail.com";
smtp.host = "smtp.gmail.com";
msmtp.enable = true;
mu.enable = true;
mbsync = {
enable = true;
create= "maildir";
expunge = "both";
patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"];
extraConfig = {
channel = {
Sync = "All";
};
account = {
Timeout = 120;
PipelineDepth = 1;
};
};
};
};
accounts.mrswarsel = {
primary = false;
address = "mrswarsel@gmail.com";
userName = "mrswarsel@gmail.com";
realName = "Swarsel";
# passwordCommand = "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.local/share/password-store/mail/mbsync/mrswarsel@gmail.com.gpg";
passwordCommand = "cat ${config.sops.secrets.mrswarsel.path}";
imap.host = "imap.gmail.com";
smtp.host = "smtp.gmail.com";
msmtp.enable = true;
mu.enable = true;
mbsync = {
enable = true;
create= "maildir";
expunge = "both";
patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"];
extraConfig = {
channel = {
Sync = "All";
};
account = {
Timeout = 120;
PipelineDepth = 1;
};
};
};
};
};
#+end_src
*** Emacs
#+begin_src nix :tangle profiles/common/home.nix
# enable emacs overlay for bleeding edge features
# also read init.el file and install use-package packages
programs.emacs = {
enable = true;
package = (pkgs.emacsWithPackagesFromUsePackage {
config = ../../Emacs.org; # tangling my Emacs.org file here instead of directly putting init.el allows avoidance of automatically installing packages in blocks using UTF-8 characters, which would break the nix evaluation happening in this line. This line is also the reason why (for now) the Emacs configuration lives in a different .org file
package = pkgs.emacs-pgtk;
alwaysEnsure = true;
alwaysTangle = true;
extraEmacsPackages = epkgs: [
epkgs.mu4e
epkgs.use-package
epkgs.lsp-bridge
epkgs.doom-themes
# build the rest of the packages myself
# org-calfw is severely outdated on MELPA and throws many warnings on emacs startup
# build the package from the haji-ali fork, which is well-maintained
(epkgs.trivialBuild rec {
pname = "calfw";
version = "1.0.0-20231002";
src = pkgs.fetchFromGitHub {
owner = "haji-ali";
repo = "emacs-calfw";
rev = "bc99afee611690f85f0cd0bd33300f3385ddd3d3";
hash = "sha256-0xMII1KJhTBgQ57tXJks0ZFYMXIanrOl9XyqVmu7a7Y=";
};
packageRequires = [ epkgs.howm ];
})
(epkgs.trivialBuild rec {
pname = "fast-scroll";
version = "1.0.0-20191016";
src = pkgs.fetchFromGitHub {
owner = "ahungry";
repo = "fast-scroll";
rev = "3f6ca0d5556fe9795b74714304564f2295dcfa24";
hash = "sha256-w1wmJW7YwXyjvXJOWdN2+k+QmhXr4IflES/c2bCX3CI=";
};
packageRequires = [];
})
];
});
};
#+end_src
*** Waybar
Again I am just using the first bar option here that I was able to find good understandable documentation for. Of note is that the `cpu` section's `format` is not defined here, but in section 1 (since not every machine has the same number of cores)
#+begin_src nix :tangle profiles/common/home.nix
programs.waybar = {
enable = true;
# systemd.enable = true;
settings = {
mainBar = {
layer = "top";
position = "top";
modules-left = [ "sway/workspaces" "custom/outer-right-arrow-dark" "sway/window"];
modules-center = [ "sway/mode" "custom/configwarn" ];
"sway/mode" = {
format = "<span style=\"italic\" font-weight=\"bold\">{}</span>";
};
"custom/configwarn" = {
exec= "bash ~/.dotfiles/scripts/checkconfigstatus.sh";
interval= 60;
};
"group/hardware" = {
orientation = "inherit";
drawer = {
"transition-left-to-right" = true;
};
modules = [
"tray"
"temperature"
"custom/left-arrow-light"
"disk"
"custom/left-arrow-dark"
"memory"
"custom/left-arrow-light"
"cpu"
"custom/left-arrow-dark"
];
};
temperature = {
critical-threshold = 80;
format-critical = " {temperatureC}°C";
format = " {temperatureC}°C";
};
mpris = {
format= "{player_icon} {title} <small>[{position}/{length}]</small>";
format-paused= "{player_icon} <i>{title} <small>[{position}/{length}]</small></i>";
player-icons= {
"default" = " ";
"mpv" = "🎵 ";
"spotify" = " ";
};
status-icons= {
"paused"= " ";
};
interval = 1;
title-len = 20;
artist-len = 20;
album-len = 10;
};
"custom/left-arrow-dark" = {
format = "";
tooltip = false;
};
"custom/outer-left-arrow-dark"= {
format = "";
tooltip = false;
};
"custom/left-arrow-light"= {
format= "";
tooltip= false;
};
"custom/right-arrow-dark"= {
format= "";
tooltip= false;
};
"custom/outer-right-arrow-dark"= {
format= "";
tooltip= false;
};
"custom/right-arrow-light"= {
format= "";
tooltip= false;
};
"sway/workspaces"= {
disable-scroll= true;
format= "{name}";
};
"clock#1"= {
min-length= 8;
interval= 1;
format= "{:%H:%M:%S}";
# on-click-right= "gnome-clocks";
tooltip-format= "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>";
};
"clock#2"= {
format= "{:%d. %B %Y}";
# on-click-right= "gnome-clocks";
tooltip-format= "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>";
};
pulseaudio= {
format= "{icon} {volume:2}%";
format-bluetooth= "{icon} {volume}%";
format-muted= "MUTE";
format-icons= {
headphones= "";
default= [
""
""
];
};
scroll-step= 1;
on-click= "pamixer -t";
on-click-right= "pavucontrol";
};
memory= {
interval= 5;
format= " {}%";
tooltip-format= "Memory: {used:0.1f}G/{total:0.1f}G\nSwap: {swapUsed}G/{swapTotal}G";
};
cpu= {
min-length= 6;
interval= 5;
format-icons = ["" "" "" "" "" "" "" ""];
# on-click-right= "com.github.stsdc.monitor";
on-click-right= "kitty -o confirm_os_window_close=0 btm";
};
battery= {
states= {
"warning"= 60;
"error"= 30;
"critical"= 15;
};
interval=5;
format= "{icon} {capacity}%";
format-charging= "{capacity}% ";
format-plugged= "{capacity}% ";
format-icons= [
""
""
""
""
""
];
on-click-right= "wlogout -p layer-shell";
};
disk= {
interval= 30;
format= "Disk {percentage_used:2}%";
path= "/";
states= {
"warning"= 80;
"critical"= 90;
};
tooltip-format = "{used} used out of {total} on {path} ({percentage_used}%)\n{free} free on {path} ({percentage_free}%)";
};
tray= {
icon-size= 20;
};
network= {
interval = 5;
format-wifi= "{signalStrength}% ";
format-ethernet= "";
format-linked= "{ifname} (No IP) ";
format-disconnected= "Disconnected ";
format-alt= "{ifname}: {ipaddr}/{cidr}";
tooltip-format-ethernet= "{ifname} via {gwaddr}: {essid} {ipaddr}/{cidr}\n\n{bandwidthUpBytes} {bandwidthDownBytes}";
tooltip-format-wifi= "{ifname} via {gwaddr}: {essid} {ipaddr}/{cidr} \n{signaldBm}dBm @ {frequency}MHz\n\n{bandwidthUpBytes} {bandwidthDownBytes}";
};
};
};
style = ''
@define-color foreground #fdf6e3;
@define-color background #1a1a1a;
@define-color background-alt #292b2e;
@define-color foreground-warning #268bd2;
@define-color background-warning @background;
@define-color foreground-error red;
@define-color background-error @background;
@define-color foreground-critical gold;
@define-color background-critical blue;
,* {
border: none;
border-radius: 0;
font-family: "FiraCode Nerd Font Propo", "Font Awesome 5 Free";
font-size: 14px;
min-height: 0;
margin: -1px 0px;
}
window#waybar {
background: transparent;
color: @foreground;
transition-duration: .5s;
}
window#waybar.hidden {
opacity: 0.2;
}
#mpris {
padding: 0 10px;
background-color: transparent;
color: #1DB954;
font-family: Monospace;
font-size: 12px;
}
#custom-right-arrow-dark,
#custom-left-arrow-dark {
color: @background;
background: @background-alt;
font-size: 24px;
}
#window {
font-size: 12px;
padding: 0 20px;
}
#mode {
background: @background-critical;
color: @foreground-critical;
padding: 0 3px;
}
#custom-configwarn {
color: black;
padding: 0 3px;
animation-name: configblink;
animation-duration: 0.5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#custom-outer-right-arrow-dark,
#custom-outer-left-arrow-dark {
color: @background;
font-size: 24px;
}
#custom-outer-left-arrow-dark,
#custom-left-arrow-dark,
#custom-left-arrow-light {
margin: 0 -1px;
}
#custom-right-arrow-light,
#custom-left-arrow-light {
color: @background-alt;
background: @background;
font-size: 24px;
}
#workspaces,
#clock.1,
#clock.2,
#clock.3,
#pulseaudio,
#memory,
#cpu,
#temperature,
#mpris,
#tray {
background: @background;
}
#network,
#clock.2,
#battery,
#cpu,
#custom-pseudobat,
#disk {
background: @background-alt;
}
#workspaces button {
padding: 0 2px;
color: #fdf6e3;
}
#workspaces button.focused {
color: @foreground-warning;
}
#workspaces button:hover {
background: @foreground;
color: @background;
border: @foreground;
padding: 0 2px;
box-shadow: inherit;
text-shadow: inherit;
}
#workspaces button.urgent {
color: @background-critical;
background: @foreground-critical;
}
#network {
color: #cc99c9;
}
#temperature {
color: #9ec1cf;
}
#disk {
/*color: #b58900;*/
color: #9ee09e;
}
#disk.warning {
color: @foreground-error;
background-color: @background-error;
}
#disk.critical,
#temperature.critical {
color: @foreground-critical;
background-color: @background-critical;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#pulseaudio.muted {
color: @foreground-error;
}
#memory {
/*color: #2aa198;*/
color: #fdfd97;
}
#cpu {
/*color: #6c71c4;*/
color: #feb144;
}
#pulseaudio {
/*color: #268bd2;*/
color: #ff6663;
}
#battery,
#custom-pseudobat {
color: cyan;
}
#battery.discharging {
color: #859900;
}
@keyframes blink {
to {
color: @foreground-error;
background-color: @background-error;
}
}
@keyframes configblink {
to {
color: @foreground-error;
background-color: transparent;
}
}
#battery.critical:not(.charging) {
color: @foreground-critical;
background-color: @background-critical;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#clock.1,
#clock.2,
#clock.3 {
font-family: Monospace;
}
#clock,
#pulseaudio,
#memory,
#cpu,
#tray,
#temperature,
#network,
#mpris,
#battery,
#custom-pseudobat,
#disk {
padding: 0 3px;
}
'';
};
#+end_src
*** Firefox
#+begin_src nix :tangle profiles/common/home.nix
programs.firefox = {
enable = true;
package = pkgs.firefox.override {
nativeMessagingHosts = [
pkgs.tridactyl-native
pkgs.browserpass
pkgs.plasma5Packages.plasma-browser-integration
];
};
policies = {
CaptivePortal = false;
DisableFirefoxStudies = true;
DisablePocket = true;
DisableTelemetry = true;
DisableFirefoxAccounts = false;
NoDefaultBookmarks = true;
OfferToSaveLogins = false;
OfferToSaveLoginsDefault = false;
EnableTrackingProtection = true;
};
profiles.default = {
isDefault = true;
extensions = with pkgs.nur.repos.rycee.firefox-addons; [
tridactyl
browserpass
clearurls
darkreader
enhancer-for-youtube
istilldontcareaboutcookies
translate-web-pages
ublock-origin
reddit-enhancement-suite
pushbullet
sponsorblock
web-archives
single-file
widegithub
enhanced-github
unpaywall
# fastforwardteam
don-t-fuck-with-paste
plasma-integration
# build the rest of my firefox addons myself
# app id can be found in the manifest.json file of the .xpi
# (.xpi is just a normal archive)
# url can be found by copy url of the "add extension" button on the addon page
# the rest of the information is also found in the manifest.json, but might not be
# needed
(let version = "3.4.5.0";
in buildFirefoxXpiAddon {
pname = "bypass-paywalls-clean";
inherit version;
addonId = "magnolia@12.34";
url =
"https://gitlab.com/magnolia1234/bpc-uploads/-/raw/master/bypass_paywalls_clean-3.4.5.0.xpi";
sha256 = "703d30c15b88291bd0305cc59013693aea5f75a40ea98fb8e252d1c7bfb43514";
meta = with lib; {
homepage =
"https://gitlab.com/magnolia1234/bypass-paywalls-firefox-clean";
description = "Bypass Paywalls of (custom) news sites";
license = licenses.mit;
platforms = platforms.all;
};
})
(buildFirefoxXpiAddon {
pname = ":emoji:";
version = "0.1.3";
addonId = "gonelf@gmail.com";
url = "https://addons.mozilla.org/firefox/downloads/file/3365324/emojidots-0.1.3.xpi";
sha256 = "4f7cc25c478fe52eb82f37c9ff4978dcaa3f95020398c5b184e517f6efa2c201";
meta = with lib;
{
description = "emoji autocomplete anywhere on the internet";
mozPermissions = [ "https://gist.githubusercontent.com/gonelf/d8ae3ccb7902b501c4a5dd625d4089da/raw/5eeda197ba92f8c8139e846a1225d5640077e06f/emoji_pretty.json" "tabs" "storage"];
platforms = platforms.all;
};
})
];
search.engines = {
"Nix Packages" = {
urls = [{
template = "https://search.nixos.org/packages";
params = [
{ name = "type"; value = "packages"; }
{ name = "query"; value = "{searchTerms}"; }
];
}];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@np" ];
};
"NixOS Wiki" = {
urls = [{
template = "https://nixos.wiki/index.php?search={searchTerms}";
}];
iconUpdateURL = "https://nixos.wiki/favicon.png";
updateInterval = 24 * 60 * 60 * 1000; # every day
definedAliases = [ "@nw" ];
};
"NixOS Options" = {
urls = [{
template = "https://search.nixos.org/options";
params = [
{ name = "query"; value = "{searchTerms}"; }
];
}];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@no" ];
};
"Home Manager Options" = {
urls = [{ template = "https://mipmip.github.io/home-manager-option-search/";
params = [
{ name = "query"; value = "{searchTerms}"; }
];
}];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@hm" ];
};
"Google".metaData.alias = "@g";
};
search.force = true; # this is required because otherwise the search.json.mozlz4 symlink gets replaced on every firefox restart
};
};
#+end_src
*** Browserpass
#+begin_src nix :tangle profiles/common/home.nix
# programs.browserpass = {
# enable = true;
# browsers = [
# "firefox"
# ];
# };
#+end_src
** Services
Services that can be defined through home-manager should be defined here.
*** General
#+begin_src nix :tangle profiles/common/home.nix
services.gnome-keyring = {
enable = true;
};
services.mbsync = {
enable = false;
};
services.kdeconnect = {
enable = true;
indicator = true;
};
services.syncthing = {
enable = true;
};
# this enables the emacs server
services.emacs.enable = true;
#+end_src
*** Mako
The `extraConfig` section here CANNOT be reindented. This has something to do with how nix handles multiline strings, when indented Mako will fail to start. This might be a mako bug as well.
#+begin_src nix :tangle profiles/common/home.nix
services.mako = {
enable = true;
# backgroundColor = "#2e3440";
# borderColor = "#88c0d0";
borderRadius = 15;
borderSize = 1;
defaultTimeout = 5000;
height = 150;
icons = true;
ignoreTimeout = true;
layer = "overlay";
maxIconSize = 64;
sort = "-time";
width = 300;
# font = "monospace 10";
extraConfig = "[urgency=low]
border-color=#cccccc
[urgency=normal]
border-color=#d08770
[urgency=high]
border-color=#bf616a
default-timeout=3000
[category=mpd]
default-timeout=2000
group-by=category
";
};
#+end_src
** Sway
I am currently using SwayFX, which adds some nice effects to sway, like rounded corners and hiding the separator between title and content of a window.
#+begin_src nix :tangle profiles/common/home.nix
wayland.windowManager.sway = {
enable = true;
package = pkgs.swayfx;
systemd.enable = true;
systemd.xdgAutostart = true;
wrapperFeatures.gtk = true;
config = rec {
modifier = "Mod4";
terminal = "kitty";
menu = "fuzzel";
bars = [{ command = "waybar";}];
keybindings = let
modifier = config.wayland.windowManager.sway.config.modifier;
in {
"${modifier}+q" = "kill";
"${modifier}+f" = "exec firefox";
"${modifier}+Space" = "exec fuzzel";
"${modifier}+Shift+Space" = "floating toggle";
"${modifier}+e" = "exec emacsclient -nquc -a emacs -e \"(dashboard-open)\"";
"${modifier}+Shift+m" = "exec emacsclient -nquc -a emacs -e \"(mu4e)\"";
"${modifier}+Shift+c" = "exec emacsclient -nquc -a emacs -e \"(swarsel/open-calendar)\"";
"${modifier}+Shift+s" = "exec \"bash ~/.dotfiles/scripts/checkspotify.sh\"";
"${modifier}+m" = "exec \"bash ~/.dotfiles/scripts/checkspotifytui.sh\"";
"${modifier}+x" = "exec \"bash ~/.dotfiles/scripts/checkkitty.sh\"";
"${modifier}+d" = "exec \"bash ~/.dotfiles/scripts/checkdiscord.sh\"";
"${modifier}+Shift+r" = "exec \"bash ~/.dotfiles/scripts/restart.sh\"";
"${modifier}+Shift+F12" = "move scratchpad";
"${modifier}+F12" = "scratchpad show";
"${modifier}+c" = "exec qalculate-gtk";
"${modifier}+p" = "exec pass-fuzzel";
"${modifier}+Shift+p" = "exec pass-fuzzel --type";
"${modifier}+Escape" = "mode $exit";
# "${modifier}+Shift+Escape" = "exec com.github.stsdc.monitor";
"${modifier}+Shift+Escape" = "exec kitty -o confirm_os_window_close=0 btm";
"${modifier}+s" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png";
"${modifier}+i" = "exec \"bash ~/.dotfiles/scripts/startup.sh\"";
"${modifier}+1" = "workspace 1:";
"${modifier}+Shift+1" = "move container to workspace 1:";
"${modifier}+2" = "workspace 2:";
"${modifier}+Shift+2" = "move container to workspace 2:";
"${modifier}+3" = "workspace 3:";
"${modifier}+Shift+3" = "move container to workspace 3:";
"${modifier}+4" = "workspace 4:";
"${modifier}+Shift+4" = "move container to workspace 4:";
"${modifier}+5" = "workspace 5:";
"${modifier}+Shift+5" = "move container to workspace 5:";
"${modifier}+6" = "workspace 6:";
"${modifier}+Shift+6" = "move container to workspace 6:";
"${modifier}+7" = "workspace 7:";
"${modifier}+Shift+7" = "move container to workspace 7:";
"${modifier}+8" = "workspace 8:";
"${modifier}+Shift+8" = "move container to workspace 8:";
"${modifier}+9" = "workspace 9:";
"${modifier}+Shift+9" = "move container to workspace 9:";
"${modifier}+0" = "workspace 10:";
"${modifier}+Shift+0" = "move container to workspace 10:";
"XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +5%";
"XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -5%";
"${modifier}+Left" = "focus left";
"${modifier}+Right" = "focus right";
"${modifier}+Down" = "focus down";
"${modifier}+Up" = "focus up";
"${modifier}+Shift+Left" = "move left 40px";
"${modifier}+Shift+Right" = "move right 40px";
"${modifier}+Shift+Down" = "move down 40px";
"${modifier}+Shift+Up" = "move up 40px";
"${modifier}+h" = "focus left";
"${modifier}+l" = "focus right";
"${modifier}+j" = "focus down";
"${modifier}+k" = "focus up";
"${modifier}+Shift+h" = "move left 40px";
"${modifier}+Shift+l" = "move right 40px";
"${modifier}+Shift+j" = "move down 40px";
"${modifier}+Shift+k" = "move up 40px";
"${modifier}+Ctrl+Shift+c" = "reload";
"${modifier}+Shift+e" = "exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'";
"${modifier}+r" = "mode resize";
"${modifier}+Return" = "exec kitty";
};
modes = {
resize = {
Down = "resize grow height 10 px or 10 ppt";
Escape = "mode default";
Left = "resize shrink width 10 px or 10 ppt";
Return = "mode default";
Right = "resize grow width 10 px or 10 ppt";
Up = "resize shrink height 10 px or 10 ppt";
};
};
defaultWorkspace = "workspace 1:";
startup = [
{ command = "kitty -T kittyterm";}
{ command = "sleep 60; kitty -T spotifytui -o confirm_os_window_close=0 spt";}
];
window = {
border = 1;
titlebar = false;
};
assigns = {
# disabled, this is too annoying to be of use
# "1:一" = [{ app_id = "^firefox$"; }];
};
colors = {
focused = {
# background = "#080808";
# border = "#80a0ff";
# childBorder = "#80a0ff";
# indicator = "#080808";
# text = "#ffd700";
};
unfocused = {
# background = "#080808";
# border = "#80a0ff";
# childBorder = "#303030";
# indicator = "#80a0ff";
# text = "#c6c6c6";
};
};
floating = {
border = 1;
criteria = [
{title = "^Picture-in-Picture$";}
{app_id = "qalculate-gtk";}
{app_id = "org.gnome.clocks";}
{app_id = "com.github.stsdc.monitor";}
{app_id = "blueman";}
{app_id = "pavucontrol";}
{app_id = "syncthingtray";}
{app_id = "SchildiChat";}
{class = "Element";}
{title = "Element";}
{app_id = "com.nextcloud.desktopclient.nextcloud";}
{app_id = "gnome-system-monitor";}
{title = "(?:Open|Save) (?:File|Folder|As)";}
{title = "^Add$";}
{title = "com-jgoodies-jdiskreport-JDiskReport";}
{app_id = "discord";}
{window_role = "pop-up";}
{window_role = "bubble";}
{window_role = "dialog";}
{window_role = "task_dialog";}
{window_role = "menu";}
{window_role = "Preferences";}
];
titlebar = false;
};
window = {
commands = [
{
command = "opacity 0.95";
criteria = {
class = ".*";
};
}
{
command = "opacity 0.95";
criteria = {
app_id = ".*";
};
}
{
command = "opacity 0.99";
criteria = {
app_id = "firefox";
};
}
{
command = "sticky enable, shadows enable";
criteria = {
title="^Picture-in-Picture$";
};
}
{
command = "opacity 0.8, sticky enable, border normal, move container to scratchpad";
criteria = {
title="kittyterm";
};
}
{
command = "opacity 0.95, sticky enable, border normal, move container to scratchpad";
criteria = {
title="spotifytui";
};
}
{
command = "resize set width 60 ppt height 60 ppt, sticky enable, move container to scratchpad";
criteria = {
app_id="^$";
class="^$";
};
}
{
command = "resize set width 60 ppt height 60 ppt, sticky enable, move container to scratchpad";
criteria = {
class="Spotify";
};
}
{
command = "sticky enable";
criteria = {
app_id = "discord";
};
}
{
command = "resize set width 60 ppt height 60 ppt, sticky enable";
criteria = {
class = "Element";
};
}
{
command = "resize set width 60 ppt height 60 ppt, sticky enable";
criteria = {
app_id = "SchildiChat";
};
}
];
};
gaps = {
inner = 5;
};
};
extraSessionCommands =''
export SDL_VIDEODRIVER=wayland
export QT_QPA_PLATFORM=wayland
export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
export _JAVA_AWT_WM_NONREPARENTING=1
export XDG_CURRENT_DESKTOP=sway
export XDG_SESSION_DESKTOP=sway
export QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox";
export ANKI_WAYLAND=1;
export OBSIDIAN_USE_WAYLAND=1;
'';
# extraConfigEarly = "
# exec systemctl --user import-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK
# exec hash dbus-update-activation-environment 2>/dev/null && dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK
# ";
extraConfig =let
modifier = config.wayland.windowManager.sway.config.modifier;
in "
exec_always autotiling
set $exit \"exit: [s]leep, [p]oweroff, [r]eboot, [l]ogout\"
mode $exit {
bindsym --to-code {
s exec \"systemctl suspend\", mode \"default\"
p exec \"systemctl poweroff\"
r exec \"systemctl reboot\"
l exec \"swaymsg exit\"
Return mode \"default\"
Escape mode \"default\"
${modifier}+x mode \"default\"
}
}
exec systemctl --user import-environment
blur enable
blur_xray disable
blur_passes 1
blur_radius 1
shadows enable
corner_radius 2
titlebar_separator disable
default_dim_inactive 0.02
";
};
#+end_src
* TODO Manual tasks, Useful bits, flake.nix skeleton and Closing Parenthesis (this needs to be the last heading)
Here are listed some tasks that I was not able to automate yet, these need to be done automatically for now. Also, this section exists to add an extra closing parenthesis to common.nix so that I do not need to think about this anymore if I ever decide to add more headings towards the end of this file ;)
- TODO: Check if the below tasks can be automated
1) In blueman, toggle the `ConnectionNotifier` plugin to off (since it is highly annoing)
The last blocks exist to close the opening parenthesis of modules/common.nix (home-manager) and profiles/common.nix (NixOS):
** Useful bits
Here I have gathered some snippets that I have deleted from my configuration but figured they might be of use to someone still :)
*** let-block for overriding a package in nixpkgs (here: replacing airsonic with airsonic-advanced)
This can be useful if a module does not let you use your own package yourself.
#+begin_src nix
pkgs = import nixpkgs { inherit system;
overlays = [ emacs-overlay.overlay
nur.overlay
nixgl.overlay
(self: super: {
airsonic = super.airsonic.overrideAttrs (_: rec {
version = "11.0.2-kagemomiji";
name = "airsonic-advanced-${version}";
src = super.fetchurl {
url = "https://github.com/kagemomiji/airsonic-advanced/releases/download/11.0.2/airsonic.war";
sha256 = "PgErtEizHraZgoWHs5jYJJ5NsliDd9VulQfS64ackFo=";
};
});
})
];
config.allowUnfree = true;
};
#+end_src
** Closing parentheses for common/home.nix and common/nixos.nix
#+begin_src nix :tangle profiles/common/home.nix
}
#+end_src
#+begin_src nix :tangle profiles/common/nixos.nix
}
#+end_src
** flake.nix
This tangles the flake.nix file; This block only needs to be touched when updating the general structure of the flake. For everything else, see the respective noweb-ref block.
#+begin_src nix :noweb yes :tangle flake.nix
{
description = "SwarseFlake - Nix Flake for all SwarselSystems";
inputs = {
<<flakeinputs>>
};
outputs = inputs@{
self,
<<flakeinputsatoutputs>>
...
}: let
<<flakelet>>
in {
# NixOS setups - run home-manager as a NixOS module for better compatibility
# another benefit - full rebuild on nixos-rebuild switch
# run rebuild using `nswitch`
# NEW HOSTS: For a new host, decide whether a NixOS (nixosConfigurations) or non-NixOS (homeConfigurations) is used.
# Make sure to move hardware-configuration to the appropriate location, by default it is found in /etc/nixos/.
nixosConfigurations = {
<<flakenixosconf>>
};
# pure Home Manager setups - for non-NixOS machines
# run rebuild using `hmswitch`
homeConfigurations = {
<<flakehomeconf>>
};
nixOnDroidConfigurations = {
<<flakedroidconf>>
};
packages.x86_64-linux = {
<<flakenixosgenerators>>
};
};
}
#+end_src