Compare commits

..

No commits in common. "main" and "reduce-common" have entirely different histories.

145 changed files with 5524 additions and 11587 deletions

2
.envrc
View file

@ -1,2 +0,0 @@
nix_direnv_manual_reload
use flake

View file

@ -1,37 +0,0 @@
on: [push]
jobs:
check:
runs-on: nixos-host
steps:
- name: Checkout
uses: actions/checkout@v3
# cache not needed since we now run on the host directly
# - name: Load cached nix store
# id: cache-nix-store
# uses: actions/cache/restore@v4
# with:
# path: /nix/store
# key: ${{ runner.os }}-nix-store
- name: Build server
run: |
nix shell nixpkgs#nixos-rebuild -c nixos-rebuild build --flake .#beefcake
- name: Build router
run: |
nix shell nixpkgs#nixos-rebuild -c nixos-rebuild build --flake .#router
- name: Build desktop
run: |
nix shell nixpkgs#nixos-rebuild -c nixos-rebuild build --flake .#dragon
- name: Build laptop
run: |
nix shell nixpkgs#nixos-rebuild -c nixos-rebuild build --flake .#foxtrot
# - name: Save nix store
# uses: actions/cache/save@v4
# with:
# path: /nix/store
# key: ${{ steps.cache-nix-store.outputs.cache-primary-key }}

View file

@ -1,25 +0,0 @@
on: [push]
jobs:
check:
runs-on: nixos-host
steps:
- name: Checkout
uses: actions/checkout@v3
# cache not needed since we now run on the host directly
# - name: Load cached nix store
# id: cache-nix-store
# uses: actions/cache/restore@v4
# with:
# path: /nix/store
# key: ${{ runner.os }}-nix-store
- name: Check nix flake
run: |
nix flake check
# - name: Save nix store
# uses: actions/cache/save@v4
# with:
# path: /nix/store
# key: ${{ steps.cache-nix-store.outputs.cache-primary-key }}

6
.gitignore vendored
View file

@ -1,7 +1,3 @@
/.direnv
result
.pre-commit-config.yaml
*.log *.log
result
*.qcow2 *.qcow2

View file

@ -1,19 +1,6 @@
keys: keys:
# list any public keys here - &daniel age1stdue5q5teskee057ced6rh9pzzr93xsy66w4sc3zu49rgxl7cjshztt45 # pass age-key | rg '# pub'
- &sshd-at-beefcake age1k8s590x34ghz7yrjyrgzkd24j252srf0mhfy34halp4frwr065csrlt2ev # ssh beefcake "nix-shell -p ssh-to-age --run 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age'"
# pass age-key | rg '# pub'
- &daniel age1stdue5q5teskee057ced6rh9pzzr93xsy66w4sc3zu49rgxl7cjshztt45
# per-host keys can be derived from a target host's ssh keys like so:
# ssh host "nix shell nixpkgs#ssh-to-age -c $SHELL -c 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age'"
- &sshd-at-beefcake age1etv56f7kf78a55lxqtydrdd32dpmsjnxndf4u28qezxn6p7xt9esqvqdq7
- &sshd-at-router age1zd7c3g5d20shdftq8ghqm0r92488dg4pdp4gulur7ex3zx2yq35ssxawpn
- &sshd-at-dragon age1ez4why08hdx0qf940cjzs6ep4q5rk2gqq7lp99pe58fktpwv65esx4xrht
- &ssh-foxtrot age1njnet9ltjuxasqv3ckn67r5natke6xgd8wlx8psf64pyc4duvurqhedw80
# after updating this file, you may need to update the keys for any associated files like so:
# sops updatekeys secrets.file
creation_rules: creation_rules:
- path_regex: secrets/[^/]+\.(ya?ml|json|env|ini)$ - path_regex: secrets/[^/]+\.(ya?ml|json|env|ini)$
key_groups: key_groups:
@ -24,18 +11,3 @@ creation_rules:
- age: - age:
- *daniel - *daniel
- *sshd-at-beefcake - *sshd-at-beefcake
- path_regex: secrets/router/[^/]+\.(ya?ml|json|env|ini)$
key_groups:
- age:
- *daniel
- *sshd-at-router
- path_regex: secrets/dragon/[^/]+\.(ya?ml|json|env|ini)$
key_groups:
- age:
- *daniel
- *sshd-at-dragon
- path_regex: secrets/foxtrot/[^/]+\.(ya?ml|json|env|ini)$
key_groups:
- age:
- *daniel
- *ssh-foxtrot

View file

@ -1,85 +1,4 @@
{lib, ...}: let {
inherit (lib.attrsets) mapAttrs' filterAttrs;
in {
standardWithHibernateSwap = {
disks ? ["/dev/sda"],
swapSize,
...
}: {
/*
this is my standard partitioning scheme for my machines which probably want hibernation capabilities
a UEFI-compatible boot partition
it includes an LUKS-encrypted btrfs volume
a swap partition big enough to dump all the machine's RAM into
*/
disko.devices = {
disk = {
primary = {
type = "disk";
device = builtins.elemAt disks 0;
content = {
type = "gpt";
partitions = {
ESP = {
label = "EFI";
name = "ESP";
size = "4G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [
"defaults"
];
};
};
swap = {
size = swapSize;
content = {
type = "swap";
discardPolicy = "both";
resumeDevice = true; # resume from hiberation from this device
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "crypted";
extraOpenArgs = ["--allow-discards"];
# if you want to use the key for interactive login be sure there is no trailing newline
# for example use `echo -n "password" > /tmp/secret.key`
keyFile = "/tmp/secret.key"; # Interactive
# settings.keyFile = "/tmp/password.key";
# additionalKeyFiles = ["/tmp/additionalSecret.key"];
content = {
type = "btrfs";
extraArgs = ["-f"];
subvolumes = {
"/nixos" = {
mountpoint = "/";
mountOptions = ["compress=zstd" "noatime"];
};
"/home" = {
mountpoint = "/home";
mountOptions = ["compress=zstd" "noatime"];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = ["compress=zstd" "noatime"];
};
};
};
};
};
};
};
};
};
};
};
standard = {disks ? ["/dev/vda"], ...}: { standard = {disks ? ["/dev/vda"], ...}: {
# this is my standard partitioning scheme for my machines: an LUKS-encrypted # this is my standard partitioning scheme for my machines: an LUKS-encrypted
# btrfs volume # btrfs volume
@ -142,7 +61,67 @@ in {
}; };
}; };
}; };
# TODO: figure out what I can't have an optiona/default 'name' attribute here so I can DRY with "standard"
thinker = {disks ? ["/dev/vda"], ...}: {
disko.devices = {
disk = {
vdb = {
type = "disk";
device = builtins.elemAt disks 0;
content = {
type = "gpt";
partitions = {
ESP = {
label = "EFI";
name = "ESP";
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [
"defaults"
];
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "crypted";
extraOpenArgs = ["--allow-discards"];
# if you want to use the key for interactive login be sure there is no trailing newline
# for example use `echo -n "password" > /tmp/secret.key`
keyFile = "/tmp/secret.key"; # Interactive
# settings.keyFile = "/tmp/password.key";
# additionalKeyFiles = ["/tmp/additionalSecret.key"];
content = {
type = "btrfs";
extraArgs = ["-f"];
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = ["compress=zstd" "noatime"];
};
"/home" = {
mountpoint = "/home";
mountOptions = ["compress=zstd" "noatime"];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = ["compress=zstd" "noatime"];
};
};
};
};
};
};
};
};
};
};
};
unencrypted = {disks ? ["/dev/vda"], ...}: { unencrypted = {disks ? ["/dev/vda"], ...}: {
disko.devices = { disko.devices = {
disk = { disk = {
@ -193,203 +172,6 @@ in {
}; };
}; };
}; };
beefcake = let
zpools = {
zroot = {
/*
TODO: at the time of writing, disko does not support draid6
so I'm building/managing the array manually for the time being
the root pool is just a single disk right now
*/
name = "zroot";
config = {
type = "zpool";
# mode = "draid6";
rootFsOptions = {
compression = "zstd";
"com.sun:auto-snapshot" = "false";
};
mountpoint = "/";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot@blank$' || zfs snapshot zroot@blank";
datasets = {
zfs_fs = {
type = "zfs_fs";
mountpoint = "/zfs_fs";
options."com.sun:auto-snapshot" = "true";
};
zfs_unmounted_fs = {
type = "zfs_fs";
options.mountpoint = "none";
};
zfs_legacy_fs = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/zfs_legacy_fs";
};
zfs_testvolume = {
type = "zfs_volume";
size = "10M";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/ext4onzfs";
};
};
encrypted = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
keylocation = "file:///tmp/secret.key";
};
# use this to read the key during boot
/*
postCreateHook = ''
zfs set keylocation="prompt" "zroot/$name";
'';
*/
};
"encrypted/test" = {
type = "zfs_fs";
mountpoint = "/zfs_crypted";
};
};
};
};
zstorage = {
/*
PARITY_COUNT=3 NUM_DRIVES=8 HOT_SPARES=2 sudo -E zpool create -f -O mountpoint=none -O compression=on -O xattr=sa -O acltype=posixacl -o ashift=12 -O atime=off -O recordsize=64K zstorage draid{$PARITY_COUNT}:{$NUM_DRIVES}c:{$HOT_SPARES}s /dev/disk/by-id/scsi-35000039548cb637c /dev/disk/by-id/scsi-35000039548cb7c8c /dev/disk/by-id/scsi-35000039548cb85c8 /dev/disk/by-id/scsi-35000039548d9b504 /dev/disk/by-id/scsi-35000039548da2b08 /dev/disk/by-id/scsi-35000039548dad2fc /dev/disk/by-id/scsi-350000399384be921 /dev/disk/by-id/scsi-35000039548db096c
sudo zfs create -o mountpoint=legacy zstorage/nix
sudo zfs create -o canmount=on -o mountpoint=/storage zstorage/storage
*/
name = "zstorage";
config = {};
};
};
diskClass = {
storage = {
type = "zfs";
pool = zpools.zroot.name;
};
boot = {
content = {
type = "gpt";
partitions = {
ESP = {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
zfs = {
size = "100%";
content = {
type = "zfs";
pool = zpools.zroot.name;
};
};
};
};
};
};
bootDisks = {
"/dev/sdi" = {
name = "i";
enable = true;
};
"/dev/sdj" = {
name = "j";
enable = true;
}; # TODO: join current boot drive to new boot pool
};
storageDisks = {
"/dev/sda" = {
enable = true;
name = "a";
};
"/dev/sdb" = {
enable = true;
name = "b";
};
"/dev/sdc" = {
enable = true;
name = "c";
};
"/dev/sdd" = {
enable = true;
name = "d";
};
# TODO: start small
"/dev/sde" = {
enable = false;
name = "e";
};
"/dev/sdf" = {
enable = false;
name = "f";
};
"/dev/sdg" = {
enable = false;
name = "g";
};
"/dev/sdh" = {
enable = false;
name = "h";
};
# gap for two boot drives
"/dev/sdk" = {
enable = false;
name = "k";
};
"/dev/sdl" = {
enable = false;
name = "l";
};
"/dev/sdm" = {
enable = false;
name = "m";
};
"/dev/sdn" = {
# TODO: this is my holding cell for random stuff right now
enable = false;
name = "n";
};
};
diskoBoot = mapAttrs' (device: {name, ...}: {
name = "boot-${name}";
value = {
inherit device;
type = "disk";
content = diskClass.boot.content;
};
}) (filterAttrs (_: {enable, ...}: enable) bootDisks);
diskoStorage = mapAttrs' (device: {name, ...}: {
name = "storage-${name}";
value = {
inherit device;
type = "disk";
content = diskClass.storage.content;
};
}) (filterAttrs (_: {enable, ...}: enable) storageDisks);
in {
disko.devices = {
disk = diskoBoot // diskoStorage;
zpool = {
zroot = zpools.zroot.config;
};
};
};
legacy = {disks ? ["/dev/vda"], ...}: { legacy = {disks ? ["/dev/vda"], ...}: {
disko.devices = { disko.devices = {
disk = { disk = {
@ -401,9 +183,9 @@ in {
format = "gpt"; format = "gpt";
partitions = [ partitions = [
{ {
label = "EFI";
name = "ESP"; name = "ESP";
size = "512M"; start = "1M";
end = "500M";
bootable = true; bootable = true;
content = { content = {
type = "filesystem"; type = "filesystem";

File diff suppressed because it is too large Load diff

940
flake.nix
View file

@ -1,45 +1,172 @@
{ {
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable";
home-manager.url = "github:nix-community/home-manager/master";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
helix.url = "github:helix-editor/helix/master";
helix.inputs.nixpkgs.follows = "nixpkgs";
disko.url = "github:nix-community/disko/master"; disko.url = "github:nix-community/disko/master";
disko.inputs.nixpkgs.follows = "nixpkgs"; disko.inputs.nixpkgs.follows = "nixpkgs";
sops-nix.url = "github:Mic92/sops-nix"; sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs-unstable"; sops-nix.inputs.nixpkgs.follows = "nixpkgs";
# sops-nix.inputs.nixpkgs-stable.follows = "nixpkgs"; sops-nix.inputs.nixpkgs-stable.follows = "nixpkgs";
git-hooks.url = "github:cachix/git-hooks.nix";
git-hooks.inputs.nixpkgs.follows = "nixpkgs";
home-manager.url = "github:nix-community/home-manager/release-24.11";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
home-manager-unstable.url = "github:nix-community/home-manager";
home-manager-unstable.inputs.nixpkgs.follows = "nixpkgs-unstable";
helix.url = "github:helix-editor/helix/master";
hardware.url = "github:nixos/nixos-hardware"; hardware.url = "github:nixos/nixos-hardware";
# hardware.inputs.nixpkgs.follows = "nixpkgs";
hyprland.url = "github:hyprwm/Hyprland"; hyprland.url = "github:hyprwm/Hyprland";
hyprland.inputs.nixpkgs.follows = "nixpkgs";
wezterm.url = "github:wez/wezterm?dir=nix"; api-lyte-dev.url = "git+ssh://gitea@git.lyte.dev/lytedev/api.lyte.dev.git";
wezterm.inputs.nixpkgs.follows = "nixpkgs-unstable"; api-lyte-dev.inputs.nixpkgs.follows = "nixpkgs";
slippi.url = "github:lytedev/slippi-nix"; ssbm.url = "github:lytedev/ssbm-nix/my-nixpkgs";
# slippi.url = "git+file:///home/daniel/code/open-source/slippi-nix"; ssbm.inputs.nixpkgs.follows = "nixpkgs";
slippi.inputs.nixpkgs.follows = "nixpkgs-unstable";
slippi.inputs.home-manager.follows = "home-manager-unstable";
jovian.url = "github:Jovian-Experiments/Jovian-NixOS/development"; # doesn't support the forge mod loader yet
jovian.inputs.nixpkgs.follows = "nixpkgs-unstable"; # nix-minecraft.url = "github:Infinidoge/nix-minecraft";
# nnf.url = "github:thelegy/nixos-nftables-firewall?rev=71fc2b79358d0dbacde83c806a0f008ece567b7b"; # need to bump ishiiruka upstream I think
# slippi-desktop.url = "github:project-slippi/slippi-desktop-app";
mobile-nixos = { # slippi-desktop.flake = false;
url = "github:lytedev/mobile-nixos"; # ssbm.inputs.slippi-desktop.follows = "slippi-desktop";
flake = false;
}; };
outputs = {
self,
nixpkgs,
home-manager,
...
} @ inputs: let
inherit (self) outputs;
systems = [
"aarch64-linux"
# "i686-linux"
"x86_64-linux"
"aarch64-darwin"
"x86_64-darwin"
];
forAllSystems = nixpkgs.lib.genAttrs systems;
color-schemes = (import ./lib/colors.nix inputs).schemes;
colors = color-schemes.catppuccin-mocha-sapphire;
# colors = (import ./lib/colors.nix inputs).color-schemes.donokai;
font = {
name = "IosevkaLyteTerm";
size = 12;
};
in {
colors = colors;
font = font;
# Your custom packages
# Acessible through 'nix build', 'nix shell', etc
packages = forAllSystems (system: import ./pkgs nixpkgs.legacyPackages.${system});
# Formatter for your nix files, available through 'nix fmt'
# Other options beside 'alejandra' include 'nixpkgs-fmt'
formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.alejandra);
# Your custom packages and modifications, exported as overlays
overlays = import ./overlays {inherit inputs;};
# Reusable nixos modules you might want to export
# These are usually stuff you would upstream into nixpkgs
nixosModules = import ./modules/nixos;
# Reusable home-manager modules you might want to export
# These are usually stuff you would upstream into home-manager
homeManagerModules = import ./modules/home-manager;
# NixOS configuration entrypoint
# Available through 'nixos-rebuild --flake .#your-hostname'
nixosConfigurations = let
mkNixosSystem = system: modules: homeManagerModules:
nixpkgs.lib.nixosSystem {
system = system;
specialArgs = {
inherit inputs outputs system colors font;
flake = self;
};
modules =
[
inputs.sops-nix.nixosModules.sops
self.nixosModules.common
]
++ modules
++ [
inputs.home-manager.nixosModules.home-manager
{
home-manager = {
extraSpecialArgs = {inherit inputs outputs system colors font;};
users.daniel = {
imports = homeManagerModules;
};
};
}
];
};
base = mkNixosSystem "x86_64-linux" [./nixos/base] [outputs.homeManagerModules.base];
in {
base = base;
nixos = base; # alias
thablet = mkNixosSystem "x86_64-linux" [./nixos/thablet] [outputs.homeManagerModules.base];
thinker = mkNixosSystem "x86_64-linux" [./nixos/thinker] [outputs.homeManagerModules.thinker];
foxtrot = mkNixosSystem "x86_64-linux" [./nixos/foxtrot] [
outputs.homeManagerModules.foxtrot
];
beefcake =
mkNixosSystem "x86_64-linux" [
inputs.api-lyte-dev.nixosModules.x86_64-linux.api-lyte-dev
./nixos/beefcake
] (with outputs.homeManagerModules; [
linux
]);
rascal = mkNixosSystem "x86_64-linux" [./nixos/rascal] [
outputs.homeManagerModules.linux
];
musicbox = mkNixosSystem "x86_64-linux" [./nixos/musicbox] [outputs.homeManagerModules.sway];
router = mkNixosSystem "x86_64-linux" [./nixos/router] [outputs.homeManagerModules.common];
};
# Standalone home-manager configuration entrypoint
# Available through 'home-manager --flake .#your-username@your-hostname'
homeConfigurations = {
# TODO: non-system-specific home configurations?
"base-x86_64-linux" = let
system = "x86_64-linux";
in
home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.${system};
extraSpecialArgs = {inherit inputs outputs system colors font;};
modules = with outputs.homeManagerModules; [linux];
};
"base-aarch64-darwin" = let
system = "aarch64-darwin";
in
home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.${system};
extraSpecialArgs = {inherit inputs outputs system colors font;};
modules = with outputs.homeManagerModules; [macos];
};
};
# TODO: nix-on-droid for phone terminal usage?
# TODO: nix-darwin for work?
# TODO: nixos ISO?
# Disk partition schemes and functions
diskoConfigurations = import ./disko;
# Flake templates for easily setting up Nix in a project using common patterns I like
templates = import ./templates/all.nix;
}; };
nixConfig = { nixConfig = {
@ -50,770 +177,13 @@
"https://helix.cachix.org" "https://helix.cachix.org"
"https://nix-community.cachix.org" "https://nix-community.cachix.org"
"https://nix.h.lyte.dev" "https://nix.h.lyte.dev"
"https://hyprland.cachix.org"
]; ];
extra-trusted-public-keys = [ extra-trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"helix.cachix.org-1:ejp9KQpR1FBI2onstMQ34yogDm4OgU2ru6lIwPvuCVs=" "helix.cachix.org-1:ejp9KQpR1FBI2onstMQ34yogDm4OgU2ru6lIwPvuCVs="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"h.lyte.dev-2:te9xK/GcWPA/5aXav8+e5RHImKYMug8hIIbhHsKPN0M=" "h.lyte.dev:HeVWtne31ZG8iMf+c15VY3/Mky/4ufXlfTpT8+4Xbs0="
"hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
]; ];
}; };
outputs = {
self,
nixpkgs,
nixpkgs-unstable,
disko,
sops-nix,
git-hooks,
wezterm,
home-manager,
home-manager-unstable,
helix,
hardware,
jovian,
mobile-nixos,
# nnf,
# hyprland,
slippi,
...
}: let
inherit (self) outputs;
inherit (outputs) nixosModules homeManagerModules overlays;
# TODO: make @ inputs unnecessary by making arguments explicit in all modules?
systems = ["aarch64-linux" "aarch64-darwin" "x86_64-darwin" "x86_64-linux"];
forSystems = nixpkgs.lib.genAttrs systems;
pkgsFor = system: (import nixpkgs {inherit system;}).extend overlays.default;
genPkgs = func: (forSystems (system: func (pkgsFor system)));
# pkg = callee: overrides: genPkgs (pkgs: pkgs.callPackage callee overrides);
unstable = {
forSystems = nixpkgs-unstable.lib.genAttrs systems;
pkgsFor = system: (import nixpkgs-unstable {inherit system;}).extend overlays.default;
genPkgs = func: (forSystems (system: func (pkgsFor system)));
pkg = callee: overrides: genPkgs (pkgs: pkgs.callPackage callee overrides);
};
style = {
colors = (import ./lib/colors.nix {inherit (nixpkgs) lib;}).schemes.catppuccin-mocha-sapphire;
font = {
name = "IosevkaLyteTerm";
size = 12;
};
};
/*
moduleArgs = {
# inherit style;
inherit helix slippi hyprland hardware disko home-manager;
inherit (outputs) nixosModules homeManagerModules diskoConfigurations overlays;
};
*/
pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAPLXOjupz3ScYjgrF+ehrbp9OvGAWQLI6fplX6w9Ijb daniel@lyte.dev";
in {
/*
kind of a quirk, but package definitions are actually in the "additions"
overlay I did this to work around some recursion problems
TODO: https://discourse.nixos.org/t/infinite-recursion-getting-started-with-overlays/48880
*/
packages = genPkgs (pkgs: {inherit (pkgs) iosevkaLyteTerm iosevkaLyteTermSubset nix-base-container-image;});
diskoConfigurations = import ./disko {inherit (nixpkgs) lib;};
templates = import ./templates;
formatter = genPkgs (p: p.alejandra);
checks = genPkgs ({system, ...}: {
git-hooks = git-hooks.lib.${system}.run {
src = ./.;
hooks = {
alejandra.enable = true;
};
};
});
devShells = genPkgs ({
system,
pkgs,
mkShell,
...
}: {
default = mkShell {
inherit (outputs.checks.${system}.git-hooks) shellHook;
packages = with pkgs; [
lua-language-server
nodePackages.bash-language-server
];
};
});
overlays = {
# the default overlay composes all the other overlays together
default = final: prev: {
overlays = with overlays; [
additions
modifications
unstable-packages
];
};
additions = final: prev: let
iosevkaLyteTerm = prev.callPackage ./packages/iosevkaLyteTerm.nix {};
in {
inherit iosevkaLyteTerm;
iosevkaLyteTermSubset = prev.callPackage ./packages/iosevkaLyteTermSubset.nix {
inherit iosevkaLyteTerm;
};
nix-base-container-image = final.dockerTools.buildImageWithNixDb {
name = "git.lyte.dev/lytedev/nix";
tag = "latest";
copyToRoot = with final; [
bash
coreutils
curl
gawk
gitFull
git-lfs
gnused
nodejs
wget
sudo
nixVersions.stable
cacert
gnutar
gzip
openssh
xz
(pkgs.writeTextFile {
name = "nix.conf";
destination = "/etc/nix/nix.conf";
text = ''
accept-flake-config = true
experimental-features = nix-command flakes
build-users-group =
substituters = https://nix.h.lyte.dev https://cache.nixos.org/
trusted-substituters = https://nix.h.lyte.dev https://cache.nixos.org/
trusted-public-keys = h.lyte.dev:HeVWtne31ZG8iMf+c15VY3/Mky/4ufXlfTpT8+4Xbs0= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
'';
})
];
extraCommands = ''
# enable /usr/bin/env for scripts
mkdir -p usr
ln -s ../bin usr/bin
# create /tmp
mkdir -p tmp
# create HOME
mkdir -vp root
'';
config = {
Cmd = ["/bin/bash"];
Env = [
"LANG=en_GB.UTF-8"
"ENV=/etc/profile.d/nix.sh"
"BASH_ENV=/etc/profile.d/nix.sh"
"NIX_BUILD_SHELL=/bin/bash"
"PAGER=cat"
"PATH=/usr/bin:/bin"
"SSL_CERT_FILE=${final.cacert}/etc/ssl/certs/ca-bundle.crt"
"USER=root"
];
};
};
};
modifications = final: prev: let
wezterm-input = wezterm;
in rec {
helix = helix.outputs.packages.${prev.system}.helix;
final.helix = helix;
/*
TODO: would love to use a current wezterm build so I can make use of ssh/mux functionality without breakage
source: https://github.com/wez/wezterm/issues/3771
not-yet-merged (abandoned?): https://github.com/wez/wezterm/pull/4737
I did try using the latest code via the flake, but alas it did not resolve my issues with mux'ing
*/
wezterm = wezterm-input.outputs.packages.${prev.system}.default;
# wezterm = (import nixpkgs {inherit (prev) system;}).wezterm;
final.wezterm = wezterm;
# zellij = prev.zellij.overrideAttrs rec {
# version = "0.41.0";
# src = prev.fetchFromGitHub {
# owner = "zellij-org";
# repo = "zellij";
# rev = "v0.41.0";
# hash = "sha256-A+JVWYz0t9cVA8XZciOwDkCecsC2r5TU2O9i9rVg7do=";
# };
# cargoDeps = prev.zellij.cargoDeps.overrideAttrs (prev.lib.const {
# name = "zellij-vendor.tar.gz";
# inherit src;
# outputHash = "sha256-WxrMI7fV0pNsGjbNpXLr+xnMdWYkC4WxIeN4OK3ZPIE=";
# });
# };
# final.zellij = zellij;
};
unstable-packages = final: _prev: {
unstable-packages = import nixpkgs-unstable {
system = final.system;
config.allowUnfree = true;
};
};
};
nixosModules = import ./modules/nixos {
inherit home-manager home-manager-unstable helix nixosModules homeManagerModules pubkey overlays style sops-nix disko;
flakeInputs = self.inputs;
};
homeManagerModules = import ./modules/home-manager {
inherit home-manager home-manager-unstable helix nixosModules homeManagerModules pubkey overlays style;
inherit (nixpkgs) lib;
flakeInputs = self.inputs;
};
nixosConfigurations = {
beefcake = let
system = "x86_64-linux";
in
nixpkgs.lib.nixosSystem {
inherit system;
modules = with nixosModules; [
home-manager-defaults
# TODO: disko?
hardware.nixosModules.common-cpu-intel
outputs.nixosModules.deno-netlify-ddns-client
{
services.deno-netlify-ddns-client = {
enable = true;
username = "beefcake.h";
# TODO: router doesn't even do ipv6 yet...
ipv6 = false;
};
}
family-users
common
podman
troubleshooting-tools
virtual-machines
virtual-machines-gui
linux
fonts
./nixos/beefcake.nix
{
services.kanidm.package = (unstable.pkgsFor system).kanidm;
}
];
};
dragon = nixpkgs-unstable.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-unstable-defaults
outputs.diskoConfigurations.standard
hardware.nixosModules.common-cpu-amd
hardware.nixosModules.common-pc-ssd
common
password-manager
wifi
graphical-workstation
virtual-machines
virtual-machines-gui
music-production
# plasma6
gaming
slippi.nixosModules.default
outputs.nixosModules.deno-netlify-ddns-client
{
services.deno-netlify-ddns-client = {
enable = true;
username = "dragon.h";
# TODO: router doesn't even do ipv6 yet...
ipv6 = false;
};
}
./nixos/dragon.nix
{
home-manager.users.daniel = {
imports = with homeManagerModules; [
senpai
iex
cargo
firefox-no-tabs
linux-desktop-environment-config
slippi.homeManagerModules.default
];
};
}
];
};
bigtower = nixpkgs-unstable.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-unstable-defaults
outputs.diskoConfigurations.unencrypted
hardware.nixosModules.common-cpu-amd
hardware.nixosModules.common-pc-ssd
common
# wifi
graphical-workstation
music-production
gaming
./nixos/bigtower.nix
{
home-manager.users.daniel = {
imports = with homeManagerModules; [
firefox-no-tabs
linux-desktop-environment-config
];
};
}
];
};
htpc = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-defaults
hardware.nixosModules.common-pc-ssd
common
gaming
graphical-workstation
plasma6
./nixos/htpc.nix
{
home-manager.users.daniel = {
imports = with homeManagerModules; [
linux-desktop-environment-config
];
};
}
];
};
steamdeck1 = nixpkgs-unstable.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-unstable-defaults
outputs.diskoConfigurations.standard
hardware.nixosModules.common-pc-ssd
common
gaming
graphical-workstation
plasma6
jovian.outputs.nixosModules.jovian
{
networking.hostName = "steamdeck1";
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
hardware.bluetooth.enable = true;
networking.networkmanager.enable = true;
home-manager.users.daniel = {
imports = with homeManagerModules; [
firefox-no-tabs
linux-desktop-environment-config
];
};
}
];
};
foxtrot = nixpkgs-unstable.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-unstable-defaults
outputs.diskoConfigurations.standard
hardware.nixosModules.framework-13-7040-amd
common
kde-connect
password-manager
graphical-workstation
# plasma6
virtual-machines
virtual-machines-gui
laptop
gaming
cross-compiler
./nixos/foxtrot.nix
({pkgs, ...}: {
home-manager.users.daniel = {
imports = with homeManagerModules; [
senpai
iex
cargo
firefox-no-tabs
linux-desktop-environment-config
];
};
environment.systemPackages = with pkgs; [
fw-ectool
(writeShellApplication
{
name = "reset-wifi-module";
runtimeInputs = with pkgs; [kmod];
text = ''
modprobe -rv mt7921e
modprobe -v mt7921e
'';
})
(writeShellApplication
{
name = "perfmode";
# we use command -v $cmd here because we only want to invoke these calls _if_ the related package is installed on the system
# otherwise, they will likely have no effect anyways
text = ''
command -v powerprofilesctl &>/dev/null && bash -x -c 'powerprofilesctl set balanced'
command -v swaymsg &>/dev/null && bash -x -c 'swaymsg output eDP-1 mode 2880x1920@120Hz'
'';
})
(writeShellApplication
{
name = "battmode";
text = ''
command -v powerprofilesctl &>/dev/null && bash -x -c 'powerprofilesctl set power-saver'
command -v swaymsg &>/dev/null && bash -x -c 'swaymsg output eDP-1 mode 2880x1920@60Hz'
'';
})
];
})
];
};
thablet = nixpkgs-unstable.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-unstable-defaults
outputs.diskoConfigurations.standard
hardware.nixosModules.lenovo-thinkpad-x1-yoga
common
password-manager
graphical-workstation
plasma6
music-production
laptop
gaming
./nixos/thablet.nix
{
home-manager.users.daniel = {
imports = with homeManagerModules; [
senpai
iex
cargo
firefox-no-tabs
linux-desktop-environment-config
# slippi.homeManagerModules.default
];
};
}
];
};
/*
grablet = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
common
outputs.diskoConfigurations.standard
hardware.nixosModules.common-cpu-intel-kaby-lake
hardware.nixosModules.common-pc-laptopp-ssd
graphical-workstation
laptop
gaming
./nixos/thablet.nix
{
home-manager.users.daniel = {
imports = with homeManagerModules; [
iex
cargo
linux-desktop-environment-config
];
};
powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
}
];
};
*/
thinker = nixpkgs-unstable.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-unstable-defaults
{
_module.args = {
disks = ["/dev/nvme0n1"];
swapSize = "32G";
};
}
outputs.diskoConfigurations.standardWithHibernateSwap
hardware.nixosModules.lenovo-thinkpad-t480
hardware.nixosModules.common-pc-laptop-ssd
music-production
common
password-manager
graphical-workstation
plasma6
laptop
gaming
./nixos/thinker.nix
{
home-manager.users.daniel = {
imports = with homeManagerModules; [
senpai
iex
cargo
firefox-no-tabs
linux-desktop-environment-config
slippi.homeManagerModules.default
];
};
}
];
};
musicbox = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-defaults
{
_module.args = {
disks = ["/dev/sda"];
# swapSize = "8G";
};
}
outputs.diskoConfigurations.unencrypted
hardware.nixosModules.common-pc-laptop-ssd
music-production
common
graphical-workstation
wifi
# ./nixos/musicbox.nix
{
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
hardware.bluetooth.enable = true;
networking.networkmanager.enable = true;
home-manager.users.daniel = {
imports = with homeManagerModules; [
firefox-no-tabs
linux-desktop-environment-config
];
};
}
];
};
rascal = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-defaults
hardware.nixosModules.common-cpu-amd
common
linux
./nixos/rascal.nix
];
};
router = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-defaults
outputs.diskoConfigurations.unencrypted
common
linux
troubleshooting-tools
outputs.nixosModules.deno-netlify-ddns-client
{
services.deno-netlify-ddns-client = {
enable = true;
username = "router.h";
# TODO: ipv6
ipv6 = false;
};
}
/*
NOTE: maybe use this someday, but I think I need more concrete
networking knowledge before I know how to use it well. Additionally,
I can use my existing firewall configuration more easily if I manage
it directly.
nnf.nixosModules.default
*/
./nixos/router.nix
];
};
# pinephone-image =
# (import "${mobile-nixos}/lib/eval-with-configuration.nix" {
# configuration = with nixosModules; [
# linux
# home-manager-defaults
# # outputs.diskoConfigurations.unencrypted # can I even disko with an image-based installation?
# common
# wifi
# # TODO: how do I get a minimally useful mobile environment?
# # for me, this means an on-screen keyboard and suspend support I think?
# # I can live in a tty if needed and graphical stuff can all evolve later
# # not worried about modem
# # maybe/hopefully I can pull in or define my own sxmo via nix?
# ];
# device = "pine64-pinephone";
# pkgs = pkgsFor "aarch64-linux";
# })
# .outputs
# .disk-image;
pinephone = let
inherit (nixpkgs-unstable) lib;
in
lib.nixosSystem {
system = "aarch64-linux";
# lib.nixosSystem {
modules = with nixosModules; [
{
imports = [
(import "${mobile-nixos}/lib/configuration.nix" {
device = "pine64-pinephone";
})
];
# nixpkgs.hostPlatform.system = "aarch64-linux";
nixpkgs.buildPlatform = "x86_64-linux";
# TODO: quirk: since the pinephone kernel doesn't seem to have "rpfilter" support, firewall ain't working
networking.firewall.enable = lib.mkForce false;
# TODO: quirk: since git send-email requires perl support, which we don't seem to have on the pinephone, we're just disabling git for now
# TODO: would likely be easier/better to somehow ignore the assertion? probably a way to do that...
programs.git.enable = lib.mkForce false;
# this option is conflicted, presumably due to some assumption in my defaults/common config
# the sd-image module we're importing above has this set to true, so we better go with that?
# that said, I think the mobile-nixos bootloader module has this set to false, so...
# TODO: what does this mean?
boot.loader.generic-extlinux-compatible.enable = lib.mkForce true;
# another conflicting option since I think I default to NetworkManager and this conflicts with networking.wireless.enable
networking.networkmanager.enable = lib.mkForce false;
networking.wireless.enable = lib.mkForce true;
}
# TODO: how do I build this as a .img to flash to an SD card?
# for testing, this seems to work `nixos-rebuild build --impure --flake .#pinephone`
# TODO: would like to use the mobile-nixos installer?
"${nixpkgs-unstable}/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix"
linux
home-manager-unstable-defaults
# outputs.diskoConfigurations.unencrypted # can I even disko with an image-based installation?
common
wifi
{
system.stateVersion = "24.11";
}
{
# nixpkgs.buildPlatform = "x86_64-linux";
# nixpkgs.hostPlatform = lib.systems.examples.aarch64-multiplatform;
# nixpkgs.localSystem.system = lib.systems.examples.x86_64-linux;
# nixpkgs.crossSystem = lib.mkForce null;
}
];
};
};
images.pinephone = outputs.nixosConfigurations.pinephone.config.system.build.sdImage;
homeConfigurations = {
"deck" = let
system = "x86_64-linux";
pkgs = unstable.pkgsFor system;
in
home-manager-unstable.lib.homeManagerConfiguration {
inherit pkgs;
modules = with homeManagerModules; [
common
{
home = {
homeDirectory = "/home/deck";
username = "deck";
stateVersion = "24.11";
};
}
{
home.packages = with pkgs; [
ludusavi
rclone
];
}
linux
];
};
};
/*
TODO: nix-on-droid for phone terminal usage? mobile-nixos?
TODO: nix-darwin for work?
TODO: nixos ISO?
*/
};
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View file

@ -1,380 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="141.5919mm"
height="122.80626mm"
viewBox="0 0 501.70361 435.14028"
id="svg2"
version="1.1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
sodipodi:docname="Nix_snowflake_lytedev.svg"
inkscape:export-filename="Nix_snowflake_lytedev.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4">
<linearGradient
inkscape:collect="always"
id="linearGradient5562">
<stop
style="stop-color:#699ad7;stop-opacity:1"
offset="0"
id="stop5564" />
<stop
id="stop5566"
offset="0.24345198"
style="stop-color:#7eb1dd;stop-opacity:1" />
<stop
style="stop-color:#7ebae4;stop-opacity:1"
offset="1"
id="stop5568" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient5053">
<stop
style="stop-color:#415e9a;stop-opacity:1"
offset="0"
id="stop5055" />
<stop
id="stop5057"
offset="0.23168644"
style="stop-color:#4a6baf;stop-opacity:1" />
<stop
style="stop-color:#5277c3;stop-opacity:1"
offset="1"
id="stop5059" />
</linearGradient>
<linearGradient
id="linearGradient5960"
inkscape:collect="always">
<stop
id="stop5962"
offset="0"
style="stop-color:#637ddf;stop-opacity:1" />
<stop
style="stop-color:#649afa;stop-opacity:1"
offset="0.23168644"
id="stop5964" />
<stop
id="stop5966"
offset="1"
style="stop-color:#719efa;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient5867">
<stop
style="stop-color:#7363df;stop-opacity:1"
offset="0"
id="stop5869" />
<stop
id="stop5871"
offset="0.23168644"
style="stop-color:#6478fa;stop-opacity:1" />
<stop
style="stop-color:#719efa;stop-opacity:1"
offset="1"
id="stop5873" />
</linearGradient>
<linearGradient
y2="515.97058"
x2="282.26105"
y1="338.62445"
x1="213.95642"
gradientTransform="translate(983.36076,601.38885)"
gradientUnits="userSpaceOnUse"
id="linearGradient5855"
xlink:href="#linearGradient5960"
inkscape:collect="always" />
<linearGradient
y2="515.97058"
x2="282.26105"
y1="338.62445"
x1="213.95642"
gradientTransform="translate(-197.75174,-337.1451)"
gradientUnits="userSpaceOnUse"
id="linearGradient5855-8"
xlink:href="#linearGradient5867"
inkscape:collect="always" />
<linearGradient
y2="247.58188"
x2="-702.75317"
y1="102.74675"
x1="-775.20807"
gradientTransform="translate(983.36076,601.38885)"
gradientUnits="userSpaceOnUse"
id="linearGradient4544"
xlink:href="#linearGradient5960"
inkscape:collect="always" />
<clipPath
id="clipPath4501"
clipPathUnits="userSpaceOnUse">
<circle
r="241.06563"
cy="686.09473"
cx="335.13995"
id="circle4503"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#adadad;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</clipPath>
<clipPath
id="clipPath5410"
clipPathUnits="userSpaceOnUse">
<circle
r="241.13741"
cy="340.98975"
cx="335.98114"
id="circle5412"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</clipPath>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5053"
id="linearGradient5137"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(864.55062,-2197.497)"
x1="-584.19934"
y1="782.33563"
x2="-496.29703"
y2="937.71399" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5053"
id="linearGradient5147"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(864.55062,-2197.497)"
x1="-584.19934"
y1="782.33563"
x2="-496.29703"
y2="937.71399" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5562"
id="linearGradient5162"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(70.505061,-1761.3076)"
x1="200.59668"
y1="351.41116"
x2="290.08701"
y2="506.18814" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5562"
id="linearGradient5172"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(70.505061,-1761.3076)"
x1="200.59668"
y1="351.41116"
x2="290.08701"
y2="506.18814" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5562"
id="linearGradient5182"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(70.505061,-1761.3076)"
x1="200.59668"
y1="351.41116"
x2="290.08701"
y2="506.18814" />
<linearGradient
y2="506.18814"
x2="290.08701"
y1="351.41116"
x1="200.59668"
gradientTransform="translate(70.505061,-1761.3076)"
gradientUnits="userSpaceOnUse"
id="linearGradient5201"
xlink:href="#linearGradient5562"
inkscape:collect="always" />
<linearGradient
y2="937.71399"
x2="-496.29703"
y1="782.33563"
x1="-584.19934"
gradientTransform="translate(864.55062,-2197.497)"
gradientUnits="userSpaceOnUse"
id="linearGradient5205"
xlink:href="#linearGradient5053"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98318225"
inkscape:cx="112.8987"
inkscape:cy="191.21582"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2059"
inkscape:window-height="1588"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:snap-global="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:showpageshadow="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="print-logo"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
transform="translate(-156.33871,933.1905)">
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5277c3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 309.40365,-710.2521 122.19683,211.6751 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4902 -33.22946,-57.8256 z"
id="path4861"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#df3c59;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 353.50926,-797.4433 -122.21756,211.6631 -28.53477,-48.37 32.93839,-56.6875 -65.41521,-0.1719 -13.9414,-24.1698 14.23637,-24.721 93.11177,0.2939 33.46371,-57.6903 z"
id="use4863"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#df3c59;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 362.88537,-628.243 244.41439,0.012 -27.62229,48.8968 -65.56199,-0.1817 32.55876,56.7371 -13.96098,24.1585 -28.52722,0.032 -46.3013,-80.7841 -66.69317,-0.1353 z"
id="use4865"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#df3c59;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 505.14318,-720.9886 -122.19683,-211.6751 56.15706,-0.5268 32.6236,56.8692 32.85645,-56.5653 27.90237,0.011 14.29086,24.6896 -46.81047,80.4902 33.22946,57.8256 z"
id="use4867"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
<path
sodipodi:nodetypes="cccccccccc"
inkscape:connector-curvature="0"
id="path4873"
d="m 309.40365,-710.2521 122.19683,211.6751 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4902 -33.22946,-57.8256 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#8e293b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
sodipodi:nodetypes="cccccccccc"
inkscape:connector-curvature="0"
id="use4875"
d="m 451.3364,-803.53264 -244.4144,-0.012 27.62229,-48.89685 65.56199,0.18175 -32.55875,-56.73717 13.96097,-24.15851 28.52722,-0.0315 46.3013,80.78414 66.69317,0.13524 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#8e293b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
sodipodi:nodetypes="cccccccccc"
inkscape:connector-curvature="0"
id="use4877"
d="m 460.87178,-633.8425 122.21757,-211.66304 28.53477,48.37003 -32.93839,56.68751 65.4152,0.1718 13.9414,24.1698 -14.23636,24.7211 -93.11177,-0.294 -33.46371,57.6904 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#8e293b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<g
id="layer2"
inkscape:label="guides"
style="display:none"
transform="translate(72.039038,-1799.4476)">
<path
d="M 460.60629,594.72881 209.74183,594.7288 84.309616,377.4738 209.74185,160.21882 l 250.86446,1e-5 125.43222,217.255 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="1.5707963"
sodipodi:arg1="1.0471976"
sodipodi:r2="217.25499"
sodipodi:r1="250.86446"
sodipodi:cy="377.47382"
sodipodi:cx="335.17407"
sodipodi:sides="6"
id="path6032"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.236;fill:#4e4d52;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
sodipodi:type="star" />
<path
transform="translate(0,-308.26772)"
sodipodi:type="star"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#4e4d52;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
id="path5875"
sodipodi:sides="6"
sodipodi:cx="335.17407"
sodipodi:cy="685.74158"
sodipodi:r1="100.83495"
sodipodi:r2="87.32563"
sodipodi:arg1="1.0471976"
sodipodi:arg2="1.5707963"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 385.59154,773.06721 -100.83495,0 -50.41747,-87.32564 50.41748,-87.32563 100.83495,10e-6 50.41748,87.32563 z" />
<path
transform="translate(0,-308.26772)"
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path5851"
d="m 1216.5591,938.53395 123.0545,228.14035 -42.6807,-1.2616 -43.4823,-79.7725 -39.6506,80.3267 -32.6875,-19.7984 53.4737,-100.2848 -37.1157,-73.88955 z"
style="fill:url(#linearGradient5855);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.415;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c53a3a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect5884"
width="48.834862"
height="226.22897"
x="-34.74221"
y="446.17056"
transform="rotate(-30)" />
<path
transform="translate(0,-308.26772)"
sodipodi:type="star"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.509;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="path3428"
sodipodi:sides="6"
sodipodi:cx="223.93674"
sodipodi:cy="878.63831"
sodipodi:r1="28.048939"
sodipodi:r2="24.291094"
sodipodi:arg1="0"
sodipodi:arg2="0.52359878"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 251.98568,878.63831 -14.02447,24.29109 h -28.04894 l -14.02447,-24.29109 14.02447,-24.2911 h 28.04894 z" />
<use
x="0"
y="0"
xlink:href="#rect5884"
id="use4252"
transform="rotate(60,268.29786,489.4515)"
width="100%"
height="100%" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.650794;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4254"
width="5.3947482"
height="115.12564"
x="545.71014"
y="467.07007"
transform="rotate(30,575.23539,-154.13386)" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 19 KiB

View file

@ -1,4 +1,4 @@
{lib, ...}: { {nixpkgs, ...}: {
schemes = let schemes = let
mkColorScheme = scheme @ { mkColorScheme = scheme @ {
scheme-name, scheme-name,
@ -22,6 +22,7 @@
}: let }: let
base = base =
{ {
# aliases?
text = fg; text = fg;
primary = blue; primary = blue;
urgent = red; urgent = red;
@ -49,14 +50,14 @@
} }
// scheme; // scheme;
in in
base {
// { withHashPrefix = nixpkgs.lib.mapAttrs (_: value: "#${value}") base;
withHashPrefix = lib.mapAttrs (_: value: "#${value}") base; }
}; // base;
in { in {
donokai = mkColorScheme { donokai = mkColorScheme {
scheme-name = "donokai"; scheme-name = "donokai";
bg = "110f0a"; bg = "111111";
bg2 = "181818"; bg2 = "181818";
bg3 = "222222"; bg3 = "222222";
bg4 = "292929"; bg4 = "292929";

View file

@ -22,8 +22,7 @@ git add -A
host=your_host host=your_host
ssh -t "root@$host" "bash -c ' ssh -t "root@$host" "bash -c '
set -m set -m
# sleep 30 mins (sleep 300; reboot;) &
(sleep 1800; reboot;) &
jobs -p jobs -p
bg bg
disown disown
@ -80,7 +79,6 @@ nix-shell --packages git --run "sudo nix run \
# install # install
nix-shell --packages git \ nix-shell --packages git \
--run "sudo nixos-install \ --run "sudo nixos-install \
--no-write-lock-file \
--flake 'git+https://git.lyte.dev/lytedev/nix#${FLAKE_ATTR}' \ --flake 'git+https://git.lyte.dev/lytedev/nix#${FLAKE_ATTR}' \
--option trusted-substituters 'https://cache.nixos.org https://nix.h.lyte.dev' \ --option trusted-substituters 'https://cache.nixos.org https://nix.h.lyte.dev' \
--option trusted-public-keys 'cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= h.lyte.dev:HeVWtne31ZG8iMf+c15VY3/Mky/4ufXlfTpT8+4Xbs0='" --option trusted-public-keys 'cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= h.lyte.dev:HeVWtne31ZG8iMf+c15VY3/Mky/4ufXlfTpT8+4Xbs0='"
@ -108,7 +106,3 @@ $ rsync -r ~/.local/share/password-store $host:~/.local/share/password-store
3. Tailscale connection and roles. 3. Tailscale connection and roles.
4. Firefox sync configured. 4. Firefox sync configured.
# Temporary Firewall Changes
Source: https://discourse.nixos.org/t/how-to-temporarily-open-a-tcp-port-in-nixos/12306/2

View file

@ -0,0 +1,5 @@
{outputs, ...}: {
imports = with outputs.homeManagerModules; [
sway
];
}

View file

@ -0,0 +1,26 @@
{
pkgs,
# colors,
...
}: {
programs.bat = {
enable = true;
config = {
theme = "ansi";
};
# themes = {
# "Catppuccin-mocha" = builtins.readFile (pkgs.fetchFromGitHub
# {
# owner = "catppuccin";
# repo = "bat";
# rev = "477622171ec0529505b0ca3cada68fc9433648c6";
# sha256 = "6WVKQErGdaqb++oaXnY3i6/GuH2FhTgK0v4TN4Y0Wbw=";
# }
# + "/Catppuccin-mocha.tmTheme");
# };
};
home.shellAliases = {
cat = "bat";
};
}

View file

@ -0,0 +1,34 @@
{colors, ...}: {
programs.broot = {
enable = true;
enableFishIntegration = true;
settings = {
modal = true; # vim mode?
verbs = [
{
invocation = "edit";
shortcut = "e";
execution = "$EDITOR {file}";
}
];
skin = with colors.withHashPrefix; {
status_normal_fg = fg;
status_normal_bg = bg;
status_error_fg = red;
status_error_bg = yellow;
tree_fg = red;
selected_line_bg = bg2;
permissions_fg = purple;
size_bar_full_bg = red;
size_bar_void_bg = bg;
directory_fg = yellow;
input_fg = blue;
flag_value_fg = yellow;
table_border_fg = red;
code_fg = yellow;
};
};
};
}

View file

@ -0,0 +1,9 @@
{config, ...}: {
home.file."${config.xdg.configHome}/cargo/config.toml" = {
enable = true;
text = ''
[build]
rustdocflags = ["--default-theme=ayu"];
'';
};
}

View file

@ -0,0 +1,109 @@
{
pkgs,
lib,
system,
inputs,
outputs,
...
}: {
# TODO: fonts? right now they are only handled at the nixos-level (desktop-usage module)
# TODO: wallpaper?
imports = with outputs.homeManagerModules; [
# nix-colors.homeManagerModules.default
fish
bat
helix
git
iex
zellij
broot
nnn
htop
cargo
senpai
tmux
];
# TODO: specify an email?
# accounts.email.accounts = {
# primary = {
# address = "daniel@lyte.dev";
# };
# };
home = {
username = lib.mkDefault "daniel";
homeDirectory = lib.mkDefault "/home/daniel/.home";
stateVersion = lib.mkDefault "23.11";
sessionVariables = {
EDITOR = "hx";
VISUAL = "hx";
PAGER = "less";
MANPAGER = "less";
};
packages = [
# I use gawk for my fish prompt
pkgs.gawk
# text editor
inputs.helix.packages.${system}.helix
# tools I use when editing nix code
pkgs.nil
pkgs.alejandra
(pkgs.buildEnv {
name = "my-scripts-common";
paths = [./scripts/common];
})
];
};
# TODO: not common?
# programs.password-store = {
# enable = true;
# package = pkgs.pass.withExtensions (exts: [exts.pass-otp]);
# };
# programs.gitui = {
# enable = true;
# };
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
programs.eza = {
enable = true;
package = inputs.nixpkgs.legacyPackages.${system}.eza;
};
programs.skim = {
# https://github.com/lotabout/skim/issues/494
enable = false;
enableFishIntegration = true;
defaultOptions = ["--no-clear-start" "--color=16"];
};
programs.fzf = {
# using good ol' fzf until skim sucks less out of the box I guess
enable = true;
enableFishIntegration = true;
# defaultCommand = "fd --type f";
# defaultOptions = ["--height 40%"];
# fileWidgetOptions = ["--preview 'head {}'"];
};
# TODO: regular cron or something?
programs.nix-index = {
enable = true;
enableFishIntegration = true;
};
# maybe we can share somehow so things for nix-y systems and non-nix-y systems alike
# am I going to _have_ non-nix systems anymore?
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
{outputs, ...}: {
imports = with outputs.homeManagerModules; [
kitty
wezterm
];
}

View file

@ -0,0 +1,71 @@
{
config,
lib,
outputs,
...
}: {
imports = with outputs.homeManagerModules; [
melee
sway
hyprland
];
wayland.windowManager.hyprland = {
settings = {
env = [
"EWW_BAR_MON,1"
];
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
monitor = [
"DP-3,3840x2160@120,0x0,1"
];
input = {
force_no_accel = true;
sensitivity = 1; # -1.0 - 1.0, 0 means no modification.
};
};
};
wayland.windowManager.sway = {
config = {
output = {
"GIGA-BYTE TECHNOLOGY CO., LTD. AORUS FO48U 23070B000307" = {
mode = "3840x2160@120Hz";
position = "${toString (builtins.ceil (2160 / 1.5))},0";
};
"Dell Inc. DELL U2720Q D3TM623" = {
# desktop left vertical monitor
mode = "3840x2160@60Hz";
transform = "90";
scale = "1.5";
position = "0,0";
};
};
workspaceOutputAssign =
(
map
(ws: {
output = "GIGA-BYTE TECHNOLOGY CO., LTD. AORUS FO48U 23070B000307";
workspace = toString ws;
})
(lib.range 1 7)
)
++ (
map
(ws: {
output = "Dell Inc. DELL U2720Q D3TM623";
workspace = toString ws;
})
(lib.range 8 9)
);
};
};
ssbm = {
slippi-launcher = {
isoPath = "${config.home.homeDirectory}/../games/roms/dolphin/melee.iso";
};
};
}

View file

@ -0,0 +1,79 @@
{
programs.eww = {
enable = true;
};
home.file.".config/eww/eww.yuck" = {
enable = true;
text = ''
(defwidget bar []
(centerbox :orientation "h"
(sidestuff)
(box)
(music)))
(defwindow bar
:monitor 0
:stacking "fg"
:exclusive true
:geometry
(geometry
:x "0%"
:y "0%"
:width "100%"
:height "31px"
:anchor "bottom center")
(bar))
(defwidget sidestuff []
(box :class "sidestuff" :orientation "h" :space-evenly false :halign "start" :spacing 20
time
; TODO: idle inhibitor?
; TODO: get these to align properly?
(box :class "mic" (
box :class {micMuted == "false" ? "live" : "muted"} {micMuted == "false" ? " " : " "}
) {micVolume + "%"}
)
(box :class "vol" (
box :class {muted == "false" ? "live" : "muted"} {muted == "false" ? "󰕾 " : "󰖁 "}
) {volume + "%"}
)
{" " + round(EWW_CPU["avg"], 0) + "%"}
{" " + round(EWW_RAM["used_mem_perc"], 0) + "%"}
{isDesktop == "true" ? "" : " " + brightness + "%"}
{isDesktop == "true" ? "" : "󱊣 " + EWW_BATTERY["BAT0"]["capacity"] + "%/" + EWW_BATTERY["BAT1"]["capacity"] + "%"}
))
(defwidget music []
(box :class "music"
:orientation "h"
:halign "end"
:space-evenly false
{music != "" ? "''${music}" : ""}))
(deflisten music :initial ""
"playerctl --follow metadata --format '{{ title }} by {{ artist }}' || true")
(deflisten volume :initial "0"
"pamixer --get-volume; pactl subscribe | grep sink --line-buffered | while read i; do pamixer --get-volume; done")
(deflisten muted :initial "false"
"pamixer --get-mute; pactl subscribe | grep sink --line-buffered | while read i; do pamixer --get-mute; done")
(deflisten micVolume :initial "0"
"pamixer --default-source --get-volume; pactl subscribe | grep source --line-buffered | while read i; do pamixer --default-source --get-volume; done")
(deflisten micMuted :initial "false"
"pamixer --default-source --get-mute; pactl subscribe | grep source --line-buffered | while read i; do pamixer --default-source --get-mute; done")
(defpoll time :interval "1s"
"date '+%a %b %d %H:%M:%S'")
(defpoll isDesktop :interval "24h"
"if [ -d \"$HOME/.config/lytedev-env/host-desktop\" ]; then echo true; else echo false; fi")
(defpoll brightness :interval "10s"
"echo $(((100 * $(brightnessctl get)) / $(brightnessctl max)))")
'';
};
}

View file

@ -38,8 +38,8 @@ $rosewater: #f5e0dc;
font-size: 12.0pt; font-size: 12.0pt;
} }
.leftsidestuff slider { .sidestuff slider {
color: $sapphire; color: #ffd5cd;
} }
.metric {} .metric {}
@ -75,34 +75,10 @@ $rosewater: #f5e0dc;
.vol .muted, .vol .muted,
.mic .live { .mic .live {
color: $red; color: #f38ba8;
} }
.vol .live, .vol .live,
.mic .muted { .mic .muted {
color: $sapphire; color: #74c7ec;
}
.workspace {
/* height: 100%; */
padding-left: 10px;
padding-right: 10px;
color: #666666;
}
.workspace.occupied {
color: $text;
}
.workspace.occupied.active,
.workspace.active {
color: $base;
background-color: $subtext1;
}
.workspace.occupied.focused.active,
.workspace.occupied.focused,
.workspace.focused {
color: $base;
background-color: $sapphire;
} }

View file

@ -1,9 +1,8 @@
(defwidget bar [] (defwidget bar []
(centerbox :orientation "h" (centerbox :orientation "h"
(leftsidestuff) (sidestuff)
(box) (box)
(rightsidestuff) (music)))
))
(defwindow bar0 (defwindow bar0
:monitor 0 :monitor 0
@ -14,7 +13,7 @@
:x "0%" :x "0%"
:y "0%" :y "0%"
:width "100%" :width "100%"
:height "32px" :height "31px"
:anchor "bottom center") :anchor "bottom center")
(bar)) (bar))
@ -27,35 +26,27 @@
:x "0%" :x "0%"
:y "0%" :y "0%"
:width "100%" :width "100%"
:height "32px" :height "31px"
:anchor "bottom center") :anchor "bottom center")
(bar)) (bar))
(defwidget rightsidestuff [] (defwidget sidestuff []
(box :class "rightsidestuff" :orientation "h" :space-evenly false :halign "end" :valign "center" :spacing 10 (box :class "sidestuff" :orientation "h" :space-evenly false :halign "start" :spacing 20
(music)
(systray)
))
(defwidget leftsidestuff []
(box :class "leftsidestuff" :orientation "h" :space-evenly false :halign "start" :valign "center" :spacing 10
time time
; TODO: idle inhibitor? ; TODO: idle inhibitor?
; TODO: get these to align properly? icons seem lower than they should be? ; TODO: get these to align properly?
(box :class "mic" ( (box :class "mic" (
box :class {micMuted == "false" ? "live" : "muted"} {micMuted == "false" ? " " : " "} box :class {micMuted == "false" ? "live" : "muted"} {micMuted == "false" ? " " : " "}
) {"${micVolume}%"} ) {micVolume + "%"}
) )
(box :class "vol" ( (box :class "vol" (
box :class {muted == "false" ? "live" : "muted"} {muted == "false" ? "󰕾 " : "󰖁 "} box :class {muted == "false" ? "live" : "muted"} {muted == "false" ? "󰕾 " : "󰖁 "}
) {"${volume}%"} ) {volume + "%"}
) )
{" ${round(EWW_CPU["avg"], 0)}%"} {" " + round(EWW_CPU["avg"], 0) + "%"}
{" ${round(EWW_RAM["used_mem_perc"], 0)}%"} {" " + round(EWW_RAM["used_mem_perc"], 0) + "%"}
; TODO: have these "widgets" be omitted entirely instead of just empty strings {isDesktop == "true" ? "" : " " + brightness + "%"}
{(showBrightness == "true") ? (" ${brightness}%") : ""} {isDesktop == "true" ? "" : "󱊣 " + EWW_BATTERY["BAT1"]["capacity"] + "%"}
{(showBattery == "true") ? ("󱊣 ${EWW_BATTERY["BAT1"]["capacity"]}% (${batteryTime})") : ""}
(box :orientation "h" :space-evenly false :halign "start" :valign "center" (workspaces))
)) ))
(defwidget music [] (defwidget music []
@ -80,26 +71,14 @@
(deflisten micMuted :initial "false" (deflisten micMuted :initial "false"
"pamixer --default-source --get-mute; pactl subscribe | grep source --line-buffered | while read i; do pamixer --default-source --get-mute; done") "pamixer --default-source --get-mute; pactl subscribe | grep source --line-buffered | while read i; do pamixer --default-source --get-mute; done")
; "upower -d | rg '\\s*(time to empty|time to full):\\s*(\\d.*)\$' -r '\$2'; upower --monitor-detail | rg '\\s*(time to empty|time to full):\\s*(\\d.*)\$' -r '\$2'")
; (deflisten batteryTime :initial "unknown"
; "upower -d | rg '\s*time to empty:\s*(\d.*)\$' -r '\$1'; upower --monitor-detail | rg '\\s*time to empty:\\s*(\\d.*)\$' -r '\$1'")
(defpoll time :interval "1s" (defpoll time :interval "1s"
"date '+%a %b %d %H:%M:%S'") "date '+%a %b %d %H:%M:%S'")
(defpoll showBrightness :interval "24h" (defpoll isDesktop :interval "24h"
; if we have at least one file in /sys/class/backlight, we should try and show brightness "if [ -d \"$HOME/.config/lytedev-env/host-desktop\" ]; then echo true; else echo false; fi")
"if [ \"$(find /sys/class/backlight -mindepth 1 -maxdepth 1 | head -n 1 | wc -l)\" == \"1\" ]; then echo true; else echo false; fi")
(defpoll showBattery :interval "24h"
; if we have at least one battery in /sys/class/power_supply, we should try and show battery levels
"if find /sys/class/power_supply -mindepth 1 -maxdepth 1 2>&1 | rg '\/sys\/class\/power_supply\/BAT' 2>&1 > /dev/null; then echo true; else echo false; fi")
(defpoll brightness :interval "10s" (defpoll brightness :interval "10s"
"echo $(((100 * $(brightnessctl get)) / $(brightnessctl max)))") "echo $(((100 * $(brightnessctl get)) / $(brightnessctl max)))")
(deflisten batteryTime :initial "unknown" "scripts/battery-time.bash") (defpoll monitor :interval "60s"
"echo $EWW_BAR_MON")
(deflisten workspace "scripts/hypr-workspaces.bash")
(defwidget workspaces [] (literal :content workspace))

View file

@ -1,3 +0,0 @@
#!/usr/bin/env bash
{ upower -d; upower --monitor-detail; } \
| rg '\s*time to.*:\s*(\d.*)\s*$' -r '$1'

View file

@ -1,70 +0,0 @@
#!/usr/bin/env bash
# TODO: we're mixing bash arrays and not-arrays - get it together
#define icons for workspaces 1-9
ic=(1 2 3 4 5 6 7 8 9)
occ() { export o"$1"="occupied"; }
unocc() { unset -v o"$1"; }
active() { export a"$1"="active"; }
unactive() { unset -v a"$1"; }
focus() { export f"$1"="focused"; }
unfocus() { unset -v f"$1"; }
workspaces() {
for num in 1 2 3 4 5 6 7 8 9; do
unfocus $num
unactive $num
unocc $num
done
# TODO: avoid recomputing these each time and actually listen to the events?
mons_json=$(hyprctl monitors -j)
for num in $(hyprctl workspaces -j | jq -r '.[] | select(.windows > 0) | .id'); do
occ "$num"
done
for num in $(echo "$mons_json" | jq -r '.[].activeWorkspace.id'); do
active "$num"
done
for num in $(echo "$mons_json" | jq -r '.[] | select(.focused) | .activeWorkspace.id'); do
focus "$num"
done
# TODO: would be nice to have monitors' workspaces show up in left-to-right
# order as laid out in physical/pixel space
# this would make glancing at the workspace indicator more intuitive
# TODO: might be nice to exclude certain windows as counting towards "occupation" such as xwaylandvideobridge or w/e
# NOTE: maybe I can group workspaces by their monitor with some mechanism for "unassigned" workspace to show up by a "primary" monitor
# render eww widget
echo "(eventbox :onscroll \"echo {} | sed -e 's/up/-1/g' -e 's/down/+1/g' | xargs hyprctl dispatch workspace\" \
(box :class \"workspaces\" :orientation \"h\" :spacing 0 :space-evenly \"true\" \
(button :onclick \"hyprctl dispatch workspace 1\" :onrightclick \"hyprctl dispatch workspace 1\" :class \"workspace $a1 $o1 $f1\" \"${ic[0]}\") \
(button :onclick \"hyprctl dispatch workspace 2\" :onrightclick \"hyprctl dispatch workspace 2\" :class \"workspace $a2 $o2 $f2\" \"${ic[1]}\") \
(button :onclick \"hyprctl dispatch workspace 3\" :onrightclick \"hyprctl dispatch workspace 3\" :class \"workspace $a3 $o3 $f3\" \"${ic[2]}\") \
(button :onclick \"hyprctl dispatch workspace 4\" :onrightclick \"hyprctl dispatch workspace 4\" :class \"workspace $a4 $o4 $f4\" \"${ic[3]}\") \
(button :onclick \"hyprctl dispatch workspace 5\" :onrightclick \"hyprctl dispatch workspace 5\" :class \"workspace $a5 $o5 $f5\" \"${ic[4]}\") \
(button :onclick \"hyprctl dispatch workspace 6\" :onrightclick \"hyprctl dispatch workspace 6\" :class \"workspace $a6 $o6 $f6\" \"${ic[5]}\") \
(button :onclick \"hyprctl dispatch workspace 7\" :onrightclick \"hyprctl dispatch workspace 7\" :class \"workspace $a7 $o7 $f7\" \"${ic[6]}\") \
(button :onclick \"hyprctl dispatch workspace 8\" :onrightclick \"hyprctl dispatch workspace 8\" :class \"workspace $a8 $o8 $f8\" \"${ic[7]}\") \
(button :onclick \"hyprctl dispatch workspace 9\" :onrightclick \"hyprctl dispatch workspace 9\" :class \"workspace $a9 $o9 $f9\" \"${ic[8]}\") \
) \
)"
}
# initial render
workspaces
# listen to events and re-render
while true; do
# TODO: not sure why this socat | read invocation seems to stop?
socat - "UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" | while read -r line; do
workspaces "$line"
done
done
echo '(box "DONE")'

View file

@ -0,0 +1,7 @@
{pkgs, ...}: {
programs.eww = {
enable = true;
package = pkgs.eww-wayland;
configDir = ./eww;
};
}

View file

@ -0,0 +1,52 @@
{pkgs, ...}: {
programs.firefox = {
# TODO: this should be able to work on macos, no?
# TODO: enable dark theme by default
enable = true;
# TODO: uses nixpkgs.pass so pass otp doesn't work
package = pkgs.firefox.override {nativeMessagingHosts = [pkgs.passff-host];};
# extensions = with pkgs.nur.repos.rycee.firefox-addons; [
# ublock-origin
# ]; # TODO: would be nice to have _all_ my firefox stuff managed here instead of Firefox Sync maybe?
profiles = {
daniel = {
id = 0;
settings = {
"general.smoothScroll" = true;
};
extraConfig = ''
user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);
// user_pref("full-screen-api.ignore-widgets", true);
user_pref("media.ffmpeg.vaapi.enabled", true);
user_pref("media.rdd-vpx.enabled", true);
'';
userChrome = ''
#TabsToolbar {
visibility: collapse;
}
#webrtcIndicator {
display: none;
}
#main-window[tabsintitlebar="true"]:not([extradragspace="true"]) #TabsToolbar>.toolbar-items {
opacity: 0;
pointer-events: none;
}
#main-window:not([tabsintitlebar="true"]) #TabsToolbar {
visibility: collapse !important;
}
'';
# userContent = ''
# '';
};
};
};
}

View file

@ -0,0 +1,78 @@
{
programs.fish = {
enable = true;
# I load long scripts from files for a better editing experience
shellInit = builtins.readFile ./fish/shellInit.fish;
interactiveShellInit = builtins.readFile ./fish/interactiveShellInit.fish;
loginShellInit = "";
functions = {
# TODO: I think these should be loaded from fish files too for better editor experience?
d = ''
# --wraps=cd --description "Quickly jump to NICE_HOME (or given relative or absolute path) and list files."
if count $argv > /dev/null
cd $argv
else
cd $NICE_HOME
end
la
'';
c = ''
if count $argv > /dev/null
cd $NICE_HOME && d $argv
else
d $NICE_HOME
end
'';
ltl = ''
set d $argv[1] .
set -l l ""
for f in $d[1]/*
if test -z $l; set l $f; continue; end
if command test $f -nt $l; and test ! -d $f
set l $f
end
end
echo $l
'';
has_command = "command --quiet --search $argv[1]";
};
shellAbbrs = {};
shellAliases = {
l = "br";
ls = "eza --group-directories-first --classify";
la = "eza -la --group-directories-first --classify";
lA = "eza -la --all --group-directories-first --classify";
tree = "eza --tree --level=3";
lt = "eza -l --sort=modified";
lat = "eza -la --sort=modified";
lc = "lt --sort=accessed";
lT = "lt --reverse";
lC = "lc --reverse";
lD = "la --only-dirs";
"cd.." = "d ..";
"cdc" = "d $XDG_CONFIG_HOME";
"cdn" = "d $NOTES_PATH";
"cdl" = "d $XDG_DOWNLOAD_DIR";
"cdg" = "d $XDG_GAMES_DIR";
".." = "d ..";
"..." = "d ../..";
"...." = "d ../../..";
"....." = "d ../../../..";
"......" = "d ../../../../..";
"......." = "d ../../../../../..";
"........" = "d ../../../../../../..";
"........." = "d ../../../../../../../..";
p = "ping";
dc = "docker compose";
pc = "podman-compose";
k = "kubectl";
kg = "kubectl get";
v = "$EDITOR";
sv = "sudo $EDITOR";
kssh = "kitty +kitten ssh";
};
};
}

View file

@ -14,24 +14,19 @@ function fish_greeting
end end
function preprocess_pwd function preprocess_pwd
test (pwd) = / && echo / && return 1 test (pwd) = / && echo "/" && return 1
test (pwd) = $NICE_HOME && echo "~" && return 0 test (pwd) = $NICE_HOME && echo "~" && return 0
pwd \ pwd \
| cut -c2- \ | cut -c2- \
| gawk '{n=split($0,p,"/");for(i=1;i<=n;i++){if(i==n){printf "/%s",p[i]}else{printf "/%.3s",p[i]}}}' | gawk '{n=split($0,p,"/");for(i=1;i<=n;i++){if(i==n){printf "/%s",p[i]}else{printf "/%.3s",p[i]}}}'
end end
function _maybe_elevated_access_prefix function _maybe_sudo_prefix
if set -q SUDO_USER if set -q SUDO_USER
set_color -b yellow black set_color -b yellow black
printf " SUDO " printf " SUDO "
set_color -b normal normal set_color -b normal normal
printf " " printf " "
else if test $USER = root
set_color -b red black
printf " ROOT "
set_color -b normal normal
printf " "
end end
end end
@ -61,9 +56,6 @@ end
function _last_cmd_duration function _last_cmd_duration
set_color -b normal green set_color -b normal green
set -q CMD_DURATION && printf " %dms" $CMD_DURATION set -q CMD_DURATION && printf " %dms" $CMD_DURATION
if test $CMD_DURATION -gt 5000
printf "\e]777;notify;%s;%s\e\\" "WezTerm: Command Finished" (history --max 1)
end
end end
function _maybe_jobs_summary function _maybe_jobs_summary
@ -119,7 +111,7 @@ function fish_prompt
set last_cmd_status $status set last_cmd_status $status
_prompt_marker _prompt_marker
_prompt_prefix _prompt_prefix
_maybe_elevated_access_prefix _maybe_sudo_prefix
_user_and_host $last_cmd_status _user_and_host $last_cmd_status
_cur_work_dir _cur_work_dir
_maybe_git_summary _maybe_git_summary
@ -129,10 +121,8 @@ function fish_prompt
_user_prompt _user_prompt
end end
function fish_mode_prompt function fish_mode_prompt; end
end function fish_right_prompt; end
function fish_right_prompt
end
# key bindings # key bindings
fish_vi_key_bindings fish_vi_key_bindings
@ -147,19 +137,15 @@ bind --mode insert --sets-mode default jk repaint
bind --mode insert --sets-mode default jK repaint bind --mode insert --sets-mode default jK repaint
bind --mode insert --sets-mode default Jk repaint bind --mode insert --sets-mode default Jk repaint
bind --mode insert --sets-mode default JK repaint bind --mode insert --sets-mode default JK repaint
# bind --mode insert --sets-mode default jj repaint bind --mode insert --sets-mode default jj repaint
# bind --mode insert --sets-mode default jJ repaint bind --mode insert --sets-mode default jJ repaint
# bind --mode insert --sets-mode default Jj repaint bind --mode insert --sets-mode default Jj repaint
# bind --mode insert --sets-mode default JJ repaint bind --mode insert --sets-mode default JJ repaint
if has_command skim if has_command skim
bind -M insert \cg skim-cd-widget bind -M insert \cg skim-cd-widget
end end
if has_command fzf
bind -M insert \cg fzf-cd-widget
end
bind -M insert \cp up-or-search bind -M insert \cp up-or-search
bind -M insert \cn down-or-search bind -M insert \cn down-or-search
bind -M insert \ce end-of-line bind -M insert \ce end-of-line

View file

@ -33,7 +33,7 @@ set --export --universal EXA_COLORS '*=0'
set --export --universal ERL_AFLAGS "-kernel shell_history enabled -kernel shell_history_file_bytes 1024000" set --export --universal ERL_AFLAGS "-kernel shell_history enabled -kernel shell_history_file_bytes 1024000"
set --export --universal BROWSER (which firefox) set --export --universal BROWSER firefox
set --export --universal SOPS_AGE_KEY_FILE "$XDG_CONFIG_HOME/sops/age/keys.txt" set --export --universal SOPS_AGE_KEY_FILE "$XDG_CONFIG_HOME/sops/age/keys.txt"
@ -42,8 +42,6 @@ if has_command skim
set --export --universal SKIM_CTRL_T_COMMAND "fd --hidden" set --export --universal SKIM_CTRL_T_COMMAND "fd --hidden"
end end
set --export --universal NEWT_COLORS "root=black,black:border=black,blue"
# colors # colors
set -U fish_color_normal normal # default color set -U fish_color_normal normal # default color
set -U fish_color_command white # base command being run (>ls< -la) set -U fish_color_command white # base command being run (>ls< -la)
@ -68,10 +66,6 @@ set -U fish_pager_color_prefix blue # the string being completed
set -U fish_pager_color_progress white\x1e\x2d\x2dbackground\x3d333 # status indicator at the bottom set -U fish_pager_color_progress white\x1e\x2d\x2dbackground\x3d333 # status indicator at the bottom
# set -U fish_pager_color_secondary \x2d\x2dbackground\x3d181818 # alternating rows # set -U fish_pager_color_secondary \x2d\x2dbackground\x3d181818 # alternating rows
if test -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.fish'
source '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.fish'
end
function has_command --wraps=command --description "Exits non-zero if the given command cannot be found" function has_command --wraps=command --description "Exits non-zero if the given command cannot be found"
command --quiet --search $argv[1] command --quiet --search $argv[1]
end end
@ -80,9 +74,6 @@ if has_command rtx
rtx activate fish | source rtx activate fish | source
end end
for dir in ~/.cargo/bin ~/.nimble/bin ~/.local/bin /opt/homebrew/bin for dir in ~/.cargo/bin ~/.nimble/bin ~/.local/bin
test -d $dir && fish_add_path $dir fish_add_path $dir
end end
# don't let other users read my files by default
umask 077

View file

@ -0,0 +1,33 @@
{outputs, ...}: let
scale = 1.25;
in {
imports = with outputs.homeManagerModules; [
sway
sway-laptop
# hyprland
];
home = {
stateVersion = "24.05";
};
wayland.windowManager.hyprland = {
settings = {
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
monitor = [
"eDP-1,2256x1504@60,0x0,${toString scale}"
];
};
};
wayland.windowManager.sway = {
config = {
output = {
"BOE 0x0BCA Unknown" = {
mode = "2256x1504@60Hz";
scale = toString scale;
};
};
};
};
}

View file

@ -0,0 +1,84 @@
{lib, ...}: let
email = lib.mkDefault "daniel@lyte.dev";
in {
programs.git = {
enable = true;
userEmail = email;
userName = lib.mkDefault "Daniel Flanagan";
delta = {
enable = true;
options = {};
};
lfs = {
enable = true;
};
signing = {
signByDefault = true;
key = email;
};
aliases = {
a = "add -A";
ac = "commit -a";
b = "rev-parse --symbolic-full-name HEAD";
c = "commit";
cm = "commit -m";
cnv = "commit --no-verify";
co = "checkout";
d = "diff";
ds = "diff --staged";
dt = "difftool";
f = "fetch";
l = "log --graph --abbrev-commit --decorate --oneline --all";
plainlog = " log --pretty=format:'%h %ad%x09%an%x09%s' --date=short --decorate";
ls = "ls-files";
mm = "merge master";
p = "push";
pf = "push --force-with-lease";
pl = "pull";
rim = "rebase -i master";
s = "status";
};
extraConfig = {
push = {
autoSetupRemote = true;
};
branch = {
autoSetupMerge = true;
};
sendemail = {
smtpserver = "smtp.mailgun.org";
smtpuser = email;
smtrpencryption = "tls";
smtpserverport = 587;
};
url = {
# TODO: how to have per-machine not-in-git configuration?
"git@git.hq.bill.com:" = {
insteadOf = "https://git.hq.bill.com";
};
};
};
};
programs.fish.functions = {
g = {
wraps = "git";
body = ''
if test (count $argv) -gt 0
git $argv
else
git status
end
'';
};
};
}

View file

@ -0,0 +1,459 @@
{
inputs,
colors,
system,
...
}: {
programs.helix = {
enable = true;
package = inputs.helix.packages.${system}.helix;
languages = {
language-server = {
lexical = {
command = "lexical";
args = ["start"];
};
# next-ls = {
# command = "next-ls";
# args = ["--stdout"];
# };
# deno = {
# command = "deno";
# args = ["lsp"];
# config = {
# enable = true;
# lint = true;
# unstable = true;
# };
# };
};
language = [
{
name = "elixir";
language-servers = ["lexical"]; # "lexical" "next-ls" ?
auto-format = true;
}
{
name = "html";
auto-format = false;
}
{
name = "nix";
auto-format = true;
formatter = {
command = "alejandra";
args = ["-"];
};
}
{
name = "fish";
auto-format = true;
indent = {
tab-width = 2;
unit = "\t";
};
}
# {
# name = "javascript";
# language-id = "javascript";
# grammar = "javascript";
# scope = "source.js";
# injection-regex = "^(js|javascript)$";
# file-types = ["js" "mjs"];
# shebangs = ["deno"];
# language-servers = ["deno"];
# roots = ["deno.jsonc" "deno.json"];
# formatter = {
# command = "deno";
# args = ["fmt"];
# };
# auto-format = true;
# comment-token = "//";
# indent = {
# tab-width = 2;
# unit = "\t";
# };
# }
# {
# name = "typescript";
# language-id = "typescript";
# grammar = "typescript";
# scope = "source.ts";
# injection-regex = "^(ts|typescript)$";
# file-types = ["ts"];
# shebangs = ["deno"];
# language-servers = ["deno"];
# roots = ["deno.jsonc" "deno.json"];
# formatter = {
# command = "deno";
# args = ["fmt"];
# };
# auto-format = true;
# comment-token = "//";
# indent = {
# tab-width = 2;
# unit = "\t";
# };
# }
# {
# name = "jsonc";
# language-id = "json";
# grammar = "jsonc";
# scope = "source.jsonc";
# injection-regex = "^(jsonc)$";
# roots = ["deno.jsonc" "deno.json"];
# file-types = ["jsonc"];
# language-servers = ["deno"];
# indent = {
# tab-width = 2;
# unit = " ";
# };
# auto-format = true;
# }
];
};
settings = {
theme = "custom";
editor = {
soft-wrap.enable = true;
auto-pairs = false;
# auto-save = false;
# completion-trigger-len = 1;
# color-modes = false;
bufferline = "multiple";
# scrolloff = 8;
rulers = [81 121];
cursorline = true;
cursor-shape = {
normal = "block";
insert = "bar";
select = "underline";
};
file-picker.hidden = false;
indent-guides = {
render = true;
character = "";
};
lsp = {
display-messages = true;
# display-inlay-hints = true;
};
statusline = {
separator = " ";
mode = {
"normal" = "N";
"insert" = "I";
"select" = "S";
};
left = [
"file-name"
"mode"
# "selections"
# "primary-selection-length"
# "position"
# "position-percentage"
"spinner"
"diagnostics"
"workspace-diagnostics"
];
};
# center = ["file-name"];
# right = ["version-control" "total-line-numbers" "file-encoding"];
# };
};
keys = {
insert = {
j = {
k = "normal_mode";
j = "normal_mode";
K = "normal_mode";
J = "normal_mode";
};
};
normal = {
"C-k" = "jump_view_up";
"C-j" = "jump_view_down";
"C-h" = "jump_view_left";
"C-l" = "jump_view_right";
"C-q" = ":quit-all!";
# "L" = "repeat_last_motion";
space = {
q = ":reflow 80";
Q = ":reflow 120";
C = ":bc!";
h = ":toggle lsp.display-inlay-hints";
# O = ["select_textobject_inner WORD", ":pipe-to xargs xdg-open"];
};
};
select = {
space = {
q = ":reflow 80";
Q = ":reflow 120";
};
# "L" = "repeat_last_motion";
};
};
};
themes = with colors.withHashPrefix; {
custom = {
"type" = orange;
"constructor" = blue;
"constant" = orange;
"constant.builtin" = orange;
"constant.character" = yellow;
"constant.character.escape" = orange;
"string" = green;
"string.regexp" = orange;
"string.special" = blue;
"comment" = {
fg = fgdim;
modifiers = ["italic"];
};
"variable" = text;
"variable.parameter" = {
fg = red;
modifiers = ["italic"];
};
"variable.builtin" = red;
"variable.other.member" = text;
"label" = blue;
"punctuation" = fgdim;
"punctuation.special" = blue;
"keyword" = purple;
"keyword.storage.modifier.ref" = yellow;
"keyword.control.conditional" = {
fg = purple;
modifiers = ["italic"];
};
"operator" = blue;
"function" = blue;
"function.macro" = purple;
"tag" = purple;
"attribute" = blue;
"namespace" = {
fg = blue;
modifiers = ["italic"];
};
"special" = blue;
"markup.heading.marker" = {
fg = orange;
modifiers = ["bold"];
};
"markup.heading.1" = blue;
"markup.heading.2" = yellow;
"markup.heading.3" = green;
"markup.heading.4" = orange;
"markup.heading.5" = red;
"markup.heading.6" = fg3;
"markup.list" = purple;
"markup.bold" = {modifiers = ["bold"];};
"markup.italic" = {modifiers = ["italic"];};
"markup.strikethrough" = {modifiers = ["crossed_out"];};
"markup.link.url" = {
fg = red;
modifiers = ["underlined"];
};
"markup.link.text" = blue;
"markup.raw" = red;
"diff.plus" = green;
"diff.minus" = red;
"diff.delta" = blue;
"ui.linenr" = {fg = fgdim;};
"ui.linenr.selected" = {fg = fg2;};
"ui.statusline" = {
fg = fgdim;
bg = bg;
};
"ui.statusline.inactive" = {
fg = fg3;
bg = bg2;
};
"ui.statusline.normal" = {
fg = bg;
bg = purple;
modifiers = ["bold"];
};
"ui.statusline.insert" = {
fg = bg;
bg = green;
modifiers = ["bold"];
};
"ui.statusline.select" = {
fg = bg;
bg = red;
modifiers = ["bold"];
};
"ui.popup" = {
fg = text;
bg = bg2;
};
"ui.window" = {fg = fgdim;};
"ui.help" = {
fg = fg2;
bg = bg2;
};
"ui.bufferline" = {
fg = fgdim;
bg = bg2;
};
"ui.bufferline.background" = {bg = bg2;};
"ui.text" = text;
"ui.text.focus" = {
fg = text;
bg = bg3;
modifiers = ["bold"];
};
"ui.text.inactive" = {fg = fg2;};
"ui.virtual" = fg2;
"ui.virtual.ruler" = {bg = bg3;};
"ui.virtual.indent-guide" = bg3;
"ui.virtual.inlay-hint" = {
fg = bg3;
bg = bg;
};
"ui.selection" = {bg = bg5;};
"ui.cursor" = {
fg = bg;
bg = text;
};
"ui.cursor.primary" = {
fg = bg;
bg = red;
};
"ui.cursor.match" = {
fg = orange;
modifiers = ["bold"];
};
"ui.cursor.primary.normal" = {
fg = bg;
bg = text;
};
"ui.cursor.primary.insert" = {
fg = bg;
bg = text;
};
"ui.cursor.primary.select" = {
fg = bg;
bg = text;
};
"ui.cursor.normal" = {
fg = bg;
bg = fg;
};
"ui.cursor.insert" = {
fg = bg;
bg = fg;
};
"ui.cursor.select" = {
fg = bg;
bg = fg;
};
"ui.cursorline.primary" = {bg = bg3;};
"ui.highlight" = {
bg = bg3;
fg = bg;
modifiers = ["bold"];
};
"ui.menu" = {
fg = fg3;
bg = bg2;
};
"ui.menu.selected" = {
fg = text;
bg = bg3;
modifiers = ["bold"];
};
"diagnostic.error" = {
underline = {
color = red;
style = "curl";
};
};
"diagnostic.warning" = {
underline = {
color = orange;
style = "curl";
};
};
"diagnostic.info" = {
underline = {
color = blue;
style = "curl";
};
};
"diagnostic.hint" = {
underline = {
color = blue;
style = "curl";
};
};
error = red;
warning = orange;
info = blue;
hint = yellow;
"ui.background" = {
bg = bg;
fg = fgdim;
};
# "ui.cursorline.primary" = { bg = "default" }
# "ui.cursorline.secondary" = { bg = "default" }
"ui.cursorcolumn.primary" = {bg = bg3;};
"ui.cursorcolumn.secondary" = {bg = bg3;};
"ui.bufferline.active" = {
fg = primary;
bg = bg3;
underline = {
color = primary;
style = "";
};
};
};
};
};
}

View file

@ -0,0 +1,14 @@
{
programs.htop = {
enable = true;
settings = {
hide_kernel_threads = 1;
hide_userland_threads = 1;
show_program_path = 0;
header_margin = 0;
show_cpu_frequency = 1;
highlight_base_name = 1;
tree_view = 0;
};
};
}

View file

@ -1,18 +1,12 @@
{ {
pkgs, outputs,
style, colors,
config, config,
lib, lib,
# font, # font,
... ...
}: let }: {
inherit (style) colors; imports = [outputs.homeManagerModules.ewwbar];
in {
# TODO: Hyprland seems to sometimes use a ton of CPU?
home.packages = with pkgs; [
swayosd
];
home.file."${config.xdg.configHome}/hypr/hyprpaper.conf" = { home.file."${config.xdg.configHome}/hypr/hyprpaper.conf" = {
enable = true; enable = true;
@ -29,6 +23,8 @@ in {
monitor = [ monitor = [
# See https://wiki.hyprland.org/Configuring/Monitors/ # See https://wiki.hyprland.org/Configuring/Monitors/
",preferred,auto,auto" ",preferred,auto,auto"
"desc:LG Display 0x0521,3840x2160@120,0x0,1"
"desc:Dell Inc. DELL U2720Q D3TM623,3840x2160@60,3840x0,1.5,transform,3"
]; ];
xwayland = { xwayland = {
@ -38,39 +34,59 @@ in {
exec-once = [ exec-once = [
"hyprpaper" "hyprpaper"
"mako" "mako"
"swayosd-server" "eww daemon && eww open bar$EWW_BAR_MON"
"eww daemon" "firefox"
"[workspace 1 silent] firefox" "kitty --single-instance"
"[workspace 1 silent] wezterm" # "wezterm"
"xwaylandvideobridge" (lib.concatStringsSep " " [
"systemctl --user import-environment QT_QPA_PLATFORMTHEME" "swayidle -w"
"hypridle" "timeout 300 'notify-send \"Idling in 300 seconds\"'"
"resume 'notify-send \"Idling cancelled.\"'"
"timeout 480 'notify-send -u critical \"Idling in 120 seconds\"'"
"timeout 510 'notify-send -u critical \"Idling in 90 seconds\"'"
"timeout 540 'notify-send -u critical \"Idling in 60 seconds!\"'"
"timeout 570 'notify-send -u critical \"Idling in 30 seconds!\"'"
"timeout 590 'notify-send -u critical \"Idling in 10 seconds!\"'"
"timeout 591 'notify-send -u critical \"Idling in 9 seconds!\"'"
"timeout 592 'notify-send -u critical \"Idling in 8 seconds!\"'"
"timeout 593 'notify-send -u critical \"Idling in 7 seconds!\"'"
"timeout 594 'notify-send -u critical \"Idling in 6 seconds!\"'"
"timeout 595 'notify-send -u critical \"Idling in 5 seconds!\"'"
"timeout 596 'notify-send -u critical \"Idling in 4 seconds!\"'"
"timeout 597 'notify-send -u critical \"Idling in 3 seconds!\"'"
"timeout 598 'notify-send -u critical \"Idling in 2 seconds!\"'"
"timeout 599 'notify-send -u critical \"Idling in 1 second!\"'"
"timeout 600 'swaylock --daemonize'"
"timeout 600 'hyprctl dispatch dpms off'"
"resume 'hyprctl dispatch dpms on'"
# "resume 'maybe-good-morning'"
"before-sleep 'swaylock --daemonize'"
])
''swayidle -w timeout 600 'notify-send "Locking in 30 seconds..."' timeout 630 'swaylock -f' timeout 660 'hyprctl dispatch dpms off' resume 'hyprctl dispatch dpms on && maybe-good-morning' before-sleep 'swaylock -f'"''
"dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP"
]; ];
env = [ env = [
"XCURSOR_SIZE,24" "XCURSOR_SIZE,24"
"EWW_BAR_MON,0"
]; ];
input = { input = {
kb_layout = "us"; kb_layout = "us";
kb_options = "ctrl:nocaps"; kb_options = "ctrl:nocaps";
# kb_variant =
/* # kb_model =
kb_variant = # kb_rules =
kb_model =
kb_rules =
*/
follow_mouse = 2; follow_mouse = 2;
repeat_delay = 180; repeat_delay = 200;
repeat_rate = 120; repeat_rate = 60;
touchpad = { touchpad = {
natural_scroll = "yes"; natural_scroll = "yes";
tap-to-click = true; tap-to-click = true;
middle_button_emulation = true; middle_button_emulation = true;
disable_while_typing = false;
}; };
}; };
@ -83,10 +99,6 @@ in {
allow_workspace_cycles = true; allow_workspace_cycles = true;
}; };
cursor = {
no_warps = true;
};
general = { general = {
# See https://wiki.hyprland.org/Configuring/Variables/ for more # See https://wiki.hyprland.org/Configuring/Variables/ for more
"col.active_border" = "0xff${colors.primary} 0xff${colors.green} 45deg"; "col.active_border" = "0xff${colors.primary} 0xff${colors.green} 45deg";
@ -95,6 +107,7 @@ in {
gaps_in = 3; gaps_in = 3;
gaps_out = 6; gaps_out = 6;
border_size = 2; border_size = 2;
no_cursor_warps = true;
resize_on_border = true; resize_on_border = true;
no_focus_fallback = true; no_focus_fallback = true;
@ -102,112 +115,107 @@ in {
}; };
decoration = { decoration = {
rounding = 5; rounding = 3;
# blur = "no";
# blur_size = 3
# blur_passes = 1
# blur_new_optimizations = on
/* drop_shadow = "yes";
blur = "no"; shadow_range = 4;
blur_size = 3 shadow_render_power = 3;
blur_passes = 1 "col.shadow" = "rgba(1a1a1aee)";
blur_new_optimizations = on
*/
shadow = {
enabled = true;
color = "rgba(1a1a1aee)";
range = 4;
render_power = 3;
};
dim_inactive = false; dim_inactive = false;
}; };
"$mod" = "SUPER"; "$mainMod" = "SUPER";
bind = [ bind = [
# See https://wiki.hyprland.org/Configuring/Keywords/ for more # See https://wiki.hyprland.org/Configuring/Keywords/ for more
/* # "$mainMod, return, exec, wezterm"
"$mod, return, exec, wezterm" # "$mainMod SHIFT, return, exec, wezterm"
"$mod SHIFT, return, exec, wezterm" "$mainMod, return, exec, kitty --single-instance"
*/ "$mainMod SHIFT, return, exec, kitty"
"$mod, return, exec, wezterm" "$mainMod, U, exec, firefox"
"$mod SHIFT, return, exec, kitty" "$mainMod, space, exec, wofi --show drun"
"$mod, U, exec, firefox" "$mainMod, C, killactive,"
"$mod, space, exec, tofi-run | xargs hyprctl dispatch exec --" "$mainMod, M, exit,"
"$mod, C, killactive," "$mainMod, E, exec, dolphin"
"$mod SHIFT, E, exit," "$mainMod, F, togglefloating,"
"$mod, E, exec, dolphin" "$mainMod SHIFT, F, fullscreen,"
"$mod, F, togglefloating," "$mainMod, R, exec, anyrun"
"$mod SHIFT, F, fullscreen," "$mainMod, S, pseudo, # dwindle"
"$mod, R, exec, anyrun" "$mainMod, P, togglesplit, # dwindle"
"$mod, S, pseudo, # dwindle"
"$mod, P, togglesplit, # dwindle"
# Move focus with mod + arrow keys
"$mod, left, movefocus, l"
"$mod, right, movefocus, r"
"$mod, up, movefocus, u"
"$mod, down, movefocus, d"
"$mod, h, movefocus, l"
"$mod, l, movefocus, r"
"$mod, k, movefocus, u"
"$mod, j, movefocus, d"
"$mod SHIFT, H, movewindow, l"
"$mod SHIFT, L, movewindow, r"
"$mod SHIFT, K, movewindow, u"
"$mod SHIFT, J, movewindow, d"
"$mod SHIFT, V, exec, swayosd-client --input-volume mute-toggle"
", XF86AudioMicMute, exec, swayosd-client --input-volume mute-toggle"
", XF86AudioMute, exec, swayosd-client --output-volume mute-toggle"
", XF86AudioRaiseVolume, exec, swayosd-client --output-volume raise"
", XF86AudioLowerVolume, exec, swayosd-client --output-volume lower"
", XF86MonBrightnessUp, exec, swayosd-client --brightness raise"
", XF86MonBrightnessDown, exec, swayosd-client --brightness lower"
# Move focus with mainMod + arrow keys
"$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"
"$mainMod SHIFT, H, swapwindow, l"
"$mainMod SHIFT, L, swapwindow, r"
"$mainMod SHIFT, K, swapwindow, u"
"$mainMod SHIFT, J, swapwindow, d"
"$mainMod SHIFT, V, exec, pamixer --default-source --toggle-mute"
"$mainMod, F1, exec, pamixer --default-source --toggle-mute"
", XF86AudioMicMute, exec, pamixer --default-source --toggle-mute"
", XF86AudioMute, exec, pamixer --toggle-mute"
", XF86AudioRaiseVolume, exec, pamixer --increase 5"
", XF86AudioLowerVolume, exec, pamixer --decrease 5"
"CTRL, XF86AudioRaiseVolume, exec, pamixer --increase 1"
"CTRL, XF86AudioLowerVolume, exec, pamixer --decrease 1"
", XF86AudioPlay, exec, playerctl play-pause" ", XF86AudioPlay, exec, playerctl play-pause"
", XF86AudioNext, exec, playerctl next" ", XF86AudioNext, exec, playerctl next"
", XF86AudioPrev, exec, playerctl previous" ", XF86AudioPrev, exec, playerctl previous"
"$mainMod, tab, workspace, previous"
"$mod, tab, workspace, previous" # Switch workspaces with mainMod + [0-9]
"ALT, tab, workspace, previous" "$mainMod, 1, workspace, 1"
"$mainMod, 2, workspace, 2"
"$mainMod, 3, workspace, 3"
"$mainMod, 4, workspace, 4"
"$mainMod, 5, workspace, 5"
"$mainMod, 6, workspace, 6"
"$mainMod, 7, workspace, 7"
"$mainMod, 8, workspace, 8"
"$mainMod, 9, workspace, 9"
"$mainMod, 0, workspace, 10"
# Switch workspaces with mod + [0-9] # Move active window to a workspace with mainMod + SHIFT + [0-9]
"$mod, 1, workspace, 1" "$mainMod SHIFT, 1, movetoworkspace, 1"
"$mod, 2, workspace, 2" "$mainMod SHIFT, 2, movetoworkspace, 2"
"$mod, 3, workspace, 3" "$mainMod SHIFT, 3, movetoworkspace, 3"
"$mod, 4, workspace, 4" "$mainMod SHIFT, 4, movetoworkspace, 4"
"$mod, 5, workspace, 5" "$mainMod SHIFT, 5, movetoworkspace, 5"
"$mod, 6, workspace, 6" "$mainMod SHIFT, 6, movetoworkspace, 6"
"$mod, 7, workspace, 7" "$mainMod SHIFT, 7, movetoworkspace, 7"
"$mod, 8, workspace, 8" "$mainMod SHIFT, 8, movetoworkspace, 8"
"$mod, 9, workspace, 9" "$mainMod SHIFT, 9, movetoworkspace, 9"
"$mod, 0, workspace, 10" "$mainMod SHIFT, 0, movetoworkspace, 10"
", XF86MonBrightnessDown, exec, brightnessctl set 10%-"
", XF86MonBrightnessUp, exec, brightnessctl set +10%"
"SHIFT, XF86MonBrightnessDown, exec, brightnessctl set 1%"
"SHIFT, XF86MonBrightnessUp, exec, brightnessctl set 100%"
"CTRL, XF86MonBrightnessDown, exec, brightnessctl set 1%-"
"CTRL, XF86MonBrightnessUp, exec, brightnessctl set +1%"
"$mainMod SHIFT, S, exec, clipshot"
# Move active window to a workspace with mod + SHIFT + [0-9] # Scroll through existing workspaces with mainMod + scroll
"$mod SHIFT, 1, movetoworkspace, 1" "$mainMod, mouse_down, workspace, e+1"
"$mod SHIFT, 2, movetoworkspace, 2" "$mainMod, mouse_up, workspace, e-1"
"$mod SHIFT, 3, movetoworkspace, 3" "CTRL SHIFT $mainMod, L, exec, swaylock"
"$mod SHIFT, 4, movetoworkspace, 4" "$mainMod CTRL, space, exec, makoctl dismiss"
"$mod SHIFT, 5, movetoworkspace, 5" "$mainMod SHIFT CTRL, space, exec, makoctl restore"
"$mod SHIFT, 6, movetoworkspace, 6" "$mainMod SHIFT, space, exec, makoctl invoke"
"$mod SHIFT, 7, movetoworkspace, 7" "$mainMod, E, exec, thunar"
"$mod SHIFT, 8, movetoworkspace, 8"
"$mod SHIFT, 9, movetoworkspace, 9"
"$mod SHIFT, 0, movetoworkspace, 10"
"$mod SHIFT, S, exec, clipshot"
# Scroll through existing workspaces with mod + scroll
"$mod, mouse_down, workspace, e+1"
"$mod, mouse_up, workspace, e-1"
"CTRL SHIFT $mod, L, exec, hyprlock"
"$mod CTRL, space, exec, makoctl dismiss"
"$mod SHIFT CTRL, space, exec, makoctl restore"
"$mod SHIFT, space, exec, makoctl invoke default"
"$mod, E, exec, thunar"
]; ];
# Move/resize windows with mod + LMB/RMB and dragging # Move/resize windows with mainMod + LMB/RMB and dragging
bindm = ["$mod, mouse:272, movewindow" "$mod, mouse:273, resizewindow"]; bindm = ["$mainMod, mouse:272, movewindow" "$mainMod, mouse:273, resizewindow"];
}; };
extraConfig = '' extraConfig = ''
@ -227,15 +235,15 @@ in {
dwindle { dwindle {
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
# master switch for pseudotiling. Enabling is bound to mod + P in the keybinds section below # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
pseudotile = yes pseudotile = yes
preserve_split = 1 preserve_split = 1
# no_gaps_when_only = true no_gaps_when_only = true
} }
master { master {
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
# new_is_master = true new_is_master = true
} }
gestures { gestures {
@ -243,178 +251,14 @@ in {
workspace_swipe = on workspace_swipe = on
} }
## Example per-device config # Example per-device config
## See https://wiki.hyprland.org/Configuring/Keywords/#executing for more # See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
## device:epic-mouse-v1 { # device:epic-mouse-v1 {
## sensitivity = -0.5 # sensitivity = -0.5
## } # }
## See https://wiki.hyprland.org/Configuring/Window-Rules/ for more # See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
windowrulev2 = idleinhibit,class:^.*([Ss]lippi).*$ # windowrulev2 = float,class:^.*(kitty|firefox|org.wezfurlong.wezterm).*$
windowrulev2 = float,class:^.*$
windowrulev2 = tile,class:^.*([Kk]itty|[Ff]irefox|[Ww]ezterm|[Dd]iscord|[Ss]potify|[Ss]lack).*$
windowrulev2 = opacity 1.0 0.95,class:^.*$
windowrulev2 = center 1,floating:1
windowrulev2 = opacity 0.0 override, class:^(xwaylandvideobridge)$
windowrulev2 = noanim, class:^(xwaylandvideobridge)$
windowrulev2 = noinitialfocus, class:^(xwaylandvideobridge)$
windowrulev2 = maxsize 1 1, class:^(xwaylandvideobridge)$
windowrulev2 = noblur, class:^(xwaylandvideobridge)$
windowrulev2 = nofocus, class:^(xwaylandvideobridge)$
''; '';
}; };
programs.hyprlock = {
enable = true;
settings = {
# docs: https://wiki.hyprland.org/Hypr-Ecosystem/hyprlock
general = {
grace = 0;
no_face_out = true;
};
input-field = [
{
monitor = "";
fade_on_empty = false;
placeholder_text = "Locked";
rounding = 5;
font_size = 20;
font_color = "rgba(255, 255, 255, 1.0)";
inner_color = "rgba(31, 31, 47, 0.95)";
outer_color = "0xff74c7ec 0xff74c7ec 45deg";
outline_thickness = 3;
position = "0, -200";
dots_size = 0.1;
size = "300 75";
font_family = "IosevkaLyteTerm";
shadow_passes = 3;
shadow_size = 8;
shadow_color = "rgba(0, 0, 0, 1.0)";
shadow_boost = 0.8;
}
];
background = [
{
path = "~/.wallpaper";
blur_passes = 2;
}
];
label = [
{
monitor = "";
font_size = 64;
halign = "center";
valign = "center";
text_align = "center";
# rotate = 10;
position = "0, 200";
font_family = "IosevkaLyteTerm";
text = ''Locked for <span foreground="##74c7ec">$USER</span>'';
shadow_passes = 1;
shadow_size = 8;
shadow_color = "rgba(0, 0, 0, 1.0)";
shadow_boost = 0.5;
}
{
monitor = "";
font_size = 20;
halign = "center";
valign = "center";
text_align = "center";
color = "rgba(255, 255, 255, 0.5)";
position = "0 120";
font_family = "IosevkaLyteTerm";
text = "cmd[update:1000] date '+%a %b %d %H:%M:%S'";
shadow_passes = 3;
shadow_size = 1;
shadow_color = "rgba(0, 0, 0, 1.0)";
shadow_boost = 1.0;
}
{
monitor = "";
font_size = 200;
halign = "center";
valign = "center";
text_align = "center";
color = "rgba(220, 240, 255, 0.8)";
position = "0 500";
font_family = "NerdFontSymbolsOnly";
text = "󰍁";
shadow_passes = 3;
shadow_size = 1;
shadow_color = "rgba(0, 0, 0, 1.0)";
shadow_boost = 1.0;
}
];
};
};
services.hypridle = let
secondsPerMinute = 60;
lockSeconds = 10 * secondsPerMinute;
in {
enable = true;
settings = {
general = {
after_sleep_cmd = "hyprctl dispatch dpms on";
before_sleep_cmd = "loginctl lock-session";
ignore_dbus_inhibit = false;
lock_cmd = "pidof hyprlock || hyprlock";
};
listener = [
{
timeout = lockSeconds - 300;
on-timeout = ''notify-send "Auto-locking in 5 minutes"'';
on-resume = ''notify-send "Auto-locking cancelled"'';
}
{
timeout = lockSeconds - 180;
on-timeout = ''notify-send "Auto-locking in 3 minutes"'';
}
{
timeout = lockSeconds - 120;
on-timeout = ''notify-send "Auto-locking in 2 minutes"'';
}
{
timeout = lockSeconds - 60;
on-timeout = ''notify-send "Auto-locking in 1 minute"'';
}
{
timeout = lockSeconds - 30;
on-timeout = ''notify-send "Auto-locking in 30 seconds"'';
}
{
timeout = lockSeconds - 10;
on-timeout = ''notify-send -u critical "Auto-locking in 10 seconds"'';
}
{
timeout = lockSeconds;
on-timeout = ''loginctl lock-session'';
}
{
timeout = lockSeconds + 5;
on-timeout = ''hyprctl dispatch dpms off'';
on-resume = ''hyprctl dispatch dpms on'';
}
];
};
};
} }

View file

@ -0,0 +1,35 @@
{
home.file.".iex.exs" = {
enable = true;
text = ''
Application.put_env(:elixir, :ansi_enabled, true)
# PROTIP: to break, `#iex:break`
IEx.configure(
colors: [enabled: true],
inspect: [
pretty: true,
printable_limit: :infinity,
limit: :infinity,
charlists: :as_lists
],
default_prompt: [
# ANSI CHA, move cursor to column 1
# "\e[G",
:magenta,
# IEx prompt variable
"%prefix",
"#",
# IEx prompt variable
"%counter",
# plain string
">",
:reset
]
|> IO.ANSI.format()
|> IO.chardata_to_string()
)
'';
};
}

View file

@ -0,0 +1,6 @@
{
services.kdeconnect = {
enable = true;
indicator = true;
};
}

View file

@ -10,53 +10,52 @@
enableFishIntegration = true; enableFishIntegration = true;
}; };
settings = with colors.withHashPrefix; { settings = with colors.withHashPrefix; {
font_family = font.name; "font_family" = font.name;
bold_font = "${font.name} Heavy"; "bold_font" = "${font.name} Heavy";
italic_font = "${font.name} Italic"; "italic_font" = "${font.name} Italic";
bold_italic_font = "${font.name} Heavy Italic"; "bold_italic_font" = "${font.name} Heavy Italic";
font_size = toString font.size; "font_size" = toString font.size;
inactive_text_alpha = "0.5"; "inactive_text_alpha" = "0.5";
copy_on_select = true; "copy_on_select" = true;
hide_window_decorations = "yes";
scrollback_lines = 500000; "scrollback_lines" = 500000;
symbol_map = "U+23FB-U+23FE,U+2665,U+26A1,U+2B58,U+E000-U+E00A,U+E0A0-U+E0A3,U+E0B0-U+E0D4,U+E200-U+E2A9,U+E300-U+E3E3,U+E5FA-U+E6AA,U+E700-U+E7C5,U+EA60-U+EBEB,U+F000-U+F2E0,U+F300-U+F32F,U+F400-U+F4A9,U+F500-U+F8FF,U+F0001-U+F1AF0 Symbols Nerd Font Mono"; "symbol_map" = "U+23FB-U+23FE,U+2665,U+26A1,U+2B58,U+E000-U+E00A,U+E0A0-U+E0A3,U+E0B0-U+E0D4,U+E200-U+E2A9,U+E300-U+E3E3,U+E5FA-U+E6AA,U+E700-U+E7C5,U+EA60-U+EBEB,U+F000-U+F2E0,U+F300-U+F32F,U+F400-U+F4A9,U+F500-U+F8FF,U+F0001-U+F1AF0 Symbols Nerd Font Mono";
# use `kitty + list-fonts --psnames` to get the font's PostScript name # use `kitty + list-fonts --psnames` to get the font's PostScript name
allow_remote_control = true; "allow_remote_control" = true;
listen_on = "unix:/tmp/kitty"; "listen_on" = "unix:/tmp/kitty";
repaint_delay = 3; "repaint_delay" = 3;
input_delay = 3; "input_delay" = 3;
sync_to_monitor = true; "sync_to_monitor" = true;
adjust_line_height = 0; "adjust_line_height" = 0;
window_padding_width = "10.0"; "window_padding_width" = "10.0";
window_margin_width = "0.0"; "window_margin_width" = "0.0";
confirm_os_window_close = 0; "confirm_os_window_close" = 0;
enabled_layouts = "splits:split_axis=vertical,stack"; "enabled_layouts" = "splits:split_axis=vertical,stack";
shell_integration = "disabled"; "shell_integration" = "disabled";
enable_audio_bell = true; "enable_audio_bell" = true;
visual_bell_duration = "0.25"; "visual_bell_duration" = "0.25";
visual_bell_color = bg3; "visual_bell_color" = bg3;
url_style = "single"; "url_style" = "single";
strip_trailing_spaces = "smart"; "strip_trailing_spaces" = "smart";
# open_url_modifiers ctrl # open_url_modifiers ctrl
tab_bar_align = "left"; "tab_bar_align" = "left";
tab_bar_style = "separator"; "tab_bar_style" = "separator";
tab_separator = ''""''; "tab_separator" = ''""'';
tab_bar_edge = "bottom"; "tab_bar_edge" = "top";
tab_title_template = ''"{fmt.fg.tab}{fmt.bg.tab} {activity_symbol}{title} "''; "tab_title_template" = ''"{fmt.fg.tab}{fmt.bg.tab} {activity_symbol}{title} "'';
active_tab_font_style = "normal"; "active_tab_font_style" = "normal";
## name: Catppuccin Kitty Mocha ## name: Catppuccin Kitty Mocha
## author: Catppuccin Org ## author: Catppuccin Org
@ -65,75 +64,75 @@
## blurb: Soothing pastel theme for the high-spirited! ## blurb: Soothing pastel theme for the high-spirited!
# The basic colors # The basic colors
foreground = text; "foreground" = text;
background = bg; "background" = bg;
selection_foreground = bg; "selection_foreground" = bg;
selection_background = text; "selection_background" = text;
# Cursor colors # Cursor colors
cursor = text; "cursor" = text;
cursor_text_color = bg; "cursor_text_color" = bg;
# URL underline color when hovering with mouse # URL underline color when hovering with mouse
url_color = primary; "url_color" = primary;
# Kitty window border colors # Kitty window border colors
active_border_color = primary; "active_border_color" = primary;
inactive_border_color = bg3; "inactive_border_color" = bg3;
bell_border_color = urgent; "bell_border_color" = urgent;
# OS Window titlebar colors # OS Window titlebar colors
wayland_titlebar_color = "system"; "wayland_titlebar_color" = "system";
macos_titlebar_color = "system"; "macos_titlebar_color" = "system";
# Tab bar colors # Tab bar colors
active_tab_foreground = bg; "active_tab_foreground" = bg;
active_tab_background = primary; "active_tab_background" = primary;
inactive_tab_foreground = fgdim; "inactive_tab_foreground" = fgdim;
inactive_tab_background = bg2; "inactive_tab_background" = bg2;
tab_bar_background = bg; "tab_bar_background" = bg;
# Colors for marks (marked text in the terminal) # Colors for marks (marked text in the terminal)
mark1_foreground = bg; "mark1_foreground" = bg;
mark1_background = blue; "mark1_background" = blue;
mark2_foreground = bg; "mark2_foreground" = bg;
mark2_background = purple; "mark2_background" = purple;
mark3_foreground = bg; "mark3_foreground" = bg;
mark3_background = blue; "mark3_background" = blue;
# The 16 terminal colors # The 16 terminal colors
# black # black
color0 = colors.withHashPrefix."0"; "color0" = colors.withHashPrefix."0";
color8 = colors.withHashPrefix."8"; "color8" = colors.withHashPrefix."8";
# red # red
color1 = colors.withHashPrefix."1"; "color1" = colors.withHashPrefix."1";
color9 = colors.withHashPrefix."9"; "color9" = colors.withHashPrefix."9";
# green # green
color2 = colors.withHashPrefix."2"; "color2" = colors.withHashPrefix."2";
color10 = colors.withHashPrefix."10"; "color10" = colors.withHashPrefix."10";
# yellow # yellow
color3 = colors.withHashPrefix."3"; "color3" = colors.withHashPrefix."3";
color11 = colors.withHashPrefix."11"; "color11" = colors.withHashPrefix."11";
# blue # blue
color4 = colors.withHashPrefix."4"; "color4" = colors.withHashPrefix."4";
color12 = colors.withHashPrefix."12"; "color12" = colors.withHashPrefix."12";
# magenta # magenta
color5 = colors.withHashPrefix."5"; "color5" = colors.withHashPrefix."5";
color13 = colors.withHashPrefix."13"; "color13" = colors.withHashPrefix."13";
# cyan # cyan
color6 = colors.withHashPrefix."6"; "color6" = colors.withHashPrefix."6";
color14 = colors.withHashPrefix."14"; "color14" = colors.withHashPrefix."14";
# white # white
color7 = colors.withHashPrefix."7"; "color7" = colors.withHashPrefix."7";
color15 = colors.withHashPrefix."15"; "color15" = colors.withHashPrefix."15";
}; };
keybindings = { keybindings = {
"ctrl+shift+1" = "change_font_size all 12.5"; "ctrl+shift+1" = "change_font_size all 12.5";
@ -168,7 +167,7 @@
"ctrl+l" = "neighboring_window right"; "ctrl+l" = "neighboring_window right";
"ctrl+k" = "neighboring_window up"; "ctrl+k" = "neighboring_window up";
"ctrl+j" = "neighboring_window down"; "ctrl+j" = "neighboring_window down";
"ctrl+shift+h" = "nth_window -1"; "ctrl+shift+n" = "nth_window -1";
"ctrl+shift+space>u" = "kitten hints --type=url --program @"; "ctrl+shift+space>u" = "kitten hints --type=url --program @";
"ctrl+shift+z" = "toggle_layout stack"; "ctrl+shift+z" = "toggle_layout stack";

View file

@ -0,0 +1,24 @@
{
pkgs,
outputs,
# font,
...
}: {
imports = with outputs.homeManagerModules; [
desktop
firefox
];
gtk = {
enable = true;
theme = {
name = "Catppuccin-Mocha-Compact-Sapphire-Dark";
package = pkgs.catppuccin-gtk.override {
accents = ["sapphire"];
size = "compact";
tweaks = ["rimless"];
variant = "mocha";
};
};
};
}

View file

@ -0,0 +1,41 @@
{
outputs,
pkgs,
...
}: {
imports = with outputs.homeManagerModules; [
common
];
home = {
sessionVariables = {
MOZ_ENABLE_WAYLAND = "1";
};
};
programs.fish = {
shellAliases = {
sctl = "sudo systemctl";
bt = "bluetoothctl";
pa = "pulsemixer";
sctlu = "systemctl --user";
};
functions = {
pp = ''
if test (count $argv) -gt 0
while true; ping -O -i 1 -w 5 -c 10000000 $argv; sleep 1; end
else
while true; ping -O -i 1 -w 5 -c 10000000 1.1.1.1; sleep 1; end
end
'';
};
};
home.packages = [
(pkgs.buildEnv {
name = "my-linux-scripts";
paths = [./scripts/linux];
})
];
}

View file

@ -0,0 +1,15 @@
{outputs, ...}: {
imports = with outputs.homeManagerModules; [
common
desktop
];
# TODO: pinentry curses?
/*
programs.gnupg.agent = {
enable = true;
pinentryFlavor = "gnome3";
enableSSHSupport = true;
};
*/
}

View file

@ -0,0 +1,29 @@
{
colors,
font,
...
}: {
services.mako = with colors.withHashPrefix; {
enable = true;
borderSize = 1;
maxVisible = 5;
defaultTimeout = 15000;
font = "Symbols Nerd Font ${toString font.size},${font.name} ${toString font.size}";
# TODO: config
backgroundColor = bg;
textColor = text;
borderColor = primary;
progressColor = primary;
anchor = "top-right";
extraConfig = ''
[urgency=high]
border-color=${urgent}
[urgency=high]
background-color=${urgent}
border-color=${urgent}
text-color=${bg}
'';
};
}

View file

@ -0,0 +1,25 @@
{
# flake,
inputs,
# outputs,
# lib,
# config,
# pkgs,
# system,
# modulesPath,
...
}: {
imports = [
{
nixpkgs.overlays = [inputs.ssbm.overlay];
}
inputs.ssbm.homeManagerModule
];
ssbm = {
slippi-launcher = {
enable = true;
launchMeleeOnPlay = false;
};
};
}

View file

@ -0,0 +1,5 @@
{...}: {
programs.nnn = {
enable = true;
};
}

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
usage() { usage() {
echo "at - exit after the specified datetime" echo "at - waits until after the specified datetime"
echo "Usage:" echo "Usage:"
echo " at <DATETIME> && command..." echo " at <DATETIME> && command..."
echo echo
@ -9,17 +9,13 @@ usage() {
echo " at 15:00:00 && echo \"it is 3 o'clock\"" echo " at 15:00:00 && echo \"it is 3 o'clock\""
} }
[[ -z "$1" ]] && { echo "error: no DATE argument provided" >&2; usage; exit 1; } [[ -z "$1" ]] && { echo "Error: No DATE argument provided." >&2; usage; exit 1; }
d="$(date -d "${@}" +%s)" d="$(date -d "${@}" +%s)"
_dt=$((d - $(date +%s)))
days=$((_dt / 86400))
printf 'Started at %s (with duration %sd %s)\n' "$(date)" "$days" "$(date -u --date @$((_dt)) +%H:%M:%S)"
while [[ "$d" -ge "$(date +%s)" ]]; do while [[ "$d" -ge "$(date +%s)" ]]; do
_dt=$((d - $(date +%s))) _dt=$((d - $(date +%s)))
days=$((_dt / 86400)) days=$((_dt / 86400))
printf "\r%sd %s " "$days" "$(date -u --date @$((_dt)) +%H:%M:%S)"; echo -ne "\rTime Remaining: ${days}d $(date -u --date @$((_dt)) +%H:%M:%S) ";
sleep 0.1 sleep 0.1
done done
exit 0 exit 0

View file

@ -1,24 +1,15 @@
#!/usr/bin/env bash #!/usr/bin/env bash
function usage { [[ $# -lt 1 ]] && { echo "No argument provided." >&2 ; exit 1; }
echo "countdown - exit after a certain amount of time has passed"
echo " Usage:"
echo " countdown <SECONDS> && command..."
echo
echo " Examples:"
echo ' countdown 120 && echo "Two minutes has elapsed!"'
}
[[ $# -lt 1 ]] && { printf "error: no SECONDS argument provided\n" >&2; usage; exit 1; }
d=$(($(date +%s) + $1)); d=$(($(date +%s) + $1));
printf 'Started at %s\n' "$(date)" echo "Countdown started at $(date)"
while [[ "$d" -ge "$(date +%s)" ]]; do while [[ "$d" -ge "$(date +%s)" ]]; do
_dt=$((d - $(date +%s))) _dt=$((d - $(date +%s)))
days=$((_dt / 86400)) days=$((_dt / 86400))
printf "\r%sd %s " "$days" "$(date -u --date @$((_dt)) +%H:%M:%S)"; echo -ne "\r${days}d $(date -u --date @$((_dt)) +%H:%M:%S) ";
sleep 0.1 sleep 0.1
done done
printf "\rCountdown finished %s\n" "$(date)" echo -ne "\rCountdown finished $(date)\n"

View file

@ -1,5 +1,5 @@
#!/usr/bin/env sh #!/usr/bin/env sh
r="$(< "$HOME/.emoji.txt" fzf --height 40%)" r="$(< "$HOME/.emoji.txt" sk --height 40%)"
echo "$r" | awk '$0=$1' | tr -d '\n' | clip echo "$r" | awk '$0=$1' | tr -d '\n' | clip
echo "Copied $r emoji to your clipboard" echo "Copied $r emoji to your clipboard"

View file

@ -1,4 +1,4 @@
#!/usr/bin/env -S nix shell nixpkgs#deno --command deno run --allow-read --allow-run --allow-net #!/usr/bin/env -S deno run --allow-read --allow-run --allow-net
import * as path from "https://deno.land/std@0.181.0/path/mod.ts"; import * as path from "https://deno.land/std@0.181.0/path/mod.ts";

View file

@ -1,3 +0,0 @@
#!/usr/bin/env bash
N journal

View file

@ -1,6 +1,5 @@
#!/usr/bin/env sh #!/usr/bin/env sh
umask 0077
SUBDIR="${2:-./}" SUBDIR="${2:-./}"
mkdir -p "$NOTES_PATH/$SUBDIR" mkdir -p "$NOTES_PATH/$SUBDIR"
cd "$NOTES_PATH/$SUBDIR" || exit 1 cd "$NOTES_PATH/$SUBDIR" || exit 1

View file

@ -1,127 +0,0 @@
#!/usr/bin/env bash
#
# spark
# https://github.com/holman/spark
#
# Generates sparklines for a set of data.
#
# Here's a good web-based sparkline generator that was a bit of inspiration
# for spark:
#
# https://datacollective.org/sparkblocks
#
# spark takes a comma-separated or space-separated list of data and then prints
# a sparkline out of it.
#
# Examples:
#
# spark 1 5 22 13 53
# # => ▁▁▃▂▇
#
# spark 0 30 55 80 33 150
# # => ▁▂▃▅▂▇
#
# spark -h
# # => Prints the spark help text.
# Generates sparklines.
#
# $1 - The data we'd like to graph.
_echo()
{
if [ "X$1" = "X-n" ]; then
shift
printf "%s" "$*"
else
printf "%s\n" "$*"
fi
}
spark()
{
local n numbers=
# find min/max values
local min=0xffffffff max=0
for n in ${@//,/ }
do
# on Linux (or with bash4) we could use `printf %.0f $n` here to
# round the number but that doesn't work on OS X (bash3) nor does
# `awk '{printf "%.0f",$1}' <<< $n` work, so just cut it off
n=${n%.*}
(( n < min )) && min=$n
(( n > max )) && max=$n
numbers=$numbers${numbers:+ }$n
done
# print ticks
local ticks=(▁ ▂ ▃ ▄ ▅ ▆ ▇ █)
# use a high tick if data is constant
(( min == max )) && ticks=(▅ ▆)
local f=$(( (($max-$min)<<8)/(${#ticks[@]}-1) ))
(( f < 1 )) && f=1
for n in $numbers
do
_echo -n ${ticks[$(( ((($n-$min)<<8)/$f) ))]}
done
_echo
}
# If we're being sourced, don't worry about such things
if [ "$BASH_SOURCE" == "$0" ]; then
# Prints the help text for spark.
help()
{
local spark=$(basename $0)
cat <<EOF
USAGE:
$spark [-h|--help] VALUE,...
EXAMPLES:
$spark 1 5 22 13 53
▁▁▃▂█
$spark 0,30,55,80,33,150
▁▂▃▄▂█
echo 9 13 5 17 1 | $spark
▄▆▂█▁
EOF
}
# show help for no arguments if stdin is a terminal
if { [ -z "$1" ] && [ -t 0 ] ; } || [ "$1" == '-h' ] || [ "$1" == '--help' ]
then
help
exit 0
fi
spark ${@:-`cat`}
fi
# source: https://github.com/holman/spark/commit/ab88ac6f8f33698f39ece2f109b1117ef39a68eb
# The MIT License
#
# Copyright (c) Zach Holman, https://zachholman.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

View file

@ -1,3 +0,0 @@
#!/usr/bin/env bash
N todo

View file

@ -1,2 +0,0 @@
#!/usr/bin/env bash
N todo

View file

@ -0,0 +1,18 @@
{config, ...}: {
programs.senpai = {
enable = true;
config = {
addr = "a";
nick = "a";
};
};
home.file."${config.xdg.configHome}/senpai/senpai.scfg" = {
enable = true;
text = ''
address irc+insecure://beefcake:6667
nickname lytedev
password-cmd pass soju
'';
};
}

View file

@ -1,22 +1,55 @@
{ {
style, pkgs,
colors,
outputs,
lib, lib,
config, config,
# font,
... ...
}: { }: {
programs.foot = { imports = with outputs.homeManagerModules; [
linux
waybar
mako
swaylock
linux-desktop
];
programs.wofi = {
enable = true; enable = true;
settings = {
width = "640";
height = "360";
};
style = ''
* {
border-radius: 0;
}
window {
margin: 0px;
padding: 8px;
}
#outer-box {
margin: 8px;
}
#outer-box, #inner-box {
margin-top: 8px;
}
'';
}; };
xdg = { home.pointerCursor = {
enable = true; name = "Bibata-Modern-Classic";
mimeApps = { package = pkgs.bibata-cursors;
enable = true; size = 64; # TODO: this doesn't seem to work -- at least in Sway
defaultApplications = { # some icons are also missing (hand2?)
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
};
}; };
programs.foot = {
enable = true;
}; };
wayland.windowManager.sway = { wayland.windowManager.sway = {
@ -42,17 +75,6 @@
systemd = { systemd = {
enable = true; enable = true;
variables = [
"DISPLAY"
"WAYLAND_DISPLAY"
"SWAYSOCK"
"XDG_CURRENT_DESKTOP"
"XDG_SESSION_TYPE"
"NIXOS_OZONE_WL"
"XCURSOR_THEME"
"XCURSOR_SIZE"
"PATH"
];
}; };
# TODO: stuff is opening on workspace 10 (0?) # TODO: stuff is opening on workspace 10 (0?)
@ -61,7 +83,7 @@
swaymsg "workspace 1" swaymsg "workspace 1"
} }
set $tilers "(wezterm.*|kitty.*|firefox.*|[Ss]lack.*|thunar.*|[Aa]lacritty.*|[Dd]iscord.*)" set $tilers "(wezterm.*|kitty.*|firefox.*|slack.*|Slack.*|thunar.*|Alacritty.*|alacritty.*|Discord.*|discord.*)"
for_window [title=".*"] floating enable for_window [title=".*"] floating enable
for_window [app_id=$tilers] floating disable for_window [app_id=$tilers] floating disable
''; '';
@ -76,6 +98,12 @@
*/ */
]; ];
output = {
"*" = {
background = "$HOME/.wallpaper fill";
};
};
# TODO: popup_during_fullscreen smart # TODO: popup_during_fullscreen smart
focus = { focus = {
wrapping = "no"; # maybe workspace? wrapping = "no"; # maybe workspace?
@ -100,23 +128,15 @@
}; };
startup = [ startup = [
{command = "kdeconnect-indicator";}
{command = "mako";}
{
command = "swaybg -i $HOME/.wallpaper";
}
{
command = "swayosd-server";
}
{ {
command = "waybar"; command = "waybar";
} }
{ {
command = lib.concatStringsSep " " [ command = lib.concatStringsSep " " [
"swayidle -w" "swayidle -w"
"before-sleep 'swaylock'" "timeout 300 'notify-send \"Idling in 300 seconds\"'"
"timeout 300 'notify-send \"Idling in 5 minutes\"' resume 'notify-send \"Idling cancelled.\"'" "resume 'notify-send \"Idling cancelled.\"'"
"timeout 480 'notify-send -u critical \"Idling in 2 minutes\"'" "timeout 480 'notify-send -u critical \"Idling in 120 seconds\"'"
"timeout 510 'notify-send -u critical \"Idling in 90 seconds\"'" "timeout 510 'notify-send -u critical \"Idling in 90 seconds\"'"
"timeout 540 'notify-send -u critical \"Idling in 60 seconds!\"'" "timeout 540 'notify-send -u critical \"Idling in 60 seconds!\"'"
"timeout 570 'notify-send -u critical \"Idling in 30 seconds!\"'" "timeout 570 'notify-send -u critical \"Idling in 30 seconds!\"'"
@ -131,11 +151,14 @@
"timeout 598 'notify-send -u critical \"Idling in 2 seconds!\"'" "timeout 598 'notify-send -u critical \"Idling in 2 seconds!\"'"
"timeout 599 'notify-send -u critical \"Idling in 1 second!\"'" "timeout 599 'notify-send -u critical \"Idling in 1 second!\"'"
"timeout 600 'swaylock -f'" "timeout 600 'swaylock -f'"
"timeout 600 'swaymsg \"output * dpms off\"' resume 'swaymsg \"output * dpms on\" & maybe-good-morning &'" "timeout 600 'swaymsg \"output * dpms off\"'"
"resume 'swaymsg \"output * dpms on\" & maybe-good-morning &'"
"before-sleep 'swaylock'"
]; ];
} }
# {command = "firefox";} # {command = "firefox";}
# {command = "wezterm";} # {command = "wezterm";}
{command = "kitty --single-instance";}
]; ];
modes = { modes = {
@ -158,13 +181,13 @@
input = { input = {
"type:keyboard" = { "type:keyboard" = {
xkb_options = "ctrl:nocaps"; xkb_options = "ctrl:nocaps";
repeat_delay = "180"; repeat_delay = "200";
repeat_rate = "100"; repeat_rate = "60";
}; };
"type:pointer" = { "type:pointer" = {
accel_profile = "flat"; accel_profile = "flat";
pointer_accel = "0.5"; pointer_accel = "0";
}; };
"type:touchpad" = { "type:touchpad" = {
@ -177,19 +200,17 @@
}; };
keybindings = let keybindings = let
mod = config.wayland.windowManager.sway.config.modifier; mod = config.wayland.windowManager.sway.config.modifier;
menu = "tofi-run | xargs swaymsg exec --";
in { in {
# bindsym $mod+shift+space exec wofi --show drun
"${mod}+control+space" = "exec makoctl dismiss"; "${mod}+control+space" = "exec makoctl dismiss";
"${mod}+shift+space" = "exec makoctl invoke"; "${mod}+shift+space" = "exec makoctl invoke";
# "${mod}+return" = "exec kitty --single-instance"; # "${mod}+return" = "exec kitty --single-instance";
"${mod}+return" = "exec wezterm"; "${mod}+return" = "exec kitty";
"${mod}+shift+return" = "exec floating-term"; "${mod}+shift+return" = "exec floating-term";
"${mod}+shift+alt+return" = "exec kitty"; "${mod}+shift+alt+return" = "exec kitty";
"${mod}+c" = "kill"; "${mod}+c" = "kill";
"${mod}+shift+c" = "kill # TODO: kill -9?"; "${mod}+shift+c" = "kill # TODO: kill -9?";
"${mod}+alt+space" = "exec wofi --show drun"; "${mod}+space" = "exec wofi --show drun";
"${mod}" = "exec ${menu}";
"${mod}+space" = "exec ${menu}";
"${mod}+shift+s" = "exec clipshot"; "${mod}+shift+s" = "exec clipshot";
"${mod}+e" = "exec thunar"; "${mod}+e" = "exec thunar";
"${mod}+shift+r" = "reload"; "${mod}+shift+r" = "reload";
@ -252,9 +273,7 @@
"${mod}+p" = "focus parent"; "${mod}+p" = "focus parent";
"${mod}+period" = "focus child"; "${mod}+period" = "focus child";
"${mod}+comma" = "focus child"; "${mod}+comma" = "focus child";
"${mod}+tab" = "workspace back_and_forth"; "${mod}+tab" = "workspace back_and_forth";
"alt+tab" = "workspace back_and_forth";
"${mod}+minus" = "gaps inner current minus 5"; "${mod}+minus" = "gaps inner current minus 5";
"${mod}+plus" = "gaps inner current plus 5"; "${mod}+plus" = "gaps inner current plus 5";
@ -266,45 +285,12 @@
# TODO: this should also reset the horizontal and vertical gaps? # TODO: this should also reset the horizontal and vertical gaps?
"${mod}+control+equal" = "gaps inner current set 0"; "${mod}+control+equal" = "gaps inner current set 0";
"${mod}+shift+v" = "exec swayosd-client --input-volume mute-toggle";
"${mod}+F1" = "exec pactl set-sink-mute @DEFAULT_SINK@ toggle";
"XF86AudioRaiseVolume" = "exec swayosd-client --output-volume raise";
"XF86AudioLowerVolume" = "exec swayosd-client --output-volume lower";
"XF86AudioMute" = "exec swayosd-client --output-volume mute-toggle";
"XF86AudioMicMute" = "exec swayosd-client --input-volume mute-toggle";
"XF86MonBrightnessUp" = "exec swayosd-client --brightness raise";
"XF86MonBrightnessDown" = "exec swayosd-client --brightness lower";
"control+XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +1%";
"control+XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -1%";
"XF86AudioPlay" = "exec playerctl play-pause";
"XF86AudioNext" = "exec playerctl next";
"XF86AudioPrev" = "exec playerctl previous";
"--locked ${mod}+shift+v" = "exec swayosd-client --input-volume mute-toggle";
"--locked ${mod}+F1" = "exec pactl set-sink-mute @DEFAULT_SINK@ toggle";
"--locked XF86AudioRaiseVolume" = "exec swayosd-client --output-volume raise";
"--locked XF86AudioLowerVolume" = "exec swayosd-client --output-volume lower";
"--locked XF86AudioMute" = "exec swayosd-client --output-volume mute-toggle";
"--locked XF86AudioMicMute" = "exec swayosd-client --input-volume mute-toggle";
"--locked XF86MonBrightnessUp" = "exec swayosd-client --brightness raise";
"--locked XF86MonBrightnessDown" = "exec swayosd-client --brightness lower";
"--locked control+XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +1%";
"--locked control+XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -1%";
"--locked XF86AudioPlay" = "exec playerctl play-pause";
"--locked XF86AudioNext" = "exec playerctl next";
"--locked XF86AudioPrev" = "exec playerctl previous";
/*
"XF86MonBrightnessUp" = " exec swayosd-client --brightness 10";
"XF86MonBrightnessDown" = "exec swayosd-client --brightness -10";
"XF86AudioMute" = "exec pactl set-sink-mute @DEFAULT_SINK@ toggle";
"XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +5%"; "XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +5%";
"XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -5%"; "XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -5%";
"XF86AudioRaiseVolume" = "exec swayosd-client --output-volume 15"; "control+XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +1%";
"XF86AudioLowerVolume" = "exec swayosd-client --output-volume -15"; "control+XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -1%";
"XF86AudioRaiseVolume" = "exec swayosd-client --output-volume raise --max-volume 120"; "XF86AudioMute" = "exec pactl set-sink-mute @DEFAULT_SINK@ toggle";
"XF86AudioLowerVolume" = "exec swayosd-client --output-volume lower --max-volume 120"; "${mod}+F1" = "exec pactl set-sink-mute @DEFAULT_SINK@ toggle";
"XF86AudioRaiseVolume" = "exec swayosd-client --output-volume +10 --device alsa_output.pci-0000_11_00.4.analog-stereo.monitor";
"XF86AudioLowerVolume" = "exec swayosd-client --output-volume -10 --device alsa_output.pci-0000_11_00.4.analog-stereo.monitor";
"XF86AudioMicMute" = "exec pactl set-source-mute @DEFAULT_SOURCE@ toggle"; "XF86AudioMicMute" = "exec pactl set-source-mute @DEFAULT_SOURCE@ toggle";
"XF86MonBrightnessDown" = "exec brightnessctl set 10%-"; "XF86MonBrightnessDown" = "exec brightnessctl set 10%-";
"XF86MonBrightnessUp" = "exec brightnessctl set +10%"; "XF86MonBrightnessUp" = "exec brightnessctl set +10%";
@ -312,8 +298,10 @@
"shift+XF86MonBrightnessUp" = "exec brightnessctl set 100%"; "shift+XF86MonBrightnessUp" = "exec brightnessctl set 100%";
"control+XF86MonBrightnessDown" = "exec brightnessctl set 1%-"; "control+XF86MonBrightnessDown" = "exec brightnessctl set 1%-";
"control+XF86MonBrightnessUp" = "exec brightnessctl set +1%"; "control+XF86MonBrightnessUp" = "exec brightnessctl set +1%";
"XF86AudioPlay" = "exec playerctl play-pause";
"XF86AudioNext" = "exec playerctl next";
"XF86AudioPrev" = "exec playerctl previous";
"${mod}+shift+v" = "exec pactl set-source-mute @DEFAULT_SOURCE@ toggle"; "${mod}+shift+v" = "exec pactl set-source-mute @DEFAULT_SOURCE@ toggle";
*/
"${mod}+control+shift+l" = "exec swaylock"; "${mod}+control+shift+l" = "exec swaylock";
@ -321,7 +309,7 @@
}; };
assigns = {}; assigns = {};
bars = []; bars = [];
colors = with style.colors; { colors = with colors; {
background = bg; background = bg;
focused = { focused = {
background = bg; background = bg;

View file

@ -1,10 +1,14 @@
{style, ...}: { {
font,
# colors,
...
}: {
programs.swaylock = { programs.swaylock = {
enable = true; enable = true;
settings = { settings = {
color = "ffffffff"; color = "ffffffff";
image = "~/.wallpaper"; image = "~/.wallpaper";
font = style.font.name; font = font.name;
show-failed-attempts = true; show-failed-attempts = true;
ignore-empty-password = true; ignore-empty-password = true;

View file

@ -0,0 +1,7 @@
{outputs, ...}: {
imports = with outputs.homeManagerModules; [
sway
sway-laptop
hyprland
];
}

View file

@ -0,0 +1,126 @@
{
# colors,
# font,
...
}: {
programs.tmux = {
enable = true;
baseIndex = 1;
clock24 = true;
extraConfig = ''
unbind C-b
set -g prefix C-s
# enable tmux to support helix colors
set -g default-terminal "tmux-256color"
set -g terminal-overrides ",xterm-256color:RGB"
set -g update-environment "WAYLAND_DISPLAY DISPLAY"
bind R source-file "$HOME/.tmux.conf" \; display-message "Reloaded $HOME/.tmux.conf"
bind o display-message "Saved pane output to #(tmux-save-buffer '#S')"
bind O run "tmux-edit-buffer"
bind D attach-session -t . -c '#{pane_current_path}' \; display-message "Set session path to #{pane_current_path}"
bind H set -s status # toggle status bar
bind v split-window -h -c "#{pane_current_path}"
bind b split-window -c "#{pane_current_path}"
bind h split-window -c "#{pane_current_path}"
bind -n C-l select-pane -R
bind -n C-k select-pane -U
bind -n C-j select-pane -D
# enabling a ^J hotkey causes breakage when pasting anything that start with a newline, since it triggers the hotkey and some weird interaction with bracketed paste causes the pane to enter a broken state
bind -n C-h select-pane -L
bind -n C-M-l split-window -h -c "#{pane_current_path}"
bind -n C-M-j split-window -v -c "#{pane_current_path}"
# tab creation
bind -n C-t new-window
# tab nav is the default p and n binds
# window and session switcher is the default w bind
set -g mouse on
set -g escape-time 0
set -g monitor-activity on
set -g visual-bell off
set -g bell-action other
set -g activity-action none
set -g mode-keys vi
set -g history-limit 1000000
set -g status on
set -g status-position bottom
set -g status-style "fg=colour8 bg=default"
set -g status-interval 5
set -g status-left-length 50
set -g window-status-style "fg=colour8 bg=default"
set -g window-status-format "#W"
set -g window-status-separator " "
set -g window-status-activity-style "fg=colour7 bg=default"
set -g window-status-bell-style "fg=colour1 bg=default"
set -g window-status-current-style "fg=colour4 bg=default"
set -g window-status-current-format " #W "
set -g status-left "#{client_user}@#h:#S "
set -g status-right "#(kubeline && printf ' ')"
set -g status-left-length 1000
set -g message-style "fg=colour7 bg=default"
set -g pane-active-border-style fg=blue
set -g pane-border-style fg=colour0
set -g clock-mode-colour colour8
set -g base-index 1
set -g pane-base-index 1
set -g window-status-current-format "#W"
# present a menu of urls to open from the visible pane
# TODO: fuzzy search this
# bind u capture-pane \;\
# save-buffer /tmp/tmux-buffer \;\
# split-window -l 10 "urlscan /tmp/tmux-buffer"
bind -T copy-mode-vi "y" send-keys -X copy-pipe-no-clear 'clip' \; display-message 'Copied to clipboard!'
bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-no-clear 'clip' \; display-message 'Copied to clipboard!'
bind K kill-pane
bind C-S-k kill-window
# Activate OFF mode
bind -n M-o \
set prefix None \;\
set key-table off \;\
set -ag status-right " OFF"
# Disable OFF mode
bind -T off M-O \
set -u prefix \;\
set -u key-table \;\
source-file "$HOME/.config/tmux/tmux.conf"
# set -g @plugin 'tmux-plugins/tpm'
# set -g @plugin 'tmux-plugins/tmux-resurrect'
# set -g @plugin 'tmux-plugins/tmux-continuum'
# set -g @resurrect-capture-pane-contents 'on'
# set -g @resurrect-processes 'helix hx vi vim nvim emacs man less more tail top htop btm irssi weechat mutt "git log" iex mix deno watchexec mosh-client ssh senpai broot nnn iex mix'
# bind A run-shell "#{@resurrect-save-script-path}"
# bind L run-shell "#{@resurrect-restore-script-path}"
# set -g @continuum-restore 'on'
# set -g @continuum-save-interval '120'
'';
};
home.shellAliases = {
t = "tmux";
};
}

View file

@ -1,6 +1,6 @@
{ {
pkgs, colors,
style, font,
... ...
}: { }: {
programs.waybar = { programs.waybar = {
@ -10,41 +10,38 @@
"layer" = "top"; "layer" = "top";
"position" = "bottom"; "position" = "bottom";
"output" = ["eDP-1" "DP-3"]; "output" = ["eDP-1" "DP-3"];
"height" = 50; "height" = 32;
"modules-left" = [ "modules-left" = ["clock" "sway/window"];
"idle_inhibitor" "modules-center" = ["sway/workspaces"];
"sway/workspaces"
"sway/window"
];
"modules-center" = [];
"modules-right" = [ "modules-right" = [
"privacy"
"power-profiles-daemon"
"mpris" "mpris"
## "disk" "idle_inhibitor"
## TODO: will need a custom module for Disk IO "bluetooth"
# "wireplumber",
## "wireplumber" # pulseaudio module is more featureful
"pulseaudio" "pulseaudio"
"network" # "network",
"cpu" "cpu"
"memory" "memory"
"temperature" # "temperature",
"backlight" "backlight"
"battery" "battery"
"bluetooth"
"tray" "tray"
"clock"
]; ];
"bluetooth" = { "bluetooth" = {
"format" = "<span></span>"; "format" = "<span</span>";
"on-click" = "${pkgs.blueman}/bin/blueman-manager"; "format-connected" = "<span></span>";
}; "format-connected-battery" = "<span></span>";
"wireplumber" = { # "format-device-preference" = [ "device1", "device2" ], # preference list deciding the displayed devic;
"format" = "{volume}% {icon}"; "tooltip-format" = "{controller_alias}@{controller_address} ({num_connections} connected)";
"on-click" = "helvum"; "tooltip-format-connected" = "{controller_alias}@{controller_address} ({num_connections} connected)\n{device_enumerate}";
"tooltip-format-enumerate-connected" = "{device_alias}@{device_address}";
"tooltip-format-enumerate-connected-battery" = "{device_alias}@{device_address} (󰁹 {device_battery_percentage}%)";
}; };
# "wireplumber" = ;
# "format" = "{volume}% {icon}";
# "format-muted" = "";
# "on-click" = "helvum;
# },
"sway/workspaces" = { "sway/workspaces" = {
"disable-scroll" = false; "disable-scroll" = false;
"persistent_workspaces" = { "persistent_workspaces" = {
@ -62,40 +59,31 @@
"tray" = { "tray" = {
"icon-size" = 24; "icon-size" = 24;
"spacing" = 4; "spacing" = 4;
"show-passive-items" = true;
}; };
"clock" = { "clock" = {
"interval" = 1; "interval" = 1;
"format" = "{:%a %b %d\n%H:%M:%S}"; "format" = "{:%a %b %d %H:%M:%S}";
"justify" = "center";
}; };
"cpu" = { "cpu" = {
"format" = "{usage}%\nCPU"; "format" = "{usage} <span></span>";
"tooltip" = true; "tooltip" = true;
"interval" = 5; "interval" = 3;
"justify" = "center";
}; };
"memory" = { "memory" = {
"format" = "{}%\nRAM"; "format" = "{} 󰍛";
"tooltip" = true;
"interval" = 5;
"justify" = "center";
}; };
"temperature" = { "temperature" = {
/* # "thermal-zone" = 2;
"thermal-zone" = 2; # "hwmon-path" = "/sys/class/hwmon/hwmon2/temp1_input";
"hwmon-path" = "/sys/class/hwmon/hwmon2/temp1_input";
"format-critical" = "{temperatureC}°C {icon}";
*/
"critical-threshold" = 80; "critical-threshold" = 80;
"format" = "{temperatureC}\n°C"; # "format-critical" = "{temperatureC}°C {icon}";
"justify" = "center"; "format" = "{temperatureC}°C {icon}";
"format-icons" = ["" "" ""];
}; };
"backlight" = { "backlight" = {
# "device" = "acpi_video1"; # "device" = "acpi_video1";
"format" = "{percent}%\n{icon}"; "format" = "{percent}% {icon}";
"format-icons" = ["" ""]; "format-icons" = ["" ""];
"justify" = "center";
}; };
"battery" = { "battery" = {
"states" = { "states" = {
@ -103,55 +91,55 @@
"warning" = 30; "warning" = 30;
"critical" = 1; "critical" = 1;
}; };
"tooltip-format" = "{timeTo}\n{power} watts\n{health}% health\n{cycles} cycles"; "format" = "{capacity}% {icon}";
"format" = "{icon}{capacity}%-\n{time}"; "format-charging" = "{capacity}% 󱐋";
"format-charging" = "{capacity}%+\n{time}"; "format-plugged" = "{capacity}% 󰚥";
"format-plugged" = "{capacity}%=\n{time}"; "format-alt" = "{time} {icon}";
"format-alt" = "{capacity}%"; "format-good" = ""; # An empty format will hide the modul;
"format-good" = ""; # An empty format will hide the module "format-full" = "󰁹";
"format-time" = "{H}:{m}"; "format-icons" = ["󰂎" "󰁻" "󰁽" "󰁿" "󰂂"];
"justify" = "center";
}; };
"network" = { "network" = {
"format-wifi" = "{bandwidthUpBits} up \n{bandwidthDownBits} down"; "format-wifi" = "{essid} ({signalStrength}%) ";
"format-ethernet" = "{bandwidthUpBits} up \n{bandwidthDownBits} down"; "format-ethernet" = "{ifname}: {ipaddr}/{cidr} ";
"format-linked" = "{bandwidthUpBits} up \n{bandwidthDownBits} down"; "format-linked" = "{ifname} (No IP) ";
"format-disconnected" = "No Network {icon}"; "format-disconnected" = "Disconnected ";
"format-alt" = "{bandwidthUpBits} up \n{bandwidthDownBits} down"; "format-alt" = "{ifname}: {ipaddr}/{cidr}";
"interval" = 5;
"justify" = "right";
}; };
"mpris" = { "mpris" = {
"format" = "{title}\nby {artist}"; "format" = "{title} by {artist}";
"title-len" = 64;
"artist-len" = 61;
"justify" = "center";
}; };
"pulseaudio" = { "pulseaudio" = {
/* # "scroll-step" = 1, # %, can be a floa;
"scroll-step" = 1, # %, can be a floa; "format" = "{volume} {icon} <span>{format_source}</span>";
"format" = "{volume}% {icon} {format_source}"; #"format" = "{volume}% {icon} {format_source}";
"format-muted" = " {format_source}"; #"format-bluetooth" = "{volume}% {icon} {format_source}";
*/ #"format-bluetooth-muted" = " {icon} {format_source}";
"format" = "{volume}%\n{format_source}"; #"format-muted" = " {format_source}";
"format-muted" = "MUTE\n{format_source}"; "format-muted" = "󰝟 {format_source}";
"format-bluetooth" = "{volume}%\n{format_source}"; "format-source" = "";
"format-bluetooth-muted" = "MUTE\n{format_source}"; "format-source-muted" = "";
"format-source" = "MIC ON"; "format-icons" = {
"format-source-muted" = "MIC OFF"; "headphones" = "";
"handsfree" = "󱥋";
"headset" = "󰋎";
"phone" = "";
"portable" = "";
"car" = "";
"default" = ["" "" ""];
};
# TODO: toggle mute? # TODO: toggle mute?
"on-click" = "${pkgs.pavucontrol}/bin/pavucontrol"; "on-click" = "pavucontrol";
"justify" = "center";
}; };
}; };
}; };
style = let style = let
border-width = "0px"; border-width = "0px";
in in
with style.colors.withHashPrefix; '' with colors.withHashPrefix; ''
* { * {
border-radius: 0; border-radius: 0;
font-family: "${style.font.name}", "Symbols Nerd Font Mono", sans-serif; font-family: "${font.name}", "Symbols Nerd Font Mono", sans-serif;
font-size: 16px; font-size: 16px;
} }

View file

@ -0,0 +1,10 @@
{
# font,
# colors,
...
}: {
programs.wezterm = {
enable = true;
extraConfig = builtins.readFile ./wezterm/config.lua;
};
}

View file

@ -1,33 +1,43 @@
local wezterm = require 'wezterm' local wezterm = require'wezterm'
-- rough duplication of colors.nix and font values from flake.nix
FONT = {
name = "IosevkaLyteTerm";
size = 12;
}
COLORS = {
};
local config = {} local config = {}
if wezterm.config_builder then if wezterm.config_builder then
config = wezterm.config_builder() config = wezterm.config_builder()
end end
config.adjust_window_size_when_changing_font_size = false local font_spec = { family = FONT.name, weight = 'Medium', italic = false }
config.font = wezterm.font_with_fallback { local font_size = tostring(FONT.size);
{ family = "IosevkaLyteTerm", weight = 'Medium', italic = false },
local font = wezterm.font_with_fallback{
font_spec,
{ family = 'Symbols Nerd Font Mono', weight = 'Regular', italic = false }, { family = 'Symbols Nerd Font Mono', weight = 'Regular', italic = false },
'Noto Color Emoji', 'Noto Color Emoji',
} }
config.font_size = 12.0
-- config.window_frame.font = config.font
-- config.window_frame.font_size = font_size
config.default_cursor_style = 'BlinkingBar'
-- config.disable_default_key_bindings = true -- config.disable_default_key_bindings = true
config.default_cursor_style = 'BlinkingBar'
config.font = font
config.font_size = font_size
config.hide_tab_bar_if_only_one_tab = true config.hide_tab_bar_if_only_one_tab = true
config.use_fancy_tab_bar = false config.use_fancy_tab_bar = false
config.tab_bar_at_bottom = true config.tab_bar_at_bottom = false
config.window_background_opacity = 1.0 config.window_background_opacity = 1.0
config.enable_kitty_keyboard = true config.enable_kitty_keyboard = true
config.show_new_tab_button_in_tab_bar = true
config.notification_handling = "SuppressFromFocusedTab"
-- config.front_end = "WebGpu" -- config.window_frame.font = config.font
-- config.webgpu_power_preference = 'HighPerformance' -- config.window_frame.font_size = font_size
config.enable_wayland = true
-- config.use_ime = true
local function tab_title(tab_info) local function tab_title(tab_info)
local title = tab_info.tab_title local title = tab_info.tab_title
@ -38,13 +48,106 @@ local function tab_title(tab_info)
end end
-- wezterm.on('format-tab-title', function (tab, tabs, panes, config, hover, max_width) -- wezterm.on('format-tab-title', function (tab, tabs, panes, config, hover, max_width)
wezterm.on('format-tab-title', function(tab, _, _, _, _, max_width) wezterm.on('format-tab-title', function (tab, _, _, _, _, max_width)
local title = tab_title(tab) local title = tab_title(tab)
return ' ' .. string.sub(title, 0, max_width - 2) .. ' ' return ' ' .. string.sub(title, 0, max_width - 2) .. ' '
end) end)
-- see nix module which has home manager create this color scheme file -- TODO: port colors
config.color_scheme = 'catppuccin-mocha-sapphire'; config.colors = {
foreground = '${fg}',
background = '${bg}',
cursor_bg = '${text}',
cursor_fg = '${bg}',
cursor_border = '${text}',
selection_fg = '${bg}',
selection_bg = '${yellow}',
scrollbar_thumb = '${bg2}',
split = '${bg5}',
ansi = {
'${colors.withHashPrefix."0"}',
'${colors.withHashPrefix."1"}',
'${colors.withHashPrefix."2"}',
'${colors.withHashPrefix."3"}',
'${colors.withHashPrefix."4"}',
'${colors.withHashPrefix."5"}',
'${colors.withHashPrefix."6"}',
'${colors.withHashPrefix."7"}',
},
brights = {
'${colors.withHashPrefix."8"}',
'${colors.withHashPrefix."9"}',
'${colors.withHashPrefix."10"}',
'${colors.withHashPrefix."11"}',
'${colors.withHashPrefix."12"}',
'${colors.withHashPrefix."13"}',
'${colors.withHashPrefix."14"}',
'${colors.withHashPrefix."15"}',
},
tab_bar = {
background = '${bg3}',
active_tab = {
bg_color = '${primary}',
fg_color = '${bg}',
italic = false,
},
inactive_tab = {
bg_color = '${bg2}',
fg_color = '${fgdim}',
italic = false,
},
inactive_tab_hover = {
bg_color = '${bg3}',
fg_color = '${primary}',
italic = false,
},
new_tab = {
bg_color = '${bg2}',
fg_color = '${fgdim}',
italic = false,
},
new_tab_hover = {
bg_color = '${bg3}',
fg_color = '${primary}',
italic = false,
},
},
-- Arbitrary colors of the palette in the range from 16 to 255
indexed = { [136] = '#af8700' },
-- Since: 20220319-142410-0fcdea07
-- When the IME, a dead key or a leader key are being processed and are effectively
-- holding input pending the result of input composition, change the cursor
-- to this color to give a visual cue about the compose state.
compose_cursor = 'orange',
-- Colors for copy_mode and quick_select
-- available since: 20220807-113146-c2fee766
-- In copy_mode, the color of the active text is:
-- 1. copy_mode_active_highlight_* if additional text was selected using the mouse
-- 2. selection_* otherwise
copy_mode_active_highlight_bg = { Color = '#000000' },
-- use `AnsiColor` to specify one of the ansi color palette values
-- (index 0-15) using one of the names "Black", "Maroon", "Green",
-- "Olive", "Navy", "Purple", "Teal", "Silver", "Grey", "Red", "Lime",
-- "Yellow", "Blue", "Fuchsia", "Aqua" or "White".
copy_mode_active_highlight_fg = { AnsiColor = 'Black' },
copy_mode_inactive_highlight_bg = { Color = '#52ad70' },
copy_mode_inactive_highlight_fg = { AnsiColor = 'White' },
quick_select_label_bg = { Color = 'peru' },
quick_select_label_fg = { Color = '#ffffff' },
quick_select_match_bg = { AnsiColor = 'Navy' },
quick_select_match_fg = { Color = '#ffffff' },
}
config.inactive_pane_hsb = { config.inactive_pane_hsb = {
saturation = 0.8, saturation = 0.8,
@ -55,73 +158,63 @@ config.keys = {
{ {
key = 'Insert', key = 'Insert',
mods = 'SHIFT', mods = 'SHIFT',
action = wezterm.action.PasteFrom 'Clipboard' action = wezterm.action.PasteFrom'Clipboard'
}, },
{ {
key = 'v', key = 'v',
mods = 'CTRL|SHIFT', mods = 'CTRL|SHIFT',
action = wezterm.action.PasteFrom 'PrimarySelection' action = wezterm.action.PasteFrom'PrimarySelection'
}, },
{ {
key = 't', key = 't',
mods = 'CTRL|SHIFT', mods = 'CTRL|SHIFT',
action = wezterm.action.SpawnTab 'CurrentPaneDomain' action = wezterm.action.SpawnTab'CurrentPaneDomain'
}, },
{ {
key = 'h', key = 'h',
mods = 'CTRL', mods = 'CTRL',
action = wezterm.action.ActivatePaneDirection 'Left' action = wezterm.action.ActivatePaneDirection'Left'
}, },
{ {
key = 'l', key = 'l',
mods = 'CTRL', mods = 'CTRL',
action = wezterm.action.ActivatePaneDirection 'Right' action = wezterm.action.ActivatePaneDirection'Right'
}, },
{ {
key = 'k', key = 'k',
mods = 'CTRL', mods = 'CTRL',
action = wezterm.action.ActivatePaneDirection 'Up' action = wezterm.action.ActivatePaneDirection'Up'
}, },
{ {
key = 'j', key = 'j',
mods = 'CTRL', mods = 'CTRL',
action = wezterm.action.ActivatePaneDirection 'Down' action = wezterm.action.ActivatePaneDirection'Down'
}, },
{ {
key = 'j', key = 'j',
mods = 'CTRL|SHIFT', mods = 'CTRL|SHIFT',
action = wezterm.action.SplitVertical { domain = 'CurrentPaneDomain' } action = wezterm.action.SplitVertical{domain='CurrentPaneDomain'}
}, },
{ {
key = 'l', key = 'l',
mods = 'CTRL|SHIFT', mods = 'CTRL|SHIFT',
action = wezterm.action.SplitHorizontal { domain = 'CurrentPaneDomain' } action = wezterm.action.SplitHorizontal{domain='CurrentPaneDomain'}
}, },
{ {
key = 'k', key = 'k',
mods = 'CTRL|SHIFT', mods = 'CTRL|SHIFT',
action = wezterm.action.SplitVertical { args = { 'top' }, domain = 'CurrentPaneDomain' } action = wezterm.action.SplitVertical{args={'top'},domain='CurrentPaneDomain'}
}, },
{ {
key = 'h', key = 'h',
mods = 'CTRL|SHIFT', mods = 'CTRL|SHIFT',
action = wezterm.action.SplitHorizontal { args = { 'right' }, domain = 'CurrentPaneDomain' } action = wezterm.action.SplitHorizontal{args={'right'},domain='CurrentPaneDomain'}
}, },
{ {
key = 'p', key = 'p',
mods = 'CTRL|SHIFT', mods = 'CTRL|SHIFT',
action = wezterm.action.ActivateCommandPalette action = wezterm.action.ActivateCommandPalette
}, },
{
key = 'w',
mods = 'CTRL|SHIFT',
action = wezterm.action.CloseCurrentPane { confirm = true },
},
{
key = 'w',
mods = 'CTRL|ALT|SHIFT',
action = wezterm.action.CloseCurrentTab { confirm = true },
},
{ {
key = 'l', key = 'l',
mods = 'CTRL|SHIFT|ALT', mods = 'CTRL|SHIFT|ALT',
@ -130,15 +223,15 @@ config.keys = {
{ {
key = 'r', key = 'r',
mods = 'CTRL|SHIFT|ALT', mods = 'CTRL|SHIFT|ALT',
action = wezterm.action.RotatePanes 'Clockwise' action = wezterm.action.RotatePanes'Clockwise'
}, },
} }
-- config.unix_domains = { -- config.unix_domains = {
-- { -- {
-- name = 'unix', -- name = 'unix',
-- local_echo_threshold_ms = 10, -- local_echo_threshold_ms = 10,
-- }, -- },
-- } -- }
-- config.default_gui_startup_args = { 'connect', 'unix' } -- config.default_gui_startup_args = { 'connect', 'unix' }

View file

@ -0,0 +1,513 @@
{
colors,
lib,
...
}: {
# zellij does not support modern terminal keyboard input:
# https://github.com/zellij-org/zellij/issues/735
programs.zellij = {
# uses home manager's toKDL generator
enable = true;
# enableFishIntegration = true;
settings = {
pane_frames = false;
simplified_ui = true;
default_mode = "locked";
mouse_mode = true;
copy_clipboard = "primary";
copy_on_select = true;
mirror_session = false;
keybinds = with builtins; let
binder = bind: let
keys = elemAt bind 0;
action = elemAt bind 1;
argKeys = map (k: "\"${k}\"") (lib.lists.flatten [keys]);
in {
name = "bind ${concatStringsSep " " argKeys}";
value = action;
};
layer = binds: (listToAttrs (map binder binds));
in {
# _props = {clear-defaults = true;};
normal = {};
locked = layer [
[["Ctrl g"] {SwitchToMode = "Normal";}]
[["Ctrl L"] {NewPane = "Right";}]
[["Ctrl Z"] {NewPane = "Right";}]
[["Ctrl J"] {NewPane = "Down";}]
[["Ctrl h"] {MoveFocus = "Left";}]
[["Ctrl l"] {MoveFocus = "Right";}]
[["Ctrl j"] {MoveFocus = "Down";}]
[["Ctrl k"] {MoveFocus = "Up";}]
];
resize = layer [
[["Ctrl n"] {SwitchToMode = "Normal";}]
[["h" "Left"] {Resize = "Increase Left";}]
[["j" "Down"] {Resize = "Increase Down";}]
[["k" "Up"] {Resize = "Increase Up";}]
[["l" "Right"] {Resize = "Increase Right";}]
[["H"] {Resize = "Decrease Left";}]
[["J"] {Resize = "Decrease Down";}]
[["K"] {Resize = "Decrease Up";}]
[["L"] {Resize = "Decrease Right";}]
[["=" "+"] {Resize = "Increase";}]
[["-"] {Resize = "Decrease";}]
];
pane = layer [
[["Ctrl p"] {SwitchToMode = "Normal";}]
[["h" "Left"] {MoveFocus = "Left";}]
[["l" "Right"] {MoveFocus = "Right";}]
[["j" "Down"] {MoveFocus = "Down";}]
[["k" "Up"] {MoveFocus = "Up";}]
[["p"] {SwitchFocus = [];}]
[
["n"]
{
NewPane = [];
SwitchToMode = "Normal";
}
]
[
["d"]
{
NewPane = "Down";
SwitchToMode = "Normal";
}
]
[
["r"]
{
NewPane = "Right";
SwitchToMode = "Normal";
}
]
[
["x"]
{
CloseFocus = [];
SwitchToMode = "Normal";
}
]
[
["f"]
{
ToggleFocusFullscreen = [];
SwitchToMode = "Normal";
}
]
[
["z"]
{
TogglePaneFrames = [];
SwitchToMode = "Normal";
}
]
[
["w"]
{
ToggleFloatingPanes = [];
SwitchToMode = "Normal";
}
]
[
["e"]
{
TogglePaneEmbedOrFloating = [];
SwitchToMode = "Normal";
}
]
[
["c"]
{
SwitchToMode = "RenamePane";
PaneNameInput = 0;
}
]
];
move = layer [
[["Ctrl h"] {SwitchToMode = "Normal";}]
[["n" "Tab"] {MovePane = [];}]
[["p"] {MovePaneBackwards = [];}]
[["h" "Left"] {MovePane = "Left";}]
[["j" "Down"] {MovePane = "Down";}]
[["k" "Up"] {MovePane = "Up";}]
[["l" "Right"] {MovePane = "Right";}]
];
tab = layer [
[["Ctrl t"] {SwitchToMode = "Normal";}]
[
["r"]
{
SwitchToMode = "RenameTab";
TabNameInput = 0;
}
]
[["h" "Left" "Up" "k"] {GoToPreviousTab = [];}]
[["l" "Right" "Down" "j"] {GoToNextTab = [];}]
[
["n"]
{
NewTab = [];
SwitchToMode = "Normal";
}
]
[
["x"]
{
CloseTab = [];
SwitchToMode = "Normal";
}
]
[
["s"]
{
ToggleActiveSyncTab = [];
SwitchToMode = "Normal";
}
]
[
["1"]
{
GoToTab = 1;
SwitchToMode = "Normal";
}
]
[
["2"]
{
GoToTab = 2;
SwitchToMode = "Normal";
}
]
[
["3"]
{
GoToTab = 3;
SwitchToMode = "Normal";
}
]
[
["4"]
{
GoToTab = 4;
SwitchToMode = "Normal";
}
]
[
["5"]
{
GoToTab = 5;
SwitchToMode = "Normal";
}
]
[
["6"]
{
GoToTab = 6;
SwitchToMode = "Normal";
}
]
[
["7"]
{
GoToTab = 7;
SwitchToMode = "Normal";
}
]
[
["8"]
{
GoToTab = 8;
SwitchToMode = "Normal";
}
]
[
["9"]
{
GoToTab = 9;
SwitchToMode = "Normal";
}
]
[["Tab"] {ToggleTab = [];}]
];
scroll = layer [
[["Ctrl s"] {SwitchToMode = "Normal";}]
[
["e"]
{
EditScrollback = [];
SwitchToMode = "Normal";
}
]
[
["s"]
{
SwitchToMode = "EnterSearch";
SearchInput = 0;
}
]
[
["Ctrl c"]
{
ScrollToBottom = [];
SwitchToMode = "Normal";
}
]
[["j" "Down"] {ScrollDown = [];}]
[["k" "Up"] {ScrollUp = [];}]
[["Ctrl f" "PageDown" "Right" "l"] {PageScrollDown = [];}]
[["Ctrl b" "PageUp" "Left" "h"] {PageScrollUp = [];}]
[["d"] {HalfPageScrollDown = [];}]
[["u"] {HalfPageScrollUp = [];}]
# uncomment this and adjust key if using copy_on_select=false
# bind "Alt c" { Copy; }
];
search = layer [
[["Ctrl s"] {SwitchToMode = "Normal";}]
[
["Ctrl c"]
{
ScrollToBottom = [];
SwitchToMode = "Normal";
}
]
[["j" "Down"] {ScrollDown = [];}]
[["k" "Up"] {ScrollUp = [];}]
[["Ctrl f" "PageDown" "Right" "l"] {PageScrollDown = [];}]
[["Ctrl b" "PageUp" "Left" "h"] {PageScrollUp = [];}]
[["d"] {HalfPageScrollDown = [];}]
[["u"] {HalfPageScrollUp = [];}]
[["n"] {Search = "down";}]
[["p"] {Search = "up";}]
[["c"] {SearchToggleOption = "CaseSensitivity";}]
[["w"] {SearchToggleOption = "Wrap";}]
[["o"] {SearchToggleOption = "WholeWord";}]
];
entersearch = layer [
[["Ctrl c" "Esc"] {SwitchToMode = "Scroll";}]
[["Enter"] {SwitchToMode = "Search";}]
];
renametab = layer [
[["Ctrl c"] {SwitchToMode = "Normal";}]
[
["Esc"]
{
UndoRenameTab = [];
SwitchToMode = "Tab";
}
]
];
renamepane = layer [
[["Ctrl c"] {SwitchToMode = "Normal";}]
[
["Esc"]
{
UndoRenamePane = [];
SwitchToMode = "Pane";
}
]
];
session = layer [
[["Ctrl o"] {SwitchToMode = "Normal";}]
[["Ctrl s"] {SwitchToMode = "Scroll";}]
[["d"] {Detach = [];}]
];
tmux = layer [
[["["] {SwitchToMode = "Scroll";}]
[
["Ctrl b"]
{
Write = 2;
SwitchToMode = "Normal";
}
]
[
["\\\""]
{
NewPane = "Down";
SwitchToMode = "Normal";
}
]
[
["%"]
{
NewPane = "Right";
SwitchToMode = "Normal";
}
]
[
["z"]
{
ToggleFocusFullscreen = [];
SwitchToMode = "Normal";
}
]
[
["c"]
{
NewTab = [];
SwitchToMode = "Normal";
}
]
[[","] {SwitchToMode = "RenameTab";}]
[
["p"]
{
GoToPreviousTab = [];
SwitchToMode = "Normal";
}
]
[
["n"]
{
GoToNextTab = [];
SwitchToMode = "Normal";
}
]
[
["Left"]
{
MoveFocus = "Left";
SwitchToMode = "Normal";
}
]
[
["Right"]
{
MoveFocus = "Right";
SwitchToMode = "Normal";
}
]
[
["Down"]
{
MoveFocus = "Down";
SwitchToMode = "Normal";
}
]
[
["Up"]
{
MoveFocus = "Up";
SwitchToMode = "Normal";
}
]
[
["h"]
{
MoveFocus = "Left";
SwitchToMode = "Normal";
}
]
[
["l"]
{
MoveFocus = "Right";
SwitchToMode = "Normal";
}
]
[
["j"]
{
MoveFocus = "Down";
SwitchToMode = "Normal";
}
]
[
["k"]
{
MoveFocus = "Up";
SwitchToMode = "Normal";
}
]
[["o"] {FocusNextPane = [];}]
[["d"] {Detach = [];}]
[["Space"] {NextSwapLayout = [];}]
[
["x"]
{
CloseFocus = [];
SwitchToMode = "Normal";
}
]
];
"shared_except \"locked\"" = layer [
[["Ctrl g"] {SwitchToMode = "Locked";}]
[["Ctrl q"] {Quit = [];}]
[["Alt n"] {NewPane = [];}]
[["Alt h" "Alt Left"] {MoveFocusOrTab = "Left";}]
[["Alt l" "Alt Right"] {MoveFocusOrTab = "Right";}]
[["Alt j" "Alt Down"] {MoveFocus = "Down";}]
[["Alt k" "Alt Up"] {MoveFocus = "Up";}]
[["Alt ]" "Alt +"] {Resize = "Increase";}]
[["Alt -"] {Resize = "Decrease";}]
[["Alt ["] {PreviousSwapLayout = [];}]
[["Alt ]"] {NextSwapLayout = [];}]
];
"shared_except \"normal\" \"locked\"" = layer [
[["Enter" "Esc"] {SwitchToMode = "Normal";}]
];
"shared_except \"pane\" \"locked\"" = layer [
[["Ctrl p"] {SwitchToMode = "Pane";}]
];
"shared_except \"resize\" \"locked\"" = layer [
[["Ctrl n"] {SwitchToMode = "Resize";}]
];
"shared_except \"scroll\" \"locked\"" = layer [
[["Ctrl s"] {SwitchToMode = "Scroll";}]
];
"shared_except \"session\" \"locked\"" = layer [
[["Ctrl o"] {SwitchToMode = "Session";}]
];
"shared_except \"tab\" \"locked\"" = layer [
[["Ctrl t"] {SwitchToMode = "Tab";}]
];
"shared_except \"move\" \"locked\"" = layer [
[["Ctrl h"] {SwitchToMode = "Move";}]
];
"shared_except \"tmux\" \"locked\"" = layer [
[["Ctrl b"] {SwitchToMode = "Tmux";}]
];
};
default_layout = "compact";
theme = "match";
themes = {
match = with colors.withHashPrefix; {
fg = fg;
bg = bg;
black = bg;
white = fg;
red = red;
green = green;
yellow = yellow;
blue = blue;
magenta = purple;
cyan = blue;
orange = orange;
};
};
# TODO: port config
plugins = {
# tab-bar = {path = "tab-bar";};
# compact-bar = {path = "compact-bar";};
};
ui = {
pane_frames = {
rounded_corners = true;
hide_session_name = true;
};
};
};
};
home.shellAliases = {
z = "zellij";
};
}

257
modules/nixos/common.nix Normal file
View file

@ -0,0 +1,257 @@
{
config,
lib,
inputs,
colors,
# outputs,
system,
pkgs,
...
}: {
networking.hostName = lib.mkDefault "nixoslyte";
imports = [
inputs.home-manager.nixosModules.home-manager
];
hardware.enableRedistributableFirmware = true;
services.journald.extraConfig = "SystemMaxUse=1G";
environment = {
variables = {
EDITOR = "hx";
VISUAL = "hx";
PAGER = "less";
MANPAGER = "less";
};
systemPackages = with pkgs;
[
# age
# bat
# bc
# bind
# bottom
# btrfs-progs
# cue
curl
# dogdns
dua
eza
fd
file
fzf
gnumake
# gron
# hexyl
iputils
# jq
killall
less
mosh
# nmap
nettools
openssl
# pciutils
# pv
# rclone
# restic
ripgrep
rsync
# rtx
sd
# sops
smartmontools
# sqlite
# skim
# sysstat
unzip
# usbutils
# watchexec
wget
# xh
zellij
# zstd
]
++ (with inputs.home-manager.packages.${system}; [
home-manager
])
++ (with inputs.helix.packages.${system}; [
helix
]);
};
users.groups.daniel = {};
users.users = {
daniel = {
isNormalUser = true;
home = "/home/daniel/.home";
createHome = true;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAPLXOjupz3ScYjgrF+ehrbp9OvGAWQLI6fplX6w9Ijb daniel@lyte.dev"
];
group = "daniel";
extraGroups = ["users" "wheel" "video" "dialout" "uucp"];
packages = [];
};
root = {
openssh.authorizedKeys.keys = config.users.users.daniel.openssh.authorizedKeys.keys;
};
};
i18n = {
defaultLocale = "en_US.UTF-8";
};
services = {
xserver = {
layout = "us";
xkbOptions = "ctrl:nocaps";
};
openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
};
openFirewall = lib.mkDefault false;
# listenAddresses = [
# { addr = "0.0.0.0"; port = 22; }
# ];
};
tailscale = {
enable = true;
useRoutingFeatures = lib.mkDefault "client";
};
fwupd.enable = true;
smartd.enable = true;
};
console = {
font = "Lat2-Terminus16";
useXkbConfig = true;
earlySetup = true;
colors = with colors; [
bg
red
green
orange
blue
purple
yellow
fg3
fgdim
red
green
orange
blue
purple
yellow
fg
];
};
networking = {
useDHCP = lib.mkDefault true;
firewall = {
enable = lib.mkDefault true;
allowPing = lib.mkDefault true;
allowedTCPPorts = lib.mkDefault [];
allowedUDPPorts = lib.mkDefault [];
};
# TODO: podman equivalent?
extraHosts = ''
::1 host.docker.internal
127.0.0.1 host.docker.internal
'';
};
nix = {
settings = {
trusted-users = ["root" "daniel"];
experimental-features = lib.mkDefault ["nix-command" "flakes"];
substituters = [
"https://cache.nixos.org/"
"https://helix.cachix.org"
"https://nix-community.cachix.org"
"https://nix.h.lyte.dev"
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"helix.cachix.org-1:ejp9KQpR1FBI2onstMQ34yogDm4OgU2ru6lIwPvuCVs="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"h.lyte.dev:HeVWtne31ZG8iMf+c15VY3/Mky/4ufXlfTpT8+4Xbs0="
];
};
registry = {
self.flake = inputs.self;
nixpkgs = {
from = {
id = "nixpkgs";
type = "indirect";
};
flake = inputs.nixpkgs;
};
};
};
nixpkgs = {
config = {
allowUnfree = true;
};
hostPlatform = lib.mkDefault "x86_64-linux";
};
programs = {
fish = {
enable = true;
};
tmux = {
enable = true;
clock24 = true;
};
traceroute.enable = true;
git = {
enable = true;
package = pkgs.gitFull;
lfs = {
enable = true;
};
};
# https://github.com/nix-community/home-manager/issues/3113
dconf.enable = true;
};
time = {
timeZone = "America/Chicago";
};
users = {
defaultUserShell = pkgs.fish;
};
# TODO: should not be in common?
# services.udev.extraRules = ''
# # https://betaflight.com/docs/wiki/archive/Installing-Betaflight#step-1
# # ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="2e3c", ATTRS{idProduct}=="df11", MODE="0664", GROUP="uucp"
# # ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE="0664", GROUP="uucp"'
# '';
}

File diff suppressed because it is too large Load diff

View file

@ -1,93 +0,0 @@
{
lib,
config,
pkgs,
...
}: let
inherit (lib) mkEnableOption mkOption types mkIf;
inherit (lib.strings) optionalString;
cfg = config.services.deno-netlify-ddns-client;
in {
options.services.deno-netlify-ddns-client = {
enable = mkEnableOption "Enable the deno-netlify-ddns client.";
username = mkOption {
type = types.str;
};
passwordFile = mkOption {
type = types.str;
};
endpoint = mkOption {
type = types.str;
default = "https://netlify-ddns.deno.dev";
};
ipv4 = mkOption {
type = types.bool;
default = true;
};
ipv6 = mkOption {
type = types.bool;
default = true;
};
requestTimeout = mkOption {
type = types.int;
description = "The maximum number of seconds before the HTTP request times out.";
default = 180;
};
afterBootTime = mkOption {
type = types.str;
description = "A systemd.timers timespan. This option corresponds to the OnBootSec field in the timerConfig.";
default = "5m";
};
every = mkOption {
type = types.str;
description = "A systemd.timers timespan. This option corresponds to the OnUnitActiveSec field in the timerConfig.";
default = "5m";
};
};
config = {
systemd.timers.deno-netlify-ddns-client = {
enable = mkIf cfg.enable true;
after = ["network.target"];
wantedBy = ["timers.target"];
timerConfig = {
OnBootSec = cfg.afterBootTime;
OnUnitActiveSec = cfg.every;
Unit = "deno-netlify-ddns-client.service";
};
};
systemd.services.deno-netlify-ddns-client = {
enable = mkIf cfg.enable true;
after = ["network.target"];
script = ''
set -eu
password="$(cat "${cfg.passwordFile}")"
${optionalString cfg.ipv4 ''
"${pkgs.curl}/bin/curl" -4 -s \
-vvv \
-X POST \
--max-time ${toString cfg.requestTimeout} \
-u "${cfg.username}:''${password}" \
-L "${cfg.endpoint}/v1/netlify-ddns/replace-all-relevant-user-dns-records" 2>&1 \
| "${pkgs.sd}/bin/sd" --fixed-strings "''${password}" "[REDACTED]" \
| "${pkgs.sd}/bin/sd" -f i "Authorization: .*" "Authorization: [REST OF LINE REDACTED]"
''}
${optionalString cfg.ipv6 ''
${pkgs.curl}/bin/curl -6 -s \
-vvv \
-X POST \
--max-time ${toString cfg.requestTimeout} \
-u "${cfg.username}:''${password}" \
-L "${cfg.endpoint}/v1/netlify-ddns/replace-all-relevant-user-dns-records" 2>&1 \
| "${pkgs.sd}/bin/sd" --fixed-strings "''${password}" "[REDACTED]" \
| "${pkgs.sd}/bin/sd" -f i "Authorization: .*" "Authorization: [REST OF LINE REDACTED]"
''}
'';
serviceConfig = {
Type = "oneshot";
User = "root";
};
};
};
}

View file

@ -0,0 +1,156 @@
{
pkgs,
inputs,
outputs,
system,
...
}: {
imports = [
./sway.nix
# ./hyprland.nix
# ./plasma.nix
# ./gnome.nix
./user-installed-applications.nix
./kde-connect.nix
];
nixpkgs.overlays = [outputs.overlays.modifications];
# fonts.packages if unstable?
fonts.packages = with pkgs;
[
(nerdfonts.override {fonts = ["NerdFontsSymbolsOnly"];})
]
++ (with inputs.nixpkgs.legacyPackages.${system}; [
(iosevka.override {
set = "lyteterm";
privateBuildPlan = ''
[buildPlans.iosevka-lyteterm]
family = "IosevkaLyteTerm"
spacing = "fontconfig-mono"
serifs = "sans"
export-glyph-names = true
[buildPlans.iosevka-lyteterm.ligations]
inherits = "dlig"
disables = [ "exeqeqeq", "exeqeq", "exeqeq-dl", "exeq", "ineq", "connected-underscore", "connected-tilde-as-wave" ]
[buildPlans.iosevka-lyteterm.weights.regular]
shape = 400
menu = 400
css = 400
[buildPlans.iosevka-lyteterm.weights.book]
shape = 450
menu = 450
css = 450
[buildPlans.iosevka-lyteterm.weights.bold]
shape = 700
menu = 700
css = 700
[buildPlans.iosevka-lyteterm.weights.black]
shape = 900
menu = 900
css = 900
# [[buildPlans.iosevka-lyteterm.compatibility-ligatures]]
# unicode = 57600 # 0xE100
# featureTag = 'calt'
# kequence = '<*>'
[buildPlans.iosevka-lyteterm.variants]
inherits = "ss01"
[buildPlans.iosevka-lyteterm.variants.design]
capital-a = 'curly-serifless'
capital-b = 'standard-interrupted-serifless'
capital-c = 'unilateral-inward-serifed'
capital-d = 'standard-serifless'
capital-g = 'toothless-rounded-inward-serifed-hooked'
capital-i = 'serifed'
capital-j = 'serifed'
capital-k = 'curly-serifless'
capital-l = 'motion-serifed'
capital-m = 'hanging-serifless'
capital-n = 'asymmetric-serifless'
capital-p = 'open-serifless'
capital-q = 'crossing'
capital-r = 'standing-open-serifless'
capital-s = 'unilateral-inward-serifed'
capital-t = 'motion-serifed'
capital-u = 'toothless-corner-serifless'
capital-v = 'curly-serifless'
capital-w = 'curly-serifless'
capital-x = 'curly-serifless'
capital-y = 'curly-base-serifed'
capital-z = 'curly-top-serifed-with-crossbar'
a = 'double-storey-toothless-corner'
b = 'toothless-corner-serifless'
c = 'unilateral-inward-serifed'
d = 'toothless-corner-serifless'
e = 'flat-crossbar'
f = 'tailed'
g = 'double-storey-open'
# g = 'single-storey-earless-corner-flat-hook'
h = 'straight-serifless'
i = 'tailed-serifed'
j = 'serifed'
k = 'curly-serifless'
l = 'tailed-serifed'
m = 'earless-corner-double-arch-serifless'
n = 'earless-corner-straight-serifless'
p = 'earless-corner-serifless'
q = 'earless-corner-diagonal-tailed-serifless'
r = 'earless-corner-serifless'
s = 'unilateral-inward-serifed'
t = 'bent-hook-asymmetric'
u = 'toothless-corner-serifless'
v = 'curly-serifless'
w = 'curly-serifless'
x = 'curly-serifless'
y = 'curly-turn-serifless'
z = 'curly-top-serifed-with-crossbar'
# cyrl-capital-ze = 'unilateral-inward-serifed'
zero = 'reverse-slashed-split'
one = 'base'
two = 'curly-neck'
three = 'two-arcs'
four = 'semi-open-non-crossing'
# five = 'vertical-upper-left-bar'
five = 'upright-flat'
six = 'straight-bar'
seven = 'curly-serifed-crossbar'
eight = 'two-circles'
nine = 'straight-bar'
tilde = 'low'
asterisk = 'penta-low'
underscore = 'above-baseline'
pilcrow = 'low'
caret = 'low'
paren = 'flat-arc'
brace = 'curly-flat-boundary'
number-sign = 'upright-open'
ampersand = 'upper-open'
at = 'compact'
dollar = 'interrupted'
cent = 'open'
percent = 'rings-segmented-slash'
bar = 'force-upright'
ascii-single-quote = 'raised-comma'
ascii-grave = 'straight'
question = 'smooth'
punctuation-dot = 'round'
'';
})
]);
hardware = {
opengl = {
enable = true;
driSupport32Bit = true;
driSupport = true;
};
};
}

3
modules/nixos/ewwbar.nix Normal file
View file

@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [eww-wayland];
}

View file

@ -1,31 +1,21 @@
{ {pkgs, ...}: {
pkgs,
lib,
...
}: {
imports = [./pipewire.nix]; imports = [./pipewire.nix];
# mkForce is used liberally to take precedence over KDE Plasma services.xserver.enable = true;
# so I can have both "usable" at once
services.xserver.enable = lib.mkDefault true;
services.xserver.displayManager.gdm = { services.xserver.displayManager.gdm = {
enable = lib.mkForce true; # take precedence over KDE's SDDM enable = true;
}; };
services.displayManager.execCmd = lib.mkForce "exec ${pkgs.gnome.gdm}/bin/gdm";
services.displayManager.defaultSession = lib.mkForce "gnome";
programs.ssh.askPassword = "${pkgs.gnome.seahorse}/libexec/seahorse/ssh-askpass";
hardware.pulseaudio.enable = false; hardware.pulseaudio.enable = false;
services.xserver.desktopManager.gnome = { services.xserver.desktopManager.gnome = {
enable = lib.mkDefault true; enable = true;
};
extraGSettingsOverridePackages = [pkgs.gnome.mutter]; programs.gnupg.agent = {
extraGSettingsOverrides = '' enable = true;
[org.gnome.mutter] pinentryFlavor = "gnome3";
experimental-features=['scale-monitor-framebuffer'] enableSSHSupport = true;
'';
}; };
xdg.portal = { xdg.portal = {
@ -40,44 +30,45 @@
environment = { environment = {
variables = { variables = {
GTK_THEME = "Catppuccin-Mocha-Compact-Sapphire-Dark";
VISUAL = "hx"; VISUAL = "hx";
PAGER = "less"; PAGER = "less";
MANPAGER = "less"; MANPAGER = "less";
}; };
systemPackages = with pkgs; [ systemPackages = with pkgs; [
gnome.gnome-power-manager
brightnessctl brightnessctl
feh feh
# gimp
grim grim
# inkscape
# krita
libinput libinput
libinput-gestures libinput-gestures
libnotify libnotify
# lutris
# nil
# nixpkgs-fmt
noto-fonts noto-fonts
pamixer pamixer
# pavucontrol
playerctl playerctl
# pulseaudio
pulsemixer pulsemixer
# rclone
# restic
slurp slurp
# steam
swaybg swaybg
swayidle swayidle
swaylock swaylock
# vlc
# vulkan-tools
waybar waybar
# weechat
# wine
wl-clipboard wl-clipboard
zathura zathura
/*
gimp
inkscape
krita
pavucontrol
pulseaudio
rclone
restic
steam
vlc
vulkan-tools
weechat
wine
*/
]; ];
}; };
} }

View file

@ -0,0 +1,9 @@
{
outputs,
pkgs,
...
}: {
imports = [outputs.nixosModules.ewwbar outputs.nixosModules.pipewire];
programs.hyprland.enable = true;
environment.systemPackages = with pkgs; [hyprpaper];
}

25
modules/nixos/intel.nix Normal file
View file

@ -0,0 +1,25 @@
{
lib,
config,
pkgs,
...
}: {
nixpkgs.config = {
packageOverrides = pkgs: {
vaapiIntel = pkgs.vaapiIntel.override {enableHybridCodec = true;};
};
};
hardware = {
cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
opengl = {
extraPackages = with pkgs; [
intel-media-driver # LIBVA_DRIVER_NAME=iHD
vaapiIntel # LIBVA_DRIVER_NAME=i965 (older but works better for Firefox/Chromium)
vaapiVdpau
libvdpau-va-gl
];
};
};
}

View file

@ -0,0 +1,20 @@
{
programs.kdeconnect = {
enable = true;
};
networking.firewall = {
allowedTCPPortRanges = [
{
from = 1714;
to = 1764;
}
];
allowedUDPPortRanges = [
{
from = 1714;
to = 1764;
}
];
};
}

22
modules/nixos/melee.nix Normal file
View file

@ -0,0 +1,22 @@
{
# flake,
inputs,
# outputs,
# lib,
# config,
# pkgs,
# system,
# modulesPath,
...
}: {
imports = [inputs.ssbm.nixosModule];
ssbm = {
cache.enable = true;
gcc = {
rules.enable = true;
oc-kmod.enable = true;
};
};
}

View file

@ -0,0 +1,16 @@
{...}: {
environment.etc = {
"pipewire/pipewire.conf.d/92-low-latency.conf".text = ''
context.properties = {
default.clock.rate = 48000
default.clock.quantum = 128
default.clock.min-quantum = 128
default.clock.max-quantum = 128
}
jack.properties = {
node.latency = 128/48000
}
'';
};
}

View file

@ -0,0 +1,26 @@
{...}: {
services.pipewire = {
enable = true;
wireplumber.enable = true;
pulse.enable = true;
jack.enable = true;
alsa = {
enable = true;
support32Bit = true;
};
};
hardware = {
pulseaudio = {
support32Bit = true;
};
};
security = {
# I forget why I need these...
polkit.enable = true;
rtkit.enable = true;
};
}

5
modules/nixos/plasma.nix Normal file
View file

@ -0,0 +1,5 @@
{...}: {
services.xserver.enable = true;
services.xserver.displayManager.sddm.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
}

23
modules/nixos/podman.nix Normal file
View file

@ -0,0 +1,23 @@
{pkgs, ...}: {
environment = {
systemPackages = with pkgs; [
podman-compose
];
};
virtualisation = {
podman = {
enable = true;
# Create a `docker` alias for podman, to use it as a drop-in replacement
dockerCompat = true;
# Required for containers under podman-compose to be able to talk to each other.
defaultNetwork.settings.dns_enabled = true;
};
oci-containers = {
backend = "podman";
};
};
}

View file

@ -0,0 +1,39 @@
{pkgs, ...}: {
# this is really just for development usage
services.postgresql = {
enable = true;
ensureDatabases = ["daniel"];
ensureUsers = [
{
name = "daniel";
ensureDBOwnership = true;
}
];
enableTCPIP = true;
package = pkgs.postgresql_15;
authentication = pkgs.lib.mkOverride 10 ''
#type database DBuser auth-method
local all postgres peer map=superuser_map
local all daniel peer map=superuser_map
local sameuser all peer map=superuser_map
# lan ipv4
host all all 10.0.0.0/24 trust
host all all 127.0.0.1/32 trust
# tailnet ipv4
host all all 100.64.0.0/10 trust
'';
identMap = ''
# ArbitraryMapName systemUser DBUser
superuser_map root postgres
superuser_map postgres postgres
superuser_map daniel postgres
# Let other names login as themselves
superuser_map /^(.*)$ \1
'';
};
}

81
modules/nixos/sway.nix Normal file
View file

@ -0,0 +1,81 @@
{pkgs, ...}: {
imports = [./pipewire.nix];
# services.xserver.libinput.enable = true;
services.gnome.gnome-keyring.enable = true;
programs.gnupg.agent = {
enable = true;
pinentryFlavor = "gnome3";
enableSSHSupport = true;
};
programs.sway = {
enable = true;
wrapperFeatures.gtk = true;
};
xdg.portal = {
enable = true;
wlr.enable = true;
extraPortals = with pkgs; [
xdg-desktop-portal-wlr
];
};
services.dbus.enable = true;
programs.thunar = {
enable = true;
plugins = with pkgs.xfce; [thunar-archive-plugin thunar-volman];
};
services.gvfs = {
enable = true;
};
environment = {
variables = {
GTK_THEME = "Catppuccin-Mocha-Compact-Sapphire-Dark";
VISUAL = "hx";
PAGER = "less";
MANPAGER = "less";
};
systemPackages = with pkgs; [
brightnessctl
feh
# gimp
grim
# inkscape
# krita
libinput
libinput-gestures
libnotify
# lutris
# nil
# nixpkgs-fmt
noto-fonts
pamixer
# pavucontrol
playerctl
# pulseaudio
pulsemixer
# rclone
# restic
slurp
# steam
swaybg
swayidle
swaylock
# vlc
# vulkan-tools
waybar
# weechat
# wine
wl-clipboard
zathura
];
};
}

View file

@ -0,0 +1,14 @@
{pkgs, ...}: {
# enable flatpaks
services.flatpak.enable = true;
# enable appimages
boot.binfmt.registrations.appimage = {
wrapInterpreterInShell = false;
interpreter = "${pkgs.appimage-run}/bin/appimage-run";
recognitionType = "magic";
offset = 0;
mask = ''\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff'';
magicOrExtension = ''\x7fELF....AI\x02'';
};
}

9
modules/nixos/wifi.nix Normal file
View file

@ -0,0 +1,9 @@
{lib, ...}: {
networking.networkmanager.enable = lib.mkDefault true;
systemd.services.NetworkManager-wait-online.enable = lib.mkDefault false;
# TODO: networking.networkmanager.wifi.backend = "iwd"; ?
# TODO: powersave?
# TODO: can I pre-configure my usual wifi networks with SSIDs and PSKs loaded from secrets?
}

View file

@ -1,18 +0,0 @@
{
config,
outputs,
...
}: {
# a minimal, familiar setup that I can bootstrap atop
imports = with outputs.nixosModules; [
# may need to be tweaked based on the machine's paritioning scheme
outputs.diskoConfigurations.standard
desktop-usage
wifi
];
networking.hostName = config.home-manager.users.daniel.home.username;
# TODO: may not work for non-UEFI?
boot.loader.systemd-boot.enable = true;
}

55
nixos/base/default.nix Normal file
View file

@ -0,0 +1,55 @@
{
flake,
inputs,
outputs,
lib,
config,
modulesPath,
...
}: {
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
inputs.disko.nixosModules.disko
flake.diskoConfigurations.standard
]
++ (with outputs.nixosModules; [
desktop-usage
wifi
]);
nixpkgs = {
overlays = [
outputs.overlays.additions
outputs.overlays.modifications
outputs.overlays.unstable-packages
];
config = {
allowUnfree = true;
};
};
nix = {
registry = lib.mapAttrs (_: value: {flake = value;}) inputs;
nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;
settings = {
experimental-features = "nix-command flakes";
auto-optimise-store = true;
};
};
# not necessarily "base", but all my machines are UEFI so...
boot.loader.systemd-boot.enable = true;
networking = {
firewall = {
enable = true;
allowPing = true;
allowedTCPPorts = [22];
allowedUDPPorts = [];
};
};
system.stateVersion = "23.11";
}

File diff suppressed because it is too large Load diff

768
nixos/beefcake/default.nix Normal file
View file

@ -0,0 +1,768 @@
/*
if ur fans get loud:
# enable manual fan control
sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x01 0x00
# set fan speed to last byte as decimal
sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00
*/
{
# inputs,
outputs,
modulesPath,
config,
pkgs,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
outputs.nixosModules.intel
# inputs.nix-minecraft.nixosModules.minecraft-servers
];
nixpkgs.overlays = [
# inputs.nix-minecraft.overlay
];
boot.initrd.availableKernelModules = ["ehci_pci" "megaraid_sas" "usbhid" "uas" "sd_mod"];
boot.kernelModules = ["kvm-intel"];
fileSystems."/" = {
device = "/dev/disk/by-uuid/0747dcba-f590-42e6-89c8-6cb2f9114d64";
fsType = "ext4";
options = [
"usrquota"
];
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/7E3C-9018";
fsType = "vfat";
};
fileSystems."/storage" = {
device = "/dev/disk/by-uuid/ea8258d7-54d1-430e-93b3-e15d33231063";
fsType = "btrfs";
options = [
"compress=zstd:5"
"space_cache=v2"
];
};
services.nix-serve = {
enable = true;
secretKeyFile = "/var/cache-priv-key.pem";
};
services.api-lyte-dev = rec {
enable = true;
port = 5757;
stateDir = "/var/lib/api-lyte-dev";
configFile = config.sops.secrets."api.lyte.dev".path;
user = "api-lyte-dev";
group = user;
};
systemd.services.api-lyte-dev.environment.LOG_LEVEL = "debug";
sops = {
defaultSopsFile = ../../secrets/beefcake/secrets.yml;
age = {
sshKeyPaths = ["/etc/ssh/ssh_host_ed25519_key"];
keyFile = "/var/lib/sops-nix/key.txt";
generateKey = true;
};
secrets = {
# example-key = {
# # see these and other options' documentation here:
# # https://github.com/Mic92/sops-nix#set-secret-permissionowner-and-allow-services-to-access-it
# # set permissions:
# # mode = "0440";
# # owner = config.users.users.nobody.name;
# # group = config.users.users.nobody.group;
# # restart service when a secret changes or is newly initialized
# # restartUnits = [ "home-assistant.service" ];
# # symlink to certain directories
# path = "/var/lib/my-example-key/secrets.yaml";
# # for use as a user password
# # neededForUsers = true;
# };
# subdirectory
# "myservice/my_subdir/my_secret" = { };
"api.lyte.dev" = {
path = "${config.services.api-lyte-dev.stateDir}/secrets.json";
# TODO: would be cool to assert that it's correctly-formatted JSON? probably should be done in a pre-commit hook?
mode = "0440";
owner = config.services.api-lyte-dev.user;
group = config.services.api-lyte-dev.group;
};
"jland.env" = {
path = "/var/lib/jland/jland.env";
# TODO: would be cool to assert that it's correctly-formatted JSON? probably should be done in a pre-commit hook?
mode = "0440";
owner = config.users.users.jland.name;
group = config.users.groups.jland.name;
};
plausible-admin-password = {
# TODO: path = "${config.systemd.services.plausible.serviceConfig.WorkingDirectory}/plausible-admin-password.txt";
path = "/var/lib/plausible/plausible-admin-password";
mode = "0440";
owner = config.systemd.services.plausible.serviceConfig.User;
group = config.systemd.services.plausible.serviceConfig.Group;
};
plausible-secret-key-base = {
path = "/var/lib/plausible/plausible-secret-key-base";
mode = "0440";
owner = config.systemd.services.plausible.serviceConfig.User;
group = config.systemd.services.plausible.serviceConfig.Group;
};
nextcloud-admin-password = {
path = "/var/lib/nextcloud/admin-password";
mode = "0440";
# owner = config.services.nextcloud.serviceConfig.User;
# group = config.services.nextcloud.serviceConfig.Group;
};
};
};
# TODO: non-root processes and services that access secrets need to be part of
# the 'keys' group
# maybe this will fix plausible?
# systemd.services.some-service = {
# serviceConfig.SupplementaryGroups = [ config.users.groups.keys.name ];
# };
# or
# users.users.example-user.extraGroups = [ config.users.groups.keys.name ];
# TODO: directory attributes for /storage subdirectories?
# example: user daniel should be able to write to /storage/files.lyte.dev and
# caddy should be able to serve it
# TODO: declarative directory quotas? for storage/$USER and /home/$USER
# TODO: would be nice to get ALL the storage stuff declared in here
# should I be using btrfs subvolumes? can I capture file ownership, perimssions, and ACLs?
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
systemd.tmpfiles.rules = [
"d /var/spool/samba 1777 root root -"
];
networking.hostName = "beefcake";
users.extraGroups = {
"plausible" = {};
"nextcloud" = {};
"lytedev" = {};
};
users.groups.daniel.members = ["daniel"];
users.groups.nixadmin.members = ["daniel"];
users.users.daniel = {
packages = [pkgs.weechat];
extraGroups = [
"nixadmin" # write access to /etc/nixos/ files
"wheel" # sudo access
"caddy" # write access to /storage/files.lyte.dev
"users" # general users group
"jellyfin" # write access to /storage/jellyfin
"jland"
];
};
users.users.lytedev = {
# for running my services and applications and stuff
isNormalUser = true;
openssh.authorizedKeys.keys = config.users.users.daniel.openssh.authorizedKeys.keys;
group = "lytedev";
};
users.users.ben = {
isNormalUser = true;
packages = [pkgs.vim];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKUfLZ+IX85p9355Po2zP1H2tAxiE0rE6IYb8Sf+eF9T ben@benhany.com"
];
};
users.users.alan = {
isNormalUser = true;
packages = [pkgs.vim];
openssh.authorizedKeys.keys = [
""
];
};
users.users.restic = {
# used for other machines to backup to
isNormalUser = true;
openssh.authorizedKeys.keys =
[
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJbPqzKB09U+i4Kqu136yOjflLZ/J7pYsNulTAd4x903 root@chromebox.h.lyte.dev"
]
++ config.users.users.daniel.openssh.authorizedKeys.keys;
};
users.users.guest = {
# used for anonymous samba access
isSystemUser = true;
group = "users";
createHome = true;
};
users.users.plausible = {
# used for anonymous samba access
isSystemUser = true;
createHome = false;
group = "plausible";
};
users.groups.jland = {
gid = 982;
};
users.users.jland = {
uid = 986;
# used for running the jland minecraft server
isSystemUser = true;
createHome = false;
group = "jland";
};
users.users.nextcloud = {
# used for anonymous samba access
isSystemUser = true;
createHome = false;
group = "nextcloud";
};
environment.systemPackages = [pkgs.linuxquota];
# TODO: make the client declarative? right now I think it's manually git
# clone'd to /root
systemd.services.deno-netlify-ddns-client = {
serviceConfig.Type = "oneshot";
path = with pkgs; [curl bash];
environment = {
NETLIFY_DDNS_RC_FILE = "/root/deno-netlify-ddns-client/.env";
};
script = ''
bash /root/deno-netlify-ddns-client/netlify-ddns-client.sh
'';
};
systemd.timers.deno-netlify-ddns-client = {
wantedBy = ["timers.target"];
partOf = ["deno-netlify-ddns-client.service"];
timerConfig = {
OnBootSec = "10sec";
OnUnitActiveSec = "5min";
Unit = "deno-netlify-ddns-client.service";
};
};
services.caddy = {
enable = true;
email = "daniel@lyte.dev";
adapter = "caddyfile";
# acmeCA = "https://acme-staging-v02.api.letsencrypt.org/directory";
# TODO: there are some hardcoded ports here!
# https://github.com/NixOS/nixpkgs/blob/04af42f3b31dba0ef742d254456dc4c14eedac86/nixos/modules/services/misc/lidarr.nix#L72
# TODO: customize the files.lyte.dev template?
configFile = pkgs.writeText "Caddyfile" ''
video.lyte.dev {
reverse_proxy :8096
}
# lidarr.h.lyte.dev {
# reverse_proxy :8686
# }
# radarr.h.lyte.dev {
# reverse_proxy :7878
# }
# sonarr.h.lyte.dev {
# reverse_proxy :8989
# }
# bazarr.h.lyte.dev {
# reverse_proxy :${toString config.services.bazarr.listenPort}
# }
bw.lyte.dev {
reverse_proxy :${toString config.services.vaultwarden.config.ROCKET_PORT}
}
api.lyte.dev {
reverse_proxy :${toString config.services.api-lyte-dev.port}
}
a.lyte.dev {
reverse_proxy :${toString config.services.plausible.server.port}
}
nextcloud.lyte.dev {
reverse_proxy :${toString 9999}
}
git.lyte.dev {
reverse_proxy :${toString config.services.gitea.settings.server.HTTP_PORT}
}
files.lyte.dev {
file_server browse {
# browse template
# hide .*
root /storage/files.lyte.dev
}
}
nix.h.lyte.dev {
reverse_proxy :${toString config.services.nix-serve.port}
}
# proxy everything else to chromebox
:80 {
reverse_proxy 10.0.0.5:80
}
:443 {
reverse_proxy 10.0.0.5:443
}
'';
};
services.vaultwarden = {
enable = true;
config = {
DOMAIN = "https://bw.lyte.dev";
SIGNUPS_ALLOWED = "false";
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 8222;
};
};
# services.gitea-actions-runner.instances.main = {
# # TODO: simple git-based automation would be dope? maybe especially for
# # mirroring to github super easy?
# enable = false;
# };
services.gitea = {
enable = true;
appName = "git.lyte.dev";
stateDir = "/storage/gitea";
settings = {
server = {
ROOT_URL = "https://git.lyte.dev";
HTTP_ADDR = "127.0.0.1";
HTTP_PORT = 3088;
DOMAIN = "git.lyte.dev";
};
actions = {
ENABLED = true;
};
service = {
DISABLE_REGISTRATION = true;
};
session = {
COOKIE_SECURE = true;
};
log = {
# TODO: raise the log level
LEVEL = "Debug";
};
ui = {
THEMES = "catppuccin-mocha-sapphire,gitea,arc-green,auto,pitchblack";
DEFAULT_THEME = "catppuccin-mocha-sapphire";
};
};
lfs = {
enable = true;
};
dump = {
enable = true;
};
database = {
# TODO: move to postgres?
type = "sqlite3";
};
};
# TODO: ensure we're not doing the same dumb thing we were doing on the old host and eating storage
services.clickhouse.enable = true;
systemd.services.plausible.serviceConfig.User = "plausible";
systemd.services.plausible.serviceConfig.Group = "plausible";
services.plausible = {
# TODO: enable
enable = false;
database = {
clickhouse.setup = true;
postgres = {
setup = false;
dbname = "plausible";
};
};
server = {
baseUrl = "http://beefcake.hare-cod.ts.net:8899";
disableRegistration = true;
port = 8899;
secretKeybaseFile = config.sops.secrets.plausible-secret-key-base.path;
};
adminUser = {
activate = false;
email = "daniel@lyte.dev";
passwordFile = config.sops.secrets.plausible-admin-password.path;
};
};
services.postgresql = {
enable = true;
ensureDatabases = ["daniel" "plausible" "nextcloud"];
ensureUsers = [
{
name = "daniel";
ensureDBOwnership = true;
}
{
name = "plausible";
ensureDBOwnership = true;
}
{
name = "nextcloud";
ensureDBOwnership = true;
}
];
dataDir = "/storage/postgres";
enableTCPIP = true;
package = pkgs.postgresql_15;
authentication = pkgs.lib.mkOverride 10 ''
#type database DBuser auth-method
local all postgres peer map=superuser_map
local all daniel peer map=superuser_map
local sameuser all peer map=superuser_map
local plausible plausible peer map=superuser_map
local nextcloud nextcloud peer map=superuser_map
# lan ipv4
host all all 10.0.0.0/24 trust
# tailnet ipv4
host all all 100.64.0.0/10 trust
'';
identMap = ''
# ArbitraryMapName systemUser DBUser
superuser_map root postgres
superuser_map postgres postgres
superuser_map daniel postgres
# Let other names login as themselves
superuser_map /^(.*)$ \1
'';
};
services.postgresqlBackup = {
enable = true;
backupAll = true;
compression = "none"; # hoping for deduplication here?
location = "/storage/postgres-backups";
startAt = "*-*-* 03:00:00";
};
services.tailscale = {
useRoutingFeatures = "server";
};
services.jellyfin = {
enable = true;
openFirewall = false;
# uses port 8096 by default, configurable from admin UI
};
# NOTE: this server's xeon chips DO NOT seem to support quicksync or graphics in general
# but I can probably throw in a crappy GPU (or a big, cheap ebay GPU for ML
# stuff, too?) and get good transcoding performance
# jellyfin hardware encoding
# hardware.opengl = {
# enable = true;
# extraPackages = with pkgs; [
# intel-media-driver
# vaapiIntel
# vaapiVdpau
# libvdpau-va-gl
# intel-compute-runtime
# ];
# };
# nixpkgs.config.packageOverrides = pkgs: {
# vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; };
# };
services.openssh = {
listenAddresses = [
{
addr = "0.0.0.0";
port = 64022;
}
{
addr = "0.0.0.0";
port = 22;
}
];
};
# services.lidarr = {
# enable = true;
# dataDir = "/storage/lidarr";
# };
# services.radarr = {
# enable = true;
# dataDir = "/storage/radarr";
# };
# services.sonarr = {
# enable = true;
# dataDir = "/storage/sonarr";
# };
# services.bazarr = {
# enable = true;
# listenPort = 6767;
# };
services.samba-wsdd.enable = true;
services.samba = {
enable = true;
openFirewall = true;
securityType = "user";
package = pkgs.sambaFull;
extraConfig = ''
workgroup = WORKGROUP
server string = beefcake
netbios name = beefcake
security = user
#use sendfile = yes
#max protocol = smb2
# note: localhost is the ipv6 localhost ::1
hosts allow = 192.168.0.0/16 127.0.0.1 localhost
hosts deny = 0.0.0.0/0
guest account = nobody
map to guest = bad user
load printers = yes
printing = cups
printcap name = cups
'';
shares = {
libre = {
path = "/storage/libre";
browseable = "yes";
"read only" = "no";
"guest ok" = "yes";
"create mask" = "0666";
"directory mask" = "0777";
"force user" = "nobody";
"force group" = "users";
};
public = {
path = "/storage/public";
browseable = "yes";
"read only" = "no";
"guest ok" = "yes";
"create mask" = "0664";
"directory mask" = "0775";
"force user" = "nobody";
"force group" = "users";
};
family = {
path = "/storage/family";
browseable = "yes";
"read only" = "no";
"guest ok" = "no";
"create mask" = "0664";
"directory mask" = "0775";
"force user" = "nobody";
"force group" = "family";
};
daniel = {
path = "/storage/daniel";
browseable = "yes";
"read only" = "no";
"guest ok" = "no";
"create mask" = "0640";
"directory mask" = "0750";
"force user" = "daniel";
"force group" = "users";
};
printers = {
comment = "All Printers";
path = "/var/spool/samba";
public = "yes";
browseable = "yes";
# to allow user 'guest account' to print.
"guest ok" = "yes";
writable = "no";
printable = "yes";
"create mode" = 0700;
};
};
};
# paths:
# TODO: move previous backups over and put here
# clickhouse and plausible analytics once they're up and running?
services.restic.backups = let
defaults = {
passwordFile = "/root/restic-localbackup-password";
paths = [
"/storage/files.lyte.dev"
"/storage/daniel"
"/storage/gitea" # TODO: should maybe use configuration.nix's services.gitea.dump ?
"/storage/postgres-backups"
# https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault
# specifically, https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault#sqlite-database-files
"/var/lib/bitwarden_rs" # does this need any sqlite preprocessing?
# TODO: backup *arr configs?
];
initialize = true;
exclude = [];
timerConfig = {
OnCalendar = "04:45";
};
};
in {
local =
defaults
// {
repository = "/storage/backups/local";
};
rascal =
defaults
// {
extraOptions = [
"sftp.command='ssh beefcake@rascal -i /root/.ssh/id_ed25519 -s sftp'"
];
repository = "sftp://beefcake@rascal://storage/backups/beefcake";
};
# TODO: add ruby?
benland =
defaults
// {
extraOptions = [
"sftp.command='ssh daniel@n.benhaney.com -p 10022 -i /root/.ssh/id_ed25519 -s sftp'"
];
repository = "sftp://daniel@n.benhaney.com://storage/backups/beefcake";
};
};
# services.minecraft-servers.servers.jland = {
# enable = true;
# package = pkgs.fabricServers.fabric-1_19_2.override {loaderVersion = "0.14.9";};
# # Monumental Experience, modpack version 2.2.53, minecraft version 1.19.2
# # https://www.curseforge.com/minecraft/modpacks/monumental-experience/files/4826863
# # $ nix run nixpkgs#packwiz curseforge import Monumental+Experience-2.2.53.zip
# };
virtualisation.oci-containers.backend = "podman";
virtualisation.oci-containers.containers = {
minecraft-jland = {
# sending commands: https://docker-minecraft-server.readthedocs.io/en/latest/commands/
image = "docker.io/itzg/minecraft-server";
user = "${toString config.users.users.jland.uid}:${toString config.users.groups.jland.gid}";
extraOptions = [
"--tty"
"--interactive"
];
environment = {
EULA = "true";
UID = toString config.users.users.jland.uid;
GID = toString config.users.groups.jland.gid;
STOP_SERVER_ANNOUNCE_DELAY = "20";
TZ = "America/Chicago";
VERSION = "1.20.1";
MEMORY = "8G";
MAX_MEMORY = "16G";
TYPE = "FORGE";
FORGE_VERSION = "47.1.3";
ALLOW_FLIGHT = "true";
ENABLE_QUERY = "true";
MODPACK = "/data/origination-files/Server-Files-0.2.14.zip";
# TYPE = "AUTO_CURSEFORGE";
# CF_SLUG = "monumental-experience";
# CF_FILE_ID = "4826863"; # 2.2.53
# due to
# Nov 02 13:45:22 beefcake minecraft-jland[2738672]: me.itzg.helpers.errors.GenericException: The modpack authors have indicated this file is not allowed for project distribution. Please download the client zip file from https://www.curseforge.com/minecraft/modpacks/monumental-experience and pass via CF_MODPACK_ZIP environment variable or place indownloads repo directory.
# we must upload manually
# CF_MODPACK_ZIP = "/data/origination-files/Monumental+Experience-2.2.53.zip";
# ENABLE_AUTOPAUSE = "true"; # TODO: must increate or disable max-tick-time
# May also have mod/loader incompatibilities?
# https://docker-minecraft-server.readthedocs.io/en/latest/misc/autopause-autostop/autopause/
};
environmentFiles = [
config.sops.secrets."jland.env".path
];
ports = ["26965:25565"];
volumes = [
"/storage/jland/data:/data"
"/storage/jland/worlds:/worlds"
];
};
};
networking.firewall.allowedTCPPorts = [
80 # http (caddy)
443 # https (caddy)
# 5357 # ???
22 # ssh
6667 # soju irc bouncer
64022 # ssh (for ben?)
];
networking.firewall.allowedUDPPorts = [
# 53 # DNS
# 3702 # ???
64020 # mosh (for ben?)
];
networking.firewall.allowedUDPPortRanges = [
{
# mosh
from = 60000;
to = 60010;
}
];
networking.firewall = {
enable = true;
allowPing = true;
};
services.soju = {
enable = true;
listen = ["irc+insecure://:6667"];
};
system.stateVersion = "22.05";
}

View file

@ -1,137 +0,0 @@
{
pkgs,
lib,
config,
...
}: {
imports = [
{
system.stateVersion = "24.05";
home-manager.users.daniel.home.stateVersion = "24.05";
networking.hostName = "bigtower";
}
];
hardware.graphics.extraPackages = [
# pkgs.rocmPackages.clr.icd
pkgs.amdvlk
# encoding/decoding acceleration
pkgs.libvdpau-va-gl
pkgs.vaapiVdpau
];
boot = {
# kernelPackages = pkgs.linuxPackages_zen;
loader.efi.canTouchEfiVariables = true;
loader.systemd-boot.enable = true;
initrd.availableKernelModules = ["xhci_pci" "nvme" "ahci" "usbhid"];
kernelModules = ["kvm-amd"];
supportedFilesystems = ["ntfs"];
};
hardware.bluetooth = {
enable = true;
# package = pkgs.bluez;
settings = {
General = {
AutoConnect = true;
MultiProfile = "multiple";
};
};
};
/*
networking = {
firewall = let
terraria = 7777;
stardew-valley = 24642;
web-dev-lan = 18888;
ports = [
terraria
stardew-valley
web-dev-lan
];
in {
allowedTCPPorts = ports;
allowedUDPPorts = ports;
};
};
*/
environment.systemPackages = with pkgs; [
radeontop
# godot_4
prismlauncher
];
home-manager.users.daniel = {
/*
slippi-launcher = {
enable = true;
# isoPath = "${config.home-manager.users.daniel.home.homeDirectory}/../games/roms/dolphin/melee.iso";
launchMeleeOnPlay = false;
};
*/
# TODO: monitor config module?
/*
wayland.windowManager.hyprland = {
settings = {
env = [
"EWW_BAR_MON,1"
];
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
monitor = [
# "DP-2,3840x2160@60,-2160x0,1,transform,3"
"DP-3,3840x2160@120,${toString (builtins.ceil (2160 / 1.5))}x0,1"
## HDR breaks screenshare? "DP-3,3840x2160@120,${toString (builtins.ceil (2160 / 1.5))}x0,1,bitdepth,10"
## "desc:LG Display 0x0521,3840x2160@120,0x0,1"
## "desc:Dell Inc. DELL U2720Q D3TM623,3840x2160@60,3840x0,1.5,transform,1"
"DP-2,3840x2160@60,0x0,1.5,transform,1"
];
input = {
force_no_accel = true;
sensitivity = 1; # -1.0 - 1.0, 0 means no modification.
};
};
};
wayland.windowManager.sway = {
config = {
output = {
"GIGA-BYTE TECHNOLOGY CO., LTD. AORUS FO48U 23070B000307" = {
mode = "3840x2160@120Hz";
position = "${toString (builtins.ceil (2160 / 1.5))},0";
};
"Dell Inc. DELL U2720Q D3TM623" = {
# desktop left vertical monitor
mode = "3840x2160@60Hz";
transform = "90";
scale = "1.5";
position = "0,0";
};
};
workspaceOutputAssign =
(
map
(ws: {
output = "GIGA-BYTE TECHNOLOGY CO., LTD. AORUS FO48U 23070B000307";
workspace = toString ws;
})
(lib.range 1 7)
)
++ (
map
(ws: {
output = "Dell Inc. DELL U2720Q D3TM623";
workspace = toString ws;
})
(lib.range 8 9)
);
};
};
*/
};
}

View file

@ -1,176 +0,0 @@
{
pkgs,
lib,
config,
...
}: {
imports = [
{
system.stateVersion = "24.11";
home-manager.users.daniel.home.stateVersion = "24.05";
networking.hostName = "dragon";
}
{
# sops secrets config
sops = {
defaultSopsFile = ../secrets/dragon/secrets.yml;
age = {
sshKeyPaths = ["/etc/ssh/ssh_host_ed25519_key"];
keyFile = "/var/lib/sops-nix/key.txt";
generateKey = true;
};
};
}
{
sops.secrets = {
ddns-pass = {mode = "0400";};
};
services.deno-netlify-ddns-client = {
passwordFile = config.sops.secrets.ddns-pass.path;
};
}
];
hardware.amdgpu = {
amdvlk = {
enable = true;
support32Bit = {
enable = true;
};
};
};
hardware.graphics.extraPackages = [
# pkgs.rocmPackages.clr.icd
pkgs.amdvlk
# encoding/decoding acceleration
pkgs.libvdpau-va-gl
pkgs.vaapiVdpau
];
boot = {
kernelPackages = pkgs.linuxPackages_latest;
loader.efi.canTouchEfiVariables = true;
loader.systemd-boot.enable = true;
initrd.availableKernelModules = ["xhci_pci" "nvme" "ahci" "usbhid"];
kernelModules = ["kvm-amd"];
supportedFilesystems = ["ntfs"];
};
hardware.bluetooth = {
enable = true;
# package = pkgs.bluez;
settings = {
General = {
AutoConnect = true;
MultiProfile = "multiple";
};
};
};
powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
# dragon firewall
# TODO: maybe should go in the gaming module?
networking = {
firewall = let
terraria = 7777;
stardew-valley = 24642;
web-dev-lan = 18888;
ports = [
terraria
stardew-valley
web-dev-lan
];
in {
allowedTCPPorts = ports;
allowedUDPPorts = ports;
};
};
environment.systemPackages = with pkgs; [
radeontop
godot_4
prismlauncher
];
home-manager.users.daniel = {
slippi-launcher = {
enable = true;
isoPath = "${config.home-manager.users.daniel.home.homeDirectory}/../games/roms/dolphin/melee.iso";
launchMeleeOnPlay = false;
};
# TODO: monitor config module?
wayland.windowManager.hyprland = {
settings = {
exec-once = [
"eww open bar1"
];
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
monitor = [
# "DP-2,3840x2160@60,-2160x0,1,transform,3"
"DP-3,3840x2160@120,${toString (builtins.ceil (2160 / 1.5))}x0,1"
# TODO: HDR breaks screenshare?
/*
"DP-3,3840x2160@120,${toString (builtins.ceil (2160 / 1.5))}x0,1,bitdepth,10"
"desc:LG Display 0x0521,3840x2160@120,0x0,1"
"desc:Dell Inc. DELL U2720Q D3TM623,3840x2160@60,3840x0,1.5,transform,1"
*/
"DP-1,3840x2160@60,0x0,1.5,transform,1"
];
input = {
force_no_accel = true;
sensitivity = 1; # -1.0 - 1.0, 0 means no modification.
};
workspace = [
"1, monitor:DP-3, default:true"
"2, monitor:DP-3, default:false"
"3, monitor:DP-3, default:false"
"4, monitor:DP-3, default:false"
"5, monitor:DP-3, default:false"
"6, monitor:DP-3, default:false"
"7, monitor:DP-3, default:false"
"8, monitor:DP-1, default:true"
"9, monitor:DP-1, default:false"
];
};
};
wayland.windowManager.sway = {
config = {
output = {
"GIGA-BYTE TECHNOLOGY CO., LTD. AORUS FO48U 23070B000307" = {
mode = "3840x2160@120Hz";
position = "${toString (builtins.ceil (2160 / 1.5))},0";
};
"Dell Inc. DELL U2720Q D3TM623" = {
# desktop left vertical monitor
mode = "3840x2160@60Hz";
transform = "270";
scale = "1.5";
position = "0,0";
};
};
workspaceOutputAssign =
(
map
(ws: {
output = "GIGA-BYTE TECHNOLOGY CO., LTD. AORUS FO48U 23070B000307";
workspace = toString ws;
})
(lib.range 1 7)
)
++ (
map
(ws: {
output = "Dell Inc. DELL U2720Q D3TM623";
workspace = toString ws;
})
(lib.range 8 9)
);
};
};
};
}

120
nixos/dragon/default.nix Normal file
View file

@ -0,0 +1,120 @@
{
flake,
inputs,
outputs,
lib,
config,
pkgs,
modulesPath,
...
}: {
networking.hostName = "dragon";
boot.supportedFilesystems = ["ntfs"];
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
inputs.disko.nixosModules.disko
flake.diskoConfigurations.standard
inputs.hardware.nixosModules.common-cpu-amd
inputs.hardware.nixosModules.common-pc-ssd
outputs.nixosModules.pipewire-low-latency
]
++ (with outputs.nixosModules; [
melee
desktop-usage
podman
postgres
wifi
hyprland
ewwbar
])
++ [
# Or modules from other flakes (such as nixos-hardware):
# inputs.hardware.nixosModules.common-cpu-amd
# inputs.hardware.nixosModules.common-ssd
# You can also split up your configuration and import pieces of it here:
# ./users.nix
];
# TODO: https://nixos.wiki/wiki/Remote_LUKS_Unlocking
nixpkgs = {
# You can add overlays here
overlays = [
# Add overlays your own flake exports (from overlays and pkgs dir):
outputs.overlays.additions
outputs.overlays.modifications
outputs.overlays.unstable-packages
# You can also add overlays exported from other flakes:
# neovim-nightly-overlay.overlays.default
# Or define it inline, for example:
# (final: prev: {
# hi = final.hello.overrideAttrs (oldAttrs: {
# patches = [ ./change-hello-to-hi.patch ];
# });
# })
];
# Configure your nixpkgs instance
config = {
# Disable if you don't want unfree packages
allowUnfree = true;
};
};
nix = {
# This will add each flake input as a registry
# To make nix3 commands consistent with your flake
registry = lib.mapAttrs (_: value: {flake = value;}) inputs;
# This will additionally add your inputs to the system's legacy channels
# Making legacy nix commands consistent as well, awesome!
nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;
settings = {
# Enable flakes and new 'nix' command
experimental-features = "nix-command flakes";
# Deduplicate and optimize nix store
auto-optimise-store = true;
};
};
# hardware
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.systemd-boot.enable = true;
boot.initrd.availableKernelModules = ["xhci_pci" "nvme" "ahci"];
boot.kernelModules = ["kvm-amd"];
hardware.bluetooth.enable = true;
powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
services.printing.enable = true;
environment = {
systemPackages = with pkgs; [
radeontop
];
};
networking = {
firewall = {
enable = true;
allowPing = true;
allowedTCPPorts = [22 7777];
allowedUDPPorts = [];
};
};
services.udev.packages = [
pkgs.platformio
pkgs.openocd
];
programs.adb.enable = true;
users.users.daniel.extraGroups = ["adbusers"];
# https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion
system.stateVersion = "23.11";
}

View file

@ -1,14 +0,0 @@
{
"x86_64-linux": {
"headless": {
"stable": {
"name": "factorio_headless_x64-2.0.15.tar.xz",
"needsAuth": false,
"sha256": "cLRBy4B4EaYFhsARBySMHY164EO9HyNnX8kk+6qlONg=",
"tarDirectory": "x64",
"url": "https://factorio.com/get-download/2.0.15/headless/linux64",
"version": "2.0.15"
}
}
}
}

View file

@ -1,500 +0,0 @@
{pkgs, ...}:
/*
## source: https://community.frame.work/t/speakers-sound-quality/1078/82
let
pipewire-speakers-profile-json = ''{
"output": {
"blocklist": [],
"equalizer": {
"balance": 0.0,
"bypass": false,
"input-gain": 0.0,
"left": {
"band0": {
"frequency": 100.0,
"gain": 0.0,
"mode": "RLC (BT)",
"mute": false,
"q": 1.0,
"slope": "x4",
"solo": false,
"type": "Hi-pass"
},
"band1": {
"frequency": 150.0,
"gain": 4.02,
"mode": "RLC (BT)",
"mute": false,
"q": 3.0,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band2": {
"frequency": 600.0,
"gain": -5.07,
"mode": "RLC (BT)",
"mute": false,
"q": 4.000000000000008,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band3": {
"frequency": 1200.0,
"gain": -3.49,
"mode": "RLC (BT)",
"mute": false,
"q": 4.17,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band4": {
"frequency": 2000.0,
"gain": 1.43,
"mode": "RLC (BT)",
"mute": false,
"q": 4.0,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band5": {
"frequency": 5300.0,
"gain": 3.84,
"mode": "RLC (BT)",
"mute": false,
"q": 2.64,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band6": {
"frequency": 6000.0,
"gain": 4.02,
"mode": "RLC (BT)",
"mute": false,
"q": 4.36,
"slope": "x1",
"solo": false,
"type": "Hi-shelf"
},
"band7": {
"frequency": 7500.0,
"gain": -2.09,
"mode": "RLC (BT)",
"mute": false,
"q": 3.0,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band8": {
"frequency": 8000.0,
"gain": 2.01,
"mode": "RLC (BT)",
"mute": false,
"q": 4.36,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band9": {
"frequency": 900.0,
"gain": -4.12,
"mode": "RLC (BT)",
"mute": false,
"q": 5.909999999999967,
"slope": "x1",
"solo": false,
"type": "Bell"
}
},
"mode": "IIR",
"num-bands": 10,
"output-gain": -1.5,
"pitch-left": 0.0,
"pitch-right": 0.0,
"right": {
"band0": {
"frequency": 100.0,
"gain": 0.0,
"mode": "RLC (BT)",
"mute": false,
"q": 1.0,
"slope": "x4",
"solo": false,
"type": "Hi-pass"
},
"band1": {
"frequency": 150.0,
"gain": 4.02,
"mode": "RLC (BT)",
"mute": false,
"q": 3.0,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band2": {
"frequency": 600.0,
"gain": -5.07,
"mode": "RLC (BT)",
"mute": false,
"q": 4.000000000000008,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band3": {
"frequency": 1200.0,
"gain": -3.49,
"mode": "RLC (BT)",
"mute": false,
"q": 4.17,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band4": {
"frequency": 2000.0,
"gain": 1.43,
"mode": "RLC (BT)",
"mute": false,
"q": 4.0,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band5": {
"frequency": 5300.0,
"gain": 3.84,
"mode": "RLC (BT)",
"mute": false,
"q": 2.64,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band6": {
"frequency": 6000.0,
"gain": 4.02,
"mode": "RLC (BT)",
"mute": false,
"q": 4.36,
"slope": "x1",
"solo": false,
"type": "Hi-shelf"
},
"band7": {
"frequency": 7500.0,
"gain": -2.09,
"mode": "RLC (BT)",
"mute": false,
"q": 3.0,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band8": {
"frequency": 8000.0,
"gain": 2.01,
"mode": "RLC (BT)",
"mute": false,
"q": 4.36,
"slope": "x1",
"solo": false,
"type": "Bell"
},
"band9": {
"frequency": 900.0,
"gain": -4.12,
"mode": "RLC (BT)",
"mute": false,
"q": 5.909999999999967,
"slope": "x1",
"solo": false,
"type": "Bell"
}
},
"split-channels": false
},
"loudness": {
"bypass": false,
"clipping": false,
"clipping-range": 6.0,
"fft": "4096",
"input-gain": 0.0,
"output-gain": 0.0,
"std": "ISO226-2003",
"volume": 6.999999999999991
},
"plugins_order": [
"loudness",
"equalizer"
]
}
}'';
in
*/
{
imports = [
{
system.stateVersion = "24.05";
home-manager.users.daniel.home.stateVersion = "24.05";
networking.hostName = "foxtrot";
}
{
swapDevices = [
# TODO: move this to disko?
# NOTE(oninstall):
/*
sudo btrfs subvolume create /swap
sudo btrfs filesystem mkswapfile --size 32g --uuid clear /swap/swapfile
sudo swapon /swap/swapfile
*/
{device = "/swap/swapfile";}
];
# findmnt -no UUID -T /swap/swapfile
boot.resumeDevice = "/dev/disk/by-uuid/81c3354a-f629-4b6b-a249-7705aeb9f0d5";
# systemd.sleep.extraConfig = "HibernateDelaySec=180m";
services.fwupd.enable = true;
services.fwupd.extraRemotes = ["lvfs-testing"];
}
];
environment = {
systemPackages = with pkgs; [
easyeffects
godot_4
fractal
prismlauncher
upower
acpi
prismlauncher
radeontop
sops
xh
];
};
home-manager.users.daniel = {
home = {
pointerCursor = {
size = 40;
};
};
services.easyeffects = {
enable = true;
preset = "philonmetal";
# clone from https://github.com/ceiphr/ee-framework-presets
# then `cp *.json ~/.config/easyeffects/output`
# TODO: nixify this
};
services.hypridle = let
secondsPerMinute = 60;
lockSeconds = 10 * secondsPerMinute;
in {
settings = {
listener = [
{
timeout = lockSeconds + 55;
on-timeout = ''systemctl suspend'';
}
];
};
};
wayland.windowManager.hyprland = {
settings = {
exec-once = [
"eww open bar0"
];
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
monitor = [
"eDP-1,2880x1920@120Hz,0x0,1.66667"
];
};
};
wayland.windowManager.sway = {
config = {
output = {
"BOE NE135A1M-NY1 Unknown" = {
mode = "2880x1920@120Hz";
position = "1092,2160";
scale = toString (5 / 3);
};
"Dell Inc. DELL U2720Q CWTM623" = {
mode = "3840x2160@60Hz";
position = "0,0";
scale = toString 1.25;
};
/*
"BOE 0x0BCA Unknown" = {
mode = "2256x1504@60Hz";
position = "0,0";
scale = toString scale;
};
"Dell Inc. DELL U2720Q D3TM623" = {
# desktop left vertical monitor
mode = "1920x1080@60Hz";
# transform = "90";
# scale = "1.5";
position = "${toString (builtins.floor (2256 / scale))},0";
};
*/
};
};
};
};
hardware.graphics.extraPackages = [
# pkgs.rocmPackages.clr.icd
pkgs.amdvlk
# encoding/decoding acceleration
pkgs.libvdpau-va-gl
pkgs.vaapiVdpau
];
hardware.amdgpu = {
amdvlk = {
enable = true;
support32Bit = {
enable = true;
};
};
};
networking.networkmanager.wifi.powersave = false;
hardware.framework.amd-7040.preventWakeOnAC = true;
boot = {
# kernelPackages = pkgs.linuxPackages_latest;
# https://github.com/void-linux/void-packages/issues/50417#issuecomment-2131802836 fix framework 13 not shutting down
/*
kernelPatches = [
{
name = "framework13shutdownfix";
patch = builtins.fetchurl {
url = "https://github.com/void-linux/void-packages/files/15445612/0001-Add-hopefully-a-solution-for-shutdown-regression.PATCH";
sha256 = "sha256:10zcnzy5hkam2cnxx441b978gzhvnqlcc49k7bpz9dc28xyjik50";
};
}
];
*/
loader = {
efi.canTouchEfiVariables = true;
systemd-boot.enable = true;
};
# NOTE(oninstall):
/*
sudo filefrag -v /swap/swapfile | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'
the above won't work for btrfs, instead you need btrfs inspect-internal map-swapfile -r /swap/swapfile
https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#Hibernation_into_swap_file
many of these come from https://wiki.archlinux.org/title/Framework_Laptop_13#Suspend
*/
kernelParams = [
"rtc_cmos.use_acpi_alarm=1"
"amdgpu.sg_display=0"
"acpi_osi=\"!Windows 2020\""
# "nvme.noacpi=1" # maybe causing crashes upon waking?
# NOTE(oninstall):
"resume_offset=3421665"
];
initrd.availableKernelModules = ["xhci_pci" "nvme" "thunderbolt"];
kernelModules = ["kvm-amd"];
};
hardware.bluetooth = {
enable = true;
# TODO: when resuming from hibernation, it would be nice if this would
# simply resume the power state at the time of hibernation
powerOnBoot = false;
package = pkgs.bluez.overrideAttrs (finalAttrs: previousAttrs: rec {
version = "5.78";
src = pkgs.fetchurl {
url = "mirror://kernel/linux/bluetooth/bluez-${version}.tar.xz";
sha256 = "sha256-gw/tGRXF03W43g9eb0X83qDcxf9f+z0x227Q8A1zxeM=";
};
patches = [];
buildInputs =
previousAttrs.buildInputs
++ [
pkgs.python3Packages.pygments
];
});
};
powerManagement.cpuFreqGovernor = "ondemand";
/*
powerManagement.resumeCommands = ''
modprobe -rv mt7921e
modprobe -v mt7921e
'';
*/
services.power-profiles-daemon = {
enable = true;
};
services.fprintd = {
enable = false;
package = pkgs.fprintd.overrideAttrs {
# Source: https://github.com/NixOS/nixpkgs/commit/87ca2dc071581aea0e691c730d6844f1beb07c9f
mesonCheckFlags = [
# PAM related checks are timing out
"--no-suite"
"fprintd:TestPamFprintd"
];
};
};
/*
services.tlp = {
enable = true;
settings = {
CPU_ENERGY_PERF_POLICY_ON_BAT = "power";
CPU_SCALING_GOVERNOR_ON_BAT = "ondemand";
CPU_MIN_PERF_ON_BAT = 0;
CPU_MAX_PERF_ON_BAT = 80;
CPU_SCALING_GOVERNOR_ON_AC = "performance";
CPU_ENERGY_PERF_POLICY_ON_AC = "performance";
CPU_MIN_PERF_ON_AC = 0;
CPU_MAX_PERF_ON_AC = 100;
};
};
*/
networking.firewall.allowedTCPPorts = let
stardewValley = 24642;
factorio = 34197;
in [
8000 # dev stuff
factorio
stardewValley
7777
];
networking.firewall.allowedUDPPorts = let
stardewValley = 24642;
factorio = 34197;
in [
8000 # dev stuff
factorio
stardewValley
7777
];
}

190
nixos/foxtrot/default.nix Normal file
View file

@ -0,0 +1,190 @@
{
flake,
inputs,
outputs,
lib,
# config,
pkgs,
...
}: {
networking.hostName = "foxtrot";
imports =
[
inputs.disko.nixosModules.disko
flake.diskoConfigurations.standard
]
++ (with outputs.nixosModules; [
desktop-usage
podman
postgres
wifi
# hyprland
])
++ [
inputs.hardware.nixosModules.framework-13-7040-amd
];
# use updated ppd for framework 13:
# source: https://community.frame.work/t/tracking-ppd-v-tlp-for-amd-ryzen-7040/39423/137?u=lytedev
nixpkgs.overlays = [
(
final: prev: {
power-profiles-daemon = prev.power-profiles-daemon.overrideAttrs (
old: {
version = "0.13-1";
patches =
(old.patches or [])
++ [
(prev.fetchpatch {
url = "https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/merge_requests/127.patch";
sha256 = "sha256-jnq5yJvWQHOlZ78SE/4/HqiQfF25YHQH/T4wwDVRHR0=";
})
(prev.fetchpatch {
url = "https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/merge_requests/128.patch";
sha256 = "sha256-YD9wn9IQlCp02r4lmwRnx9Eur2VVP1JfC/Bm8hlzF3Q=";
})
(prev.fetchpatch {
url = "https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/merge_requests/129.patch";
sha256 = "sha256-9T+I3BAUW3u4LldF85ctE0/PLu9u+KBN4maoL653WJU=";
})
];
# explicitly fetching the source to make sure we're patching over 0.13 (this isn't strictly needed):
src = prev.fetchFromGitLab {
domain = "gitlab.freedesktop.org";
owner = "hadess";
repo = "power-profiles-daemon";
rev = "0.13";
sha256 = "sha256-ErHy+shxZQ/aCryGhovmJ6KmAMt9OZeQGDbHIkC0vUE=";
};
}
);
}
)
];
swapDevices = [
# TODO: move this to disko?
# NOTE(oninstall):
# sudo btrfs subvolume create /swap
# sudo btrfs filesystem mkswapfile --size 32g --uuid clear /swap/swapfile
# sudo swapon /swap/swapfile
{device = "/swap/swapfile";}
];
# findmnt -no UUID -T /swap/swapfile
boot.resumeDevice = "/dev/disk/by-uuid/81c3354a-f629-4b6b-a249-7705aeb9f0d5";
services.logind = {
lidSwitch = "suspend-then-hibernate";
extraConfig = ''
HandlePowerKey=suspend-then-hibernate
IdleAction=suspend-then-hibernate
IdleActionSec=10m
'';
};
systemd.sleep.extraConfig = "HibernateDelaySec=90m";
services.fwupd.enable = true;
services.fwupd.extraRemotes = ["lvfs-testing"];
hardware.opengl.extraPackages = [
# pkgs.rocmPackages.clr.icd
pkgs.amdvlk
# encoding/decoding acceleration
pkgs.libvdpau-va-gl
pkgs.vaapiVdpau
];
hardware.wirelessRegulatoryDatabase = true;
hardware.framework.amd-7040.preventWakeOnAC = true;
boot = {
kernelPackages = pkgs.linuxPackages_latest; # seeing if using the stable kernel makes wow work
loader = {
efi.canTouchEfiVariables = true;
systemd-boot.enable = true;
};
# NOTE(oninstall):
# sudo filefrag -v /swap/swapfile | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'
# the above won't work for btrfs, instead you need
# btrfs inspect-internal map-swapfile -r /swap/swapfile
# https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#Hibernation_into_swap_file
# many of these come from https://wiki.archlinux.org/title/Framework_Laptop_13#Suspend
kernelParams = [
"amdgpu.sg_display=0"
"acpi_osi=\"!Windows 2020\""
# NOTE(oninstall):
"resume_offset=3421665"
# "nvme.noacpi=1" # maybe causing crashes upon waking?
"rtc_cmos.use_acpi_alarm=1"
];
initrd.availableKernelModules = ["xhci_pci" "nvme" "thunderbolt"];
kernelModules = ["kvm-amd"];
extraModprobeConfig = ''
options cfg80211 ieee80211_regdom="US"
'';
};
hardware.bluetooth = {
enable = true;
powerOnBoot = false;
};
powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
services.printing.enable = true;
services.printing.browsing = true;
services.printing.browsedConf = ''
BrowseDNSSDSubTypes _cups,_print
BrowseLocalProtocols all
BrowseRemoteProtocols all
CreateIPPPrinterQueues All
BrowseProtocols all
'';
services.printing.drivers = [pkgs.gutenprint];
services.avahi = {
enable = true;
reflector = true;
openFirewall = true;
nssmdns = true;
};
services.fprintd = {
enable = false;
# tod.enable = true;
# tod.driver = pkgs.libfprint-2-tod1-goodix;
};
services.power-profiles-daemon = {
enable = true;
};
services.tlp = {
enable = false;
settings = {
CPU_ENERGY_PERF_POLICY_ON_BAT = "power";
CPU_SCALING_GOVERNOR_ON_BAT = "ondemand";
CPU_MIN_PERF_ON_BAT = 0;
CPU_MAX_PERF_ON_BAT = 60;
CPU_SCALING_GOVERNOR_ON_AC = "performance";
CPU_ENERGY_PERF_POLICY_ON_AC = "performance";
CPU_MIN_PERF_ON_AC = 0;
CPU_MAX_PERF_ON_AC = 100;
};
};
powerManagement.powertop.enable = true;
networking = {
firewall = {
enable = true;
allowPing = true;
allowedTCPPorts = [22];
allowedUDPPorts = [];
};
};
system.stateVersion = "24.05";
}

View file

@ -1,44 +0,0 @@
{
pkgs,
config,
lib,
...
}: {
networking.hostName = "htpc";
networking.networkmanager.enable = true;
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/sda";
boot.loader.grub.useOSProber = true;
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod"];
boot.initrd.kernelModules = ["8821au" "8812au"];
boot.kernelModules = ["kvm-intel"];
boot.extraModulePackages = [
# pkgs.rtl8811au
config.boot.kernelPackages.rtl8812au
config.boot.kernelPackages.rtl8821au
];
fileSystems."/" = {
device = "/dev/disk/by-uuid/86d8ded0-1c6f-4a79-901c-2d59c11b5ca8";
fsType = "ext4";
};
swapDevices = [];
hardware.bluetooth = {
enable = true;
# package = pkgs.bluez;
settings = {
General = {
AutoConnect = true;
MultiProfile = "multiple";
};
};
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,144 +0,0 @@
{
pkgs,
lib,
hardware,
outputs,
modulesPath,
...
}: {
nixpkgs.hostPlatform = "aarch64-linux";
networking.hostName = "htpifour";
imports = with outputs.nixosModules; [
(modulesPath + "/installer/scan/not-detected.nix")
hardware.nixosModules.raspberry-pi-4
outputs.diskoConfigurations.unencrypted
desktop-usage
# gnome
kde-plasma
wifi
flanfam
flanfamkiosk
];
hardware = {
raspberry-pi."4".apply-overlays-dtmerge.enable = true;
deviceTree = {
enable = true;
filter = "*rpi-4-*.dtb";
};
};
console.enable = false;
home-manager.users.daniel = {
imports = with outputs.homeManagerModules; [linux-desktop wallpaper-manager];
};
environment.systemPackages = with pkgs;
#with pkgs;
[
# libcec
libraspberrypi
raspberrypi-eeprom
];
programs.steam.enable = true;
programs.steam.remotePlay.openFirewall = true;
services.xserver = {
displayManager = {
# lightdm.enable = true;
autoLogin.enable = true;
autoLogin.user = "daniel";
};
# videoDrivers = ["fbdev"];
};
hardware.raspberry-pi."4".fkms-3d.enable = true;
hardware.raspberry-pi."4".audio.enable = true;
nixpkgs.overlays = [
/*
nixos-22.05
(self: super: { libcec = super.libcec.override { inherit (self) libraspberrypi; }; })
nixos-22.11
(self: super: {libcec = super.libcec.override {withLibraspberrypi = true;};})
*/
];
# Workaround for GNOME autologin: https://github.com/NixOS/nixpkgs/issues/103746#issuecomment-945091229
/*
systemd.services."getty@tty1".enable = false;
systemd.services."autovt@tty1".enable = false;
*/
# hardware
systemd.targets.sleep.enable = false;
systemd.targets.suspend.enable = false;
systemd.targets.hibernate.enable = false;
systemd.targets.hybrid-sleep.enable = false;
powerManagement.enable = false;
boot = {
kernelPackages = pkgs.linuxKernel.packages.linux_rpi4;
initrd.availableKernelModules = ["xhci_pci" "usbhid" "usb_storage"];
loader = {
grub.enable = false;
generic-extlinux-compatible.enable = true;
};
};
networking = {
networkmanager.enable = true;
# useDHCP = true;
firewall = {
enable = true;
allowPing = true;
allowedTCPPorts = [
22 # ssh
];
allowedUDPPorts = [];
};
};
/*
services.udev.extraRules = ''
# allow access to raspi cec device for video group (and optionally register it as a systemd device, used below)
SUBSYSTEM=="vchiq", GROUP="video", MODE="0660", TAG+="systemd", ENV{SYSTEMD_ALIAS}="/dev/vchiq"
'';
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
optional: attach a persisted cec-client to `/run/cec.fifo`, to avoid the CEC ~1s startup delay per command
scan for devices: `echo 'scan' &gt; /run/cec.fifo ; journalctl -u cec-client.service`
set pi as active source: `echo 'as' &gt; /run/cec.fifo`
systemd.sockets."cec-client" = {
after = ["dev-vchiq.device"];
bindsTo = ["dev-vchiq.device"];
wantedBy = ["sockets.target"];
socketConfig = {
ListenFIFO = "/run/cec.fifo";
SocketGroup = "video";
SocketMode = "0660";
};
};
systemd.services."cec-client" = {
after = ["dev-vchiq.device"];
bindsTo = ["dev-vchiq.device"];
wantedBy = ["multi-user.target"];
serviceConfig = {
ExecStart = ''${pkgs.libcec}/bin/cec-client -d 1'';
ExecStop = ''/bin/sh -c "echo q &gt; /run/cec.fifo"'';
StandardInput = "socket";
StandardOutput = "journal";
Restart = "no";
};
};
*/
hardware.graphics.driSupport32Bit = lib.mkForce false;
system.stateVersion = "24.05";
}

View file

@ -0,0 +1,28 @@
{
flake,
inputs,
outputs,
# lib,
# config,
# pkgs,
...
}: {
networking.hostName = "musicbox";
imports =
[
inputs.disko.nixosModules.disko
flake.diskoConfigurations.unencrypted
]
++ (with outputs.nixosModules; [
desktop-usage
wifi
]);
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
hardware.bluetooth.enable = true;
networking.networkmanager.enable = true;
system.stateVersion = "23.05";
}

View file

@ -1,78 +0,0 @@
{
config,
modulesPath,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "ehci_pci" "usbhid" "uas" "sd_mod"];
boot.kernelModules = ["kvm-amd"];
fileSystems."/" = {
device = "/dev/disk/by-uuid/2e2ad73a-6264-4a7b-8439-9c05295d903d";
fsType = "f2fs";
};
fileSystems."/storage" = {
device = "/dev/disk/by-uuid/410fa651-4918-447c-9337-97cc12ff6d2a";
fsType = "ext4";
};
boot.loader.grub = {
enable = true;
device = "/dev/sda";
};
users.groups.beefcake = {};
users.users = {
beefcake = {
isSystemUser = true;
createHome = true;
home = "/storage/backups/beefcake";
group = "beefcake";
extraGroups = ["sftponly"];
openssh.authorizedKeys.keys =
config.users.users.daniel.openssh.authorizedKeys.keys
++ [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK7HrojwoyHED+A/FzRjYmIL0hzofwBd9IYHH6yV0oPO root@beefcake"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAOEI82VdbyR1RYqSnFtlffHBtHFdXO0v9RmQH7GkfXo restic@beefcake"
];
};
daniel = {
# used for restic backups
isNormalUser = true;
extraGroups = ["users" "wheel" "video" "dialout" "uucp"];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAPLXOjupz3ScYjgrF+ehrbp9OvGAWQLI6fplX6w9Ijb daniel@lyte.dev"
];
};
root = {
openssh.authorizedKeys.keys = config.users.users.daniel.openssh.authorizedKeys.keys;
};
};
services.openssh.extraConfig = ''
Match Group sftponly
ChrootDirectory /storage/backups/%u
ForceCommand internal-sftp
AllowTcpForwarding no
'';
networking = {
hostName = "rascal";
networkmanager.enable = true;
firewall = {
enable = true;
allowPing = true;
allowedTCPPorts = [22];
};
};
services.tailscale.useRoutingFeatures = "server";
system.stateVersion = "24.05";
}

42
nixos/rascal/default.nix Normal file
View file

@ -0,0 +1,42 @@
{
inputs,
# outputs,
config,
modulesPath,
...
}: {
imports = [
inputs.hardware.nixosModules.common-cpu-amd
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "ehci_pci" "usbhid" "uas" "sd_mod"];
boot.kernelModules = ["kvm-amd"];
fileSystems."/" = {
device = "/dev/disk/by-uuid/2e2ad73a-6264-4a7b-8439-9c05295d903d";
fsType = "f2fs";
};
boot.loader.grub = {
enable = true;
device = "/dev/sda";
};
networking = {
hostName = "rascal";
networkmanager.enable = true;
};
users.users.beefcake = {
# used for restic backups
isNormalUser = true;
openssh.authorizedKeys.keys =
config.users.users.daniel.openssh.authorizedKeys.keys
++ [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK7HrojwoyHED+A/FzRjYmIL0hzofwBd9IYHH6yV0oPO root@beefcake"
];
};
system.stateVersion = "22.05";
}

View file

@ -1,769 +0,0 @@
{
config,
lib,
# outputs,
pkgs,
...
}: let
/*
NOTE: My goal is to be able to apply most of the common tweaks to the router
either live on the system for ad-hoc changes (such as forwarding a port for a
multiplayer game) or to tweak these values just below without reaching deeper
into the modules' implementation of these configuration values
NOTE: I could turn this into a cool NixOS module?
TODO: review https://francis.begyn.be/blog/nixos-home-router
TODO: more recent: https://github.com/ghostbuster91/blogposts/blob/a2374f0039f8cdf4faddeaaa0347661ffc2ec7cf/router2023-part2/main.md
*/
hostname = "router";
domain = "h.lyte.dev";
ip = "192.168.0.1";
cidr = "${ip}/16";
netmask = "255.255.255.0"; # see cidr
dhcp_lease_space = {
min = "192.168.0.30";
max = "192.168.0.250";
};
interfaces = {
wan = {
name = "wan";
mac = "00:01:2e:82:73:59";
};
lan = {
name = "lan";
mac = "00:01:2e:82:73:5a";
};
};
hosts = {
dragon = {
ip = "192.168.0.10";
};
bald = {
ip = "192.168.0.11";
additionalHosts = [
"ourcraft.lyte.dev"
];
};
beefcake = {
ip = "192.168.0.9";
additionalHosts = [
".beefcake.lan"
"nix.h.lyte.dev"
"idm.h.lyte.dev"
"git.lyte.dev"
"video.lyte.dev"
"paperless.h.lyte.dev"
"audio.lyte.dev"
"a.lyte.dev"
"bw.lyte.dev"
"files.lyte.dev"
"vpn.h.lyte.dev"
"atuin.h.lyte.dev"
"grafana.h.lyte.dev"
"prometheus.h.lyte.dev"
"finances.h.lyte.dev"
"nextcloud.h.lyte.dev"
"onlyoffice.h.lyte.dev"
"a.lyte.dev"
];
};
};
sysctl-entries = {
"net.ipv4.conf.all.forwarding" = true;
"net.ipv6.conf.all.forwarding" = true;
"net.ipv4.conf.default.rp_filter" = 1;
"net.ipv4.conf.${interfaces.wan.name}.rp_filter" = 1;
"net.ipv4.conf.${interfaces.lan.name}.rp_filter" = 0;
"net.ipv6.conf.${interfaces.wan.name}.accept_ra" = 2;
"net.ipv6.conf.${interfaces.wan.name}.autoconf" = 1;
"net.ipv6.conf.all.use_tempaddr" = 2;
"net.ipv6.conf.default.use_tempaddr" = lib.mkForce 2;
"net.ipv6.conf.${interfaces.wan.name}.use_tempaddr" = 2;
# "net.ipv6.conf.${interfaces.wan.name}.addr_gen_mode" = 2;
};
in {
imports = [
{
# hardware
boot = {
loader = {
efi.canTouchEfiVariables = true;
systemd-boot.enable = true;
};
initrd.availableKernelModules = ["xhci_pci"];
initrd.kernelModules = [];
kernelModules = ["kvm-intel"];
extraModulePackages = [];
};
nixpkgs.hostPlatform = "x86_64-linux";
powerManagement.cpuFreqGovernor = "performance";
hardware.cpu.intel.updateMicrocode = true;
}
];
environment.systemPackages = with pkgs; [
iftop
];
sops = {
defaultSopsFile = ../secrets/router/secrets.yml;
age = {
sshKeyPaths = ["/etc/ssh/ssh_host_ed25519_key"];
keyFile = "/var/lib/sops-nix/key.txt";
generateKey = true;
};
secrets = {
netlify-ddns-password = {mode = "0400";};
};
};
services.deno-netlify-ddns-client = {
passwordFile = config.sops.secrets.netlify-ddns-password.path;
};
boot.kernel.sysctl =
sysctl-entries
// {
};
networking = {
hostName = hostname;
domain = domain;
# disable some of the sane defaults
useDHCP = false;
firewall.enable = false;
# use systemd.network for network interface configuration
useNetworkd = true;
# maybe we need this?
nat.enable = true;
extraHosts = ''
127.0.0.1 localhost
127.0.0.2 ${hostname}.${domain} ${hostname}
${ip} ${hostname}.${domain} ${hostname}
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
'';
# the main meat and potatoes for most routers, the firewall configuration
# TODO: IPv6
nftables = let
inf = {
lan = interfaces.lan.name;
wan = interfaces.wan.name;
};
in {
enable = true;
checkRuleset = true;
ruleset = with inf; ''
table inet filter {
## set LANv4 {
## type ipv4_addr
## flags interval
## elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
## }
## set LANv6 {
## type ipv6_addr
## flags interval
## elements = { fd00::/8, fe80::/10 }
## }
## TODO: maybe tailnet?
## chain my_input_lan {
## udp sport 1900 udp dport >= 1024 meta pkttype unicast limit rate 4/second burst 20 packets accept comment "Accept UPnP IGD port mapping reply"
## udp sport netbios-ns udp dport >= 1024 meta pkttype unicast accept comment "Accept Samba Workgroup browsing replies"
## }
chain input {
type filter hook input priority 0; policy drop;
iif lo accept comment "Accept any localhost traffic"
ct state invalid drop comment "Drop invalid connections"
ct state established,related accept comment "Accept traffic originated from us"
meta l4proto ipv6-icmp accept comment "Accept ICMPv6"
meta l4proto icmp accept comment "Accept ICMP"
ip protocol igmp accept comment "Accept IGMP"
ip6 nexthdr icmpv6 icmpv6 type nd-router-solicit accept
ip6 nexthdr icmpv6 icmpv6 type nd-router-advert accept comment "Accept IPv6 router advertisements"
udp dport dhcpv6-client accept comment "IPv6 DHCP"
ip6 nexthdr icmpv6 icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query, destination-unreachable, packet-too-big, time-exceeded, parameter-problem } accept comment "Accept IPv6 ICMP and meta stuff"
ip protocol icmp icmp type { echo-request, destination-unreachable, router-advertisement, time-exceeded, parameter-problem } accept comment "Accept IPv4 ICMP and meta stuff"
ip protocol icmpv6 accept
ip protocol icmp accept
meta l4proto ipv6-icmp counter accept
udp dport dhcpv6-client counter accept
udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS"
udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS"
tcp dport 2201 accept comment "Accept SSH on port 2201"
tcp dport 53 accept comment "Accept DNS"
udp dport 53 accept comment "Accept DNS"
tcp dport { 80, 443 } accept comment "Allow HTTP/HTTPS to server (see nat prerouting)"
udp dport { 80, 443 } accept comment "Allow QUIC to server (see nat prerouting)"
tcp dport { 22 } accept comment "Allow SSH to server (see nat prerouting)"
tcp dport { 25565 } accept comment "Allow Minecraft server connections (see nat prerouting)"
udp dport { 34197 } accept comment "Allow Factorio server connections (see nat prerouting)"
iifname "${lan}" accept comment "Allow local network to access the router"
iifname "tailscale0" accept comment "Allow local network to access the router"
## ip6 saddr @LANv6 jump my_input_lan comment "Connections from private IP address ranges"
## ip saddr @LANv4 jump my_input_lan comment "Connections from private IP address ranges"
iifname "${wan}" counter drop comment "Drop all other unsolicited traffic from wan"
}
chain output {
type filter hook output priority 0;
accept
}
chain forward {
type filter hook forward priority 0;
accept
}
## chain forward {
## type filter hook forward priority filter; policy drop;
## iifname { "${lan}" } oifname { "${wan}" } accept comment "Allow trusted LAN to WAN"
## iifname { "tailscale0" } oifname { "${wan}" } accept comment "Allow trusted LAN to WAN"
## iifname { "${wan}" } oifname { "${lan}" } ct state { established, related } accept comment "Allow established back to LAN"
## }
}
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat;
iifname ${lan} accept
iifname tailscale0 accept
iifname ${wan} tcp dport {22} dnat to ${hosts.beefcake.ip}
iifname ${wan} tcp dport {80, 443} dnat to ${hosts.beefcake.ip}
iifname ${wan} udp dport {80, 443} dnat to ${hosts.beefcake.ip}
iifname ${wan} tcp dport {26966} dnat to ${hosts.beefcake.ip}
iifname ${wan} tcp dport {25565} dnat to ${hosts.bald.ip}
iifname ${wan} udp dport {25565} dnat to ${hosts.bald.ip}
iifname ${wan} udp dport {34197} dnat to ${hosts.beefcake.ip}
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname "${wan}" masquerade
}
}
'';
};
# NOTE: see flake.nix 'nnf.nixosModules.default'
/*
nftables.firewall = let
me = config.networking.nftables.firewall.localZoneName;
in {
enable = true;
snippets.nnf-common.enable = true;
zones = {
${interfaces.wan.name} = {
interfaces = [interfaces.wan.name interfaces.lan.name];
};
${interfaces.lan.name} = {
parent = interfaces.wan.name;
ipv4Addresses = [cidr];
};
## banned = {
## ingressExpression = [
## "ip saddr @banlist"
## "ip6 saddr @banlist6"
## ];
## egressExpression = [
## "ip daddr @banlist"
## "ip6 daddr @banlist6"
## ];
## };
};
rules = {
dhcp = {
from = "all";
to = [hosts.beefcake.ip];
allowedTCPPorts = [67];
allowedUDPPorts = [67];
};
http = {
from = "all";
to = [me];
allowedTCPPorts = [80 443];
};
router-ssh = {
from = "all";
to = [me];
allowedTCPPorts = [2201];
};
server-ssh = {
from = "all";
to = [hosts.beefcake.ip];
allowedTCPPorts = [22];
};
};
};
*/
};
systemd.network = {
enable = true;
# wait-online.anyInterface = true;
# configure known names for the network interfaces
links = {
"20-${interfaces.wan.name}" = {
enable = true;
matchConfig = {
MACAddress = interfaces.wan.mac;
};
linkConfig = {
Name = interfaces.wan.name;
};
};
"30-${interfaces.lan.name}" = {
enable = true;
matchConfig = {
MACAddress = interfaces.lan.mac;
};
linkConfig = {
Name = interfaces.lan.name;
};
};
};
# configure networks for the interfaces
networks = {
# LAN configuration is very simple and mostly forwarded between
# TODO: IPv6
"50-${interfaces.lan.name}" = {
matchConfig.Name = "${interfaces.lan.name}";
linkConfig = {
RequiredForOnline = "enslaved";
# Name = interfaces.lan.name;
};
address = [
cidr
];
networkConfig = {
# Description = "LAN network - connection to switch in house";
ConfigureWithoutCarrier = true;
# IPv6AcceptRA = false;
IPv6SendRA = true;
DHCPPrefixDelegation = true;
};
};
/*
WAN configuration requires DHCP to get addresses
we also disable some options to be certain we retain as much networking
control as we reasonably can, such as not letting the ISP determine our
hostname or DNS configuration
TODO: IPv6 (prefix delegation)
*/
"40-${interfaces.wan.name}" = {
matchConfig.Name = "${interfaces.wan.name}";
networkConfig = {
Description = "WAN network - connection to fiber ISP jack";
DHCP = true;
/*
IPv6AcceptRA = true;
IPv6PrivacyExtensions = true;
IPForward = true;
*/
};
dhcpV6Config = {
/*
ForceDHCPv6PDOtherInformation = true;
UseHostname = false;
UseDNS = false;
UseNTP = false;
*/
PrefixDelegationHint = "::/56";
};
dhcpV4Config = {
Hostname = hostname;
UseHostname = false;
UseDNS = false;
UseNTP = false;
UseSIP = false;
UseRoutes = false;
UseGateway = true;
};
linkConfig = {
RequiredForOnline = "routable";
# Name = interfaces.wan.name;
};
ipv6AcceptRAConfig = {
DHCPv6Client = "always";
UseDNS = false;
};
};
};
};
services.resolved.enable = false;
/*
dnsmasq serves as our DHCP and DNS server
almost all the configuration should be derived from the values at the top of
this file
*/
services.dnsmasq = {
enable = true;
settings = {
listen-address = "::,127.0.0.1,${ip}";
port = 53;
/*
dhcp-authoritative = true;
dnssec = true;
*/
enable-ra = true;
server = ["1.1.1.1" "9.9.9.9" "8.8.8.8"];
domain-needed = true;
bogus-priv = true;
no-resolv = true;
cache-size = "10000";
dhcp-range = with dhcp_lease_space; [
"${interfaces.lan.name},${min},${max},${netmask},24h"
"::,constructor:${interfaces.lan.name},ra-stateless,ra-names,4h"
];
except-interface = interfaces.wan.name;
interface = interfaces.lan.name;
dhcp-host =
[
]
++ (lib.attrsets.mapAttrsToList (name: {
ip,
identifier ? name,
time ? "12h",
...
}: "${name},${ip},${identifier},${time}")
hosts);
address =
[
"/${hostname}.${domain}/${ip}"
]
++ (lib.lists.flatten (lib.attrsets.mapAttrsToList (name: {
ip,
additionalHosts ? [],
identifier ? name,
time ? "12h",
}: [
"/${name}.${domain}/${ip}"
(lib.lists.forEach additionalHosts (h: "/${h}/${ip}"))
])
hosts));
# local domains
local = "/lan/";
domain = "lan";
expand-hosts = true;
# don't use /etc/hosts as this would advertise surfer as localhost
no-hosts = true;
};
};
/*
since the home network reserves port 22 for ssh to the big server and to
gitea, the router uses port 2201 for ssh
*/
services.openssh.listenAddresses = [
{
addr = "0.0.0.0";
port = 2201;
}
{
addr = "0.0.0.0";
port = 22;
}
{
addr = "[::]";
port = 2201;
}
{
addr = "[::]";
port = 22;
}
];
services.fail2ban.enable = true;
system.stateVersion = "24.05";
/*
NOTE: everything from here on is deprecated or old stuff
TODO: may not be strictly necessary for IPv6?
TODO: also may not even be the best implementation?
services.radvd = {
enable = false;
## NOTE: this config is just the default arch linux config I think and may
## need tweaking? this is what I had on the arch linux router, though :shrug:
config = ''
interface lo
{
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
AdvDefaultPreference low;
AdvHomeAgentFlag off;
prefix 2001:db8:1:0::/64
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
};
prefix 0:0:0:1234::/64
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
Base6to4Interface ppp0;
AdvPreferredLifetime 120;
AdvValidLifetime 300;
};
route 2001:db0:fff::/48
{
AdvRoutePreference high;
AdvRouteLifetime 3600;
};
RDNSS 2001:db8::1 2001:db8::2
{
AdvRDNSSLifetime 30;
};
DNSSL branch.example.com example.com
{
AdvDNSSLLifetime 30;
};
};
'';
};
TODO: old config, should be deleted ASAP
services.dnsmasq = {
enable = false;
settings = {
# server endpoints
listen-address = "::1,127.0.0.1,${ip}";
port = "53";
# DNS cache entries
cache-size = "10000";
# local domain entries
local = "/lan/";
domain = "lan";
expand-hosts = true;
dhcp-authoritative = true;
conf-file = "/usr/share/dnsmasq/trust-anchors.conf";
dnssec = true;
except-interface = "${wan_if}";
interface = "${lan_if}";
enable-ra = true;
# dhcp-option = "121,${cidr},${ip}";
dhcp-range = [
"lan,${dhcp_lease_space.min},${dhcp_lease_space.max},${netmask},10m"
"tag:${lan_if},::1,constructor:${lan_if},ra-names,12h"
];
dhcp-host = [
"${hosts.dragon.host},${hosts.dragon.ip},12h"
"${hosts.beefcake.host},${hosts.beefcake.ip},12h"
];
# may need to go in /etc/hosts (networking.extraHosts), too?
address = [
"/video.lyte.dev/192.168.0.9"
"/git.lyte.dev/192.168.0.9"
"/bw.lyte.dev/192.168.0.9"
"/files.lyte.dev/192.168.0.9"
"/vpn.h.lyte.dev/192.168.0.9"
"/.h.lyte.dev/192.168.0.9"
];
server = [
"${ip}"
"8.8.8.8"
"8.8.4.4"
"1.1.1.1"
"1.0.0.1"
];
};
};
TODO: old config, should be deleted ASAP
nftables = {
enable = false;
flushRuleset = true;
tables = {
filter = {
family = "inet";
content = ''
chain input {
# type filter hook input priority filter; policy accept;
type filter hook input priority 0;
# anything from loopback interface
iifname "lo" accept
# accept traffic we originated
ct state { established, related } counter accept
ct state invalid counter drop
# ICMP
ip6 nexthdr icmpv6 icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query, destination-unreachable, packet-too-big, time-exceeded, parameter-problem } counter accept
ip protocol icmp icmp type { echo-request, destination-unreachable, router-advertisement, time-exceeded, parameter-problem } counter accept
ip protocol icmpv6 counter accept
ip protocol icmp counter accept
meta l4proto ipv6-icmp counter accept
udp dport dhcpv6-client counter accept
tcp dport { 64022, 22, 53, 67, 25565 } counter accept
udp dport { 64020, 22, 53, 67 } counter accept
## iifname "iot" ip saddr $iot-ip tcp dport { llmnr } counter accept
## iifname "iot" ip saddr $iot-ip udp dport { mdns, llmnr } counter accept
iifname "${lan_if}" tcp dport { llmnr } counter accept
iifname "${lan_if}" udp dport { mdns, llmnr } counter accept
counter drop
}
# allow all outgoing
chain output {
type filter hook output priority 0;
accept
}
chain forward {
type filter hook forward priority 0;
accept
}
'';
};
nat = {
family = "ip";
content = ''
set masq_saddr {
type ipv4_addr
flags interval
elements = { ${cidr} }
}
map map_port_ipport {
type inet_proto . inet_service : ipv4_addr . inet_service
}
chain prerouting {
iifname ${lan_if} accept
type nat hook prerouting priority dstnat + 1; policy accept;
fib daddr type local dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
iifname ${wan_if} tcp dport { 22, 80, 443, 25565, 64022 } dnat to ${hosts.beefcake.ip}
iifname ${wan_if} udp dport { 64020 } dnat to ${hosts.beefcake.ip}
## iifname ${wan_if} tcp dport { 25565 } dnat to 192.168.0.244
## iifname ${wan_if} udp dport { 25565 } dnat to 192.168.0.244
## router
iifname ${wan_if} tcp dport { 2201 } dnat to ${ip}
}
chain output {
type nat hook output priority -99; policy accept;
ip daddr != 127.0.0.0/8 oif "lo" dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
}
chain postrouting {
type nat hook postrouting priority srcnat + 1; policy accept;
oifname ${lan_if} masquerade
ip saddr @masq_saddr masquerade
}
'';
};
};
};
TODO: also want to try to avoid using dhcpcd for IPv6 since systemd-networkd
should be sufficient?
dhcpcd = {
enable = false;
extraConfig = ''
duid
## No way.... https://github.com/NetworkConfiguration/dhcpcd/issues/36#issuecomment-954777644
## issues caused by guests with oneplus devices
noarp
persistent
vendorclassid
option domain_name_servers, domain_name, domain_search
option classless_static_routes
option interface_mtu
option host_name
#option ntp_servers
require dhcp_server_identifier
slaac private
noipv4ll
noipv6rs
static domain_name_servers=${ip}
interface ${wan_if}
gateway
ipv6rs
iaid 1
## option rapid_commit
## ia_na 1
ia_pd 1 ${lan_if}
interface ${lan_if}
static ip_address=${cidr}
static routers=${ip}
static domain_name_servers=${ip}
'';
};
*/
}

362
nixos/router/default.nix Normal file
View file

@ -0,0 +1,362 @@
{
flake,
inputs,
lib,
# outputs,
# config,
# pkgs,
...
}: let
# NOTE: I could turn this into a cool NixOS module?
# TODO: review https://francis.begyn.be/blog/nixos-home-router
ip = "192.168.0.1";
cidr = "${ip}/16";
netmask = "255.255.0.0";
lease = {
min = "192.168.0.5";
max = "192.168.0.250";
};
wan_if = "wan0";
lan_if = "lan0";
hosts = {
dragon = {
identifier = "dragon";
host = "dragon";
ip = "192.168.0.10";
};
beefcake = {
identifier = "beefcake";
host = "beefcake";
ip = "192.168.0.9";
};
};
in {
networking.hostName = "router";
networking.domain = "h.lyte.dev";
networking.useDHCP = false;
imports = [
inputs.disko.nixosModules.disko
flake.diskoConfigurations.unencrypted
];
# TODO: perform a hardware scan
boot = {
loader = {
efi.canTouchEfiVariables = true;
systemd-boot.enable = true;
};
kernel = {
sysctl = {
"net.ipv4.conf.all.forwarding" = true;
"net.ipv6.conf.all.forwarding" = true;
"net.ipv6.conf.all.accept_ra" = 0;
"net.ipv6.conf.all.autoconf" = 0;
"net.ipv6.conf.all.use_tempaddr" = 0;
"net.ipv6.conf.wan0.accept_ra" = 2;
# "net.ipv6.conf.wan0.autoconf" = 1;
};
};
};
powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
services.fail2ban.enable = true;
services.radvd = {
enable = true;
# NOTE: this config is just the default arch linux config I think and may
# need tweaking? this is what I had on the arch linux router, though :shrug:
config = ''
interface lo
{
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
AdvDefaultPreference low;
AdvHomeAgentFlag off;
prefix 2001:db8:1:0::/64
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
};
prefix 0:0:0:1234::/64
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
Base6to4Interface ppp0;
AdvPreferredLifetime 120;
AdvValidLifetime 300;
};
route 2001:db0:fff::/48
{
AdvRoutePreference high;
AdvRouteLifetime 3600;
};
RDNSS 2001:db8::1 2001:db8::2
{
AdvRDNSSLifetime 30;
};
DNSSL branch.example.com example.com
{
AdvDNSSLLifetime 30;
};
};
'';
};
services.resolved = {
enable = true;
extraConfig = ''
[Resolve]
DNSStubListener=no
'';
};
services.dnsmasq = {
enable = true;
settings = {
# server endpoints
listen-address = "::1,127.0.0.1,${ip}";
port = "53";
# DNS cache entries
cache-size = "10000";
# local domain entries
local = "/lan/";
domain = "lan";
expand-hosts = true;
dhcp-authoritative = true;
conf-file = "/usr/share/dnsmasq/trust-anchors.conf";
dnssec = true;
except-interface = "${wan_if}";
interface = "${lan_if}";
enable-ra = true;
# dhcp-option = "121,${cidr},${ip}";
dhcp-range = [
"lan,${lease.min},${lease.max},${netmask},10m"
"tag:${lan_if},::1,constructor:${lan_if},ra-names,12h"
];
dhcp-host = [
"${hosts.dragon.host},${hosts.dragon.ip},12h"
"${hosts.beefcake.host},${hosts.beefcake.ip},12h"
];
# may need to go in /etc/hosts (networking.extraHosts), too?
address = [
"/video.lyte.dev/192.168.0.9"
"/git.lyte.dev/192.168.0.9"
"/bw.lyte.dev/192.168.0.9"
"/files.lyte.dev/192.168.0.9"
"/vpn.h.lyte.dev/192.168.0.9"
"/.h.lyte.dev/192.168.0.9"
];
server = [
"${ip}"
"8.8.8.8"
"8.8.4.4"
"1.1.1.1"
"1.0.0.1"
];
};
};
networking.extraHosts = ''
127.0.0.1 localhost
127.0.1.1 router.h.lyte.dev router
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
'';
networking.nat.enable = true; # TODO: maybe replace some of the nftables stuff with this?
networking.firewall.enable = false;
networking.nftables = {
enable = true;
flushRuleset = true;
tables = {
filter = {
family = "inet";
content = ''
chain input {
# type filter hook input priority filter; policy accept;
type filter hook input priority 0;
# anything from loopback interface
iifname "lo" accept
# accept traffic we originated
ct state { established, related } counter accept
ct state invalid counter drop
# ICMP
ip6 nexthdr icmpv6 icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query, destination-unreachable, packet-too-big, time-exceeded, parameter-problem } counter accept
ip protocol icmp icmp type { echo-request, destination-unreachable, router-advertisement, time-exceeded, parameter-problem } counter accept
ip protocol icmpv6 counter accept
ip protocol icmp counter accept
meta l4proto ipv6-icmp counter accept
udp dport dhcpv6-client counter accept
tcp dport { 64022, 22, 53, 67, 25565 } counter accept
udp dport { 64020, 22, 53, 67 } counter accept
# iifname "iot" ip saddr $iot-ip tcp dport { llmnr } counter accept
# iifname "iot" ip saddr $iot-ip udp dport { mdns, llmnr } counter accept
iifname "${lan_if}" tcp dport { llmnr } counter accept
iifname "${lan_if}" udp dport { mdns, llmnr } counter accept
counter drop
}
# allow all outgoing
chain output {
type filter hook output priority 0;
accept
}
chain forward {
type filter hook forward priority 0;
accept
}
'';
};
nat = {
family = "ip";
content = ''
set masq_saddr {
type ipv4_addr
flags interval
elements = { ${cidr} }
}
map map_port_ipport {
type inet_proto . inet_service : ipv4_addr . inet_service
}
chain prerouting {
iifname ${lan_if} accept
type nat hook prerouting priority dstnat + 1; policy accept;
fib daddr type local dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
iifname ${wan_if} tcp dport { 22, 80, 443, 25565, 64022 } dnat to ${hosts.beefcake.ip}
iifname ${wan_if} udp dport { 64020 } dnat to ${hosts.beefcake.ip}
# iifname ${wan_if} tcp dport { 25565 } dnat to 192.168.0.244
# iifname ${wan_if} udp dport { 25565 } dnat to 192.168.0.244
# router
iifname ${wan_if} tcp dport { 2201 } dnat to ${ip}
}
chain output {
type nat hook output priority -99; policy accept;
ip daddr != 127.0.0.0/8 oif "lo" dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
}
chain postrouting {
type nat hook postrouting priority srcnat + 1; policy accept;
oifname ${lan_if} masquerade
ip saddr @masq_saddr masquerade
}
'';
};
};
};
networking.dhcpcd = {
enable = true;
extraConfig = ''
duid
# No way.... https://github.com/NetworkConfiguration/dhcpcd/issues/36#issuecomment-954777644
# issues caused by guests with oneplus devices
noarp
persistent
vendorclassid
option domain_name_servers, domain_name, domain_search
option classless_static_routes
option interface_mtu
option host_name
#option ntp_servers
require dhcp_server_identifier
slaac private
noipv4ll
noipv6rs
static domain_name_servers=${ip}
interface ${wan_if}
gateway
ipv6rs
iaid 1
# option rapid_commit
# ia_na 1
ia_pd 1 ${lan_if}
interface ${lan_if}
static ip_address=${cidr}
static routers=${ip}
static domain_name_servers=${ip}
'';
};
systemd.network = {
enable = true;
links = {
"${wan_if}" = {
enable = true;
matchConfig = {
MACAddress = "00:01:2e:82:73:59";
};
linkConfig = {
Name = wan_if;
};
};
"${lan_if}" = {
enable = true;
matchConfig = {
MACAddress = "00:01:2e:82:73:5a";
};
linkConfig = {
Name = lan_if;
};
};
};
};
services.avahi = {
enable = true;
reflector = true;
allowInterfaces = [
lan_if
];
};
system.stateVersion = "23.11";
}

View file

@ -1,92 +0,0 @@
{
pkgs,
lib,
config,
...
}: {
networking.hostName = "thablet";
boot.loader.systemd-boot.enable = true;
services.fprintd = {
# TODO: am I missing a driver? see arch wiki for this h/w
enable = false;
# tod.enable = true;
# tod.driver = pkgs.libfprint-2-tod1-goodix;
};
environment.systemPackages =
#with pkgs;
[];
# https://wiki.archlinux.org/title/Lenovo_ThinkPad_X1_Yoga_(Gen_3)#Using_acpi_call
systemd.services.activate-touch-hack = {
enable = true;
description = "Touch wake Thinkpad X1 Yoga 3rd gen hack";
unitConfig = {
After = ["suspend.target" "hibernate.target" "hybrid-sleep.target" "suspend-then-hibernate.target"];
};
serviceConfig = {
ExecStart = ''
/bin/sh -c "echo '\\_SB.PCI0.LPCB.EC._Q2A' > /proc/acpi/call"
'';
};
wantedBy = ["suspend.target" "hibernate.target" "hybrid-sleep.target" "suspend-then-hibernate.target"];
};
boot.initrd.availableKernelModules = ["xhci_pci" "nvme" "usb_storage" "sd_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = ["kvm-intel" "acpi_call"];
boot.extraModulePackages = with config.boot.kernelPackages; [acpi_call];
hardware = {
cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
graphics = {
enable = true;
enable32Bit = true;
extraPackages = with pkgs; [
intel-media-driver
intel-ocl
intel-vaapi-driver
];
};
};
hardware.bluetooth = {
enable = true;
powerOnBoot = false;
};
services.power-profiles-daemon = {
enable = true;
};
networking = {
firewall = let
terraria = 7777;
stardew-valley = 24642;
in {
allowedTCPPorts = [terraria stardew-valley];
allowedUDPPorts = [terraria stardew-valley];
};
};
home-manager.users.daniel = {
wayland.windowManager.sway = {
config = {
output = {
"AU Optronics 0x2236 Unknown" = {
mode = "2560x1440@60Hz";
position = "0,0";
scale = toString 1.25;
};
};
};
};
};
system.stateVersion = "24.05";
}

79
nixos/thablet/default.nix Normal file
View file

@ -0,0 +1,79 @@
{
flake,
inputs,
outputs,
lib,
config,
modulesPath,
...
}: {
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
inputs.disko.nixosModules.disko
flake.diskoConfigurations.standard
inputs.hardware.nixosModules.lenovo-thinkpad-x1-yoga
]
++ (with outputs.nixosModules; [
desktop-usage
gnome
wifi
]);
nixpkgs = {
overlays = [
outputs.overlays.additions
outputs.overlays.modifications
outputs.overlays.unstable-packages
];
config = {
allowUnfree = true;
};
};
nix = {
registry = lib.mapAttrs (_: value: {flake = value;}) inputs;
nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;
settings = {
experimental-features = "nix-command flakes";
auto-optimise-store = true;
};
};
# not necessarily "base", but all my machines are UEFI so...
boot.loader.systemd-boot.enable = true;
services.fprintd = {
enable = true;
# tod.enable = true;
# tod.driver = pkgs.libfprint-2-tod1-goodix;
};
environment.systemPackages =
#with pkgs;
[];
programs.steam.enable = true;
programs.steam.remotePlay.openFirewall = true;
networking = {
firewall = {
enable = true;
allowPing = true;
allowedTCPPorts = [22];
allowedUDPPorts = [];
};
};
boot.initrd.availableKernelModules = ["xhci_pci" "nvme" "usb_storage" "sd_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = ["kvm-intel"];
boot.extraModulePackages = [];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
system.stateVersion = "23.11";
}

View file

@ -1,20 +0,0 @@
{...}: {
networking.hostName = "thinker";
boot = {
loader = {
efi.canTouchEfiVariables = true;
systemd-boot.enable = true;
};
/*
sudo filefrag -v /swap/swapfile | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'
the above won't work for btrfs, instead you need
btrfs inspect-internal map-swapfile -r /swap/swapfile
https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#Hibernation_into_swap_file
*/
kernelParams = ["boot.shell_on_fail"];
initrd.availableKernelModules = ["xhci_pci" "nvme" "ahci"];
};
hardware.bluetooth.enable = true;
}

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