61 Commits

Author SHA1 Message Date
Tom Alexander
1b34841921 Comment out specific version of gpg. 2025-01-01 18:43:29 -05:00
Tom Alexander
611904761e Add kubernetes client. 2025-01-01 18:43:29 -05:00
Tom Alexander
f843b7924f Add docker. 2025-01-01 18:29:27 -05:00
Tom Alexander
7bb7b89b82 Try a specific version of gpg. 2025-01-01 13:35:29 -05:00
Tom Alexander
c1103775b6 Keep 30 days of /nix. 2025-01-01 13:31:45 -05:00
Tom Alexander
24d89ed704 Default to power-saving mode. 2024-12-31 12:51:23 -05:00
Tom Alexander
e8dff5ece1 Set up wireguard networks using functions. 2024-12-31 11:04:24 -05:00
Tom Alexander
e22b5c1c6c Add power management kernel parameters. 2024-12-31 10:27:15 -05:00
Tom Alexander
d9bc4f15d8 Add powertop. 2024-12-31 07:44:02 -05:00
Tom Alexander
77ae96ca7a Set up python. 2024-12-31 07:37:48 -05:00
Tom Alexander
d2f908005c Persist the .ssh known_hosts. 2024-12-31 07:00:41 -05:00
Tom Alexander
5e74a874ba Persist sound settings (for example, muted status) and do not enable wireguard in built ISO. 2024-12-29 15:45:52 -05:00
Tom Alexander
fe820e5843 Move remaining nix configs into folders. 2024-12-29 15:27:03 -05:00
Tom Alexander
81315e4c7b Add a snes emulator. 2024-12-29 15:12:31 -05:00
Tom Alexander
ce8718b042 Add wgh wireguard network. 2024-12-28 21:05:45 -05:00
Tom Alexander
720164497d More attempts to fix gpg decrypt with yubikey. 2024-12-27 20:53:43 -05:00
Tom Alexander
0b31b91c69 Set up wireguard. 2024-12-27 15:44:00 -05:00
Tom Alexander
2ef181cfab Attempt to fix gpg decrypt with yubikey. Did not succeed. 2024-12-27 13:09:13 -05:00
Tom Alexander
5a3450fdf8 Add gvfs and git-crypt. 2024-12-26 21:28:31 -05:00
Tom Alexander
aae534308a Add noise supression to microphone. 2024-12-25 09:17:30 -05:00
Tom Alexander
cbd8f70ce4 Merge branch 'zsh' into nix 2024-12-25 09:17:23 -05:00
Tom Alexander
64d495afa5 Use zsh-histdb package. 2024-12-23 17:28:31 -05:00
Tom Alexander
5e424b35e4 Make a zsh-histdb package. 2024-12-23 15:41:45 -05:00
Tom Alexander
7decd40844 Switch to zsh. 2024-12-23 11:14:18 -05:00
Tom Alexander
9c0f3ce601 Use dark themes. 2024-12-23 10:56:57 -05:00
Tom Alexander
e09eea2049 Switch to zen kernel optimized for znver4. 2024-12-23 10:00:01 -05:00
Tom Alexander
5d23126205 Enable secure boot. 2024-12-22 22:03:03 -05:00
Tom Alexander
748e6dee68 Set firefox as default browser. 2024-12-22 16:14:12 -05:00
Tom Alexander
27aa2f077b Set up chromium with support for wayland and widevine. 2024-12-22 00:48:57 -05:00
Tom Alexander
69098488f6 Switch to a raw file for fontconfig. 2024-12-21 17:15:54 -05:00
Tom Alexander
14e6e78aee Add the waybar scripts. 2024-12-21 16:25:40 -05:00
Tom Alexander
a0f9f4baa4 Set up waybar and building ISOs. 2024-12-21 15:46:05 -05:00
Tom Alexander
a7f3754d25 Add more sway config files. 2024-12-20 23:03:51 -05:00
Tom Alexander
54c8459fa1 Switch to vulkan renderer for sway. 2024-12-20 22:45:09 -05:00
Tom Alexander
e26118af4f Reformat all nix files. 2024-12-20 22:37:44 -05:00
Tom Alexander
764a8c58ce Add alias for emacs. 2024-12-20 22:36:32 -05:00
Tom Alexander
8f89f1c6c1 Add alacritty config. 2024-12-20 21:59:20 -05:00
Tom Alexander
862829c57c Preserve firefox cache. 2024-12-20 21:38:19 -05:00
Tom Alexander
aba96213c3 Enable the nixd language server in emacs. 2024-12-20 21:19:22 -05:00
Tom Alexander
e7ab762ee4 Fix firefox launch time. 2024-12-20 21:06:04 -05:00
Tom Alexander
b314982196 Set up firefox. 2024-12-20 18:30:35 -05:00
Tom Alexander
27060fed8d Preserve gpg directory. 2024-12-20 16:50:27 -05:00
Tom Alexander
20c1c46d12 Set up fonts. 2024-12-20 16:07:12 -05:00
Tom Alexander
3b133ed86c Do not launch alacritty at the start. 2024-12-20 15:34:02 -05:00
Tom Alexander
0aad0c39f4 Enable wayland support for emacs.
This unfortunately means pinning to a specific version (or using 3rd party emacs-overlay).
2024-12-20 15:30:51 -05:00
Tom Alexander
fe1033fa4b Switch to uid/gid 11235. 2024-12-20 15:22:46 -05:00
Tom Alexander
2ce635d028 Fix emacs config. 2024-12-20 15:03:33 -05:00
Tom Alexander
ba3a6e74eb Add git config and initial emacs config. 2024-12-20 13:17:13 -05:00
Tom Alexander
7e768022e7 Add hotkeys and window management to sway. 2024-12-19 23:08:19 -05:00
Tom Alexander
a76bd4ebd3 Fix wifi config 2024-12-19 22:20:55 -05:00
Tom Alexander
df89d1b973 Enable redistributable firmware. 2024-12-19 19:52:27 -05:00
Tom Alexander
50811aad77 Set up building an ISO from the config. 2024-12-19 19:36:10 -05:00
Tom Alexander
df3528d62a Enable graphics acceleration. 2024-12-19 18:59:38 -05:00
Tom Alexander
e97c570bb2 Trust wheel. 2024-12-19 18:09:48 -05:00
Tom Alexander
fbcb0826d2 Extremely minimal sway setup. 2024-12-19 17:33:21 -05:00
Tom Alexander
74499fb6a0 Switch to a different way of building the VM. 2024-12-19 16:28:40 -05:00
Tom Alexander
fbbff409a0 Add a build for a qemu virtual machine. 2024-12-19 16:14:47 -05:00
Tom Alexander
05da118d8f Start module for sway. 2024-12-19 15:13:56 -05:00
Tom Alexander
033d695fd9 Only set bootloader when in VM. 2024-12-19 15:06:57 -05:00
Tom Alexander
6953cdb81f Set up a minimal initial config. 2024-12-17 16:46:44 -05:00
Tom Alexander
48f700b803 Add script for managing nix testing vm. 2024-12-17 16:46:43 -05:00
79 changed files with 4836 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
{
config,
lib,
pkgs,
pkgs-unstable,
home-manager,
...
}:
{
imports = [
./roles/reset
./roles/iso
./hosts/odo
"${
builtins.fetchTarball {
url = "https://github.com/nix-community/disko/archive/refs/tags/v1.9.0.tar.gz";
sha256 = "0j76ar4qz320fakdii4659w5lww8wiz6yb7g47npywqvf2lbp388";
}
}/module.nix"
./roles/boot
./roles/zfs
./roles/network
./roles/firewall
./roles/zsh
./roles/graphics
./roles/sound
./roles/sway
./roles/alacritty
./roles/firefox
./roles/chromium
./roles/emacs
./roles/git
./roles/fonts
./roles/gpg
./roles/waybar
./roles/qemu
./roles/wireguard
./roles/bsnes
./roles/ssh
./roles/python
./roles/docker
./roles/kubernetes
];
nix.settings.experimental-features = [
"nix-command"
"flakes"
];
nix.settings.trusted-users = [ "@wheel" ];
# boot.kernelPackages = pkgs.linuxPackages_6_11;
hardware.enableRedistributableFirmware = true;
services.getty = {
autologinUser = "talexander"; # I use full disk encryption so the user password is irrelevant.
autologinOnce = true;
};
users.mutableUsers = false;
users.users.talexander = {
isNormalUser = true;
createHome = true; # https://github.com/NixOS/nixpkgs/issues/6481
group = "talexander";
extraGroups = [ "wheel" ];
uid = 11235;
packages = with pkgs; [
tree
];
# Generate with `mkpasswd -m scrypt`
hashedPassword = "$7$CU..../....VXvNQ8za3wSGpdzGXNT50/$HcFtn/yvwPMCw4888BelpiAPLAxe/zU87fD.d/N6U48";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGu+k5lrirokdW5zVdRVBOqEOAvAPlIkG/MdJNc9g5ky"
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIEI6mu6I5Jp+Ib0vJxapGHbEShZjyvzV8jz5DnzDrI39AAAABHNzaDo="
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIAFNcSXwvy+brYTOGo56G93Ptuq2MmZsjvRWAfMqbmMLAAAABHNzaDo="
];
};
users.groups.talexander.gid = 11235;
home-manager.users.talexander =
{ pkgs, ... }:
{
home.packages = [
pkgs.atool
pkgs.httpie
];
programs.bash.enable = true;
# The state version is required and should stay at the version you
# originally installed.
home.stateVersion = "24.11";
};
# Automatic garbage collection
nix.gc = {
# Runs nix-collect-garbage --delete-older-than 5d
automatic = true;
randomizedDelaySec = "14m";
options = "--delete-older-than 30d";
};
# Use doas instead of sudo
security.doas.enable = true;
security.doas.wheelNeedsPassword = false;
security.sudo.enable = false;
security.doas.extraRules = [
{
# Retain environment (for example NIX_PATH)
keepEnv = true;
persist = true; # Only ask for a password the first time.
}
];
# Do not use default packages (nixos includes some defaults like nano)
environment.defaultPackages = lib.mkForce [ ];
environment.systemPackages = with pkgs; [
wget
mg
rsync
libinput
htop
tmux
file
usbutils # for lsusb
pciutils # for lspci
mesa-demos # for glxgears TODO move to better role
vulkan-tools # for vkcube TODO move to better role
xorg.xeyes # to test which windows are using x11 TODO move to better role
ripgrep
strace
tcpdump
git-crypt
];
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
hostKeys = [
{
path = "/persist/ssh/ssh_host_ed25519_key";
type = "ed25519";
}
{
path = "/persist/ssh/ssh_host_rsa_key";
type = "rsa";
bits = 4096;
}
];
};
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
directories = [
"/var/lib/iwd" # Wifi settings
"/var/lib/nixos" # Contains user information (uids/gids)
"/var/lib/systemd" # Systemd state directory for random seed, persistent timers, core dumps, persist hardware state like backlight and rfkill
"/var/log/journal" # Logs, alternatively set `services.journald.storage = "volatile";` to write to /run/log/journal
"/etc/zfs/zpool.cache" # Which zpools to import, the root zpool is already imported and does not need this cache file but this captures additional pools. TODO consider setting cachefile=none on main pool.
];
files = [
"/etc/machine-id" # Systemd unique machine id "otherwise, the system journal may fail to list earlier boots, etc"
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
];
# users.talexander = {
# directories = [];
# files = [];
# };
};
# Write a list of the currently installed packages to /etc/current-system-packages
environment.etc."current-system-packages".text =
let
packages = builtins.map (p: "${p.name}") config.environment.systemPackages;
sortedUnique = builtins.sort builtins.lessThan (lib.unique packages);
formatted = builtins.concatStringsSep "\n" sortedUnique;
in
formatted;
# nixpkgs.overlays = [
# (final: prev: {
# nix = pkgs-unstable.nix;
# })
# ];
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "24.11"; # Did you read the comment?
}

360
nix/configuration/flake.lock generated Normal file
View File

@@ -0,0 +1,360 @@
{
"nodes": {
"crane": {
"inputs": {
"nixpkgs": [
"lanzaboote",
"nixpkgs"
]
},
"locked": {
"lastModified": 1717535930,
"narHash": "sha256-1hZ/txnbd/RmiBPNUs7i8UQw2N89uAK3UzrGAWdnFfU=",
"owner": "ipetkov",
"repo": "crane",
"rev": "55e7754ec31dac78980c8be45f8a28e80e370946",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"lanzaboote",
"nixpkgs"
]
},
"locked": {
"lastModified": 1717285511,
"narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"lanzaboote",
"pre-commit-hooks-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1734366194,
"narHash": "sha256-vykpJ1xsdkv0j8WOVXrRFHUAdp9NXHpxdnn1F4pYgSw=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "80b0fdf483c5d1cb75aaad909bd390d48673857f",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-24.11",
"repo": "home-manager",
"type": "github"
}
},
"impermanence": {
"locked": {
"lastModified": 1734945620,
"narHash": "sha256-olIfsfJK4/GFmPH8mXMmBDAkzVQ1TWJmeGT3wBGfQPY=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "d000479f4f41390ff7cf9204979660ad5dd16176",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"lanzaboote": {
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
],
"pre-commit-hooks-nix": "pre-commit-hooks-nix",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1718178907,
"narHash": "sha256-eSZyrQ9uoPB9iPQ8Y5H7gAmAgAvCw3InStmU3oEjqsE=",
"owner": "nix-community",
"repo": "lanzaboote",
"rev": "b627ccd97d0159214cee5c7db1412b75e4be6086",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "v0.4.1",
"repo": "lanzaboote",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1735141468,
"narHash": "sha256-VIAjBr1qGcEbmhLwQJD6TABppPMggzOvqFsqkDoMsAY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4005c3ff7505313cbc21081776ad0ce5dfd7a3ce",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-b93b4e9b5": {
"locked": {
"lastModified": 1713721570,
"narHash": "sha256-R0s+O5UjTePQRb72XPgtkTmEiOOW8n+1q9Gxt/OJnKU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b93b4e9b527904aadf52dba6ca35efde2067cbd4",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b93b4e9b527904aadf52dba6ca35efde2067cbd4",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1710695816,
"narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "614b4613980a522ba49f0d194531beddbb7220d3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1734649271,
"narHash": "sha256-4EVBRhOjMDuGtMaofAIqzJbg4Ql7Ai0PSeuVZTHjyKQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d70bd19e0a38ad4790d3913bf08fcbfc9eeca507",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks-nix": {
"inputs": {
"flake-compat": [
"lanzaboote",
"flake-compat"
],
"gitignore": "gitignore",
"nixpkgs": [
"lanzaboote",
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1717664902,
"narHash": "sha256-7XfBuLULizXjXfBYy/VV+SpYMHreNRHk9nKMsm1bgb4=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "cc4d466cb1254af050ff7bdf47f6d404a7c646d1",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
"impermanence": "impermanence",
"lanzaboote": "lanzaboote",
"nixpkgs": "nixpkgs",
"nixpkgs-b93b4e9b5": "nixpkgs-b93b4e9b5",
"nixpkgs-unstable": "nixpkgs-unstable",
"zsh-histdb": "zsh-histdb"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": [
"lanzaboote",
"flake-utils"
],
"nixpkgs": [
"lanzaboote",
"nixpkgs"
]
},
"locked": {
"lastModified": 1717813066,
"narHash": "sha256-wqbRwq3i7g5EHIui0bIi84mdqZ/It1AXBSLJ5tafD28=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "6dc3e45fe4aee36efeed24d64fc68b1f989d5465",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"zsh-histdb": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1,
"narHash": "sha256-TFks1dvPwAXKQeePh9jmxj06ZfXArH1pN9yXVQWeL6w=",
"path": "flakes/zsh-histdb",
"type": "path"
},
"original": {
"path": "flakes/zsh-histdb",
"type": "path"
}
}
},
"root": "root",
"version": 7
}

111
nix/configuration/flake.nix Normal file
View File

@@ -0,0 +1,111 @@
# Build ISO image
# nix build --extra-experimental-features nix-command --extra-experimental-features flakes .#iso.odo
# output: result/iso/nixos.iso
# Run the ISO image
# "$(nix-build '<nixpkgs>' --no-out-link -A 'qemu')/bin/qemu-system-x86_64" \
# -accel kvm \
# -cpu host \
# -smp cores=8 \
# -m 32768 \
# -drive "file=$(nix-build '<nixpkgs>' --no-out-link -A 'OVMF.fd')/FV/OVMF.fd,if=pflash,format=raw,readonly=on" \
# -drive if=pflash,format=raw,file="/tmp/OVMF_VARS.fd" \
# -nic user,hostfwd=tcp::60022-:22 \
# -boot order=d \
# -cdrom "$(readlink -f ./result/iso/nixos.iso)" \
# -display vnc=127.0.0.1:0
#
# doas cp "$(nix-build '<nixpkgs>' --no-out-link -A 'OVMF.fd')/FV/OVMF_VARS.fd" /tmp/OVMF_VARS.fd
# doas "$(nix-build '<nixpkgs>' --no-out-link -A 'qemu')/bin/qemu-system-x86_64" -accel kvm -cpu host -smp cores=8 -m 32768 -drive "file=$(nix-build '<nixpkgs>' --no-out-link -A 'OVMF.fd')/FV/OVMF.fd,if=pflash,format=raw,readonly=on" -drive if=pflash,format=raw,file="/tmp/OVMF_VARS.fd" -nic user,hostfwd=tcp::60022-:22 -boot order=d -cdrom /persist/machine_setup/nix/configuration/result/iso/nixos.iso -display vnc=127.0.0.1:0
# Get a repl for this flake
# nix repl --expr "builtins.getFlake \"$PWD\""
# TODO maybe use `nix eval --raw .#iso.odo.outPath`
# iso.odo.isoName == "nixos.iso"
# full path = <outPath> / iso / <isoName>
{
description = "My system configuration";
inputs = {
impermanence.url = "github:nix-community/impermanence";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-b93b4e9b5.url = "github:NixOS/nixpkgs/b93b4e9b527904aadf52dba6ca35efde2067cbd4";
home-manager.url = "github:nix-community/home-manager/release-24.11";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
lanzaboote = {
url = "github:nix-community/lanzaboote/v0.4.1";
# Optional but recommended to limit the size of your system closure.
inputs.nixpkgs.follows = "nixpkgs";
};
zsh-histdb = {
url = "path:flakes/zsh-histdb";
# Optional but recommended to limit the size of your system closure.
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
nixpkgs-unstable,
nixpkgs-b93b4e9b5,
impermanence,
home-manager,
lanzaboote,
zsh-histdb,
...
}@inputs:
let
base_x86_64_linux = rec {
system = "x86_64-linux";
specialArgs = {
pkgs-b93b4e9b5 = import nixpkgs-b93b4e9b5 {
inherit system;
};
pkgs-unstable = import nixpkgs-unstable {
inherit system;
};
};
modules = [
impermanence.nixosModules.impermanence
home-manager.nixosModules.home-manager
lanzaboote.nixosModules.lanzaboote
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
}
{ nixpkgs.overlays = [ zsh-histdb.overlays.default ]; }
./configuration.nix
];
};
systems = {
odo = {
main = nixpkgs.lib.nixosSystem (base_x86_64_linux // { });
iso = nixpkgs.lib.nixosSystem (
base_x86_64_linux
// {
modules = base_x86_64_linux.modules ++ [
(nixpkgs + "/nixos/modules/installer/cd-dvd/iso-image.nix")
# TODO: maybe? imports = [ "${modulesPath}/profiles/image-based-appliance.nix" ];
{
isoImage.makeEfiBootable = true;
isoImage.makeUsbBootable = true;
me.buildingIso = true;
}
];
}
);
};
};
in
{
nixosConfigurations.odo = systems.odo.main;
iso.odo = systems.odo.iso.config.system.build.isoImage;
};
}

View File

@@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1735141468,
"narHash": "sha256-VIAjBr1qGcEbmhLwQJD6TABppPMggzOvqFsqkDoMsAY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4005c3ff7505313cbc21081776ad0ce5dfd7a3ce",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View File

@@ -0,0 +1,34 @@
{
description = "A slightly better history for zsh";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs =
{
self,
nixpkgs,
flake-utils,
...
}:
let
out =
system:
let
pkgs = nixpkgs.legacyPackages.${system};
# Maybe pkgs = import nixpkgs { inherit system; }; ?
appliedOverlay = self.overlays.default pkgs pkgs;
in
{
packages = rec {
default = zsh-histdb;
zsh-histdb = appliedOverlay.zsh-histdb;
};
};
in
flake-utils.lib.eachDefaultSystem out
// {
overlays.default = final: prev: {
zsh-histdb = final.callPackage ./package.nix { };
};
};
}

View File

@@ -0,0 +1,29 @@
# unpackPhase
# patchPhase
# configurePhase
# buildPhase
# checkPhase
# installPhase
# fixupPhase
# installCheckPhase
# distPhase
{
stdenv,
pkgs,
sqlite,
...
}:
stdenv.mkDerivation {
name = "zsh-histdb";
src = pkgs.fetchgit {
url = "https://github.com/larkery/zsh-histdb.git";
rev = "90a6c104d0fcc0410d665e148fa7da28c49684eb";
sha256 = "sha256-vtG1poaRVbfb/wKPChk1WpPgDq+7udLqLfYfLqap4Vg=";
};
buildInputs = [ sqlite ];
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/share/zsh/plugins/zsh-histdb
cp -r $src/histdb-* $src/*.zsh $src/db_migrations $out/share/zsh/plugins/zsh-histdb/
'';
}

View File

@@ -0,0 +1,25 @@
{ config, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./disk-config.nix
./optimized_build.nix
./power_management.nix
./screen_brightness.nix
];
# Generate with `head -c4 /dev/urandom | od -A none -t x4`
networking.hostId = "908cbf04";
networking.hostName = "odo"; # Define your hostname.
time.timeZone = "America/New_York";
me.secureBoot.enable = true;
# Early KMS
boot.initrd.kernelModules = [ "amdgpu" ];
# Mount tmpfs at /tmp
boot.tmp.useTmpfs = true;
}

View File

@@ -0,0 +1,121 @@
{
config,
lib,
pkgs,
...
}:
lib.mkIf (!config.me.buildingIso) {
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
ESP = {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [
"umask=0077"
"noatime"
"discard"
];
};
};
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
};
zpool = {
zroot = {
type = "zpool";
# mode = "mirror";
# Workaround: cannot import 'zroot': I/O error in disko tests
options.cachefile = "none";
options = {
ashift = "12";
compatibility = "openzfs-2.2-freebsd";
autotrim = "on";
};
rootFsOptions = {
acltype = "posixacl";
atime = "off";
relatime = "off";
xattr = "sa";
mountpoint = "none";
compression = "lz4";
canmount = "off";
utf8only = "on";
dnodesize = "auto";
normalization = "formD";
};
datasets = {
"linux/nix" = {
type = "zfs_fs";
options.mountpoint = "none";
options = {
encryption = "aes-256-gcm";
keyformat = "passphrase";
# keylocation = "file:///tmp/secret.key";
};
};
"linux/nix/root" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/root@blank$' || zfs snapshot zroot/linux/nix/root@blank";
};
"linux/nix/nix" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/nix";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/nix@blank$' || zfs snapshot zroot/linux/nix/nix@blank";
options = {
recordsize = "16MiB";
compression = "zstd-19";
};
};
"linux/nix/home" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/home";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/home@blank$' || zfs snapshot zroot/linux/nix/home@blank";
};
"linux/nix/persist" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/persist";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/persist@blank$' || zfs snapshot zroot/linux/nix/persist@blank";
};
"linux/nix/state" = {
type = "zfs_fs";
options.mountpoint = "legacy";
mountpoint = "/state";
postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/state@blank$' || zfs snapshot zroot/linux/nix/state@blank";
};
};
};
};
};
# Make sure all persistent volumes are marked as neededForBoot
#
# Also mounts /home so it is mounted before the user home directories are created.
fileSystems."/persist".neededForBoot = true;
fileSystems."/state".neededForBoot = true;
fileSystems."/home".neededForBoot = true;
}

View File

@@ -0,0 +1,36 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"nvme"
"xhci_pci"
"thunderbolt"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp58s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@@ -0,0 +1,51 @@
{
config,
lib,
pkgs,
pkgs-unstable,
...
}:
{
imports = [ ];
nix.settings.system-features = lib.mkForce [
"gccarch-znver4"
"gccarch-skylake"
# "gccarch-alderlake" missing pkgwait
"gccarch-x86-64-v3"
"benchmark"
"big-parallel"
"kvm"
"nixos-test"
];
# nixpkgs.hostPlatform = {
# gcc.arch = "znver4";
# gcc.tune = "znver4";
# system = "x86_64-linux";
# };
nixpkgs.overlays = [
(
self: super:
let
optimizeWithFlags =
pkg: flags:
pkg.overrideAttrs (old: {
NIX_CFLAGS_COMPILE = [ (old.NIX_CFLAGS_COMPILE or "") ] ++ flags;
});
in
{
linux_znver4 = optimizeWithFlags super.linux_zen [
"-march=znver4"
"-mtune=znver4"
];
}
)
(final: prev: {
linux-firmware = pkgs-unstable.linux-firmware;
})
];
boot.kernelPackages = lib.mkIf (!config.me.buildingIso) (pkgs.linuxPackagesFor pkgs.linux_znver4);
}

View File

@@ -0,0 +1,49 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
environment.systemPackages = with pkgs; [
powertop
];
# amdgpu.abmlevel=3 :: Automatically reduce screen brightness but tweak colors to compensate for power reduction.
# pcie_aspm=force pcie_aspm.policy=powersupersave :: Enable PCIe active state power management for power reduction.
# nowatchdog :: Disable watchdog for power savings (related to disable_sp5100_watchdog above).
# amd_pstate=passive :: Fully automated hardware pstate control.
# amd_pstate=active :: Same as passive except we can set the energy performance preference (EPP) to suggest how much we prefer performance or energy efficiency.
# amd_pstate=guided :: Same as passive except we can set upper and lower frequency bounds.
# amdgpu.dcdebugmask=0x10 :: Allegedly disables Panel Replay from https://community.frame.work/t/tracking-freezing-arch-linux-amd/39495/32
boot.kernelParams = [
"amdgpu.abmlevel=3"
"pcie_aspm=force"
"pcie_aspm.policy=powersupersave"
"nowatchdog"
"amdgpu.dcdebugmask=0x10"
];
systemd.tmpfiles.rules = [
"w- /sys/firmware/acpi/platform_profile - - - - low-power"
"w- /sys/devices/system/cpu/cpufreq/policy0/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy1/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy2/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy3/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy4/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy5/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy6/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy7/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy8/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy9/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy10/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy11/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy12/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy13/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy14/energy_performance_preference - - - - power"
"w- /sys/devices/system/cpu/cpufreq/policy15/energy_performance_preference - - - - power"
];
}

View File

@@ -0,0 +1,14 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
systemd.tmpfiles.rules = [
"w- /sys/class/backlight/amdgpu_bl1/brightness - - - - 85"
];
}

View File

@@ -0,0 +1,24 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
environment.systemPackages = with pkgs; [
alacritty
xdg-utils # for xdg-open
];
home-manager.users.talexander =
{ pkgs, ... }:
{
home.file.".config/alacritty/alacritty.toml" = {
source = ./files/alacritty.toml;
};
};
}

View File

@@ -0,0 +1,44 @@
[colors]
draw_bold_text_with_bright_colors = true
indexed_colors = []
[colors.bright]
black = "0x666666"
blue = "0x7aa6da"
cyan = "0x54ced6"
green = "0x9ec400"
magenta = "0xb77ee0"
red = "0xff3334"
white = "0xffffff"
yellow = "0xe7c547"
[colors.normal]
black = "0x000000"
blue = "0x7aa6da"
cyan = "0x70c0ba"
green = "0xb9ca4a"
magenta = "0xc397d8"
red = "0xd54e53"
white = "0xeaeaea"
yellow = "0xe6c547"
[colors.primary]
background = "0x000000"
foreground = "0xeaeaea"
[font]
size = 11.0
[[hints.enabled]]
command = "xdg-open"
post_processing = true
regex = "(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)[^\u0000-\u001F\u007F-<>\"\\s{-}\\^⟨⟩`]+"
[hints.enabled.mouse]
enabled = false
mods = "None"
[scrolling]
history = 10000
# Lines moved per scroll.
multiplier = 3

View File

@@ -0,0 +1,11 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
}

View File

@@ -0,0 +1,95 @@
# ISO does not work with systemd initrd yet https://github.com/NixOS/nixpkgs/pull/291750
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
options = {
me.secureBoot = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Enable to use secure boot.
'';
};
};
};
config = lib.mkMerge [
(lib.mkIf (!config.me.buildingIso) {
boot.loader.grub.enable = false;
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
# TODO: make not write bootx64.efi
boot.loader.efi.canTouchEfiVariables = false;
# Automatically delete old generations
boot.loader.systemd-boot.configurationLimit = 3;
# Check what will be lost with `zfs diff zroot/linux/root@blank`
boot.initrd.systemd.enable = lib.mkDefault true;
boot.initrd.systemd.services.zfs-rollback = {
description = "Rollback ZFS root dataset to blank snapshot";
wantedBy = [
"initrd.target"
];
after = [
"zfs-import-zroot.service"
];
before = [
"sysroot.mount"
];
path = with pkgs; [
zfs
];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = ''
zfs rollback -r zroot/linux/nix/root@blank
zfs rollback -r zroot/linux/nix/home@blank
echo "rollback complete"
'';
};
# boot.loader.systemd-boot.extraEntries = {
# "windows.conf" = ''
# title Windows
# efi /EFI/Microsoft/Boot/bootmgfw.efi
# options root=PARTUUID=17e325bf-a378-4d1d-be6a-f6df5476f0fa
# '';
# };
})
(lib.mkIf (config.me.secureBoot.enable) {
# For debugging and troubleshooting Secure Boot.
environment.systemPackages = with pkgs; [
sbctl
];
boot.loader.systemd-boot.enable = lib.mkForce false;
boot.lanzaboote = {
enable = true;
pkiBundle = "/etc/secureboot";
};
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
directories = [
"/etc/secureboot" # Secure Boot Keys
];
};
})
];
}
# efibootmgr -c -d /dev/sda -p 1 -L NixOS-boot -l '\EFI\NixOS-boot\grubx64.efi'
# Text-only:
# sudo cp "$(nix-build '<nixpkgs>' --no-out-link -A 'refind')/share/refind/refind_x64.efi" /boot/EFI/boot/bootx64.efi
# Full graphics:
# $ sudo nix-shell -p refind efibootmgr
# $ refind-install

View File

@@ -0,0 +1,14 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
environment.systemPackages = with pkgs; [
bsnes-hd
];
}

View File

@@ -0,0 +1,53 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
# TODO: Read https://bbs.archlinux.org/viewtopic.php?pid=2209507#p2209507 and apply desired settings.
environment.systemPackages = with pkgs; [
(chromium.override { enableWideVine = true; })
];
nixpkgs.config.allowUnfreePredicate =
pkg:
builtins.elem (lib.getName pkg) [
"chromium"
"chromium-unwrapped"
"widevine-cdm"
];
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
directories = [
{
directory = ".config/chromium";
user = "talexander";
group = "talexander";
mode = "0700";
}
];
};
};
environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
directories = [
{
directory = ".cache/chromium";
user = "talexander";
group = "talexander";
mode = "0700";
}
];
};
};
nixpkgs.config.chromium.commandLineArgs = "--enable-features=Vulkan";
}

View File

@@ -0,0 +1,39 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
virtualisation.docker.enable = true;
virtualisation.docker.rootless = {
enable = true;
setSocketVariable = true;
};
environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
directories = [
{
directory = "/var/lib/docker";
user = "root";
group = "root";
mode = "0740";
}
];
users.talexander = {
directories = [
{
directory = ".local/share/docker";
user = "talexander";
group = "talexander";
mode = "0740";
}
];
};
};
}

View File

@@ -0,0 +1,81 @@
{
config,
lib,
pkgs,
...
}:
let
plainmacs = pkgs.writeShellScriptBin "plainmacs" ''
INIT_SCRIPT=$(cat <<EOF
(progn
(setq make-backup-files nil auto-save-default nil create-lockfiles nil)
(load-theme 'tango-dark t)
(set-face-attribute 'default nil :background "black")
;; Bright yellow highlighting for selected region
(set-face-attribute 'region nil :background "#ffff50" :foreground "black")
;; Bright green cursor to distinguish from yellow region
(set-cursor-color "#ccff66")
;; Hightlight the current line
(set-face-attribute 'line-number-current-line nil :foreground "white")
;; Set default font
(set-face-attribute 'default nil :height 100 :width 'regular :weight 'regular :family "Cascadia Mono")
;; Set fallback font for unicode glyphs
(when (display-graphic-p)
(set-fontset-font "fontset-default" nil (font-spec :name "Noto Color Emoji")))
(menu-bar-mode -1)
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
(when ( fboundp 'scroll-bar-mode)
(scroll-bar-mode -1))
(pixel-scroll-precision-mode)
(setq frame-resize-pixelwise t)
)
EOF
)
exec ${pkgs.emacs29-pgtk}/bin/emacs -q --eval "$INIT_SCRIPT" "''${@}"
'';
e_shorthand = pkgs.writeShellScriptBin "e" ''
exec ${pkgs.emacs29-pgtk}/bin/emacs "''${@}"
'';
in
{
imports = [ ];
environment.systemPackages = with pkgs; [
plainmacs
e_shorthand
emacs29-pgtk
clang # To compile tree-sitter grammars
nixd # nix language server
nixfmt-rfc-style # auto-formatting nix files through nixd
];
home-manager.users.talexander =
{ pkgs, ... }:
{
home.file.".config/emacs" = {
source = ./files/emacs;
recursive = true;
};
};
environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
directories = [
".config/emacs/eln-cache" # Installed packages
".config/emacs/elpa" # Installed packages
".config/emacs/private" # For recentf
".config/emacs/tree-sitter" # Compiled tree-sitter grammars
];
files = [
".config/emacs/history" # For savehist
".config/emacs/.last-package-update-day" # For use-package
];
};
};
environment.variables.EDITOR = "${plainmacs}/bin/plainmacs";
}

View File

@@ -0,0 +1,25 @@
(setq gc-cons-threshold (* 128 1024 1024)) ;; 128MiB Increase garbage collection threshold for performance (default 800000)
;; Increase amount of data read from processes, default 4k
(when (version<= "27.0" emacs-version)
(setq read-process-output-max (* 10 1024 1024)) ;; 10MiB
)
;; Suppress warnings
(setq byte-compile-warnings '(not obsolete))
(setq warning-suppress-log-types '((comp) (bytecomp)))
(setq native-comp-async-report-warnings-errors 'silent)
;; Set up default visual settings
(setq frame-resize-pixelwise t)
;; Disable toolbar & menubar
(menu-bar-mode -1)
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
(when (display-graphic-p)
(context-menu-mode +1))
(setq default-frame-alist '((fullscreen . maximized)
(vertical-scroll-bars . nil)
(horizontal-scroll-bars . nil)
;; Set dark colors in early-init to prevent flashes of white.
(background-color . "#000000")))

View File

@@ -0,0 +1,86 @@
(use-package diminish)
;; Eglot recommends pulling the latest of the standard libraries it
;; uses from ELPA if you're not tracking the current.config/emacsevelopment
;; branch.
(use-package xref
:pin gnu
)
(use-package eldoc
:pin gnu
:diminish
)
;; Other packages
(use-package emacs
:config
(setq enable-recursive-minibuffers t)
;; Filter the M-x list base on the current mode
(setq read-extended-command-predicate #'command-completion-default-include-p)
;; Enable triggering completion with the tab key.
(setq tab-always-indent 'complete)
)
(use-package dashboard
:config
(dashboard-setup-startup-hook))
(when (version<= "26.0.50" emacs-version )
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(add-hook 'prog-mode-hook 'column-number-mode)
)
;; Display a horizontal line instead of ^L for page break characters
(use-package page-break-lines
:diminish
:config
(global-page-break-lines-mode +1)
)
(use-package recentf
;; This is an emacs built-in but we're pulling the latest version
:config
(setq recentf-max-saved-items 100)
(setq recentf-save-file (recentf-expand-file-name "~/.config/emacs/private/cache/recentf"))
(recentf-mode 1))
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
;; This is an emacs built-in but we're pulling the latest version
:config
(savehist-mode))
(use-package which-key
:diminish
:config
(which-key-mode))
(use-package windmove
:config
(windmove-default-keybindings))
(setq tramp-default-method "ssh")
(use-package nginx-mode
:mode (
("headers\\.include\\'" . nginx-mode)
)
:config
(setq nginx-indent-level 4))
(use-package systemd
:mode
(("\\.service\\'" . systemd-mode)
("\\.timer\\'" . systemd-mode))
)
(use-package pkgbuild-mode
:mode
(("PKGBUILD\\'" . pkgbuild-mode))
)
(provide 'base-extensions)

View File

@@ -0,0 +1,127 @@
;; ========== Function to reload current file =================
(defun reload-file ()
"Revert buffer without confirmation."
(interactive)
(revert-buffer :ignore-auto :noconfirm))
;; ===========================================================
;; ============= Run commands ================================
(defun run-command-on-buffer (cmd &rest args)
"Run a command using the current buffer as stdin and replacing its contents if the command succeeds with the stdout from the command. This is useful for code formatters."
(let (
(stdout-buffer (generate-new-buffer "tmp-stdout" t))
(full-cmd (append '(call-process-region nil nil cmd nil stdout-buffer nil) args))
)
(unwind-protect
(let ((exit-status (eval full-cmd)))
(if (eq exit-status 0)
(save-excursion
(replace-buffer-contents stdout-buffer)
)
(message "FAILED running command on buffer %s" (append (list cmd) args))
)
)
(kill-buffer stdout-buffer)
)
)
)
(defun run-command-in-directory (dir cmd &rest args)
"Run a command in the specified directory. If the directory is nil, the directory of the file is used. The stdout result is trimmed of whitespace and returned."
(let (
(default-directory (or dir default-directory))
(stdout-buffer (generate-new-buffer "tmp-stdout" t))
(full-cmd (append '(call-process cmd nil (list stdout-buffer nil) nil) args))
)
(unwind-protect
(let ((exit-status (condition-case nil (eval full-cmd) (file-missing nil))))
(if (eq exit-status 0)
(progn
(with-current-buffer stdout-buffer
(string-trim (buffer-string))
)
)
)
)
(kill-buffer stdout-buffer)
)
)
)
(defun load-directory (dir)
(let ((load-it (lambda (f)
(load-file (concat (file-name-as-directory dir) f)))
))
(mapc load-it (directory-files dir nil "\\.el$"))))
(defun generate-vc-link ()
(interactive)
(or
(generate-github-link)
(generate-source-hut-link)
)
)
(defun generate-github-link ()
"Generate a permalink to the current line."
(interactive)
(let (
(current-rev (vc-working-revision buffer-file-name))
(line-number (line-number-at-pos))
(repository-url (vc-git-repository-url buffer-file-name))
(relative-path (file-relative-name buffer-file-name (vc-root-dir)))
)
(save-match-data
(and (string-match "\\(git@github\.com:\\|https://github\.com/\\)\\([^/]+\\)/\\([^.]+\\).git" repository-url)
(let* (
(gh-org (match-string 2 repository-url))
(gh-repo (match-string 3 repository-url))
(full-url (format "https://github.com/%s/%s/blob/%s/%s?plain=1#L%s" gh-org gh-repo current-rev relative-path line-number))
)
(message "%s" full-url)
(kill-new full-url)
t
)
)
)
)
)
(defun generate-source-hut-link ()
"Generate a permalink to the current line."
(interactive)
(let (
(current-rev (vc-working-revision buffer-file-name))
(line-number (line-number-at-pos))
(repository-url (vc-git-repository-url buffer-file-name))
(relative-path (file-relative-name buffer-file-name (vc-root-dir)))
)
(message "Using repo url %s" repository-url)
(save-match-data
(and (string-match "https://git.sr.ht/\\([^/]+\\)/\\([^/]+\\)" repository-url)
(let* (
(sh-org (match-string 1 repository-url))
(sh-repo (match-string 2 repository-url))
(full-url (format "https://git.sr.ht/%s/%s/tree/%s/%s#L%s" sh-org sh-repo current-rev relative-path line-number))
)
(message "%s" full-url)
(kill-new full-url)
t
)
)
)
)
)
(defmacro when-linux (&rest body)
"Execute only when on Linux."
(declare (indent defun))
`(when (eq system-type 'gnu/linux) ,@body))
(defmacro when-freebsd (&rest body)
"Execute only when on FreeBSD."
(declare (indent defun))
`(when (eq system-type 'berkeley-unix) ,@body))
(provide 'base-functions)

View File

@@ -0,0 +1,12 @@
;; Add your keys here, as such
;; Disable the suspend frame hotkeys
(global-unset-key (kbd "C-z"))
(global-unset-key (kbd "C-x C-z"))
;; dabbrev-expand. Seems to be some sort of dumb-expand. Accidentally hitting it when trying to use M-?
(global-unset-key (kbd "M-/"))
(global-set-key (kbd "C-x g l") 'generate-vc-link)
(provide 'base-global-keys)

View File

@@ -0,0 +1,15 @@
;; Set theme
(load-theme 'tango-dark t)
(set-face-attribute 'default nil :background "black")
;; Bright yellow highlighting for selected region
(set-face-attribute 'region nil :background "#ffff50" :foreground "black")
;; Bright green cursor to distinguish from yellow region
(set-face-attribute 'cursor nil :background "#ccff66")
;; Hightlight the current line
(set-face-attribute 'line-number-current-line nil :foreground "white")
;; Set default font
(set-face-attribute 'default nil :height 100 :width 'regular :weight 'regular :family "Cascadia Mono")
;; Set fallback font for unicode glyphs
(set-fontset-font t 'emoji (font-spec :name "Noto Color Emoji") nil 'prepend)
(provide 'base-theme)

View File

@@ -0,0 +1,94 @@
(package-initialize)
(use-package use-package)
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/")
)
(use-package auto-package-update
:ensure t
:config
(setq auto-package-update-delete-old-versions t
auto-package-update-interval 14)
(auto-package-update-maybe))
(defun assert-directory (p)
(unless (file-exists-p p) (make-directory p t))
p
)
(defconst private-dir (expand-file-name "private" user-emacs-directory))
(defconst temp-dir (format "%s/cache" private-dir)
"Hostname-based elisp temp directories")
(assert-directory (concat temp-dir "/auto-save-list/"))
(setq autoload-directory (concat user-emacs-directory (file-name-as-directory "elisp") (file-name-as-directory "autoload")))
(add-to-list 'load-path (assert-directory autoload-directory))
(setq-default
;; Disable backup files and lockfiles
make-backup-files nil
auto-save-default nil
create-lockfiles nil
;; Unless otherwise specified, always install packages if they are absent.
use-package-always-ensure t
;; Point custom-file at /dev/null so emacs does not write any settings to my dotfiles.
custom-file "/dev/null"
;; Don't pop up a small window at the bottom of emacs at launch.
inhibit-startup-screen t
inhibit-startup-message t
;; Don't show the list of buffers when opening many files.
inhibit-startup-buffer-menu t
;; Give the scratch buffer a clean slate.
initial-major-mode 'fundamental-mode
initial-scratch-message nil
;; Send prompts to mini-buffer not the GUI
use-dialog-box nil
;; End files with line break
require-final-newline t
;; Use spaces, not tabs
indent-tabs-mode nil
;; Use a better frame title
frame-title-format '("" invocation-name ": "(:eval (if (buffer-file-name)
(abbreviate-file-name (buffer-file-name))
"%b")))
;; Use 'y' or 'n' instead of 'yes' or 'no'
use-short-answers t
;; Natively compile packages
package-native-compile t
;; Confirm when opening a file that does not exist
confirm-nonexistent-file-or-buffer t
;; Do not require double space to end a sentence.
sentence-end-double-space nil
;; Show trailing whitespace
show-trailing-whitespace t
;; Remove the line when killing it with ctrl-k
kill-whole-line t
)
;; (setq-default fringes-outside-margins t)
;; Per-pixel scrolling instead of per-line
(pixel-scroll-precision-mode)
;; Typed text replaces selection
(delete-selection-mode)
;; Delete trailing whitespace before save
(add-hook 'before-save-hook 'delete-trailing-whitespace)
;; If the underlying file changes, reload it automatically. This is useful for moving around in git without confusing language servers.
(setopt auto-revert-avoid-polling t)
(setopt auto-revert-interval 5)
(setopt auto-revert-check-vc-info t)
(global-auto-revert-mode)
;;;;; Performance
;; Run garbage collect when emacs is idle
(run-with-idle-timer 5 t (lambda () (garbage-collect)))
(add-function :after after-focus-change-function
(lambda ()
(unless (frame-focus-state)
(garbage-collect))))
(provide 'base)

View File

@@ -0,0 +1,47 @@
(use-package eglot
:pin gnu
:commands (eglot eglot-ensure)
:bind (:map eglot-mode-map
;; M-.
;; ([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
;; M-?
;; ([remap xref-find-references] . lsp-ui-peek-find-references)
("C-c C-a" . eglot-code-actions)
;; C-M-.
([remap xref-find-apropos] . #'consult-eglot-symbols)
)
;; :hook (
;; (eglot-managed-mode . (lambda ()
;; (when (eglot-managed-p)
;; (corfu-mode +1)
;; )
;; ))
;; )
:config
(fset #'jsonrpc--log-event #'ignore) ;; Disable logging LSP traffic for performance boost
(set-face-attribute 'eglot-highlight-symbol-face nil :background "#0291a1" :foreground "black")
(set-face-attribute 'eglot-mode-line nil :inherit 'mode-line :bold nil)
:custom
(eglot-autoshutdown t "Shut down server when last buffer is killed.")
(eglot-sync-connect 0 "Don't block on language server starting.")
(eglot-send-changes-idle-time 0.1)
)
(use-package consult-eglot
:commands (consult-eglot-symbols)
)
(use-package company
:after eglot
:hook (eglot-managed-mode . company-mode)
:config
(setq company-backends '((company-capf)))
(setq company-idle-delay 0) ;; Default 0.2
)
;; (use-package company-box
;; :hook (company-mode . company-box-mode))
(provide 'common-lsp)

View File

@@ -0,0 +1,16 @@
(require 'util-tree-sitter)
(use-package bash-ts-mode
:ensure nil
:commands (bash-ts-mode)
:hook (
(bash-ts-mode . (lambda ()
(flymake-mode +1)
)))
:init
(add-to-list 'major-mode-remap-alist '(sh-mode . bash-ts-mode))
(add-to-list 'treesit-language-source-alist '(bash "https://github.com/tree-sitter/tree-sitter-bash"))
(unless (treesit-ready-p 'bash) (treesit-install-language-grammar 'bash))
)
(provide 'lang-bash)

View File

@@ -0,0 +1,49 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(defun locate-compile-commands-file ()
"See if compile_commands.json exists."
;; This can be generated by prefixing the make command with `intercept-build15 --append`
(let ((compile-commands-file (locate-dominating-file (buffer-file-name) "compile_commands.json")))
compile-commands-file
)
)
(defun activate-c-eglot ()
"Activate eglot for the c family of languages."
(when (locate-compile-commands-file)
(eglot-ensure)
(defclass my/eglot-c (eglot-lsp-server) ()
:documentation
"Own eglot server class.")
(add-to-list 'eglot-server-programs
'(c-ts-mode . (my/eglot-c "/usr/local/bin/clangd15")))
(add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
)
)
(use-package c-mode
:mode (
("\\.c\\'" . c-ts-mode)
("\\.h\\'" . c-or-c++-ts-mode)
)
:commands (c-mode c-ts-mode)
:pin manual
:ensure nil
:hook (
(c-ts-mode . (lambda ()
(activate-c-eglot)
))
)
:init
(add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode))
(add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode))
(add-to-list 'major-mode-remap-alist '(c-or-c++-mode . c-or-c++-ts-mode))
(add-to-list 'treesit-language-source-alist '(c "https://github.com/tree-sitter/tree-sitter-c"))
(add-to-list 'treesit-language-source-alist '(cpp "https://github.com/tree-sitter/tree-sitter-cpp"))
(unless (treesit-ready-p 'c) (treesit-install-language-grammar 'c))
(unless (treesit-ready-p 'cpp) (treesit-install-language-grammar 'cpp))
)
(provide 'lang-c)

View File

@@ -0,0 +1,13 @@
(use-package dockerfile-ts-mode
:pin manual
:mode (
("Dockerfile\\'" . dockerfile-ts-mode)
)
:commands (dockerfile-mode dockerfile-ts-mode)
:init
(add-to-list 'major-mode-remap-alist '(dockerfile-mode . dockerfile-ts-mode))
(add-to-list 'treesit-language-source-alist '(dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile"))
(unless (treesit-ready-p 'dockerfile) (treesit-install-language-grammar 'dockerfile))
)
(provide 'lang-dockerfile)

View File

@@ -0,0 +1,33 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(use-package go-ts-mode
:pin manual
:mode (
("\\.go\\'" . go-ts-mode)
("/go\\.mod\\'" . go-mod-ts-mode)
)
:commands (go-ts-mode go-mod-ts-mode)
:hook (
(go-ts-mode . (lambda ()
(when-linux
(eglot-ensure)
)
))
(go-mod-ts-mode . (lambda ()
(when-linux
(eglot-ensure)
)
))
;; (before-save . lsp-format-buffer)
)
:init
(add-to-list 'treesit-language-source-alist '(go "https://github.com/tree-sitter/tree-sitter-go"))
(add-to-list 'treesit-language-source-alist '(gomod "https://github.com/camdencheek/tree-sitter-go-mod"))
(unless (treesit-ready-p 'go) (treesit-install-language-grammar 'go))
(unless (treesit-ready-p 'gomod) (treesit-install-language-grammar 'gomod))
)
(provide 'lang-go)

View File

@@ -0,0 +1,177 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(use-package json-ts-mode
:ensure nil
:pin manual
:mode (
("\\.json\\'" . json-ts-mode)
)
:commands (json-ts-mode)
:hook (
(json-ts-mode . (lambda ()
(add-hook 'before-save-hook 'json-fmt-jq nil 'local)
))
)
:init
(add-to-list 'treesit-language-source-alist '(json "https://github.com/tree-sitter/tree-sitter-json"))
(unless (treesit-ready-p 'json) (treesit-install-language-grammar 'json))
)
(defun json-fmt-jq ()
"Run jq."
(run-command-on-buffer "jq" "--monochrome-output" ".")
)
(defun configure-typescript-language-server ()
"Configures the typescript language server."
(when-linux
;; Either initializationOptions or workspace/didChangeConfiguration works.
(setq eglot-workspace-configuration
(list (cons ':typescript '(:inlayHints (:includeInlayParameterNameHints
"all"
:includeInlayParameterNameHintsWhenArgumentMatchesName
t
:includeInlayFunctionParameterTypeHints
t
:includeInlayVariableTypeHints
t
:includeInlayVariableTypeHintsWhenTypeMatchesName
t
:includeInlayPRopertyDeclarationTypeHints
t
:includeInlayFunctionLikeReturnTypeHints
t
:includeInlayEnumMemberValueHints
t)))))
(eglot-ensure)
;; (defclass my/eglot-typescript (eglot-lsp-server) ()
;; :documentation
;; "Own eglot server class.")
;; (add-to-list 'eglot-server-programs
;; '((js-mode js-ts-mode tsx-ts-mode typescript-ts-mode typescript-mode) . (my/eglot-typescript "typescript-language-server" "--stdio" :initializationOptions (:preferences (:includeInlayParameterNameHints
;; "all"
;; :includeInlayParameterNameHintsWhenArgumentMatchesName
;; t
;; :includeInlayFunctionParameterTypeHints
;; t
;; :includeInlayVariableTypeHints
;; t
;; :includeInlayVariableTypeHintsWhenTypeMatchesName
;; t
;; :includeInlayPRopertyDeclarationTypeHints
;; t
;; :includeInlayFunctionLikeReturnTypeHints
;; t
;; :includeInlayEnumMemberValueHints
;; t)))))
)
)
(use-package tsx-ts-mode
:ensure nil
:pin manual
:mode (
("\\.tsx\\'" . tsx-ts-mode)
)
:commands (tsx-ts-mode)
:hook (
(tsx-ts-mode . (lambda ()
(when-linux
(configure-typescript-language-server)
)
))
)
:init
(add-to-list 'treesit-language-source-alist '(tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")))
(unless (treesit-ready-p 'tsx) (treesit-install-language-grammar 'tsx))
)
(use-package typescript-ts-mode
:ensure nil
:pin manual
:mode (
("\\.ts\\'" . typescript-ts-mode)
)
:commands (typescript-ts-mode)
:hook (
(typescript-ts-mode . (lambda ()
(configure-typescript-language-server)
))
)
:init
(add-to-list 'treesit-language-source-alist '(typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")))
(unless (treesit-ready-p 'typescript) (treesit-install-language-grammar 'typescript))
)
(use-package js-ts-mode
:ensure nil
:pin manual
:mode (
("\\.js\\'" . js-ts-mode)
)
:commands (js-ts-mode)
:hook (
(js-ts-mode . (lambda ()
(when-linux
(eglot-ensure)
)
))
)
:init
(add-to-list 'treesit-language-source-alist '(javascript . ("https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")))
(unless (treesit-ready-p 'javascript) (treesit-install-language-grammar 'javascript))
)
(defun prettier-fmt ()
"Run prettier."
(run-command-on-buffer "prettier" "--stdin-filepath" buffer-file-name)
)
(use-package css-ts-mode
:ensure nil
:pin manual
:mode (
("\\.css\\'" . css-ts-mode)
)
:commands (css-ts-mode)
:custom (css-indent-offset 2)
:init
(add-to-list 'treesit-language-source-alist '(css "https://github.com/tree-sitter/tree-sitter-css"))
(unless (treesit-ready-p 'css) (treesit-install-language-grammar 'css))
:hook (
(css-ts-mode . (lambda ()
(eglot-ensure)
(defclass my/eglot-css (eglot-lsp-server) ()
:documentation
"Own eglot server class.")
(add-to-list 'eglot-server-programs
'(css-ts-mode . (my/eglot-css "vscode-css-language-server" "--stdio")))
;; (add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
(add-hook 'before-save-hook 'prettier-fmt nil 'local)
))
)
)
(use-package web-mode
:mode (("\\.dust\\'" . dust-mode)
)
:config
(setq web-mode-markup-indent-offset 2)
(setq web-mode-enable-current-element-highlight t)
)
;; Define a custom mode for dust so that org-mode handle #+BEGIN_SRC dust blocks
(define-derived-mode dust-mode web-mode "WebDust"
"Major mode for editing dust templates in web-mode."
(web-mode)
(web-mode-set-engine "dust")
;; (setq web-mode-content-type "html")
)
(provide 'lang-javascript)

View File

@@ -0,0 +1,21 @@
(defun lua-format-buffer ()
"Run stylua."
(interactive)
(run-command-on-buffer "stylua" "--search-parent-directories" "--stdin-filepath" buffer-file-name "-")
)
(use-package lua-mode
:mode
(("\\.lua\\'" . lua-mode)
("\\.rockspec\\'" . lua-mode))
:commands lua-mode
:hook (
(lua-mode . (lambda ()
(add-hook 'before-save-hook 'lua-format-buffer nil 'local)
))
)
:custom
(lua-indent-level 4)
)
(provide 'lang-lua)

View File

@@ -0,0 +1,14 @@
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (setq markdown-command "multimarkdown"))
;; For code block editing
(use-package edit-indirect
:commands (edit-indirect-region edit-indirect-save edit-indirect-abort edit-indirect-commit edit-indirect-display-active-buffer)
)
(provide 'lang-markdown)

View File

@@ -0,0 +1,22 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(use-package nix-mode
:mode (("\\.nix\\'" . nix-mode)
)
:commands nix-mode
:hook (
(nix-mode . (lambda ()
(eglot-ensure)
(defclass my/eglot-nix (eglot-lsp-server) ()
:documentation
"Own eglot server class.")
(add-to-list 'eglot-server-programs
'(nix-mode . (my/eglot-nix "nixd")))
(add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
))
)
)
(provide 'lang-nix)

View File

@@ -0,0 +1,81 @@
(use-package org
:ensure nil
:commands org-mode
:bind (
("C-c l" . org-store-link)
("C-c a" . org-agenda)
("C--" . org-timestamp-down)
("C-=" . org-timestamp-up)
)
:hook (
(org-mode . (lambda ()
(org-indent-mode +1)
))
)
:config
(require 'org-tempo)
(setq org-export-latex-listings t)
(setq org-startup-truncated nil)
(setq org-startup-folded nil)
(setq org-src-fontify-natively t
org-src-tab-acts-natively t
org-confirm-babel-evaluate nil
)
;; Show the full source of org-mode links instead of condensing them. I.E. render "[[foo]]" instead of "foo"
(setq org-descriptive-links nil)
;; Only interpret _ and ^ and sub and superscripts if they're of the form _{subscript} and ^{superscript}
(setq org-export-with-sub-superscripts '{})
;; Don't include a "validate" link at the bottom of html export
(setq org-html-validation-link nil)
(setq org-latex-listings 'minted)
(setq org-latex-minted-options '(("breaklines" "true")
("breakanywhere" "true")
("bgcolor" "mintedbg") ("frame" "single") ("framesep" "6pt") ("fontsize" "\\footnotesize")))
;; TODO: There is an option to set the compiler, could be better than manually doing this here https://orgmode.org/manual/LaTeX_002fPDF-export-commands.html
;; (setq org-latex-compiler "lualatex")
(setq org-latex-pdf-process
'("lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
(add-to-list 'org-latex-packages-alist '("cache=false" "minted"))
(add-to-list 'org-latex-packages-alist '("" "svg"))
(add-to-list 'org-latex-packages-alist '("margin=2cm" "geometry" nil))
(add-to-list 'org-src-lang-modes '("dot" . "graphviz-dot"))
(org-babel-do-load-languages 'org-babel-load-languages
'((shell . t)
(js . t)
(emacs-lisp . t)
(python . t)
(dot . t)
(css . t)
(gnuplot . t)
(sqlite . t)
))
(require 'color)
(let ((bg (face-attribute 'default :background)))
(custom-set-faces
`(org-block ((t (:inherit default :background ,(color-lighten-name bg 15) :extend ,t))))
`(org-block-begin-line ((t (:inherit default :background ,"#472300" :extend ,t))))
`(org-block-end-line ((t (:inherit default :background ,"#472300" :extend ,t))))
))
)
(use-package org-bullets
:commands org-bullets-mode
:hook (org-mode . org-bullets-mode)
)
(use-package gnuplot-mode)
(use-package gnuplot)
(use-package graphviz-dot-mode)
(provide 'lang-org)

View File

@@ -0,0 +1,92 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(defun python-backspace (arg)
"Special handling of python backspace."
(interactive "*p")
(if mark-active
(backward-delete-char-untabify arg)
(python-indent-dedent-line-backspace arg)
)
)
(defun locate-venv-poetry ()
"Find a poetry venv."
(run-command-in-directory nil "poetry" "env" "info" "-p")
)
(defun locate-pyproject-directory ()
"Adapt lsp-python-ms for poetry."
(let ((pypoetry-file (locate-dominating-file (buffer-file-name) "pyproject.toml")))
pypoetry-file
)
)
(defun python-fmt ()
"format python."
(python-fmt-black)
(python-fmt-isort)
)
(defun python-fmt-black ()
"Run black."
(run-command-on-buffer "black" "--quiet" "--fast" "-")
)
(defun python-fmt-isort ()
"Run isort."
(run-command-on-buffer "isort" "-")
)
(defun add-poetry-venv-to-path ()
"Add the bin folder in the poetry venv to exec-path."
(let (
(venv-path (locate-venv-poetry))
)
(when venv-path
(make-local-variable 'exec-path)
(add-to-list 'exec-path (concat venv-path "/bin"))
)
)
)
(use-package python
:mode ("\\.py\\'" . python-ts-mode)
:commands (python-mode python-ts-mode)
:pin manual
:hook (
(python-ts-mode . (lambda ()
(when-linux
(when (executable-find "poetry")
(add-poetry-venv-to-path)
(let ((venv (locate-venv-poetry))) (when venv
(setq eglot-workspace-configuration
(list (cons ':python (list ':venvPath venv ':pythonPath (concat venv "/bin/python")))))
))
)
(eglot-ensure)
)
;; (when-freebsd
;; (eglot-ensure)
;; (defclass my/eglot-pylyzer (eglot-lsp-server) ()
;; :documentation
;; "Own eglot server class.")
;; (add-to-list 'eglot-server-programs
;; '(python-ts-mode . (my/eglot-pylyzer "pylyzer" "--server")))
;; )
(add-hook 'before-save-hook 'python-fmt nil 'local)
))
)
:bind ((:map python-ts-mode-map ([backspace] . python-backspace))
)
:init
(add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode))
(add-to-list 'treesit-language-source-alist '(python "https://github.com/tree-sitter/tree-sitter-python"))
(unless (treesit-ready-p 'python) (treesit-install-language-grammar 'python))
)
(provide 'lang-python)

View File

@@ -0,0 +1,92 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(defun locate-rust-analyzer ()
"Find rust-analyzer."
(let ((rust-analyzer-paths (list (locate-rust-analyzer-rustup) (locate-rust-analyzer-ansible-built) (locate-rust-analyzer-in-path))))
(let ((first-non-nil-path (seq-find (lambda (elt) elt) rust-analyzer-paths)))
first-non-nil-path
)
)
)
(defun locate-rust-analyzer-rustup ()
"Find rust-analyzer through rustup."
(run-command-in-directory nil "rustup" "which" "rust-analyzer")
)
(defun locate-rust-analyzer-ansible-built ()
"Find rust-analyzer where the ansible playbook built it."
(let ((rust-analyzer-path "/opt/rust-analyzer/target/release/rust-analyzer"))
(when (file-exists-p rust-analyzer-path)
rust-analyzer-path
)
)
)
(defun locate-rust-analyzer-in-path ()
"Find rust-analyzer in $PATH."
(executable-find "rust-analyzer")
)
(use-package rust-ts-mode
:pin manual
:mode (
("\\.rs\\'" . rust-ts-mode)
)
:commands (rust-ts-mode)
:hook (
(rust-ts-mode . (lambda ()
(eglot-ensure)
;; Disable on-type formatting which was incorrectly injecting parenthesis into my code.
(make-local-variable 'eglot-ignored-server-capabilities)
(add-to-list 'eglot-ignored-server-capabilities :documentOnTypeFormattingProvider)
;; Configure initialization options
(let ((rust-analyzer-command (locate-rust-analyzer)))
(when rust-analyzer-command
;; (add-to-list 'eglot-server-programs `(rust-ts-mode . (,rust-analyzer-command)))
(add-to-list 'eglot-server-programs `(rust-ts-mode . (,rust-analyzer-command :initializationOptions (:imports (:granularity (:enforce t :group "item")
:merge (:glob nil)
:prefix "self")
))))
)
)
(add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
))
)
:init
(add-to-list 'major-mode-remap-alist '(rust-mode . rust-ts-mode))
(add-to-list 'treesit-language-source-alist '(rust "https://github.com/tree-sitter/tree-sitter-rust"))
(unless (treesit-ready-p 'rust) (treesit-install-language-grammar 'rust))
:config
;; Add keybindings for interacting with Cargo
(use-package cargo
:hook (rust-ts-mode . cargo-minor-mode))
)
(use-package toml-ts-mode
:ensure nil
:pin manual
:mode (
("\\.toml\\'" . toml-ts-mode)
)
:commands (toml-ts-mode)
:init
(add-to-list 'treesit-language-source-alist '(toml "https://github.com/tree-sitter/tree-sitter-toml"))
(unless (treesit-ready-p 'toml) (treesit-install-language-grammar 'toml))
)
;; Set additional rust-analyzer settings:
;;
;; (add-to-list 'eglot-server-programs `(rust-ts-mode . (,rust-analyzer-command :initializationOptions (:cargo (:features "all")))))
;;
;; In addition to the above, directory-specific settings can be written to a .dir-locals.el with the contents:
;;
;; (
;; (rust-ts-mode . ((eglot-workspace-configuration
;; . (:rust-analyzer (:cargo (:noDefaultFeatures t :features ["compare" "tracing"]))))
;; ))
;; )
(provide 'lang-rust)

View File

@@ -0,0 +1,38 @@
(require 'common-lsp)
(require 'util-tree-sitter)
(defun terraform-fmt ()
"Run terraform fmt."
(run-command-on-buffer "terraform" "fmt" "-")
)
(use-package hcl-mode
:mode (("\\.hcl\\'" . hcl-mode))
:commands hcl-mode
:custom (hcl-indent-level 2)
:hook (
(hcl-mode . (lambda () (unless (derived-mode-p 'terraform-mode) (add-hook 'before-save-hook 'terraform-fmt nil 'local))))
)
)
(use-package terraform-mode
:mode (("\\.tf\\'" . terraform-mode)
("\\.tfvars\\'" . terraform-mode))
:commands terraform-mode
:custom (terraform-indent-level 2)
:hook (
(terraform-mode . (lambda ()
(eglot-ensure)
(defclass my/eglot-terraform (eglot-lsp-server) ()
:documentation
"Own eglot server class.")
(add-to-list 'eglot-server-programs
'(terraform-mode . (my/eglot-terraform "terraform-ls" "serve")))
(add-hook 'before-save-hook 'eglot-format-buffer nil 'local)
))
)
)
(provide 'lang-terraform)

View File

@@ -0,0 +1,17 @@
(defun xml-fmt ()
"Run xmllint --format."
(run-command-on-buffer "xmllint" "--format" "-")
)
(use-package nxml-mode
:commands (nxml-mode)
:pin manual
:ensure nil
:hook (
(nxml-mode . (lambda ()
(add-hook 'before-save-hook 'xml-fmt nil 'local)
))
)
)
(provide 'lang-xml)

View File

@@ -0,0 +1,27 @@
(defun yaml-format-buffer ()
"Run prettier."
(interactive)
(run-command-on-buffer "prettier" "--stdin-filepath" buffer-file-name)
)
(use-package yaml-ts-mode
:mode
(
("\\.y[a]?ml\\'" . yaml-ts-mode)
("playbook\\.tmp\\'" . yaml-ts-mode)
("environments/[^/]*/group_vars/[^/]*\\'" . yaml-ts-mode)
("environments/[^/]*/host_vars/[^/]*\\'" . yaml-ts-mode)
)
:commands (yaml-ts-mode)
:hook (
(yaml-ts-mode . (lambda ()
(add-hook 'before-save-hook 'yaml-format-buffer nil 'local)
))
)
:init
(add-to-list 'major-mode-remap-alist '(yaml-mode . yaml-ts-mode))
(add-to-list 'treesit-language-source-alist '(yaml "https://github.com/ikatyang/tree-sitter-yaml"))
(unless (treesit-ready-p 'yaml) (treesit-install-language-grammar 'yaml))
)
(provide 'lang-yaml)

View File

@@ -0,0 +1,10 @@
(use-package flymake
:pin manual
:ensure nil
:commands (flymake-mode)
:config
;; Set the text before the brackets for flymake's modeline output to an empty string to make it less verbose.
(setq flymake-mode-line-lighter "")
)
(provide 'util-flymake)

View File

@@ -0,0 +1,16 @@
(use-package treesit
:pin manual
:ensure nil
:commands (treesit-install-language-grammar treesit-ready-p)
:init
(setq treesit-language-source-alist '())
:config
;; Default to the max level of detail in treesitter highlighting. This
;; can be overridden in each language's use-package call with:
;;
;; :custom
;; (treesit-font-lock-level 3)
(setq treesit-font-lock-level 4)
)
(provide 'util-tree-sitter)

View File

@@ -0,0 +1,61 @@
(defun my/minibuffer-delete (arg)
"When looking for files, go up an entire directory with the backspace button if theres no text after the directory."
(interactive "p")
(if minibuffer-completing-file-name
(if (string-match-p ".*/$" (minibuffer-contents))
(vertico-directory-delete-word arg)
(vertico-directory-delete-char arg))
(delete-backward-char arg)))
(use-package vertico
:config
(vertico-mode)
(vertico-mouse-mode)
;; Remove prefix when switching to tilde or root ("/")
(setq file-name-shadow-properties '(invisible t intangible t))
(file-name-shadow-mode +1)
(set-face-attribute 'vertico-current nil :inherit nil :background "#383b01")
:custom
(vertico-count 20)
)
;; Create an ido/ivy-like experience when selecting files.
(use-package vertico-directory
:after vertico
:ensure nil
:bind ( :map vertico-map
("RET" . vertico-directory-enter)
:map minibuffer-local-map
("DEL" . my/minibuffer-delete)
)
)
(use-package consult
:custom
(completion-in-region-function #'consult-completion-in-region)
(xref-show-xrefs-function #'consult-xref)
(xref-show-definitions-function #'consult-xref)
(consult-project-root-function #'deadgrep--project-root)
:bind (
("C-. s" . consult-ripgrep)
("C-s" . consult-line)
("M-g g" . consult-goto-line)
("C-. e" . consult-flymake)
)
)
;; (use-package corfu
;; :commands (corfu-mode global-corfu-mode)
;; :custom
;; (corfu-auto t)
;; )
(use-package marginalia
:config (marginalia-mode))
(use-package orderless
:custom (completion-styles '(orderless)))
(provide 'util-vertico)

View File

@@ -0,0 +1,41 @@
(add-to-list 'load-path (concat user-emacs-directory "elisp"))
(require 'base)
(require 'base-theme)
(require 'base-extensions)
(require 'base-functions)
(require 'base-global-keys)
(require 'util-vertico)
(require 'util-flymake)
(require 'lang-python)
(require 'lang-javascript)
(require 'lang-rust)
(require 'lang-yaml)
(require 'lang-org)
(require 'lang-bash)
(require 'lang-markdown)
(require 'lang-lua)
(require 'lang-terraform)
(require 'lang-go)
(require 'lang-dockerfile)
(require 'lang-c)
(require 'lang-xml)
(require 'lang-nix)
(load-directory autoload-directory)

View File

@@ -0,0 +1,113 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
programs.firefox = {
enable = true;
package = (pkgs.wrapFirefox (pkgs.firefox-unwrapped.override { pipewireSupport = true; }) { });
languagePacks = [ "en-US" ];
preferences = {
# "identity.sync.tokenserver.uri": "https://ffsync.fizz.buzz/token/1.0/sync/1.5";
"media.hardware-video-decoding.force-enabled" = true;
"media.ffmpeg.vaapi.enabled" = true;
"doh-rollout.doorhanger-decision" = "UIDisabled";
"dom.security.https_only_mode" = true;
"dom.security.https_only_mode_ever_enabled" = true;
"extensions.activeThemeID" = "firefox-compact-dark@mozilla.org";
# Disable ads
"extensions.pocket.enabled" = false;
"browser.newtabpage.activity-stream.showSponsored" = false;
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
"browser.newtabpage.activity-stream.feeds.section.topstories" = false;
"browser.newtabpage.pinned" = "[]";
"browser.newtabpage.activity-stream.section.highlights.includePocket" = false;
"browser.topsites.contile.enabled" = false;
# Disable cache when devtools are open.
"devtools.cache.disabled" = true;
# Do not track header.
"privacy.donottrackheader.enabled" = true;
# Tell websites not to share or sell my data.
"privacy.globalprivacycontrol.enabled" = true;
# Disable "studies" (slice testing)
"app.shield.optoutstudies.enabled" = false;
# Disable attribution which is used by advertisers to track you.
"dom.private-attribution.submission.enabled" = false;
# Disable battery status, used to track users.
"dom.battery.enabled" = false;
# Disable that websites can get notifications if you copy, paste, or cut something from a web page, and it lets them know which part of the page had been selected.
#
# This breaks copying from BigQuery https://github.com/microsoft/monaco-editor/issues/1540
# dom.event.clipboardevents.enabled: false
# Isolates all browser identifier sources (e.g. cookies) to the first party domain, with the goal of preventing tracking across different domains.
"privacy.firstparty.isolate" = true;
# Do not preload URLs that auto-complete in the address bar.
"browser.urlbar.speculativeConnect.enabled" = false;
# Do not resist fingerprinting because that tells websites to use light mode.
# https://bugzilla.mozilla.org/show_bug.cgi?id=1732114
"privacy.resistFingerprinting" = false; # (default false)
# Instead, enable fingerprinting protection, which allows configuring an override.
"privacy.fingerprintingProtection" = true;
# Allow sending dark mode preference to websites.
# Allow sending timezone to websites.
"privacy.fingerprintingProtection.overrides" =
"+AllTargets,-CSSPrefersColorScheme,-JSDateTimeUTC,-CanvasExtractionBeforeUserInputIsBlocked";
# Disable weather on new tab page
"browser.newtabpage.activity-stream.showWeather" = false;
};
# Check about:policies#documentation and https://mozilla.github.io/policy-templates/ for options.
policies = {
DisableTelemetry = true;
DisplayBookmarksToolbar = "newtab";
# Check about:support for extension/add-on ID strings.
# Valid strings for installation_mode are "allowed", "blocked",
# "force_installed" and "normal_installed".
ExtensionSettings = {
# "*".installation_mode = "blocked"; # blocks all addons except the ones specified below
"uBlock0@raymondhill.net" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi";
installation_mode = "force_installed";
};
"firefox@teleparty.com" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/netflix-party-is-now-teleparty/latest.xpi";
installation_mode = "normal_installed";
};
};
};
};
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
directories = [
{
directory = ".mozilla";
user = "talexander";
group = "talexander";
mode = "0700";
}
];
};
};
environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
directories = [
{
directory = ".cache/mozilla";
user = "talexander";
group = "talexander";
mode = "0700";
}
];
};
};
}

View File

@@ -0,0 +1,20 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
# Open ports in the firewall.
networking.firewall.allowedTCPPorts = [
22 # ssh
];
networking.firewall.allowedUDPPorts = [
5353 # mDNS
];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
}

View File

@@ -0,0 +1,25 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
fonts = {
enableDefaultPackages = false;
packages = with pkgs; [
cascadia-code
source-sans-pro
source-serif-pro
noto-fonts-color-emoji
];
fontconfig = {
localConf = (builtins.readFile ./files/fonts.conf);
useEmbeddedBitmaps = true;
};
};
}

View File

@@ -0,0 +1,99 @@
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<!-- reject all bitmap fonts, with the exception of 'terminus' -->
<selectfont>
<!-- <acceptfont> -->
<!-- <pattern> -->
<!-- <patelt name="family"> <string>Terminus</string> </patelt> -->
<!-- </pattern> -->
<!-- </acceptfont> -->
<rejectfont>
<pattern>
<patelt name="scalable"> <bool>false</bool> </patelt>
</pattern>
</rejectfont>
<rejectfont>
<!-- You don't want ghostscript fonts in your web browsing because of annoying ligatures like ffi -->
<glob>/usr/share/fonts/gsfonts/*</glob>
</rejectfont>
</selectfont>
<!-- preferred aliases -->
<alias>
<family>serif</family>
<prefer>
<family>Source Serif Pro</family>
<family>Source Sans Pro</family>
</prefer>
</alias>
<!-- preferred aliases -->
<alias>
<family>sans-serif</family>
<prefer>
<family>Source Sans Pro</family>
<family>Source Serif Pro</family>
</prefer>
</alias>
<!-- preferred aliases -->
<alias>
<family>monospace</family>
<prefer>
<family>Cascadia Mono</family>
<family>Cascadia Code</family>
</prefer>
</alias>
<!-- Screw it. Force Liberation Mono to be source code pro. -->
<match target="pattern">
<test qual="any" name="family"><string>Liberation Mono</string></test>
<edit name="family" mode="assign" binding="same"><string>Cascadia Mono</string></edit>
</match>
<!-- Dejavu Sans Mono keeps coming back when I query "monospace". Doesn't happen when I'm using Souce Code Pro but does happen with cascadia... force it to cascadia -->
<match target="pattern">
<test qual="any" name="family"><string>monospace</string></test>
<edit name="family" mode="assign" binding="same"><string>Cascadia Mono</string></edit>
</match>
<!-- Disable ligatures in monospace fonts. -->
<match target="font">
<test name="family" compare="eq" ignore-blanks="true">
<string>Cascadia Code</string>
</test>
<edit name="fontfeatures" mode="append">
<string>liga off</string>
<string>dlig off</string>
</edit>
</match>
<!-- Font Display Settings -->
<match target="font" >
<edit mode="assign" name="rgba" >
<const>rgb</const>
</edit>
</match>
<match target="font" >
<edit mode="assign" name="hinting" >
<bool>true</bool>
</edit>
</match>
<match target="font" >
<edit mode="assign" name="hintstyle" >
<const>hintslight</const>
</edit>
</match>
<match target="font" >
<edit mode="assign" name="antialias" >
<bool>true</bool>
</edit>
</match>
<match target="font" >
<edit mode="assign" name="lcdfilter" >
<const>lcddefault</const>
</edit>
</match>
</fontconfig>

View File

@@ -0,0 +1,22 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
environment.systemPackages = with pkgs; [
git
];
home-manager.users.talexander =
{ pkgs, ... }:
{
home.file.".gitconfig" = {
source = ./files/gitconfig_home;
};
};
}

View File

@@ -0,0 +1,35 @@
[user]
email = tom@fizz.buzz
name = Tom Alexander
signingkey = D3A179C9A53C0EDE
[push]
default = simple
[alias]
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
bh = log --oneline --branches=* --remotes=* --graph --decorate
amend = commit --amend --no-edit
[core]
excludesfile = ~/.gitignore_global
[commit]
gpgsign = true
[pull]
rebase = true
[log]
date = local
[init]
defaultBranch = main
# Use meld for `git difftool` and `git mergetool`
[diff]
tool = meld
[difftool]
prompt = false
[difftool "meld"]
cmd = meld "$LOCAL" "$REMOTE"
[merge]
tool = meld
[mergetool "meld"]
# Make the middle pane start with partially-merged contents:
cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"
# Make the middle pane start without any merge progress:
# cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"

View File

@@ -0,0 +1,111 @@
{
config,
lib,
pkgs,
pkgs-unstable,
...
}:
{
imports = [ ];
# Fetch public keys:
# gpg --locate-keys tom@fizz.buzz
#
# gpg -vvv --auto-key-locate local,wkd --locate-keys tom@fizz.buzz
hardware.gpgSmartcards.enable = true;
services.udev.packages = [ pkgs.yubikey-personalization ];
services.pcscd.enable = true;
# services.gnome.gnome-keyring.enable = true;
# services.dbus.packages = [ pkgs.gcr ];
# services.pcscd.plugins = lib.mkForce [ ];
# programs.gpg.scdaemonSettings = {
# disable-ccid = true;
# };
# .gnupg/scdaemon.conf
home-manager.users.talexander =
{ pkgs, ... }:
{
home.file.".gnupg/scdaemon.conf" = {
source = ./files/scdaemon.conf;
};
};
programs.gnupg.dirmngr.enable = true;
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
pinentryPackage = pkgs.pinentry-qt;
# settings = {
# disable-ccid = true;
# };
};
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
directories = [
{
directory = ".gnupg";
user = "talexander";
group = "talexander";
mode = "0700";
} # Local keyring
];
};
};
# nixpkgs.overlays = [
# (final: prev: {
# pcsclite = prev.pcsclite.overrideAttrs (old: {
# postPatch = ''
# substituteInPlace src/libredirect.c src/spy/libpcscspy.c \
# --replace-fail "libpcsclite_real.so.1" "$lib/lib/libpcsclite_real.so.1"
# '';
# });
# })
# ];
# security.polkit.extraConfig = ''
# polkit.addRule(function(action, subject) {
# if (action.id == "org.debian.pcsc-lite.access_card") {
# return polkit.Result.YES;
# }
# });
# polkit.addRule(function(action, subject) {
# if (action.id == "org.debian.pcsc-lite.access_pcsc") {
# return polkit.Result.YES;
# }
# });
# '';
environment.systemPackages = with pkgs; [
pcsctools
];
# nixpkgs.overlays = [
# (final: prev: {
# gnupg = pkgs-unstable.gnupg;
# scdaemon = pkgs-unstable.scdaemon;
# })
# ];
# nixpkgs.overlays = [
# (final: prev: {
# gnupg = prev.gnupg.overrideAttrs (old: rec {
# version = "2.4.7";
# src = prev.fetchurl {
# url = "https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-${version}.tar.bz2";
# hash = "sha256-eyRwbk2n4OOwbKBoIxAnQB8jgQLEHJCWMTSdzDuF60Y=";
# };
# });
# })
# ];
}

View File

@@ -0,0 +1,2 @@
reader-port Yubico Yubi
disable-ccid

View File

@@ -0,0 +1,12 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
hardware.graphics.enable = true;
}

View File

@@ -0,0 +1,18 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
options.me.buildingIso = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = "Whether we are building an ISO image.";
};
}

View File

@@ -0,0 +1,43 @@
{
config,
lib,
pkgs,
...
}:
let
alias_kx = pkgs.writeShellScriptBin "kx" ''
exec ${pkgs.kubeswitch}/bin/switcher "''${@}"
'';
alias_ks = pkgs.writeShellScriptBin "ks" ''
exec ${pkgs.kubeswitch}/bin/switcher namespace "''${@}"
'';
alias_k = pkgs.writeShellScriptBin "k" ''
exec ${pkgs.kubectl}/bin/kubectl "''${@}"
'';
alias_ka = pkgs.writeShellScriptBin "ka" ''
exec ${pkgs.kubectl}/bin/kubectl "''${@}" --all-namespaces
'';
alias_kdel = pkgs.writeShellScriptBin "kdel" ''
exec ${pkgs.kubectl}/bin/kubectl delete --all "''${@}"
'';
alias_kd = pkgs.writeShellScriptBin "kd" ''
export KUBECTL_EXTERNAL_DIFF="${pkgs.colordiff}/bin/colordiff -N -u"
exec ${pkgs.kubectl}/bin/kubectl diff "''${@}"
'';
in
{
imports = [ ];
environment.systemPackages = with pkgs; [
kubectl
kubeswitch
stern
alias_kx
alias_ks
alias_k
alias_ka
alias_kdel
alias_kd
];
}

View File

@@ -0,0 +1,54 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
networking.dhcpcd.enable = false;
networking.useDHCP = false;
networking.nameservers = [
"194.242.2.2#doh.mullvad.net"
"2a07:e340::2#doh.mullvad.net"
];
services.resolved = {
enable = true;
# dnssec = "true";
domains = [ "~." ];
fallbackDns = [ ];
dnsovertls = "true";
};
# Without this, systemd-resolved will send DNS requests for <X>.home.arpa to the per-link DNS server (172.16.0.1) which does not support DNS-over-TLS. This leads to the connection anging and timing out. This causes firefox startup to take an extra 10+ seconds.
#
# Test with: drill @127.0.0.53 odo.home.arpa
networking.extraHosts = ''
127.0.0.1 odo.home.arpa
10.216.1.1 homeserver
10.216.1.6 media
10.216.1.12 odo
10.217.1.1 drmario
10.217.2.1 mrmanager
'';
networking.wireless.iwd = {
enable = true;
settings = {
General = {
EnableNetworkConfiguration = true;
AddressRandomization = "network";
ControlPortOverNL80211 = false;
};
};
};
environment.systemPackages = with pkgs; [
iw
iwd
ldns # for drill
arp-scan # To find devices on the network
];
}

View File

@@ -0,0 +1,18 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
environment.systemPackages = with pkgs; [
python3
poetry
pyright
isort
black
];
}

View File

@@ -0,0 +1,14 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
environment.systemPackages = with pkgs; [
qemu
];
}

View File

@@ -0,0 +1,13 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
# Reset some defaults to start from a minimal more-arch-linux-like state. Think of this like a CSS reset sheet.
}

View File

@@ -0,0 +1,73 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
environment.systemPackages = with pkgs; [
pavucontrol
];
# rtkit is optional but recommended
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# If you want to use JACK applications, uncomment this
#jack.enable = true;
extraLv2Packages = [ pkgs.rnnoise-plugin ];
configPackages = [
(pkgs.writeTextDir "share/pipewire/pipewire.conf.d/20-rnnoise.conf" ''
context.modules = [
{ name = libpipewire-module-filter-chain
args = {
node.description = "Noise Canceling source"
media.name = "Noise Canceling source"
filter.graph = {
nodes = [
{
type = lv2
name = rnnoise
plugin = "https://github.com/werman/noise-suppression-for-voice#stereo"
label = noise_suppressor_stereo
control = {
}
}
]
}
capture.props = {
node.name = "capture.rnnoise_source"
node.passive = true
audio.rate = 48000
# Optionally specify a specific input: (ID from `pactl list`)
# target.object = "alsa_input.usb-Shure_Incorporated_Shure_Digital-00.analog-stereo"
}
playback.props = {
node.name = "rnnoise_source"
media.class = Audio/Source
audio.rate = 48000
}
}
}
]
'')
];
};
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
directories = [
".local/state/wireplumber" # Sound settings
];
};
};
}

View File

@@ -0,0 +1,19 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
files = [
".ssh/known_hosts"
];
};
};
}

View File

@@ -0,0 +1,380 @@
{
config,
lib,
pkgs,
...
}:
let
sway-config = pkgs.writeTextFile {
name = "config";
text = ''
# Default config for sway
#
# Copy this to ~/.config/sway/config and edit it to your liking.
#
# Read `man 5 sway` for a complete reference.
### Variables
#
# Logo key. Use Mod1 for Alt.
set $mod Mod4
# set $mod Mod1
# Home row direction keys, like vim
set $left h
set $down j
set $up k
set $right l
# Your preferred terminal emulator
set $term ${pkgs.alacritty}/bin/alacritty
# Your preferred application launcher
# Note: it's recommended that you pass the final command to sway
# set $menu dmenu_path | dmenu | xargs swaymsg exec
set $menu ${pkgs.wofi}/bin/wofi --show drun --gtk-dark
# Do not show a title bar on windows
default_border pixel 2
bindsym $mod+grave exec $term
include ${base-hotkeys}
include ${display-configs}
include ${window-management}
include ${movement}
include ${disable-focus-follows-mouse}
include ${background}
include ${touchpad_input}
include ${waybar}
include ${announce_sway_start}
'';
};
base-hotkeys = pkgs.writeTextFile {
name = "base-hotkeys.conf";
text = ''
### Key bindings
#
# Basics:
#
# kill focused window
bindsym $mod+Shift+q kill
# start your launcher
bindsym $mod+Return exec $menu
# Drag floating windows by holding down $mod and left mouse button.
# Resize them with right mouse button + $mod.
# Despite the name, also works for non-floating windows.
# Change normal to inverse to use left mouse button for resizing and right
# mouse button for dragging.
floating_modifier $mod normal
# reload the configuration file
bindsym $mod+Shift+c reload
# exit sway (logs you out of your Wayland session)
bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'
'';
};
display-configs = pkgs.writeTextFile {
name = "display-configs.conf";
text = ''
output 'Unknown 0x095F 0x00000000' scale 1.5
output 'BOE 0x095F Unknown' scale 1.5
output 'BOE 0x0BCA Unknown' scale 1.5
'';
};
window-management = pkgs.writeTextFile {
name = "window-management.conf";
text = ''
#
# Layout stuff:
#
# You can "split" the current object of your focus with
# $mod+b or $mod+v, for horizontal and vertical splits
# respectively.
bindsym $mod+h splith
bindsym $mod+v splitv
# Switch the current container between different layout styles
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split
# Make the current focus fullscreen
bindsym $mod+f fullscreen
# Toggle the current focus between tiling and floating mode
bindsym $mod+Shift+space floating toggle
# Swap focus between the tiling area and the floating area
bindsym $mod+space focus mode_toggle
# move focus to the parent container
bindsym $mod+a focus parent
#
# Scratchpad:
#
# Sway has a "scratchpad", which is a bag of holding for windows.
# You can send windows there and get them back later.
# Move the currently focused window to the scratchpad
bindsym $mod+Shift+minus move scratchpad
# Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them.
bindsym $mod+minus scratchpad show
#
# Resizing containers:
#
mode "resize" {
# left will shrink the containers width
# right will grow the containers width
# up will shrink the containers height
# down will grow the containers height
bindsym $left resize shrink width 10px
bindsym $down resize grow height 10px
bindsym $up resize shrink height 10px
bindsym $right resize grow width 10px
# ditto, with arrow keys
bindsym Left resize shrink width 10px
bindsym Down resize grow height 10px
bindsym Up resize shrink height 10px
bindsym Right resize grow width 10px
# return to default mode
bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"
'';
};
movement = pkgs.writeTextFile {
name = "movement.conf";
text = ''
#
# Moving around:
#
# Move your focus around
# bindsym $mod+$left focus left
# bindsym $mod+$down focus down
# bindsym $mod+$up focus up
# bindsym $mod+$right focus right
# or use $mod+[up|down|left|right]
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right
# _move_ the focused window with the same, but add Shift
bindsym $mod+Shift+$left move left
bindsym $mod+Shift+$down move down
bindsym $mod+Shift+$up move up
bindsym $mod+Shift+$right move right
# ditto, with arrow keys
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
#
# Workspaces:
#
# switch to workspace
bindsym $mod+1 workspace 1
bindsym $mod+2 workspace 2
bindsym $mod+3 workspace 3
bindsym $mod+4 workspace 4
bindsym $mod+5 workspace 5
bindsym $mod+6 workspace 6
bindsym $mod+7 workspace 7
bindsym $mod+8 workspace 8
bindsym $mod+9 workspace 9
bindsym $mod+0 workspace 10
# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace 1
bindsym $mod+Shift+2 move container to workspace 2
bindsym $mod+Shift+3 move container to workspace 3
bindsym $mod+Shift+4 move container to workspace 4
bindsym $mod+Shift+5 move container to workspace 5
bindsym $mod+Shift+6 move container to workspace 6
bindsym $mod+Shift+7 move container to workspace 7
bindsym $mod+Shift+8 move container to workspace 8
bindsym $mod+Shift+9 move container to workspace 9
bindsym $mod+Shift+0 move container to workspace 10
# Note: workspaces can have any name you want, not just numbers.
# We just use 1-10 as the default.
'';
};
disable-focus-follows-mouse = pkgs.writeTextFile {
name = "disable-focus-follows-mouse.conf";
text = ''
# Disable focus following mouse
focus_follows_mouse no
'';
};
background = pkgs.writeTextFile {
name = "background.conf";
text = ''
output * bg ${./files/bliss.jpg} fill
'';
};
touchpad_input = pkgs.writeTextFile {
name = "touchpad_input.conf";
text = ''
input * xkb_rules "evdev"
# All touchpads
input type:touchpad {
dwt enabled
click_method clickfinger
tap enabled
}
'';
};
waybar = pkgs.writeTextFile {
name = "waybar.conf";
text = ''
#
# Status Bar:
#
# Read `man 5 sway-bar` for more information about this section.
bar {
position top
font pango:Cascadia Mono, FontAwesome 10
swaybar_command waybar
colors {
statusline #ffffff
background #323232
inactive_workspace #32323200 #32323200 #5c5c5c
}
}
'';
};
announce_sway_start = pkgs.writeTextFile {
name = "announce_sway_start.conf";
text = ''
# announce a running sway session to systemd
exec systemctl --user import-environment XDG_SESSION_TYPE XDG_CURRENT_DESKTOP
exec dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
'';
};
start_screen_share = pkgs.writeShellScriptBin "start_screen_share" ''
# Disable displaying notifications. This is useful for video conference screen sharing.
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "''${BASH_SOURCE[0]}" )" && pwd )"
makoctl set-mode do-not-disturb
swaymsg output "'Dell Inc. DELL U3014 P1V6N35M329L'" scale 2
'';
stop_screen_share = pkgs.writeShellScriptBin "stop_screen_share" ''
# Allow mako to show notifications again.
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "''${BASH_SOURCE [ 0 ]}" )" && pwd )"
makoctl set-mode default
swaymsg output "'Dell Inc. DELL U3014 P1V6N35M329L'" scale 1
'';
in
{
imports = [ ];
environment.systemPackages = with pkgs; [
alacritty
pcmanfm
start_screen_share
stop_screen_share
];
# Probably would be cleaner to use environment.sessionVariables but programs.sway.extraSessionCommands is sway-specific.
programs.sway.extraSessionCommands =
if config.me.buildingIso then
''
export WLR_RENDERER_ALLOW_SOFTWARE=1
export NIXOS_OZONE_WL=1 # Wayland support for chromium and electron
export QT_QPA_PLATFORMTHEME=gtk3 # Use gtk theme in Qt applications
''
else
''
export WLR_RENDERER=vulkan
export NIXOS_OZONE_WL=1 # Wayland support for chromium and electron
export QT_QPA_PLATFORMTHEME=gtk3 # Use gtk theme in Qt applications
'';
programs.sway = {
enable = true;
wrapperFeatures.gtk = true;
extraOptions =
if config.me.buildingIso then
[
"--debug"
"--config"
"${sway-config}"
"--unsupported-gpu"
]
else
[
"--debug"
"--config"
"${sway-config}"
];
};
environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
files = [
".cache/wofi-drun" # Execution history for wofi to sort results
];
};
};
xdg = {
portal = {
enable = true;
extraPortals = with pkgs; [
xdg-desktop-portal-wlr
xdg-desktop-portal-gtk
];
wlr = {
enable = true;
settings = {
# uninteresting for this problem, for completeness only
screencast = {
# output_name = "eDP-1";
max_fps = 30;
exec_before = "${start_screen_share}";
exec_after = "${stop_screen_share}";
chooser_type = "simple";
chooser_cmd = "${pkgs.slurp}/bin/slurp -f %o -or";
};
};
};
};
};
# Configure default programs (for example, default browser)
home-manager.users.talexander =
{ pkgs, ... }:
{
home.file = {
".config/mimeapps.list" = {
source = ./files/mimeapps.list;
};
};
home.file = {
".config/gtk-3.0/settings.ini" = {
source = ./files/settings.ini;
};
};
};
# For mounting drives in pcmanfm
services.gvfs.enable = true;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 KiB

View File

@@ -0,0 +1,23 @@
[Default Applications]
x-scheme-handler/http=firefox.desktop
x-scheme-handler/https=firefox.desktop
x-scheme-handler/chrome=firefox.desktop
text/html=firefox.desktop
application/x-extension-htm=firefox.desktop
application/x-extension-html=firefox.desktop
application/x-extension-shtml=firefox.desktop
application/xhtml+xml=firefox.desktop
application/x-extension-xhtml=firefox.desktop
application/x-extension-xht=firefox.desktop
[Added Associations]
x-scheme-handler/http=firefox.desktop;
x-scheme-handler/https=firefox.desktop;
x-scheme-handler/chrome=firefox.desktop;
text/html=firefox.desktop;
application/x-extension-htm=firefox.desktop;
application/x-extension-html=firefox.desktop;
application/x-extension-shtml=firefox.desktop;
application/xhtml+xml=firefox.desktop;
application/x-extension-xhtml=firefox.desktop;
application/x-extension-xht=firefox.desktop;

View File

@@ -0,0 +1,2 @@
[Settings]
gtk-application-prefer-dark-theme=1

View File

@@ -0,0 +1,90 @@
{
config,
lib,
pkgs,
...
}:
let
waybar_available_memory =
(pkgs.writeScriptBin "waybar_custom_available_memory" (
builtins.readFile ./files/waybar_scripts/waybar_available_memory_linux.bash
)).overrideAttrs
(old: {
buildCommand = "${old.buildCommand}\n patchShebangs $out";
});
waybar_battery =
(pkgs.writeScriptBin "waybar_custom_battery" (
builtins.readFile ./files/waybar_scripts/waybar_battery_linux.bash
)).overrideAttrs
(old: {
buildCommand = "${old.buildCommand}\n patchShebangs $out";
});
waybar_clock =
(pkgs.writeScriptBin "waybar_custom_clock" (
builtins.readFile ./files/waybar_scripts/waybar_custom_clock.py
)).overrideAttrs
(old: {
buildCommand = "${old.buildCommand}\n patchShebangs $out";
});
waybar_night_mode =
(pkgs.writeScriptBin "waybar_night_mode" (
builtins.readFile ./files/waybar_scripts/waybar_night_mode.bash
)).overrideAttrs
(old: {
buildCommand = "${old.buildCommand}\n patchShebangs $out";
});
waybar_sound =
(pkgs.writeScriptBin "waybar_custom_sound" (
builtins.readFile ./files/waybar_scripts/waybar_sound_linux.bash
)).overrideAttrs
(old: {
buildCommand = "${old.buildCommand}\n patchShebangs $out";
});
waybar_temperature =
(pkgs.writeScriptBin "waybar_custom_temperature" (
builtins.readFile ./files/waybar_scripts/waybar_temperature_linux.bash
)).overrideAttrs
(old: {
buildCommand = "${old.buildCommand}\n patchShebangs $out";
});
in
{
imports = [ ];
environment.systemPackages = with pkgs; [
waybar
waybar_available_memory
waybar_battery
waybar_clock
waybar_night_mode
waybar_sound
waybar_temperature
python3 # for clock TODO python should not be in the system packages, maybe switch to a venv? ref https://nixos.wiki/wiki/Python
bc # for temperature and sound
jq # for memory, battery, sound, night mode, and temperature
upower # for battery
wlsunset # for night mode
];
services.upower.enable = true; # for battery
home-manager.users.talexander =
{ pkgs, ... }:
{
home.file = {
".config/waybar/config" = {
source = ./files/waybar_config.json;
};
".config/waybar/style.css" = {
source = ./files/style.css;
};
};
};
}

View File

@@ -0,0 +1,211 @@
/* Work-around for regressions introduced in 0.9.15 */
* {
all: unset;
}
/* Reset all styles */
* {
border: none;
border-radius: 0;
min-height: 0;
margin: 0;
padding: 0;
}
/* -----------------------------------------------------------------------------
* Keyframes
* -------------------------------------------------------------------------- */
@keyframes blink-warning {
70% {
color: white;
}
to {
color: white;
background-color: orange;
}
}
@keyframes blink-critical {
70% {
color: white;
}
to {
color: white;
background-color: red;
}
}
/* -----------------------------------------------------------------------------
* Base styles
* -------------------------------------------------------------------------- */
/* The whole bar */
#waybar {
background: #323232;
color: white;
font-family:
Cascadia Mono,
monospace;
font-size: 10px;
}
tooltip {
background-color: #323232;
}
/* Each module */
#battery,
#clock,
#cpu,
#custom-available_memory,
#custom-battery,
#custom-clock,
#custom-night_mode,
#custom-sound,
#custom-temperature,
#idle_inhibitor,
#memory,
#mode,
#network,
#pulseaudio,
#temperature,
#tray {
padding-left: 10px;
padding-right: 10px;
border: 1px solid white;
}
/* -----------------------------------------------------------------------------
* Module styles
* -------------------------------------------------------------------------- */
#battery {
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#custom-battery.warning {
color: orange;
}
#custom-battery.critical {
color: red;
}
#battery.warning.discharging {
animation-name: blink-warning;
animation-duration: 3s;
}
#battery.critical.discharging {
animation-name: blink-critical;
animation-duration: 2s;
}
#clock {
font-weight: bold;
}
#custom-clock {
font-weight: bold;
}
#cpu {
/* No styles */
}
#cpu.warning {
color: orange;
}
#cpu.critical {
color: red;
}
#memory {
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#memory.warning {
color: orange;
}
#memory.critical {
color: red;
animation-name: blink-critical;
animation-duration: 2s;
}
#mode {
background: #64727d;
border-top: 2px solid white;
/* To compensate for the top border and still have vertical centering */
padding-bottom: 2px;
}
#window {
padding-left: 10px;
padding-right: 10px;
}
#network {
/* No styles */
}
#network.disconnected {
color: orange;
}
#pulseaudio {
/* No styles */
}
#pulseaudio.muted {
/* No styles */
}
#custom-spotify {
color: rgb(102, 220, 105);
}
#temperature {
/* No styles */
}
#temperature.critical {
color: red;
}
#tray {
/* No styles */
}
#window {
font-weight: bold;
}
#workspaces button {
border-top: 2px solid transparent;
/* To compensate for the top border and still have vertical centering */
padding-bottom: 2px;
padding-left: 10px;
padding-right: 10px;
color: #888888;
}
#workspaces button.focused {
border-color: #4c7899;
color: white;
background-color: #285577;
}
#workspaces button.urgent {
border-color: #c9545d;
color: #c9545d;
}

View File

@@ -0,0 +1,57 @@
{
// "height": 10, // Waybar height (to be removed for auto height)
"modules-left": ["sway/workspaces", "sway/mode"],
"modules-center": ["sway/window"],
"modules-right": ["custom/night_mode", "custom/temperature", "custom/sound", "custom/available_memory", "custom/battery", "idle_inhibitor", "custom/clock", "tray"],
"sway/workspaces": {
"disable-scroll": true
},
"sway/mode": {
"format": "<span style=\"italic\">{}</span>"
},
"sway/window": {
"format": "{title}"
},
"idle_inhibitor": {
"format": "{icon}",
"format-icons": {
"activated": "☕",//☕
"deactivated": "💤"//☾☁⛾⛔⏾⌛⏳💤
}
},
"tray": {
// "icon-size": 21,
"spacing": 10
},
"custom/clock": {
"exec": "waybar_custom_clock",
"return-type": "json",
"restart-interval": 30
},
"custom/battery": {
"exec": "waybar_custom_battery",
"return-type": "json",
"restart-interval": 30
},
"custom/available_memory": {
"exec": "waybar_custom_available_memory",
"return-type": "json",
"restart-interval": 30
},
"custom/sound": {
"exec": "waybar_custom_sound",
"return-type": "json",
"restart-interval": 30
},
"custom/temperature": {
"exec": "waybar_custom_temperature",
"return-type": "json",
"restart-interval": 30
},
"custom/night_mode": {
"exec": "waybar_night_mode",
"return-type": "json",
"restart-interval": 30,
"on-click": "pkill -USR1 -f waybar_night_mode"
}
}

View File

@@ -0,0 +1,32 @@
#!/usr/bin/env bash
#
# Read memory usage in Linux
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SLEEP_INTERVAL=${SLEEP_INTERVAL:-30}
while true; do
memory_usage=$(free --bytes --wide)
total_bytes=$(grep 'Mem:' <<<"$memory_usage" | awk '{print $2}')
free_bytes=$(grep 'Mem:' <<<"$memory_usage" | awk '{print $4}')
free_percent=$((100 * free_bytes / total_bytes))
text=""
if [ $free_bytes -ge $((1024 * 1024 * 1024)) ]; then
text="$((free_bytes / 1024 / 1024 / 1024)) GiB"
fi
tooltip="${free_percent}%"
jq --unbuffered --compact-output <<EOF
{
"text":"${text}",
"tooltip":"${tooltip}",
"percentage":${free_percent}
}
EOF
sleep $SLEEP_INTERVAL
done

View File

@@ -0,0 +1,80 @@
#!/usr/bin/env bash
#
# Read battery status in Linux
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
batteries=$(upower --enumerate | grep BAT)
function generate_battery_update {
local battery_path=$1
local battery_status=$(upower --show-info "$battery_path")
local battery_state=$(grep 'state:' <<<"$battery_status" | awk '{print $2}')
local battery_percentage=$(grep 'percentage:' <<<"$battery_status" | awk '{print $2}')
battery_percentage=${battery_percentage%\%}
set +e
local time_remaining=$(grep 'time to empty:' <<<"$battery_status" | sed 's/\W*time to empty:\W*//g')
local tooltip="$time_remaining until empty"
if [ -z "$time_remaining" ]; then
time_remaining=$(grep 'time to full:' <<<"$battery_status" | sed 's/\W*time to full:\W*//g')
if [ -z "$time_remaining" ]; then
tooltip="fully charged"
else
tooltip="$time_remaining until full"
fi
fi
set -e
local battery_icon=""
local class=""
if [ $battery_state = "charging" ]; then
if [ $battery_percentage -eq 100 ]; then
battery_icon="⚡"
else
battery_icon="⚡"
fi
elif [ $battery_percentage -le 12 ]; then
battery_icon="⚠"
elif [ $battery_percentage -le 25 ]; then
battery_icon="▁"
elif [ $battery_percentage -le 37 ]; then
battery_icon="▂"
elif [ $battery_percentage -le 50 ]; then
battery_icon="▃"
elif [ $battery_percentage -le 62 ]; then
battery_icon="▄"
elif [ $battery_percentage -le 75 ]; then
battery_icon="▅"
elif [ $battery_percentage -le 87 ]; then
battery_icon="▆"
elif [ $battery_percentage -lt 100 ]; then
battery_icon="▇"
else
battery_icon="█"
fi
if [ $battery_percentage -le 15 ]; then
class="critical"
elif [ $battery_percentage -le 30 ]; then
class="warning"
fi
jq --unbuffered --compact-output <<EOF
{
"text":"${battery_percentage}% ${battery_icon}",
"tooltip":"$tooltip",
"percentage":${battery_percentage},
"class":"${class}"
}
EOF
}
while read bat; do
generate_battery_update "$bat"
done<<<"$batteries"
upower --monitor | grep --line-buffered 'device changed:' | while read l; do
while read bat; do
generate_battery_update "$bat"
done<<<"$batteries"
done

View File

@@ -0,0 +1,107 @@
#!/usr/bin/env python
#
# Custom waybar module for clocks. Implemented because the official clock module was downloading timezone definitions on every boot.
import datetime
import json
import sys
import time
from dataclasses import dataclass
from functools import lru_cache
from typing import Final, List, Optional
from zoneinfo import ZoneInfo
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
@dataclass
class Update:
text: Optional[str]
alt: Optional[str]
tooltip: Optional[str]
css_class: Optional[List[str]]
percentage: Optional[str]
def dump(self) -> str:
# Dump a dict because we can't name our member variable "class"
return json.dumps(
{
k: v
for k, v in {
"text": self.text,
"alt": self.alt,
"tooltip": self.tooltip,
"class": self.css_class,
"percentage": self.percentage,
}.items()
if v is not None
}
)
@lru_cache(maxsize=1)
def make_calendar(today: datetime.date, tz: datetime.tzinfo):
width: Final[int] = 20
start_of_month = today.replace(day=1)
month_header = today.strftime("%B %Y")
padding = width - len(month_header)
right_padding = " " * (padding // 2)
left_padding = right_padding + (" " if padding % 2 == 1 else "")
header = f"{left_padding}{month_header}{right_padding}"
days_of_week = "Su Mo Tu We Th Fr Sa"
timezone_str = str(tz)
# Make the grid
first_day_padding = " " * (
0 if start_of_month.weekday() == 6 else (3 * (1 + start_of_month.weekday())) - 1
)
output = f"{header}\n{days_of_week}\n{first_day_padding}"
print_day = start_of_month
while print_day.month == today.month:
if print_day.weekday() == 6:
output += "\n"
else:
output += " "
if print_day == today:
output += '<span foreground="#323232" background="#CCCCCC">'
output += f"{print_day.day: >2}"
if print_day == today:
output += "</span>"
print_day += datetime.timedelta(days=1)
output += f'\n<span size="small">{timezone_str}</span>'
return output
def main():
tz: Optional[datetime.tzinfo] = (
ZoneInfo(sys.argv[1]) if len(sys.argv) >= 2 else LOCAL_TIMEZONE
)
if tz is None:
raise Exception("Failed to detect timezone.")
next_update = time.time()
while True:
time_before_next_update = next_update - time.time()
if time_before_next_update > 0:
time.sleep(time_before_next_update)
next_update = 60 * (1 + int(time.time()) // 60)
now = datetime.datetime.now(tz=tz)
text = now.strftime("%Y-%m-%d %H:%M:%S")
tooltip = make_calendar(now.date(), tz)
out = Update(
text=text,
alt="foo",
tooltip=f"<tt>{tooltip}</tt>",
css_class=["foo"],
percentage="100",
)
print(out.dump(), flush=True)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,93 @@
#!/usr/bin/env bash
#
# Power an icon for tinting the screen at night.
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SLEEP_INTERVAL=${SLEEP_INTERVAL:-30}
# ◓◒●◌◎
# 🔴🔵🟠🟡🟢🟣🟤
# 🟥🟦🟧🟨🟩🟪🟫
# ☀☯⭐🌝🌞⏾
# 🌑🌓🌗🌕
# 👓
############## Setup #########################
function cleanup {
log "Killing child process $wlsunset_pid"
kill "$wlsunset_pid"
true
}
for sig in EXIT; do
trap "set +e; cleanup" "$sig"
done
function die {
local status_code="$1"
shift
(>&2 echo "${@}")
exit "$status_code"
}
function log {
(>&2 echo "${@}")
}
############## Program #########################
function main {
local night_mode_icon night_mode_text night_mode_class
night_mode_mode="auto"
night_mode_class=""
wlsunset -S 07:00 -s 22:00 &
wlsunset_pid=$!
while true; do
if [ "$night_mode_mode" == "auto" ]; then
night_mode_icon="🌗"
night_mode_text="auto"
elif [ "$night_mode_mode" == "on" ]; then
night_mode_icon="🌑"
night_mode_text="night"
elif [ "$night_mode_mode" == "off" ]; then
night_mode_icon="🌕"
night_mode_text="day"
fi
render
sleep "$SLEEP_INTERVAL" &
wait $! || true
done
}
function render {
jq --unbuffered --compact-output <<EOF
{
"text":"${night_mode_icon}",
"tooltip":"${night_mode_text}",
"percentage":100,
"class":"${night_mode_class}"
}
EOF
}
function handle_click {
if [ "$night_mode_mode" == "auto" ]; then
log "Setting night mode to force-day."
night_mode_mode="off"
elif [ "$night_mode_mode" == "on" ]; then
log "Setting night mode to auto."
night_mode_mode="auto"
elif [ "$night_mode_mode" == "off" ]; then
log "Setting night mode to force-night."
night_mode_mode="on"
fi
kill -s SIGUSR1 "$wlsunset_pid"
}
trap "handle_click" SIGUSR1
main "${@}"

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
#
# Read volume status in Linux
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SLEEP_INTERVAL=${SLEEP_INTERVAL:-30}
while true; do
current_vol_decimal=$(wpctl get-volume @DEFAULT_AUDIO_SINK@ | sed 's/Volume: //g')
if [[ "$current_vol_decimal" = *MUTED* ]]; then
current_vol_percent=0
else
current_vol_percent=$(bc -s <<<"$current_vol_decimal * 100")
current_vol_percent=${current_vol_percent%.*} # Remove decimal
fi
tooltip="<tt>$(wpctl status)</tt>"
tooltip=${tooltip//$'\n'/\\n}
tooltip=${tooltip//$'\t'/\\t}
class=""
icon=""
if [ $current_vol_percent -eq 0 ]; then
icon="🔇"
elif [ $current_vol_percent -le 50 ]; then
icon="🔉"
else
icon="🔊"
fi
jq --unbuffered --compact-output <<EOF
{
"text":"${current_vol_percent}% ${icon}",
"tooltip":"${tooltip}",
"percentage":${current_vol_percent},
"class":"${class}"
}
EOF
sleep $SLEEP_INTERVAL
done

View File

@@ -0,0 +1,56 @@
#!/usr/bin/env bash
#
# Read temperature status in Linux
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SLEEP_INTERVAL=${SLEEP_INTERVAL:-30}
function print_all_x86_pkg_temps {
for thermal_zone in /sys/class/thermal/thermal_zone*; do
local thermal_zone_type=$(cat "$thermal_zone/type")
if [ "$thermal_zone_type" != "x86_pkg_temp" ] && [ "$thermal_zone_type" != "acpitz" ]; then
continue
fi
local thermal_zone_temperature=$(cat "$thermal_zone/temp")
echo "$thermal_zone_temperature"
done
}
while true; do
sum_temperature=0
num_temperature=0
max_temperature=0
while read temp; do
numeric_temp=$(bc -s <<<"$temp / 1000.0")
sum_temperature=$(bc -s <<<"$sum_temperature + $numeric_temp")
num_temperature=$((num_temperature + 1))
max_temperature=$(bc <<EOF
define max(a,b){
if(a>b)
{
return(a)
}else{
return(b)
}
}
max($max_temperature,$numeric_temp)
EOF
)
done<<<$(print_all_x86_pkg_temps)
avg_temperature=$(bc -s <<<"$sum_temperature / $num_temperature")
tooltip=""
class=""
icon="🌡"
jq --unbuffered --compact-output <<EOF
{
"text":"${max_temperature}℃ ${icon}",
"tooltip":"${tooltip//$'\n'/\\n}",
"percentage":50,
"class":"${class}"
}
EOF
sleep $SLEEP_INTERVAL
done

View File

@@ -0,0 +1,49 @@
{
config,
lib,
pkgs,
...
}:
let
activatedWg = name: {
networking.wg-quick.interfaces."${name}".configFile = "/persist/manual/wireguard/${name}.conf";
systemd.services."wg-quick-${name}" = {
after = [
"nss-lookup.target"
"systemd-resolved.service"
"multi-user.target"
];
preStart = "${pkgs.toybox}/bin/sleep 10";
};
# systemd.services."wg-quick-${name}".after = [
# "nss-lookup.target"
# "systemd-resolved.service"
# "multi-user.target"
# ];
# systemd.services."wg-quick-${name}".preStart = "${pkgs.toybox}/bin/sleep 10";
};
deactivatedWg = name: {
networking.wg-quick.interfaces."${name}" = {
configFile = "/persist/manual/wireguard/${name}.conf";
autostart = false;
};
};
wgConfig = lib.attrsets.recursiveUpdate (lib.attrsets.recursiveUpdate (lib.attrsets.recursiveUpdate
(lib.attrsets.recursiveUpdate {
networking.firewall.allowedUDPPorts = [ 51821 ];
networking.wireguard.enable = true;
} (activatedWg "drmario"))
(activatedWg "wgh")
) (activatedWg "colo")) (deactivatedWg "wgf");
in
{
imports = [ ];
config = lib.mkIf (!config.me.buildingIso) wgConfig;
# environment.systemPackages = with pkgs; [
# wireguard-tools
# ];
}

View File

@@ -0,0 +1,21 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [ ];
boot.zfs.devNodes = "/dev/disk/by-partuuid";
services.zfs = {
autoScrub = {
enable = true;
interval = "monthly";
};
trim.enable = true;
};
}

View File

@@ -0,0 +1,98 @@
{
config,
lib,
pkgs,
...
}:
let
zshrc = pkgs.writeTextFile {
name = ".zshrc";
text = ''
# Lines configured by zsh-newuser-install
HISTFILE=~/.zhistory
HISTSIZE=100000
SAVEHIST=100000
setopt appendhistory notify
unsetopt beep
bindkey -e
# End of lines configured by zsh-newuser-install
# The following lines were added by compinstall
#
# Use menu complete immediately instead of after the first tab
setopt MENU_COMPLETE
zstyle :compinstall filename "$HOME/.zshrc"
autoload -Uz compinit
compinit
# End of lines added by compinstall
# Enable the 2d menu for tab completion
zstyle ':completion:*' menu select
autoload colors zsh/terminfo
if [[ "$terminfo[colors]" -ge 8 ]]; then
colors
fi
for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE; do
eval PR_$color='%{$terminfo[bold]$fg[''${(L)color}]%}'
eval PR_LIGHT_$color='%{$fg[''${(L)color}]%}'
(( count = $count + 1 ))
done
PR_NO_COLOR="%{$terminfo[sgr0]%}"
PS1="[$PR_BLUE%n$PR_WHITE@$PR_GREEN%U%m%u$PR_NO_COLOR:$PR_RED%2c$PR_NO_COLOR]%(!.#.$) "
source ${pkgs.zsh-histdb}/share/zsh/plugins/zsh-histdb/sqlite-history.zsh
autoload -Uz add-zsh-hook
source ${pkgs.zsh-histdb}/share/zsh/plugins/zsh-histdb/histdb-interactive.zsh
bindkey '^r' _histdb-isearch
# TODO: Consider moving to /etc/profile.d
#while read file; do
# if [ -e "$file" ]; then
# source "$file"
# fi
#done <<<"$(find $HOME/.config/ansible_deploy/zshrc -maxdepth 1 -type f -name '*.zsh' -print)"
'';
};
in
{
imports = [ ];
environment.systemPackages = with pkgs; [
zsh
sqlite # TODO: can this be pulled into zsh-histdb automatically?
];
users.users.talexander.shell = pkgs.zsh;
environment.shells = with pkgs; [ zsh ];
programs.zsh = {
enable = true;
};
home-manager.users.talexander =
{ pkgs, ... }:
{
home.file.".zshrc" = {
source = "${zshrc}";
};
};
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
users.talexander = {
directories = [
{
directory = ".histdb";
user = "talexander";
group = "talexander";
mode = "0700";
}
];
};
};
}

113
nix/virtual_machine/nix_vm.bash Executable file
View File

@@ -0,0 +1,113 @@
#!/usr/bin/env bash
#
# Manage a nix vm for testing.
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
: ${VM_ROOT_ZFS:="zroot/linux/archmain/vm/nix"}
: ${VM_ROOT_MOUNT:="/vm/nix"}
: ${VM_DISK_SIZE:="100G"}
# Manual Steps:
#
# Download the nixos livecd from https://channels.nixos.org/nixos-24.11/latest-nixos-gnome-x86_64-linux.iso
############## Setup #########################
function die {
local status_code="$1"
shift
(>&2 echo "${@}")
exit "$status_code"
}
function log {
(>&2 echo "${@}")
}
############## Program #########################
function main {
local cmd="$1"
shift 1
if [ "$cmd" = "init" ]; then
vm_init "${@}"
elif [ "$cmd" = "install" ]; then
vm_install "${@}"
elif [ "$cmd" = "run" ]; then
vm_run "${@}"
elif [ "$cmd" = "iso_ssh" ]; then
vm_iso_ssh "${@}"
elif [ "$cmd" = "iso_sync" ]; then
vm_iso_sync "${@}"
elif [ "$cmd" = "ssh" ]; then
vm_ssh "${@}"
elif [ "$cmd" = "sync" ]; then
vm_sync "${@}"
else
die 1 "Unknown command: $cmd"
fi
}
function vm_init {
zfs create -o mountpoint=none -o canmount=off "$VM_ROOT_ZFS"
zfs create -u -o "mountpoint=$VM_ROOT_MOUNT" -o canmount=on "$VM_ROOT_ZFS/settings"
zfs create -s "-V${VM_DISK_SIZE}" -o volmode=dev -o primarycache=metadata -o secondarycache=none -o volblocksize=64K "${VM_ROOT_ZFS}/disk0"
zfs snapshot -r "$VM_ROOT_ZFS@empty"
zfs mount "$VM_ROOT_ZFS/settings"
# Empty EFI variables
cp /usr/share/edk2/x64/OVMF_VARS.4m.fd "${VM_ROOT_MOUNT}/"
}
function vm_install {
VM_CDROM="$1"
shift 1
vm_run "${@}"
}
function vm_run {
local additional_args=()
if [ -n "${VM_CDROM:-}" ]; then
log "Using CD $VM_CDROM"
additional_args+=("-cdrom" "$VM_CDROM")
fi
exec qemu-system-x86_64 \
-accel kvm \
-cpu host \
-smp cores=8 \
-m 32768 \
-drive file=/usr/share/edk2/x64/OVMF_CODE.4m.fd,if=pflash,format=raw,readonly=on \
-drive if=pflash,format=raw,file="$(readlink -f "${VM_ROOT_MOUNT}/OVMF_VARS.4m.fd")" \
-drive "if=none,file=/dev/zvol/${VM_ROOT_ZFS}/disk0,format=raw,id=hd0" \
-device nvme,serial=deadbeef,drive=hd0 \
-nic user,hostfwd=tcp::60022-:22 \
-boot order=d \
"${additional_args[@]}"
}
function vm_iso_ssh {
exec gpg_auth ssh -p 60022 nixos@127.0.0.1
}
function vm_iso_sync {
gpg_auth rsync -av --delete --progress -e 'ssh -p 60022' "$DIR/../configuration" nixos@127.0.0.1:~/
gpg_auth ssh -p 60022 nixos@127.0.0.1 'sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/latest -- --mode destroy,format,mount ./configuration/hosts/odo/disk-config.nix'
gpg_auth ssh -t -p 60022 nixos@127.0.0.1 sudo nixos-install --flake ./configuration#odovm
}
function vm_ssh {
exec gpg_auth ssh -p 60022 127.0.0.1
}
function vm_sync {
gpg_auth rsync -av --delete --progress -e 'ssh -p 60022' "$DIR/../configuration" 127.0.0.1:~/
gpg_auth ssh -t -p 60022 127.0.0.1 doas nixos-rebuild boot --flake ./configuration#odovm
}
main "${@}"