commit 17c5379a9ac2a67b7634024f7625169aa62fa3ce Author: Phillip Michelsen Date: Sun Feb 1 00:42:40 2026 +0800 Initial commit diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..cdd44dd --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "home-manager": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1768912518, + "narHash": "sha256-FJlof1jnbLIT5RbKxef/NV6RzcOj1GoMzXE4FcBFg5Y=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "9c5f8aceb6ef620e881f50fe65cb4a2c6b1e8527", + "type": "github" + }, + "original": { + "id": "home-manager", + "type": "indirect" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1768564909, + "narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1768564909, + "narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "home-manager": "home-manager", + "nixpkgs": "nixpkgs_2" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..504a958 --- /dev/null +++ b/flake.nix @@ -0,0 +1,48 @@ +{ + description = "Phillip NixOS config"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = { self, nixpkgs, home-manager, ... }: + let + myModules = { + desktop = { + sway = ./modules/desktop/sway.nix; + greetd = ./modules/desktop/greetd.nix; + }; + + audio = { + pipewire = ./modules/audio/pipewire.nix; + }; + + network = { + networkmanager = ./modules/network/networkmanager.nix; + firewall = ./modules/network/firewall.nix; + }; + + misc = { + fonts = ./modules/misc/fonts.nix; + }; + }; + + mkHost = { system, name }: + nixpkgs.lib.nixosSystem { + inherit system; + + specialArgs = { inherit myModules; }; + + modules = [ + ./hosts/${name}/hardware-configuration.nix + ./hosts/${name}/configuration.nix + ]; + }; + in + { + nixosConfigurations = { + desktop-main = mkHost { system = "x86_64-linux"; name = "desktop-main"; }; + # add more hosts here later + }; + }; +} diff --git a/hosts/desktop-main/configuration.nix b/hosts/desktop-main/configuration.nix new file mode 100644 index 0000000..d8f8cca --- /dev/null +++ b/hosts/desktop-main/configuration.nix @@ -0,0 +1,122 @@ +{ myModules, inputs, pkgs, ... }: +{ + imports = [ + myModules.desktop.sway + myModules.desktop.greetd + + myModules.audio.pipewire + + myModules.network.networkmanager + myModules.network.firewall + + myModules.misc.fonts + ]; + + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + nixpkgs.config.allowUnfree = true; + + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + networking.hostName = "desktop-main"; + + time.timeZone = "Asia/Hong_Kong"; + i18n.defaultLocale = "en_US.UTF-8"; + console.keyMap = "us"; + + # Users (host-owned, per your decision) + users.users.phill = { + isNormalUser = true; + extraGroups = [ "wheel" "networkmanager" "video" "input" "audio" ]; + shell = pkgs.fish; + }; + security.sudo.wheelNeedsPassword = true; + programs.fish.enable = true; + + my.desktop.sway = { + utilities = "full"; # minimal|essentials|full + x11Compatibility = true; + }; + + my.desktop.greetd = { + user = "phill"; + command = "${pkgs.sway}/bin/sway"; + }; + + my.audio.pipewire = { + support32Bit = true; + tools = "full"; # none|basic|full + }; + + my.network.networkmanager = { + wifiPowersave = false; + useResolved = true; + }; + + my.network.firewall = { + allowPing = true; + allowedTCPPorts = [ ]; + trustedInterfaces = [ ]; + }; + + my.misc.fonts.extra = with pkgs; [ + nerd-fonts.fira-code + nerd-fonts.hack + ]; + + programs.steam.enable = true; + programs.gamemode.enable = true; + + programs.thunar.enable = true; + services.tumbler.enable = true; + + programs.neovim = { + enable = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + }; + + environment.systemPackages = with pkgs; [ + git + lazygit + go + firefox + foot + prismlauncher + discord + spotify + wireguard-tools + lua-language-server + vlc + gnumake + fd + ripgrep + bat + delta + fzf + tree-sitter + gcc + clang + zathura + texliveFull + tinymist + gopls + opencode + lsof + tmux + nodejs + localsend + luajitPackages.tiktoken_core + unzip + protonvpn-gui + cht-sh + zoxide + starship + filezilla + typst + ]; + + # Must match the value you originally installed with (do not change casually) + system.stateVersion = "25.05"; +} diff --git a/hosts/desktop-main/hardware-configuration.nix b/hosts/desktop-main/hardware-configuration.nix new file mode 100644 index 0000000..fcb5303 --- /dev/null +++ b/hosts/desktop-main/hardware-configuration.nix @@ -0,0 +1,38 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/1252e9aa-9258-47bd-a5c7-32326bbdd797"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/3C0E-0836"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + fileSystems."/home/phill/mount/arch" = + { device = "/dev/disk/by-uuid/460d5b9f-5003-451e-9d00-64654dae177c"; + fsType = "btrfs"; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/59aa4cf4-5df1-40a2-9abd-4180ba6b069c"; } + ]; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/modules/audio/pipewire.nix b/modules/audio/pipewire.nix new file mode 100644 index 0000000..eef4c1c --- /dev/null +++ b/modules/audio/pipewire.nix @@ -0,0 +1,44 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.my.audio.pipewire; +in +{ + options.my.audio.pipewire = { + support32Bit = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Enable 32-bit ALSA support (useful for some games/apps)."; + }; + + tools = lib.mkOption { + type = lib.types.enum [ "none" "basic" "full" ]; + default = "basic"; + description = "Install common audio tools."; + }; + }; + + config = { + security.rtkit.enable = true; + + services.pipewire = { + enable = true; + wireplumber.enable = true; + + alsa = { + enable = true; + support32Bit = cfg.support32Bit; + }; + + pulse.enable = true; + jack.enable = true; + }; + + environment.systemPackages = + if cfg.tools == "none" then + [ ] + else if cfg.tools == "basic" then + with pkgs; [ pavucontrol ] + else + with pkgs; [ pavucontrol pulsemixer helvum ]; + }; +} diff --git a/modules/desktop/greetd.nix b/modules/desktop/greetd.nix new file mode 100644 index 0000000..0bff0b1 --- /dev/null +++ b/modules/desktop/greetd.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.my.desktop.greetd; +in +{ + options.my.desktop.greetd = { + user = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "User account that runs the default session."; + }; + + command = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Command to run for the default session (use an absolute path)."; + }; + }; + + config = { + assertions = [ + { + assertion = cfg.user != null; + message = "my.desktop.greetd.user must be set."; + } + { + assertion = cfg.command != null; + message = "my.desktop.greetd.command must be set (use an absolute path like \"${pkgs.sway}/bin/sway\")."; + } + ]; + + services.greetd = { + enable = true; + settings.default_session = { + user = cfg.user; + command = cfg.command; + }; + }; + }; +} diff --git a/modules/desktop/sway.nix b/modules/desktop/sway.nix new file mode 100644 index 0000000..e569728 --- /dev/null +++ b/modules/desktop/sway.nix @@ -0,0 +1,65 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.my.desktop.sway; + + utilitiesPkgs = + if cfg.utilities == "minimal" then + [ ] + else if cfg.utilities == "essentials" then + with pkgs; [ + wl-clipboard + grim + ] + else if cfg.utilities == "full" then + with pkgs; [ + wl-clipboard + grim + slurp + swaylock + swayidle + waybar + mako # notifications + wofi # launcher + brightnessctl + playerctl + pavucontrol + ] + else + [ ]; + + portalPkgs = with pkgs; [ xdg-desktop-portal-gtk ]; +in +{ + options.my.desktop.sway = { + utilities = lib.mkOption { + type = lib.types.enum [ "minimal" "essentials" "full" ]; + default = "essentials"; + description = "Utility bundle size for a Sway environment."; + }; + + x11Compatibility = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Enable XWayland support for X11-only applications."; + }; + }; + + config = lib.mkMerge [ + { + programs.sway = { + enable = true; + xwayland.enable = cfg.x11Compatibility; + }; + + services.seatd.enable = true; + + xdg.portal = { + enable = true; + wlr.enable = true; + extraPortals = portalPkgs; + }; + + environment.systemPackages = utilitiesPkgs; + } + ]; +} diff --git a/modules/misc/fonts.nix b/modules/misc/fonts.nix new file mode 100644 index 0000000..e7a3a80 --- /dev/null +++ b/modules/misc/fonts.nix @@ -0,0 +1,23 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.my.misc.fonts; +in +{ + options.my.misc.fonts = { + extra = lib.mkOption { + type = lib.types.listOf lib.types.package; + default = [ ]; + description = "Extra font packages to install in addition to the defaults."; + }; + }; + + config = { + fonts.packages = + (with pkgs; [ + dejavu_fonts + noto-fonts + noto-fonts-color-emoji + ]) + ++ cfg.extra; + }; +} diff --git a/modules/network/firewall.nix b/modules/network/firewall.nix new file mode 100644 index 0000000..90bb534 --- /dev/null +++ b/modules/network/firewall.nix @@ -0,0 +1,37 @@ +{ config, lib, ... }: +let + cfg = config.my.network.firewall; +in +{ + options.my.network.firewall = { + allowedTCPPorts = lib.mkOption { + type = lib.types.listOf lib.types.port; + default = [ ]; + }; + + allowedUDPPorts = lib.mkOption { + type = lib.types.listOf lib.types.port; + default = [ ]; + }; + + trustedInterfaces = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + allowPing = lib.mkOption { + type = lib.types.bool; + default = false; + }; + }; + + config = { + networking.firewall = { + enable = true; + allowedTCPPorts = cfg.allowedTCPPorts; + allowedUDPPorts = cfg.allowedUDPPorts; + trustedInterfaces = cfg.trustedInterfaces; + allowPing = cfg.allowPing; + }; + }; +} diff --git a/modules/network/networkmanager.nix b/modules/network/networkmanager.nix new file mode 100644 index 0000000..16e2612 --- /dev/null +++ b/modules/network/networkmanager.nix @@ -0,0 +1,27 @@ +{ config, lib, ... }: +let + cfg = config.my.network.networkmanager; +in +{ + options.my.network.networkmanager = { + wifiPowersave = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Enable Wi-Fi powersave (may reduce performance/latency)."; + }; + + useResolved = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Use systemd-resolved for DNS."; + }; + }; + + config = { + networking.networkmanager.enable = true; + + networking.networkmanager.wifi.powersave = cfg.wifiPowersave; + + services.resolved.enable = cfg.useResolved; + }; +} diff --git a/modules/users/phill.nix b/modules/users/phill.nix new file mode 100644 index 0000000..c0aa72c --- /dev/null +++ b/modules/users/phill.nix @@ -0,0 +1,9 @@ +{ ... }: +{ + users.users.phill = { + isNormalUser = true; + extraGroups = [ "wheel" "networkmanager" "video" "input" ]; + }; + + security.sudo.wheelNeedsPassword = true; +}