# Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running ‘nixos-help’). { config, lib, nixpkgs, pkgs, home-manager, ... }: let my_python = (pkgs.python3.withPackages (ps: with ps; [ git_plan ])); my_emacs = (pkgs.emacsWithPackagesFromUsePackage { config = ./emacs.el; defaultInitFile = true; package = pkgs.emacs29-pgtk.overrideAttrs (old: { withTreeSitter = true; }); alwaysEnsure = true; extraEmacsPackages = epkgs: [ pkgs.mu epkgs.treesit-grammars.with-all-grammars ]; }); in { imports = [ #./gnupg.nix ]; nix.settings.experimental-features = [ "nix-command" "flakes" ]; nix.extraOptions = '' !include ${config.sops.secrets.github_token.path} bash-prompt = (nix:$name)\040\[\033[1;32m\][\u@\h:\w]\$\[\033[0m\]\040 extra-sandbox-paths = /nix/var/cache/ccache ''; sops = { environment.SOPS_GPG_EXEC = "${pkgs.gnupg}/bin/gpg"; defaultSopsFile = ./secrets.yaml; secrets = { fastmail_password = { owner = config.users.users.knazarov.name; group = config.users.users.knazarov.group; }; github_token = { owner = config.users.users.knazarov.name; group = config.users.users.knazarov.group; }; git_plan_config = { owner = config.users.users.knazarov.name; group = config.users.users.knazarov.group; }; git_plan_credentials = { owner = config.users.users.knazarov.name; group = config.users.users.knazarov.group; }; mullvad_account = { }; }; }; # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. # Configure network proxy if necessary # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; # Enable networking networking.networkmanager.enable = true; # Set your time zone. time.timeZone = "Europe/London"; # Select internationalisation properties. i18n.defaultLocale = "en_US.UTF-8"; i18n.extraLocaleSettings = { LC_ADDRESS = "en_US.UTF-8"; LC_IDENTIFICATION = "en_US.UTF-8"; LC_MEASUREMENT = "en_US.UTF-8"; LC_MONETARY = "en_US.UTF-8"; LC_NAME = "en_US.UTF-8"; LC_NUMERIC = "en_US.UTF-8"; LC_PAPER = "en_US.UTF-8"; LC_TELEPHONE = "en_US.UTF-8"; LC_TIME = "en_US.UTF-8"; }; # Mainly to access SMB shares on local network services.gvfs = { enable = true; package = lib.mkForce pkgs.gnome3.gvfs; }; # Configure keymap in X11 services.xserver = { layout = "us"; xkbVariant = ""; }; # Define a user account. Don't forget to set a password with ‘passwd’. users.users.knazarov = { isNormalUser = true; description = "Konstantin Nazarov"; extraGroups = [ "networkmanager" "wheel" config.users.groups.keys.name ]; packages = with pkgs; [ ]; openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDGxebDydOcs7URJjXFHMU++ruaZOJpXbK4ixH19pWTsX7WtxxriZxD4+RQ3oyllGG/8sEFzEe0NoTHUPU6YrBpfwT/ekGDmCJHtvZ+rZs+cRQd6tObfAUip1B1Mcvhuaj0prnrbfohOuHpvQ/L8TogIKuHgczDmud4KGUu0mxCsUHbD5tlKpsgN+dJXkvjxsO7JhhF9JpFTrYAU0gTuBPTt3ynpnZKrE1NgnE0iy+CEr/v41dLqxw3fUjT3nOFUQ1l/VKTw5mLt5Iw7XmBLuFGLRAVrwzXxeBCfYqKGYgY4QV8HCcVpcqC8zWmRskiRetzQ/5HwRagm4yZr0I+LZ305nGB0cSJzLWXXOUF6SDg2cqAXFpF/o2LoFCmaV5h3jmCGOUrowF7oV4mYwBMWfabrbZx21z/R56GkAOOEKc2h+Qh5wIj4yayX081SkqJK3J9+3vGG4VvXnwGnPnWQFqrzeedyV74maffGBGFYm0UOcD+oG6EwM+7MEUBpJm9m4c= knazarov" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHkDvP2BO1uV0AwEjABYFEiA2BbGo1IsSht4emYMRLgi root@mira" ]; }; nixpkgs.config.allowUnfree = true; environment.systemPackages = with pkgs; [ # needed to request polkit access (for instance, for SMB shares) lxqt.lxqt-policykit vim waybar foot wayland xdg-utils glib dracula-theme gnome3.adwaita-icon-theme swaylock swayidle wl-clipboard qutebrowser keyd tdesktop git source-code-pro pavucontrol brightnessctl sops age ssh-to-age syncthing pass pkgs.gnupg pciutils slack q-sh notes-sh transmission-gtk mpv imv okular yt-dlp evince # document viewer firefox gthumb unzip somafm-cli yubikey-manager yubikey-manager-qt gnome.gedit # temporary ripgrep file zoom-us obs-studio gnome.nautilus xfce.thunar zig morph gomuks nheko mullvad-vpn mullvad usbutils wf-recorder xournalpp dnsutils graphviz fzf nixfmt my_emacs libreoffice gcc #network-manager-applet (clang-tools.override { llvmPackages = llvmPackages_17; enableLibcxx = true; }) # mainly for clang-format # wget my_python ]; services.mullvad-vpn = { enable = true; }; systemd.services."mullvad-daemon".postStart = let mullvad = config.services.mullvad-vpn.package; in '' while ! ${mullvad}/bin/mullvad status >/dev/null; do sleep 1; done ${mullvad}/bin/mullvad account login `cat /var/run/secrets/mullvad_account` ${mullvad}/bin/mullvad auto-connect set on ${mullvad}/bin/mullvad tunnel ipv6 set on ''; services.fwupd.enable = true; services.gnome.gnome-keyring.enable = true; #services.emacs.package = nixpkgs.emacsUnstablePgtk; # Enables wayland support in electron apps (e.g. slack) environment.sessionVariables.NIXOS_OZONE_WL = "1"; # Set default browser to qutebrowser in electron apps #environment.sessionVariables.DEFAULT_BROWSER = #"${pkgs.qutebrowser}/bin/qutebrowser"; # Set default browser to qutebrowser everywhere else #xdg.mime.defaultApplications = { #"text/html" = "org.qutebrowser.qutebrowser.desktop"; #"x-scheme-handler/http" = "org.qutebrowser.qutebrowser.desktop"; #"x-scheme-handler/https" = "org.qutebrowser.qutebrowser.desktop"; #"x-scheme-handler/about" = "org.qutebrowser.qutebrowser.desktop"; #"x-scheme-handler/unknown" = "org.qutebrowser.qutebrowser.desktop"; #}; # Enable screen sharing on Wayland xdg = { portal = { enable = true; wlr.enable = true; extraPortals = with pkgs; [ xdg-desktop-portal-wlr xdg-desktop-portal-gtk ]; }; }; # Some programs need SUID wrappers, can be configured further or are # started in user sessions. # programs.mtr.enable = true; programs.gnupg.package = pkgs.gnupg; programs.gnupg.agent = { enable = true; enableSSHSupport = true; }; programs.sway = { enable = true; wrapperFeatures.gtk = true; }; # List services that you want to enable: services.pipewire = { enable = true; alsa.enable = true; alsa.support32Bit = true; pulse.enable = true; wireplumber.enable = true; }; # Disable unneeded PipeWire devices and rename the ones I use to more recognizable names environment.etc."wireplumber/main.lua.d/51-device-rename.lua".text = '' table.insert(alsa_monitor.rules, { matches = { { { "node.name", "equals", "alsa_output.usb-Audioengine_LLC_Audioengine_2__AE202010001A2002-00.analog-stereo" }, }, }, apply_properties = { ["node.description"] = "Speakers", ["node.nick"] = "Speakers", }, }) table.insert(alsa_monitor.rules, { matches = { { { "node.name", "equals", "alsa_output.usb-SteelSeries_SteelSeries_Arctis_5_00000000-00.analog-chat" }, }, }, apply_properties = { ["node.description"] = "Headphones", ["node.nick"] = "Headphones", }, }) table.insert(alsa_monitor.rules, { matches = { { { "node.name", "equals", "alsa_input.usb-SteelSeries_SteelSeries_Arctis_5_00000000-00.analog-chat" }, }, }, apply_properties = { ["node.description"] = "Headphone Mic", ["node.nick"] = "Headphone Mic", }, }) table.insert(alsa_monitor.rules, { matches = { {{ "node.name", "equals", "alsa_output.usb-SteelSeries_SteelSeries_Arctis_5_00000000-00.analog-game" },}, }, apply_properties = { ["node.disabled"] = true, }, }) table.insert(alsa_monitor.rules, { matches = { {{ "node.name", "equals", "alsa_output.pci-0000_14_00.1.hdmi-stereo" },}, }, apply_properties = { ["node.disabled"] = true, }, }) table.insert(alsa_monitor.rules, { matches = { {{ "node.name", "equals", "alsa_input.usb-MACROSILICON_USB_Video-02.analog-stereo" },}, }, apply_properties = { ["node.disabled"] = true, }, }) ''; services.dbus.enable = true; services.greetd = { enable = true; settings = rec { initial_session = { command = "${pkgs.sway}/bin/sway"; user = "knazarov"; }; default_session = initial_session; }; }; services.keyd = { enable = true; keyboards = { default = { ids = [ "*" ]; settings = { main = { capslock = "overload(control, esc)"; leftalt = "layer(meta_mac)"; leftmeta = "layer(alt)"; }; "meta_mac:M" = { c = "C-insert"; v = "S-insert"; }; }; }; }; }; # Enable the OpenSSH daemon. services.openssh = { enable = true; # settings = { # passwordAuthentication = false; # kbdInteractiveAuthentication = false; # }; }; services.jellyfin = { enable = true; openFirewall = true; }; networking.firewall.allowedTCPPorts = [ 8096 # Syncthing 8384 22000 ]; networking.firewall.allowedUDPPorts = [ # Syncthing 22000 21027 ]; # This value determines the NixOS release from which the default # settings for stateful data, like file locations and database versions # on your system were taken. It‘s perfectly fine and recommended to leave # this value at the release version of the first install of this system. # Before changing this value read the documentation for this option # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). system.stateVersion = "23.11"; # Did you read the comment? # needed for sway security.polkit.enable = true; # needed for pipewire security.rtkit.enable = true; # allow remote rebuilds nix.settings.trusted-users = [ "@wheel" ]; # needed for YubiKey smartcard support services.pcscd.enable = true; fonts.fontDir.enable = true; fonts.fonts = with pkgs; [ dejavu_fonts source-code-pro font-awesome # for waybar indicators ]; home-manager.users.knazarov = { # The home.stateVersion option does not have a default and must be set home.stateVersion = "23.05"; programs.bash = { enable = true; bashrcExtra = '' if [[ "$INSIDE_EMACS" = 'vterm' ]] \ && [[ -n ''${EMACS_VTERM_PATH} ]] \ && [[ -f ''${EMACS_VTERM_PATH}/etc/emacs-vterm-bash.sh ]]; then source ''${EMACS_VTERM_PATH}/etc/emacs-vterm-bash.sh fi ''; shellAliases = { nn = "notes.sh -n"; ne = ''notes.sh -l | fzf --tac --with-nth="2..-1" | xargs -o notes.sh -e''; }; }; gtk = { enable = true; gtk3.extraConfig = { gtk-enable-animations = "0"; }; gtk4.extraConfig = { gtk-enable-animations = "0"; }; }; programs.direnv = { enable = true; nix-direnv = { enable = true; }; }; programs.gpg = { enable = true; package = pkgs.gnupg; publicKeys = [ { source = ./gpg_public_key.asc; trust = "ultimate"; } { source = ./pgp_keys/FB4809DC51A4F483.asc; trust = "ultimate"; } ]; settings = { default-key = "0x0560020C9C577C1B"; }; mutableKeys = false; mutableTrust = false; }; programs.git = { enable = true; package = pkgs.gitAndTools.gitFull; # needed for git send-email support userName = "Konstantin Nazarov"; userEmail = "mail@knazarov.com"; signing = { gpgPath = "${pkgs.gnupg}/bin/gpg2"; key = "0x0560020C9C577C1B"; signByDefault = true; }; }; accounts.email = { maildirBasePath = "${config.users.users.knazarov.home}/Maildir"; accounts = { personal = let account = "mail@knazarov.com"; in { primary = true; flavor = "fastmail.com"; address = account; userName = account; realName = "Konstantin Nazarov"; passwordCommand = "cat /run/secrets/fastmail_password"; gpg = { key = "0x0560020C9C577C1B"; signByDefault = true; }; mu.enable = true; msmtp.enable = true; mbsync = { enable = true; # Folders existing on the server, but not locally, will be created. create = "maildir"; }; }; }; }; programs.mu = { enable = true; }; programs.msmtp.enable = true; programs.mbsync = { enable = true; }; #services.easyeffects = { # enable = true; #}; services.swayidle = { enable = true; timeouts = [ { timeout = 300; command = "${pkgs.swaylock}/bin/swaylock -f -c 000000"; } { timeout = 600; command = ''${pkgs.sway}/bin/swaymsg "output * dpms off"''; resumeCommand = ''${pkgs.sway}/bin/swaymsg "output * dpms on"''; } ]; events = [{ event = "before-sleep"; command = "${pkgs.swaylock}/bin/swaylock -f -c 000000"; }]; }; services.emacs = { enable = true; package = my_emacs; client.enable = true; }; wayland.windowManager.sway = { enable = true; xwayland = true; config = rec { modifier = "Mod4"; terminal = "foot"; bars = [{ "command" = "waybar"; }]; keybindings = pkgs.lib.mkOptionDefault { "XF86AudioRaiseVolume" = "exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"; "XF86AudioLowerVolume" = "exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"; "XF86AudioMute" = "exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; "XF86AudioMicMute" = "exec pactl set-source-mute @DEFAULT_SOURCE@ toggle"; "XF86MonBrightnessUp" = "exec brightnessctl s +5%"; "XF86MonBrightnessDown" = "exec brightnessctl s 5%-"; #"Mod4+Return" = #"exec emacs --eval '(progn (setq confirm-kill-processes nil) (vterm))'"; "Mod4+Return" = "exec emacsclient -c"; "Mod4+space" = "exec ${pkgs.foot}/bin/foot -T mylauncher -a mylauncher ${pkgs.q-sh}/bin/q"; "Mod4+p" = "exec '${pkgs.grim}/bin/grim -g \"$$(${pkgs.slurp}/bin/slurp)\" - | ${pkgs.wl-clipboard}/bin/wl-copy -t image/png'"; }; output = { "*" = { bg = "${./wallpaper.jpg} fill"; }; "Lenovo Group Limited LEN T32p-20 VNA4VRNY" = { scale = "1.5"; }; }; input = { "type:keyboard" = { xkb_layout = "us,ru"; xkb_options = "grp:alt_space_toggle"; }; }; gaps = { inner = 10; outer = 5; }; colors.unfocused = { border = "#dddddd"; background = "#dddddd"; text = "#888888"; indicator = "#888888"; childBorder = "#888888"; }; }; extraConfig = '' for_window [title="as_toolbar"] floating enable for_window [title="mylauncher"] floating enable for_window [title="Firefox.*Sharing Indicator"] floating enable; default_border pixel 3 input 1386:885:Wacom_Intuos_M_Pen map_to_output HDMI-A-1 ''; }; programs.foot = { enable = true; settings = { main = { font = "monospace:size=10"; }; colors = { background = "feffff"; foreground = "333333"; regular0 = "333333"; regular1 = "bd4436"; regular2 = "008700"; regular3 = "cdcc42"; regular4 = "0017f5"; regular5 = "b92cc6"; regular6 = "5bbdf9"; regular7 = "c7c7c7"; bright0 = "333333"; bright1 = "bd4436"; bright2 = "008700"; bright3 = "cdcc42"; bright4 = "0017f5"; bright5 = "b92cc6"; bright6 = "5bbdf9"; bright7 = "feffff"; }; key-bindings = { clipboard-copy = "Control+Insert"; clipboard-paste = "Shift+Insert"; primary-paste = "Control+Shift+v"; }; }; }; programs.qutebrowser = { enable = true; searchEngines = { DEFAULT = "https://kagi.com/search?q={}"; g = "https://www.google.com/search?hl=en&q={}"; }; #config.set('content.media.video_capture', True, 'https://www.meet.google.com') settings = { tabs.position = "left"; content.cookies.accept = "no-3rdparty"; }; extraConfig = '' config.set('content.javascript.can_access_clipboard', True, 'amazon.com') config.set('content.javascript.can_access_clipboard', True, 'awsapps.com') config.set('content.media.audio_capture', True, 'https://meet.google.com') config.set('content.media.video_capture', True, 'https://meet.google.com') config.set('content.media.audio_video_capture', True, 'https://meet.google.com') config.set('content.notifications.enabled', False, 'https://meet.google.com') config.set('content.register_protocol_handler', False, 'https://calendar.google.com?cid=%25s') ''; keyBindings = { insert = { "" = "insert-text -- {clipboard}"; }; }; }; programs.waybar = { enable = true; settings = [{ layer = "top"; position = "top"; height = 24; modules-left = [ "sway/workspaces" "sway/mode" ]; modules-center = [ "sway/window" ]; modules-right = [ "idle_inhibitor" "battery" "clock" "tray" ]; clock.format = "{:%Y-%m-%d %H:%M}"; battery = { states = { # good = 95; warning = 30; critical = 15; }; format = "{capacity}% {icon}"; format-charging = "{capacity}% "; format-plugged = "{capacity}% "; format-alt = "{time} {icon}"; format-icons = [ "" "" "" "" "" ]; }; idle_inhibitor = { format = "{icon}"; format-icons = { activated = ""; deactivated = ""; }; }; }]; }; services.syncthing = { enable = true; }; home.pointerCursor = { name = "Adwaita"; package = pkgs.gnome.adwaita-icon-theme; size = 24; x11 = { enable = true; defaultCursor = "Adwaita"; }; }; }; virtualisation = { podman = { enable = true; dockerCompat = true; defaultNetwork.settings = { dns_enabled = true; }; }; }; services.udev.packages = [ pkgs.android-udev-rules ]; #udevadm info --query=all --name=/dev/sda1 | grep ID_SERIAL services.udev.extraRules = ''ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", '' + '' ENV{ID_FS_USAGE}=="filesystem", ENV{ID_SERIAL_SHORT}=="Hidizs_AP80PRO", '' + ''RUN{program}+="${pkgs.systemd}/bin/systemd-mount --owner knazarov '' + ''--no-block --automount=yes --collect $devnode /media"''; systemd.timers."git_plan" = { wantedBy = [ "timers.target" ]; timerConfig = { OnBootSec = "1h"; OnUnitActiveSec = "1h"; Unit = "git_plan.service"; }; }; systemd.services."git_plan" = { script = '' ${my_python}/bin/python3 -m git_plan -c /var/run/secrets/git_plan_config -r /var/run/secrets/git_plan_credentials oneshot ''; serviceConfig = { Type = "oneshot"; User = "knazarov"; StateDirectory = "git_plan"; Environment = "PYTHONUNBUFFERED=1"; }; }; systemd.timers."git_plan_pr" = { wantedBy = [ "timers.target" ]; timerConfig = { OnCalendar = "Mon,Tue,Wed,Thu,Fri *-*-* 10:00:00"; Unit = "git_plan_pr.service"; }; }; systemd.services."git_plan_pr" = { script = '' ${my_python}/bin/python3 -m git_plan -c /var/run/secrets/git_plan_config -r /var/run/secrets/git_plan_credentials pr ''; serviceConfig = { Type = "oneshot"; User = "knazarov"; StateDirectory = "git_plan"; Environment = "PYTHONUNBUFFERED=1"; }; }; }