{ config, pkgs, ... }: let greetdApodDir = "/var/lib/greetd/apod"; greetdApodCurrent = "${greetdApodDir}/current"; swaySession = pkgs.writeTextDir "share/wayland-sessions/sway.desktop" '' [Desktop Entry] Name=Sway Comment=An i3-compatible Wayland compositor Exec=${config.programs.sway.package}/bin/sway Type=Application DesktopNames=sway ''; regreetPasswordPrompt = pkgs.regreet.overrideAttrs (oldAttrs: { postPatch = (oldAttrs.postPatch or "") + '' substituteInPlace src/gui/model.rs \ --replace-fail $' } else {\n let username = if let Some(username) = self.get_current_username() {' \ $' } else if self.sys_util.get_sessions().len() == 1 {\n let (session, sess_info) = self.sys_util.get_sessions().iter().next().expect("one session");\n info!("No session selected; using only available session: {session}");\n (Some(session.to_string()), Some(sess_info.clone()))\n } else {\n let username = if let Some(username) = self.get_current_username() {' substituteInPlace src/gui/component.rs \ --replace-fail $' // Set the default behaviour of pressing the Return key to act like the login button.\n root.set_default_widget(Some(&widgets.ui.login_button));\n\n AsyncComponentParts { model, widgets }' \ $' // Set the default behaviour of pressing the Return key to act like the login button.\n root.set_default_widget(Some(&widgets.ui.login_button));\n\n // Immediately start authentication so the password entry appears and receives focus.\n sender.input(Self::Input::Login {\n input: String::new(),\n info: UserSessInfo::extract(\n &widgets.ui.usernames_box,\n &widgets.ui.username_entry,\n &widgets.ui.sessions_box,\n &widgets.ui.session_entry,\n ),\n });\n\n AsyncComponentParts { model, widgets }' ''; }); regreetState = pkgs.writeText "regreet-state.toml" '' last_user = "jet" [user_to_last_sess] jet = "Sway" ''; fetchGreetdApod = pkgs.writeShellApplication { name = "greetd-apod-wallpaper"; runtimeInputs = [ pkgs.coreutils pkgs.curl pkgs.jq ]; text = '' set -euo pipefail state_dir="${greetdApodDir}" current_link="${greetdApodCurrent}" user_current="/home/jet/.local/state/nasa-apod/current" mkdir -p "$state_dir" chmod 0755 "$state_dir" install_current() { local source="$1" local target="$2" if [ -s "$source" ]; then cp --dereference --force "$source" "$target" chmod 0644 "$target" ln -sfn "$target" "$current_link" fi } if [ ! -e "$current_link" ] && [ -e "$user_current" ]; then install_current "$user_current" "$state_dir/bootstrap" fi read_api_key_file() { local key_file="$1" if [ -r "$key_file" ]; then while IFS= read -r line; do case "$line" in NASA_API_KEY=*) api_key="''${line#NASA_API_KEY=}" ;; esac done < "$key_file" fi } api_key="''${NASA_API_KEY:-}" if [ -z "$api_key" ]; then read_api_key_file "''${NASA_API_KEY_FILE:-/home/jet/.config/nasa-api.env}" fi if [ -z "$api_key" ]; then read_api_key_file /etc/nasa-api.env fi if [ -z "$api_key" ]; then exit 0 fi today="$(date +%F)" for cached in "$state_dir/apod-$today".*; do if [ -s "$cached" ]; then ln -sfn "$cached" "$current_link" exit 0 fi done api_curl_args=( --fail --silent --show-error --location --connect-timeout 5 --max-time 20 ) image_curl_args=( --fail --silent --show-error --location --retry 2 --retry-delay 5 --retry-max-time 120 --connect-timeout 10 --max-time 60 ) api_request="$(mktemp)" trap 'rm -f "$api_request"' EXIT { printf '%s\n' 'url = "https://api.nasa.gov/planetary/apod"' printf '%s\n' 'get' printf 'data-urlencode = "api_key=%s"\n' "$api_key" printf '%s\n' 'data-urlencode = "thumbs=True"' } > "$api_request" chmod 0600 "$api_request" json="$(curl "''${api_curl_args[@]}" --config "$api_request" || true)" if [ -z "$json" ]; then exit 0 fi media_type="$(printf '%s' "$json" | jq -r '.media_type // empty')" case "$media_type" in image) image_url="$(printf '%s' "$json" | jq -r '.hdurl // .url // empty')" ;; video) image_url="$(printf '%s' "$json" | jq -r '.thumbnail_url // empty')" ;; *) exit 0 ;; esac if [ -z "$image_url" ]; then exit 0 fi ext="''${image_url##*.}" ext="''${ext%%\?*}" case "$ext" in jpg|jpeg|png|webp) ;; *) ext="jpg" ;; esac date_stamp="$(printf '%s' "$json" | jq -r '.date // empty')" if [ -z "$date_stamp" ]; then date_stamp="$(date +%F)" fi target="$state_dir/apod-$date_stamp.$ext" tmp="$target.tmp" if [ ! -s "$target" ]; then if curl "''${image_curl_args[@]}" "$image_url" -o "$tmp" && [ -s "$tmp" ]; then mv "$tmp" "$target" chmod 0644 "$target" else rm -f "$tmp" fi fi if [ -e "$target" ]; then ln -sfn "$target" "$current_link" fi ''; }; in { boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.configurationLimit = 3; boot.loader.efi.canTouchEfiVariables = true; boot.loader.timeout = 1; boot.loader.systemd-boot.consoleMode = "max"; boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; # Ensure current wireless firmware is available. hardware.enableRedistributableFirmware = true; hardware.bluetooth = { enable = true; powerOnBoot = true; settings = { General = { Experimental = true; # Show battery charge of Bluetooth devices }; }; }; services.blueman.enable = true; networking.networkmanager.enable = true; networking.networkmanager.settings = { connection = { "wifi.powersave" = 2; }; device = { "wifi.scan-rand-mac-address" = false; }; }; services.resolved.enable = true; networking.firewall.enable = true; # Required for Tailscale networking.firewall.checkReversePath = "loose"; networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 4096 ]; services.tailscale = { enable = true; }; systemd.services.tailscale-set-operator = { description = "Set Tailscale operator user"; after = [ "tailscaled.service" ]; requires = [ "tailscaled.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig.Type = "oneshot"; path = [ pkgs.tailscale ]; script = '' tailscale set --operator=jet ''; }; systemd.services.opencode-tailnet = { description = "Expose OpenCode on the tailnet"; after = [ "network-online.target" "tailscaled.service" "tailscale-set-operator.service" ]; wants = [ "network-online.target" ]; requires = [ "tailscaled.service" "tailscale-set-operator.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; User = "jet"; Restart = "always"; RestartSec = 5; ExecStartPre = [ "${pkgs.tailscale}/bin/tailscale serve --bg 4096" ]; ExecStart = "/etc/profiles/per-user/jet/bin/opencode serve --hostname 127.0.0.1 --port 4096"; WorkingDirectory = config.users.users.jet.home; }; }; time.timeZone = "America/Los_Angeles"; i18n.defaultLocale = "en_US.UTF-8"; # Framework Laptop 13 AMD AI 300 Series specific configurations # Enable AMD GPU support and power management hardware.graphics = { enable = true; enable32Bit = true; }; # Enable keyd for key remapping services.keyd = { enable = true; keyboards = { default = { ids = [ "*" ]; # Apply to all keyboards settings = { main = { capslock = "esc"; esc = "capslock"; leftalt = "leftcontrol"; leftcontrol = "leftalt"; mute = "mute"; # ← Key 1: mute volumedown = "playpause"; # ← Key 2: play/pause volumeup = "volumedown"; # ← Key 3: vol down previoussong = "volumeup"; # ← Key 4: vol up playpause = "command(touch /tmp/keyd-f5-test)"; # ← Key 5: lock screen (testing) nextsong = "noop"; # ← Key 6: disabled brightnessdown = "noop"; # ← Key 7: disabled brightnessup = "noop"; # ← Key 8: disabled # Key 9: display toggle (leftmeta+p) - disabled below rfkill = "brightnessdown"; # ← Key 10: brightness down sysrq = "brightnessup"; # ← Key 11: brightness up media = "sysrq"; # ← Key 12: screenshot }; }; }; frameworkRadio = { ids = [ "32ac:0006" ]; settings = { main = { brightnessdown = "noop"; # ← Key 7: disabled brightnessup = "noop"; # ← Key 8: disabled rfkill = "brightnessdown"; # ← Key 10: brightness down }; }; }; }; }; # Prevent trackpad interference with keyd environment.etc."libinput/local-overrides.quirks".text = '' [Serial Keyboards] MatchUdevType=keyboard MatchName=keyd virtual keyboard AttrKeyboardIntegration=internal ''; # Codex currently probes the conventional FHS bubblewrap path. systemd.tmpfiles.rules = [ "L+ /usr/bin/bwrap - - - - ${pkgs.bubblewrap}/bin/bwrap" "d ${greetdApodDir} 0755 root root -" ]; # Set Ghostty as default terminal xdg.terminal-exec = { enable = true; settings = { default = [ "com.mitchellh.ghostty.desktop" ]; }; }; services.flatpak.enable = true; virtualisation.docker.enable = true; programs.sway = { enable = true; wrapperFeatures.gtk = true; }; services.greetd = { enable = true; settings.default_session = { command = "env GTK_USE_PORTAL=0 GDK_DEBUG=no-portals SESSION_DIRS=/run/current-system/sw/share/wayland-sessions XDG_DATA_DIRS=/run/current-system/sw/share ${pkgs.dbus}/bin/dbus-run-session ${pkgs.cage}/bin/cage -s -d -- ${config.programs.regreet.package}/bin/regreet"; user = "greeter"; }; }; programs.regreet = { enable = true; package = regreetPasswordPrompt; font = { package = pkgs.atkinson-hyperlegible-next; name = "Atkinson Hyperlegible Next"; size = 16; }; settings = { background = { path = greetdApodCurrent; fit = "Cover"; }; GTK.application_prefer_dark_theme = true; appearance.greeting_msg = "Welcome back"; widget.clock = { format = "%a %b %d %I:%M %p"; resolution = "1s"; }; }; }; services.accounts-daemon.enable = true; age = { identityPaths = [ "/home/jet/.ssh/id_ed25519" ]; secrets.nasa-api-env = { file = ./secrets/nasa-api.env.age; owner = "jet"; group = "users"; mode = "0400"; }; }; system.activationScripts.regreetDefaultSession.text = '' ${pkgs.coreutils}/bin/install -D -m 0644 ${regreetState} /var/lib/regreet/state.toml chown greeter:greeter /var/lib/regreet/state.toml ''; fonts = { packages = [ pkgs.atkinson-hyperlegible-next pkgs.nerd-fonts.commit-mono ]; fontconfig.defaultFonts = { sansSerif = [ "Atkinson Hyperlegible Next" ]; serif = [ "Atkinson Hyperlegible Next" ]; monospace = [ "CommitMono Nerd Font" ]; }; }; systemd.services.greetd-apod-wallpaper = { description = "Fetch NASA APOD wallpaper for greetd"; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; restartIfChanged = false; serviceConfig = { Type = "oneshot"; ExecStart = "${fetchGreetdApod}/bin/greetd-apod-wallpaper"; EnvironmentFile = "-${config.age.secrets.nasa-api-env.path}"; TimeoutStartSec = "3min"; }; }; systemd.timers.greetd-apod-wallpaper = { wantedBy = [ "timers.target" ]; timerConfig = { OnActiveSec = "2m"; OnUnitActiveSec = "1h"; Persistent = false; Unit = "greetd-apod-wallpaper.service"; }; }; xdg.portal = { enable = true; wlr.enable = true; config.common.default = [ "wlr" "gtk" ]; extraPortals = with pkgs; [ xdg-desktop-portal-gtk ]; }; programs.dconf.enable = true; services.gvfs.enable = true; services.udisks2.enable = true; security.polkit.enable = true; security.pam.services.swaylock = { }; services.printing.enable = true; services.pulseaudio.enable = false; security.rtkit.enable = true; services.pipewire = { enable = true; alsa.enable = true; alsa.support32Bit = true; pulse.enable = true; }; users.users.jet = { isNormalUser = true; description = "Jet"; extraGroups = [ "networkmanager" "wheel" "video" "render" "docker" ]; }; nixpkgs.config.allowUnfree = true; nix.settings = { experimental-features = [ "nix-command" "flakes" ]; trusted-users = [ "root" "jet" ]; max-jobs = "auto"; cores = 0; build-users-group = "nixbld"; }; nix.gc = { automatic = true; dates = "daily"; options = "--delete-older-than 7d"; }; nix.optimise.automatic = true; # Framework-specific services # Enable fwupd for BIOS updates (distributed through LVFS) services.fwupd.enable = true; # Enable periodic TRIM for NVMe/SSD health services.fstrim.enable = true; services.irqbalance.enable = true; services.earlyoom.enable = true; # Power management for laptop services.logind = { settings = { Login = { HandleLidSwitch = "suspend"; HandleLidSwitchExternalPower = "suspend"; HandleLidSwitchDocked = "ignore"; HandlePowerKey = "suspend"; }; }; }; # Enable auto-cpufreq for intelligent power management (replaces TLP) services.auto-cpufreq.enable = true; services.auto-cpufreq.settings = { battery = { governor = "powersave"; turbo = "never"; }; charger = { governor = "performance"; turbo = "auto"; }; }; # Disable power-profiles-daemon (conflicts with auto-cpufreq) services.power-profiles-daemon.enable = false; # Enable power management (governor managed dynamically by auto-cpufreq) powerManagement.enable = true; # v4l2loopback for OBS Virtual Camera boot.extraModulePackages = with config.boot.kernelPackages; [ v4l2loopback ]; boot.kernelModules = [ "v4l2loopback" ]; boot.extraModprobeConfig = '' options cfg80211 ieee80211_regdom=US options v4l2loopback devices=1 video_nr=1 card_label="OBS Virtual Camera" exclusive_caps=1 ''; # RAM optimizations for 96GB system boot.kernel.sysctl = { "vm.vfs_cache_pressure" = 50; # Keep more filesystem cache in RAM "vm.dirty_ratio" = 15; # Write to disk when 15% of RAM is dirty "vm.dirty_background_ratio" = 5; # Start writing when 5% dirty "kernel.nmi_watchdog" = 0; "net.core.default_qdisc" = "fq"; "net.ipv4.tcp_congestion_control" = "bbr"; }; environment.systemPackages = with pkgs; [ bubblewrap docker docker-compose flatpak swaySession wget nh ]; environment.pathsToLink = [ "/share/wayland-sessions" ]; programs.steam.enable = true; programs.nix-index-database.comma.enable = true; # https://wiki.nixos.org/wiki/Appimage programs.appimage = { enable = true; binfmt = true; }; # GameCube adapter udev rules for Slippi/Dolphin # Disable USB autosuspend for Framework's problematic devices (fingerprint reader, USB-C hub) services.udev.extraRules = '' # GameCube adapter USB device (vendor ID 057e, product ID 0337) SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", MODE="0666" # GameCube adapter HID device (needed for Dolphin to access controllers) KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", MODE="0666", GROUP="input" # Disable autosuspend for Framework fingerprint reader ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="27a6", ATTR{power/autosuspend}="-1" # Disable autosuspend for Framework USB-C hub controllers ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="32ac", ATTR{power/autosuspend}="-1" ''; system.stateVersion = "25.05"; }