commit 1e9b3e0ab1ebc7ef36155de8e9e9504e814c8a13 Author: Lukas Wurzinger Date: Sun Sep 17 13:31:20 2023 +0200 init diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..639ed80 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,17 @@ +keys: +- &admin_lukas age17nt4yca38wrlptapekwmkrjx232cruygty82qhvz3t7g7z4jq9fshdglks +- &host_glacier age190zn56uqtemazc4fjtc649h7634hl9zh6jzrmq478y2t94x8vswqv5q3j8 +- &host_flamingo age1p55v299rqjg7ltz3h3suq2efrgsntn2ej9lzljw9prkx50x7hd4s7cnfcc +- &host_scenery age1nxr8lyst9eleuu9dyrnlwps8xschps42tfzwxfyvyy32n75rssfsayj52j +- &host_abacus age15hmzz0mdrrtlrxwdyv7wfwfs58vzcyg3esnf5ccu5vlg83a8aq6sqp95dv +- &host_vessel age1fvn3rex66xczhard8dcx0s38xdegvguyaepytu6kh9hndhheqqwqcgnc3y +creation_rules: + - path_regex: secrets/[^/]+\.yaml$ + key_groups: + - age: + - *admin_lukas + - *host_glacier + - *host_flamingo + - *host_scenery + - *host_abacus + - *host_vessel diff --git a/README.md b/README.md new file mode 100644 index 0000000..1ef6254 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# ✨ puter ✨ + +## Setup + +```bash +fdisk $disk + +mkfs.vfat -F 32 -n BOOT $boot + +cryptsetup luksFormat -yv --label cryptmain $main +cryptsetup open $main main +mkfs.btrfs /dev/mapper/main + +mount /dev/mapper/main /mnt + +for vol in nix persist home log; do btrfs subvol create /mnt/$vol; done + +umount /mnt + +mount -t tmpfs -o size=8G,mode=755 tmpfs /mnt + +mkdir -p /mnt/{boot,nix,persist,home,var/log} + +for vol in nix persist home var/log; do mount -o subvol=$(basename $vol),compress=zstd,noatime /dev/mapper/main /mnt/$vol; done + +mount $boot /mnt/boot + +nixos-install --no-root-password --flake github:lukaswrz/puter#system +``` + +```bash +fdisk $disk + +mkfs.vfat -F 32 -n BOOT $boot + +mkfs.btrfs -L main $main + +mount $main /mnt + +for vol in nix persist log; do btrfs subvol create /mnt/$vol; done + +umount /mnt + +mount -t tmpfs -o size=2G,mode=755 tmpfs /mnt + +mkdir -p /mnt/{boot,nix,persist,home,var/log} + +for vol in nix persist var/log; do mount -o subvol=$(basename $vol),compress=zstd,noatime $main /mnt/$vol; done + +mount -t tmpfs -o size=2G tmpfs /mnt/home + +mount $boot /mnt/boot + +nixos-install --no-root-password --flake github:lukaswrz/puter#system +``` diff --git a/common/home-manager/desktop.nix b/common/home-manager/desktop.nix new file mode 100644 index 0000000..4f74133 --- /dev/null +++ b/common/home-manager/desktop.nix @@ -0,0 +1,204 @@ +{ + pkgs, + inputs, + config, + lib, + ... +}: { + imports = [ + ./features/bottom.nix + ./features/cava.nix + ./features/cursor.nix + ./features/darkman.nix + ./features/direnv.nix + ./features/fish.nix + ./features/fnott.nix + ./features/foot.nix + ./features/fuzzel.nix + ./features/gammastep.nix + ./features/git.nix + ./features/helix.nix + ./features/i3status-rust.nix + ./features/imv.nix + ./features/joshuto.nix + ./features/mmtc.nix + ./features/mpd.nix + ./features/mpris-proxy.nix + ./features/mpv.nix + ./features/qutebrowser + ./features/readline.nix + ./features/ssh.nix + ./features/swayidle.nix + ./features/swaylock.nix + ./features/sway.nix + ./features/zathura.nix + ]; + + home.packages = with pkgs; [ + appimage-run + wineWowPackages.unstableFull + + bat + curl + ffmpeg + file + gitui + hexyl + hyperfine + imagemagick + ncdu + netcat-openbsd + nmap + procs + progress + pv + rage + ripdrag + rsync + sops + systeroid + tokei + tutanota-desktop + vscodium + wf-recorder + ]; + + xdg = { + enable = true; + mime.enable = true; + mimeApps = { + enable = true; + defaultApplications = let + mkDefaultApplication = mimeTypes: desktopFile: (lib.genAttrs mimeTypes (_: desktopFile)); + in + lib.attrsets.mergeAttrsList [ + ( + mkDefaultApplication [ + "x-scheme-handler/http" + "x-scheme-handler/https" + "text/html" + ] "qutebrowser.desktop" + ) + ( + mkDefaultApplication [ + "x-scheme-handler/mailto" + ] "tutanota-desktop.desktop" + ) + # TODO + # ( + # mkDefaultApplication [ + # "inode/directory" + # ] "" + # ) + # ( + # mkDefaultApplication [ + # "x-scheme-handler/geo" + # ] "" + # ) + ( + mkDefaultApplication [ + "image/png" + "image/jpeg" + "image/webp" + "image/avif" + "image/heif" + "image/bmp" + "image/x-icns" + ] "imv.desktop" + ) + ( + mkDefaultApplication [ + "audio/aac" + "audio/mp4" + "audio/mpeg" + "audio/mpegurl" + "audio/ogg" + "audio/vnd.rn-realaudio" + "audio/vorbis" + "audio/x-flac" + "audio/x-mp3" + "audio/x-mpegurl" + "audio/x-ms-wma" + "audio/x-musepack" + "audio/x-oggflac" + "audio/x-pn-realaudio" + "audio/x-scpls" + "audio/x-speex" + "audio/x-vorbis" + "audio/x-vorbis+ogg" + "audio/x-wav" + ] "mpv.desktop" + ) + ( + mkDefaultApplication [ + "application/pdf" + ] "zathura.desktop" + ) + ( + mkDefaultApplication [ + # TODO: Add more text filetypes + "text/plain" + "text/x-cmake" + "text/markdown" + "application/x-docbook+xml" + "application/json" + "application/x-yaml" + ] "helix.desktop" + ) + ( + mkDefaultApplication [ + "video/3gp" + "video/3gpp2" + "video/divx" + "video/fli" + "video/mp2t" + "video/mp4v-es" + "video/msvideo" + "video/quicktime" + "video/vnd.mpegurl" + "video/x-avi" + "video/x-m4v" + "video/x-mpeg2" + "video/x-msvideo" + "video/x-ms-wmx" + "video/x-ogm+ogg" + "video/x-theora+ogg" + "video/3gpp" + "video/avi" + "video/dv" + "video/flv" + "video/mp4" + "video/mpeg" + "video/ogg" + "video/vnd.divx" + "video/vnd.rn-realvideo" + "video/x-flv" + "video/x-matroska" + "video/x-ms-asf" + "video/x-ms-wmv" + "video/x-ogm" + "video/x-theora" + "application/x-matroska" + ] "mpv.desktop" + ) + ]; + }; + userDirs = { + enable = true; + createDirectories = true; + desktop = "${config.home.homeDirectory}/desk"; + documents = "${config.home.homeDirectory}/doc"; + download = "${config.home.homeDirectory}/dl"; + music = "${config.home.homeDirectory}/music"; + pictures = "${config.home.homeDirectory}/pic"; + publicShare = "${config.home.homeDirectory}/pub"; + templates = "${config.home.homeDirectory}/tpl"; + videos = "${config.home.homeDirectory}/vid"; + }; + }; + + xdg.dataFile."flatpak/overrides/global".text = '' + [Context] + filesystems=/nix/store:ro;${config.xdg.dataHome}/fonts:ro;${config.xdg.dataHome}/icons:ro + ''; +} diff --git a/common/home-manager/features/bottom.nix b/common/home-manager/features/bottom.nix new file mode 100644 index 0000000..3c5372b --- /dev/null +++ b/common/home-manager/features/bottom.nix @@ -0,0 +1 @@ +{programs.bottom.enable = true;} diff --git a/common/home-manager/features/cava.nix b/common/home-manager/features/cava.nix new file mode 100644 index 0000000..e884630 --- /dev/null +++ b/common/home-manager/features/cava.nix @@ -0,0 +1,14 @@ +{pkgs, ...}: { + home.packages = with pkgs; [ + cava + ]; + + xdg.configFile."cava/config".text = '' + [input] + method = pulse + source = auto + + [output] + method = ncurses + ''; +} diff --git a/common/home-manager/features/cursor.nix b/common/home-manager/features/cursor.nix new file mode 100644 index 0000000..8f1f1d7 --- /dev/null +++ b/common/home-manager/features/cursor.nix @@ -0,0 +1,9 @@ +{pkgs, ...}: { + home.pointerCursor = { + name = "Bibata-Modern-Classic"; + size = 16; + package = pkgs.bibata-cursors; + gtk.enable = true; + x11.enable = true; + }; +} diff --git a/common/home-manager/features/darkman.nix b/common/home-manager/features/darkman.nix new file mode 100644 index 0000000..da4e542 --- /dev/null +++ b/common/home-manager/features/darkman.nix @@ -0,0 +1,30 @@ +{pkgs, ...}: { + systemd.user.services.darkman = { + Unit = { + Description = "Framework for dark-mode and light-mode transitions"; + Documentation = ["man:darkman(1)"]; + }; + + Service = { + Type = "dbus"; + BusName = "nl.whynothugo.darkman"; + ExecStart = "${pkgs.darkman}/bin/darkman run"; + Restart = "on-failure"; + TimeoutStopSec = 15; + Slice = "background.slice"; + LockPersonality = true; + RestrictNamespaces = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "@timer" + "mincore" + ]; + MemoryDenyWriteExecute = true; + }; + + Install = { + WantedBy = ["default.target"]; + }; + }; +} diff --git a/common/home-manager/features/direnv.nix b/common/home-manager/features/direnv.nix new file mode 100644 index 0000000..2b51c9d --- /dev/null +++ b/common/home-manager/features/direnv.nix @@ -0,0 +1,6 @@ +{ + programs.direnv = { + enable = true; + nix-direnv.enable = true; + }; +} diff --git a/common/home-manager/features/dunst.nix b/common/home-manager/features/dunst.nix new file mode 100644 index 0000000..c2a52e3 --- /dev/null +++ b/common/home-manager/features/dunst.nix @@ -0,0 +1,22 @@ +{ + services.dunst = { + enable = true; + settings = { + global = { + width = 500; + height = 200; + offset = "20x50"; + origin = "top-right"; + transparency = 10; + frame_color = "#eceff1"; + font = "monospace 12"; + }; + + urgency_normal = { + background = "#37474f"; + foreground = "#eceff1"; + timeout = 10; + }; + }; + }; +} diff --git a/common/home-manager/features/fish.nix b/common/home-manager/features/fish.nix new file mode 100644 index 0000000..0a82ef4 --- /dev/null +++ b/common/home-manager/features/fish.nix @@ -0,0 +1,149 @@ +{pkgs, ...}: { + programs.fish = { + enable = true; + shellAbbrs = { + l = "ls"; + lsa = "ls -a"; + la = "ls -a"; + lsl = "ls -l"; + ll = "ls -l"; + lsla = "ls -la"; + lla = "ls -la"; + cp = "cp -n"; + cpr = "cp -rn"; + mv = "mv -n"; + rm = "rm -i"; + rmr = "rm -ri"; + rr = "rm -ri"; + gi = "git"; + gic = "git commit"; + gico = "git checkout"; + gis = "git status"; + gid = "git diff"; + gidh = "git diff HEAD"; + gia = "git add"; + s = "sudo"; + g = "grep"; + gn = "grep -n"; + gin = "grep -in"; + grin = "grep -rin"; + df = "df -h"; + du = "du -h"; + c = "cd"; + "cd." = "cd ."; + "cd.." = "cd .."; + v = "hx"; + vi = "hx"; + vim = "hx"; + }; + shellAliases = { + ls = "ls --classify=auto --color=auto"; + ffmpeg = "ffmpeg -hide_banner"; + ffprobe = "ffprobe -hide_banner"; + ffplay = "ffplay -hide_banner"; + }; + functions = { + fish_greeting = ""; + fish_prompt = '' + set -l __last_command_exit_status $status + + if not set -q -g __fish_arrow_functions_defined + set -g __fish_arrow_functions_defined + function _git_branch_name + set -l branch (git symbolic-ref --quiet HEAD 2>/dev/null) + if set -q branch[1] + echo (string replace -r '^refs/heads/' ''' $branch) + else + echo (git rev-parse --short HEAD 2>/dev/null) + end + end + + function _is_git_dirty + not command git diff-index --cached --quiet HEAD -- &>/dev/null + or not command git diff --no-ext-diff --quiet --exit-code &>/dev/null + end + + function _is_git_repo + type -q git + or return 1 + git rev-parse --git-dir >/dev/null 2>&1 + end + + function _hg_branch_name + echo (hg branch 2>/dev/null) + end + + function _is_hg_dirty + set -l stat (hg status -mard 2>/dev/null) + test -n "$stat" + end + + function _is_hg_repo + fish_print_hg_root >/dev/null + end + + function _repo_branch_name + _$argv[1]_branch_name + end + + function _is_repo_dirty + _is_$argv[1]_dirty + end + + function _repo_type + if _is_hg_repo + echo hg + return 0 + else if _is_git_repo + echo git + return 0 + end + return 1 + end + end + + set -l cyan (set_color -o cyan) + set -l yellow (set_color -o yellow) + set -l red (set_color -o red) + set -l green (set_color -o green) + set -l blue (set_color -o blue) + set -l normal (set_color normal) + + set -l prompt_color "$green" + if test $__last_command_exit_status != 0 + set prompt_color "$red" + end + + set -l prompt "$prompt_color\$" + if fish_is_root_user + set prompt "$prompt_color#" + end + + set -l cwd $cyan(basename -- (prompt_pwd)) + + set -l repo_info + if set -l repo_type (_repo_type) + set -l repo_branch $red(_repo_branch_name $repo_type) + set repo_info "$blue $repo_type:($repo_branch$blue)" + + if _is_repo_dirty $repo_type + set -l dirty "$yellow ✗" + set repo_info "$repo_info$dirty" + end + end + + echo -n -s -- $cwd $repo_info ' ' $prompt ' '$normal + ''; + }; + interactiveShellInit = '' + bind \ee edit_command_buffer + fish_vi_key_bindings + set fish_cursor_default block blink + set fish_cursor_insert line blink + set fish_cursor_replace_one underscore blink + set fish_cursor_visual block + + set -x EDITOR hx + ''; + }; +} diff --git a/common/home-manager/features/fnott.nix b/common/home-manager/features/fnott.nix new file mode 100644 index 0000000..76a173a --- /dev/null +++ b/common/home-manager/features/fnott.nix @@ -0,0 +1,66 @@ +{pkgs, ...}: { + services.fnott = { + enable = true; + settings = { + main = { + min-width = 400; + max-icon-size = 96; + + stacking-order = "bottom-up"; + anchor = "top-right"; + notification-margin = 5; + + selection-helper = "${pkgs.bemenu}/bin/bemenu"; + + background = "263238ff"; + + border-color = "546e7acf"; + border-size = 2; + + padding-vertical = 20; + padding-horizontal = 20; + + title-font = "sans-serif"; + title-color = "ffffffff"; + title-format = "%a%A"; + + summary-font = "sans-serif"; + summary-color = "ffffffff"; + summary-format = "%s\n"; + + body-font = "sans-serif"; + body-color = "ffffffff"; + body-format = "%b"; + + progress-bar-height = 20; + progress-bar-color = "ffffffff"; + + max-timeout = 0; + default-timeout = 10; + idle-timeout = 0; + }; + + # TODO + low = { + background = "2632388f"; + title-color = "888888ff"; + summary-color = "888888ff"; + body-color = "888888ff"; + }; + + normal = { + background = "263238ff"; + title-color = "ffffffff"; + summary-color = "ffffffff"; + body-color = "ffffffff"; + }; + + critical = { + background = "546e7aaf"; + title-color = "888888ff"; + summary-color = "888888ff"; + body-color = "888888ff"; + }; + }; + }; +} diff --git a/common/home-manager/features/foot.nix b/common/home-manager/features/foot.nix new file mode 100644 index 0000000..d886426 --- /dev/null +++ b/common/home-manager/features/foot.nix @@ -0,0 +1,53 @@ +{pkgs, ...}: { + programs.foot = { + enable = true; + + settings = { + main = { + app-id = "foot"; + font = "monospace:size=12"; + initial-window-size-chars = "80x24"; + notify = "notify-send -a \${app-id} -i \${app-id} \${title} \${body}"; + }; + + scrollback = { + lines = 10000; + }; + + url = { + launch = "${pkgs.xdg-utils}/bin/xdg-open \${url}"; + }; + + cursor = { + style = "block"; + blink = "yes"; + }; + + mouse = { + hide-when-typing = "yes"; + }; + + colors = { + alpha = "0.9"; + foreground = "a9b1d6"; + background = "09090a"; + regular0 = "212121"; + regular1 = "f07178"; + regular2 = "c3e88d"; + regular3 = "ffcb6b"; + regular4 = "82aaff"; + regular5 = "c792ea"; + regular6 = "89ddff"; + regular7 = "eeffff"; + bright0 = "4a4a4a"; + bright1 = "f07178"; + bright2 = "c3e88d"; + bright3 = "ffcb6b"; + bright4 = "82aaff"; + bright5 = "c792ea"; + bright6 = "89ddff"; + bright7 = "ffffff"; + }; + }; + }; +} diff --git a/common/home-manager/features/fuzzel.nix b/common/home-manager/features/fuzzel.nix new file mode 100644 index 0000000..e061486 --- /dev/null +++ b/common/home-manager/features/fuzzel.nix @@ -0,0 +1,25 @@ +{config, ...}: { + programs.fuzzel = { + enable = true; + + settings = { + main = { + font = "Iosevka Nerd Font"; + terminal = "${config.programs.foot.package}/bin/foot"; + layer = "overlay"; + }; + colors = { + background = "263238c0"; + text = "ffffffff"; + match = "eeffffff"; + selection = "82aaffdd"; + selection-text = "eeffffff"; + border = "314549fa"; + }; + border = { + width = 2; + radius = 5; + }; + }; + }; +} diff --git a/common/home-manager/features/gammastep.nix b/common/home-manager/features/gammastep.nix new file mode 100644 index 0000000..c5704ce --- /dev/null +++ b/common/home-manager/features/gammastep.nix @@ -0,0 +1,7 @@ +{ + services.gammastep = { + enable = true; + provider = "geoclue2"; + tray = true; + }; +} diff --git a/common/home-manager/features/git.nix b/common/home-manager/features/git.nix new file mode 100644 index 0000000..a23ef17 --- /dev/null +++ b/common/home-manager/features/git.nix @@ -0,0 +1,83 @@ +{pkgs, ...}: { + programs.git = { + enable = true; + delta = { + enable = true; + options = { + decorations = { + commit-decoration-style = "bold yellow box ul"; + file-decoration-style = "brightyellow ul ol"; + file-style = "bold yellow ul"; + hunk-header-decoration-style = "purple box"; + hunk-header-style = "file line-number syntax"; + }; + features = "line-numbers decorations"; + whitespace-error-style = "22 reverse"; + }; + }; + package = pkgs.gitAndTools.gitFull; + userName = "Lukas Wurzinger"; + userEmail = "lukas@wrz.one"; + extraConfig = { + color.ui = true; + feature.manyFiles = true; + init.defaultBranch = "main"; + push.autoSetupRemote = true; + }; + lfs.enable = true; + ignores = [ + ".idea/" + ".vscode/" + ".iml" + "*.sublime-workspace" + + "node_modules/" + "vendor/" + + "log/" + "*.log" + + "__pycache__/" + "zig-cache/" + + "*.com" + "*.class" + "*.dll" + "*.exe" + "*.o" + "*.so" + "*.pyc" + "*.pyo" + + "*.7z" + "*.dmg" + "*.gz" + "*.iso" + "*.jar" + "*.rar" + "*.tar" + "*.zip" + "*.msi" + + "*.sqlite" + "*.sqlite3" + "*.db" + "*.db3" + "*.s3db" + "*.sl3" + "*.rdb" + + "*.bak" + "*.swp" + "*.swo" + "*~" + "*#" + + "zig-out/" + ]; + # signing = { + # signByDefault = true; + # key = ""; + # }; + }; +} diff --git a/common/home-manager/features/helix.nix b/common/home-manager/features/helix.nix new file mode 100644 index 0000000..a164f7f --- /dev/null +++ b/common/home-manager/features/helix.nix @@ -0,0 +1,24 @@ +{pkgs, ...}: { + programs.helix = { + enable = true; + defaultEditor = true; + settings = { + theme = "penumbra+"; + editor = { + lsp.display-messages = true; + indent-guides.render = true; + file-picker.hidden = false; + line-number = "relative"; + bufferline = "multiple"; + cursor-shape = { + insert = "bar"; + normal = "block"; + select = "underline"; + }; + }; + keys.normal = { + esc = ["collapse_selection" "keep_primary_selection"]; + }; + }; + }; +} diff --git a/common/home-manager/features/i3status-rust.nix b/common/home-manager/features/i3status-rust.nix new file mode 100644 index 0000000..659fa3e --- /dev/null +++ b/common/home-manager/features/i3status-rust.nix @@ -0,0 +1,93 @@ +{ + programs.i3status-rust = { + enable = true; + + bars = { + default = { + icons = "material-nf"; + + settings = { + theme.overrides = { + idle_bg = "#000000"; + idle_fg = "#c5c8c6"; + info_bg = "#3971ed"; + info_fg = "#0e0e0ef0"; + good_bg = "#198844"; + good_fg = "#0e0e0ef0"; + warning_bg = "#fba922"; + warning_fg = "#0e0e0ef0"; + critical_bg = "#cc342b"; + critical_fg = "#0e0e0ef0"; + separator = ""; + separator_bg = "auto"; + separator_fg = "auto"; + }; + }; + + blocks = [ + { + block = "focused_window"; + format = "{ $title $visible_marks |}"; + } + { + block = "net"; + format = " $icon ^icon_net_up $speed_up ^icon_net_down $speed_down "; + interval = 1; + } + { + block = "memory"; + format = " $icon $mem_used "; + interval = 5; + } + { + block = "cpu"; + format = " $icon $barchart "; + interval = 5; + } + { + block = "disk_space"; + path = "/home"; + info_type = "available"; + alert_unit = "GB"; + alert = 10; + warning = 15; + format = " $icon $used/$total "; + } + { + block = "battery"; + interval = 10; + format = " $icon $percentage "; + missing_format = ""; + device = "BAT0"; + } + { + block = "battery"; + interval = 10; + format = " $icon $percentage {$time |}"; + missing_format = ""; + device = "BAT1"; + } + { + block = "sound"; + format = " $icon {$volume |}"; + device_kind = "sink"; + } + { + block = "sound"; + format = " $icon {$volume |}"; + device_kind = "source"; + } + { + block = "music"; + format = "{ $icon $combo $prev $play $next |}"; + } + { + block = "time"; + interval = 1; + format = " $icon $timestamp.datetime(f:'%H:%M:%S, %b %d.') "; + } + ]; + }; + }; + }; +} diff --git a/common/home-manager/features/imv.nix b/common/home-manager/features/imv.nix new file mode 100644 index 0000000..814c74b --- /dev/null +++ b/common/home-manager/features/imv.nix @@ -0,0 +1,12 @@ +{ + programs.imv = { + enable = true; + settings = { + options = { + background = "checks"; + loop_input = false; + overlay = true; + }; + }; + }; +} diff --git a/common/home-manager/features/joshuto.nix b/common/home-manager/features/joshuto.nix new file mode 100644 index 0000000..bc2e65d --- /dev/null +++ b/common/home-manager/features/joshuto.nix @@ -0,0 +1,8 @@ +{ + programs.joshuto = { + enable = true; + settings = { + xdg_open = true; + }; + }; +} diff --git a/common/home-manager/features/mmtc.nix b/common/home-manager/features/mmtc.nix new file mode 100644 index 0000000..9f04399 --- /dev/null +++ b/common/home-manager/features/mmtc.nix @@ -0,0 +1,108 @@ +{ + pkgs, + config, + ... +}: { + home.packages = with pkgs; [ + mmtc + ]; + + xdg.configFile."mmtc/mmtc.ron".text = '' + Config( + address: "${config.services.mpd.network.listenAddress}:${builtins.toString config.services.mpd.network.port}", + clear_query_on_play: false, + cycle: false, + jump_lines: 24, + seek_secs: 5.0, + search_fields: SearchFields( + file: false, + title: true, + artist: true, + album: true, + ), + ups: 1.0, + layout: Rows([ + Fixed(1, Columns([ + Ratio(12, Textbox(Styled([Fg(Indexed(122)), Bold], Text("Title")))), + Ratio(10, Textbox(Styled([Fg(Indexed(158)), Bold], Text("Artist")))), + Ratio(10, Textbox(Styled([Fg(Indexed(194)), Bold], Text("Album")))), + Ratio(1, Textbox(Styled([Fg(Indexed(230)), Bold], Text("Time")))), + ])), + Min(0, Queue([ + Column( + item: Ratio(12, If(QueueCurrent, + Styled([Italic], If(QueueTitleExist, QueueTitle, QueueFile)), + If(QueueTitleExist, QueueTitle, QueueFile), + )), + style: [Fg(Indexed(75))], + selected_style: [Fg(Black), Bg(Indexed(75)), Bold], + ), + Column( + item: Ratio(10, If(QueueCurrent, + Styled([Italic], QueueArtist), + QueueArtist, + )), + style: [Fg(Indexed(111))], + selected_style: [Fg(Black), Bg(Indexed(111)), Bold], + ), + Column( + item: Ratio(10, If(QueueCurrent, + Styled([Italic], QueueAlbum), + QueueAlbum, + )), + style: [Fg(Indexed(147))], + selected_style: [Fg(Black), Bg(Indexed(147)), Bold], + ), + Column( + item: Ratio(1, If(QueueCurrent, + Styled([Italic], QueueDuration), + QueueDuration, + )), + style: [Fg(Indexed(183))], + selected_style: [Fg(Black), Bg(Indexed(183)), Bold], + ), + ])), + Fixed(1, Columns([ + Min(0, Textbox(Styled([Bold], If(Searching, + Parts([ + Styled([Fg(Indexed(113))], Text("Searching: ")), + Styled([Fg(Indexed(185))], Query), + Styled([Fg(Indexed(185))], Text("⎸")), + ]), + If(Not(Stopped), Parts([ + Styled([Fg(Indexed(113))], Parts([ + If(Playing, Text("[playing: "), Text("[paused: ")), + CurrentElapsed, + Text("/"), + CurrentDuration, + Text("] "), + ])), + If(TitleExist, + Parts([ + Styled([Fg(Indexed(149))], CurrentTitle), + If(ArtistExist, Parts([ + Styled([Fg(Indexed(216))], Text(" | ")), + Styled([Fg(Indexed(185))], CurrentArtist), + If(AlbumExist, Parts([ + Styled([Fg(Indexed(216))], Text(" | ")), + Styled([Fg(Indexed(221))], CurrentAlbum), + ])), + ])), + ]), + Styled([Fg(Indexed(185))], CurrentFile), + ), + ])), + )))), + Fixed(7, TextboxR(Styled([Fg(Indexed(81))], Parts([ + Text("["), + If(Repeat, Text("@")), + If(Random, Text("#")), + If(Single, Text("^"), If(Oneshot, Text("!"))), + If(Consume, Text("*")), + Text("]"), + ])))), + ])), + ]), + ) + ''; +} diff --git a/common/home-manager/features/mpd.nix b/common/home-manager/features/mpd.nix new file mode 100644 index 0000000..2139f71 --- /dev/null +++ b/common/home-manager/features/mpd.nix @@ -0,0 +1,22 @@ +{config, ...}: { + services = { + mpd = { + enable = true; + musicDirectory = config.xdg.userDirs.music; + extraConfig = '' + audio_output { + type "pipewire" + name "pipewire" + } + ''; + + network.startWhenNeeded = true; + }; + + mpdris2 = { + enable = true; + multimediaKeys = true; + notifications = true; + }; + }; +} diff --git a/common/home-manager/features/mpris-proxy.nix b/common/home-manager/features/mpris-proxy.nix new file mode 100644 index 0000000..bff539d --- /dev/null +++ b/common/home-manager/features/mpris-proxy.nix @@ -0,0 +1,3 @@ +{ + services.mpris-proxy.enable = true; +} diff --git a/common/home-manager/features/mpv.nix b/common/home-manager/features/mpv.nix new file mode 100644 index 0000000..fc6f124 --- /dev/null +++ b/common/home-manager/features/mpv.nix @@ -0,0 +1,20 @@ +{pkgs, ...}: { + programs.mpv = { + enable = true; + + config = { + vo = "gpu"; + profile = "gpu-hq"; + scale = "ewa_lanczossharp"; + cscale = "ewa_lanczossharp"; + video-sync = "display-resample"; + interpolation = true; + tscale = "oversample"; + force-window = "immediate"; + save-position-on-quit = true; + screenshot-template = "%f_%wH%wM%wS.%wT"; + }; + + scripts = [pkgs.mpvScripts.mpris]; + }; +} diff --git a/common/home-manager/features/nushell/config.nu b/common/home-manager/features/nushell/config.nu new file mode 100644 index 0000000..ff4f24b --- /dev/null +++ b/common/home-manager/features/nushell/config.nu @@ -0,0 +1,48 @@ +$env.config = { + show_banner: false + + rm: { + always_trash: true + } + + cd: { + abbreviations: true + } + + table: { + index_mode: auto + } + + history: { + max_size: 1_000_000 + } + + completions: { + case_sensitive: false + algorithm: "fuzzy" + } + + cursor_shape: { + emacs: line + vi_insert: block + vi_normal: underscore + } + + edit_mode: vi + + bracketed_paste: true + + shell_integration: true + + render_right_prompt_on_last_line: true + + hooks: { + pre_prompt: [{ || + let direnv = (direnv export json | from json) + let direnv = if ($direnv | length) == 1 { $direnv } else { {} } + $direnv | load-env + }] + } +} + +def lsg [] { ls | sort-by type name -i | grid -c | str trim } diff --git a/common/home-manager/features/nushell/default.nix b/common/home-manager/features/nushell/default.nix new file mode 100644 index 0000000..80eeed2 --- /dev/null +++ b/common/home-manager/features/nushell/default.nix @@ -0,0 +1,45 @@ +{ + programs.nushell = { + enable = true; + + configFile.source = ./config.nu; + + environmentVariables = { + # FIXME: Not properly serialized + PROMPT_COMMAND_RIGHT = "''"; + }; + + shellAliases = { + l = "ls"; + lsa = "ls -a"; + la = "ls -a"; + lsl = "ls -l"; + ll = "ls -l"; + lsla = "ls -la"; + lla = "ls -la"; + cpr = "cp -r"; + rmr = "rm -r"; + rr = "rm -r"; + gi = "git"; + gic = "git commit"; + gico = "git checkout"; + gis = "git status"; + gid = "git diff"; + gidh = "git diff HEAD"; + gia = "git add"; + s = "sudo"; + g = "grep"; + gn = "grep -n"; + gin = "grep -in"; + grin = "grep -rin"; + df = "df -h"; + du = "du -h"; + c = "cd"; + "cd." = "cd ."; + "cd.." = "cd .."; + ffmpeg = "ffmpeg -hide_banner"; + ffprobe = "ffprobe -hide_banner"; + ffplay = "ffplay -hide_banner"; + }; + }; +} diff --git a/common/home-manager/features/qutebrowser/default.nix b/common/home-manager/features/qutebrowser/default.nix new file mode 100644 index 0000000..7a3b4a5 --- /dev/null +++ b/common/home-manager/features/qutebrowser/default.nix @@ -0,0 +1,196 @@ +{ + programs.qutebrowser = { + enable = true; + extraConfig = '' + from locale import getdefaultlocale + from os import environ + from re import match + from pathlib import Path + + config.load_autoconfig() + + c.aliases = { + "o": "open", + "q": "quit", + "w": "session-save", + "wq": "quit --save", + "adblock-toggle": "config-cycle -t content.blocking.enabled", + "incognito": "open --private", + "mpv": "spawn --detach mpv {url}", + } + + c.colors.webpage.bg = "black" + + # TODO + # c.editor.command = [ + # "neovide", + # "--nofork", + # "--wayland-app-id", + # "neovidefloat", + # "--", + # "+normal {line}G{column0}l", + # "--", + # "{file}", + # ] + + c.editor.encoding = "utf-8" + + config.bind("td", "config-cycle colors.webpage.darkmode.enabled;; restart") + + c.tabs.show = "multiple" + + c.tabs.tabs_are_windows = True + + c.content.local_content_can_access_remote_urls = True + + c.url.default_page = Path("${./start.html}").as_uri() + + c.url.start_pages = [c.url.default_page] + + c.url.searchengines = { + "DEFAULT": "https://www.google.com/search?q={}", + "g": "https://www.google.com/search?q={}", + "ddg": "https://lite.duckduckgo.com/lite?q={}", + "wt": "https://en.wiktionary.org/w/index.php?search={}", + "w": "https://en.wikipedia.org/w/index.php?search={}", + "bs": "https://search.brave.com/search?q={}", + "aur": "https://aur.archlinux.org/packages/?SB=p&SO=d&O=0&K={}", + "gh": "https://github.com/search?q={}", + "gist": "https://gist.github.com/search?q={}", + "dd": "https://thefreedictionary.com/{}", + "dr": "https://search.disroot.org/?q={}", + } + + try: + l = getdefaultlocale()[0] + if l is None or l in ("C", "POSIX"): + raise ValueError + + rematch = match(r"([a-z]+)(_([A-Z]+)?)", l) + if rematch is None: + raise ValueError + + language = rematch[1] + + try: + locale = rematch[3] + c.content.headers.accept_language = f"{language}-{locale},{language};q=0.9,en-{locale},en;q=0.8,en-US,en;q=0.7,*;q=0.6" + except IndexError: + c.content.headers.accept_language = f"{language};q=0.9,en-US,en;q=0.8,*;q=0.7" + except: + c.content.headers.accept_language = "en-US,en;q=0.9" + + # TODO + # c.colors.webpage.preferred_color_scheme = "dark" + + base00 = "#1f2022" + base01 = "#282828" + base02 = "#444155" + base03 = "#585858" + base04 = "#b8b8b8" + base05 = "#a3a3a3" + base06 = "#e8e8e8" + base07 = "#f8f8f8" + base08 = "#f2241f" + base09 = "#ffa500" + base0A = "#b1951d" + base0B = "#67b11d" + base0C = "#2d9574" + base0D = "#4f97d7" + base0E = "#a31db1" + base0F = "#b03060" + + c.colors.completion.fg = base05 + c.colors.completion.odd.bg = base01 + c.colors.completion.even.bg = base00 + c.colors.completion.category.fg = base0A + c.colors.completion.category.bg = base00 + c.colors.completion.category.border.top = base00 + c.colors.completion.category.border.bottom = base00 + c.colors.completion.item.selected.fg = base05 + c.colors.completion.item.selected.bg = base02 + c.colors.completion.item.selected.border.top = base02 + c.colors.completion.item.selected.border.bottom = base02 + c.colors.completion.item.selected.match.fg = base0B + c.colors.completion.match.fg = base0B + c.colors.completion.scrollbar.fg = base05 + c.colors.completion.scrollbar.bg = base00 + c.colors.contextmenu.disabled.bg = base01 + c.colors.contextmenu.disabled.fg = base04 + c.colors.contextmenu.menu.bg = base00 + c.colors.contextmenu.menu.fg = base05 + c.colors.contextmenu.selected.bg = base02 + c.colors.contextmenu.selected.fg = base05 + c.colors.downloads.bar.bg = base00 + c.colors.downloads.start.fg = base00 + c.colors.downloads.start.bg = base0D + c.colors.downloads.stop.fg = base00 + c.colors.downloads.stop.bg = base0C + c.colors.downloads.error.fg = base08 + c.colors.hints.fg = base00 + c.colors.hints.bg = base0A + c.colors.hints.match.fg = base05 + c.colors.keyhint.fg = base05 + c.colors.keyhint.suffix.fg = base05 + c.colors.keyhint.bg = base00 + c.colors.messages.error.fg = base00 + c.colors.messages.error.bg = base08 + c.colors.messages.error.border = base08 + c.colors.messages.warning.fg = base00 + c.colors.messages.warning.bg = base0E + c.colors.messages.warning.border = base0E + c.colors.messages.info.fg = base05 + c.colors.messages.info.bg = base00 + c.colors.messages.info.border = base00 + c.colors.prompts.fg = base05 + c.colors.prompts.border = base00 + c.colors.prompts.bg = base00 + c.colors.prompts.selected.bg = base02 + c.colors.prompts.selected.fg = base05 + c.colors.statusbar.normal.fg = base0B + c.colors.statusbar.normal.bg = base00 + c.colors.statusbar.insert.fg = base00 + c.colors.statusbar.insert.bg = base0D + c.colors.statusbar.passthrough.fg = base00 + c.colors.statusbar.passthrough.bg = base0C + c.colors.statusbar.private.fg = base00 + c.colors.statusbar.private.bg = base01 + c.colors.statusbar.command.fg = base05 + c.colors.statusbar.command.bg = base00 + c.colors.statusbar.command.private.fg = base05 + c.colors.statusbar.command.private.bg = base00 + c.colors.statusbar.caret.fg = base00 + c.colors.statusbar.caret.bg = base0E + c.colors.statusbar.caret.selection.fg = base00 + c.colors.statusbar.caret.selection.bg = base0D + c.colors.statusbar.progress.bg = base0D + c.colors.statusbar.url.fg = base05 + c.colors.statusbar.url.error.fg = base08 + c.colors.statusbar.url.hover.fg = base05 + c.colors.statusbar.url.success.http.fg = base0C + c.colors.statusbar.url.success.https.fg = base0B + c.colors.statusbar.url.warn.fg = base0E + c.colors.tabs.bar.bg = base00 + c.colors.tabs.indicator.start = base0D + c.colors.tabs.indicator.stop = base0C + c.colors.tabs.indicator.error = base08 + c.colors.tabs.odd.fg = base05 + c.colors.tabs.odd.bg = base01 + c.colors.tabs.even.fg = base05 + c.colors.tabs.even.bg = base00 + c.colors.tabs.pinned.even.bg = base0C + c.colors.tabs.pinned.even.fg = base07 + c.colors.tabs.pinned.odd.bg = base0B + c.colors.tabs.pinned.odd.fg = base07 + c.colors.tabs.pinned.selected.even.bg = base02 + c.colors.tabs.pinned.selected.even.fg = base05 + c.colors.tabs.pinned.selected.odd.bg = base02 + c.colors.tabs.pinned.selected.odd.fg = base05 + c.colors.tabs.selected.odd.fg = base05 + c.colors.tabs.selected.odd.bg = base02 + c.colors.tabs.selected.even.fg = base05 + c.colors.tabs.selected.even.bg = base02 + c.colors.webpage.bg = base00 + ''; + }; +} diff --git a/common/home-manager/features/qutebrowser/start.html b/common/home-manager/features/qutebrowser/start.html new file mode 100644 index 0000000..764fac5 --- /dev/null +++ b/common/home-manager/features/qutebrowser/start.html @@ -0,0 +1,212 @@ + + + + + + + start + + + + +
+
+ +
+ +
+
+
social
+ +
+ +
+
google
+ +
+ + + +
+
personal
+ +
+ +
+
dev
+ +
+ +
+
misc
+ +
+
+
+ + + diff --git a/common/home-manager/features/readline.nix b/common/home-manager/features/readline.nix new file mode 100644 index 0000000..c4e02d2 --- /dev/null +++ b/common/home-manager/features/readline.nix @@ -0,0 +1,11 @@ +{ + programs.readline = { + enable = true; + + variables = { + editing-mode = "vi"; + completion-ignore-case = "on"; + enable-bracketed-paste = "on"; + }; + }; +} diff --git a/common/home-manager/features/ssh.nix b/common/home-manager/features/ssh.nix new file mode 100644 index 0000000..26e52c7 --- /dev/null +++ b/common/home-manager/features/ssh.nix @@ -0,0 +1,8 @@ +{ + programs.ssh = { + enable = true; + + compression = true; + serverAliveInterval = 60; + }; +} diff --git a/common/home-manager/features/sway.nix b/common/home-manager/features/sway.nix new file mode 100644 index 0000000..8f88282 --- /dev/null +++ b/common/home-manager/features/sway.nix @@ -0,0 +1,537 @@ +{ + pkgs, + config, + lib, + ... +}: { + imports = [ + ./cursor.nix + ]; + + # TODO: darkman + + wayland.windowManager.sway = let + wpctl = "${pkgs.wireplumber}/bin/wpctl"; + xdg-user-dir = "${pkgs.xdg-user-dirs}/bin/xdg-user-dir"; + notify-send = "${pkgs.libnotify}/bin/notify-send"; + slurp = "${pkgs.slurp}/bin/slurp"; + grim = "${pkgs.grim}/bin/grim"; + wl-copy = "${pkgs.wl-clipboard}/bin/wl-copy"; + swaynag = "${config.wayland.windowManager.sway.package}/bin/swaynag"; + swaymsg = "${config.wayland.windowManager.sway.package}/bin/swaymsg"; + brightnessctl = "${pkgs.brightnessctl}/bin/brightnessctl"; + mpc = "${pkgs.mpc-cli}/bin/mpc"; + fnottctl = "${config.services.fnott.package}/bin/fnottctl"; + modifier = "Mod4"; + terminal = "${config.programs.foot.package}/bin/foot"; + in { + enable = true; + + systemd = { + enable = true; + xdgAutostart = true; + }; + + wrapperFeatures = { + base = true; + gtk = true; + }; + + # TODO: Remove GTK_THEME + extraSessionCommands = '' + export MOZ_ENABLE_WAYLAND=1 + export MOZ_DBUS_REMOTE=1 + export QT_QPA_PLATFORM=wayland-egl + export QT_WAYLAND_DISABLE_WINDOWDECORATION=1 + export _JAVA_AWT_WM_NONREPARENTING=1 + export SDL_VIDEODRIVER=wayland + export BEMENU_OPTS='--tb #3971ed --tf #1d1f21 --fb #1d1f21 --ff #c5c8c6 --nb #1d1f21 --nf #c5c8c6 --hb #282a2e --hf #ffffff --sb #1d1f21 --sf #c5c8c6 --scb #373b41 --scf #3971ed --scrollbar autohide --fn monospace --bottom' + export GTK_THEME=Adwaita:dark + export XDG_SESSION_DESKTOP="''${XDG_SESSION_DESKTOP:-sway}" + export SUDO_ASKPASS=${ + pkgs.writeShellScript "askpass" '' + echo -n | ${pkgs.bemenu}/bin/bemenu --password --prompt askpass + '' + } + export GDK_SCALE=1 + ''; + + config = { + inherit modifier terminal; + + startup = [ + {command = "${pkgs.dex}/bin/dex --autostart";} + ]; + + # FIXME: Currently done by extraConfig + # defaultWorkspace = "workspace number 1"; + + gaps = { + smartBorders = "on"; + smartGaps = true; + }; + + window = { + titlebar = false; + + commands = [ + { + command = "inhibit_idle fullscreen"; + criteria.app_id = "mpv"; + } + ]; + }; + + workspaceAutoBackAndForth = true; + + input = { + "type:keyboard" = { + xkb_layout = lib.mkDefault "us"; + repeat_rate = "45"; + repeat_delay = "250"; + }; + + "type:pointer" = { + accel_profile = "flat"; + }; + + "type:touchpad" = { + tap = "enabled"; + natural_scroll = "enabled"; + dwt = "enabled"; + }; + }; + + bars = [ + { + statusCommand = "${config.programs.i3status-rust.package}/bin/i3status-rs ~/.config/i3status-rust/config-default.toml"; + command = "${config.wayland.windowManager.sway.package}/bin/swaybar"; + position = "top"; + trayOutput = "*"; + fonts = { + names = ["Iosevka Nerd Font" "monospace"]; + style = "Regular"; + size = 13.0; + }; + colors = { + background = "#000000"; + separator = "#121616f4"; + statusline = "#121616f4"; + focusedWorkspace = { + border = "#3971ed"; + background = "#3971ed"; + text = "#0e0e0ef0"; + }; + activeWorkspace = { + border = "#c5c8c6"; + background = "#969896"; + text = "#0e0e0ef0"; + }; + inactiveWorkspace = { + border = "#000000"; + background = "#000000"; + text = "#c5c8c6"; + }; + urgentWorkspace = { + border = "#cc342b"; + background = "#cc342b"; + text = "#0e0e0ef0"; + }; + bindingMode = { + border = "#fba922"; + background = "#fba922"; + text = "#0e0e0ef0"; + }; + }; + } + ]; + + colors = { + focused = { + border = "#c5c8c6"; + background = "#3971ed"; + text = "#0e0e0ef0"; + indicator = "#3971ed"; + childBorder = "#3971ed"; + }; + focusedInactive = { + border = "#121616f4"; + background = "#121616f4"; + text = "#c5c8c6"; + indicator = "#969896"; + childBorder = "#121616f4"; + }; + unfocused = { + border = "#121616f4"; + background = "#0e0e0ef0"; + text = "#c5c8c6"; + indicator = "#121616f4"; + childBorder = "#121616f4"; + }; + urgent = { + border = "#cc342b"; + background = "#cc342b"; + text = "#0e0e0ef0"; + indicator = "#cc342b"; + childBorder = "#cc342b"; + }; + placeholder = { + border = "#0e0e0ef0"; + background = "#0e0e0ef0"; + text = "#c5c8c6"; + indicator = "#0e0e0ef0"; + childBorder = "#0e0e0ef0"; + }; + background = "#ffffff"; + }; + + floating.criteria = [ + {app_id = "neovidefloat";} + {app_id = "mpvfloat";} + {app_id = "footfloat";} + ]; + + keybindings = { + "${modifier}+Shift+q" = "kill"; + + "${modifier}+d" = "exec ${config.programs.fuzzel.package}/bin/fuzzel"; + "${modifier}+Shift+d" = "exec ${pkgs.bemenu}/bin/bemenu-run --no-exec | xargs ${swaymsg} exec --"; + + "${modifier}+Return" = "exec ${terminal}"; + "${modifier}+Shift+Return" = "exec ${terminal} --class footfloat"; + + "${modifier}+Left" = "focus left"; + "${modifier}+Down" = "focus down"; + "${modifier}+Up" = "focus up"; + "${modifier}+Right" = "focus right"; + + "${modifier}+h" = "focus left"; + "${modifier}+j" = "focus down"; + "${modifier}+k" = "focus up"; + "${modifier}+l" = "focus right"; + + "${modifier}+Shift+Left" = "move left"; + "${modifier}+Shift+Down" = "move down"; + "${modifier}+Shift+Up" = "move up"; + "${modifier}+Shift+Right" = "move right"; + + "${modifier}+Shift+h" = "move left"; + "${modifier}+Shift+j" = "move down"; + "${modifier}+Shift+k" = "move up"; + "${modifier}+Shift+l" = "move right"; + + "${modifier}+s" = "layout stacking"; + "${modifier}+w" = "layout tabbed"; + "${modifier}+e" = "layout toggle split"; + + "${modifier}+Space" = "focus mode_toggle"; + "${modifier}+Shift+Space" = "floating toggle"; + + "${modifier}+1" = "workspace number 1"; + "${modifier}+2" = "workspace number 2"; + "${modifier}+3" = "workspace number 3"; + "${modifier}+4" = "workspace number 4"; + "${modifier}+5" = "workspace number 5"; + "${modifier}+6" = "workspace number 6"; + "${modifier}+7" = "workspace number 7"; + "${modifier}+8" = "workspace number 8"; + "${modifier}+9" = "workspace number 9"; + "${modifier}+0" = "workspace number 10"; + "${modifier}+F1" = "workspace number 11"; + "${modifier}+F2" = "workspace number 12"; + "${modifier}+F3" = "workspace number 13"; + "${modifier}+F4" = "workspace number 14"; + "${modifier}+F5" = "workspace number 15"; + "${modifier}+F6" = "workspace number 16"; + "${modifier}+F7" = "workspace number 17"; + "${modifier}+F8" = "workspace number 18"; + "${modifier}+F9" = "workspace number 19"; + "${modifier}+F10" = "workspace number 20"; + "${modifier}+F11" = "workspace number 21"; + "${modifier}+F12" = "workspace number 22"; + + "${modifier}+Shift+1" = "move container to workspace number 1"; + "${modifier}+Shift+2" = "move container to workspace number 2"; + "${modifier}+Shift+3" = "move container to workspace number 3"; + "${modifier}+Shift+4" = "move container to workspace number 4"; + "${modifier}+Shift+5" = "move container to workspace number 5"; + "${modifier}+Shift+6" = "move container to workspace number 6"; + "${modifier}+Shift+7" = "move container to workspace number 7"; + "${modifier}+Shift+8" = "move container to workspace number 8"; + "${modifier}+Shift+9" = "move container to workspace number 9"; + "${modifier}+Shift+0" = "move container to workspace number 10"; + "${modifier}+Shift+F1" = "move container to workspace number 11"; + "${modifier}+Shift+F2" = "move container to workspace number 12"; + "${modifier}+Shift+F3" = "move container to workspace number 13"; + "${modifier}+Shift+F4" = "move container to workspace number 14"; + "${modifier}+Shift+F5" = "move container to workspace number 15"; + "${modifier}+Shift+F6" = "move container to workspace number 16"; + "${modifier}+Shift+F7" = "move container to workspace number 17"; + "${modifier}+Shift+F8" = "move container to workspace number 18"; + "${modifier}+Shift+F9" = "move container to workspace number 19"; + "${modifier}+Shift+F10" = "move container to workspace number 20"; + "${modifier}+Shift+F11" = "move container to workspace number 21"; + "${modifier}+Shift+F12" = "move container to workspace number 22"; + + Print = + "exec " + + pkgs.writeShellScript "grabraw" '' + set -e + set -o pipefail + f=$(${xdg-user-dir} PICTURES)/$(date +'screenshot-%Y%m%d-%H%M%S').png + ${grim} -t png - | tee -- "$f" | ${wl-copy} --type image/png + ${notify-send} --icon "$f" -- "$f copied to clipboard." + ''; + "Shift+Print" = + "exec " + + pkgs.writeShellScript "grabregion" '' + set -e + set -o pipefail + f=$(${xdg-user-dir} PICTURES)/$(date +'screenshot-%Y%m%d-%H%M%S').png + ${slurp} | ${grim} -t png -g - - | tee -- "$f" | ${wl-copy} --type image/png + ${notify-send} --icon "$f" -- "$f copied to clipboard." + ''; + "Control+Shift+Print" = + "exec " + + pkgs.writeShellScript "grabcolor" '' + set -e + set -o pipefail + c=$(${slurp} -b 00000000 -p | ${grim} -g - - | ${pkgs.imagemagick}/bin/convert - -format '%[pixel:p{0,0}]' txt:- | tail --lines 1 | cut -d ' ' -f 4) + ${wl-copy} --type text/plain --trim-newline <<< "$c" + ${notify-send} -- "$c copied to clipboard." + ''; + + "${modifier}+x" = "split h"; + "${modifier}+y" = "split v"; + + "${modifier}+f" = "fullscreen toggle"; + "${modifier}+a" = "focus parent"; + "${modifier}+c" = "focus child"; + + "${modifier}+Shift+c" = "reload"; + "${modifier}+Shift+r" = "restart"; + + "${modifier}+Shift+z" = '' + exec ${swaynag} \ + -t warning \ + -m 'What do you want to do?' \ + -b 'Exit sway' 'systemctl --user stop sway-session.target && ${swaymsg} exit' \ + -b 'Shutdown' 'systemctl --user stop sway-session.target && shutdown now' \ + -b 'Reboot' 'systemctl --user stop sway-session.target && reboot' \ + -b 'Suspend' 'loginctl lock-session && systemctl suspend' \ + -b 'Hibernate' 'loginctl lock-session && systemctl hibernate' + ''; + + "${modifier}+b" = "exec ${fnottctl} dismiss"; + "${modifier}+Shift+b" = "exec ${fnottctl} actions"; + + XF86AudioRaiseVolume = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 1%+"; + XF86AudioLowerVolume = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 1%-"; + "Shift+XF86AudioRaiseVolume" = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 10%+"; + "Shift+XF86AudioLowerVolume" = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 10%-"; + XF86AudioMute = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SINK@ 1"; + "Shift+XF86AudioMute" = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SINK@ 0"; + XF86AudioMicMute = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SOURCE@ 1"; + "Shift+XF86AudioMicMute" = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SOURCE@ 0"; + "${modifier}+n" = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SINK@ 1"; + "${modifier}+Shift+n" = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SINK@ 0"; + "${modifier}+m" = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SOURCE@ 1"; + "${modifier}+Shift+m" = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SOURCE@ 0"; + + XF86AudioPause = "exec ${mpc} pause"; + XF86AudioPlay = "exec ${mpc} play"; + XF86AudioPrev = "exec ${mpc} prev"; + XF86AudioNext = "exec ${mpc} next"; + + XF86MonBrightnessUp = "exec ${brightnessctl} set +1%"; + XF86MonBrightnessDown = "exec ${brightnessctl} set 1%-"; + "Shift+XF86MonBrightnessUp" = "exec ${brightnessctl} set +10%"; + "Shift+XF86MonBrightnessDown" = "exec ${brightnessctl} set 10%-"; + + "${modifier}+Apostrophe" = "move workspace to output right"; + + "${modifier}+Minus" = "scratchpad show"; + "${modifier}+Shift+Minus" = "move scratchpad"; + "${modifier}+Underscore" = "move container to scratchpad"; + + "${modifier}+Shift+s" = "exec loginctl lock-session"; + + XF86PowerOff = "exec loginctl lock-session"; + "Shift+XF86PowerOff" = "exec systemctl suspend-then-hibernate"; + + XF86Eject = "exec loginctl lock-session"; + "Shift+XF86Eject" = "exec systemctl suspend-then-hibernate"; + + Pause = "exec loginctl lock-session"; + "Shift+Pause" = "exec systemctl suspend-then-hibernate"; + + "${modifier}+r" = "mode resize"; + "${modifier}+g" = "mode gaps"; + "${modifier}+p" = "mode mpc"; + "${modifier}+i" = "mode microphone"; + "${modifier}+t" = "mode clipboard"; + "${modifier}+v" = "mode volume"; + "${modifier}+u" = "mode brightness"; + }; + + modes = { + resize = { + h = "resize shrink width 1 px or 1 ppt"; + j = "resize grow height 1 px or 1 ppt"; + k = "resize shrink height 1 px or 1 ppt"; + l = "resize grow width 1 px or 1 ppt"; + "Shift+h" = "resize shrink width 10 px or 10 ppt"; + "Shift+j" = "resize grow height 10 px or 10 ppt"; + "Shift+k" = "resize shrink height 10 px or 10 ppt"; + "Shift+l" = "resize grow width 10 px or 10 ppt"; + + Return = "mode default"; + Escape = "mode default"; + }; + + volume = { + k = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 1%+"; + j = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 1%-"; + "Shift+k" = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 10%+"; + "Shift+j" = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 10%-"; + + Return = "mode default"; + Escape = "mode default"; + }; + + microphone = { + XF86AudioRaiseVolume = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SOURCE@ 1%+"; + XF86AudioLowerVolume = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SOURCE@ 1%-"; + "Shift+XF86AudioRaiseVolume" = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SOURCE@ 10%+"; + "Shift+XF86AudioLowerVolume" = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SOURCE@ 10%-"; + + Return = "mode default"; + Escape = "mode default"; + }; + + brightness = { + j = "exec ${brightnessctl} set 1%-"; + k = "exec ${brightnessctl} set +1%"; + + Return = "mode default"; + Escape = "mode default"; + }; + + clipboard = { + c = "exec ${wl-copy} --clear"; + + Return = "mode default"; + Escape = "mode default"; + }; + + "gaps inner" = { + plus = "gaps inner current plus 1"; + minus = "gaps inner current minus 1"; + "0" = "gaps inner current set 0"; + + "Shift+plus" = "gaps inner all plus 1"; + "Shift+minus" = "gaps inner all minus 1"; + "Shift+0" = "gaps inner all set 0"; + + Return = "mode default"; + Escape = "mode default"; + }; + + "gaps outer" = { + plus = "gaps outer current plus 1"; + minus = "gaps outer current minus 1"; + "0" = "gaps outer current set 0"; + + "Shift+plus" = "gaps outer all plus 1"; + "Shift+minus" = "gaps outer all minus 1"; + "Shift+0" = "gaps outer all set 0"; + + Return = "mode default"; + Escape = "mode default"; + }; + + gaps = { + o = ''mode "gaps outer"''; + i = ''mode "gaps inner"''; + + Return = "mode default"; + Escape = "mode default"; + }; + + "mpc volume" = { + j = "exec ${mpc} volume -1"; + k = "exec ${mpc} volume +1"; + "Shift+j" = "exec exec ${mpc} volume -10"; + "Shift+k" = "exec exec ${mpc} volume +10"; + + Return = "mode default"; + Escape = "mode default"; + }; + + mpc = { + XF86AudioRaiseVolume = "exec ${mpc} volume +1"; + XF86AudioLowerVolume = "exec ${mpc} volume -1"; + "Shift+XF86AudioRaiseVolume" = "exec ${mpc} volume +10"; + "Shift+XF86AudioLowerVolume" = "exec ${mpc} volume -10"; + + j = "exec ${mpc} next"; + k = "exec ${mpc} prev"; + + c = "exec ${mpc} toggle"; + + o = "exec ${mpc} consume on"; + "Shift+o" = "exec ${mpc} consume off"; + + "1" = "exec ${mpc} single on"; + "Shift+1" = "exec ${mpc} single off"; + + r = "exec ${mpc} random on"; + "Shift+r" = "exec ${mpc} random off"; + + p = "exec ${mpc} stop"; + + s = "exec ${mpc} shuffle"; + + h = "exec ${mpc} seek -00:00:01"; + l = "exec ${mpc} seek +00:00:01"; + "Shift+h" = "exec ${mpc} seek -00:00:10"; + "Shift+l" = "exec ${mpc} seek +00:00:10"; + + v = ''mode "mpc volume"''; + + Return = "mode default"; + Escape = "mode default"; + }; + + # TODO: bind + # wall = { + # s = pkgs.writeShellScript "setwall" '' + # set -euo pipefail + # shopt -s nullglob + # shopt -s globstar + + # # select the output first... + + # file=$( + # for file in * + # do + # echo "''${file@Q}" + # done | ${pkgs.bemenu}/bin/bemenu --lines 10 --prompt askpass + # ) + + # if [[ $? != 0 ]]; then + # exit 1 + # fi + # ''; + # }; + }; + + seat."*".xcursor_theme = "${config.home.pointerCursor.name} ${builtins.toString config.home.pointerCursor.size}"; + }; + + # FIXME: Should be done by defaultWorkspace + extraConfig = '' + workspace number 1 + ''; + }; +} diff --git a/common/home-manager/features/swayidle.nix b/common/home-manager/features/swayidle.nix new file mode 100644 index 0000000..684dbd8 --- /dev/null +++ b/common/home-manager/features/swayidle.nix @@ -0,0 +1,28 @@ +{ + pkgs, + config, + ... +}: { + services.swayidle = { + enable = true; + + events = [ + { + event = "lock"; + command = "${config.programs.swaylock.package}/bin/swaylock --daemonize"; + } + { + event = "before-sleep"; + command = "${pkgs.systemd}/bin/loginctl lock-session"; + } + ]; + + timeouts = [ + { + timeout = 600; + command = "${pkgs.chayang}/bin/chayang && ${pkgs.systemd}/bin/loginctl lock-session && ${config.wayland.windowManager.sway.package}/bin/swaymsg output \\\\* power off"; + resumeCommand = "${config.wayland.windowManager.sway.package}/bin/swaymsg output \\\\* power on"; + } + ]; + }; +} diff --git a/common/home-manager/features/swaylock.nix b/common/home-manager/features/swaylock.nix new file mode 100644 index 0000000..2ea8444 --- /dev/null +++ b/common/home-manager/features/swaylock.nix @@ -0,0 +1,18 @@ +{ + programs.swaylock = { + enable = true; + settings = { + ignore-empty-password = true; + show-failed-attempts = true; + indicator-caps-lock = true; + color = "000000"; + ring-color = "111111"; + line-color = "00000000"; + inside-color = "00000088"; + separator-color = "00000000"; + key-hl-color = "000033"; + indicator-radius = 100; + indicator-thickness = 12; + }; + }; +} diff --git a/common/home-manager/features/zathura.nix b/common/home-manager/features/zathura.nix new file mode 100644 index 0000000..4de14ad --- /dev/null +++ b/common/home-manager/features/zathura.nix @@ -0,0 +1,3 @@ +{ + programs.zathura.enable = true; +} diff --git a/common/home-manager/server.nix b/common/home-manager/server.nix new file mode 100644 index 0000000..a91fab8 --- /dev/null +++ b/common/home-manager/server.nix @@ -0,0 +1,26 @@ +{ + pkgs, + inputs, + config, + ... +}: { + imports = [ + ./features/bottom.nix + ./features/direnv.nix + ./features/fish.nix + ./features/git.nix + ./features/helix.nix + ./features/readline.nix + ]; + + home.packages = with pkgs; [ + curl + file + ncdu + netcat-openbsd + procs + progress + pv + rsync + ]; +} diff --git a/common/nixos/desktop.nix b/common/nixos/desktop.nix new file mode 100644 index 0000000..b715892 --- /dev/null +++ b/common/nixos/desktop.nix @@ -0,0 +1,124 @@ +{ + pkgs, + inputs, + config, + lib, + ... +}: { + imports = [ + "${inputs.impermanence}/nixos.nix" + + ./features/avahi.nix + ./features/bluetooth.nix + ./features/command-not-found.nix + ./features/fonts.nix + ./features/fwupd.nix + ./features/geoclue.nix + ./features/greetd.nix + ./features/opengl.nix + ./features/openssh.nix + ./features/pipewire.nix + ./features/sops.nix + ./features/sudo.nix + ./features/swaylock.nix + ./features/users.nix + ./features/xdpw.nix + ]; + + fileSystems = { + "/" = { + device = "tmpfs"; + fsType = "tmpfs"; + options = ["size=8G" "mode=755"]; + }; + + "/boot" = { + device = "/dev/disk/by-label/BOOT"; + fsType = "vfat"; + }; + + "/nix" = { + device = "/dev/mapper/main"; + fsType = "btrfs"; + options = ["subvol=nix" "compress=zstd" "noatime"]; + }; + + "/persist" = { + device = "/dev/mapper/main"; + fsType = "btrfs"; + options = ["subvol=persist" "compress=zstd" "noatime"]; + neededForBoot = true; + }; + + "/home" = { + device = "/dev/mapper/main"; + fsType = "btrfs"; + options = ["subvol=home" "compress=zstd" "noatime"]; + }; + + "/tmp" = { + device = "tmpfs"; + fsType = "tmpfs"; + options = ["size=16G" "mode=777"]; + }; + + "/var/log" = { + device = "/dev/mapper/main"; + fsType = "btrfs"; + options = ["subvol=log" "compress=zstd" "noatime"]; + neededForBoot = true; + }; + }; + + environment.persistence."/persist" = { + directories = [ + "/var/lib" + "/etc/NetworkManager" + ]; + files = [ + "/etc/machine-id" + "/etc/ssh/ssh_host_ed25519_key" + "/etc/ssh/ssh_host_ed25519_key.pub" + ]; + }; + + programs.fuse.userAllowOther = true; + + boot = { + loader = { + systemd-boot = { + enable = true; + consoleMode = "max"; + }; + + efi = { + canTouchEfiVariables = true; + efiSysMountPoint = "/boot"; + }; + }; + + initrd.luks.devices.main.device = "/dev/disk/by-label/cryptmain"; + + kernelParams = ["quiet" "splash" "vm.max_map_count=2147483642"]; + kernelPackages = lib.mkDefault pkgs.linuxPackages_zen; + }; + + zramSwap.enable = true; + + networking.networkmanager.enable = true; + users.users.lukas.extraGroups = ["networkmanager"]; + + time.timeZone = lib.mkDefault "Europe/Berlin"; + i18n.defaultLocale = lib.mkDefault "en_US.UTF-8"; + console.keyMap = lib.mkDefault "us"; + services.xserver.layout = lib.mkDefault "us"; + + programs.dconf.enable = true; + + # TODO + # xdg.portal.xdgOpenUsePortal = true; + + environment.systemPackages = with pkgs; [ + bibata-cursors + ]; +} diff --git a/common/nixos/features/avahi.nix b/common/nixos/features/avahi.nix new file mode 100644 index 0000000..94e2c07 --- /dev/null +++ b/common/nixos/features/avahi.nix @@ -0,0 +1,14 @@ +{ + services.avahi = { + enable = true; + nssmdns = true; + publish = { + enable = true; + addresses = true; + domain = true; + hinfo = true; + userServices = true; + workstation = true; + }; + }; +} diff --git a/common/nixos/features/bluetooth.nix b/common/nixos/features/bluetooth.nix new file mode 100644 index 0000000..3dac4a1 --- /dev/null +++ b/common/nixos/features/bluetooth.nix @@ -0,0 +1,3 @@ +{ + hardware.bluetooth.enable = true; +} diff --git a/common/nixos/features/command-not-found.nix b/common/nixos/features/command-not-found.nix new file mode 100644 index 0000000..fa415f2 --- /dev/null +++ b/common/nixos/features/command-not-found.nix @@ -0,0 +1,3 @@ +{ + programs.command-not-found.enable = false; +} diff --git a/common/nixos/features/fonts.nix b/common/nixos/features/fonts.nix new file mode 100644 index 0000000..8b38299 --- /dev/null +++ b/common/nixos/features/fonts.nix @@ -0,0 +1,26 @@ +{pkgs, ...}: { + fonts = { + enableDefaultPackages = true; + + packages = with pkgs; [ + noto-fonts + noto-fonts-extra + noto-fonts-cjk-sans + noto-fonts-cjk-serif + noto-fonts-emoji + (nerdfonts.override {fonts = ["Noto"];}) + (nerdfonts.override {fonts = ["Iosevka"];}) + ]; + + fontconfig = { + enable = true; + + defaultFonts = { + monospace = ["NotoSansMono Nerd Font"]; + sansSerif = ["Noto Sans"]; + serif = ["Noto Serif"]; + emoji = ["Noto Color Emoji"]; + }; + }; + }; +} diff --git a/common/nixos/features/fwupd.nix b/common/nixos/features/fwupd.nix new file mode 100644 index 0000000..a62f709 --- /dev/null +++ b/common/nixos/features/fwupd.nix @@ -0,0 +1,3 @@ +{ + services.fwupd.enable = true; +} diff --git a/common/nixos/features/geoclue.nix b/common/nixos/features/geoclue.nix new file mode 100644 index 0000000..ce62f46 --- /dev/null +++ b/common/nixos/features/geoclue.nix @@ -0,0 +1,3 @@ +{ + services.geoclue2.enable = true; +} diff --git a/common/nixos/features/greetd.nix b/common/nixos/features/greetd.nix new file mode 100644 index 0000000..3d635fa --- /dev/null +++ b/common/nixos/features/greetd.nix @@ -0,0 +1,10 @@ +{pkgs, ...}: { + services.greetd = { + enable = true; + settings = { + default_session = { + command = "${pkgs.greetd.tuigreet}/bin/tuigreet --time --cmd sway"; + }; + }; + }; +} diff --git a/common/nixos/features/opengl.nix b/common/nixos/features/opengl.nix new file mode 100644 index 0000000..96b99ce --- /dev/null +++ b/common/nixos/features/opengl.nix @@ -0,0 +1,6 @@ +{ + hardware.opengl = { + enable = true; + driSupport = true; + }; +} diff --git a/common/nixos/features/openssh.nix b/common/nixos/features/openssh.nix new file mode 100644 index 0000000..fc6275c --- /dev/null +++ b/common/nixos/features/openssh.nix @@ -0,0 +1,16 @@ +{ + services.openssh = { + enable = true; + openFirewall = true; + hostKeys = [ + { + path = "/etc/ssh/ssh_host_ed25519_key"; + type = "ed25519"; + } + ]; + settings = { + PermitRootLogin = "no"; + PasswordAuthentication = false; + }; + }; +} diff --git a/common/nixos/features/pipewire.nix b/common/nixos/features/pipewire.nix new file mode 100644 index 0000000..f09150e --- /dev/null +++ b/common/nixos/features/pipewire.nix @@ -0,0 +1,10 @@ +{ + security.rtkit.enable = true; + services.pipewire = { + enable = true; + wireplumber.enable = true; + alsa.enable = true; + pulse.enable = true; + jack.enable = true; + }; +} diff --git a/common/nixos/features/sops.nix b/common/nixos/features/sops.nix new file mode 100644 index 0000000..a5e7613 --- /dev/null +++ b/common/nixos/features/sops.nix @@ -0,0 +1,6 @@ +{inputs, ...}: { + sops.defaultSopsFile = ../../../secrets/default.yaml; + + sops.age.sshKeyPaths = ["/persist/etc/ssh/ssh_host_ed25519_key"]; + sops.gnupg.sshKeyPaths = []; +} diff --git a/common/nixos/features/sudo.nix b/common/nixos/features/sudo.nix new file mode 100644 index 0000000..9e6a881 --- /dev/null +++ b/common/nixos/features/sudo.nix @@ -0,0 +1,8 @@ +{ + security.sudo = { + enable = true; + execWheelOnly = true; + wheelNeedsPassword = true; + extraConfig = ''Defaults lecture="never"''; + }; +} diff --git a/common/nixos/features/swaylock.nix b/common/nixos/features/swaylock.nix new file mode 100644 index 0000000..93f484d --- /dev/null +++ b/common/nixos/features/swaylock.nix @@ -0,0 +1,3 @@ +{ + security.pam.services.swaylock = {}; +} diff --git a/common/nixos/features/users.nix b/common/nixos/features/users.nix new file mode 100644 index 0000000..1cad86d --- /dev/null +++ b/common/nixos/features/users.nix @@ -0,0 +1,29 @@ +{ + inputs, + pkgs, + config, + ... +}: { + sops.secrets."users/lukas".neededForUsers = true; + + programs.fish.enable = true; + users = { + mutableUsers = false; + users = { + root.hashedPassword = "!"; + lukas = { + isNormalUser = true; + shell = pkgs.fish; + hashedPasswordFile = config.sops.secrets."users/lukas".path; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK4U9RzV/gVGBfrCOye7BlS11g5BS7SmuZ36n2ZIJyAX lukas@glacier" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAztZgcRBHqX8Wb2nAlP1qCKF205M3un/D1YnREcO7Dy lukas@flamingo" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMC6vIcPgOHiAnG1be8IQVePlrsxN/X9PEFJghS6EcOb lukas@scenery" + ]; + extraGroups = ["wheel"]; + }; + }; + }; + + nix.settings.allowed-users = [config.users.users.lukas.name]; +} diff --git a/common/nixos/features/xdpw.nix b/common/nixos/features/xdpw.nix new file mode 100644 index 0000000..416c910 --- /dev/null +++ b/common/nixos/features/xdpw.nix @@ -0,0 +1,9 @@ +{pkgs, ...}: { + xdg.portal = { + enable = true; + extraPortals = [ + pkgs.xdg-desktop-portal-wlr + pkgs.xdg-desktop-portal-gtk + ]; + }; +} diff --git a/common/nixos/server.nix b/common/nixos/server.nix new file mode 100644 index 0000000..ce0d390 --- /dev/null +++ b/common/nixos/server.nix @@ -0,0 +1,99 @@ +{ + pkgs, + inputs, + config, + lib, + ... +}: { + imports = [ + (inputs.impermanence + "/nixos.nix") + + ./features/avahi.nix + ./features/command-not-found.nix + ./features/openssh.nix + ./features/sops.nix + ./features/sudo.nix + ./features/users.nix + ]; + + fileSystems = { + "/" = { + device = "tmpfs"; + fsType = "tmpfs"; + options = ["size=4G" "mode=755"]; + }; + + "/boot" = { + device = "/dev/disk/by-label/BOOT"; + fsType = "vfat"; + }; + + "/nix" = { + device = "/dev/disk/by-label/main"; + fsType = "btrfs"; + options = ["subvol=nix" "compress=zstd" "noatime"]; + }; + + "/persist" = { + device = "/dev/disk/by-label/main"; + fsType = "btrfs"; + options = ["subvol=persist" "compress=zstd" "noatime"]; + neededForBoot = true; + }; + + "/home" = { + device = "tmpfs"; + fsType = "tmpfs"; + options = ["size=4G" "mode=751"]; + neededForBoot = true; + }; + + "/tmp" = { + device = "tmpfs"; + fsType = "tmpfs"; + options = ["size=16G" "mode=777"]; + }; + + "/var/log" = { + device = "/dev/disk/by-label/main"; + fsType = "btrfs"; + options = ["subvol=log" "compress=zstd" "noatime"]; + neededForBoot = true; + }; + }; + + environment.persistence."/persist" = { + directories = [ + "/var/lib" + "/srv" + ]; + files = [ + "/etc/machine-id" + "/etc/ssh/ssh_host_ed25519_key" + "/etc/ssh/ssh_host_ed25519_key.pub" + ]; + }; + + programs.fuse.userAllowOther = true; + + boot = { + loader = { + systemd-boot = { + enable = true; + consoleMode = "max"; + }; + + efi = { + canTouchEfiVariables = true; + efiSysMountPoint = "/boot"; + }; + }; + }; + + zramSwap.enable = true; + + time.timeZone = lib.mkDefault "UTC"; + i18n.defaultLocale = lib.mkDefault "en_US.UTF-8"; + console.keyMap = lib.mkDefault "us"; + services.xserver.layout = lib.mkDefault "us"; +} diff --git a/ffcfg b/ffcfg new file mode 100755 index 0000000..893aa43 --- /dev/null +++ b/ffcfg @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +set -eu +shopt -s nullglob + +for dir in ~/.mozilla/firefox/*.default ~/.mozilla/firefox/*.default-release ~/.mozilla/firefox/*.dev-edition-default ~/.var/app/org.mozilla.firefox/.mozilla/firefox/*.default ~/.var/app/org.mozilla.firefox/.mozilla/firefox/*.default-release ~/.var/app/org.mozilla.firefox/.mozilla/firefox/*.dev-edition-default; do + cat < $dir/user.js +user_pref('signon.prefillForms', false); +user_pref('signon.rememberSignons', false); +user_pref('privacy.webrtc.legacyGlobalIndicator', false); +user_pref('browser.compactmode.show', true); +user_pref('toolkit.legacyUserProfileCustomizations.stylesheets', true); +user_pref('signon.autofillForms', false); +user_pref('signon.formlessCapture.enabled', false); +user_pref('browser.formfill.enable', false); +user_pref('extensions.pocket.enabled', false); +user_pref('browser.newtabpage.activity-stream.showSponsored', false); +user_pref('browser.newtabpage.activity-stream.showSponsoredTopSites', false); +user_pref('browser.newtabpage.activity-stream.feeds.section.topstories', false); +user_pref('browser.newtabpage.activity-stream.feeds.topsites', false); +user_pref('browser.newtabpage.activity-stream.section.highlights.includeBookmarks', false); +user_pref('browser.newtabpage.activity-stream.section.highlights.includeDownloads', false); +user_pref('browser.newtabpage.activity-stream.section.highlights.includeVisited', false); +user_pref('media.ffmpeg.vaapi.enabled', true); +user_pref('media.rdd-vpx.enabled', true); +user_pref('toolkit.telemetry.unified', false); +user_pref('toolkit.telemetry.enabled', false); +user_pref('toolkit.telemetry.server', 'data:,'); +user_pref('toolkit.telemetry.archive.enabled', false); +user_pref('toolkit.telemetry.newProfilePing.enabled', false); +user_pref('toolkit.telemetry.shutdownPingSender.enabled', false); +user_pref('toolkit.telemetry.updatePing.enabled', false); +user_pref('toolkit.telemetry.bhrPing.enabled', false); +user_pref('toolkit.telemetry.firstShutdownPing.enabled', false); +user_pref('toolkit.telemetry.coverage.opt-out', true); +user_pref('toolkit.coverage.opt-out', true); +user_pref('toolkit.coverage.endpoint.base', ''); +user_pref('browser.ping-centre.telemetry', false); +user_pref('app.shield.optoutstudies.enabled', false); +user_pref('app.normandy.enabled', false); +user_pref('app.normandy.api_url', ''); +user_pref('breakpad.reportURL', ''); +user_pref('browser.tabs.crashReporting.sendReport', false); +user_pref('browser.crashReports.unsubmittedCheck.autoSubmit2', false); +user_pref("network.http.referer.XOriginPolicy", 1); +user_pref("network.http.referer.XOriginTrimmingPolicy", 0); +EOF +done diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..c792c81 --- /dev/null +++ b/flake.lock @@ -0,0 +1,132 @@ +{ + "nodes": { + "hardware": { + "locked": { + "lastModified": 1694710316, + "narHash": "sha256-uRh46iIC86D8BD1wCDA5gRrt+hslUXiD0kx/UjnjBcs=", + "owner": "NixOS", + "repo": "nixos-hardware", + "rev": "570256327eb6ca6f7bebe8d93af49459092a0c43", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixos-hardware", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1694643239, + "narHash": "sha256-pv2k/5FvyirDE8g4TNehzwZ0T4UOMMmqWSQnM/luRtE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "d9b88b43524db1591fb3d9410a21428198d75d49", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "impermanence": { + "locked": { + "lastModified": 1694622745, + "narHash": "sha256-z397+eDhKx9c2qNafL1xv75lC0Q4nOaFlhaU1TINqb8=", + "owner": "nix-community", + "repo": "impermanence", + "rev": "e9643d08d0d193a2e074a19d4d90c67a874d932e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "impermanence", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1694767346, + "narHash": "sha256-5uH27SiVFUwsTsqC5rs3kS7pBoNhtoy9QfTP9BmknGk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ace5093e36ab1e95cb9463863491bee90d5a4183", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1693675694, + "narHash": "sha256-2pIOyQwGyy2FtFAUIb8YeKVmOCcPOTVphbAvmshudLE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5601118d39ca9105f8e7b39d4c221d3388c0419d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1693626178, + "narHash": "sha256-Rpiy6lIOu4zny8tfGuIeN1ji9eSz9nPmm9yBhh/4IOM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bfb7dfec93f3b5d7274db109f2990bc889861caf", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "hardware": "hardware", + "home-manager": "home-manager", + "impermanence": "impermanence", + "nixpkgs": "nixpkgs", + "sops-nix": "sops-nix" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": "nixpkgs_2", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1694495315, + "narHash": "sha256-sZEYXs9T1NVHZSSbMqBEtEm2PGa7dEDcx0ttQkArORc=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "ea208e55f8742fdcc0986b256bdfa8986f5e4415", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..4f479c1 --- /dev/null +++ b/flake.nix @@ -0,0 +1,113 @@ +{ + description = "My NixOS configuration"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + hardware.url = "github:NixOS/nixos-hardware"; + + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + impermanence.url = "github:nix-community/impermanence"; + + sops-nix.url = "github:Mic92/sops-nix"; + }; + + outputs = { + self, + nixpkgs, + home-manager, + sops-nix, + ... + } @ inputs: let + inherit (self) outputs; + + forEachSystem = f: + nixpkgs.lib.genAttrs [ + "x86_64-linux" + "aarch64-linux" + ] (system: + f { + pkgs = import nixpkgs {inherit system;}; + }); + + mkSystem = class: name: args @ {modules ? [], ...}: + nixpkgs.lib.nixosSystem ({ + specialArgs = {inherit inputs;}; + } + // args + // { + modules = + modules + ++ [ + ({ + lib, + config, + ... + }: { + nix = { + registry = lib.mapAttrs (_: value: {flake = value;}) inputs; + + nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry; + + settings = { + experimental-features = "nix-command flakes"; + auto-optimise-store = true; + }; + }; + + nixpkgs.config.allowUnfree = true; + + networking.hostName = lib.mkDefault name; + }) + (./common/nixos + "/${class}.nix") + (./nixos + "/${name}") + home-manager.nixosModules.home-manager + { + home-manager = { + useGlobalPkgs = true; + extraSpecialArgs = {inherit inputs;}; + users.lukas.imports = [ + ({config, ...}: { + home.homeDirectory = + nixpkgs.lib.mkDefault "/home/${config.home.username}"; + + systemd.user.startServices = "sd-switch"; + }) + (./common/home-manager + "/${class}.nix") + (./home-manager + "/${name}/lukas.nix") + ]; + }; + } + (sops-nix + "/modules/sops") + ]; + }); + + setups = { + desktop = { + glacier = {}; + + flamingo = {}; + + scenery = {}; + }; + + server = { + abacus = {}; + + vessel = {}; + }; + }; + in { + formatter = forEachSystem ({pkgs}: pkgs.alejandra); + + nixosConfigurations = + nixpkgs.lib.attrsets.mergeAttrsList + (builtins.attrValues (nixpkgs.lib.mapAttrs + (class: configs: (nixpkgs.lib.mapAttrs (mkSystem class) configs)) + setups)); + }; +} diff --git a/home-manager/abacus/lukas.nix b/home-manager/abacus/lukas.nix new file mode 100644 index 0000000..c8f750a --- /dev/null +++ b/home-manager/abacus/lukas.nix @@ -0,0 +1,9 @@ +{pkgs, ...}: { + home = { + username = "lukas"; + packages = with pkgs; [ + gitea + ]; + stateVersion = "23.11"; + }; +} diff --git a/home-manager/flamingo/lukas.nix b/home-manager/flamingo/lukas.nix new file mode 100644 index 0000000..72321cd --- /dev/null +++ b/home-manager/flamingo/lukas.nix @@ -0,0 +1,66 @@ +{pkgs, ...}: { + home = { + username = "lukas"; + stateVersion = "23.11"; + }; + + wayland.windowManager.sway = { + config = { + input."type:keyboard".xkb_layout = "de"; + + output.eDP-1 = { + mode = "1920x1080"; + position = "0,0"; + background = ''"$(${pkgs.xdg-user-dirs}/bin/xdg-user-dir PICTURES)/sway/primary" fill''; + }; + + workspaceOutputAssign = [ + { + output = "e-DP1"; + workspace = "number 1"; + } + { + output = "e-DP1"; + workspace = "number 2"; + } + { + output = "e-DP1"; + workspace = "number 3"; + } + { + output = "e-DP1"; + workspace = "number 4"; + } + { + output = "e-DP1"; + workspace = "number 5"; + } + { + output = "e-DP1"; + workspace = "number 6"; + } + { + output = "e-DP1"; + workspace = "number 7"; + } + { + output = "e-DP1"; + workspace = "number 8"; + } + { + output = "e-DP1"; + workspace = "number 9"; + } + { + output = "e-DP1"; + workspace = "number 10"; + } + ]; + + gaps = { + inner = 4; + outer = 6; + }; + }; + }; +} diff --git a/home-manager/glacier/lukas.nix b/home-manager/glacier/lukas.nix new file mode 100644 index 0000000..e2fea36 --- /dev/null +++ b/home-manager/glacier/lukas.nix @@ -0,0 +1,98 @@ +{pkgs, ...}: { + home = { + username = "lukas"; + packages = with pkgs; [ + nvtop-amd + mullvad-vpn + ]; + stateVersion = "23.11"; + }; + + wayland.windowManager.sway = let + primary = "Acer Technologies XB283K KV 120918F984200"; + secondary = "LG Electronics LG HDR 4K 0x00008FEE"; + in { + config = { + output.${primary} = { + mode = "3840x2160@144.004Hz"; + position = "0,0"; + background = ''"$(${pkgs.xdg-user-dirs}/bin/xdg-user-dir PICTURES)/sway/primary" fill''; + }; + + output.${secondary} = { + mode = "3840x2160@59.997Hz"; + position = "3840,-1680"; + transform = "90"; + background = ''"$(${pkgs.xdg-user-dirs}/bin/xdg-user-dir PICTURES)/sway/secondary" fill''; + }; + + workspaceOutputAssign = [ + { + output = primary; + workspace = "1"; + } + { + output = primary; + workspace = "2"; + } + { + output = primary; + workspace = "3"; + } + { + output = primary; + workspace = "4"; + } + { + output = primary; + workspace = "5"; + } + { + output = primary; + workspace = "6"; + } + { + output = primary; + workspace = "7"; + } + { + output = primary; + workspace = "8"; + } + { + output = primary; + workspace = "9"; + } + { + output = primary; + workspace = "10"; + } + { + output = secondary; + workspace = "11"; + } + { + output = secondary; + workspace = "12"; + } + { + output = secondary; + workspace = "13"; + } + { + output = secondary; + workspace = "14"; + } + ]; + + gaps = { + inner = 12; + outer = 14; + }; + + input."Razer Razer DeathAdder V3" = { + pointer_accel = "0.0"; + }; + }; + }; +} diff --git a/home-manager/scenery/lukas.nix b/home-manager/scenery/lukas.nix new file mode 100644 index 0000000..72321cd --- /dev/null +++ b/home-manager/scenery/lukas.nix @@ -0,0 +1,66 @@ +{pkgs, ...}: { + home = { + username = "lukas"; + stateVersion = "23.11"; + }; + + wayland.windowManager.sway = { + config = { + input."type:keyboard".xkb_layout = "de"; + + output.eDP-1 = { + mode = "1920x1080"; + position = "0,0"; + background = ''"$(${pkgs.xdg-user-dirs}/bin/xdg-user-dir PICTURES)/sway/primary" fill''; + }; + + workspaceOutputAssign = [ + { + output = "e-DP1"; + workspace = "number 1"; + } + { + output = "e-DP1"; + workspace = "number 2"; + } + { + output = "e-DP1"; + workspace = "number 3"; + } + { + output = "e-DP1"; + workspace = "number 4"; + } + { + output = "e-DP1"; + workspace = "number 5"; + } + { + output = "e-DP1"; + workspace = "number 6"; + } + { + output = "e-DP1"; + workspace = "number 7"; + } + { + output = "e-DP1"; + workspace = "number 8"; + } + { + output = "e-DP1"; + workspace = "number 9"; + } + { + output = "e-DP1"; + workspace = "number 10"; + } + ]; + + gaps = { + inner = 4; + outer = 6; + }; + }; + }; +} diff --git a/home-manager/vessel/lukas.nix b/home-manager/vessel/lukas.nix new file mode 100644 index 0000000..314c368 --- /dev/null +++ b/home-manager/vessel/lukas.nix @@ -0,0 +1,6 @@ +{pkgs, ...}: { + home = { + username = "lukas"; + stateVersion = "23.11"; + }; +} diff --git a/nixos/abacus/default.nix b/nixos/abacus/default.nix new file mode 100644 index 0000000..6d43075 --- /dev/null +++ b/nixos/abacus/default.nix @@ -0,0 +1,81 @@ +{ + lib, + pkgs, + inputs, + config, + self, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + + ./gitea.nix + ./hiraeth.nix + ./navidrome.nix + ./vaultwarden.nix + ./woodpecker.nix + ]; + + nixpkgs.hostPlatform = "aarch64-linux"; + + boot.initrd.availableKernelModules = ["xhci_pci" "virtio_pci" "virtio_scsi" "usbhid" "sr_mod"]; + + system.stateVersion = "23.11"; + + powerManagement.cpuFreqGovernor = "performance"; + + networking = { + interfaces.enp1s0.ipv6.addresses = [ + { + address = "2a01:4f8:c012:24ed::2"; + prefixLength = 64; + } + ]; + defaultGateway6 = { + address = "fe80::1"; + interface = "enp1s0"; + }; + firewall.allowedTCPPorts = [80 443]; + }; + + security.acme = { + defaults.email = "lukas@wrz.one"; + acceptTerms = true; + }; + + services.nginx = { + enable = true; + + recommendedGzipSettings = true; + recommendedBrotliSettings = true; + recommendedTlsSettings = true; + recommendedOptimisation = true; + + virtualHosts = { + "wrz.one" = { + enableACME = true; + forceSSL = true; + locations."/" = { + root = "/srv/http/wrz.one"; + }; + }; + + "defenestrated.systems" = { + enableACME = true; + forceSSL = true; + locations."/" = { + root = "/srv/http/defenestrated.systems"; + }; + }; + + "static.defenestrated.systems" = { + enableACME = true; + forceSSL = true; + locations."/" = { + root = "/srv/http/static.defenestrated.systems"; + }; + }; + }; + }; +} diff --git a/nixos/abacus/gitea.nix b/nixos/abacus/gitea.nix new file mode 100644 index 0000000..dcf7cbd --- /dev/null +++ b/nixos/abacus/gitea.nix @@ -0,0 +1,43 @@ +{config, ...}: let + fqdn = "git.defenestrated.systems"; +in { + services.nginx.virtualHosts.${fqdn} = { + enableACME = true; + forceSSL = true; + locations."/" = { + recommendedProxySettings = true; + proxyPass = "http://127.0.0.1:${builtins.toString config.services.gitea.settings.server.HTTP_PORT}"; + }; + }; + + services.gitea = { + enable = true; + + appName = "git.defenestrated.systems"; + + database.type = "postgres"; + + settings = { + server = { + ROOT_URL = "https://${fqdn}/"; + HTTP_PORT = 8020; + DOMAIN = fqdn; + DISABLE_REGISTRATION = true; + }; + }; + + lfs.enable = true; + }; + + services.postgresql = { + enable = true; + + authentication = '' + local gitea all ident map=gitea-users + ''; + + identMap = '' + gitea-users gitea gitea + ''; + }; +} diff --git a/nixos/abacus/hiraeth.nix b/nixos/abacus/hiraeth.nix new file mode 100644 index 0000000..1f10cb7 --- /dev/null +++ b/nixos/abacus/hiraeth.nix @@ -0,0 +1,116 @@ +{ + pkgs, + config, + lib, + ... +}: let + hiraeth = let + version = "1.1.1"; + in + pkgs.callPackage pkgs.buildGoModule { + pname = "hiraeth"; + inherit version; + src = pkgs.fetchFromGitHub { + owner = "lukaswrz"; + repo = "hiraeth"; + rev = "v${version}"; + hash = "sha256-GPDGwrYVy9utp5u4iyf0PqIAlI/izcwAsj4yFStYmTE="; + }; + vendorSha256 = "sha256-bp9xDB7tplHEBR1Z+Ouks2ZwcktAhaZ/zSSPcu7LWr8="; + }; +in { + services.nginx.virtualHosts."share.defenestrated.systems" = { + enableACME = true; + forceSSL = true; + locations."/" = { + recommendedProxySettings = true; + proxyPass = "http://127.0.0.1:8010"; + }; + }; + + users = { + users = { + hiraeth = { + isSystemUser = true; + group = config.users.groups.hiraeth.name; + }; + }; + groups.hiraeth = {}; + }; + + systemd.services.hiraeth = { + description = "Hiraeth File Sharing Service"; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = rec { + Type = "simple"; + User = config.users.users.hiraeth.name; + Group = config.users.groups.hiraeth.name; + # DynamicUser = true; + StateDirectory = "hiraeth"; + StateDirectoryMode = "0700"; + UMask = "0077"; + WorkingDirectory = "/var/lib/hiraeth"; + ExecStart = "${hiraeth}/bin/hiraeth run"; + Restart = "on-failure"; + TimeoutSec = 15; + ReadOnlyPaths = "/etc/hiraeth/hiraeth.toml"; + + DevicePolicy = "closed"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + ProtectHome = "read-only"; + PrivateTmp = true; + PrivateUsers = true; + ProtectControlGroups = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = ["AF_INET" "AF_INET6"]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + }; + }; + + sops.secrets."hiraeth/session_secret" = { + mode = "0400"; + owner = config.users.users.hiraeth.name; + group = config.users.users.hiraeth.group; + }; + + environment.etc."hiraeth/hiraeth.toml" = let + settings = { + address = "localhost:8010"; + name = "hiraeth"; + data = "data"; + database_file = "hiraeth.db"; + trusted_proxies = [ + "127.0.0.1" + ]; + inline_types = [ + "image/png" + "image/jpeg" + "application/pdf" + ]; + session_secret_file = config.sops.secrets."hiraeth/session_secret".path; + chunk_size = 8388608; + }; + + settingsFormat = pkgs.formats.toml {}; + + settingsFile = settingsFormat.generate "hiraeth.toml" settings; + in { + source = settingsFile; + + mode = "0440"; + user = config.users.users.hiraeth.name; + group = config.users.users.hiraeth.group; + }; +} diff --git a/nixos/abacus/navidrome.nix b/nixos/abacus/navidrome.nix new file mode 100644 index 0000000..d93d190 --- /dev/null +++ b/nixos/abacus/navidrome.nix @@ -0,0 +1,28 @@ +{config, ...}: let + musicDir = "/srv/music"; +in { + services.navidrome = { + enable = true; + + settings = { + Address = "127.0.0.1"; + Port = 8040; + MusicFolder = musicDir; + }; + }; + + services.nginx.virtualHosts."music.defenestrated.systems" = { + enableACME = true; + forceSSL = true; + locations."/" = { + recommendedProxySettings = true; + proxyPass = "http://127.0.0.1:${builtins.toString config.services.navidrome.settings.Port}"; + }; + }; + + fileSystems.${musicDir} = { + device = "/dev/disk/by-label/storage"; + fsType = "btrfs"; + options = ["subvol=music" "compress=zstd" "noatime"]; + }; +} diff --git a/nixos/abacus/vaultwarden.nix b/nixos/abacus/vaultwarden.nix new file mode 100644 index 0000000..75acd97 --- /dev/null +++ b/nixos/abacus/vaultwarden.nix @@ -0,0 +1,20 @@ +{config, ...}: { + services.vaultwarden = { + enable = true; + + config = { + SIGNUPS_ALLOWED = false; + ROCKET_ADDRESS = "127.0.0.1"; + ROCKET_PORT = 8000; + }; + }; + + services.nginx.virtualHosts."vault.defenestrated.systems" = { + enableACME = true; + forceSSL = true; + locations."/" = { + recommendedProxySettings = true; + proxyPass = "http://${config.services.vaultwarden.config.ROCKET_ADDRESS}:${builtins.toString config.services.vaultwarden.config.ROCKET_PORT}"; + }; + }; +} diff --git a/nixos/abacus/woodpecker.nix b/nixos/abacus/woodpecker.nix new file mode 100644 index 0000000..e08d4e3 --- /dev/null +++ b/nixos/abacus/woodpecker.nix @@ -0,0 +1,162 @@ +{ + config, + pkgs, + lib, + ... +}: let + giteaSecretFile = config.sops.secrets."woodpecker/gitea".path; + sharedSecretFile = config.sops.secrets."woodpecker/shared".path; + + port = 3030; + rpcPort = 3031; +in { + sops.secrets."woodpecker/gitea" = {}; + sops.secrets."woodpecker/shared" = {}; + + services.postgresql = { + enable = true; + + ensureDatabases = ["woodpecker"]; + + ensureUsers = [ + { + name = "woodpecker"; + ensurePermissions = { + "DATABASE woodpecker" = "ALL PRIVILEGES"; + }; + } + ]; + }; + + services.nginx.virtualHosts."woodpecker.defenestrated.systems" = { + enableACME = true; + forceSSL = true; + locations."/".proxyPass = "http://localhost:${builtins.toString port}/"; + }; + + services = { + woodpecker-server = { + enable = true; + + environment = { + WOODPECKER_HOST = "https://woodpecker.defenestrated.systems"; + WOODPECKER_OPEN = "false"; + WOODPECKER_GITEA = "true"; + WOODPECKER_GITEA_CLIENT = "true"; + WOODPECKER_GITEA_URL = config.services.gitea.settings.server.ROOT_URL; + WOODPECKER_ADMIN = "lukaswrz"; + + WOODPECKER_DATABASE_DRIVER = "postgres"; + WOODPECKER_DATABASE_DATASOURCE = "postgres:///woodpecker?host=/run/postgresql"; + + WOODPECKER_SERVER_ADDR = ":${builtins.toString port}"; + WOODPECKER_GRPC_ADDR = ":${builtins.toString rpcPort}"; + + WOODPECKER_LOG_LEVEL = "debug"; + }; + }; + + woodpecker-agents = { + agents.exec = { + enable = true; + + environment = { + WOODPECKER_SERVER = "localhost:${toString rpcPort}"; + WOODPECKER_MAX_WORKFLOWS = "10"; + WOODPECKER_BACKEND = "local"; + WOODPECKER_FILTER_LABELS = "type=exec"; + WOODPECKER_HEALTHCHECK = "false"; + + NIX_REMOTE = "daemon"; + PAGER = "cat"; + }; + + environmentFile = [sharedSecretFile]; + }; + + agents.docker = { + enable = true; + + environment = { + WOODPECKER_SERVER = "localhost:${toString rpcPort}"; + WOODPECKER_MAX_WORKFLOWS = "10"; + WOODPECKER_BACKEND = "docker"; + WOODPECKER_FILTER_LABELS = "type=docker"; + WOODPECKER_HEALTHCHECK = "false"; + }; + + environmentFile = [sharedSecretFile]; + + extraGroups = ["docker"]; + }; + }; + }; + + systemd.services.woodpecker-server = { + serviceConfig = { + # Set username for database access + User = "woodpecker"; + + BindPaths = [ + # Allow access to the database path + "/run/postgresql" + ]; + + # Why is services.woodpecker-server.environmentFile just a single path? + EnvironmentFile = [giteaSecretFile sharedSecretFile]; + }; + }; + + # Adjust exec runner service for Nix + systemd.services.woodpecker-agent-exec = { + # Might break deployment + restartIfChanged = false; + + path = with pkgs; [ + woodpecker-plugin-git + bash + coreutils + git + git-lfs + gnutar + gzip + nix + ]; + + serviceConfig = { + # Same option as upstream, without @setuid + SystemCallFilter = lib.mkForce "~@clock @privileged @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap"; + + BindPaths = [ + "/nix/var/nix/daemon-socket/socket" + "/run/nscd/socket" + ]; + + BindReadOnlyPaths = [ + "/etc/passwd:/etc/passwd" + "/etc/group:/etc/group" + "/etc/nix:/etc/nix" + "${config.environment.etc."ssh/ssh_known_hosts".source}:/etc/ssh/ssh_known_hosts" + "/etc/machine-id" + # Channels are dynamic paths in the nix store, therefore we need to bind mount the whole thing + "/nix/" + ]; + }; + }; + + virtualisation.docker.enable = true; + + # Adjust Docker runner service for Nix + systemd.services.woodpecker-agent-docker = { + after = ["docker.socket"]; + + # Might break deployment + restartIfChanged = false; + + serviceConfig = { + BindPaths = [ + "/var/run/docker.sock" + ]; + }; + }; +} diff --git a/nixos/features/flatpak.nix b/nixos/features/flatpak.nix new file mode 100644 index 0000000..9ea3baf --- /dev/null +++ b/nixos/features/flatpak.nix @@ -0,0 +1,32 @@ +{ + pkgs, + config, + ... +}: { + services.flatpak.enable = true; + + # Workaround for https://github.com/NixOS/nixpkgs/issues/119433 + system.fsPackages = [pkgs.bindfs]; + fileSystems = let + mkRoSymBind = path: { + device = path; + fsType = "fuse.bindfs"; + options = ["ro" "resolve-symlinks" "x-gvfs-hide"]; + }; + # TODO + # aggregatedIcons = pkgs.buildEnv { + # name = "system-icons"; + # paths = config.environment.systemPackages; + # pathsToLink = [ "/share/icons" ]; + # }; + aggregatedFonts = pkgs.buildEnv { + name = "system-fonts"; + paths = config.fonts.packages; + pathsToLink = ["/share/fonts"]; + }; + in { + # "/usr/share/icons" = mkRoSymBind "${aggregatedIcons}/share/icons"; + "/usr/share/icons" = mkRoSymBind "/run/current-system/sw/share/icons"; + "/usr/share/fonts" = mkRoSymBind "${aggregatedFonts}/share/fonts"; + }; +} diff --git a/nixos/features/opentabletdriver.nix b/nixos/features/opentabletdriver.nix new file mode 100644 index 0000000..3397874 --- /dev/null +++ b/nixos/features/opentabletdriver.nix @@ -0,0 +1,3 @@ +{ + hardware.opentabletdriver.enable = true; +} diff --git a/nixos/features/printing.nix b/nixos/features/printing.nix new file mode 100644 index 0000000..eebebac --- /dev/null +++ b/nixos/features/printing.nix @@ -0,0 +1,9 @@ +{ + services = { + printing = { + enable = true; + webInterface = false; + }; + system-config-printer.enable = true; + }; +} diff --git a/nixos/features/steam.nix b/nixos/features/steam.nix new file mode 100644 index 0000000..141efd5 --- /dev/null +++ b/nixos/features/steam.nix @@ -0,0 +1,12 @@ +{ + programs.steam = { + enable = true; + remotePlay.openFirewall = true; + dedicatedServer.openFirewall = true; + }; + + programs.gamescope = { + enable = true; + capSysNice = true; + }; +} diff --git a/nixos/flamingo/default.nix b/nixos/flamingo/default.nix new file mode 100644 index 0000000..4e704e4 --- /dev/null +++ b/nixos/flamingo/default.nix @@ -0,0 +1,33 @@ +{ + lib, + pkgs, + inputs, + config, + self, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + + inputs.hardware.nixosModules.lenovo-thinkpad-t480 + + ../features/flatpak.nix + ]; + + nixpkgs.hostPlatform = "x86_64-linux"; + + boot = { + initrd.availableKernelModules = ["xhci_pci" "nvme" "usb_storage" "sd_mod"]; + kernelModules = ["kvm-intel"]; + }; + + hardware.cpu.intel.updateMicrocode = config.hardware.enableRedistributableFirmware; + + system.stateVersion = "23.11"; + + powerManagement.cpuFreqGovernor = "powersave"; + + console.keyMap = "de"; + services.xserver.layout = "de"; +} diff --git a/nixos/glacier/default.nix b/nixos/glacier/default.nix new file mode 100644 index 0000000..3362617 --- /dev/null +++ b/nixos/glacier/default.nix @@ -0,0 +1,53 @@ +{ + pkgs, + inputs, + config, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + + inputs.hardware.nixosModules.common-cpu-amd + inputs.hardware.nixosModules.common-gpu-amd + inputs.hardware.nixosModules.common-pc-ssd + + ../features/flatpak.nix + ../features/opentabletdriver.nix + ../features/printing.nix + ../features/steam.nix + ]; + + nixpkgs.hostPlatform = "x86_64-linux"; + + boot = { + initrd = { + availableKernelModules = ["nvme" "ahci" "xhci_pci" "usbhid" "usb_storage" "sd_mod"]; + kernelModules = ["amdgpu"]; + }; + kernelModules = ["kvm-amd"]; + + binfmt.emulatedSystems = ["aarch64-linux"]; + }; + + hardware.cpu.amd.updateMicrocode = config.hardware.enableRedistributableFirmware; + + system.stateVersion = "23.11"; + + powerManagement.cpuFreqGovernor = "performance"; + + services.printing.drivers = with pkgs; [ + epson-escpr + epson-escpr2 + ]; + + services.mullvad-vpn.enable = true; + + services.xserver = { + enable = true; + layout = "us"; + libinput.enable = true; + windowManager.i3.enable = true; + displayManager.startx.enable = true; + }; +} diff --git a/nixos/scenery/default.nix b/nixos/scenery/default.nix new file mode 100644 index 0000000..10a4095 --- /dev/null +++ b/nixos/scenery/default.nix @@ -0,0 +1,29 @@ +{ + pkgs, + inputs, + config, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + + inputs.hardware.nixosModules.lenovo-thinkpad-x260 + ]; + + nixpkgs.hostPlatform = "x86_64-linux"; + + boot = { + initrd.availableKernelModules = ["xhci_pci" "nvme" "usb_storage" "sd_mod"]; + kernelModules = ["kvm-intel"]; + }; + + hardware.cpu.intel.updateMicrocode = config.hardware.enableRedistributableFirmware; + + system.stateVersion = "23.11"; + + powerManagement.cpuFreqGovernor = "powersave"; + + console.keyMap = "de"; + services.xserver.layout = "de"; +} diff --git a/nixos/vessel/backup.nix b/nixos/vessel/backup.nix new file mode 100644 index 0000000..cf99717 --- /dev/null +++ b/nixos/vessel/backup.nix @@ -0,0 +1,27 @@ +{pkgs, ...}: { + systemd.timers.local-backup = { + description = "Local rsync Backup"; + wantedBy = ["timers.target"]; + timerConfig = { + OnCalendar = "*-*-* 00:00:00"; + Persistent = true; + Unit = "rsync-backup.service"; + }; + }; + + systemd.services.local-backup = { + description = "Local rsync Backup"; + serviceConfig = { + Type = "oneshot"; + ExecStart = ''${pkgs.rsync}/bin/rsync --verbose --verbose --archive --update --delete /srv/storage/ /srv/backup/''; + User = "root"; + Group = "root"; + }; + }; + + fileSystems."/srv/backup" = { + device = "/dev/disk/by-label/backup"; + fsType = "btrfs"; + options = ["subvol=main" "compress=zstd" "noatime"]; + }; +} diff --git a/nixos/vessel/default.nix b/nixos/vessel/default.nix new file mode 100644 index 0000000..6cad068 --- /dev/null +++ b/nixos/vessel/default.nix @@ -0,0 +1,38 @@ +{ + lib, + pkgs, + inputs, + config, + self, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + + inputs.hardware.nixosModules.common-cpu-intel + inputs.hardware.nixosModules.common-gpu-intel + inputs.hardware.nixosModules.common-pc-ssd + + ./backup.nix + ]; + + nixpkgs.hostPlatform = "x86_64-linux"; + + boot = { + initrd.availableKernelModules = ["ahci" "xhci_pci" "usbhid" "usb_storage" "sd_mod"]; + kernelModules = ["kvm-intel"]; + }; + + hardware.cpu.intel.updateMicrocode = config.hardware.enableRedistributableFirmware; + + system.stateVersion = "23.11"; + + powerManagement.cpuFreqGovernor = "performance"; + + fileSystems."/srv/storage" = { + device = "/dev/disk/by-label/storage"; + fsType = "btrfs"; + options = ["subvol=main" "compress=zstd" "noatime"]; + }; +} diff --git a/secrets/default.yaml b/secrets/default.yaml new file mode 100644 index 0000000..19e64cd --- /dev/null +++ b/secrets/default.yaml @@ -0,0 +1,72 @@ +users: + lukas: ENC[AES256_GCM,data:ZWqn13HJAjUTENyhIm9V2VwPxFn6w936vE+iJCl/siozbtl844elAIDyMq3o+rjDshQrF/zbP13CWsdhG4HBmQVAN+kekNYzsB9eNKRJbPRoBDn1WY7CQaTg+nSpxs369hjiqIk5rJN7qQ==,iv:CMNhONeR1dtsR5Et3CqrphiNJA6Pm9DGsdjEEMP33ew=,tag:APEIninRHTwegf5MdaPhsA==,type:str] +woodpecker: + gitea: ENC[AES256_GCM,data:UHXxNfwjwFe4W36gt1o7JAYwqjwRAkYhZzM5OvEqXcfwhrZ0W46WqnrKLtPIjBsOajQiysqk0VpHmNGbxcSAUU6CQ0mcRCT5l6wte5lyIba6GCqiKxn+M7bqBhLFm0Yn9bFnoNm+QRiOCsvglMGdxZlQwJgS2XRkiMIRg6bB2QqcXbXtcw7w79H7smZjgA==,iv:Jz4qkB/XVcrN05LIFNXq1lPLD45mxKRc1ioqn8wf1xg=,tag:mLX2Lryo4dl3+L8WJwUYdw==,type:str] + shared: ENC[AES256_GCM,data:plxZCJOZ3GkBcHkek7tZJoqIoJjNYjLeyeqUXelumn6wa8rvWiBA4Ji3MVg++xVW9ZxxHjFAxfOi,iv:r3lC9qC02mG8sJ/a3avBfxszwtdULt0DF2iGcN4wrjY=,tag:rsXE2xoVjbDZmzOLX1MM6A==,type:str] +hiraeth: + session_secret: ENC[AES256_GCM,data:ZjKWkpN19sZ9MvrsHQnb8oIDsg4MEIFoGEpWPegMRfAfvZU5WDmwb7+A6VrluqFCGErfLQ8/q0cTTBybdqbDtA==,iv:/iUel/2DzAmjHH1OIascoP0wfuTxaRTIDalVCjfUNss=,tag:xJYh7Hv22+cE34gNJ0ABkA==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age17nt4yca38wrlptapekwmkrjx232cruygty82qhvz3t7g7z4jq9fshdglks + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpLzdCU1ZqQlo1TnFwRDZp + dkJyUEZlSnVMaG1kelZIR0FGRUNKV0JtQ1RVCkZ6RDFmU0txejBCZjUvOTRrMWkz + dTlFaEoxOU9lZ29vaVVKQ3BzMjdyanMKLS0tIFRzWFFPY3ZCL0lMY3ZVNDFKTW5n + VnQ1MHd3dmFUWTc0Rnh2Q095SjhXdTQKKD5UWbzyodQ53CT08eJe/9ZyZawgEFU8 + GSP4ItGIh6mfCssZoQ5P4rS2H8x+ycSaz2rLD9q3p1RDP9QQBnPovw== + -----END AGE ENCRYPTED FILE----- + - recipient: age190zn56uqtemazc4fjtc649h7634hl9zh6jzrmq478y2t94x8vswqv5q3j8 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZdEs2ZVlZcWJCM0JGcnB4 + aGhRY3ZWcEo3Z1h0N3ZTd2VvTjJ4cmVpcldVCnY4MTJiSjJHZThabTE4RTZmeWRL + WWp2UC9jRTRLcEtmWmMvYWllOENWcmcKLS0tIHhhL0FOODh5Sm1ldmhVMGxJVGRw + dUUyM0VSQVFtQTVNVzNibWRqWk1TM0UKpYfwcLOwAk/VkfmciLuMekGlHe+Bzn3a + hatmpeAGc7Kmkb1hDjhweq/MEIKtIamm0vYnmOmOwA1U94+7UkB79Q== + -----END AGE ENCRYPTED FILE----- + - recipient: age1p55v299rqjg7ltz3h3suq2efrgsntn2ej9lzljw9prkx50x7hd4s7cnfcc + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWc2NXUUZ0cHRmVTlhV3p2 + dHNGa1FWRzFneUlSSmJzeHhuV0QxSXlCN1ZvCjJTaWZhOGFUYmRidXZwR00vSTQ5 + MUw4TkhTaE1lU1UzQTh3UUJla0crSm8KLS0tIGFNNXRJZkRJRTdpZEZUZmJaTEpV + NWdSM0hmcHpId2RiRDFKUGNDZE0rUW8KqZttjrJXXdOYSfe0hbLkQHCOXf81NoCi + 6he+/81wLsQSvkFRD5KrjQKcs9FzxggG/pHhSv408VGD/3gFRxjTtg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1nxr8lyst9eleuu9dyrnlwps8xschps42tfzwxfyvyy32n75rssfsayj52j + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjNHJoQUJqRTZRbWo5V21p + blhBMFExby95NTdGUy8rck13SzlIRHRKZzAwCjRDeEV6K3pjUnVqM1NtQ3BzUGZo + RGt5RkcyU3FiVllUU3drMEszNHpPRTQKLS0tIHJaSERKQjJEaW1oRCtGc2dlUXpL + bWxreFI2ZDlTR3VBNUppZTNiU2E2NzAK2tcBp5tEtwvV5qQlcSp3W3svkz3DyPsv + JiOoh+BOQz2MMaIFfTUwwMuIrROwtQlXu38vfle6ANFS0BYvJqsrtw== + -----END AGE ENCRYPTED FILE----- + - recipient: age15hmzz0mdrrtlrxwdyv7wfwfs58vzcyg3esnf5ccu5vlg83a8aq6sqp95dv + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEUmZaTDgvNCttOXhFZW9t + SkxBekZnZkM3aXB1MUdkcmdkWWhGRzJjVGdRCklRdzNRMTFINHVmajFlR2JSdGZI + eDM3dk00K243QWU0NFVxUDRUNm9FdXMKLS0tIDc5WGhUb0l5WE83ZWxmOERqTW1j + QStSd0Zaa1dIbHg0LysrTGgyMUdLUHMKXt0WQnMFH0z6rfTGC5isM3U1GQsEB+DR + GhzgI8mycdd0HQWxiFUAL+Wj5hhw2O+EZDigQ4Ky9/Wmee1jyH1T5g== + -----END AGE ENCRYPTED FILE----- + - recipient: age1fvn3rex66xczhard8dcx0s38xdegvguyaepytu6kh9hndhheqqwqcgnc3y + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzVWwwcXFJb2lwbjhuZGF6 + eUFuSzhaWWFMdmFjV25sQ1hHRFF5Z2R5MEdrCmJXdWlsb1BGakN5ZWxyVUppcGky + ZjRJbEFQdE02azNFcGszMVVLemxxeEEKLS0tIGpUZTZ3ZThid1U4YzdyM1F3L3gz + VUZ6QitucE1OVTdobHhrK3B5TGljS2sKalCwO2GBQHXmb2NLdsdtzr8u0EaMjxSL + WDPXbOYfJ66BwqmnbW7zMiTDf21OKrZAvcbwtoZ3CtJvs5D6I9ygdw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2023-09-04T19:08:24Z" + mac: ENC[AES256_GCM,data:X4SOdGY/MiD28vhbWzDRYUb4pvafB3rpaUyZhJTuadPCDqs8zVvL8A2hJWZlscgW/SSKC9Pn4HBFRejCEvbClAPzbbbdbiq7M+YEvPFwDzZO76iQbHNBYYah56A7uX3xXwYt6l3p2Vms2HeQ/TbpVxtCERM3TU33nlWdfKVdOcU=,iv:HPw4ROPsoMHi8soZokA7SKLLhBqAeplsxjeiwF4/Tvs=,tag:lOJi50HYLP2J+wH2SFOySQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3