nixos/configuration.nix

835 lines
23 KiB
Nix
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
pkgs.mu.mu4e
epkgs.treesit-grammars.with-all-grammars
epkgs.evil-collection
];
});
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;
};
"${config.networking.hostName}_syncthing_key" = {
owner = config.users.users.knazarov.name;
group = config.users.users.knazarov.group;
};
"${config.networking.hostName}_syncthing_cert" = {
owner = config.users.users.knazarov.name;
group = config.users.users.knazarov.group;
};
mullvad_account = { };
kagi_api_key = {
owner = config.users.users.knazarov.name;
group = config.users.users.knazarov.group;
};
};
};
# 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.gnome.gvfs;
};
# Configure keymap in X11
services.xserver = {
xkb.layout = "us";
xkb.variant = "";
};
# 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
bc
dracula-theme
adwaita-icon-theme
swaylock
swayidle
wl-clipboard
keyd
tdesktop
git
source-code-pro
pavucontrol
brightnessctl
sops
age
ssh-to-age
syncthing
pass
pkgs.gnupg
pciutils
slack
q-sh
notes-sh
transmission_4-gtk
mpv
imv
okular
yt-dlp
evince # document viewer
firefox
gthumb
unzip
somafm-cli
# these packages have some problem with installation now
#yubikey-manager
#yubikey-manager-qt
ripgrep
file
zoom-us
obs-studio
nautilus
xfce.thunar
zig
mullvad-vpn
mullvad
usbutils
xournalpp
dnsutils
graphviz
fzf
fd
nixfmt
my_emacs
libreoffice
gcc
neovim
go
gopls
lazygit
guile
solc
kdenlive
kooha # screen capture
inotify-tools
# ----------
# mainly needed for npm which decided to play hardball
automake
autoconf
# ----------
(pkgs.callPackage ./nil_cli.nix {})
#network-manager-applet
#(clang-tools.override {
#llvmPackages = llvmPackages_17;
#enableLibcxx = false;
#}) # mainly for clang-format
clang-tools
# wget
my_python
# latex basics
(pkgs.texlive.combine {
inherit (pkgs.texlive) scheme-basic
dvisvgm dvipng beamer metafont
wrapfig amsmath ulem hyperref capt-of;
})
nodejs
networkmanagerapplet
qpwgraph
bat
chafa
];
services.blueman.enable = true;
services.tailscale.enable = true;
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 set ipv6 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";
# 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;
enableExtraSocket = 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;
};
services.pipewire.wireplumber.extraConfig.bluetoothEnhancements = {
"monitor.bluez.properties" = {
"bluez5.enable-sbc-xq" = true;
"bluez5.enable-msbc" = true;
"bluez5.enable-hw-volume" = true;
"bluez5.roles" = [ "hsp_hs" "hsp_ag" "hfp_hf" "hfp_ag" ];
};
};
programs.steam = {
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. Its 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.packages = with pkgs; [
dejavu_fonts
(nerdfonts.override { fonts = [ "SourceCodePro" ]; })
source-code-pro
font-awesome # for waybar indicators
];
services.syncthing = {
enable = true;
user = "knazarov";
configDir = "/home/knazarov/.config/syncthing";
key = config.sops.secrets."${config.networking.hostName}_syncthing_key".path;
cert = config.sops.secrets."${config.networking.hostName}_syncthing_cert".path;
};
home-manager.users.knazarov = {
# The home.stateVersion option does not have a default and must be set
home.stateVersion = "24.11";
home.sessionVariables = {
EDITOR = "emacs -nw --no-splash";
GUILE_LOAD_PATH = "${config.users.users.knazarov.home}/guile";
};
home.file.".guile" = {
source = ./guile-config;
};
programs.lf = {
enable = true;
extraConfig = ''
set sixel true
set previewer ${pkgs.chafa}/bin/chafa
'';
};
programs.bat = {
enable = true;
config = {
theme = "ansi";
};
};
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" --preview "notes.sh -p {}" --print-query --bind 'alt-enter:print-query' | xargs -o -d "\n" -n 2 notes.sh -f'';
vim = "emacs -nw --no-splash";
};
};
xdg.mimeApps = {
enable = true;
defaultApplications = {
"text/html" = "firefox.desktop";
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
"x-scheme-handler/about" = "firefox.desktop";
"x-scheme-handler/unknown" = "firefox.desktop";
};
};
gtk = {
enable = true;
gtk3.extraConfig = { gtk-enable-animations = "0"; };
gtk4.extraConfig = { gtk-enable-animations = "0"; };
};
# Workaround for https://github.com/nix-community/home-manager/issues/5146
services.gpg-agent = {
enable = true;
pinentryPackage = pkgs.pinentry-gnome3;
enableExtraSocket = true;
};
programs.gpg = {
enable = true;
package = pkgs.gnupg;
publicKeys = [
{
source = ./gpg_public_key.asc;
trust = "ultimate";
}
{
source = ./pgp_keys/FB4809DC51A4F483.asc;
trust = "ultimate";
}
{
source = ./pgp_keys/60B2FF168764BED2D4ADE1BF7DE090DD4DB68232.asc;
trust = "ultimate";
}
{
source = ./pgp_keys/8311DCF21B41308C743FBFEA44B0C3FE7CD9EAE3.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;
};
extraConfig = {
push = {
autoSetupRemote = 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";
};
neomutt = { enable = true; };
};
};
};
programs.neomutt = { enable = true; };
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+Return" = "exec foot";
"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'";
"Mod4+o" =
"exec '${pkgs.kooha}/bin/kooha'";
};
output = {
"*" = { bg = "${./wallpaper.jpg} fill"; };
"Lenovo Group Limited LEN T32p-20 VNA4VRNY" = { scale = "1.5"; };
"LG Electronics LG TV SSCR2 0x01010101" = { mode = "1920x1080@60Hz"; };
};
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 DP-1
exec_always ${pkgs.networkmanagerapplet}/bin/nm-applet --indicator
'';
};
programs.foot = {
enable = true;
settings = {
main = { font = "Source Code Pro:size=12"; };
colors = {
background = "ffffff";
foreground = "000000";
regular0 = "000000";
regular1 = "a60000";
regular2 = "005e00";
regular3 = "813e00";
regular4 = "0031a9";
regular5 = "721045";
regular6 = "00538b";
regular7 = "bfbfbf";
bright0 = "595959";
bright1 = "972500";
bright2 = "315b00";
bright3 = "70480f";
bright4 = "2544bb";
bright5 = "5317ac";
bright6 = "005a5f";
bright7 = "ffffff";
};
key-bindings = {
clipboard-copy = "Control+Insert";
clipboard-paste = "Shift+Insert";
primary-paste = "Control+Shift+v";
};
};
};
programs.waybar = {
enable = true;
settings = [{
layer = "top";
position = "top";
height = 24;
modules-left = [ "sway/workspaces" "sway/mode" ];
modules-center = [ "sway/window" ];
modules-right = [ "custom/maildir" "idle_inhibitor" "battery" "clock" "tray" ];
clock.format = "{:%Y-%m-%d %H:%M}";
"custom/maildir" = {
exec = "${./waybar_maildir.sh} /home/knazarov/Maildir/personal/Inbox/new knazarov";
format = " {} ";
return-type = "json";
};
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.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
(pkgs.callPackage ./zsa-udev-rules.nix {})];
#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";
};
};
}