Initial commit

Note: not the actual initial commit.

I swear I will stop repeatedly force pushing to this single commit eventually
ok.
This commit is contained in:
eriedaberrie 2023-01-05 12:14:24 -08:00
commit 9083c619a6
132 changed files with 6608 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

BIN
assets/DannyMyBrother.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
assets/EmeraldOx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

BIN
assets/EmeraldOxBlur.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 KiB

BIN
assets/NeonBlack.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
assets/NeonColors.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

BIN
assets/nerd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

BIN
assets/pointingSoyjaks.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

BIN
assets/quag-head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

1
assets/searxng.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="92mm" height="92mm" viewBox="0 0 92 92"><g transform="translate(-40.921 -17.417)"><circle cx="75.921" cy="53.903" r="30" style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="M67.515 37.915a18 18 0 0 1 21.051 3.313 18 18 0 0 1 3.138 21.078" style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><rect width="18.846" height="39.963" x="3.706" y="122.09" ry="0" style="opacity:1;fill:#3050ff;fill-opacity:1;stroke:none;stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" transform="rotate(-46.235)"/></g></svg>

After

Width:  |  Height:  |  Size: 726 B

BIN
assets/snowyMountain.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

1092
flake.lock Normal file

File diff suppressed because it is too large Load diff

80
flake.nix Normal file
View file

@ -0,0 +1,80 @@
# Nixos System Configuration
{
description = "Modules and configuration for my NixOS system";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-23.11";
my-nix-packages = {
url = "github:eriedaberrie/my-nix-packages";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-index-database = {
url = "github:nix-community/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
lanzaboote = {
url = "github:nix-community/lanzaboote";
inputs.nixpkgs.follows = "nixpkgs";
};
cl-hyprland-ipc = {
url = "github:eriedaberrie/cl-hyprland-ipc";
inputs.nixpkgs.follows = "nixpkgs";
};
# nur.url = github:nix-community/NUR;
xdph = {
url = "github:hyprwm/xdg-desktop-portal-hyprland";
inputs.nixpkgs.follows = "nixpkgs";
};
hyprland = {
url = "git+https://github.com/hyprwm/Hyprland?submodules=1";
inputs.xdph.follows = "xdph";
};
hyprlock = {
url = "github:hyprwm/hyprlock";
inputs.nixpkgs.follows = "nixpkgs";
};
emacs-overlay = {
url = "github:nix-community/emacs-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
agenix = {
url = "github:ryantm/agenix";
inputs.nixpkgs.follows = "nixpkgs";
};
grim-hyprland = {
url = "github:eriedaberrie/grim-hyprland";
inputs.nixpkgs.follows = "nixpkgs";
};
spicetify-nix = {
url = "github:the-argus/spicetify-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-gaming.url = "github:fufexan/nix-gaming";
};
outputs = inputs: {
nixosConfigurations = import ./hosts inputs;
lib = import ./lib inputs;
homeManagerModules.default = import ./modules/home;
nixosModules.default = import ./modules/os;
};
nixConfig = {
extra-substituters = [
"https://nix-community.cachix.org"
"https://hyprland.cachix.org"
"https://nix-gaming.cachix.org"
];
extra-trusted-public-keys = [
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
"nix-gaming.cachix.org-1:nbjlureqMbRAxR1gJ/f3hxemL9svXaZF/Ees8vCUUs4="
];
};
}

15
hosts/default.nix Normal file
View file

@ -0,0 +1,15 @@
{ self, ... }:
self.lib.mkSystems {
msft-laptop = {
system = "x86_64-linux";
module = ./msft-laptop;
};
groceries = {
system = "x86_64-linux";
module = ./groceries;
};
}

View file

@ -0,0 +1,89 @@
{ pkgs, config, ... }:
{
imports = [
./services
./hardware-configuration.nix
];
time.timeZone = "America/Los_Angeles";
my = {
user = {
username = "serverie";
homeModule = ./home;
};
fs.bootPartition = false;
zram.writebackDevice = "/dev/sdb";
cli.fish.enable = true;
};
boot = {
initrd.availableKernelModules = [
"virtio_pci"
"virtio_scsi"
"ahci"
"sd_mod"
];
kernelParams = [ "console=ttyS0,19200n8" ];
kernelModules = [ "virtio_net" ];
loader = {
timeout = 10;
grub = {
enable = true;
forceInstall = true;
device = "nodev";
extraConfig = ''
serial --speed=19200 --unit=0 --word=8 --parity=no --stop=1;
terminal_input serial;
terminal_output serial
'';
};
};
};
networking = {
usePredictableInterfaceNames = false;
useDHCP = false;
interfaces.eth0 = {
useDHCP = true;
tempAddress = "disabled";
};
};
environment.systemPackages = with pkgs; [
inetutils
mtr
sysstat
nil
];
documentation.enable = false;
services = {
openssh = {
enable = true;
settings = {
LoginGraceTime = 0;
PasswordAuthentication = false;
PermitRootLogin = "no";
};
};
};
users.users.${config.my.user.username} = {
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIElnlmCCIRhwe7z/a4dpwNoPF65II8NsOHUWJIBdr2Rg errie@nix-laptop"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFDWYERkHOqml1ntOUp8iZRTtvuAVUXcT4RRdqYtvxBy u0_a313@localhost"
];
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,28 @@
# 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 + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "virtio_pci" "virtio_scsi" "ahci" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/sda";
fsType = "ext4";
autoResize = true;
};
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s5.useDHCP = lib.mkDefault true;
}

View file

@ -0,0 +1,18 @@
_:
{
imports = [ ./packages.nix ];
my = {
git.enable = true;
shell = {
aliases.enable = true;
direnv.enable = true;
fish.enable = true;
globalNpmPackages.enable = true;
};
};
home.stateVersion = "23.05";
}

View file

@ -0,0 +1,6 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
];
}

View file

@ -0,0 +1,38 @@
{ config, ... }:
{
imports = [
./forgejo.nix
./sync
];
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.nginx = {
enable = true;
virtualHosts = {
"eriedaberrie.me" = {
forceSSL = true;
enableACME = true;
acmeRoot = null;
serverAliases = [ "www.eriedaberrie.me" ];
locations."/".proxyPass = "http://127.0.0.1:8080/";
};
};
};
security.acme = {
acceptTerms = true;
defaults.email = "eriedaberrie@gmail.com";
certs = {
"eriedaberrie.me" = {
dnsProvider = "porkbun";
credentialsFile = config.age.secrets.porkbun-auth.path;
extraDomainNames = [
"www.eriedaberrie.me"
];
};
};
};
}

View file

@ -0,0 +1,70 @@
{ pkgs, config, lib, ... }:
let
cfg = config.services.forgejo;
in {
services.forgejo = {
enable = true;
appName = "Eriedaberrie's Forgejo";
lfs.enable = true;
settings = {
server = {
PROTOCOL = "http+unix";
ROOT_URL = "https://git.eriedaberrie.me/";
};
service = {
COOKIE_SECURE = true;
DISABLE_REGISTRATION = true;
};
ui = {
DEFAULT_THEME = "catppuccin-mocha-lavender";
THEMES = "catppuccin-mocha-lavender,forgejo-auto,forgejo-light,forgejo-dark,auto,gitea,arc-green";
};
"highlight.mapping" = {
".lock" = "json";
};
};
user = "git";
};
# Because the module only autocreates the user if it's the default name
users.users = lib.mkIf (cfg.user != "forgejo") {
${cfg.user} = {
inherit (cfg) group;
description = "Forgejo Service";
home = cfg.stateDir;
useDefaultShell = true;
isSystemUser = true;
};
};
systemd.tmpfiles.rules = let
inherit (cfg) customDir user group;
catppuccinSource = pkgs.fetchzip {
url = "https://github.com/catppuccin/gitea/releases/download/v0.4.1/catppuccin-gitea.tar.gz";
hash = "sha256-14XqO1ZhhPS7VDBSzqW55kh6n5cFZGZmvRCtMEh8JPI=";
stripRoot = false;
};
fileName = "theme-catppuccin-mocha-lavender.css";
in [
"d '${customDir}/public' 0750 ${user} ${group} - -"
"d '${customDir}/public/assets' 0750 ${user} ${group} - -"
"d '${customDir}/public/assets/css' 0750 ${user} ${group} - -"
"z '${customDir}/public' 0750 ${user} ${group} - -"
"z '${customDir}/public/assets' 0750 ${user} ${group} - -"
"z '${customDir}/public/assets/css' 0750 ${user} ${group} - -"
"L+ '${customDir}/public/assets/css/${fileName}' - - - - ${catppuccinSource}/${fileName}"
];
services.nginx = {
virtualHosts."git.eriedaberrie.me" = {
forceSSL = true;
useACMEHost = "eriedaberrie.me";
locations."/".proxyPass = "http://forgejo/";
};
upstreams.forgejo.servers."unix:${cfg.settings.server.HTTP_ADDR}" = { };
};
security.acme.certs."eriedaberrie.me".extraDomainNames = [ "git.eriedaberrie.me" ];
}

View file

@ -0,0 +1,18 @@
_:
{
imports = [
./syncthing.nix
./syncyomi.nix
];
services.nginx = {
virtualHosts."sync.eriedaberrie.me" = {
forceSSL = true;
useACMEHost = "eriedaberrie.me";
locations."/".return = "301 $scheme://eriedaberrie.me$request_uri";
};
};
security.acme.certs."eriedaberrie.me".extraDomainNames = [ "sync.eriedaberrie.me" ];
}

View file

@ -0,0 +1,39 @@
{ config, ... }:
let
sockDir = "/run/syncthing";
cfg = config.services.syncthing;
in {
my.syncthing.enable = true;
services = {
nginx = let
upstream = "syncthing";
in {
virtualHosts."sync.eriedaberrie.me" = {
locations."/syncthing/".proxyPass = "http://${upstream}/";
};
upstreams.${upstream}.servers."unix:${cfg.guiAddress}" = { };
};
syncthing = {
guiAddress = "${sockDir}/syncthing.sock";
settings = {
gui = {
address = cfg.guiAddress;
unixSocketPermissions = "666";
user = "serverie";
password = "$2a$10$sSOgRCl5kB0ixakiVidWI.IH26tkoNZHqf9eUwoHmHxPEDRdYDZ06";
};
};
};
};
systemd.tmpfiles.rules = let
inherit (cfg) user group;
in [
"d '${sockDir}' 0755 ${user} ${group} - -"
"z '${sockDir}' 0755 ${user} ${group} - -"
];
}

View file

@ -0,0 +1,21 @@
{ config, ... }:
let
cfg = config.services.syncyomi;
baseUrl = "/syncyomi/";
in {
services = {
nginx = {
virtualHosts."sync.eriedaberrie.me" = {
locations.${baseUrl}.proxyPass = "http://127.0.0.1:${builtins.toString cfg.settings.port}/";
};
};
syncyomi = {
enable = true;
settings = {
inherit baseUrl;
};
};
};
}

View file

@ -0,0 +1,74 @@
{ pkgs, config, ... }:
let
interface = "wg0";
listenPort = 51821;
tcpPort = 82;
in {
systemd.services."udp2raw-${interface}" = {
after = [ "network.target" ];
before = [ "wg-quick-${interface}.service" ];
wantedBy = [ "wg-quick-${interface}.service" ];
serviceConfig = {
ExecStart = "${pkgs.udp2raw}/bin/udp2raw -s -l 0.0.0.0:${builtins.toString tcpPort} -r 127.0.0.1:${builtins.toString listenPort} -a";
};
};
services.dnsmasq = {
enable = true;
settings = {
inherit interface;
};
};
networking = {
nat = {
enable = true;
externalInterface = "eth0";
internalInterfaces = [ interface ];
enableIPv6 = true;
};
firewall = {
allowedUDPPorts = [ listenPort ];
allowedTCPPorts = [ tcpPort ];
interfaces.${interface} = {
allowedUDPPorts = [ 53 ];
allowedTCPPorts = [ 53 ];
};
};
wg-quick.interfaces = {
${interface} = {
address = [ "10.0.0.1/24" "fdc9:281f:04d7:9ee9::1/64" ];
inherit listenPort;
privateKeyFile = config.age.secrets.wg-groceries.path;
postUp = ''
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -o eth0 -j MASQUERADE
${pkgs.iptables}/bin/ip6tables -A FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/ip6tables -t nat -A POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o eth0 -j MASQUERADE
'';
preDown = ''
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.0.0.1/24 -o eth0 -j MASQUERADE
${pkgs.iptables}/bin/ip6tables -D FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/ip6tables -t nat -D POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o eth0 -j MASQUERADE
'';
peers = [
{
publicKey = "mX5cMCXQbnovPOHDFdcV3egG3u9Xd3sci+mqUhFSz1Q=";
allowedIPs = [ "10.0.0.2/32" "fdc9:281f:04d7:9ee9::2/128" ];
}
{
publicKey = "Hkk76wQQ3dYY31GYUSHMIOBgiKDPqm00cKBLMzwTO1s=";
allowedIPs = [ "10.0.0.3/32" "fdc9:281f:04d7:9ee9::3/128" ];
}
];
};
};
};
}

View file

@ -0,0 +1,22 @@
_:
{
services = {
wordpress = {
sites."iclean.eriedaberrie.me" = {
settings = {
FORCE_SSL_ADMIN = true;
};
};
webserver = "nginx";
};
nginx.virtualHosts."iclean.eriedaberrie.me" = {
forceSSL = true;
useACMEHost = "eriedaberrie.me";
};
};
security.acme.certs."eriedaberrie.me".extraDomainNames = [ "iclean.eriedaberrie.me" ];
}

View file

@ -0,0 +1,97 @@
{ pkgs, lib, ... }:
{
imports = [
./hardware-configuration.nix
];
time.timeZone = "America/Los_Angeles";
my = {
user = {
username = "errie";
homeModule = ./home;
};
secure-boot.enable = true;
bootloader.type = "systemdBoot";
fs = {
luks.enable = true;
ssd.enable = true;
bootPartition = true;
snapshots = true;
type = "btrfs";
};
laptop = {
enable = true;
amd.enable = true;
};
networking = {
networkManager.enable = true;
eddie = let
forwardedPorts = [ 14110 50459 ];
in {
enable = true;
allowedTCPPorts = forwardedPorts;
allowedUDPPorts = forwardedPorts;
};
};
bin-compat.enable = true;
docker.enable = true;
interception.enable = true;
location.enable = true;
virt-manager.enable = true;
wireshark.enable = true;
syncthing = {
enable = true;
asUser = true;
};
cli = {
fish.enable = true;
nix-index.enable = true;
sudo.insults.enable = true;
};
desktop = {
enable = true;
audio.enable = true;
bluetooth.enable = true;
gaming.enable = true;
hyprland.enable = true;
printing.enable = true;
};
};
environment.systemPackages = with pkgs; [
dos2unix
amdgpu_top
(p7zip.override {enableUnfree = true;})
];
programs = {
git.package = pkgs.gitFull;
};
hardware.sensor.iio.enable = true;
services = {
fwupd.enable = true;
flatpak.enable = true;
openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
};
};
};
system.stateVersion = "23.11";
}

View file

@ -0,0 +1,23 @@
# 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" "thunderbolt" "usb_storage" "usbhid" "uas" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -0,0 +1,68 @@
{ ... }:
{
imports = [ ./packages.nix ];
my = {
email.enable = true;
git.enable = true;
keepassxc.enable = true;
cli = {
bat.enable = true;
btop.enable = true;
eza.enable = true;
};
fetch = {
fastfetch.enable = true;
others.enable = true;
};
graphical = {
enable = true;
dunst.enable = true;
emacs.enable = true;
firefox.enable = true;
mangohud.enable = true;
mpv.enable = true;
obs.enable = true;
zathura.enable = true;
wayland = {
enable = true;
fuzzel.enable = true;
hyprland.enable = true;
eww.enable = true;
foot.enable = true;
gammastep.enable = true;
hyprlock.enable = true;
ydotool.enable = true;
};
};
mpd = {
enable = true;
ncmpcpp.enable = true;
};
shell = {
aliases.enable = true;
direnv.enable = true;
fish.enable = true;
globalNpmPackages.enable = true;
starship.enable = true;
};
};
programs = {
java.enable = true;
};
services = {
playerctld.enable = true;
};
home.stateVersion = "23.11";
}

View file

@ -0,0 +1,37 @@
{ pkgs, inputs, ... }:
{
home.packages = (with pkgs; [
jaq
imagemagick
ffmpeg-full
python3
ruby
lazygit
playerctl
cantata
socat
sway
imv
gimp
inkscape
xfce.thunar
yt-dlp
libqalculate
qalculate-gtk
libreoffice
(hunspellWithDicts [ hunspellDicts.en-us ])
zoom-us
slack
remmina
winetricks
ripdrag
(vesktop.override {withSystemVencord = false;})
aseprite
qbittorrent
nicotine-plus
r2modman
]) ++ (with inputs.nix-gaming.packages.${pkgs.system}; [
wine-ge
]);
}

View file

@ -0,0 +1,98 @@
{ pkgs, lib, ... }:
{
imports = [
./hardware-configuration.nix
./wireguard.nix
];
time.timeZone = "America/Los_Angeles";
my = {
user = {
username = "errie";
homeModule = ./home;
};
bootloader.type = "systemdBoot";
fs = {
bootPartition = true;
snapshots = true;
type = "btrfs";
};
networking = {
networkManager.enable = true;
eddie = {
enable = true;
allowedTCPPorts = [ 50459 ];
};
};
bin-compat.enable = true;
interception.enable = true;
location.enable = true;
virt-manager.enable = true;
wireshark.enable = true;
syncthing = {
enable = true;
asUser = true;
};
cli = {
fish.enable = true;
nix-index.enable = true;
};
desktop = {
enable = true;
audio.enable = true;
bluetooth.enable = true;
gaming.enable = true;
hyprland.enable = true;
printing.enable = true;
};
};
systemd.services.nginx.wantedBy = lib.mkForce [ ];
environment.systemPackages = with pkgs; [
gcc
dos2unix
];
programs = {
zsh.enable = true;
git.package = pkgs.gitFull;
};
services = {
flatpak.enable = true;
openssh.enable = true;
mullvad-vpn = {
enable = true;
package = pkgs.mullvad-vpn;
};
nginx = {
enable = true;
virtualHosts."127.0.0.1" = {
listen = [
{
addr = "127.0.0.1";
port = 80;
}
];
locations."/" = {
proxyPass = "http://127.0.0.1:3000/";
};
};
};
};
system.stateVersion = "22.11";
}

View file

@ -0,0 +1,26 @@
# 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 = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp2s0.useDHCP = lib.mkDefault true;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -0,0 +1,68 @@
{ pkgs, ... }:
{
imports = [ ./packages.nix ];
my = {
email.enable = true;
git.enable = true;
keepassxc.enable = true;
cli = {
bat.enable = true;
btop.enable = true;
eza.enable = true;
};
fetch = {
fastfetch.enable = true;
others.enable = true;
};
graphical = {
enable = true;
dunst.enable = true;
emacs.enable = true;
firefox.enable = true;
mpv.enable = true;
obs.enable = true;
zathura.enable = true;
wayland = {
enable = true;
fuzzel.enable = true;
hyprland.enable = true;
eww.enable = true;
foot.enable = true;
gammastep.enable = true;
swayidle.enable = true;
swaylock.enable = true;
ydotool.enable = true;
};
};
shell = {
aliases.enable = true;
direnv.enable = true;
fish.enable = true;
globalNpmPackages.enable = true;
starship.enable = true;
zsh.enable = true;
};
spotify = {
spicetify.enable = true;
};
};
programs = {
java.enable = true;
neovim = {
enable = true;
plugins = with pkgs.vimPlugins; [ packer-nvim ];
};
};
home.stateVersion = "22.11";
}

View file

@ -0,0 +1,45 @@
{ pkgs, inputs, self, ... }:
{
home.packages = (with pkgs; [
jaq
imagemagick
ffmpeg
nodejs
sbcl
racket
ghc
pyright
sumneko-lua-language-server
clang-tools
bear
rust-analyzer
cmake
meson
lazygit
fortune
neo-cowsay
lolcat
playerctl
socat
sway
imv
gimp
inkscape
xfce.thunar
libqalculate
qalculate-gtk
libreoffice
(hunspellWithDicts [ hunspellDicts.en-us ])
zoom-us
slack
remmina
godot_4
winetricks
ripdrag
aseprite
qbittorrent
]) ++ (with inputs.nix-gaming.packages.${pkgs.system}; [
wine-ge
]);
}

View file

@ -0,0 +1,72 @@
{ pkgs, config, lib, ... }:
let
interface = "wg0";
listenPort = 51821;
tcpPort = 82;
in {
systemd.services = {
"wg-quick-${interface}".wantedBy = lib.mkForce [ ];
"udp2raw-${interface}" = {
after = [ "network.target" ];
before = [ "wg-quick-${interface}.service" ];
requires = [ "wg-quick-${interface}.service" ];
wantedBy = [ "wg-quick-${interface}.service" ];
serviceConfig = let
remoteIP = "66.175.222.204";
in {
ExecStartPre = pkgs.writeShellScript "pre-udp2raw-${interface}" ''
eval "$(
${pkgs.iproute2}/bin/ip route | ${pkgs.gawk}/bin/awk \
'$1=="default" {
printf "%s", "${pkgs.iproute2}/bin/ip route add ${remoteIP}"
for (i=2; i<=NF; i+=2) {
if ($i=="via" || $i=="dev" || $i=="metric") {
printf " %s %s", $i, $(i+1)
}
}
print " proto static"
}'
)"
'';
ExecStart = pkgs.writeShellScript "udp2raw-${interface}" ''
exec ${pkgs.udp2raw}/bin/udp2raw -c \
-l "127.0.0.1:${builtins.toString listenPort}" \
-r "${remoteIP}:${builtins.toString tcpPort}" \
-a
'';
ExecStopPost = "${pkgs.iproute2}/bin/ip route flush ${remoteIP} proto static";
Restart = "on-failure";
};
};
};
networking = {
firewall.checkReversePath = "loose";
wg-quick.interfaces = {
${interface} = let
publicKey = "Awb1R2KZ3v4MArN/Lmxr4BTL0rdFm5dJID6ntifr4GQ=";
in {
address = [ "10.0.0.2/32" "fdc9:281f:04d7:9ee9::2/128" ];
dns = [ "10.0.0.1" ];
privateKeyFile = config.age.secrets.wg-nix-laptop.path;
mtu = 1332;
postUp = [
"wg set wg0 peer ${publicKey} persistent-keepalive 25"
];
peers = [
{
inherit publicKey;
allowedIPs = [ "0.0.0.0/0" "::/0" ];
endpoint = "127.0.0.1:${builtins.toString listenPort}";
}
];
};
};
};
}

33
lib/default.nix Normal file
View file

@ -0,0 +1,33 @@
{ nixpkgs, self, ... } @ inputs:
let
inherit (nixpkgs) lib;
in rec {
mkSystems = builtins.mapAttrs (hostName: cfg: lib.nixosSystem {
inherit (cfg) system;
specialArgs = {inherit self inputs;};
modules = [
{
networking = {inherit hostName;};
nixpkgs.hostPlatform = cfg.system;
}
self.nixosModules.default
cfg.module
];
});
recReadDir = startDir: dir: lib.concatMapAttrs (file: type: let
fullFile = "${dir}/${file}";
in
if type == "directory" then recReadDir startDir fullFile
else {${fullFile} = "${startDir}/${fullFile}";}
) (builtins.readDir "${startDir}/${dir}");
filterNixReadDir = dir: lib.filterAttrs (name: _:
builtins.match ".*\\.nix" name == null
) (recReadDir dir ".");
}

67
modules/home/cli.nix Normal file
View file

@ -0,0 +1,67 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.cli;
in {
options.my.cli = {
bat.enable = lib.mkEnableOption null;
btop.enable = lib.mkEnableOption null;
eza.enable = lib.mkEnableOption null // {
default = true;
};
ranger.enable = lib.mkEnableOption null;
};
config = lib.mkMerge [
(lib.mkIf cfg.bat.enable {
programs.bat = {
enable = true;
config = {
map-syntax = [ "flake.lock:JSON" ];
theme = "catppuccinMocha";
};
themes = {
catppuccinMocha = {
src = pkgs.fetchFromGitHub {
owner = "catppuccin";
repo = "bat";
rev = "ba4d16880d63e656acced2b7d4e034e4a93f74b1";
sha256 = "1g2r6j33f4zys853i1c5gnwcdbwb6xv5w6pazfdslxf69904lrg9";
};
file = "Catppuccin-mocha.tmTheme";
};
};
};
xdg.configFile."btop/themes/catppuccin_mocha.theme".source = pkgs.fetchFromGitHub {
owner = "catppuccin";
repo = "btop";
rev = "89ff712eb62747491a76a7902c475007244ff202";
hash = "sha256-J3UezOQMDdxpflGax0rGBF/XMiKqdqZXuX4KMVGTxFk=";
} + "/themes/catppuccin_mocha.theme";
})
(lib.mkIf cfg.btop.enable {
programs.btop = {
enable = true;
settings = {
vim_keys = true;
color_theme = "catppuccin_mocha";
};
};
})
(lib.mkIf cfg.eza.enable {
programs.eza = {
enable = true;
};
})
(lib.mkIf cfg.ranger.enable {
home.packages = [ pkgs.ranger ];
xdg.configFile."ranger/rc.conf".text = ''
set preview_images true
set preview_images_method kitty
'';
})
];
}

28
modules/home/default.nix Normal file
View file

@ -0,0 +1,28 @@
{ lib, osConfig, ... }:
{
imports = [
# inputs.nur.hmModules.nur
./graphical
./themes
./cli.nix
./email.nix
./fetch.nix
./git.nix
./mpd.nix
./nix.nix
./packages.nix
./shell.nix
./spotify.nix
];
xdg.enable = true;
dconf.settings = lib.mkIf osConfig.my.virt-manager.enable {
"org/virt-manager/virt-manager/connections" = {
autoconnect = [ "qemu:///system" ];
uris = [ "qemu:///system" ];
};
};
}

114
modules/home/email.nix Normal file
View file

@ -0,0 +1,114 @@
{ pkgs, config, lib, osConfig, ... }:
let
cfg = config.my.email;
in {
options.my.email = {
enable = lib.mkEnableOption null;
git.enable = lib.mkEnableOption null // {
default = true;
};
emacs.enable = lib.mkEnableOption null // {
default = config.my.git.enable;
};
};
config = lib.mkIf cfg.enable (let
emailJson = osConfig.age.secrets.email.path;
anyConfigCmd = delim: t: k:
"${pkgs.jaq}/bin/jaq -r ${delim}.${t}.${k}${delim} ${emailJson}";
in lib.mkMerge [
(lib.mkIf cfg.emacs.enable {
accounts.email = {
maildirBasePath = "Mail";
accounts = builtins.mapAttrs (type: address: {
inherit address;
realName = address;
passwordCommand = anyConfigCmd "" type "password";
primary = type == "personal";
flavor = "gmail.com";
smtp.tls.useStartTls = true;
mbsync = {
enable = true;
create = "both";
expunge = "both";
};
mu.enable = true;
imapnotify = let
mbsync = "${config.programs.mbsync.package}/bin/mbsync";
mu = "${pkgs.mu}/bin/mu";
in {
enable = true;
boxes = [ "Inbox" ];
onNotify = "${mbsync} ${type} && ${mu} index";
onNotifyPost = let
notify-send = "${pkgs.libnotify}/bin/notify-send";
muFindEscape = f: let
sed = "${pkgs.gnused}/bin/sed";
in "${mu} find \"l:$FILE\" -f ${f}"
+ " | ${sed} 's/</\\&lt;/g'"
+ " | ${sed} 's/>/\\&gt;/g'";
in pkgs.writeScript "inbox-notify-latest-${type}" ''
FILE="$(${mu} find "m:/${type}/Inbox" -z -s d -n 1 -f l)"
exec ${notify-send} -i mail-unread-new \
"[${address}] $(${muFindEscape "s"})" \
"from: $(${muFindEscape "f"})"
'';
extraConfig.wait = 3;
};
}) {
personal = "erlic006@gmail.com";
other = "eriedaberrie@gmail.com";
};
};
programs = {
mbsync.enable = true;
mu.enable = true;
};
services.imapnotify.enable = true;
home.sessionVariables.MAILDIR = config.accounts.email.maildirBasePath;
})
(lib.mkIf cfg.git.enable (let
gitSetEmail = pkgs.writeShellScriptBin "git-set-email" (let
git = "${config.programs.git.package}/bin/git";
gitConfRep = "${git} config --replace-all --local";
in ''
${git} rev-parse --is-inside-work-tree > /dev/null || exit 1
if [ -z "$1" ]; then
declare -a keys=("user.name"
"user.email"
"sendemail.from"
"sendemail.smtpUser"
"sendemail.smtpPass"
"sendemail.smtpEncryption"
"sendemail.smtpServer"
"sendemail.smtpServerPort"
"sendemail.smtpSslCertPath")
for key in "''${keys[@]}"; do
${git} config --unset-all --local "$key"
done
else
[ "$(${pkgs.jaq}/bin/jaq "has(\"$1\")" ${emailJson})" = true ] || exit 1
NAME="$(${anyConfigCmd "\"" "$1" "name"})"
ADDRESS="$(${anyConfigCmd "\"" "$1" "address"})"
${gitConfRep} 'user.name' "$NAME"
${gitConfRep} 'user.email' "$ADDRESS"
${gitConfRep} 'sendemail.from' "$NAME <$ADDRESS>"
${gitConfRep} 'sendemail.smtpPass' "$(${anyConfigCmd "\"" "$1" "password"})"
declare -a keys=("smtpEncryption"
"smtpServer"
"smtpServerPort"
"smtpSslCertPath"
"smtpUser")
for key in "''${keys[@]}"; do
${gitConfRep} "sendemail.$key" \
"$(${git} config --get --global "sendemail.$1.$key")"
done
fi
'');
in {
home.packages = [ gitSetEmail];
}))
]);
}

83
modules/home/fetch.nix Normal file
View file

@ -0,0 +1,83 @@
{ pkgs, config, lib, inputs, ... }:
let
cfg = config.my.fetch;
in {
options.my.fetch = {
fastfetch.enable = lib.mkEnableOption null;
neofetch.enable = lib.mkEnableOption null;
others.enable = lib.mkEnableOption null;
};
config = lib.mkMerge [
(lib.mkIf cfg.fastfetch.enable {
home.packages = [
(inputs.my-nix-packages.packages.${pkgs.system}.fastfetch.overrideAttrs {
flashfetchModules = [
"title"
"separator"
"os"
"kernel"
"uptime"
"shell"
"display"
"wm"
"theme"
"icons"
"font"
"cursor"
"terminal"
"terminalFont"
"cpu"
"gpu"
"memory"
"disk"
"battery"
"locale"
];
})
];
})
(lib.mkIf cfg.neofetch.enable {
home.packages = [ pkgs.neofetch ];
xdg.configFile = {
"neofetch/config.conf".text = ''
print_info() {
info title
info underline
info "OS" distro
info "Host" model
info "Kernel" kernel
info "Uptime" uptime
info "Shell" shell
info "Resolution" resolution
info "DE" de
info "Theme" theme
info "Icons" icons
info "Terminal" term
info "Terminal Font" term_font
info "CPU" cpu
info "GPU" gpu
info "Memory" memory
info cols
}
memory_percent="on"
shell_path="on"
speed_shorthand="off"
'';
};
})
(lib.mkIf cfg.others.enable {
home.packages = with pkgs; [
nitch
(uwufetch.overrideAttrs (old: {
preBuild = old.preBuild or "" + ''
mkdir -p $out/include
'';
}))
];
})
];
}

43
modules/home/git.nix Normal file
View file

@ -0,0 +1,43 @@
{ pkgs, config, lib, osConfig, ... }:
let
cfg = config.my.git;
in {
options.my.git = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
home = {
sessionVariables.FILTER_BRANCH_SQUELCH_WARNING = 1;
shellAliases = {
g = "git";
lg = "lazygit";
};
packages = with pkgs; [
git-absorb
];
};
programs.git = {
enable = true;
inherit (osConfig.programs.git) package;
userName = "eriedaberrie";
userEmail = "eriedaberrie@gmail.com";
aliases = {
hardfetch = "!git fetch --progress $1 && git reset --hard $1 && :";
pushf = "push --force-with-lease";
syncdates = "filter-branch --env-filter 'export GIT_COMMITTER_DATE=\"$GIT_AUTHOR_DATE\"'";
};
extraConfig = {
commit.verbose = true;
init.defaultBranch = "main";
pull.rebase = true;
push.autoSetupRemote = true;
rebase.autoStash = true;
rerere.enabled = true;
github.user = "eriedaberrie";
gitlab.user = "eriedaberrie";
};
};
};
}

View file

@ -0,0 +1,88 @@
{ pkgs, config, lib, osConfig, ... }:
let
cfg = config.my.graphical;
in {
imports = [
./wayland
./dunst.nix
./emacs.nix
./firefox.nix
./keepassxc.nix
./kitty.nix
./mangohud.nix
./mpv.nix
./obs.nix
./qtk.nix
./qutebrowser.nix
./zathura.nix
];
options.my.graphical = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
fonts.fontconfig.enable = true;
xdg = {
userDirs = {
enable = true;
createDirectories = true;
};
mimeApps = {
enable = true;
defaultApplications = let
editor = "emacsclient.desktop";
email = "emacsclient-mail.desktop";
pdf = "org.pwmt.zathura.desktop";
browser = "firefox.desktop";
image = "imv.desktop";
video = "mpv.desktop";
explorer = "thunar.desktop";
in {
"application/octet-stream" = editor;
"text/plain" = editor;
"x-scheme-handler/http" = browser;
"x-scheme-handler/https" = browser;
"x-scheme-handler/mailto" = email;
"application/pdf" = pdf;
"image/bmp" = image;
"image/jpeg" = image;
"image/gif" = image;
"image/png" = image;
"image/svg+xml" = image;
"image/webp" = image;
"inode/directory" = explorer;
"video/mp4" = video;
"video/mpeg" = video;
};
};
};
services = let
bluetooth = osConfig.my.desktop.bluetooth.enable;
networkManager = osConfig.my.networking.networkManager.enable;
in {
mpris-proxy.enable = bluetooth;
blueman-applet.enable = bluetooth;
network-manager-applet.enable = networkManager;
};
home = let
cursorSize = 36;
in {
pointerCursor = {
package = pkgs.catppuccin-cursors.mochaDark;
name = "catppuccin-mocha-dark-cursors";
size = cursorSize;
gtk.enable = true;
};
sessionVariables = lib.mkIf config.my.graphical.wayland.hyprland.enable {
HYPRCURSOR_THEME = "catppuccin-mocha-dark";
HYPRCURSOR_SIZE = cursorSize;
};
};
};
}

View file

@ -0,0 +1,86 @@
{ pkgs, config, lib, theme, inputs, self, ... }:
let
cfg = config.my.graphical.dunst;
in {
options.my.graphical.dunst = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable (let
volumeTag = "my-volume";
brightnessTag = "my-brightness";
dunstify = "${config.services.dunst.package}/bin/dunstify";
dunstVolume = let
wpctl = "${pkgs.wireplumber}/bin/wpctl";
in pkgs.writeShellScriptBin "dunst-volume" ''
SINK="''${3:-@DEFAULT_AUDIO_SINK@}"
${wpctl} "$1" $SINK "$2"
VOLUME_DATA="$(${wpctl} get-volume $SINK)"
VOLUME="$(awk '{print 100*$2}' <<< "$VOLUME_DATA")"
if grep -q '\[MUTED\]' <<< "$VOLUME_DATA"; then
exec ${dunstify} -u low -t 1000 -i audio-volume-muted \
-h "string:x-dunst-stack-tag:${volumeTag}" \
-h "int:value:$VOLUME" \
"Volume: $VOLUME%" "(muted)"
else
if (( "$VOLUME" >= 75 )); then
ICON=high
elif (( "$VOLUME" <= 25 )); then
ICON=low
else
ICON=medium
fi
exec ${dunstify} -u low -t 1000 -i "audio-volume-$ICON" \
-h "string:x-dunst-stack-tag:${volumeTag}" \
-h "int:value:$VOLUME" \
"Volume: $VOLUME%"
fi
'';
dunstBrightness = let
brightnessctl = "${pkgs.brightnessctl}/bin/brightnessctl";
in pkgs.writeShellScriptBin "dunst-brightness" ''
${brightnessctl} set "$1"
BRIGHTNESS="$(awk -F , '{print 100*$3/$5}' <<< "$(${brightnessctl} info -m)")"
exec ${dunstify} -u low -t 1000 \
-h "string:x-dunst-stack-tag:${brightnessTag}" \
-h "int:value:$BRIGHTNESS" \
"Brightness: $BRIGHTNESS%"
'';
in {
home.packages = [
dunstVolume
dunstBrightness
];
services.dunst = {
enable = true;
iconTheme = {
inherit (config.gtk.iconTheme) name package;
size = "24x24";
};
settings = with theme; {
global = {
background = "#${base}";
foreground = "#${text}";
highlight = "#${lavender}";
frame_color = "#${peach}";
separator_color = "frame";
corner_radius = 10;
offset = "10x50";
font = "Inter 11";
dmenu = "${pkgs.fuzzel}/bin/fuzzel -d";
browser = "${pkgs.xdg-utils}/bin/xdg-open";
};
volume_tag = {
stack_tag = "${volumeTag}";
history_ignore = true;
};
brightness_tag = {
stack_tag = "${brightnessTag}";
history_ignore = true;
};
urgency_critical.frame_color = "#${yellow}";
};
};
});
}

View file

@ -0,0 +1,212 @@
{ pkgs, lib, config, inputs, ... }:
let
cfg = config.my.graphical.emacs;
in {
options.my.graphical.emacs = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable (let
inherit (inputs.emacs-overlay.overlays.package null pkgs) emacsPackagesFor;
extraEpkgsMap = epkgs: extraEpkgList: map (extraEpkg: extraEpkg epkgs) extraEpkgList;
org-modern-indent = epkgs: epkgs.trivialBuild rec {
pname = "org-modern-indent";
version = "f2b859bc53107b2a1027b76dbf4aaebf14c03433";
src = pkgs.fetchFromGitHub {
owner = "jdtsmith";
repo = pname;
rev = version;
hash = "sha256-vtbaa3MURnAI1ypLueuSfgAno0l51y3Owb7g+jkK6JU=";
};
propagatedUserEnvPkgs = with epkgs; [ compat ];
buildInputs = propagatedUserEnvPkgs;
};
eglot-booster = epkgs: epkgs.trivialBuild rec {
pname = "eglot-booster";
version = "e19dd7ea81bada84c66e8bdd121408d9c0761fe6";
src = pkgs.fetchFromGitHub {
owner = "jdtsmith";
repo = pname;
rev = version;
hash = "sha256-vF34ZoUUj8RENyH9OeKGSPk34G6KXZhEZozQKEcRNhs=";
};
propagatedUserEnvPkgs = [];
};
extraPackages = epkgs: with epkgs; [
f
dash
dashboard
undo-fu
god-mode
multiple-cursors
expand-region
avy
lispy
ace-window
goggles
dtrt-indent
aggressive-indent
rainbow-delimiters
highlight-indent-guides
which-key
eglot-java
yasnippet
yasnippet-snippets
consult
consult-yasnippet
embark
embark-consult
orderless
marginalia
vertico
corfu
cape
all-the-icons
all-the-icons-completion
treemacs
treemacs-all-the-icons
doom-modeline
minions
dirvish
pdf-tools
engrave-faces
org-modern
djvu
nov
org-pdftools
org-alert
editorconfig
envrc
sly
sly-asdf
sly-named-readtables
racket-mode
haskell-mode
lua-mode
nix-mode
gdscript-mode
markdown-mode
csv-mode
meson-mode
jinx
minimap
magit
forge
eat
mpv
lingva
mastodon
circe
circe-notifications
elfeed
xkcd
page-break-lines
hl-todo
ligature
gruvbox-theme
catppuccin-theme
solaire-mode
with-editor
nyan-mode
mu4e
org-msg
emacs-everywhere
treesit-grammars.with-all-grammars
] ++ extraEpkgsMap epkgs [
eglot-booster
org-modern-indent
];
alternateEmacsclient = pkgs.writeShellScript "alternate-emacsclient" ''
${pkgs.systemd}/bin/systemctl --user start emacs.service && \
exec ${config.programs.emacs.finalPackage}/bin/emacsclient -c -a "" "$@"
'';
in {
programs.emacs = {
enable = true;
package = (emacsPackagesFor pkgs.emacs29-pgtk).emacsWithPackages extraPackages;
};
services.emacs = {
enable = true;
startWithUserSession = "graphical";
};
home = {
sessionVariables.ALTERNATE_EDITOR = alternateEmacsclient;
packages = with pkgs; [
emacs-lsp-booster
emacs-all-the-icons-fonts
gdb
clang-tools
nil
nodePackages.typescript-language-server
ghc
stylish-haskell
haskell-language-server
hunspellDicts.en-us
imagemagick
(texlive.combine {
inherit (texlive) scheme-basic
dvisvgm dvipng # Preview and export as html
wrapfig amsmath ulem hyperref capt-of
# Export code with engraved backend
fvextra etoolbox fancyvrb upquote lineno
tcolorbox pgf environ pdfcol
xcolor float
nopageno;
})
pandoc
];
file.".clang-format".text = ''
---
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: Always
...
'';
};
xdg.desktopEntries = let
extendDefault = lib.recursiveUpdate {
icon = "emacs";
terminal = false;
type = "Application";
settings.Keywords = "emacsclient;";
actions = {
new-window.name = "New Window";
new-instance.name = "New Instance";
};
};
in {
emacsclient = extendDefault rec {
name = "Emacs (Client)";
exec = "${config.programs.emacs.finalPackage}/bin/emacsclient -a ${alternateEmacsclient} -c %F";
genericName = "Text Editor";
comment = "Edit text";
mimeType = ["text/english" "text/plain" ];
categories = [ "Development" "TextEditor" ];
startupNotify = true;
settings.StartupWMClass = "Emacs";
actions = {
new-window = {inherit exec;};
new-instance.exec = "${config.programs.emacs.finalPackage}/bin/emacs %F";
};
};
emacsclient-mail = extendDefault rec {
name = "Emacs (Mail, Client)";
exec = (pkgs.writeShellScript "emacsclient-mail" ''
u=''${1//\\/\\\\}
u=''${u//\"/\\\"}
exec ${config.programs.emacs.finalPackage}/bin/emacsclient -a ${alternateEmacsclient} -c \
--eval "(message-mailto \"$u\")"
'') + " %u";
comment = "GNU Emacs is an extensible, customizable text editor - and more";
mimeType = [ "x-scheme-handler/mailto" ];
noDisplay = true;
actions = {
new-window = {inherit exec;};
new-instance.exec = "${config.programs.emacs.finalPackage}/bin/emacs -f message-mailto %u";
};
};
};
});
}

View file

@ -0,0 +1,140 @@
{ pkgs, config, lib, self, ... }:
let
cfg = config.my.graphical.firefox;
in {
options.my.graphical.firefox = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
programs.firefox = {
enable = true;
policies = {
DisableFirefoxStudies = true;
DisablePocket = true;
DisableFirefoxAccounts = true;
DisableProfileImport = true;
DisplayBookmarksToolbar = "never";
NoDefaultBookmarks = true;
OfferToSaveLogins = false;
DontCheckDefaultBrowser = true;
UserMessaging = {
ExtensionRecommendations = false;
SkipOnboarding = true;
};
ExtensionSettings = let
mozillaExtensions = {
buster-captcha-solver = "{e58d3966-3d76-4cd9-8552-1582fbc800c1}";
clearurls = "{74145f27-f039-47ce-a470-a662b129930a}";
search_by_image = "{2e5ff8c8-32fe-46d0-9fc8-6b8986621f3c}";
styl-us = "{7a7a4a92-a2a0-41d1-9fd7-1e92480d612d}";
traduzir-paginas-web = "{036a55b4-5e72-4d05-a06c-cba2dfcc134a}";
violentmonkey = "{aecec67f-0d10-4fa7-b7c7-609a2db280cf}";
indie-wiki-buddy = "{cb31ec5d-c49a-4e5a-b240-16c767444f62}";
sponsorblock = "sponsorBlocker@ajay.app";
tabcenter-reborn = "tabcenter-reborn@ariasuni";
ublock-origin = "uBlock0@raymondhill.net";
firefox-color = "FirefoxColor@mozilla.com";
} // lib.optionalAttrs config.my.keepassxc.enable {
keepassxc-browser = "keepassxc-browser@keepassxc.org";
};
in builtins.mapAttrs (_: url: {
install_url = url;
installation_mode = "force_installed";
}) (lib.mapAttrs' (name: id:
lib.nameValuePair id "https://addons.mozilla.org/firefox/downloads/latest/${name}/latest.xpi"
) mozillaExtensions);
};
profiles.errie = {
settings = {
"browser.aboutConfig.showWarning" = false;
"browser.cache.disk.enable" = false;
"browser.cache.memory.capacity" = 2000000;
"browser.ctrlTab.sortByRecentlyUsed" = false;
"browser.newtabpage.activity-stream.feeds.section.topstories" = false;
"browser.newtabpage.activity-stream.feeds.topsites" = false;
"browser.newtabpage.pinned" = [];
"browser.startup.page" = 3;
"cookiebanners.service.mode" = 1;
"cookiebanners.service.mode.privateBrowsing" = 1;
"devtools.selfxss.count" = 100;
"media.ffmpeg.vaapi.enabled" = true;
"privacy.webrtc.legacyGlobalIndicator" = false;
"toolkit.legacyUserProfileCustomizations.stylesheets" = true;
"ui.key.menuAccessKeyFocuses" = false;
"widget.wayland.fractional-scale.enabled" = true;
};
search = {
default = "DuckDuckGo";
force = true;
order = [ "DuckDuckGo" "SearXNG" "Google" ];
engines = {
"SearXNG" = {
definedAliases = [ "@searxng" ];
icon = "${self}/assets/searxng.svg";
urls = [{
template = "https://etsi.me/search";
params = [{
name = "q";
value = "{searchTerms}";
}];
}];
};
"Nix Packages" = {
definedAliases = [ "@pkgs" "@nixpkgs" ];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
urls = [{
template = "https://search.nixos.org/packages";
params = [
{
name = "channel";
value = "unstable";
}
{
name = "type";
value = "packages";
}
{
name = "query";
value = "{searchTerms}";
}
];
}];
};
"Hoogle" = {
definedAliases = [ "@hoogle" ];
urls = [{
template = "https://hoogle.haskell.org/";
params = [{
name = "hoogle";
value = "{searchTerms}";
}];
}];
};
} // lib.genAttrs [ "Bing" "Amazon.com" "eBay" ] (_: {metaData.hidden = true;});
};
userChrome = let
verticalTabs = pkgs.fetchzip {
url = "https://codeberg.org/ranmaru22/firefox-vertical-tabs/archive/v6.5.tar.gz";
hash = "sha256-DHI8QFr4z00tlS8SlWrrNymP6pRQ55YHq6ZegDx5iYk=";
};
in ''
@import url("file://${verticalTabs}/userChrome.css");
/* Hide the close button */
.titlebar-buttonbox-container,
.titlebar-spacer[type="post-tabs"]
{
display: none !important;
}
/* Remove padding on the right */
#nav-bar {
--uc-navbar-padding: 0;
}
'';
};
};
};
}

View file

@ -0,0 +1,29 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.keepassxc;
in {
options.my.keepassxc = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
home.packages = [ pkgs.keepassxc ];
systemd.user.services.keepassxc = {
Unit = {
Description = "KeePassXC password manager";
After = [ "graphical-session-pre.target" "tray.target" "eww-bar.service" ];
PartOf = [ "graphical-session.target" ];
Requires = [ "tray.target" ];
};
Service = {
ExecStart = "${pkgs.keepassxc}/bin/keepassxc";
Environment = "QT_QPA_PLATFORM=wayland";
};
Install = {
WantedBy = [ "graphical-session.target" ];
};
};
};
}

View file

@ -0,0 +1,28 @@
{ config, lib, ... }:
let
cfg = config.my.graphical.kitty;
in {
options.my.graphical.kitty = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
programs.kitty = {
enable = true;
theme = "Catppuccin-Mocha";
font = {
name = "JetBrainsMono Nerd Font";
size = 11;
};
keybindings = {
"ctrl+backspace" = "send_text all \\x1b\\x7f";
};
settings = {
window_margin_width = 5;
focus_follows_mouse = "yes";
shell_integration = "no-cursor";
};
};
};
}

View file

@ -0,0 +1,23 @@
{ config, lib, ... }:
let
cfg = config.my.graphical.mangohud;
in {
options.my.graphical.mangohud = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
programs.mangohud = {
enable = true;
enableSessionWide = true;
settings = {
no_display = true;
vsync = 0;
full = true;
output_folder = "${config.xdg.cacheHome}/mangohud";
toggle_hud = "Shift_R+BackSpace";
};
};
};
}

View file

@ -0,0 +1,38 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.graphical.mpv;
in {
options.my.graphical.mpv = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
programs.mpv = {
enable = true;
scripts = with pkgs.mpvScripts; [
mpris
sponsorblock
thumbfast
uosc
];
bindings = {
tab = "script-binding uosc/flash-ui";
};
config = {
ao = "pipewire,";
osd-bar = false;
border = false;
};
scriptOpts = {
uosc = {
top_bar_controls = false;
top_bar_title = "\${media-title}";
top_bar_alt_title = "\${filename}";
top_bar_alt_title_place = "below";
};
thumbfast.hwdec = true;
};
};
};
}

View file

@ -0,0 +1,20 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.graphical.obs;
in {
options.my.graphical.obs = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
programs.obs-studio = {
enable = true;
plugins = with pkgs.obs-studio-plugins; [
wlrobs
obs-vkcapture
obs-vaapi
];
};
};
}

View file

@ -0,0 +1,67 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.graphical;
in {
options.my.graphical = {
qt.enable = lib.mkEnableOption null // {
default = true;
};
gtk = {
enable = lib.mkEnableOption null // {
default = true;
};
emacsKeys.enable = lib.mkEnableOption null;
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
(lib.mkIf cfg.qt.enable {
qt = {
enable = true;
platformTheme.name = "gtk3";
};
})
(lib.mkIf cfg.gtk.enable {
dconf.settings = {
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
gtk-key-theme = lib.mkIf (cfg.gtk.emacsKeys.enable) "Emacs";
};
};
gtk = {
enable = true;
font = {
package = pkgs.inter;
name = "Inter";
size = 11;
};
iconTheme = {
package = pkgs.catppuccin-papirus-folders.override {
flavor = "mocha";
accent = "lavender";
};
name = "Papirus-Dark";
};
theme = {
package = pkgs.catppuccin-gtk.override {
accents = [ "lavender" ];
size = "compact";
tweaks = [ "rimless" ];
variant = "mocha";
};
name = "catppuccin-mocha-lavender-compact+rimless";
};
} // lib.optionalAttrs cfg.gtk.emacsKeys.enable {
gtk2.extraConfig = ''
gtk-key-theme-name = "Emacs"
'';
gtk3.extraConfig = {
gtk-key-theme-name = "Emacs";
};
};
})
]);
}

View file

@ -0,0 +1,90 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.graphical.qutebrowser;
in {
options.my.graphical.qutebrowser = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable (let
mapLeader = "<Space>";
in {
programs.qutebrowser = {
enable = true;
package = (pkgs.qutebrowser.override {enableWideVine = true;}).overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs or [] ++ [ pkgs.makeWrapper ];
postInstall = old.postInstall or "" + ''
wrapProgram $out/bin/qutebrowser \
--unset QT_QPA_PLATFORMTHEME
'';
});
aliases = {
bN = "tab-prev";
bd = "tab-close";
bn = "tab-next";
bp = "tab-prev";
h = "help";
q = "close";
qa = "quit";
w = "session-save";
wq = "quit --save";
wqa = "quit --save";
so = "config-source";
"so%" = "config-source";
};
keyBindings = {
normal = {
"clc" = "set-cmd-text :open -t https://www.dl.cambridgescp.com/stage/clc/";
"<Ctrl+Shift+Tab>" = "tab-focus last";
"<Ctrl+Shift+Space>" = "edit-text";
"<Ctrl+d>" = "fake-key <PgDown>";
"<Ctrl+u>" = "fake-key <PgUp>";
"${mapLeader}<Space>" = ''
config-cycle statusbar.show in-mode always ;; \
config-cycle tabs.show switching always \
'';
};
insert = {
"<Ctrl+Shift+Space>" = "edit-text";
"<Ctrl+h>" = "fake-key <Backspace>";
"<Ctrl+w>" = "fake-key <Ctrl+Backspace>";
};
command."<Ctrl+w>" = "rl-backward-kill-word";
prompt."<Ctrl+w>" = "rl-backward-kill-word";
};
settings = {
changelog_after_upgrade = "patch";
auto_save = {
session = true;
interval = 15000;
};
editor = {
command = [
"/bin/sh" "-c"
''
emacsclient -e '(require '\"'\"'emacs-everywhere nil :noerror)' && \
emacsclient -c '+{line}:{column}' '{file}' \
''
];
remove_file = true;
};
content.pdfjs = true;
scrolling.smooth = true;
colors.webpage.preferred_color_scheme = "dark";
};
extraConfig = ''
import catppuccin
catppuccin.setup(c, 'mocha')
config.unbind('<Ctrl+w>')
config.unbind('<Ctrl+Shift+w>')
'';
};
xdg.configFile."qutebrowser/catppuccin".source = pkgs.fetchFromGitHub {
owner = "catppuccin";
repo = "qutebrowser";
rev = "6737f1c36a9d05be05b7961945e7028c0f70831f";
sha256 = "0nv214p0k292y2gr5afcjvxnjs1ai78vnxyb7qzj1r4vk7r3nh0k";
};
});
}

View file

@ -0,0 +1,38 @@
{ pkgs, config, lib, inputs, ... }:
let
cfg = config.my.graphical.wayland;
in {
imports = [
./eww
./hyprland.nix
./hyprlock.nix
./swaylock.nix
./swayidle.nix
./gammastep.nix
./kanshi.nix
./gestures.nix
./ydotool.nix
./foot.nix
./fuzzel.nix
];
options.my.graphical.wayland = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
home = {
packages = (with pkgs; [
wl-clipboard
grim
slurp
wev
gamescope
inputs.my-nix-packages.packages.${system}.geticons
]);
sessionVariables.NIXOS_OZONE_WL = "1";
};
};
}

View file

@ -0,0 +1,83 @@
{ pkgs, config, lib, self, theme, ... }:
let
cfg = config.my.graphical.wayland.eww;
in {
options.my.graphical.wayland.eww = {
enable = lib.mkEnableOption null;
};
config = let
inherit (pkgs) eww;
in lib.mkIf cfg.enable {
home.packages = [ eww ];
xdg.configFile = builtins.mapAttrs (name: src: {
source = pkgs.substituteAll ({
inherit src;
acpi = "${pkgs.acpi}/bin/acpi";
hyprctl = "${config.wayland.windowManager.hyprland.package}/bin/hyprctl";
ruby = "${pkgs.ruby}/bin/ruby";
soyjak = "${self}/assets/pointingSoyjaks.png";
} // theme);
target = "eww/${name}";
executable = builtins.match "\\./scripts/.*" name != null;
}) (self.lib.filterNixReadDir ./.) // {
"eww/_mocha.scss".text = builtins.concatStringsSep "\n"
(lib.mapAttrsToList (name: value: "\$${name}: #${value};") theme);
};
wayland.windowManager.hyprland.settings = let
inherit (config.my.graphical.wayland.hyprland) mainMod;
toggleSoyjaks = pkgs.writeShellScript "toggle-soyjaks" ''
if ${eww}/bin/eww active-windows | ${pkgs.gnugrep}/bin/grep -q 'soyjak-layer'; then
${eww}/bin/eww close soyjak-layer
else
${eww}/bin/eww open soyjak-layer
fi
'';
in {
bind = [
"${mainMod} CTRL, S, exec, ${toggleSoyjaks}"
];
};
systemd.user = {
services = {
eww = {
Unit = {
Description = "Eww background daemon";
partOf = [ "tray.target" ];
};
Service = {
Environment = "PATH=${lib.makeBinPath (with pkgs; [ coreutils bash ])}";
ExecStart = "${eww}/bin/eww daemon --no-daemonize";
};
Install = {
WantedBy = [ "tray.target" ];
};
};
eww-bar = {
Unit = {
Description = "Eww bar";
After = "eww.service";
};
Service = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "eww-bar-open" ''
# Lack of quotes intentional
exec ${eww}/bin/eww open-many \
$(${config.wayland.windowManager.hyprland.package}/bin/hyprctl monitors -j | \
${pkgs.jaq}/bin/jaq -r '.[] | .id' | \
${pkgs.gnused}/bin/sed 's/^/bar/')
'';
};
Install = {
WantedBy = [ "eww.service" ];
};
};
};
};
};
}

View file

@ -0,0 +1,98 @@
@import "mocha";
button, menubar, menubar > menuitem {
all: unset;
}
.bar-wrap > * {
border-radius: 10px;
margin: 10px;
}
.bar-main {
font-family: "Jost";
font-size: 16px;
background-color: $base;
color: $text;
}
.workspaces > button {
border-style: solid;
border-width: 6px 0 0 0;
&:hover {
background-color: $surface0;
}
&.nonexistent {
border-color: transparent;
}
&.existing {
border-color: $surface1;
&:hover {
border-color: $overlay1;
}
}
&.active {
border-color: $rosewater;
}
}
.title {
font-size: 14px;
}
.bar-end > * {
margin-right: 30px;
}
.tray > menuitem {
margin-right: 15px;
& menu {
background-color: $mantle;
}
}
@mixin battery-color($property) {
#{$property}: $text;
.battery-low & {
#{$property}: $red;
}
}
.battery-tip {
@include battery-color(background-color);
}
.battery-box {
border-style: solid;
border-width: 2px;
@include battery-color(border-color);
}
.battery-val {
margin: 2px;
@include battery-color(background-color);
.battery-charging & {
background-color: $green;
}
}
.power {
font-family: "Jetbrains Mono Nerd Font";
font-size: 30px;
color: $red;
transition: color, background-color 0.15s;
&:hover {
background-color: $red;
color: $base;
}
}
tooltip {
color: $text;
background-color: rgba($crust, 1);
border-radius: 7px;
}
.soyjak-layer {
background-color: transparent;
}

View file

@ -0,0 +1,149 @@
;;; Eww config
(defpoll time
:interval "5s"
"date '+%l:%M %p'")
(defpoll date
:interval "1m"
"date '+%D'")
(defpoll acpi
:interval "20s"
:initial ""
"@acpi@ -b")
(deflisten hyprlisten
:initial "{
\"workspaces\": ${jq(10, `[{active: false, existing: false, id: range(.) + 1}]`)},
\"title\": \"\"
}"
"scripts/hyprlisten.rb")
(defwindow bar0
:monitor 0
:geometry (geometry :height "42px"
:width "1920px"
:anchor "top center")
:stacking "fg"
(bar))
(defwindow bar1
:monitor 1
:geometry (geometry :height "42px"
:width "100%"
:anchor "top center")
:stacking "fg"
(bar))
(defwindow bar2
:monitor 2
:geometry (geometry :height "42px"
:width "100%"
:anchor "top center")
:stacking "fg"
(bar))
(defwidget bar-wrap []
(box :class "bar-wrap"
:orientation "h"
(bar)))
(defwidget bar []
(box :class "bar-main"
:orientation "h"
(bar-start)
(bar-center)
(bar-end)))
(defwidget bar-start []
(box :class "bar-start"
:orientation "h"
:halign "start"
:space-evenly false
(workspaces)))
(defwidget bar-center []
(box :class "bar-center"
:orientation "h"
:halign "center"
(title)))
(defwidget bar-end []
(box :class "bar-end"
:orientation "h"
:halign "end"
:space-evenly false
(tray)
(battery)
(time)))
(defwidget workspaces []
(eventbox
:onscroll "@hyprctl@ dispatch focusworkspaceoncurrentmonitor e$([ \"{}\" = \"up\" ] && echo '-' || echo '+')1"
(box :class "workspaces"
:orientation "h"
:halign "start"
(for workspace in {hyprlisten.workspaces}
(button :class "${workspace.active ? 'active' :
(workspace.existing ? 'existing' : 'nonexistent')}"
:width 42
:height 42
:tooltip "Switch to Workspace ${workspace.id}"
:onclick "@hyprctl@ dispatch focusworkspaceoncurrentmonitor ${workspace.id}"
{workspace.id})))))
(defwidget title []
(label :class "title"
:limit-width 70
:text {hyprlisten.title}))
(defwidget tray []
(systray :class "tray"
:icon-size 24
:prepend-new true
:spacing 6))
(defwidget battery []
(box :class "battery ${EWW_BATTERY.BAT1.status == 'Charging' ? 'battery-charging' :
(EWW_BATTERY.BAT1.capacity <= 20 ? 'battery-low' : '')}"
:orientation "h"
:tooltip acpi
(box :class "battery-box"
:valign "center"
:width 28
:height 14
(box :class "battery-val"
:halign "start"
:width {4 + round (EWW_BATTERY.BAT1.capacity / 5 , 0)}))
(box :class "battery-tip"
:halign "start"
:valign "center"
:width 3
:height 6)))
(defwidget time []
(box :class "time"
:tooltip date
time))
(defwidget power []
(eventbox :class "power"
:width 42
:cursor "pointer"
:onclick "wlogout -p layer-shell &"
:tooltip "Logout options"
"襤"))
(defwindow soyjak-layer
:monitor 0
:geometry (geometry :width "100%"
:height "100%"
:anchor "bottom left")
:stacking "overlay"
(soyjak))
(defwidget soyjak []
(image :path "@soyjak@"
:image-width 1920
:image-height 1080))

View file

@ -0,0 +1,75 @@
#!@ruby@
# frozen_string_literal: true
require 'socket'
require 'json'
$stdout.sync = true
SOCK_DIR = "#{ENV['XDG_RUNTIME_DIR']}/hypr/#{ENV['HYPRLAND_INSTANCE_SIGNATURE']}"
SOCK1 = "#{SOCK_DIR}/.socket.sock"
SOCK2 = "#{SOCK_DIR}/.socket2.sock"
def hyprctl(cmd)
Socket.unix(SOCK1) do |s|
s.print cmd
s.read.force_encoding('UTF-8')
end
end
class Workspaces
attr_reader :data
def initialize
@active = JSON.parse(hyprctl('j/monitors')).detect { |m| m['focused'] }['activeWorkspace']['id']
existing = JSON.parse(hyprctl('j/workspaces')).to_h { |w| [w['id'], true] }
@data = (1..9).map { |id| {id: id, active: id == @active, existing: !!existing[id]} }
end
def update_active(workspace)
workspace = workspace.to_i
update_val(@active, active: false)
update_val(workspace, active: true)
@active = workspace
end
def update_val(workspace, **kwargs)
@data[workspace - 1].merge!(kwargs) if workspace.between?(1, 9)
end
end
class State
def initialize(**kwargs)
@data = kwargs
end
def update(**kwargs)
@data.merge!(kwargs)
end
def to_s
JSON.fast_generate(@data)
end
end
Socket.unix(SOCK2) do |socket|
ws = Workspaces.new
state = State.new(
title: JSON.parse(hyprctl('j/activewindow'))['title'] || '',
workspaces: ws.data,
)
puts state
while (line = socket.gets)
event, data = line.split('>>', 2)
case event
when 'activewindow' then state.update(title: data.chomp.split(',', 2).last)
when 'closewindow' then state.update(title: '')
when 'workspace' then ws.update_active(data.chomp)
when 'focusedmon' then ws.update_active(data.chomp.split(',', 2).last)
when 'createworkspace' then ws.update_val(data.chomp.to_i, existing: true)
when 'destroyworkspace' then ws.update_val(data.chomp.to_i, existing: false)
else next
end
puts state
end
end

View file

@ -0,0 +1,51 @@
{ config, lib, theme, ... }:
let
cfg = config.my.graphical.wayland.foot;
in {
options.my.graphical.wayland.foot = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable (let
loweredTheme = builtins.mapAttrs (_: lib.toLower) theme;
in {
programs.foot = {
enable = true;
settings = {
main = {
font = "JetbrainsMono Nerd Font:size=11";
pad = "5x5 center";
};
scrollback = {
indicator-position = "fixed";
indicator-format = "percentage";
};
cursor.color = with loweredTheme; "${base} ${rosewater}";
text-bindings = {
"\\x1b\\x7f" = "Control+BackSpace";
};
colors = with loweredTheme; rec {
foreground = text;
background = base;
regular0 = surface1;
regular1 = red;
regular2 = green;
regular3 = yellow;
regular4 = blue;
regular5 = pink;
regular6 = teal;
regular7 = subtext1;
bright0 = regular0;
bright1 = regular1;
bright2 = regular2;
bright3 = regular3;
bright4 = regular4;
bright5 = regular5;
bright6 = regular6;
bright7 = regular7;
};
};
};
});
}

View file

@ -0,0 +1,46 @@
{ pkgs, config, lib, theme, ... }:
let
cfg = config.my.graphical.wayland.fuzzel;
in {
options.my.graphical.wayland.fuzzel = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
home.packages = [ pkgs.fuzzel ];
xdg.configFile."fuzzel/fuzzel.ini".text = lib.generators.toINI { } {
main = {
font = "DejaVu Sans Mono:size=13";
icon-theme = "Papirus-Dark";
show-actions = true;
terminal = "${config.programs.foot.package}/bin/foot -e";
width = 80;
horizontal-pad = 60;
vertical-pad = 30;
inner-pad = 20;
line-height = 24;
};
colors = builtins.mapAttrs (_: val: "${val}FF") (with theme; {
background = mantle;
text = overlay2;
match = lavender;
selection = surface0;
selection-text = text;
selection-match = mauve;
border = mauve;
});
key-bindings = {
cursor-left = "Left Control+b Mod1+h";
cursor-right = "Right Control+f Mod1+l";
delete-prev = "BackSpace Control+h";
delete-prev-word = "Mod1+BackSpace Control+BackSpace Control+w";
prev = "Up Control+p Mod1+k";
prev-page = "KP_Prior Mod1+v";
next = "Down Control+n Mod1+j";
next-page = "KP_Next Control+v";
};
border.width = 3;
};
};
}

View file

@ -0,0 +1,26 @@
{ config, lib, ... }:
let
cfg = config.my.graphical.wayland.gammastep;
in {
options.my.graphical.wayland.gammastep = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
services.gammastep = {
enable = true;
provider = "geoclue2";
temperature = {
day = 6500;
night = 2750;
};
settings = {
general = {
fade = 1;
adjustment-method = "wayland";
};
};
};
};
}

View file

@ -0,0 +1,29 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.graphical.wayland.gestures;
in {
options.my.graphical.wayland.gestures = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
xdg.configFile = let
serviceName = "libinput-gestures.service";
service = "${pkgs.libinput-gestures}/share/systemd/user/${serviceName}";
in {
"systemd/user/${serviceName}".source = service;
"systemd/user/hyprland-session.target.wants/${serviceName}".source = service;
"libinput-gestures.conf" = {
text = let
hyprctl = "${config.wayland.windowManager.hyprland.package}/bin/hyprctl";
in ''
gesture pinch in 4 ${hyprctl} dispatch killactive
'';
onChange = ''
${pkgs.systemd}/bin/systemctl --user restart ${serviceName}
'';
};
};
};
}

View file

@ -0,0 +1,445 @@
{ pkgs, inputs, config, lib, self, osConfig, theme, ... }:
let
cfg = config.my.graphical.wayland.hyprland;
in {
options.my.graphical.wayland.hyprland = {
enable = lib.mkEnableOption null;
tearing = lib.mkEnableOption null;
mainMod = lib.mkOption {
type = lib.types.str;
default = "SUPER";
};
lockBinary = lib.mkOption {
type = lib.types.str;
};
wallpaper = {
enable = lib.mkEnableOption null // {
default = true;
};
backend = lib.mkOption {
type = lib.types.enum [ "hyprpaper" "swaybg" ];
default = "swaybg";
};
image = lib.mkOption {
type = lib.types.pathInStore;
default = "${self}/assets/snowyMountain.jpg";
};
};
};
config = lib.mkIf cfg.enable (let
toggleOption = pkgs.writeShellScriptBin "hypr-toggle-opt" ''
hyprctl keyword "$1" "$(hyprctl getoption "$1" -j | ${pkgs.jaq}/bin/jaq '1 - .int')"
'';
copyOutput = pkgs.writeShellScript "hypr-copy-output" ''
MONITOR="$(hyprctl monitors -j | ${pkgs.jaq}/bin/jaq -r '.[] | select(.focused).name')"
grim -o "$MONITOR" - | wl-copy -t image/png
'';
copyWindow = pkgs.writeShellScript "hypr-copy-window" ''
WINDOW="$(hyprctl activewindow -j | ${pkgs.jaq}/bin/jaq -r '.address')"
grim -w "$WINDOW" - | wl-copy -t image/png
'';
winShiftS = with pkgs; writeShellScriptBin "win-shift-s" ''
FILENAME="/tmp/win-shift-s-$PPID.png"
MONITOR="$(hyprctl monitors -j | ${_ jaq} -r '.[] | select(.focused)')"
${_ grim} -o "$(${_ jaq} -r '.name' <<< "$MONITOR")" "$FILENAME"
${_ imv} -f "$FILENAME" & IMV_PROC=$!
DIMENSIONS="$(${_ slurp} -f '%wx%h+%X+%Y')"
[ "$?" -eq 0 ] && \
${_ imagemagick} "$FILENAME" -crop "$DIMENSIONS" - | \
${wl-clipboard}/bin/wl-copy -t image/png
kill $IMV_PROC
exec rm "$FILENAME"
'';
timeWindow = let
inherit (inputs.cl-hyprland-ipc.packages.${pkgs.system}) cl-hyprland-ipc;
inherit (cl-hyprland-ipc) asdfFasl faslExt;
sbclWithPackages = pkgs.sbcl.withPackages (_: [ cl-hyprland-ipc ]);
in pkgs.runCommand "time-window" { } ''
${sbclWithPackages}/bin/sbcl --load ${asdfFasl}/asdf.${faslExt} \
--load ${../../scripts/time-window.lisp} \
--eval '(setf uiop:*image-entry-point* #'\''\''time-window:main)' \
--eval '(uiop:dump-image "time-window" :executable t :compression t)'
mkdir -p $out/bin
cp time-window $out/bin
'';
in {
home.packages = [
toggleOption
timeWindow
];
wayland.windowManager.hyprland = let
c = builtins.mapAttrs (_: t: "0xFF${t}") theme;
inherit (cfg) mainMod;
activeBorder = "${c.peach} ${c.mauve} 45deg";
transparent = "0x00000000";
in {
enable = true;
package = osConfig.programs.hyprland.package;
settings = {
exec-once = lib.optional (!osConfig.my.fs.luks.enable) "${pkgs.writeShellScript "start-hyprland" ''
[ -n "$GREETD_SOCK" ] && ${pkgs.swaylock-effects}/bin/swaylock ${
lib.optionalString cfg.wallpaper.enable "-i ${cfg.wallpaper.image}"
} &
''}";
env = [ ]
++ lib.optional config.my.graphical.emacs.enable "VISUAL, emacsclient -c";
monitor = [
"eDP-1, preferred, 0x0, 1.33"
", preferred, auto, 1"
# Manually reserved area for bar
", addreserved, 42, 0, 0, 0"
];
input = {
kb_layout = "us";
repeat_delay = 300;
repeat_rate = 20;
float_switch_override_focus = 2;
touchpad = {
natural_scroll = true;
scroll_factor = 0.3;
};
};
general = {
layout = "dwindle";
allow_tearing = cfg.tearing;
gaps_in = 5;
gaps_out = 13;
border_size = 3;
"col.active_border" = activeBorder;
"col.inactive_border" = transparent;
};
dwindle = {
force_split = 2;
preserve_split = true;
no_gaps_when_only = 1;
special_scale_factor = 0.9;
};
decoration = {
rounding = 11;
dim_special = 0;
drop_shadow = false;
blur = {
enabled = false;
size = 8;
passes = 2;
ignore_opacity = true;
xray = true;
noise = 0;
contrast = 1;
brightness = 1;
};
};
group = {
"col.border_active" = activeBorder;
"col.border_inactive" = transparent;
"col.border_locked_active" = c.red;
"col.border_locked_inactive" = transparent;
groupbar = {
render_titles = false;
height = 3;
"col.active" = c.green;
"col.inactive" = transparent;
"col.locked_active" = c.red;
"col.locked_inactive" = transparent;
};
};
animations = {
enabled = true;
bezier = [
"easeInSine, 0.12, 0, 0.39, 0"
"easeOutSine, 0.61, 1, 0.88, 1"
];
animation = [
"windowsIn, 1, 3, easeOutSine, slide"
"windowsOut, 1, 3, easeInSine, slide"
"windowsMove, 1, 2.5, easeOutSine, slide"
"workspaces, 1, 2.5, easeOutSine, slide"
"specialWorkspace, 1, 6, default, slidevert"
"fade, 0"
];
};
gestures = {
workspace_swipe = true;
};
binds = {
allow_workspace_cycles = true;
};
xwayland = {
use_nearest_neighbor = false;
force_zero_scaling = true;
};
misc = {
vrr = 1;
disable_hyprland_logo = true;
disable_splash_rendering = true;
background_color = c.crust;
disable_autoreload = true;
focus_on_activate = true;
animate_manual_resizes = false;
animate_mouse_windowdragging = false;
new_window_takes_over_fullscreen = 2;
enable_swallow = false;
swallow_regex = "^(foot(client)?|kitty)$";
};
windowrule = [
"tile, ^(Aseprite)$"
"fullscreen, ^(Baba Is You|ADanceOfFireAndIce)$"
"float, ^(EverestSplash-linux)$"
"float, title:^(emacs-everywhere)$"
] ++ lib.optional cfg.tearing
"immediate, ^(ADanceOfFireAndIce|Celeste|hollow_knight\\.x86_64|portal2_linux)$";
windowrulev2 = [
"float, class:^(firefox)$, title:^(Picture-in-Picture)$"
"pin, class:^(firefox)$, title:^(Picture-in-Picture)$"
"tile, class:^(Spotify)$, title:^(?!Ozone X11$).*$"
"float, class:^(Spotify)$, title:^$"
];
bind = [
"${mainMod}, Return, exec, foot"
"${mainMod}, C, killactive,"
"${mainMod} SHIFT, C, exec, hyprctl activewindow -j | ${pkgs.jaq}/bin/jaq -r '.pid' | xargs kill -9"
"${mainMod}, E, exec, thunar"
"${mainMod}, M, exec, emacsclient -c"
"${mainMod} SHIFT, M, exec, emacsclient -e '(emacs-everywhere)'"
"${mainMod} SHIFT, Return, togglefloating,"
"${mainMod}, Space, fullscreen, 1"
"${mainMod} SHIFT, Space, fullscreen, 0"
"${mainMod}, I, exec, dunstctl action"
"${mainMod} SHIFT, I, exec, dunstctl context"
"${mainMod} ALT, I, exec, dunstctl history-pop"
"${mainMod} CTRL, I, exec, dunstctl close"
"${mainMod}, Semicolon, exec, killall fuzzel || fuzzel"
"${mainMod}, Y, pin,"
# Groups
"${mainMod}, F, changegroupactive, f"
"${mainMod} SHIFT, F, togglegroup,"
"${mainMod} CTRL, F, lockactivegroup, toggle"
# Directions
"${mainMod}, Period, layoutmsg, preselect r"
"${mainMod}, Comma, layoutmsg, preselect d"
"${mainMod}, S, layoutmsg, togglesplit"
# Moving windows (with groups)
"${mainMod} SHIFT, left, movewindoworgroup, l"
"${mainMod} SHIFT, right, movewindoworgroup, r"
"${mainMod} SHIFT, up, movewindoworgroup, u"
"${mainMod} SHIFT, down, movewindoworgroup, d"
"${mainMod} SHIFT, H, movewindoworgroup, l"
"${mainMod} SHIFT, L, movewindoworgroup, r"
"${mainMod} SHIFT, K, movewindoworgroup, u"
"${mainMod} SHIFT, J, movewindoworgroup, d"
# Moving windows (without groups)
"${mainMod} ALT, left, movewindow, l"
"${mainMod} ALT, right, movewindow, r"
"${mainMod} ALT, up, movewindow, u"
"${mainMod} ALT, down, movewindow, d"
"${mainMod} ALT, H, movewindow, l"
"${mainMod} ALT, L, movewindow, r"
"${mainMod} ALT, K, movewindow, u"
"${mainMod} ALT, J, movewindow, d"
# Workspaces
"${mainMod} CTRL, P, focusworkspaceoncurrentmonitor, previous"
"${mainMod} CTRL, N, focusworkspaceoncurrentmonitor, empty"
"${mainMod} CTRL SHIFT, P, movetoworkspace, previous"
"${mainMod} CTRL SHIFT, N, movetoworkspace, empty"
# Screenshot
", Print, exec, ${copyOutput}"
"ALT, Print, exec, ${copyWindow}"
"${mainMod} SHIFT, S, exec, grim -g \"$(slurp)\" - | wl-copy -t image/png"
# Move focus
"${mainMod}, left, movefocus, l"
"${mainMod}, right, movefocus, r"
"${mainMod}, up, movefocus, u"
"${mainMod}, down, movefocus, d"
"${mainMod}, H, movefocus, l"
"${mainMod}, L, movefocus, r"
"${mainMod}, K, movefocus, u"
"${mainMod}, J, movefocus, d"
# Switch workspaces with mainMod + [1-9]
"${mainMod}, 1, focusworkspaceoncurrentmonitor, 1"
"${mainMod}, 2, focusworkspaceoncurrentmonitor, 2"
"${mainMod}, 3, focusworkspaceoncurrentmonitor, 3"
"${mainMod}, 4, focusworkspaceoncurrentmonitor, 4"
"${mainMod}, 5, focusworkspaceoncurrentmonitor, 5"
"${mainMod}, 6, focusworkspaceoncurrentmonitor, 6"
"${mainMod}, 7, focusworkspaceoncurrentmonitor, 7"
"${mainMod}, 8, focusworkspaceoncurrentmonitor, 8"
"${mainMod}, 9, focusworkspaceoncurrentmonitor, 9"
# Switch workspaces with mainMod + N/P/O
"${mainMod}, N, focusworkspaceoncurrentmonitor, e+1"
"${mainMod}, P, focusworkspaceoncurrentmonitor, e-1"
"${mainMod} SHIFT, N, movetoworkspace, e+1"
"${mainMod} SHIFT, P, movetoworkspace, e-1"
# Move active window to a workspace with mainMod + SHIFT + [1-9]
"${mainMod} SHIFT, 1, movetoworkspace, 1"
"${mainMod} SHIFT, 2, movetoworkspace, 2"
"${mainMod} SHIFT, 3, movetoworkspace, 3"
"${mainMod} SHIFT, 4, movetoworkspace, 4"
"${mainMod} SHIFT, 5, movetoworkspace, 5"
"${mainMod} SHIFT, 6, movetoworkspace, 6"
"${mainMod} SHIFT, 7, movetoworkspace, 7"
"${mainMod} SHIFT, 8, movetoworkspace, 8"
"${mainMod} SHIFT, 9, movetoworkspace, 9"
# Scroll through existing workspaces with mainMod + scroll/side buttons
"${mainMod}, mouse_down, focusworkspaceoncurrentmonitor, e-1"
"${mainMod}, mouse_up, focusworkspaceoncurrentmonitor, e+1"
"${mainMod}, mouse:275, focusworkspaceoncurrentmonitor, e-1"
"${mainMod}, mouse:276, focusworkspaceoncurrentmonitor, e+1"
# Scratchpads
"${mainMod} SHIFT, 0, movetoworkspace, special:a"
"${mainMod}, 0, togglespecialworkspace, a"
"${mainMod} SHIFT, minus, movetoworkspace, special:b"
"${mainMod}, minus, togglespecialworkspace, b"
"${mainMod} SHIFT, equal, movetoworkspace, special:c"
"${mainMod}, equal, togglespecialworkspace, c"
"${mainMod}, T, exec, ${toggleOption}/bin/hypr-toggle-opt input:touchpad:disable_while_typing"
];
bindl = [
"${mainMod}, Q, exec, ${cfg.lockBinary}"
"${mainMod} ALT, Q, exec, killall ${cfg.lockBinary} .${cfg.lockBinary}-wrapped ; ${cfg.lockBinary}"
"${mainMod} SHIFT, Q, exit,"
", XF86AudioMute, exec, dunst-volume set-mute toggle"
];
binde = [
# Resize windows
"${mainMod} CTRL ALT, left, resizeactive, -10 0"
"${mainMod} CTRL ALT, right, resizeactive, 10 0"
"${mainMod} CTRL ALT, up, resizeactive, 0 -10"
"${mainMod} CTRL ALT, down, resizeactive, 0 10"
"${mainMod} CTRL ALT, H, resizeactive, -10 0"
"${mainMod} CTRL ALT, L, resizeactive, 10 0"
"${mainMod} CTRL ALT, K, resizeactive, 0 -10"
"${mainMod} CTRL ALT, J, resizeactive, 0 10"
# Move floating windows
"${mainMod} CTRL, left, moveactive, -50 0"
"${mainMod} CTRL, right, moveactive, 50 0"
"${mainMod} CTRL, up, moveactive, 0 -50"
"${mainMod} CTRL, down, moveactive, 0 50"
"${mainMod} CTRL, H, moveactive, -50 0"
"${mainMod} CTRL, L, moveactive, 50 0"
"${mainMod} CTRL, K, moveactive, 0 -50"
"${mainMod} CTRL, J, moveactive, 0 50"
];
bindm = [
# Move/resize windows with mainMod + LMB/RMB and dragging
"${mainMod}, mouse:272, movewindow"
"${mainMod}, mouse:273, resizewindow"
];
bindel = [
# Media keys
", XF86AudioRaiseVolume, exec, dunst-volume set-volume 5%+"
", XF86AudioLowerVolume, exec, dunst-volume set-volume 5%-"
", XF86MonBrightnessDown, exec, dunst-brightness 5%+"
", XF86MonBrightnessUp, exec, dunst-brightness 5%-"
];
};
extraConfig = ''
# Passthrough mode
bind = ${mainMod}, Escape, submap, passthrough
submap = passthrough
bind = ${mainMod}, Escape, submap, reset
submap = reset
# OBS
bind = ${mainMod} CTRL, O, submap, OBS
submap = OBS
bind = , Space, pass, ^(com\.obsproject\.Studio)$
bind = , P, pass, ^(com\.obsproject\.Studio)$
bind = , Escape, submap, reset
bind = ${mainMod}, Escape, submap, reset
submap = reset
'';
};
systemd.user.services = lib.mkIf cfg.wallpaper.enable {
hyprpaper = lib.mkIf (cfg.wallpaper.backend == "hyprpaper") {
Unit = {
Description = "Background wallpaper image via hyprpaper";
After = "hyprland-session.target";
};
Service = {
ExecStart = let
hyprpaperConfig = pkgs.writeText "hyprpaper.conf" ''
preload = ${cfg.wallpaper.image}
wallpaper = ,${cfg.wallpaper.image}
ipc = off
splash = off
'';
in "${pkgs.hyprpaper}/bin/hyprpaper -c ${hyprpaperConfig}";
};
Install = {
WantedBy = [ "hyprland-session.target" ];
};
};
swaybg = lib.mkIf (cfg.wallpaper.backend == "swaybg") {
Unit = {
Description = "Background wallpaper image via swaybg";
After = "hyprland-session.target";
};
Service = {
ExecStart = "${pkgs.swaybg}/bin/swaybg -i ${cfg.wallpaper.image} -m fill -o '*'";
};
Install = {
WantedBy = [ "hyprland-session.target" ];
};
};
};
});
}

View file

@ -0,0 +1,66 @@
{ pkgs, config, lib, self, theme, inputs, ... }:
let
cfg = config.my.graphical.wayland.hyprlock;
in {
options.my.graphical.wayland.hyprlock = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
programs.hyprlock = {
enable = true;
package = inputs.hyprlock.packages.${pkgs.system}.hyprlock;
settings = let
c = builtins.mapAttrs (_: t: "0xFF${t}") theme;
commaVals = x: y: "${builtins.toString x}, ${builtins.toString y}";
in {
general = {
hide_cursor = true;
};
background = lib.singleton {
path = "screenshot";
blur_size = 15;
blur_passes = 3;
};
input-field = lib.singleton {
fade_on_empty = false;
placeholder_text = "";
size = commaVals 350 70;
dots_size= 0.33;
outline_thickness = 5;
position = commaVals 0 (-100);
outer_color = c.mauve;
inner_color = c.crust;
font_color = c.text;
check_color = c.blue;
fail_color = c.red;
capslock_color = c.yellow;
numlock_color = c.yellow;
bothlock_color = c.yellow;
};
image = lib.singleton {
path = "${self}/assets/quag-head.png";
size = 180;
border_size = 5;
position = commaVals 0 80;
border_color = c.mauve;
};
};
};
my.graphical.wayland = {
ydotool.enable = true;
swayidle.lockCommand = "${config.programs.hyprlock.package}/bin/hyprlock --no-fade-in & sleep 0.3";
hyprland.lockBinary = "hyprlock";
};
wayland.windowManager.hyprland.settings.misc.allow_session_lock_restore = true;
};
}

View file

@ -0,0 +1,40 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.graphical.wayland.kanshi;
in {
options.my.graphical.wayland.kanshi = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
services.kanshi = {
enable = true;
systemdTarget = "hyprland-session.target";
profiles = {
undocked = {
outputs = [
{
criteria = "eDP-1";
status = "enable";
scale = 1.0;
}
];
};
docked = {
exec = "${pkgs.systemd}/bin/systemctl --user restart eww-bar.service";
outputs = [
{
criteria = "eDP-1";
status = "disable";
}
{
criteria = "HDMI-A-1";
status = "enable";
}
];
};
};
};
};
}

View file

@ -0,0 +1,41 @@
{ pkgs, config, lib, osConfig, ... }:
let
cfg = config.my.graphical.wayland.swayidle;
in {
options.my.graphical.wayland.swayidle = {
enable = lib.mkEnableOption null // {
default = osConfig.my.laptop.enable;
};
lockCommand = lib.mkOption {
type = lib.types.str;
};
};
config = lib.mkIf cfg.enable {
services.swayidle = {
enable = true;
systemdTarget = "hyprland-session.target";
timeouts = let
inherit (pkgs) brightnessctl acpi gnugrep systemd;
withBat = command: "${acpi}/bin/acpi -b | ${gnugrep}/bin/grep -q 'Discharging' && ${command}";
in [
{
timeout = 60;
command = withBat "${brightnessctl}/bin/brightnessctl -s s 0";
resumeCommand = withBat "${brightnessctl}/bin/brightnessctl -r";
}
{
timeout = 300;
command = withBat "${systemd}/bin/systemctl suspend";
}
];
events = [
{
event = "before-sleep";
command = cfg.lockCommand;
}
];
};
};
}

View file

@ -0,0 +1,75 @@
{ pkgs, config, lib, theme, ... }:
let
cfg = config.my.graphical.wayland.swaylock;
in {
options.my.graphical.wayland.swaylock = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
programs.swaylock = {
enable = true;
package = with pkgs; symlinkJoin {
name = "swaylock-effects-blur-flags";
paths = [ swaylock-effects ];
nativeBuildInputs = [ makeWrapper ];
postBuild = ''
wrapProgram $out/bin/swaylock \
--add-flags -S \
--add-flags --fade-in \
--add-flags 0.3 \
--add-flags --effect-blur \
--add-flags 15x3
'';
};
settings = with theme; {
indicator = true;
clock = true;
indicator-thickness = 6;
ignore-empty-password = true;
show-failed-attempts = true;
show-keyboard-layout = true;
indicator-caps-lock = true;
line-uses-inside = true;
key-hl-color = crust;
bs-hl-color = crust;
inside-caps-lock-color = yellow;
caps-lock-key-hl-color = yellow;
caps-lock-bs-hl-color = yellow;
text-caps-lock-color = crust;
ring-caps-lock-color = crust;
ring-ver-color = blue;
text-ver-color = blue;
ring-clear-color = yellow;
text-clear-color = yellow;
ring-wrong-color = red;
text-wrong-color = red;
inside-color = crust;
inside-ver-color = crust;
inside-clear-color = crust;
inside-wrong-color = crust;
ring-color = mauve;
text-color = rosewater;
layout-bg-color = mauve;
layout-text-color = crust;
};
};
my.graphical.wayland = {
swayidle.lockCommand = "${pkgs.swaylock-effects}/bin/swaylock -f -S --effect-blur 15x3";
hyprland.lockBinary = "swaylock";
};
wayland.windowManager.hyprland.settings.misc.allow_session_lock_restore = true;
};
}

View file

@ -0,0 +1,20 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.graphical.wayland.ydotool;
in {
options.my.graphical.wayland.ydotool = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
home.packages = [ pkgs.ydotool ];
xdg.configFile = let
serviceName = "ydotool.service";
service = "${pkgs.ydotool}/share/systemd/user/${serviceName}";
in {
"systemd/user/${serviceName}".source = service;
"systemd/user/default.target.wants/${serviceName}".source = service;
};
};
}

View file

@ -0,0 +1,19 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.graphical.zathura;
in {
options.my.graphical.zathura = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
home.packages = [ pkgs.zathura ];
xdg.configFile."zathura/zathurarc".source = pkgs.fetchFromGitHub {
owner = "catppuccin";
repo = "zathura";
rev = "1bda9d8274dd327b7931886ef0c5c1eb33903814";
hash = "sha256-HWOc5tnVgU/HUcVcIXACeuu3RDH1pHO/8DQRsWqumIA=";
} + "/src/catppuccin-mocha";
};
}

44
modules/home/mpd.nix Normal file
View file

@ -0,0 +1,44 @@
{ pkgs, config, lib, osConfig, ... }:
let
cfg = config.my.mpd;
in {
options.my.mpd = {
enable = lib.mkEnableOption null;
usePipewire = lib.mkEnableOption null // {
default = true;
};
ncmpcpp = {
enable = lib.mkEnableOption null;
};
};
config = lib.mkIf cfg.enable {
services.mpd = {
enable = true;
extraConfig = ''
restore_paused "yes"
zeroconf_enabled "no"
${lib.optionalString cfg.usePipewire ''
audio_output {
type "pipewire"
name "Pipewire Sound Server"
mixer_type "hardware"
replay_gain_handler "none"
}
''}
'';
};
home.packages = [ pkgs.mpc-cli ];
programs.ncmpcpp = lib.mkIf cfg.ncmpcpp.enable {
enable = true;
settings = {
mpd_host = "127.0.0.1";
mpd_port = config.services.mpd.network.port;
};
};
};
}

39
modules/home/nix.nix Normal file
View file

@ -0,0 +1,39 @@
{ config, lib, osConfig, ... }:
let
cfg = config.my.nix;
in {
options.my.nix = {
gc = lib.mkEnableOption null // {
default = true;
};
};
config = {
xdg.configFile = {
"nixpkgs/config.nix".text = lib.generators.toPretty {multiline = true;} {
inherit (osConfig.nixpkgs.config) allowUnfree;
};
};
systemd.user = lib.mkIf cfg.gc {
services.nix-gc = {
Unit = {
Description = "Nix User Garbage Collector";
};
Service = {
ExecStart = "${osConfig.nix.package}/bin/nix-collect-garbage ${osConfig.nix.gc.options}";
};
};
timers = {
nix-gc = lib.mkIf osConfig.nix.gc.automatic {
Timer = osConfig.systemd.timers.nix-gc.timerConfig;
Install = {
WantedBy = [ "timers.target" ];
};
};
};
};
};
}

10
modules/home/packages.nix Normal file
View file

@ -0,0 +1,10 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
xdg-utils
libnotify
pulsemixer
pavucontrol
];
}

View file

@ -0,0 +1,52 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'socket'
Thread.abort_on_exception = true
SOCK_DIR = "#{ENV['XDG_RUNTIME_DIR']}/hypr/#{ENV['HYPRLAND_INSTANCE_SIGNATURE']}"
SOCK1 = "#{SOCK_DIR}/.socket.sock"
SOCK2 = "#{SOCK_DIR}/.socket2.sock"
SOCK_ = "#{SOCK_DIR}/.personal.sock"
def hyprctl(cmd)
Socket.unix(SOCK1) do |s|
s.print cmd
s.read.force_encoding('UTF-8')
end
end
def server_listen(server, sig_out)
while (socket = server.accept)
while (line = socket.gets)
case line.chomp
when 'group_next'
sig_out[:group_next] = true
end
end
end
ensure
File.unlink(SOCK_)
end
signals = {}
Thread.new do
server = UNIXServer.new(SOCK_)
rescue Errno::EADDRINUSE
puts 'personal sock address in use' rescue nil
else
server_listen(server, signals)
end
Socket.unix(SOCK2) do |socket|
while (line = socket.gets)
event, _, data = line.partition('>>')
data = data.split(',')
case event
when 'openwindow'
hyprctl 'dispatch togglegroup' if signals.delete(:group_next)
end
end
end

View file

@ -0,0 +1,29 @@
(asdf:load-system :alexandria)
(asdf:load-system :cl-fad)
(uiop:define-package #:sync-music
(:use #:cl #:alexandria)
(:export #:sync-music #:main))
(in-package #:sync-music)
(defvar *dry-run-p* nil)
(defvar *cleanupp* nil)
(defun translate-file-name (file)
(when (cl-fad:directory-pathname-p file)
(return file))
(switch ((pathname-type file) :test #'string-equal)
("flac" (make-pathname :name (pathname-name file) :type "ogg"))
(("mp3" "ogg" "cue" "m3u" "m3u8") file)))
(defun sync-directory (directory destination)
(loop :for file :in (cl-fad:list-directory directory :follow-symlinks t)
:for file-destination := (merge-pathnames destination (translate-file-name file))
:when file-destination
:collect file-destination :into destinations))
(defun sync-music (destination &key (music-directory #P"~/Music/"))
(unless (cl-fad:directory-exists-p music-directory)
(error "Music directory `~A` does not exist!" music-directory))
(sync-directory music-directory destination))

View file

@ -0,0 +1,31 @@
(asdf:load-system :cl-hyprland-ipc)
(uiop:define-package #:time-window
(:use #:cl)
(:export #:time-window #:main))
(in-package #:time-window)
(defun time-window (argv use-pid)
(time
(let* ((process-info (uiop:launch-program argv))
(pid (uiop:process-info-pid process-info)))
(format t "Started process via `~{~A~^ ~}` with PID ~A~%" argv pid)
(hyprland-ipc:handle-events
:return-on-non-nil-p t
:open-window (lambda (address workspace-name class title)
(declare (ignorable address workspace-name class title))
(or (not use-pid)
(= pid
(gethash "pid"
(hyprland-ipc:find-client-data address)))))))))
(defun main ()
(let* ((argv (uiop:command-line-arguments))
(use-pid (string= (first argv) "-p")))
(when use-pid
(setf argv (rest argv)))
(unless argv
(format *error-output* "Needs command string!~%")
(uiop:quit 1 t))
(time-window argv use-pid)))

219
modules/home/shell.nix Normal file
View file

@ -0,0 +1,219 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.shell;
in {
options.my.shell = {
aliases.enable = lib.mkEnableOption null;
direnv.enable = lib.mkEnableOption null;
fish.enable = lib.mkEnableOption null;
globalNpmPackages.enable = lib.mkEnableOption null;
starship.enable = lib.mkEnableOption null;
zsh.enable = lib.mkEnableOption null;
};
config = lib.mkMerge [
(lib.mkIf cfg.aliases.enable {
home.shellAliases = {
e = "emacsclient -n -c";
et = "emacsclient -nw";
v = lib.mkDefault "vim";
jq = "jaq";
java = "java -Dawt.useSystemAAFontSettings=lcd";
j = "javac *.java && java Main";
syu = "nh os switch --ask --update -- --accept-flake-config";
nswitch = "nh os switch --ask -- --accept-flake-config";
};
})
(lib.mkIf cfg.direnv.enable {
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
})
(lib.mkIf cfg.fish.enable {
programs.fish = {
enable = true;
interactiveShellInit = let
catppuccinMochaSrc = pkgs.fetchFromGitHub {
owner = "catppuccin";
repo = "fish";
rev = "91e6d6721362be05a5c62e235ed8517d90c567c9";
hash = "sha256-l9V7YMfJWhKDL65dNbxaddhaM6GJ0CFZ6z+4R6MJwBA=";
};
catppuccinMochaVars = pkgs.runCommandLocal "catppuccin-mocha-vars" { } ''
${pkgs.ed}/bin/ed '${catppuccinMochaSrc}/themes/Catppuccin Mocha.theme' <<- EOF
v/^fish_/d
%s/^/set -g /
w $out
EOF
'';
in ''
set -g fish_greeting
${lib.optionalString config.my.graphical.wayland.foot.enable ''
if [ "$TERM" = "foot" ]
function mark_prompt_start --on-event fish_prompt
echo -en "\e]133;A\e\\"
end
end
''}
'';
plugins = with pkgs.fishPlugins; [
{
name = "autopair";
src = autopair.src;
}
{
name = "sponge";
src = sponge.src;
}
];
};
})
(lib.mkIf cfg.globalNpmPackages.enable {
home = let
npmPackagesPath = "${config.home.homeDirectory}/.npm-packages";
in {
file.".npmrc".text = ''
prefix = ${npmPackagesPath}
'';
sessionPath = [
"${npmPackagesPath}/bin"
];
sessionVariables.NODE_PATH = "${npmPackagesPath}/lib/node_modules";
};
})
(lib.mkIf cfg.zsh.enable {
programs.zsh = {
enable = true;
dotDir = ".config/zsh";
autocd = true;
localVariables = {
ZVM_VI_HIGHLIGHT_FOREGROUND = "black";
ZVM_VI_HIGHLIGHT_BACKGROUND = "red";
};
initExtraFirst = ''
if [[ -n $INSIDE_EMACS ]]; then
bindkey -e
else
AUTOPAIR_INHIBIT_INIT=true
fi
'';
initExtra = ''
zstyle ':completion:*' menu select
zstyle ':completion:*' matcher-list ''\'' \
'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' \
'+r:|[._-]=* r:|=*' \
'+l:|=* r:|=*'
zmodload zsh/complist
bindkey -M menuselect "''${terminfo[kcbt]}" reverse-menu-complete
if [[ -n $INSIDE_EMACS ]]; then
autoload -Uz add-zsh-hook
add-zsh-hook -d precmd zvm_init
bindkey "^W" vi-backward-kill-word
else
zle -N autopair-insert
zle -N autopair-close
zle -N autopair-delete
zvm_after_init_commands+=('
for p in ''${(@k)AUTOPAIR_PAIRS}; do
zvm_bindkey viins "$p" autopair-insert
bindkey -M isearch "$p" self-insert
local rchar="$(_ap-get-pair $p)"
if [[ $p != $rchar ]]; then
zvm_bindkey viins "$rchar" autopair-close
bindkey -M isearch "$rchar" self-insert
fi
done
zvm_bindkey viins "''${terminfo[kbs]}" autopair-delete
zvm_bindkey viins "^h" autopair-delete
bindkey -M isearch "''${terminfo[kbs]}" backward-delete-char
bindkey -M isearch "^h" backward-delete-char
zvm_bindkey viins "^[''${terminfo[kbs]}" vi-backward-kill-word
zvm_bindkey viins "^W" vi-backward-kill-word
')
fi
'';
plugins = with pkgs; [
{
name = "zsh-autopair";
src = zsh-autopair;
file = "share/zsh/zsh-autopair/autopair.zsh";
}
{
name = "zsh-vi-mode";
src = zsh-vi-mode;
file = "share/zsh-vi-mode/zsh-vi-mode.plugin.zsh";
}
{
name = "fast-syntax-highlighting";
src = zsh-fast-syntax-highlighting;
file = "share/zsh/site-functions/fast-syntax-highlighting.plugin.zsh";
}
];
};
})
(lib.mkIf cfg.starship.enable {
programs.starship = {
enable = true;
settings = {
add_newline = false;
continuation_prompt = "[>](bold green) ";
character = {
disabled = false;
success_symbol = "[%](bold green)";
error_symbol = "[%](bold yellow)";
vimcmd_symbol = "[%](bold blue)";
};
status = {
disabled = false;
format = "[$symbol$common_meaning$status]($style) ";
symbol = "";
map_symbol = true;
not_executable_symbol = "+x ";
not_found_symbol = "?? ";
sigint_symbol = "XX ";
signal_symbol = "!! ";
pipestatus = true;
pipestatus_separator = "[|](bold yellow) ";
pipestatus_format = "[\\[](bold yellow) $pipestatus"
+ "[\\] => ](bold yellow)"
+ "[$symbol$common_meaning$status]($style) ";
};
directory = {
style = "bold blue";
truncation_length = 6;
truncate_to_repo = false;
truncation_symbol = ".../";
};
nix_shell.format = "[$state( \\($name\\))]($style) ";
git_branch.format = "[$symbol$branch(:$remote_branch)]($style) ";
line_break.disabled = true;
c.disabled = true;
cmake.disabled = true;
golang.disabled = true;
haskell.disabled = true;
java.disabled = false; # the only marginally useful one
nodejs.disabled = true;
lua.disabled = true;
nim.disabled = true;
package.disabled = true;
perl.disabled = true;
php.disabled = true;
python.disabled = true;
ruby.disabled = true;
rust.disabled = true;
};
};
})
];
}

74
modules/home/spotify.nix Normal file
View file

@ -0,0 +1,74 @@
{ pkgs, inputs, config, lib, osConfig, ... }:
let
cfg = config.my.spotify;
in {
imports = [ inputs.spicetify-nix.homeManagerModule ];
options.my.spotify = {
spicetify.enable = lib.mkEnableOption null;
spotifyd.enable = lib.mkEnableOption null;
};
config = lib.mkMerge [
(lib.mkIf cfg.spicetify.enable {
home.packages = [
(pkgs.runCommandLocal "spicetify-desktop" { } ''
mkdir -p "$out/share/applications"
${pkgs.ed}/bin/ed ${pkgs.spotify}/share/applications/spotify.desktop <<- EOF
%s/^Exec=spotify/Exec=spotifywm/
w $out/share/applications/spotify.desktop
EOF
'')
];
programs.spicetify = let
spicePkgs = inputs.spicetify-nix.packages.${pkgs.system}.default;
in {
enable = true;
theme = spicePkgs.themes.catppuccin;
colorScheme = "mocha";
windowManagerPatch = true;
enabledExtensions = with spicePkgs.extensions; [
fullAppDisplay
shuffle
];
};
})
(lib.mkIf cfg.spotifyd.enable {
home.packages = [ pkgs.spotify-tui ];
services.spotifyd = {
enable = true;
package = pkgs.spotifyd.override {
withMpris = true;
withPulseAudio = true;
};
settings.global = {
username_cmd = "head -1 ${osConfig.age.secrets.spotify.path}";
password_cmd = "tail -1 ${osConfig.age.secrets.spotify.path}";
device_name = "spotifyd";
cache_path = "${config.xdg.cacheHome}/spotifyd";
max_cache_size = 1000000000;
no_audio_cache = false;
bitrate = 320;
initial_volume = "60";
volume_normalization = true;
normalisation_pregain = -10;
use_mpris = true;
backend = "pulseaudio";
volume_controller = "softvol";
zeroconf_port = 1234;
};
};
xdg.configFile."spotify-tui/config.yml".source = pkgs.fetchFromGitHub {
owner = "catppuccin";
repo = "spotify-tui";
rev = "45a4ef12508784410c516746c9d84862d52e4567";
sha256 = "1i9c30n20wq0mpvfd2ip19b1mp9ifiy2shxh16i6kfql9jr7wwj5";
} + "/mocha.yml";
})
];
}

View file

@ -0,0 +1,31 @@
{
rosewater = "F5E0DC";
flamingo = "F2CDCD";
pink = "F5C2E7";
mauve = "CBA6F7";
red = "F38BA8";
maroon = "EBA0AC";
peach = "FAB387";
yellow = "F9E2AF";
green = "A6E3A1";
teal = "94E2D5";
sky = "89DCEB";
sapphire = "74C7EC";
blue = "89B4FA";
lavender = "B4BEFE";
text = "CDD6F4";
subtext1 = "BAC2DE";
subtext0 = "A6ADC8";
overlay2 = "9399B2";
overlay1 = "7F849C";
overlay0 = "6C7086";
surface2 = "585B70";
surface1 = "45475A";
surface0 = "313244";
base = "1E1E2E";
mantle = "181825";
crust = "11111B";
}

View file

@ -0,0 +1,5 @@
_:
{
_module.args.theme = import ./catppuccin.nix;
}

View file

@ -0,0 +1,44 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.cli.applications;
in {
options.my.cli.applications = {
enable = lib.mkEnableOption null // {
default = true;
};
};
config = lib.mkIf cfg.enable {
environment = {
systemPackages = with pkgs; [
vim
wget
gnumake
findutils
psmisc
file
file-rename
moreutils
pciutils
rlwrap
unzip
unar
bat
fd
ripgrep
eza
];
sessionVariables = {
EDITOR = lib.mkDefault "ex";
VISUAL = lib.mkDefault "vim";
};
};
programs = {
git.enable = true;
htop.enable = true;
};
};
}

View file

@ -0,0 +1,12 @@
_:
{
imports = [
./applications.nix
./fish.nix
./less.nix
./nix-index.nix
./sudo.nix
./tmux.nix
];
}

16
modules/os/cli/fish.nix Normal file
View file

@ -0,0 +1,16 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.cli.fish;
in {
options.my.cli.fish = {
enable = lib.mkEnableOption null // {
default = true;
};
};
config = lib.mkIf cfg.enable {
users.defaultUserShell = pkgs.fish;
programs.fish.enable = true;
};
}

19
modules/os/cli/less.nix Normal file
View file

@ -0,0 +1,19 @@
{ config, lib, ... }:
let
cfg = config.my.cli.less;
in {
options.my.cli.less = {
enable = lib.mkEnableOption null // {
default = true;
};
};
config = lib.mkIf cfg.enable {
programs.less.enable = true;
environment.sessionVariables = {
MANPAGER = "less -R --use-color -Dd+r -Du+b";
MANROFFOPT = "-P -c";
};
};
}

View file

@ -0,0 +1,28 @@
{ inputs, config, lib, ... }:
let
cfg = config.my.cli.nix-index;
in {
imports = [
inputs.nix-index-database.nixosModules.nix-index
];
options.my.cli.nix-index = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
programs = {
nix-index = {
enable = true;
enableBashIntegration = false;
enableFishIntegration = false;
enableZshIntegration = false;
};
nix-index-database = {
comma.enable = true;
};
};
};
}

20
modules/os/cli/sudo.nix Normal file
View file

@ -0,0 +1,20 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.cli.sudo;
in {
options.my.cli.sudo = {
insults.enable = lib.mkEnableOption null;
};
config = lib.mkMerge [
(lib.mkIf cfg.insults.enable {
security.sudo = {
package = pkgs.sudo.override {withInsults = true;};
extraConfig = ''
Defaults insults
'';
};
})
];
}

15
modules/os/cli/tmux.nix Normal file
View file

@ -0,0 +1,15 @@
{ config, lib, ... }:
let
cfg = config.my.cli.tmux;
in {
options.my.cli.tmux = {
enable = lib.mkEnableOption null // {
default = true;
};
};
config = lib.mkIf cfg.enable {
programs.tmux.enable = true;
};
}

View file

@ -0,0 +1,23 @@
{ config, lib, ... }:
let
cfg = config.my.bootloader;
in {
options.my.bootloader = {
type = lib.mkOption {
type = with lib.types; nullOr (enum [ "systemdBoot" ]);
default = null;
};
};
config = {
boot.loader = lib.mkIf (cfg.type != null) {
systemd-boot = lib.mkIf (cfg.type == "systemdBoot") {
enable = true;
editor = false;
};
efi.canTouchEfiVariables = true;
timeout = lib.mkDefault 0;
};
};
}

View file

@ -0,0 +1,14 @@
_:
{
imports = [
./shared
./fs
./networking
./bootloader.nix
./secure-boot.nix
./user.nix
./zram.nix
];
}

View file

@ -0,0 +1,33 @@
{ config, lib, ... }:
let
cfg = config.my.fs;
in {
config = lib.mkIf (cfg.type == "btrfs") {
fileSystems = builtins.mapAttrs (_: options: {
inherit (cfg) device;
fsType = "btrfs";
options = [ "noatime" "space_cache=v2" "compress=zstd:9" ]
++ options
++ lib.optional config.services.fstrim.enable "nodiscard";
}) ({
"/" = [ "subvol=root" ];
"/nix" = [ "subvol=nix" ];
"/home" = [ "subvol=home" ];
} // lib.optionalAttrs cfg.snapshots {
"/home/${config.my.user.username}/.cache" = [ "subvol=misc/cache" ];
"/home/${config.my.user.username}/no-snapshot" = [ "subvol=misc/other" ];
});
services = {
snapper = lib.mkIf cfg.snapshots {
configs.home = {
SUBVOLUME = "/home";
ALLOW_USERS = [ config.my.user.username ];
TIMELINE_CREATE = true;
TIMELINE_CLEANUP = true;
};
};
};
};
}

View file

@ -0,0 +1,42 @@
{ config, lib, ... }:
let
cfg = config.my.fs;
in {
imports = [
./btrfs.nix
./ext4.nix
./luks.nix
./ssd.nix
];
options.my.fs = {
bootPartition = lib.mkEnableOption null // {
default = true;
};
device = lib.mkOption {
type = lib.types.path;
default = "/dev/disk/by-label/nixos";
};
snapshots = lib.mkEnableOption null;
swapPartition = lib.mkEnableOption null;
type = lib.mkOption {
type = with lib.types; nullOr (enum [ "btrfs" "ext4" ]);
default = null;
};
};
config = {
fileSystems = lib.mkIf cfg.bootPartition {
"/boot" = {
device = "/dev/disk/by-label/BOOT";
fsType = "vfat";
options = [ "umask=0077" ];
};
};
swapDevices = lib.mkIf cfg.swapPartition [
{device = "/dev/disk/by-label/swap";}
];
};
}

View file

@ -0,0 +1,15 @@
{ config, lib, ... }:
let
cfg = config.my.fs;
in {
config = lib.mkIf (cfg.type == "ext4") {
fileSystems = {
"/" = {
inherit (cfg) device;
fsType = "ext4";
options = [ "noatime" ];
};
};
};
}

View file

@ -0,0 +1,23 @@
{ config, lib, ... }:
let
cfg = config.my.fs.luks;
in {
options.my.fs.luks = {
enable = lib.mkEnableOption null;
device = lib.mkOption {
type = lib.types.path;
default = "/dev/disk/by-label/nixos-crypt";
};
name = lib.mkOption {
type = lib.types.str;
default = "nixos";
};
};
config = lib.mkIf cfg.enable {
my.fs.device = lib.mkDefault "/dev/mapper/${cfg.name}";
boot.initrd.luks.devices.${cfg.name} = {inherit (cfg) device;};
};
}

View file

@ -0,0 +1,19 @@
{ config, lib, ... }:
let
cfg = config.my.fs.ssd;
in {
options.my.fs.ssd = {
enable = lib.mkEnableOption null;
enableLuksIntegration = lib.mkEnableOption null // {
default = true;
};
};
config = lib.mkIf cfg.enable {
boot.initrd.luks.devices.${config.my.fs.luks.name} = lib.mkIf cfg.enableLuksIntegration {
allowDiscards = true;
bypassWorkqueues = true;
};
};
}

View file

@ -0,0 +1,106 @@
{ pkgs, config, lib, ... }:
let
cfg = config.my.networking.warp;
in {
options = {
my.networking.warp = {
enable = lib.mkEnableOption (lib.mdDoc "cloudflare-warp, a service that replaces the connection between your device and the Internet with a modern, optimized, protocol");
package = lib.mkOption {
type = lib.types.package;
default = pkgs.cloudflare-warp;
defaultText = lib.literalExpression "pkgs.cloudflare-warp";
description = lib.mdDoc "The package to use for Cloudflare Warp.";
};
user = lib.mkOption {
type = lib.types.str;
default = "warp";
description = lib.mdDoc "User account under which Cloudflare Warp runs.";
};
group = lib.mkOption {
type = lib.types.str;
default = "warp";
description = lib.mdDoc "Group under which Cloudflare Warp runs.";
};
certificate = lib.mkOption {
type = with lib.types; nullOr path;
default = null;
description = lib.mdDoc ''
Path to the Cloudflare root certificate. There is a download link in the docs [here](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/install-cloudflare-cert/).
'';
};
udpPort = lib.mkOption {
type = lib.types.int;
default = 2408;
description = lib.mdDoc ''
The UDP port to open in the firewall. Warp uses port 2408 by default, but fallback ports can be used if that conflicts with another service. See the [firewall documentation](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/deployment/firewall#warp-udp-ports) for the pre-configured available fallback ports.
'';
};
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = lib.mdDoc ''
Opens UDP port in the firewall. See `udpPort` configuration option, and [firewall documentation](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/deployment/firewall#warp-udp-ports).
'';
};
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
security.pki = lib.mkIf (cfg.certificate != null) {
certificateFiles = [ cfg.certificate ];
};
networking.firewall = lib.mkIf cfg.openFirewall {
allowedUDPPorts = [ cfg.udpPort ];
};
users.users = lib.mkIf (cfg.user == "warp") {
warp = {
isSystemUser = true;
group = "warp";
description = "Cloudflare Warp user";
home = "/var/lib/cloudflare-warp";
};
};
users.groups = lib.mkIf (cfg.group == "warp") {
warp = { };
};
systemd = {
packages = [ cfg.package ];
services.warp-svc = {
after = [ "network-online.target" "systemd-resolved.service" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
StateDirectory = "cloudflare-warp";
User = "warp";
Umask = "0077";
# Hardening
LockPersonality = true;
PrivateMounts = true;
PrivateTmp = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
# Leaving on strict activates warp on plus
ProtectSystem = "full";
RestrictNamespaces = true;
RestrictRealtime = true;
};
};
};
};
}

View file

@ -0,0 +1,26 @@
{ config, lib, ... }:
let
cfg = config.my.networking;
in {
imports = [
./cloudflare-warp.nix
./eddie.nix
];
options.my.networking = {
networkManager.enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.networkManager.enable {
networking.networkmanager = {
enable = true;
wifi = {
scanRandMacAddress = lib.mkDefault false;
};
};
systemd.services.NetworkManager-wait-online.enable = lib.mkDefault false;
my.user.extraGroups = [ "networkmanager" ];
};
}

View file

@ -0,0 +1,64 @@
{ pkgs, config, lib, inputs, ... }:
let
cfg = config.my.networking.eddie;
in {
options.my.networking.eddie = {
enable = lib.mkEnableOption null;
package = lib.mkPackageOption inputs.my-nix-packages.packages.${pkgs.system} "eddie-ui" {};
allowedTCPPorts = lib.mkOption {
type = with lib.types; listOf port;
default = [ ];
};
allowedUDPPorts = lib.mkOption {
type = with lib.types; listOf port;
default = [ ];
};
};
config = lib.mkIf cfg.enable {
boot.kernelModules = [ "tun" ];
environment.systemPackages = [ cfg.package ];
networking.iproute2.enable = true;
networking.firewall = {
checkReversePath = "loose";
interfaces = rec {
tun0 = {inherit (cfg) allowedTCPPorts allowedUDPPorts;};
Eddie = tun0;
};
};
systemd.services.eddie-elevated = {
description = "Eddie Elevation";
wantedBy = [ "multi-user.target" ];
wants = [ "network.target" "network-online.target" ];
after = [
"network-online.target"
"NetworkManager.service"
"systemd-resolved.service"
];
path = (with pkgs; [
iproute2
procps
kmod
mono
])
++ lib.optional config.services.nscd.enable
config.services.nscd.package
++ lib.optional config.networking.firewall.enable
(if config.networking.nftables.enable
then pkgs.nftables
else pkgs.iptables);
serviceConfig = {
ExecStart = "${cfg.package}/lib/eddie-ui/eddie-cli-elevated mode=service";
Restart = "always";
RestartSec = 5;
TimeoutStopSec = 5;
};
};
};
}

View file

@ -0,0 +1,26 @@
{ pkgs, config, lib, inputs, ... }:
let
cfg = config.my.secure-boot;
in {
imports = [
inputs.lanzaboote.nixosModules.lanzaboote
];
options.my.secure-boot = {
enable = lib.mkEnableOption null;
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ pkgs.sbctl ];
boot = {
loader.systemd-boot.enable = lib.mkForce false;
lanzaboote = {
enable = true;
pkiBundle = "/etc/secureboot";
};
};
};
}

Some files were not shown because too many files have changed in this diff Show more