nixos/configuration.nix

733 lines
20 KiB
Nix
Raw 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
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. 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.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 = { "<Shift+Ins>" = "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";
};
};
}