{ description = "Stationette nix config"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; disko.url = "github:nix-community/disko/latest"; impermanence.url = "github:nix-community/impermanence"; home-manager = { url = "github:nix-community/home-manager/release-25.11"; inputs.nixpkgs.follows = "nixpkgs"; }; firefox-addons = { url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons"; inputs.nixpkgs.follows = "nixpkgs"; }; try-cli = { url = "github:tobi/try-cli"; inputs.nixpkgs.follows = "nixpkgs"; }; elephant = { url = "github:abenz1267/elephant"; inputs.nixpkgs.follows = "nixpkgs"; }; walker = { url = "github:abenz1267/walker"; inputs.elephant.follows = "elephant"; inputs.nixpkgs.follows = "nixpkgs"; }; voxtype = { url = "github:peteonrails/voxtype"; inputs.nixpkgs.follows = "nixpkgs"; }; hyprland-preview-share-picker = { url = "github:WhySoBad/hyprland-preview-share-picker"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { self, nixpkgs, nixpkgs-unstable, impermanence, disko, home-manager, try-cli, voxtype, hyprland-preview-share-picker, ... } @ inputs: let lib = nixpkgs.lib; system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; pkgs-unstable = nixpkgs-unstable.legacyPackages.${system}; in { nixosConfigurations = { stationette = nixpkgs.lib.nixosSystem { modules = [ ./hardware-configuration.nix disko.nixosModules.disko impermanence.nixosModules.impermanence home-manager.nixosModules.home-manager { # nix --extra-experimental-features "nix-command flakes" run github:nix-community/disko/latest#disko-install -- --flake ./#stationette --disk stationette --write-efi-boot-entries /dev/sda disko.devices = { disk = { stationette = { type = "disk"; device = "/dev/sda"; # Check this with lsblk content = { type = "gpt"; partitions = { ESP = { size = "512M"; type = "EF00"; content = { type = "filesystem"; format = "vfat"; mountpoint = "/boot"; mountOptions = [ "fmask=0022" "dmask=0022" "umask=0077" ]; }; }; root = { size = "100%"; content = { type = "btrfs"; extraArgs = [ "-f" ]; # Force overwrite subvolumes = { "/root" = { mountpoint = "/"; mountOptions = [ "compress=zstd" "noatime" ]; }; "/nix" = { mountpoint = "/nix"; mountOptions = [ "compress=zstd" "noatime" ]; }; "/persist" = { mountpoint = "/persist"; mountOptions = [ "compress=zstd" "noatime" ]; }; "/swap" = { mountpoint = "/.swapvol"; swap.swapfile.size = "8G"; }; }; }; }; }; }; }; }; }; boot = { loader = { limine = { enable = true; extraConfig = '' timeout: 3 default_entry: 2 interface_branding: Station Bootloader interface_branding_color: 2 hash_mismatch_panic: no term_background: 1a1b26 backdrop: 1a1b26 # Tokyo Night palette term_palette: 15161e;f7768e;9ece6a;e0af68;7aa2f7;bb9af7;7dcfff;a9b1d6 term_palette_bright: 414868;f7768e;9ece6a;e0af68;7aa2f7;bb9af7;7dcfff;c0caf5 term_foreground: c0caf5 term_foreground_bright: c0caf5 term_background_bright: 24283b ''; }; efi.canTouchEfiVariables = true; # timeout = 0; }; plymouth = { enable = true; theme = "black_hud"; themePackages = with pkgs; [ (adi1090x-plymouth-themes.override { selected_themes = [ "black_hud" ]; }) ]; }; initrd.verbose = false; # Found by running sudo btrfs inspect-internal map-swapfile -r /.swapvol/swapfile kernelParams = [ "resume_offset=533760" "quiet" "udev.log_level=3" "systemd.show_status=auto" "splash" ]; bootspec.enable = true; resumeDevice = "/dev/disk/by-partlabel/disk-stationette-root"; }; swapDevices = [ { device = "/.swapvol/swapfile"; } ]; powerManagement.enable = true; systemd = { packages = with pkgs; [ uwsm ]; settings = { Manager = { DefaultTimeoutStopSec = "5s"; }; }; }; environment = { pathsToLink = [ "/share/uwsm" ]; persistence."/persist" = { hideMounts = true; directories = [ "/var/log" "/var/lib/bluetooth" "/var/lib/networkmanager" "/var/lib/nixos" "/etc/ssh" "/var/lib/systemd/coredump" "/etc/NetworkManager/system-connections" ]; files = [ "/etc/machine-id" ]; }; systemPackages = with pkgs; [ hyprland-preview-share-picker.packages.${system}.default makima pywal16 uwsm v4l-utils brightnessctl satty hyprpaper libnotify mako qt6.qtwayland grim gnome-calculator hypridle hyprlock hyprpicker wlogout wl-clipboard waybar bat highlight btop eza fzf neovim ripgrep tldr unzip openssl wget zip zoxide jq git lazygit less tree tmux tmuxinator wget zenity gum pkgs-unstable.yazi rsync p7zip impala xdg-terminal-exec rustc cargo gcc rustfmt clippy ]; }; networking = { hostName = "stationette"; networkmanager.enable = true; wireless = { iwd.enable = true; networks = { ssid = "Outskirt Stable"; psk = "SidonPhlegm"; }; }; firewall = { enable = true; # Ports used by Local Send allowedTCPPorts = [ 53317 ]; allowedUDPPorts = [ 53317 ]; }; }; users.users.chris = { uid = 1000; isNormalUser = true; initialPassword = "changeme123"; shell = pkgs.zsh; extraGroups = [ "chris" "wheel" "networkmanager" ]; }; nixpkgs.config.allowUnfree = true; programs = { localsend = { enable = true; openFirewall = true; }; zsh = { enable = true; }; hyprland = { enable = true; package = pkgs-unstable.hyprland; xwayland.enable = true; withUWSM = true; }; steam = { enable = true; remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server localNetworkGameTransfers.openFirewall = true; # Open ports in the firewall for Steam Local Network Game Transfers }; }; services = { openssh.enable = true; dbus.enable = true; envfs.enable = true; # This ensures normal shebangs work (#!/bin/bash) expressvpn.enable = true; locate.enable = true; fwupd.enable = true; "power-profiles-daemon".enable = true; upower = { enable = true; percentageLow = 20; percentageCritical = 5; percentageAction = 3; criticalPowerAction = "Hibernate"; }; displayManager = { sddm = { enable = true; wayland.enable = true; theme = "maya"; }; autoLogin.enable = true; autoLogin.user = "chris"; defaultSession = "hyprland-uwsm"; }; }; system.stateVersion = "25.11"; home-manager = { users.chris = { pkgs, lib, ... }: { home = { file.".mozilla/firefox/default/search.json.mozlz4".force = lib.mkForce true; username = "chris"; homeDirectory = "/home/chris"; enableNixpkgsReleaseCheck = false; stateVersion = "25.11"; persistence."/persist" = { directories = [ "Downloads" "Tower" "Code" ".steam" ".config/dotfiles" ".mozilla/firefox" ".config/nvim" ".config/yazi/plugins" ".config/nixos" ".config/sinew.in" ".local/share/direnv" ".local/share/nvim" ".local/share/voxtype" ".local/share/zoxide" ".local/share/Enpass" ".local/share/Steam" ".local/share/station" ".local/state/station" ".ssh" ]; files = [ ".config/shell/.env" ]; }; activation = { setupDotfiles = lib.hm.dag.entryAfter ["writeBoundary"] '' if [[ -v DRY_RUN ]]; then echo "Dry run: Would bootstrap dotfiles from labs.scarif.space" exit fi TEMP_DIR=$(mktemp -d) DOTFILES_DIR="$HOME/.config/dotfiles" DOTFILES_GIT_DIR="$DOTFILES_DIR/.git" if [ ! -d "$DOTFILES_GIT_DIR" ]; then echo "No local repository so cloning from remote" SOURCE="https://labs.scarif.space/chris/dotfiles.git" ${pkgs.git}/bin/git clone -b main "$SOURCE" "$TEMP_DIR" mv "$TEMP_DIR/.git" "$DOTFILES_GIT_DIR" else echo "Local repository found so cloning from there" ${pkgs.git}/bin/git clone -b main "$DOTFILES_GIT_DIR" "$TEMP_DIR" ${pkgs.git}/bin/git --git-dir="$DOTFILES_GIT_DIR" --work-tree="$TEMP_DIR" pull --rebase || true fi echo "Copying dot files to home" ${pkgs.coreutils}/bin/cp -rfT "$TEMP_DIR" "$HOME" NVIM_DIR="$HOME/.config/nvim" echo "Neovim config not initialised so initialising from remote" ${pkgs.git}/bin/git --git-dir="$DOTFILES_GIT_DIR" --work-tree="$HOME" submodule set-url ".config/nvim" https://labs.scarif.space/chris/nvim.git ${pkgs.git}/bin/git --git-dir="$DOTFILES_GIT_DIR" --work-tree="$HOME" submodule update --init || true ${pkgs.git}/bin/git --git-dir="$DOTFILES_GIT_DIR" --work-tree="$HOME" submodule set-url ".config/nvim" git@labs.scarif.space:chris/nvim.git cd "$HOME" echo "Cleanup" ${pkgs.coreutils}/bin/rm -rf "$TEMP_DIR" ${pkgs.coreutils}/bin/rm -rf "$HOME/.git" || true echo "Dotfiles bootstrapped successfully." ''; setupDevDirectories = lib.hm.dag.entryAfter ["writeBoundary"] '' if [[ -v DRY_RUN ]]; then echo "Dry run: Would create dev directories" exit fi echo "Creating development directories" for dir in "DevOps" "FSharp" "JavaScript" "Scala" "Rust" "PHP" "Tutorials" "Sites" "MobileApps" "Tries"; do if [ ! -d "$HOME/Code/$dir" ]; then mkdir -p "$HOME/Code/$dir" fi done ''; }; packages = with pkgs; [ # jetbrains.rider # android-studio # beekeeper-studio # brave # go # lua lunar-client chromium direnv wiremix xournalpp bluetui spotify nodePackages.pnpm try-cli.packages.${system}.default # (python3.withPackages (python-pkgs: [ python-pkgs.pip python-pkgs.requests ])) # zig obsidian mailspring # thunderbird # libreoffice-qt # hunspell # blueberry # pkgs-unstable.hyprshot # catppuccin-cursors.macchiatoBlue # catppuccin-gtk # papirus-folders # pkgs-unstable.php84Packages.composer # pkgs-unstable.php84Packages.xdebug # pkgs-unstable.php84Extensions.sqlite3 # pkgs-unstable.php84Extensions.redis # pkgs-unstable.php84Extensions.sodium # pkgs-unstable.php84Extensions.pgsql # pkgs-unstable.php84Extensions.iconv # pkgs-unstable.php84Extensions.gd # pkgs-unstable.php84Extensions.zip # php antigravity gimp # kdePackages.dolphin nautilus enpass enpass-cli expressvpn ffmpeg ffmpegthumbnailer gpu-screen-recorder inkscape krita libreoffice-fresh nextcloud-client nodejs_24 signal-desktop sxiv tenacity zathura ghostty yarn uwsm wally-cli kdePackages.wacomtablet # kdePackages.print-manager mpv vlc imv # telegram-desktop ]; }; xdg.mimeApps = { enable = true; defaultApplications = { # Directories "inode/directory" = [ "org.gnome.Nautilus.desktop" ]; # Images "image/png" = [ "imv.desktop" ]; "image/jpeg" = [ "imv.desktop" ]; "image/gif" = [ "imv.desktop" ]; "image/webp" = [ "imv.desktop" ]; "image/bmp" = [ "imv.desktop" ]; "image/tiff" = [ "imv.desktop" ]; # Documents "application/pdf" = [ "zathura.desktop" ]; # Web and Browser "x-scheme-handler/http" = [ "firefox.desktop" ]; "x-scheme-handler/https" = [ "firefox.desktop" ]; "text/html" = [ "firefox.desktop" ]; # Video "video/mp4" = [ "mpv.desktop" ]; "video/x-msvideo" = [ "mpv.desktop" ]; "video/x-matroska" = [ "mpv.desktop" ]; "video/x-flv" = [ "mpv.desktop" ]; "video/x-ms-wmv" = [ "mpv.desktop" ]; "video/mpeg" = [ "mpv.desktop" ]; "video/ogg" = [ "mpv.desktop" ]; "video/webm" = [ "mpv.desktop" ]; "video/quicktime" = [ "mpv.desktop" ]; "video/3gpp" = [ "mpv.desktop" ]; "video/3gpp2" = [ "mpv.desktop" ]; "video/x-ms-asf" = [ "mpv.desktop" ]; "video/x-ogm+ogg" = [ "mpv.desktop" ]; "video/x-theora+ogg" = [ "mpv.desktop" ]; "application/ogg" = [ "mpv.desktop" ]; # Mail "x-scheme-handler/mailto" = [ "mailspring.desktop" ]; # Text and Code "text/plain" = [ "nvim.desktop" ]; "text/english" = [ "nvim.desktop" ]; "text/x-makefile" = [ "nvim.desktop" ]; "text/x-c++hdr" = [ "nvim.desktop" ]; "text/x-c++src" = [ "nvim.desktop" ]; "text/x-chdr" = [ "nvim.desktop" ]; "text/x-csrc" = [ "nvim.desktop" ]; "text/x-java" = [ "nvim.desktop" ]; "text/x-moc" = [ "nvim.desktop" ]; "text/x-pascal" = [ "nvim.desktop" ]; "text/x-tcl" = [ "nvim.desktop" ]; "text/x-tex" = [ "nvim.desktop" ]; "application/x-shellscript" = [ "nvim.desktop" ]; "text/x-c" = [ "nvim.desktop" ]; "text/x-c++" = [ "nvim.desktop" ]; "application/xml" = [ "nvim.desktop" ]; "text/xml" = [ "nvim.desktop" ]; }; }; imports = [ inputs.walker.homeManagerModules.default inputs.voxtype.homeManagerModules.default ]; services = { swayosd.enable = true; }; systemd.user = { enable = true; timers = { "station-battery-monitor" = { wantedBy = [ "timers.target" ]; timerConfig = { OnBootSec = "1min"; OnUnitActiveSec = "30sec"; Unit = "station-battery-monitor.service"; }; }; }; services = { "station-battery-monitor" = { after = "graphical-session.target"; serviceConfig = { Type = "oneshot"; ExecStart = "%h/.local/share/omarchy/bin/omarchy-battery-monitor"; Environment = "DISPLAY=:0"; LogLevelMax = "warning"; }; }; }; }; programs = let lock-false = { Value = false; Status = "locked"; }; lock-true = { Value = true; Status = "locked"; }; in { walker = { enable = true; config = {}; runAsService = true; }; elephant = { enable = true; }; voxtype = { enable = true; package = voxtype.packages.${system}.vulkan; model.name = "base.en"; service.enable = true; }; firefox = { enable = true; package = pkgs.wrapFirefox pkgs.firefox-unwrapped { extraPolicies = { DisableTelemetry = true; DisableFirefoxStudies = true; EnableTrackingProtection = { Value= true; Locked = true; Cryptomining = true; Fingerprinting = true; }; DisablePocket = true; DisableFirefoxAccounts = false; DisableAccounts = false; DisableFirefoxScreenshots = true; OverrideFirstRunPage = ""; OverridePostUpdatePage = ""; DontCheckDefaultBrowser = true; DisplayBookmarksToolbar = "always"; # alternatives: "always" or "newtab" DisplayMenuBar = "default-off"; # alternatives: "always", "never" or "default-on" SearchBar = "unified"; # alternative: "separate" /* ---- EXTENSIONS ---- */ ExtensionSettings = { "*".installation_mode = "allowed"; # blocks all addons except the ones specified below # Enpass "firefox-enpass@enpass.io" = { install_url = "https://dl.enpass.io/stable/extensions/firefox/versions/v6.11.10.2/enpass_password_manager-6.11.10.2.xpi"; installation_mode = "force_installed"; }; }; /* ---- PREFERENCES ---- */ # Set preferences shared by all profiles. Preferences = { "browser.contentblocking.category" = { Value = "strict"; Status = "locked"; }; "extensions.pocket.enabled" = lock-false; "extensions.screenshots.disabled" = lock-true; "browser.topsites.contile.enabled" = lock-false; "browser.formfill.enable" = lock-false; "browser.search.suggest.enabled" = lock-false; "browser.search.suggest.enabled.private" = lock-false; "browser.urlbar.suggest.searches" = lock-false; "browser.urlbar.showSearchSuggestionsFirst" = lock-false; "browser.newtabpage.activity-stream.feeds.section.topstories" = lock-false; "browser.newtabpage.activity-stream.feeds.snippets" = lock-false; "browser.newtabpage.activity-stream.section.highlights.includePocket" = lock-false; "browser.newtabpage.activity-stream.section.highlights.includeBookmarks" = lock-false; "browser.newtabpage.activity-stream.section.highlights.includeDownloads" = lock-false; "browser.newtabpage.activity-stream.section.highlights.includeVisited" = lock-false; "browser.newtabpage.activity-stream.showSponsored" = lock-false; "browser.newtabpage.activity-stream.system.showSponsored" = lock-false; "browser.newtabpage.activity-stream.showSponsoredTopSites" = lock-false; "browser.newtabpage.activity-stream.feeds.section.highlights" = false; }; }; }; profiles = { default = { id = 0; name = "default"; isDefault = true; search = { default = "holocron"; order = [ "holocron" "google" ]; engines= { holocron = { name = "Holocron"; urls = [{ template = "https://holocron.scarif.space/search"; params = [ { name = "q"; value = "{searchTerms}"; } ]; }]; icon = "https://holocron.scarif.space/favicon.ico"; definedAliases = [ "@h" ]; }; bing.metaData.hidden = true; ebay.metaData.hidden = true; perplexity.metaData.hidden = true; }; }; }; }; }; }; nixpkgs = { config = { allowUnfree = true; allowUnfreePredicate = (_: true); permittedInsecurePackages = [ "electron-25.9.0" # Obsidian "beekeeper-studio-5.3.4" ]; }; }; }; extraSpecialArgs = { inherit inputs; }; }; system = { autoUpgrade = { enable = true; allowReboot = false; runGarbageCollection = true; date = "daily"; }; }; fonts = { packages = with pkgs; [ nerd-fonts.jetbrains-mono nerd-fonts.fira-code ]; }; } ]; }; }; # Standalone home-manager configuration entrypoint #homeConfigurations = { # chris = home-manager.lib.homeManagerConfiguration { # inherit pkgs; # extraSpecialArgs = { # inherit inputs; # }; # modules = [ # ./home # ]; # }; #}; nix.settings = { extra-substituters = [ "https://walker.cachix.org" "https://walker-git.cachix.org" ]; extra-trusted-public-keys = [ "walker.cachix.org-1:fG8q+uAaMqhsMxWjwvk0IMb4mFPFLqHjuvfwQxE4oJM=" "walker-git.cachix.org-1:vmC0ocfPWh0S/vRAQGtChuiZBTAe4wiKDeyyXM0/7pM=" ]; }; }; }