Compare commits

...

35 Commits
master ... hola

Author SHA1 Message Date
Matthieu Morin b809108bb6 resolve disko config conflict with device in configuration.nix 2024-06-09 21:04:38 +00:00
Matthieu Morin d97344170b Make a systemd mount unit instead of unfunctioning sh script in systemd stage 1 2024-06-09 20:18:16 +00:00
Matthieu Morin 0c6fe348d8 fixes - systemd 2024-06-09 19:30:54 +00:00
Matthieu Morin 7893c9effa deleting unused module for btrfs 2024-06-09 18:17:38 +00:00
Matthieu Morin af36675d77 git config 2024-06-09 17:15:09 +00:00
Matthieu Morin 231aed27bf Add home/laozi/common/core/fonts.nix 2024-06-09 17:13:10 +00:00
Matthieu Morin 8908e8bee0 Add home/laozi/common/core/bat.nix 2024-06-09 17:12:16 +00:00
Matthieu Morin ddfe750fb8 init 2024-06-09 17:11:39 +00:00
Matthieu Morin 061c0fbc54 GeistMono 2024-06-09 16:57:00 +00:00
Matthieu Morin 7e7650200e typo desktops -> desktop 2024-06-09 16:27:08 +00:00
Matthieu Morin 6dcd45108e default user imports for rehoboam 2024-06-09 16:26:38 +00:00
Matthieu Morin 3c46d4e9f5 default user imports 2024-06-09 16:26:03 +00:00
Matthieu Morin d15f55e998 zsh init 2024-06-09 15:55:29 +00:00
Matthieu Morin 360d35308d Scan all core, add sudo 2h limit 2024-06-09 15:53:08 +00:00
Matthieu Morin 6ff38c96c3 delete -> initrd present in system config 2024-06-09 15:46:04 +00:00
Matthieu Morin 63ce33d343 add auto locale options 2024-06-09 15:43:18 +00:00
Matthieu Morin e19044a9b5 Templating for system init.
Networking, pipewire for audio, time, i18n, console,
2024-06-09 15:41:39 +00:00
Matthieu Morin eec674e7ad specifying hdd.key file on mounted usb 2024-06-09 15:18:56 +00:00
Matthieu Morin a77669ec61 Update primary usb uuid 2024-06-09 14:50:37 +00:00
Matthieu Morin 4c2a8b9ea5 hdd key 2024-06-09 14:18:45 +00:00
Matthieu Morin d6d8394c4b Add systems/common/disks/jeroboam2.nix 2024-06-09 02:40:30 +00:00
Matthieu Morin 07f9428403 usb unattended 2024-06-09 02:33:27 +00:00
Matthieu Morin d4a5d3c200 luks upd 2024-06-09 01:42:13 +00:00
Matthieu Morin 1484eb8b1e Update systems/jeroboam/default.nix 2024-06-09 01:40:10 +00:00
Matthieu Morin 807535f788 Update systems/jeroboam/default.nix 2024-06-09 01:25:52 +00:00
Matthieu Morin 5dba3da29f Rewrite Rehoboam 2024-06-09 01:23:26 +00:00
Matthieu Morin cadb82328e preinstall 2024-06-09 00:46:22 +00:00
Matthieu Morin 8d61252da8 Add systems/common/disks/jeroboam.nix 2024-06-09 00:41:07 +00:00
Matthieu Morin 8411fe06c6 Update systems/common/disks/single-partition-btrfs-persist-luks.nix 2024-06-09 00:39:26 +00:00
Matthieu Morin 32250d3451 Jeroboam init 2024-06-08 22:40:22 +00:00
Matthieu Morin 3afb03e13b add a simple shell 2024-06-08 21:21:38 +00:00
Matthieu Morin 01d3a25602 laozi on jeroboam 2024-06-07 15:30:53 +02:00
Matthieu Morin 533334fd30 default btrfs disk config via disko with swapfile, compression and variable disk numbers 2024-06-07 15:28:25 +02:00
Matthieu Morin e9fe3adf98 update to 24.-5 starting point 2024-06-07 14:39:56 +02:00
matthieu42morin c95d3a3c17 asdf 2024-06-07 13:37:13 +02:00
109 changed files with 6888 additions and 2 deletions

38
.editorconfig Normal file
View File

@ -0,0 +1,38 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,py}]
charset = utf-8
# 4 space indentation
[*.py]
indent_style = space
indent_size = 4
[*.nix]
indent_style = space
indent_size = 4
# Tab indentation (no size specified)
[Makefile]
indent_style = tab
# Indentation override for all JS under lib directory
[lib/**.js]
indent_style = space
indent_size = 2
# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2

148
README.md
View File

@ -1,3 +1,147 @@
# nixos-config-priv
# Nix-Config
WIP
## Architecture
## Inputs
Dependencies
- release-23.11
- unstable
- hardware
- sops
- home manager
-
## Outputs
### Systems Confs (./systems)
Configurations (In the traditional way configuration.nix) that are specific to specific machines/hosts/systems.
#### Systems/Common/core
Configuration that is common to !all systems!.
#### Systems/Common/users
Configuration that is common to specific users.
#### Systems/Common/optional
Configuration that is optional, does not have to be on any user or system.
### Home Manager Configs (./home)
User-specific Configurations that should not give a crap where they live.
### Custom ./modules
Contains Nix expressions that offer customized functionalities inside and outside of my config.
Split into system and home
#### Home
Defines those modules that are specific to my user envs.
#### System
Defines system wide modules.
### [Custom ./overlays](https://nixos.org/manual/nixpkgs/stable/#chap-overlays)
overrides, patches, builds to nixpkgs.
### pkgs
Custom packages, nicely imports together with nixpkgs. TBH should go upstream, so this is for temporary pkgs fixes
### shell.nix
Run this on new systems to get temporary shell to setup the whole rest.
### Formatter
Useful without LSP setup
## Inspirations
A thank you to:
[Emergent Mind's nix flake config and yewtube vids]()
[NvChad](https://github.com/NvChad/NvChad)
[Hlissner's dotfiles](https://github.com/hlissner/dotfiles)
## 💾 References
### features
#### Cache
https://docs.attic.rs/introduction.html
#### Wayland
[Awesome Wayland](https://github.com/rcalixte/awesome-wayland)
### Disko
https://github.com/nix-community/disko
https://nixos.wiki/wiki/Disko
### Python
https://wiki.nixos.org/wiki/Python#Using_regular_Python_virtual_environment
https://github.com/nvbn/thefuck
https://stevelosh.com/projects/
### 04/25
Added some things from
- https://github.com/fidgetingbits/nixvim
- https://github.com/yrashk/nix-home/tree/master
-
### Yubikey based fde
https://nixos.wiki/wiki/Yubikey_based_Full_Disk_Encryption_(FDE)_on_NixOS
### 👥 Nix ppl
#### [Misterio77](https://github.com/Misterio77)
[Dotfiles](https://github.com/Misterio77/dotfiles)
[Nixcolors](https://github.com/Misterio77/nix-colors)
#### [Vimjoyer](https://github.com/vimjoyer)
#### [Sioodmy](https://github.com/sioodmy/dotfiles)
#### [NotAShelf(https://github.com/NotAShelf/nyx/)
#### [Hutzdog](https://git.sr.ht/~hutzdog/Dotfiles)
#### [Gytis-ivaskevicius](https://github.com/gytis-ivaskevicius/nixfiles/)
#### [Fufexan](https://github.com/fufexan/dotfiles)
#### []()
### 👥 Non-Nix ppl
#### [Bennetthardwick](https://github.com/bennetthardwick/dotfiles)
####
### Desktop features
#### [Hyprland]()
#####[HyprPicker](https://github.com/hyprwm/hyprpicker)

View File

@ -0,0 +1,47 @@
{ config, pkgs, ... }:
{
# Import other configuration modules
# (hardware-configuration.nix is autogenerated upon installation)
# paths in nix expressions are always relative the file which defines them
imports =
[
./hardware-configuration.nix
./my-dev-tools.nix
./my-desktop-env.nix
./etc.nix
];
# Name your host machine
networking.hostName = "mymachine";
# Set your time zone.
time.timeZone = "Europe/Paris";
# Enter keyboard layout
services.xserver.layout = "us";
services.xserver.xkbVariant = "altgr-intl";
# Define user accounts
users.extraUsers =
{
myuser =
{
extraGroups = [ "wheel" "networkmanager" ];
isNormalUser = true;
};
};
# Install some packages
environment.systemPackages =
with pkgs;
[
ddate
testdisk
zsh
];
# Enable the OpenSSH daemon
services.openssh.enable = true;
}

173
flake.nix Normal file
View File

@ -0,0 +1,173 @@
{
description = "Nix Config";
# ===================================================================== #
# ============================== INPUTS =============================== #
# ===================================================================== #
inputs = {
# ============= Official NixOS and HM Package Sources ============= #
nixpkgs.url = "github:NixOS/nixpkgs/release-24.05";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; # also see 'unstable-packages' overlay at 'overlays/default.nix"
hardware.url = "github:nixos/nixos-hardware";
home-manager = {
url = "github:nix-community/home-manager/release-24.05";
inputs.nixpkgs.follows = "nixpkgs";
};
# =========================== Utilities =========================== #
# -------------------------- Lanzaboote --------------------------- #
lanzabote = {
url = "github:nix-community/lanzaboote";
inputs.nixpkgs.follows = "unstable";
};
# ------------ Declarative partitioning and formatting ------------ #
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
# ------------- Secrets mngmt. C ./docs/secretsmgmt.md ------------ #
sops-nix = {
url = "github:mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
# ------------------------------ VIM ------------------------------ #
nixvim = {
url = "github:nix-community/nixvim/nixos-24.05";
inputs.nixpkgs.follows = "nixpkgs";
};
# ------------------------ Windows manager ------------------------ #
hyprland = {
url = "github:hyprwm/hyprland";
inputs.nixpkgs.follows = "nixpkgs";
};
hyprland-plugins = {
url = "github:hyprwm/hyprland-plugins";
inputs.hyprland.follows = "hyprland";
};
hyprland-themes = {
url = "github:hyprwm/hyprland-themes";
inputs.hyprland.follows = "hyprland";
};
# ------------------------------ ZSH ------------------------------ #
nix-zsh-completions = {
url = "github:nix-community/nix-zsh-completions";
inputs.nixpkgs.follows = "nixpkgs";
};
# -------------------------- Nix-Colors --------------------------- #
# https://github.com/Misterio77/nix-colors
nix-colors = {
url = "github:misterio77/nix-colors";
inputs.nixpkgs.follows = "nixpkgs";
};
# ====================== Personal Repositories ====================== #
# Private secrets repo. See ./docs/secretsmgmt.md
# Authenticate via ssh and use shallow clone
nix-secrets = {
url = "git+ssh://git@gitlab.com/emergentmind/nix-secrets.git?ref=main&shallow=1";
flake = false;
};
};
# ===================================================================== #
# ============================== OUTPUTS ============================== #
# ===================================================================== #
outputs = { self, nixpkgs, home-manager, ... } @ inputs:
let
inherit (self) outputs;
forAllSystems = nixpkgs.lib.genAttrs [
"x86_64-linux"
#"aarch64-darwin"
];
inherit (nixpkgs) lib;
configVars = import ./vars { inherit inputs lib; };
configLib = import ./lib { inherit lib; };
specialArgs = { inherit inputs outputs configVars configLib nixpkgs; };
in
{
# ============================ CUSTOM ============================= #
# ---------------------------- Modules ---------------------------- #
# Custom modules to enable special functionality for nixos or home-manager oriented configs.
nixosModules = import ./modules/nixos;
homeManagerModules = import ./modules/home-manager;
# ---------------------------- Overlays --------------------------- #
# Custom modifications/overrides to upstream packages.
overlays = import ./overlays { inherit inputs outputs; };
# ---------------------------- Packages --------------------------- #
# Custom packages to be shared or upstreamed.
packages = forAllSystems
(system:
let pkgs = nixpkgs.legacyPackages.${system};
in import ./pkgs { inherit pkgs; }
);
# ============================= Tools ============================= #
# --------------------------- Formatter --------------------------- #
# Nix formatter available through 'nix fmt' https://nix-community.github.io/nixpkgs-fmt
formatter = forAllSystems
(system:
nixpkgs.legacyPackages.${system}.nixpkgs-fmt
);
# -------------------------- INIT Shell -------------------------- #
# Shell configured with packages that are typically only needed when working on or with nix-config.
devShells = forAllSystems
(system:
let pkgs = nixpkgs.legacyPackages.${system};
in import ./shell.nix { inherit pkgs; }
);
# ======================= Configurations ========================== #
#
# Building configurations available through `just rebuild` or `nixos-rebuild --flake .#hostname`
nixosConfigurations = {
# Jedidiah - the
# jedidiah
# The one who listened too much
rehoboam = lib.nixosSystem {
modules = [ ./system/rehoboam ];
specialArgs = { inherit inputs outputs;};
};
# The rebel who worships the golden calf
jeroboam = lib.nixosSystem {
modules = [ ./systems/jeroboam ];
specialArgs = { inherit inputs outputs;};
}
};
homeConfigurations = {
"sunzi@rehoboam" = lib.homeManagerConfiguration {
modules = [ ./home/sunzi/rehoboam.nix ];
pkgs = pkgsFor.x86_64-linux;
extraSpecialArgs = {inherit inputs nix-colors outputs;};
};
"sunzi@jeroboam" = lib.homeManagerConfiguration {
modules = [ ./home/sunzi/jeroboam.nix ];
pkgs = pkgsFor.x86_64-linux;
extraSpecialArgs = {inherit inputs nix-colors outputs;};
};
"laozi@rehoboam" = lib.homeManagerConfiguration {
modules = [ ./home/laozi/rehoboam.nix ];
pkgs = pkgsFor.x86_64-linux;
extraSpecialArgs = {inherit inputs nix-colors outputs;};
};
"laozi@jeroboam" = lib.homeManagerConfiguration {
modules = [ ./home/laozi/jeroboam.nix ];
pkgs = pkgsFor.x86_64-linux;
extraSpecialArgs = {inherit inputs nix-colors outputs;};
};
};
}
}

View File

@ -0,0 +1,95 @@
{ config, lib, pkgs, outputs, ... }:
{
imports = [
# Packages with custom configs go here
./bash.nix # backup shell
./bat.nix # cat with better syntax highlighting and extras like batgrep.
./direnv.nix # shell environment manager. Hooks inot shell direnv to look for .envrc before prompts
./fonts.nix # core fonts
./git.nix # personal git config
./foot.nix # terminal
./nixvim # vim goodness
./screen.nix # hopefully rarely needed but good to have if so
./ssh.nix # personal ssh configs
./zoxide.nix # cd replacement
./zsh # primary shell: includes zsh, oh-my-zsh, and p10k theme
] ++ (builtins.attrValues outputs.homeManagerModules);
services.ssh-agent.enable = true;
home = {
username = lib.mkDefault "laozi";
homeDirectory = lib.mkDefault "/home/${config.home.username}";
stateVersion = lib.mkDefault "24.05";
sessionPath = [
"$HOME/.local/bin"
"$HOME/scripts/talon_scripts"
];
sessionVariables = {
FLAKE = "$HOME/src/nix-config";
SHELL = "zsh";
TERM = "foot";
TERMINAL = "foot";
EDITOR = "nvim";
MANPAGER = "batman"; # see ./cli/bat.nix
};
};
home.packages = builtins.attrValues {
inherit (pkgs)
# Packages that don't have custom configs go here
# TODO: spaces before comment are removed by nixpkgs-fmt
# See: https://github.com/nix-community/nixpkgs-fmt/issues/305
borgbackup# backups
btop# resource monitor
coreutils# basic gnu utils
# curl
eza# ls replacement
fd# tree style ls
findutils# find
fzf# fuzzy search
jq# JSON pretty printer and manipulator
nix-tree# nix package tree viewer
ncdu# TUI disk usage
pciutils
pfetch# system info
pre-commit# git hooks
p7zip# compression & encryption
ripgrep# better grep
usbutils
tree# cli dir tree viewer
unzip# zip extraction
unrar# rar extraction
wget# downloader
zip; # zip compression
};
nixpkgs = {
overlays = builtins.attrValues outputs.overlays;
config = {
allowUnfree = true;
# Workaround for https://github.com/nix-community/home-manager/issues/2942
allowUnfreePredicate = (_: true);
};
};
nix = {
package = lib.mkDefault pkgs.nix;
settings = {
experimental-features = [ "nix-command" "flakes" "repl-flake" ];
warn-dirty = true;
};
};
programs = {
home-manager.enable = true;
};
# Nicely reload system units when changing configs
systemd.user.startServices = "sd-switch";
}

View File

@ -0,0 +1,20 @@
# https://github.com/sharkdp/bat
# https://github.com/eth-p/bat-extras
{ pkgs, ... }: {
programs.bat = {
enable = true;
config = {
# Show line numbers, Git modifications and file header (but no grid)
style = "numbers,changes,header";
theme = "gruvbox-dark";
};
extraPackages = builtins.attrValues {
inherit (pkgs.bat-extras)
batgrep# search through and highlight files using ripgrep
batdiff# Diff a file against the current git index, or display the diff between to files
batman; # read manpages using bat as the formatter
};
};
}

View File

@ -0,0 +1,81 @@
{ config, lib, pkgs, outputs, configLib, ... }:
{
imports = (configLib.scanPaths ./.)
++ (builtins.attrValues outputs.homeManagerModules);
services.ssh-agent.enable = true;
home = {
username = lib.mkDefault "ta";
homeDirectory = lib.mkDefault "/home/${config.home.username}";
stateVersion = lib.mkDefault "24.05";
sessionPath = [
"$HOME/.local/bin"
"$HOME/scripts/talon_scripts"
];
sessionVariables = {
FLAKE = "$HOME/src/nix-config";
SHELL = "zsh";
TERM = "foot";
TERMINAL = "foot";
EDITOR = "nvim";
MANPAGER = "batman"; # see ./cli/bat.nix
};
};
home.packages = builtins.attrValues {
inherit (pkgs)
# Packages that don't have custom configs go here
# TODO: spaces before comment are removed by nixpkgs-fmt
# See: https://github.com/nix-community/nixpkgs-fmt/issues/305
borgbackup# backups
btop# resource monitor
coreutils# basic gnu utils
# curl
eza# ls replacement
fd# tree style ls
findutils# find
fzf# fuzzy search
jq# JSON pretty printer and manipulator
nix-tree# nix package tree viewer
ncdu# TUI disk usage
pciutils
pfetch# system info
pre-commit# git hooks
p7zip# compression & encryption
ripgrep# better grep
usbutils
tree# cli dir tree viewer
unzip# zip extraction
unrar# rar extraction
wget# downloader
zstd # zstd compression
zip; # zip compression
};
nixpkgs = {
overlays = builtins.attrValues outputs.overlays;
config = {
allowUnfree = true;
# Workaround for https://github.com/nix-community/home-manager/issues/2942
allowUnfreePredicate = (_: true);
};
};
nix = {
package = lib.mkDefault pkgs.nix;
settings = {
experimental-features = [ "nix-command" "flakes" "repl-flake" ];
warn-dirty = false;
};
};
programs = {
home-manager.enable = true;
};
# Nicely reload system units when changing configs
systemd.user.startServices = "sd-switch";
}

View File

@ -0,0 +1,8 @@
{ pkgs, ... }:
{
fonts.fontconfig.enable = true;
home.packages = [
pkgs.nerdfonts # loads the complete collection. look into overide for FiraMono or potentially mononoki
];
}

View File

@ -0,0 +1,29 @@
{ pkgs, lib, config, ... }:
{
programs.git = {
enable = true;
package = pkgs.gitAndTools.gitFull;
userName = "madmin42";
userEmail = "areyoumad@mattmor.in";
aliases = { };
extraConfig = {
init.defaultBranch = "main";
url = {
"ssh://git@github.com" = {
insteadOf = "https://github.com";
};
"ssh://git@gitlab.com" = {
insteadOf = "https://gitlab.com";
};
};
user.signing.key = "";
#TODO sops - Re-enable once sops setup complete
commit.gpgSign = false;
gpg.program = "${config.programs.gpg.package}/bin/gpg2";
};
# enable git Large File Storage: https://git-lfs.com/
# lfs.enable = true;
ignores = [ ".direnv" "result" ];
};
}

View File

@ -0,0 +1,15 @@
{ pkgs, ... }: {
# TODO add ttf-font-awesome or font-awesome for waybar
fontProfiles = {
enable = true;
monospace = {
family = "GeistMono Nerd Font";
package = pkgs.nerdfonts.override { fonts = [ "GeistMono" ]; };
};
regular = {
family = "Geist Mono";
package = pkgs.geist;
};
};
}

19
home/laozi/jeroboam.nix Normal file
View File

@ -0,0 +1,19 @@
{ configVars, ... }:
{
imports = [
#################### Required Configs ####################
common/core #required
#################### Host-specific Optional Configs ####################
common/optional/sops.nix
common/optional/helper-scripts
common/optional/desktop
];
home = {
username = configVars.username;
homeDirectory = "/home/${configVars.username}";
};
}

20
home/laozi/rehoboam.nix Normal file
View File

@ -0,0 +1,20 @@
{ configVars, ... }:
{
imports = [
#################### Required Configs ####################
common/core #required
#################### Host-specific Optional Configs ####################
common/optional/sops.nix
common/optional/helper-scripts
common/optional/desktop
];
services.yubikey-touch-detector.enable = true;
home = {
username = configVars.username;
homeDirectory = "/home/${configVars.username}";
};
}

View File

@ -0,0 +1,78 @@
{
programs.bash = {
enable = true;
enableCompletion = true;
shellAliases = {
ll = "ls -alF";
la = "ls -A";
l = "ls -CF";
vi = "nvim";
vim = "nvim";
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alert = "notify-send --urgency=low -i \"$([ $? = 0 ] && echo terminal || echo error)\" \"$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')\"";
};
initExtra = ''
# ~/.bashrc: executed by bash(1) for non-login shells.
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
complete -C /usr/bin/terraform terraform
'';
};
}

View File

@ -0,0 +1,95 @@
{ config, lib, pkgs, outputs, ... }:
{
imports = [
# Packages with custom configs go here
./bash.nix # backup shell
./bat.nix # cat with better syntax highlighting and extras like batgrep.
./direnv.nix # shell environment manager. Hooks inot shell direnv to look for .envrc before prompts
./fonts.nix # core fonts
./git.nix # personal git config
./foot.nix # terminal
./nixvim # vim goodness
./screen.nix # hopefully rarely needed but good to have if so
./ssh.nix # personal ssh configs
./zoxide.nix # cd replacement
./zsh # primary shell: includes zsh, oh-my-zsh, and p10k theme
] ++ (builtins.attrValues outputs.homeManagerModules);
services.ssh-agent.enable = true;
home = {
username = lib.mkDefault "laozi";
homeDirectory = lib.mkDefault "/home/${config.home.username}";
stateVersion = lib.mkDefault "24.05";
sessionPath = [
"$HOME/.local/bin"
"$HOME/scripts/talon_scripts"
];
sessionVariables = {
FLAKE = "$HOME/src/nix-config";
SHELL = "zsh";
TERM = "foot";
TERMINAL = "foot";
EDITOR = "nvim";
MANPAGER = "batman"; # see ./cli/bat.nix
};
};
home.packages = builtins.attrValues {
inherit (pkgs)
# Packages that don't have custom configs go here
# TODO: spaces before comment are removed by nixpkgs-fmt
# See: https://github.com/nix-community/nixpkgs-fmt/issues/305
borgbackup# backups
btop# resource monitor
coreutils# basic gnu utils
# curl
eza# ls replacement
fd# tree style ls
findutils# find
fzf# fuzzy search
jq# JSON pretty printer and manipulator
nix-tree# nix package tree viewer
ncdu# TUI disk usage
pciutils
pfetch# system info
pre-commit# git hooks
p7zip# compression & encryption
ripgrep# better grep
usbutils
tree# cli dir tree viewer
unzip# zip extraction
unrar# rar extraction
wget# downloader
zip; # zip compression
};
nixpkgs = {
overlays = builtins.attrValues outputs.overlays;
config = {
allowUnfree = true;
# Workaround for https://github.com/nix-community/home-manager/issues/2942
allowUnfreePredicate = (_: true);
};
};
nix = {
package = lib.mkDefault pkgs.nix;
settings = {
experimental-features = [ "nix-command" "flakes" "repl-flake" ];
warn-dirty = true;
};
};
programs = {
home-manager.enable = true;
};
# Nicely reload system units when changing configs
systemd.user.startServices = "sd-switch";
}

View File

@ -0,0 +1,15 @@
{ pkgs, ... }: {
#set to default values
programs.direnv = {
package = pkgs.direnv;
enable = true;
enableBashIntegration = true;
enableZshIntegration = true;
silent = false;
loadInNixShell = true;
direnvrcExtra = "";
nix-direnv = {
enable = true; # better than native direnv nix functionality - https://github.com/nix-community/nix-direnv
package = pkgs.nix-direnv;
};
}

View File

@ -0,0 +1,11 @@
#----=[ Fonts ]=----#
{ pkgs, ... }:
{
fonts.fontconfig.enable = true; # required to autoload fonts from packages
home.packages = [
pkgs.noto-fonts
# pkgs.nerdfonts # => loads the complete collection.
(nerdfonts.override { fonts = [ "FiraCode" "GeistMono" "DroidSansMono" "FontAwesome" "MaterialDesignIcons"]; })
pkgs.meslo-lgs-nf
];
}

View File

@ -0,0 +1,29 @@
{ pkgs, lib, config, ... }:
{
programs.git = {
enable = true;
package = pkgs.gitAndTools.gitFull;
userName = "mattmor";
userEmail = "matt.b.morin@protonmail.com";
aliases = { };
extraConfig = {
init.defaultBranch = "master";
url = {
"ssh://git@github.com" = {
insteadOf = "https://github.com";
};
"ssh://git@gitlab.com" = {
insteadOf = "https://gitlab.com";
};
};
user.signing.key = "";
#TODO sops - Re-enable once sops setup complete
commit.gpgSign = false;
gpg.program = "${config.programs.gpg.package}/bin/gpg2";
};
# enable git Large File Storage: https://git-lfs.com/
# lfs.enable = true;
ignores = [ ".direnv" "result" ];
};
}

View File

@ -0,0 +1,518 @@
{ inputs, pkgs, ... }: {
imports = [
inputs.nixvim.homeManagerModules.nixvim
];
programs.nixvim = {
enable = true;
enableMan = true; # install man pages for nixvim options
clipboard.register = "unnamedplus"; # use system clipboard instead of internal registers
# TODO: nixvim: gruvbox-material
colorschemes = {
gruvbox = {
enable = true;
contrastDark = "medium";
transparentBg = "true";
};
};
options = {
# # Lua reference:
# vim.o behaves like :set
# vim.go behaves like :setglobal
# vim.bo for buffer-scoped options
# vim.wo for window-scoped options (can be double indexed)
#
# ========= General Appearance =========
#
hidden = true; # Makes vim act like all other editors, buffers can exist in the background without being in a window. http://items.sjbach.com/319/configuring-vim-right
number = true; # show line numbers
relativenumber = true; # show relative linenumbers
laststatus = 0; # Display status line always
history = 1000; # Store lots of :cmdline history
showcmd = true; # Show incomplete cmds down the bottom
showmode = true; # Show current mode down the bottom
autoread = true; # Reload files changed outside vim
lazyredraw = true; # Redraw only when needed
showmatch = true; # highlight matching braces
ruler = true; # show current line and column
visualbell = true; # No sounds
listchars = "trail:·"; # Display tabs and trailing spaces visually
wrap = false; # Don't wrap lines
linebreak = true; # Wrap lines at convenient points
# ========= Font =========
guifont = "NotoSansMono:h9"; # fontname:fontsize
# ========= Cursor =========
guicursor = "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20,n-v-i:blinkon0";
# ========= Redirect Temp Files =========
# backup
backupdir = "$HOME/.vim/backup//,/tmp//,.";
writebackup = false;
# swap
directory = "$HOME/.vim/swap//,/tmp//,.";
# ================ Indentation ======================
autoindent = true;
cindent = true; # automatically indent braces
smartindent = true;
smarttab = true;
shiftwidth = 4;
softtabstop = 4;
tabstop = 4;
expandtab = true;
# ================ Folds ============================
foldmethod = "indent"; # fold based on indent
foldnestmax = 3; # deepest fold is 3 levels
foldenable = false; # don't fold by default
# ================ Completion =======================
wildmode = "list:longest";
wildmenu = true; # enable ctrl-n and ctrl-p to scroll thru matches
# stuff to ignore when tab completing
wildignore = "*.o,*.obj,*~,vim/backups,sass-cache,DS_Store,vendor/rails/**,vendor/cache/**,*.gem,log/**,tmp/**,*.png,*.jpg,*.gif";
# ================ Scrolling ========================
scrolloff = 4; # Start scrolling when we're 4 lines away from margins
sidescrolloff = 15;
sidescroll = 1;
# ================ Searching ========================
incsearch = true;
hlsearch = true;
ignorecase = true;
smartcase = true;
# ================ Movement ========================
backspace = "indent,eol,start"; # allow backspace in insert mode
};
#
# ========= UI Plugins =========
#
# Display colors for when # FFFFFF codes are detected in buffer text.
plugins.nvim-colorizer = {
enable = true;
fileTypes = [ "*" ];
};
# TODO: nixvim: additional commands for alpha
# Greeter
plugins.alpha = {
enable = true;
iconsEnabled = true; # installs nvim-web-devicons.
layout = [
{
type = "padding";
val = 2;
}
{
type = "text";
val = [
" ______"
" / /\\"
" / /##\\"
" / /####\\"
" / /######\\"
" / /########\\"
" / /##########\\"
" / /#####/\\#####\\"
" / /#####/++\\#####\\"
" / /#####/++++\\#####\\"
" / /#####/\\+++++\\#####\\"
" / /#####/ \\+++++\\#####\\"
" / /#####/ \\+++++\\#####\\"
" / /#####/ \\+++++\\#####\\"
" / /#####/ \\+++++\\#####\\"
" / /#####/__________\\+++++\\#####\\"
" / \\+++++\\#####\\"
"/__________________________\\+++++\\####/"
"\\+++++++++++++++++++++++++++++++++\\##/"
" \\+++++++++++++++++++++++++++++++++\\/"
" ``````````````````````````````````"
""
];
}
{
type = "padding";
val = 2;
}
{
type = "group";
val = [
{
command = "<CMD>ene <CR>";
desc = " New file";
shortcut = "<Leader>cn";
}
{
command = ":qa<CR>";
desc = " Quit Neovim";
shortcut = ":q";
}
];
}
{
type = "padding";
val = 2;
}
{
opts = {
hl = "Keyword";
position = "center";
};
type = "text";
val = "The way out is through.";
}
];
};
# TODO: nixvim switch to lightline and lightline-bufferline
plugins.airline = {
enable = true;
powerline = true;
extensions = {
# TODO: nixvim: Figure out tabline extension stuff in nixvim
# TODO: nixvim: Possibly use bufferline or lightline-bufferline instead
# """" Tabline settings
#
# " show buffer numbers in the tab line for easier deleting
# " use :echo airline#extensions#tabline#get() to see what is actually set
# let g:airline#extensions#tabline#show_tab_nr = 1
# let g:airline#extensions#tabline#tabs_label = 't'
# let g:airline#extensions#tabline#buffers_label = 'b'
# let g:airline#extensions#tabline#buffer_nr_show = 1
#
# " Disable showing buffer numbers for splits when using tabs. This gets quite
# " annoying if there's quite a few splits open.
# let g:airline#extensions#tabline#show_splits = 0
#
# " Title adjustments
# "airline_symbols Show tab numbers in the tab title
# let g:airline#extensions#tabline#tab_nr_type = 1
#
# " https://github.com/vim-airline/vim-airline/issues/476
#
# " show the buffer index
# "let g:airline#extensions#tabline#buffer_idx_mode = 1
# "
# " https://github.com/vim-airline/vim-airline/wiki/Configuration-Examples-and-Snippets#a-different-example-add-the-window-number-in-front-of-the-mode
# function! WindowNumber(...)
# let builder = a:1
# let context = a:2
# call builder.add_section('airline_b', '%{tabpagewinnr(tabpagenr())}')
# return 0
# endfunction
};
};
plugins.fidget = {
enable = true;
text.spinner = "triangle";
};
# ========= Undo history ========
# TODO: nixvim: set up alos, map to <leader>u
# plugins.undotree = {};
#
# ========= File Search =========
#
plugins.telescope = {
# https://github.com/nvim-telescope/telescope.nvim
enable = true;
extensions.fzy-native.enable = true;
};
# ========= File Nav ===========
# TODO: nixvim set this one up
# plugins.harpoon = {};
#
# ========== Dev Tools =========
#
plugins.fugitive.enable = true; # vim-fugitive
# plugins.surround.enable = true; # vim-surround
# Load Plugins that aren't provided as modules by nixvim
extraPlugins = builtins.attrValues {
inherit (pkgs.vimPlugins)
# linting and fixing (config in extraConfigVim)
# https://github.com/dense-analysis/ale
# TODO: nixvim: revamp setup to lua
# there is also a lightline-ale plugin/extension for lightline when you get around to it
# by default ALE completion is disabled. need to determine if it's worth enabling and ditching youcompleteme ... it likely is for simplicity!
ale
vim-illuminate# Highlight similar words as are under the cursor
vim-numbertoggle# Use relative number on focused buffer only
range-highlight-nvim# Highlight range as specified in commandline e.g. :10,15
vimade# Dim unfocused buffers
vim-twiggy# Fugitive plugin to add branch control
vimwiki# Vim Wiki
YouCompleteMe# Code completion engine
# TODO: nixvim: make sure this is working and not conflicting with YCM
# supertab # Use <tab> for insert completion needs - https://github.com/ervandew/supertab/
# Keep vim-devicons as last entry
vim-devicons;
};
# ========= Mapleader =========
globals.mapleader = ";";
#
# ========= Key binds =========
#
# MODES Key:
# "n" Normal mode
# "i" Insert mode
# "v" Visual and Select mode
# "s" Select mode
# "t" Terminal mode
# "" Normal, visual, select and operator-pending mode
# "x" Visual mode only, without select
# "o" Operator-pending mode
# "!" Insert and command-line mode
# "l" Insert, command-line and lang-arg mode
# "c" Command-line mode
keymaps = [
# TODO: nixvim: Test sudo save
# {
# # sudo save
# mode= ["c"];
# key = "w!!";
# action = "<cmd>w !sudo tee > /dev/null %<CR>";
# }
{
# edit vimrc
mode = [ "" ];
key = "<Leader>ve";
action = "<cmd>e ~/.config/.vimrc<CR>";
options = { noremap = true; };
}
{
# reload vimrc
mode = [ "n" ];
key = "<Leader>vr";
action = "<cmd>so $MYVIMRC<CR>";
options = { noremap = true; };
}
{
# clear search highlighting
mode = [ "n" ];
key = "<space><space>";
action = "<cmd>nohlsearch<CR>";
options = { noremap = true; };
}
# ======== Movement ========
{
# move down through wrapped lines
mode = [ "n" ];
key = "j";
action = "gj";
options = { noremap = true; };
}
{
# move up through wrapped lines
mode = [ "n" ];
key = "k";
action = "gk";
options = { noremap = true; };
}
{
# rebind 1/2 page down
mode = [ "n" ];
key = "<C-j>";
action = "<C-d>";
options = { noremap = true; };
}
{
# rebind 1/2 page up
mode = [ "n" ];
key = "<C-k>";
action = "<C-u>";
options = { noremap = true; };
}
{
# move to beginning/end of line
mode = [ "n" ];
key = "E";
action = "$";
options = { noremap = true; };
}
# {
# # disable default move to beginning/end of line
# mode = ["n"];
# key = "$";
# action = "<nop>";
# }
# =========== Fugitive Plugin =========
{
# quick git status
mode = [ "n" ];
key = "<Leader>gs";
action = "<cmd>G<CR>";
options = { noremap = true; };
}
{
# quick merge command: take from right page (tab 3) upstream
mode = [ "n" ];
key = "<Leader>gj";
action = "<cmd>diffget //3<CR>";
options = { noremap = true; };
}
{
# quick merge command: take from left page (tab 2) head
mode = [ "n" ];
key = "<Leader>gf";
action = "<cmd>diffget //2<CR>";
options = { noremap = true; };
}
# ========== Telescope Plugin =========
{
# find files
mode = [ "n" ];
key = "<Leader>ff";
action = "<cmd>Telescope find_files<CR>";
options = { noremap = true; };
}
{
# live grep
mode = [ "n" ];
key = "<Leader>fg";
action = "<cmd>Telescope live_grep<CR>";
options = { noremap = true; };
}
{
# buffers
mode = [ "n" ];
key = "<Leader>fb";
action = "<cmd>Telescope buffers<CR>";
options = { noremap = true; };
}
{
# help tags
mode = [ "n" ];
key = "<Leader>fh";
action = "<cmd>Telescope help_tags<CR>";
options = { noremap = true; };
}
# ========= Twiggy =============
{
# toggle display twiggy
mode = [ "n" ];
key = "<Leader>tw";
action = ":Twiggy<CR>";
options = { noremap = true; };
}
];
extraConfigVim = ''
" ================ Persistent Undo ==================
" Keep undo history across sessions, by storing in file.
" Only works all the time.
if has('persistent_undo')
silent !mkdir ~/.vim/backups > /dev/null 2>&1
set undodir=~/.vim/backups
set undofile
endif
" ================ Vim Wiki config =================
" See :h vimwiki_list for info on registering wiki paths
let wiki_0 = {}
let wiki_0.path = '~/dotfiles.wiki/'
let wiki_0.index = 'home'
let wiki_0.syntax = 'markdown'
let wiki_0.ext = '.md'
" fill spaces in page names with _ in pathing
let wiki_0.links_space_char = '_'
" TODO: nixvim: CONFIRM THESE PATHS FOR NIXOS
let wiki_1 = {}
let wiki_1.path = '~/doc/foundry/thefoundry.wiki/'
let wiki_1.index = 'home'
let wiki_1.syntax = 'markdown'
let wiki_1.ext = '.md'
" fill spaces in page names with _ in pathing
let wiki_1.links_space_char = '_'
let g:vimwiki_list = [wiki_0, wiki_1]
" let g:vimwiki_list = [wiki_0, wiki_1, wiki_2]
" ================ Ale ========================
" linter and fixer packages have to be installed via AUR or pamac
let g:ale_linters = {
\ 'c': ['clang-tidy'],
\ 'python': ['flake8'],
\ 'vim': ['vint'],
\ 'markdown': ['markdownlint'],
\ }
let g:ale_fixers = {
\ 'c': ['clang-format'],
\ 'javascript': ['prettier', 'eslint'],
\ 'json': ['fixjson', 'prettier'],
\ 'python': ['black', 'isort'],
\ }
" Set global fixers for all file types except Markdown
" Why? because double spaces at the end of a line in markdown indicate a
" linebreak without creating a new paragraph
function! SetGlobalFixers()
let g:ale_fixers['*'] = ['trim_whitespace', 'remove_trailing_lines']
endfunction
augroup GlobalFixers
autocmd!
autocmd VimEnter * call SetGlobalFixers()
augroup END
" Set buffer-local fixers for Markdown files
augroup MarkdownFixers
autocmd!
autocmd FileType markdown let b:ale_fixers = ['prettier']
augroup END
let g:ale_fix_on_save = 1
'';
# extraConfigLua = ''
# -- ========= Colorscheme Overrides ==========
# -- Override cursor color and blink for nav and visual mode
# vim.cmd("highlight Cursor guifg=black guibg=orange");
#
# -- Override cursor color for insert mode
# vim.cmd("highlight iCursor guifg=black guibg=orange");
# '';
};
}
# # Syntax support
# vim-polyglot # a collection of language packs for vim
#
# # The following are commented out because they are already included in vim-polyglot
# # but in case poly-glot fails I want to be able to quickly enable what I need.
# haskell-vim
# plantuml-syntax
# pgsql-vim
# python-syntax
# rust-vim
# vim-markdown
# vim-nix
# vim-terraform
# vim-toml

View File

@ -0,0 +1,33 @@
{ outputs, lib, ... }:
{
programs.ssh = {
enable = true;
extraConfig = ''
#req'd for enabling yubikey-agent
AddKeysToAgent yes
'';
matchBlocks = {
"yubikey-hosts" = {
host = "gitlab.com github.com";
forwardAgent = true;
identitiesOnly = true;
identityFile = [
"~/.ssh/id_yubikey" # This is an auto symlink to whatever yubikey is plugged in. See hosts/common/optional/yubikey
"~/.ssh/id_mila"
"~/.ssh/id_hello" # fallback to id_hello if yubis aren't present
];
};
};
# FIXME: This should probably be for git systems only?
#controlMaster = "auto";
#controlPath = "~/.ssh/sockets/S.%r@%h:%p";
#controlPersist = "60m";
#extraConfig = ''
#Include config.d/*
#'';
};
# home.file.".ssh/sockets/.keep".text = "# Managed by Home Manager";
}

View File

@ -0,0 +1,10 @@
{
programs.zoxide = {
enable = true;
enableBashIntegration = true;
enableZshIntegration = true;
options = [
"--cmd cd" #replace cd with z and zi (via cdi)
];
};
}

View File

@ -0,0 +1,130 @@
{ pkgs, ... }: {
programs.zsh = {
enable = true;
# relative to ~
dotDir = ".config/zsh";
enableCompletion = true;
syntaxHighlighting.enable = true;
autocd = true;
enableAutosuggestions = true;
history.size = 10000;
history.share = true;
plugins = [
{
name = "powerlevel10k-config";
src = ./p10k;
file = "p10k.zsh";
}
{
name = "zsh-powerlevel10k";
src = "${pkgs.zsh-powerlevel10k}/share/zsh-powerlevel10k/";
file = "powerlevel10k.zsh-theme";
}
{
name = "zsh-term-title";
src = "${pkgs.zsh-term-title}/share/zsh/zsh-term-title/";
}
{
name = "cd-gitroot";
src = "${pkgs.cd-gitroot}/share/zsh/cd-gitroot";
}
{
name = "zhooks";
src = "${pkgs.zhooks}/share/zsh/zhooks";
}
];
initExtraFirst = ''
# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
if [[ -r "''${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-''${(%):-%n}.zsh" ]]; then
source "''${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-''${(%):-%n}.zsh"
fi
'';
initExtra = ''
# autoSuggestions config
unsetopt correct # autocorrect commands
setopt hist_ignore_all_dups # remove older duplicate entries from history
setopt hist_reduce_blanks # remove superfluous blanks from history items
setopt inc_append_history # save history entries as soon as they are entered
# auto complete options
setopt auto_list # automatically list choices on ambiguous completion
setopt auto_menu # automatically use menu completion
zstyle ':completion:*' menu select # select completions with arrow keys
zstyle ':completion:*' group-name "" # group results by category
zstyle ':completion:::::' completer _expand _complete _ignored _approximate # enable approximate matches for completion
# bindkey '^I' forward-word # tab
# bindkey '^[[Z' backward-word # shift+tab
# bindkey '^ ' autosuggest-accept # ctrl+space
'';
oh-my-zsh = {
enable = true;
# Standard OMZ plugins pre-installed to $ZSH/plugins/
# Custom OMZ plugins are added to $ZSH_CUSTOM/plugins/
# Enabling too many plugins will slowdown shell startup
plugins = [
"git"
"sudo" # press Esc twice to get the previous command prefixed with sudo https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/sudo
];
extraConfig = ''
# Display red dots whilst waiting for completion.
COMPLETION_WAITING_DOTS="true"
'';
};
shellAliases = {
# Overrides those provided by OMZ libs, plugins, and themes.
# For a full list of active aliases, run `alias`.
#-------------Bat related------------
cat = "bat";
diff = "batdiff";
rg = "batgrep";
man = "batman";
#------------Navigation------------
doc = "cd $HOME/documents";
scripts = "cd $HOME/scripts";
ts = "cd $HOME/.talon/user/fidget";
src = "cd $HOME/src";
edu = "cd $HOME/src/edu";
dfs = "cd $HOME/src/dotfiles";
dfsw = "cd $HOME/src/dotfiles.wiki";
nfs = "cd $HOME/src/nix-config";
uc = "cd $HOME/src/unmovedcentre";
l = "eza -lah";
la = "eza -lah";
ll = "eza -lh";
ls = "eza";
lsa = "eza -lah";
#-------------Neovim---------------
e = "nvim";
vi = "nvim";
vim = "nvim";
#-----------Nix related----------------
ne = "nix-instantiate --eval";
nb = "nix-build";
ns = "nix-shell";
#-----------Remotes----------------
cakes = "ssh -l freshcakes freshcakes.memeoid.cx";
gooey = "ssh -l pi 10.13.37.69";
gusto = "ssh -l ta 10.13.37.5";
grief = "ssh -l ta 10.13.37.7";
#-------------Git Goodness-------------
# just reference `$ alias` and use the defautls, they're good.
};
};
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
{
programs.brave = {
enable = true;
commandLineArgs = [
"--no-default-browser-check"
"--restore-last-sesion"
];
};
}

View File

@ -0,0 +1,9 @@
{
programs.brave = {
enable = true;
commandLineArgs = [
"--no-default-browser-check"
"--restore-last-sesion"
];
};
}

View File

@ -0,0 +1,8 @@
#
# TODO stage 4: this is a placeholder list for now
#
signal-desktop
telegram-desktop
discord
slack

View File

@ -0,0 +1,17 @@
{
imports = [
# Packages with custom configs go here
./hyprland
########## Utilities ##########
# ./services/dunst.nix # Notification daemon
# ./waybar.nix # infobar
#./rofi-wayland.nix #app launcher
#./hyprpaper.nix #wallpaper daemon
# ./gtk.nix # mainly in gnome
# ./qt.nix # mainly in kde
# ./fonts.nix
];
}

View File

@ -0,0 +1,15 @@
{ pkgs, ... }: {
# TODO add ttf-font-awesome or font-awesome for waybar
fontProfiles = {
enable = true;
monospace = {
family = "FiraCode Nerd Font";
package = pkgs.nerdfonts.override { fonts = [ "FiraCode" ]; };
};
regular = {
family = "Fira Sans";
package = pkgs.fira;
};
};
}

View File

@ -0,0 +1,34 @@
{ config, pkgs, lib, ... }:
{
gtk = {
enable = true;
#font.name = TODO see misterio https://github.com/Misterio77/nix-config/blob/f4368087b0fd0bf4a41bdbf8c0d7292309436bb0/home/misterio/features/desktop/common/gtk.nix he has a custom config for managing fonts, colorsheme etc.
theme = {
name = "adwaita-dark";
package = pkgs.adw-gtk3;
};
iconTheme = {
name = "elementary-Xfce-dark";
package = pkgs.elementary-xfce-icon-theme;
};
#TODO add ascendancy cursor pack
#cursortTheme.name = "";
#cursortTheme.package = ;
# https://store.kde.org/p/2135229 Catpuccin Mocha Modern Aurora 6 Plasma 6 Window Decorations
gtk3.extraConfig = {
Settings = ''
gtk-application-prefer-dark-theme=1
'';
};
gtk4.extraConfig = {
Settings = ''
gtk-application-prefer-dark-theme=1
'';
};
};
}

View File

@ -0,0 +1,141 @@
# +++ https://github.com/Misterio77/nix-config/blob/main/home/misterio/features/desktop/hyprland/basic-binds.nix
{ lib, config, ... }: {
wayland.windowManager.hyprland.settings = {
bindm = [
"SUPER,mouse:272,movewindow"
"SUPER,mouse:273,resizewindow"
];
bind =
let
workspaces = [
"0"
"1"
"2"
"3"
"4"
"5"
"6"
"7"
"8"
"9"
"F1"
"F2"
"F3"
"F4"
"F5"
"F6"
"F7"
"F8"
"F9"
"F10"
"F11"
"F12"
];
# Map keys (arrows and hjkl) to hyprland directions (l, r, u, d)
directions = rec {
left = "l";
right = "r";
up = "u";
down = "d";
h = left;
l = right;
k = up;
j = down;
};
#swaylock = "${config.programs.swaylock.package}/bin/swaylock";
#playerctl = "${config.services.playerctld.package}/bin/playerctl";
#playerctld = "${config.services.playerctld.package}/bin/playerctld";
#makoctl = "${config.services.mako.package}/bin/makoctl";
#wofi = "${config.programs.wofi.package}/bin/wofi";
#pass-wofi = "${pkgs.pass-wofi.override {
#pass = config.programs.password-store.package;
#}}/bin/pass-wofi";
#grimblast = "${pkgs.inputs.hyprwm-contrib.grimblast}/bin/grimblast";
#pactl = "${pkgs.pulseaudio}/bin/pactl";
#tly = "${pkgs.tly}/bin/tly";
#gtk-play = "${pkgs.libcanberra-gtk3}/bin/canberra-gtk-play";
#notify-send = "${pkgs.libnotify}/bin/notify-send";
#gtk-launch = "${pkgs.gtk3}/bin/gtk-launch";
#xdg-mime = "${pkgs.xdg-utils}/bin/xdg-mime";
#defaultApp = type: "${gtk-launch} $(${xdg-mime} query default ${type})";
#terminal = config.home.sessionVariables.TERM;
#browser = defaultApp "x-scheme-handler/https";
#editor = defaultApp "text/plain";
in
[
#################### Program Launch ####################
"SHIFTALT,Return,exec,kitty"
#################### Basic Bindings ####################
"SHIFTALT,q,killactive"
"SUPERSHIFT,e,exit"
"SUPER,s,togglesplit"
"SUPER,f,fullscreen,1"
"SUPERSHIFT,f,fullscreen,0"
"SUPERSHIFT,space,togglefloating"
"SUPER,minus,splitratio,-0.25"
"SUPERSHIFT,minus,splitratio,-0.3333333"
"SUPER,equal,splitratio,0.25"
"SUPERSHIFT,equal,splitratio,0.3333333"
"SUPER,g,togglegroup"
"SUPER,t,lockactivegroup,toggle"
"SUPER,apostrophe,changegroupactive,f"
"SUPERSHIFT,apostrophe,changegroupactive,b"
"SUPER,u,togglespecialworkspace"
"SUPERSHIFT,u,movetoworkspacesilent,special"
"SUPER,i,pseudo"
] ++
# Change workspace
(map
(n:
"ALT,${n},workspace,name:${n}"
)
workspaces) ++
# Move window to workspace
(map
(n:
"SHIFTALT,${n},movetoworkspacesilent,name:${n}"
)
workspaces) ++
# Move focus
(lib.mapAttrsToList
(key: direction:
"ALT,${key},movefocus,${direction}"
)
directions) ++
# Swap windows
(lib.mapAttrsToList
(key: direction:
"SUPERSHIFT,${key},swapwindow,${direction}"
)
directions) ++
# Move windows
(lib.mapAttrsToList
(key: direction:
"SHIFTALT,${key},movewindoworgroup,${direction}"
)
directions) ++
# Move monitor focus
(lib.mapAttrsToList
(key: direction:
"SUPERALT,${key},focusmonitor,${direction}"
)
directions) ++
# Move workspace to other monitor
(lib.mapAttrsToList
(key: direction:
"SUPERALTSHIFT,${key},movecurrentworkspacetomonitor,${direction}"
)
directions);
};
}

View File

@ -0,0 +1,100 @@
{ lib, config, pkgs, ... }:
let
hyprland = pkgs.inputs.hyprland.hyprland.override {wrapRuntimeDeps = false;};
xdph = pkgs.inputs.hyprland.xdg-desktop-portal-hyprland.override {inherit hyprland;};
in {
imports = [
# custom key binds
./binds.nix
];
# NOTE: xdg portal package is currently set in /hosts/common/optional/hyprland.nix
wayland.windowManager.hyprland = {
enable = true;
# systemd = {
# enable = true;
# # TODO: experiment with whether this is required.
# # Same as default, but stop the graphical session too
# extraCommands = lib.mkBefore [
# "systemctl --user stop graphical-session.target"
# "systemctl --user start hyprland-session.target"
# ];
# };
# plugins = [];v
settings = {
env = [
"NIXOS_OZONE_WL, 1" # for ozone-based and electron apps to run on wayland
"MOZ_ENABLE_WAYLAND, 1" # for firefox to run on wayland
"MOZ_WEBRENDER, 1" # for firefox to run on wayland
"XDG_SESSION_TYPE,wayland"
"WLR_NO_HARDWARE_CURSORS,1"
"WLR_RENDERER_ALLOW_SOFTWARE,1"
# "QT_QPA_PLATFORM,wayland"
];
# general = {
# gaps_in = 8;
# gaps_out = 5;
# border_size = 3;
# cursor_inactive_timeout = 4;
# };
#
# input = {
# kb_layout = "us";
# # mouse = {
# # acceleration = 1.0;
# # naturalScroll = true;
# # };
# };
#
# decoration = {
# active_opacity = 0.94;
# inactive_opacity = 0.75;
# fullscreen_opacity = 1.0;
# # rounding = 7;
# blur = {
# enabled = false;
# size = 5;
# passes = 3;
# new_optimizations = true;
# ignore_opacity = true;
# };
# drop_shadow = false;
# shadow_range = 12;
# shadow_offset = "3 3";
# "col.shadow" = "0x44000000";
# "col.shadow_inactive" = "0x66000000";
# };
# exec-once = ''${startupScript}/path'';
};
# load at the end of the hyperland set
# extraConfig = '' '';
};
# # TODO: move below into individual .nix files with their own configs
# home.packages = builtins.attrValues {
# inherit (pkgs)
# nm-applet --indicator & # notification manager applet.
# bar
# waybar # closest thing to polybar available
# where is polybar? not supported yet: https://github.com/polybar/polybar/issues/414
# eww # alternative - complex at first but can do cool shit apparently
#
# # Wallpaper daemon
# hyprpaper
# swaybg
# wpaperd
# mpvpaper
# swww # vimjoyer recoomended
# nitrogen
#
# # app launcher
# rofi-wayland;
# wofi # gtk rofi
# };
}

View File

@ -0,0 +1,79 @@
# https://www.reddit.com/r/hyprland/comments/1b2l3lc/hyprlock_with_pywal/
# https://github.com/zDyanTB/HyprNova/blob/master/.config/hypr/hyprlock.conf
{
source = $HOME/.cache/wal/colors-hyprland.conf
background {
monitor =
path = $HOME/.current_wallpaper # only png supported for now
# color = $color1
# all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations
blur_size = 4
blur_passes = 3 # 0 disables blurring
noise = 0.0117
contrast = 1.3000 # Vibrant!!!
brightness = 0.8000
vibrancy = 0.2100
vibrancy_darkness = 0.0
}
input-field {
monitor =
size = 250, 50
outline_thickness = 3
dots_size = 0.26 # Scale of input-field height, 0.2 - 0.8
dots_spacing = 0.64 # Scale of dots' absolute size, 0.0 - 1.0
dots_center = true
outer_color = $color0
inner_color = $color0
font_color = $color6
fade_on_empty = true
placeholder_text = <i>Password...</i> # Text rendered in the input box when it's empty.
hide_input = false
position = 0, 50
halign = center
valign = bottom
}
# Current time
label {
monitor =
text = cmd[update:1000] echo "<b><big> $(date +"%H:%M:%S") </big></b>"
color = $color6
font_size = 64
font_family = JetBrains Mono Nerd Font 10
shadow_passes = 3
shadow_size = 4
position = 0, 16
halign = center
valign = center
}
# Date
label {
monitor =
text = cmd[update:18000000] echo "<b> "$(date +'%A, %-d %B %Y')" </b>"
color = $color7
font_size = 24
font_family = JetBrains Mono Nerd Font 10
position = 0, -16
halign = center
valign = center
}
label {
monitor =
text = Hey $USER
color = $color7
font_size = 18
font_family = Inter Display Medium
position = 0, 30
halign = center
valign = bottom
}
}

View File

@ -0,0 +1,75 @@
{
lib,
stdenv,
pkg-config,
cmake,
cairo,
expat,
file,
fribidi,
hyprlang,
libdatrie,
libGL,
libjpeg,
libselinux,
libsepol,
libthai,
libwebp,
pango,
pcre,
pcre2,
util-linux,
wayland,
wayland-protocols,
wayland-scanner,
libXdmcp,
debug ? false,
version ? "git",
}:
stdenv.mkDerivation {
pname = "hyprpaper" + lib.optionalString debug "-debug";
inherit version;
src = ../.;
cmakeBuildType =
if debug
then "Debug"
else "Release";
nativeBuildInputs = [
cmake
pkg-config
];
buildInputs = [
cairo
expat
file
fribidi
hyprlang
libdatrie
libGL
libjpeg
libselinux
libsepol
libthai
libwebp
pango
pcre
pcre2
wayland
wayland-protocols
wayland-scanner
libXdmcp
util-linux
];
meta = with lib; {
homepage = "https://github.com/hyprwm/hyprpaper";
description = "A blazing fast wayland wallpaper utility with IPC controls";
license = licenses.bsd3;
platforms = platforms.linux;
mainProgram = "hyprpaper";
};
}

View File

@ -0,0 +1,14 @@
{ pkgs, ... }:
{
qt = {
enable = true;
platformTheme = "gtk2";
style = {
name = "gtk2";
# autodetected themes:
# adwaita, adwaita-dark, adwaita-highcontrast, adwaita-hightcontrastinverse, breeze, bb10bright, bb10dark, cde, cleanlooks, gtk2, motfi, plastique
#theme package
package = pkgs.qt6Packages.qt6gtk2;
};
};
}

View File

@ -0,0 +1,96 @@
{
pkgs,
theme,
...
}: {
home.packages = with pkgs; [
libsixel
# for displaying images
];
programs.foot = {
enable = true;
server.enable = false;
settings = {
main = {
app-id = "foot";
title = "foot";
locked-title = "no";
term = "xterm-256color";
font = "monospace:size=10.5";
vertical-letter-offset = "-0.75";
pad = "12x21 center";
resize-delay-ms = 100;
notify = "notify-send -a \${app-id} -i \${app-id} \${title} \${body}";
selection-target = "primary";
# box-drawings-uses-font-glyphs = "yes";
dpi-aware = "yes";
bold-text-in-bright = "no";
word-delimiters = ",`|:\"'()[]{}<>";
};
cursor = {
style = "beam";
beam-thickness = 2;
};
scrollback = {
lines = 10000;
multiplier = 3;
};
bell = {
urgent = "yes";
notify = "yes";
command = "notify-send bell";
command-focused = "no";
};
url = {
launch = "xdg-open \${url}";
label-letters = "sadfjklewcmpgh";
osc8-underline = "url-mode";
protocols = "http, https, ftp, ftps, file, gemini, gopher, irc, ircs";
uri-characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.,~:;/?#@!$&%*+=\"'()[]";
};
colors = with theme.colors; {
alpha = "0.75";
foreground = text;
background = base;
regular0 = surface1;
regular1 = red;
regular2 = green;
regular3 = yellow;
regular4 = blue;
regular5 = pink;
regular6 = teal;
regular7 = subtext1;
bright0 = surface2;
bright1 = red;
bright2 = green;
bright3 = yellow;
bright4 = blue;
bright5 = pink;
bright6 = teal;
bright7 = subtext0;
};
mouse = {
hide-when-typing = "yes";
};
key-bindings = {
show-urls-launch = "Control+Shift+u";
unicode-input = "Control+Shift+i";
};
mouse-bindings = {
selection-override-modifiers = "Shift";
primary-paste = "BTN_MIDDLE";
select-begin = "BTN_LEFT";
select-begin-block = "Control+BTN_LEFT";
select-extend = "BTN_RIGHT";
select-extend-character-wise = "Control+BTN_RIGHT";
select-word = "BTN_LEFT-2";
select-word-whitespace = "Control+BTN_LEFT-2";
#select-row = "BTN_LEFT-3";
};
};
};
}

View File

@ -0,0 +1,435 @@
/*
VS Codium
*/
{ pkgs, inputs, system, config, ... }:
{
programs.vscodium = {
enable = true;
package = pkgs.unstable.vscodium;
enableExtensionUpdateCheck = true;
enableUpdateCheck = true;
extensions = let
t = inputs.nix-vscode-extensions.extensions.${system}.forVSCodeVersion
config.programs.vscode.package.version;
p = t.vscode-marketplace;
in [
# general
p.bierner.emojisense
p.bierner.markdown-checkbox
p.bierner.markdown-emoji
p.davidlday.languagetool-linter
p.dracula-theme.theme-dracula
p.eamodio.gitlens
p.gruntfuggly.todo-tree
p.mkhl.direnv
p.robole.marky-stats
p.stkb.rewrap
p.tomoki1207.pdf
p.tyriar.sort-lines
# haskell
p.haskell.haskell # language server
p.justusadam.language-haskell # syntax highlighting
p.s0kil.vscode-hsx # HSX is HTML templating for IHP
# other languages
p.banacorn.agda-mode
p.denoland.vscode-deno
p.jnoortheen.nix-ide
p.kokakiwi.vscode-just
p.mark-hansen.hledger-vscode
p.samuelcolvin.jinjahtml
p.scala-lang.scala
p.scalameta.metals
p.tamasfe.even-better-toml
# C#
# the nixpkgs version of this has a patch for a problem where uname isn't found
pkgs.unstable.vscode-extensions.ms-dotnettools.csharp
p.ms-dotnettools.vscode-dotnet-runtime
p.csharpier.csharpier-vscode
];
{
"extensionsGallery": {
"serviceUrl": "https://open-vsx.org/vscode/gallery",
"itemUrl": "https://open-vsx.org/vscode/item"
"cacheUrl": "",
"controlUrl": ""
}
}
keybindings = [
{
key = "ctrl+shift+t";
command = "workbench.action.terminal.focus";
when = "!terminalFocus";
}
{
key = "ctrl+shift+t";
command = "workbench.action.focusActiveEditorGroup";
when = "terminalFocus";
}
# use ctrl+c in the terminal for copying if there's a selection
# (passed through to the shell otherwise)
# thanks to https://stackoverflow.com/a/69928270/7659481
{
key = "ctrl+c";
command = "workbench.action.terminal.copySelection";
when = "terminalFocus && terminalProcessSupported && terminalTextSelected";
}
# use ctrl+v in the terminal for pasting
{
key = "ctrl+v";
command = "workbench.action.terminal.paste";
when = "terminalFocus && terminalProcessSupported";
}
# workaround to use Neo2 backslash for Agda Unicode input
# neither `[Backslash]` nor `capslock+u` work
# taken from the record keys function from the shortcut editor
{
key = "[Backslash]";
command = "-agda-mode.input-symbol[Activate]";
}
{
key = "["; # this is what Neo2 ß registers as
command = "agda-mode.input-symbol[Activate]";
when = "editorTextFocus && !editorHasSelection && editorLangId == 'agda'";
}
{
key = "ctrl+x ctrl+=";
command = "-agda-mode.lookup-symbol";
}
{
key = "ctrl+c ctrl+s";
command = "agda-mode.lookup-symbol";
when = "editorTextFocus && !editorHasSelection && editorLangId == 'agda'";
}
];
userSettings = {
# ======== General ========
"workbench.commandPalette.experimental.suggestCommands" = true;
"security.workspace.trust.enabled" = false;
"update.showReleaseNotes" = false;
"extensions.autoUpdate" = false;
# Themes
"workbench.colorTheme": "Kimbie Dark"
"workbench.iconTheme" = "material-icon-theme";
"workbench.productIconTheme" = "material-product-icons";
"workbench.cloudChanges.continueOn" = "off";
"workbench.cloudChanges.autoResume" = "off";
"workbench.startupEditor" = "none";
"update.mode" = "start";
"window.menuBarVisibility": "compact",
# ======== Telemetry ========
"continue.telemetryEnabled" = false;
"allowAnonymousTelemetry" = false;
"telemetry.telemetryLevel" = "off";
"aws.telemetry" = false;
"redhat.telemetry.enabled" = false;
"aws.codeWhisperer.shareCodeWhispererContentWithAWS" = false;
"code-runner.enableAppInsights" = false;
"workbench.enableExperiments" = false;
"typescript.tsserver.experimental.enableProjectDiagnostics" = false;
"keyboard.dispatch" = "keyCode";
# ======== Terminal ========
"terminal.integrated.splitCwd" = "workspaceRoot";
"terminal.integrated.confirmOnKill" = "always";
"terminal.integrated.copyOnSelection" = true;
"terminal.integrated.tabs.hideCondition" = "never";
"terminal.integrated.scrollback" = 5000;
"terminal.integrated.cursorStyle" = "line";
"terminal.integrated.cursorBlinking" = "solid";
"terminal.integrated.cursorWidth" = 1;
"terminal.integrated.fontFamily" = "Geist";
"terminal.integrated.fontSize" = 14;
"terminal.integrated.lineHeight" = 1.2;
"terminal.integrated.rightClickBehavior" = "default";
"terminal.integrated.minimumContrastRatio" = 1;
# ===== Linux =====
/*
vscode fixes colors in the termial to meet certain contrast ratios
I just want the original colors
*/
# "terminal.integrated.shell.linux" = "${pkgs.fish}/bin/fish";
# "terminal.integrated.shellArgs.linux" = [
# "--login"
# "-c"
# "set -x EDITOR vim"
# ];
"terminal.integrated.defaultProfile.linux" = "zsh";
"terminal.integrated.profiles.linux" = {
"zsh" = {
"path" = "${pkgs.zsh}/bin/zsh";
};
};
"terminal.external.linuxExec" = "#!/bin/bash";
# ===== Win =====
"terminal.integrated.defaultProfile.windows" = "Git Bash";
"terminal.integrated.profiles.windows" = {
"Custom Init" = {
"path" = "pwsh.exe";
"args" = [
"-noexit";
"-file";
"${env:APPDATA}\\PowerShell\\custom-init.ps1"
]
}
};
"terminal.integrated.env.windows" = {
"CHERE_INVOKING" = "1"
};
# "terminal.integrated.defaultProfile.windows" = "PowerShell";
# "terminal.integrated.shell.windows" = "${pkgs.pwsh}/bin/pwsh.exe";
# "terminal.integrated.shellArgs.windows" = [
# "-NoLogo"
# "-NoProfile"
# "-Command"
# "set-location ${pkgs.pwsh}"
# "-Command"
# "set-location ${pkgs.pwsh}"
# "-Command"
# "set EDITOR vim"
# ];
# ===== Explorer =====
"explorer.confirmDelete" = false;
"explorer.confirmDragAndDrop" = false;
# ===== Files =====
"files.defaultLanguage" = "javascript";
"files.enableTrash" = true;
"files.insertFinalNewline" = true;
"files.trimTrailingWhitespace" = false;
# ===== Git =====
"git.autofetch" = "all"; # regularly fetch from all remotes of the repo
"git.autofetchPeriod" = 120;
"git.closeDiffOnOperation" = true; # close diff editors on commits etc.
"git.confirmForcePush" = false;
"git.confirmSync" = false;
"git.allowForcePush" = true;
"git.path" = "";
"git.enableSmartCommit" = false; # commit all if nothing staged
# ===== Editor =====
"editor.inlineSuggest.enabled" = true;
"editor.links" = true;
"editor.codeLens" = true;
"editor.autoIndent" = "advanced";
"editor.detectIndentation" = true;
"editor.hover.enabled" = true;
# allow various mathematical symbols for use in stuff like TeX and Agda
"editor.unicodeHighlight.allowedCharacters" = builtins.listToAttrs (map (x: { name = x; value = true; }) [
"" "" "" "" "α" "γ" "ρ" "σ" "ι" "" "" ""
]);
"editor.hover.delay" = 150;
"editor.suggest.preview" = true;
"editor.suggestFontSize" = 12;
"editor.fontFamily" = "Geist";
"editor.fontSize" = 15;
"editor.fontLigatures" = true;
"editor.rulers" = [ 100 ];
"editor.wordWrapColumn" = 100; # column to wrap at; ignored by default due to wordWrap, relevant e.g. for markdown
"editor.wordWrap" = "on"; # by default, wrap at the viewport
"rewrap.wrappingColumn" = 100; # rewrap text with rewrap extension at column 100
"editor.renderWhitespace" = "boundary";
"editor.guides.bracketPairs" = true;
"editor.language.brackets" = [
[ "[" "]" ]
[ "{" "}" ]
[ "(" ")" ]
[ "" "" ]
];
# by default, I use tabs for indentation for accessibility reasons
"editor.insertSpaces" = false;
"editor.tabSize" = 4;
"editor.detectIndentation" = true;
"editor.scrollbar.vertical" = "visible";
"editor.minimap.showSlider" = "always";
"editor.minimap.size" = "fill";
"editor.minimap.maxColumn" = 100;
# DiffEditor
"diffEditor.experimental.showMoves" = true;
"diffEditor.ignoreTrimWhitespace" = false;
"diffEditor.diffAlgorithm" = "advanced";
# Files
"files.trimFinalNewlines" = true;
"files.trimTrailingWhitespace" = true;
"files.insertFinalNewline" = true;
"files.watcherExclude" = {
"**/.bloop" = true;
"**/.metals" = true;
"**/.ammonite" = true;
};
# === JS/TS ===
"[javascript]" = {
"editor.defaultFormatter" = "esbenp.prettier-vscode"
};
"[typescript]" = {
"editor.defaultFormatter" = "esbenp.prettier-vscode"
};
"javascript.format.enable" = true;
"javascript.format.semicolons" = "insert";
"debug.javascript.codelens.npmScripts" = "all";
"javascript.suggestionActions.enabled" = true;
# "debug.javascript.autoAttachSmartPattern" = [
# "${workspaceFolder}/**";
# "!**/node_modules/**";
# "**/$KNOWN_TOOLS$/**"
# ];
"typescript.updateImportsOnFileMove.enabled" = "always";
"typescript.implementationsCodeLens.enabled" = true;
"typescript.tsserver.log" = "off";
"typescript.tsserver.enableTracing" = false;
"typescript.format.placeOpenBraceOnNewLineForFunctions" = true;
"typescript.implementationsCodeLens.showOnInterfaceMethods" = true;
"typescript.tsserver.useSyntaxServer" = "always";
"typescript.tsserver.maxTsServerMemory" = 2048;
"typescript.tsserver.web.projectWideIntellisense.enabled" = true;
"typescript.format.enable" = true;
"javascript.referencesCodeLens.enabled" = false;
"javascript.referencesCodeLens.showOnAllFunctions" = true;
"javascript.inlayHints.parameterNames.enabled" = "all";
"javascript.inlayHints.parameterTypes.enabled" = true;
"javascript.updateImportsOnFileMove.enabled" = "always";
"npm.fetchOnlinePackageInfo" = true;
# Svelte + Web dev
"svelte.plugin.typescript.hover.enable" = true;
"svelte.plugin.typescript.enable" = true;
"svelte.enable-ts-plugin" = true;
"css.hover.documentation" = true;
"html.hover.documentation" = true;
# === Rust ===
"rust.show_hover_context" = true;
# === Golang ===
"go.useLanguageServer" = true;
"go.lintTool" = "golangci-lint";
# === Py ===
"[python]" = {
"editor.formatOnType" = true
};
"python.missingPackage.severity" = "Warning";
"python.languageServer" = "Jedi";
"python.experiments.enabled" = false;
"python.experiments.optOutFrom" = [
"All"
];
# Haskell
"haskell.manageHLS"= "PATH";
# TODO Tree
#"todo-tree.general.showActivityBarBadge" = true;
#"todo-tree.general.tags" = [ "TODO" "FIXME" ];
# Marky Markdown
"markyMarkdown.statsShowReadingTime" = false;
"markyMarkdown.statsShowWords" = true;
"markyMarkdown.statsShowCharacters" = true;
"markyMarkdown.statsItemSeparator" = " / ";
"languageToolLinter.lintOnOpen" = true;
# https://github.com/davidlday/vscode-languagetool-linter/issues/603
# "languageToolLinter.languageTool.ignoredWordHint" = false;
"languageToolLinter.languageTool.preferredVariants" = "en-US,de-DE,nl-NL";
"languageToolLinter.languageTool.ignoredWordsGlobal" = [
"iirc" "eisfunke" "eisfunkelab" "kb" "nebelhorn" "agda" "dir"
];
# === IaC, Devops ===
"terraform.experimentalFeatures.prefillRequiredFields" = true;
"terraform.experimentalFeatures.validateOnSave" = true;
"[ansible]" = {
"editor.detectIndentation" = true;
"editor.insertSpaces" = true;
"editor.tabSize" = 2;
"editor.quickSuggestions" = {
"comments" = true;
"other" = true;
"strings" = true
};
"editor.autoIndent" = "advanced"
};
"ansible.lightspeed.enabled" = false;
"yaml.hover" = true;
"yaml.completion" = true;
# === Nix ===
"nix.enableLanguageServer" = true; // Enable LSP.
"nix.serverPath" = "nil"; // The path to the LSP server executable.
# === advanced
"nix.serverSettings" = {
"nil" = {
"formatting" = { "command" = ["nixpkgs-fmt"] }
}
};
#"agdaMode.inputMethod.activationKey" = "ß";
# language specific indentation settings
"[html]" = {
"editor.defaultFormatter" = "esbenp.prettier-vscode"
};
"[jsonc]" = {
"editor.defaultFormatter" = "esbenp.prettier-vscode"
};
"[json]" = {
"editor.defaultFormatter" = "esbenp.prettier-vscode"
};
"[latex]" = {
"editor.defaultFormatter" = "esbenp.prettier-vscode";
"editor.formatOnPaste" = false;
"editor.suggestSelection" = "recentlyUsedByPrefix"
};
"[svelte]" = {
"editor.acceptSuggestionOnCommitCharacter" = true;
"editor.acceptSuggestionOnEnter" = "off"
};
"[scala]" = { # follow Scala style guide
"editor.insertSpaces" = true;
"editor.tabSize" = 2;
};
"[markdown]" = { # indent markdown with spaces so YAML frontmatter doesn't break
"editor.wordWrap" = "bounded"; # wrap markdown files at line width
"editor.insertSpaces" = true;
"editor.tabSize" = 2;
};
"[haskell]"."editor.insertSpaces" = true; # GHC warns when using tabs
"[python]"."editor.insertSpaces" = true; # black forces spaces
"[agda]"."editor.insertSpaces" = true; # agda forces spaces
};
};
}

View File

@ -0,0 +1,11 @@
/*
additional shell apps not needed on a minimal system
*/
{ pkgs, inputs', ... }:
{
home.packages = [
pkgs.ffmpeg_6
pkgs.yt-dlp
pkgs.dcraw # for converting RAW pictures

View File

@ -0,0 +1,44 @@
# home level sops. see hosts/common/optional/sops.nix for hosts level
# TODO should I split secrtets.yaml into a home level and a hosts level or move to a single sops.nix entirely?
{ inputs, ... }:
let
secretspath = builtins.toString inputs.mysecrets;
in
{
imports = [
inputs.sops-nix.homeManagerModules.sops
];
sops = {
# gnupg = {
# home = "/var/lib/sops";
# sshKeyPaths = [ ];
# }
# This is the ta/dev key and needs to have been copied to this location on the host
age.keyFile = "/home/ta/.config/sops/age/keys.txt";
defaultSopsFile = "${secretspath}/secrets.yaml";
# defaultSopsFile = ../../../../hosts/common/secrets.yaml;
validateSopsFiles = false;
secrets = {
"private_keys/maya" = {
path = "/home/ta/.ssh/id_maya";
};
"private_keys/mara" = {
path = "/home/ta/.ssh/id_mara";
};
"private_keys/manu" = {
path = "/home/ta/.ssh/id_manu";
};
"private_keys/mila" = {
path = "/home/ta/.ssh/id_mila";
};
"private_keys/meek" = {
path = "/home/ta/.ssh/id_meek";
};
};
};
}

View File

@ -0,0 +1,30 @@
{pkgs, ...}: {
imports = [
./global
./features/desktop/wireless
./features/desktop/hyprland
./features/pass
];
wallpaper = pkgs.wallpapers.plains-gold-field;
monitors = [
{
name = "HDMI-A-1";
width = 1920;
height = 1080;
workspace = "2";
x = 0;
}
{
name = "eDP-1";
width = 1920;
height = 1080;
workspace = "1";
x = 1920;
primary = true;
}
];
# programs.git.userEmail = "gabriel@zoocha.com";
}

View File

@ -0,0 +1,34 @@
{ lib, configVars, ... }:
let
in
{
imports = [
#################### Hardware Modules ####################
inputs.hardware.nixosModules.common-cpu-amd
inputs.hardware.nixosModules.lenovo-ideapad-15arh05 # Replace with actual model, push upstream, several drivers needed.
inputs.hardware.nixosModules.common-pc-ssd
inputs.hardware.nixosModules.common-pc-laptop
# inputs.hardware.nixosModules.common-cpu-amd
# inputs.hardware.nixosModules.common-cpu-intel
# inputs.hardware.nixosModules.common-gpu-nvidia
# inputs.hardware.nixosModules.common-gpu-intel
# example fingerprint sensor https://github.com/ahbnr/nixos-06cb-009a-fingerprint-sensor/tree/main/pkgs
#################### Required Configs ####################
./common/core #required
#################### Host-specific Optional Configs ####################
];
home = {
username = configVars.username;
homeDirectory = "/home/${configVars.username}";
};
# Disable impermanence
#home.persistence = lib.mkForce { };
}

View File

View File

@ -0,0 +1,15 @@
{ inputs, lib, pkgs, config, outputs, ... }:
{
imports = [
# =========== Required Configs =========== #
common/core #required
# =========== Host-specific Optional Configs =========== #
common/optional/sops.nix
common/optional/helper-scripts
common/optional/desktops/gtk.nix
common/optional/browsers/brave.nix # for testing against 'media' user
];
}

0
install.sh Normal file
View File

0
keys/id_dromedar Normal file
View File

0
keys/id_falcon Normal file
View File

0
keys/id_fennec Normal file
View File

0
keys/id_gerbil Normal file
View File

23
lib/default.nix Normal file
View File

@ -0,0 +1,23 @@
{ lib, ... }:
{
# use path relative to the root of the project
relativeToRoot = lib.path.append ../.;
scanPaths = path:
builtins.map
(f: (path + "/${f}"))
(builtins.attrNames
(lib.attrsets.filterAttrs
(
path: _type:
(_type == "directory") # include directories
|| (
# FIXME this barfs when child directories don't contain a default.nix
# example:
# error: getting status of '/nix/store/mx31x8530b758ap48vbg20qzcakrbc8 (see hosts/common/core/services/default.nix)a-source/hosts/common/core/services/default.nix': No such file or directory
# I created a blank default.nix in hosts/common/core/services to work around
(path != "default.nix") # ignore default.nix
&& (lib.strings.hasSuffix ".nix" path) # include .nix files
)
)
(builtins.readDir path)));
}

View File

@ -0,0 +1,59 @@
# https://github.com/Misterio77/nix-config/blob/63850798c0216eee77a09958236e0608c8cab023/modules/home-manager/colors.nix
{
lib,
config,
pkgs,
...
}: let
cfg = config.colorscheme;
inherit (lib) types mkOption;
hexColor = types.strMatching "#([0-9a-fA-F]{3}){1,2}";
removeFilterPrefixAttrs = prefix: attrs:
lib.mapAttrs' (n: v: {
name = lib.removePrefix prefix n;
value = v;
}) (lib.filterAttrs (n: _: lib.hasPrefix prefix n) attrs);
in {
options.colorscheme = {
source = mkOption {
type = types.either types.path hexColor;
# TODO: generate default from hostname
# colorFromString = c: builtins.substring 0 6 (builtins.hashString "md5" c);
default =
if config.wallpaper != null
then config.wallpaper
else "#2B3975";
};
mode = mkOption {
type = types.enum ["dark" "light"];
default = "dark";
};
type = mkOption {
type = types.enum (pkgs.generateColorscheme null null).schemeTypes;
default = "fruit-salad";
};
generatedDrv = mkOption {
type = types.package;
default = pkgs.generateColorscheme (cfg.source.name or "default") cfg.source;
};
rawColorscheme = mkOption {
type = types.attrs;
default = cfg.generatedDrv.imported.${cfg.type};
};
colors = mkOption {
readOnly = true;
type = types.attrsOf hexColor;
default = cfg.rawColorscheme.colors.${cfg.mode};
};
harmonized = mkOption {
readOnly = true;
type = types.attrsOf hexColor;
default = removeFilterPrefixAttrs "${cfg.mode}-" cfg.rawColorscheme.harmonized_colors;
};
};
}

View File

@ -0,0 +1,7 @@
{
fonts = import ./fonts.nix;
monitors = import ./monitors.nix;
shellcolor = import ./shellcolor.nix;
wallpaper = import ./wallpaper.nix;
colors = import ./colors.nix;
}

View File

@ -0,0 +1,36 @@
# https://github.com/Misterio77/nix-config/blob/63850798c0216eee77a09958236e0608c8cab023/modules/home-manager/fonts.nix
{
lib,
config,
...
}: let
mkFontOption = kind: {
family = lib.mkOption {
type = lib.types.str;
default = null;
description = "Family name for ${kind} font profile";
example = "Fira Code";
};
package = lib.mkOption {
type = lib.types.package;
default = null;
description = "Package for ${kind} font profile";
example = "pkgs.fira-code";
};
};
cfg = config.fontProfiles;
in {
options.fontProfiles = {
enable = lib.mkEnableOption "Whether to enable font profiles";
monospace = mkFontOption "monospace";
regular = mkFontOption "regular";
};
config = lib.mkIf cfg.enable {
fonts.fontconfig.enable = true;
home.packages = [
cfg.monospace.package
cfg.regular.package
];
};
}

View File

@ -0,0 +1,65 @@
# https://github.com/Misterio77/nix-config/blob/63850798c0216eee77a09958236e0608c8cab023/modules/home-manager/monitors.nix
{
lib,
config,
...
}: let
inherit (lib) mkOption types;
cfg = config.monitors;
in {
options.monitors = mkOption {
type = types.listOf (
types.submodule {
options = {
name = mkOption {
type = types.str;
example = "DP-1";
};
primary = mkOption {
type = types.bool;
default = false;
};
width = mkOption {
type = types.int;
example = 1920;
};
height = mkOption {
type = types.int;
example = 1080;
};
refreshRate = mkOption {
type = types.int;
default = 60;
};
x = mkOption {
type = types.int;
default = 0;
};
y = mkOption {
type = types.int;
default = 0;
};
enabled = mkOption {
type = types.bool;
default = true;
};
workspace = mkOption {
type = types.nullOr types.str;
default = null;
};
};
}
);
default = [];
};
config = {
assertions = [
{
assertion =
((lib.length config.monitors) != 0)
-> ((lib.length (lib.filter (m: m.primary) config.monitors)) == 1);
message = "Exactly one monitor must be set to primary.";
}
];
};
}

View File

@ -0,0 +1,85 @@
# https://github.com/Misterio77/nix-config/blob/63850798c0216eee77a09958236e0608c8cab023/modules/home-manager/shellcolor.nix
{
config,
lib,
pkgs,
...
}: let
cfg = config.programs.shellcolor;
package = pkgs.shellcolord;
renderSetting = key: value: ''
${key}=${value}
'';
renderSettings = settings: lib.concatStrings (lib.mapAttrsToList renderSetting settings);
in {
options.programs.shellcolor = {
enable = lib.mkEnableOption "shellcolor";
enableBashIntegration = lib.mkOption {
default = true;
type = lib.types.bool;
description = ''
Whether to enable Bash integration.
'';
};
enableZshIntegration = lib.mkOption {
default = true;
type = lib.types.bool;
description = ''
Whether to enable Zsh integration.
'';
};
enableBashSshFunction = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether to enable SSH integration by replacing ssh with a bash function.
'';
};
settings = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = {};
example = lib.literalExpression ''
{
base00 = "000000";
base05 = "ffffff";
}
'';
description = ''
Options for shellcolord config file. Colors (without leading #)
from base00 until base0F.
'';
};
};
config = lib.mkIf cfg.enable {
home.packages = [package];
xdg.configFile."shellcolor.conf" = lib.mkIf (cfg.settings != {}) {
text = renderSettings cfg.settings;
onChange = ''
timeout 1 ${package}/bin/shellcolor apply || true
'';
};
programs.bash.initExtra = lib.mkIf cfg.enableBashIntegration (
lib.mkBefore ''
${package}/bin/shellcolord $$ & disown
${lib.optionalString cfg.enableBashSshFunction ''
ssh() {
${package}/bin/shellcolor disable $$
command ssh "$@"
${package}/bin/shellcolor enable $$
${package}/bin/shellcolor apply $$
}
''}
''
);
programs.zsh.initExtra = lib.mkIf cfg.enableZshIntegration (
lib.mkBefore ''
${package}/bin/shellcolord $$ & disown
''
);
}

View File

@ -0,0 +1,11 @@
{lib, ...}: let
inherit (lib) types mkOption;
in {
options.wallpaper = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Wallpaper path
'';
};
}

View File

@ -0,0 +1,14 @@
starship.enable = true;
starship.settings = {
aws.disabled = true;
gcloud.disabled = true;
kubernetes.disabled = false;
git_branch.style = "242";
directory.style = "blue";
directory.truncate_to_repo = false;
directory.truncation_length = 8;
python.disabled = true;
ruby.disabled = true;
hostname.ssh_only = false;
hostname.style = "bold green";
};

94
modules/zsh/default.nix Normal file
View File

@ -0,0 +1,94 @@
{ pkgs, lib, config, ... }:
with lib;
let cfg = config.modules.zsh;
in {
options.modules.zsh = { enable = mkEnableOption "zsh"; };
config = mkIf cfg.enable {
home.packages = [
pkgs.zsh
];
programs.zsh = {
enable = true;
# directory to put config files in
dotDir = ".config/zsh";
enableCompletion = true;
enableAutosuggestions = true;
enableSyntaxHighlighting = true;
# .zshrc
initExtra = ''
PROMPT="%F{blue}%m %~%b "$'\n'"%(?.%F{green}%Bλ%b |.%F{red}?) %f"
export PASSWORD_STORE_DIR="$XDG_DATA_HOME/password-store";
export ZK_NOTEBOOK_DIR="~/stuff/notes";
export DIRENV_LOG_FORMAT="";
bindkey '^ ' autosuggest-accept
# zoxide
eval "$(zoxide init zsh)"
edir() { tar -cz $1 | age -p > $1.tar.gz.age && rm -rf $1 &>/dev/null && echo "$1 encrypted" }
ddir() { age -d $1 | tar -xz && rm -rf $1 &>/dev/null && echo "$1 decrypted" }
'';
# basically aliases for directories:
# `cd ~dots` will cd into ~/.config/nixos
dirHashes = {
dots = "$HOME/.config/nixos";
stuff = "$HOME/stuff";
media = "/run/media/$USER";
junk = "$HOME/stuff/other";
};
# Tweak settings for history
history = {
save = 1000;
size = 1000;
path = "$HOME/.cache/zsh_history";
};
# Set some aliases
shellAliases = {
gc = "nix-collect-garbage --delete-old";
refresh = "source ${config.home.homeDirectory}/.zshrc";
show_path = "echo $PATH | tr ':' '\n'";
c = "clear";
mkdir = "mkdir -vp";
rm = "rm -rifv";
mv = "mv -iv";
cp = "cp -riv";
cat = "bat --paging=never --style=plain";
ls = "exa -a --icons";
tree = "exa --tree --icons";
nd = "nix develop -c $SHELL";
rebuild = "doas nixos-rebuild switch --flake $NIXOS_CONFIG_DIR --fast; notify-send 'Rebuild complete\!'";
};
# Source all plugins, nix-style
plugins = [
{
name = "auto-ls";
src = pkgs.fetchFromGitHub {
owner = "notusknot";
repo = "auto-ls";
rev = "";
sha256 = "";
};
};
# {
# name = ""
# src = pkgs.fetchFromGitHub {
# owner = "";
# repo = "";
# rev = "";
# sha256 = "";
# }
# }
];
};
};
}

26
overlays/default.nix Normal file
View File

@ -0,0 +1,26 @@
#
# This file defines overlays/custom modifications to upstream packages
#
{ inputs, ... }: {
# This one brings our custom packages from the 'pkgs' directory
additions = final: _prev: import ../pkgs { pkgs = final; };
# This one contains whatever you want to overlay
# You can change versions, add patches, set compilation flags, anything really.
# https://nixos.wiki/wiki/Overlays
modifications = final: prev: {
# example = prev.example.overrideAttrs (oldAttrs: let ... in {
# ...
# });
};
# When applied, the unstable nixpkgs set (declared in the flake inputs) will
# be accessible through 'pkgs.unstable'
unstable-packages = final: _prev: {
unstable = import inputs.nixpkgs-unstable {
system = final.system;
config.allowUnfree = true;
};
};
}

View File

@ -0,0 +1,8 @@
#https://github.com/Misterio77/nix-config/tree/63850798c0216eee77a09958236e0608c8cab023/pkgs/colorschemes
{
pkgs,
wallpapers,
generateColorscheme,
...
}:
pkgs.lib.mapAttrs (_: v: generateColorscheme v.name v) wallpapers

View File

@ -0,0 +1,52 @@
{pkgs, ...}: let
inherit (pkgs) lib;
matugen = import (fetchTarball {
url = "https://github.com/InioX/matugen/archive/3040fe974b94bc70b49e6c3b868a8eb1c7b294a3.tar.gz";
sha256 = "sha256:0v7np4294fzwxmgf7pjcxvky63lrq1ajim1b8ywbp47wy9k0pcgs";
}) {inherit pkgs;};
generateColorscheme = name: source: let
schemeTypes = ["content" "expressive" "fidelity" "fruit-salad" "monochrome" "neutral" "rainbow" "tonal-spot"];
isHexColor = c: lib.isString c && (builtins.match "#([0-9a-fA-F]{3}){1,2}" c) != null;
config = (pkgs.formats.toml {}).generate "config.toml" {
templates = {};
config = {
colors_to_harmonize = {
light-red = "#d03e3e";
light-orange = "#d7691d";
light-yellow = "#ad8200";
light-green = "#31861f";
light-cyan = "#00998f";
light-blue = "#3173c5";
light-magenta = "#9e57c2";
dark-red = "#e15d67";
dark-orange = "#fc804e";
dark-yellow = "#e1b31a";
dark-green = "#5db129";
dark-cyan = "#21c992";
dark-blue = "#00a3f2";
dark-magenta = "#b46ee0";
};
};
};
in
pkgs.runCommand "colorscheme-${name}" {
__contentAddressed = true;
passthru = let
drv = generateColorscheme name source;
in {
inherit schemeTypes;
# Incurs IFD
imported = lib.genAttrs schemeTypes (scheme: lib.importJSON "${drv}/${scheme}.json");
};
} ''
mkdir "$out" -p
for type in ${lib.concatStringsSep " " schemeTypes}; do
${matugen}/bin/matugen ${
if (isHexColor source)
then "color hex"
else "image"
} --config ${config} -j hex -t "scheme-$type" "${source}" > "$out/$type.json"
done
'';
in generateColorscheme

22
pkgs/default.nix Normal file
View File

@ -0,0 +1,22 @@
{pkgs ? import <nixpkgs> {}}: let
inherit (pkgs) lib;
in rec {
# Personal scripts
nix-inspect = pkgs.callPackage ./nix-inspect {};
# My slightly customized plymouth theme, just makes the blue outline white
plymouth-spinner-monochrome = pkgs.callPackage ./plymouth-spinner-monochrome {};
# My wallpaper collection
wallpapers = import ./wallpapers {inherit pkgs;};
allWallpapers = pkgs.linkFarmFromDrvs "wallpapers" (lib.attrValues wallpapers);
# And colorschemes based on it
generateColorscheme = import ./colorschemes/generator.nix {inherit pkgs;};
colorschemes = import ./colorschemes {inherit pkgs wallpapers generateColorscheme;};
allColorschemes = let
# This is here to help us keep IFD cached (hopefully)
combined = pkgs.writeText "colorschemes.json" (builtins.toJSON (lib.mapAttrs (_: drv: drv.imported) colorschemes));
in
pkgs.linkFarmFromDrvs "colorschemes" (lib.attrValues colorschemes ++ [combined]);
}

View File

@ -0,0 +1,29 @@
{
pkgs = import <nixpkgs> {};
# Dependencies (replace if versions differ)
deps = pkgs.stdenv + pkgs.libdrm + pkgs.sdbus + pkgs.wayland + pkgs.pipewire;
# Build xdg-desktop-portal-hyprland (adjust as needed)
xdgDesktopPortalHyprland = pkgs.buildPackage {
name = "xdg-desktop-portal-hyprland";
src = pkgs.fetchFromGitHub {
rev = "v0.5.2"; # Replace with desired version
owner = "hyprwm";
repo = "xdg-desktop-portal-hyprland";
};
buildInputs = deps;
meta = with pkgs; in {
# Set installation paths (optional, adjust as needed)
buildInputs = pkgs.lib.make (deps ++ [ stdenv.cc ]);
installPhase = pkgs.mkDerivation {
name = "xdg-desktop-portal-hyprland-install";
buildInputs = with pkgs; in deps ++ [ buildInputs ];
shellHook = ''
cp -r ${src}/build/lib ${pkgs.lib}/
cp -r ${src}/build/include ${pkgs.lib.include}/xdg-desktop-portal-hyprland
'';
};
};
};
}

37
pkgs/name/default.nix Normal file
View File

@ -0,0 +1,37 @@
{ lib, stdenv, fetchgit }:
let
pname = "cd-gitroot";
install_path = "share/zsh/${pname}";
in
stdenv.mkDerivation {
inherit pname;
version = "66f6ba7549b9973eb57bfbc188e29d2f73bf31bb";
src = fetchgit {
url = "https://github.com/mollifier/cd-gitroot";
hash = "sha256-pLdF8wbkA9mPI5cg8VPYAW7i3cWNJX3+lfAZ5cZPUgE=";
};
strictDeps = true;
dontBuild = true;
buildInputs = [ ];
installPhase = ''
install -m755 -D cd-gitroot.plugin.zsh --target-directory $out/${install_path}/
install -m755 -D cd-gitroot --target-directory $out/${install_path}/
install -m755 -D _cd-gitroot --target-directory $out/share/zsh/site-functions/
'';
meta = with lib; {
homepage = "https://github.com/mollifier/cd-gitroot";
license = licenses.mit;
longDescription = ''zsh plugin to change directory to git repository root directory.
You can add the following to your `programs.zsh.plugins` list:
```nix
programs.zsh.plugins = [
{
name = "${pname}";
src = "''${pkgs.${pname}}/${install_path}";
}
];
```
'';
maintainers = with maintainers; [ fidgetingbits ];
};
}

View File

@ -0,0 +1,23 @@
{
stdenv,
logo ? null,
lib,
...
}:
stdenv.mkDerivation {
pname = "plymouth-custom";
version = "1.0";
src = ./src;
buildPhase = lib.optionalString (logo != null) ''
ln -s ${logo} watermark.png
'';
installPhase = ''
mkdir -p $out/share/plymouth/themes
cp -rT . $out/share/plymouth/themes/spinner-monochrome
'';
meta = {
platforms = lib.platforms.all;
};
}

281
scripts/bootstrap-nixos.sh Normal file
View File

@ -0,0 +1,281 @@
#!/usr/bin/env bash
set -eo pipefail
# User variables
config_location="git://git@git.mattmor.in/org/nix/os-config.git"
target_hostname=""
target_destination=""
target_user="ta"
ssh_key=""
ssh_port="22"
remote_passwd="nixos"
persist_dir=""
# Create a temp directory for generated host keys
temp=$(mktemp -d)
# Cleanup temporary directory on exit
function cleanup() {
rm -rf "$temp"
}
trap cleanup exit
function red() {
echo -e "\x1B[31m[!] $1 \x1B[0m"
if [ -n "${2-}" ]; then
echo -e "\x1B[31m[!] $($2) \x1B[0m"
fi
}
function green() {
echo -e "\x1B[32m[+] $1 \x1B[0m"
if [ -n "${2-}" ]; then
echo -e "\x1B[32m[+] $($2) \x1B[0m"
fi
}
function yellow() {
echo -e "\x1B[33m[*] $1 \x1B[0m"
if [ -n "${2-}" ]; then
echo -e "\x1B[33m[*] $($2) \x1B[0m"
fi
}
function yes_or_no() {
while true; do
read -rp "$* [y/n] (default: y): " yn
yn=${yn:-y}
case $yn in
[Yy]*) return 0 ;;
[Nn]*) return 1 ;;
esac
done
}
function sync() {
# $1 = user, $2 = source, $3 = destination
rsync -av --filter=':- .gitignore' -e "ssh -l $1" "$2" "$1"@"${target_destination}":
}
function help_and_exit() {
echo
echo "Remotely installs NixOS on a target machine using this nix-config."
echo
echo "USAGE: $0 -n=<target_hostname> -d=<target_destination> -k=<ssh_key> [OPTIONS]"
echo
echo "ARGS:"
echo " -n=<target_hostname> specify target_hostname of the target host to deploy the nixos config on."
echo " -d=<target_destination> specify ip or url to the target host."
echo " -k=<ssh_key> specify the full path to the ssh_key you'll use for remote access to the"
echo " target during install process."
echo " Example: -k=/home/${target_user}/.ssh/my_ssh_key"
echo
echo "OPTIONS:"
echo " -u=<target_user> specify target_user with sudo access. nix-config will be cloned to their home."
echo " Default='${target_user}'."
echo " -p=<remote_passwd> Specify a password for target machine user. This is temporary until install is complete."
echo " Default='${remote_passwd}'."
echo " --port=<ssh_port> specify the ssh port to use for remote access. Default=${ssh_port}."
echo " --impermanence Use this flag if the target machine has impermanence enabled. WARNING: Assumes /persist path."
echo " --debug Enable debug mode."
echo " -h | --help Print this help."
exit 0
}
# Handle command-line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-n=*)
target_hostname="${1#-n=}"
;;
-d=*)
target_destination="${1#-d=}"
;;
-u=*)
target_user="${1#-u=}"
;;
-k=*)
ssh_key="${1#-k=}"
;;
-p=*)
remote_passwd="${1#-p=}"
;;
--port=*)
ssh_port="${1#--port=}"
;;
--temp-override=*)
temp="${1#--temp-override=}"
;;
--impermanence)
persist_dir="/persist"
;;
--debug)
set -x
;;
-h | --help) help_and_exit ;;
*)
echo "Invalid option detected."
help_and_exit
;;
esac
shift
done
# SSH commands
ssh_cmd="ssh -oport=${ssh_port} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i $ssh_key -t $target_user@$target_destination"
ssh_root_cmd=$(echo "$ssh_cmd" | sed "s|${target_user}@|root@|") # uses @ in the sed switch to avoid it triggering on the $ssh_key value
scp_cmd="scp -oport=${ssh_port} -o StrictHostKeyChecking=no -i $ssh_key"
function nixos_anywhere() {
green "Installing NixOS on remote host $target_hostname at $target_destination"
###
# nixos-anywhere extra-files generation
###
green "Preparing a new ssh_host_ed25519_key pair for $target_hostname."
# Create the directory where sshd expects to find the host keys
install -d -m755 "$temp/$persist_dir/etc/ssh"
# Generate host keys without a passphrase
ssh-keygen -t ed25519 -f "$temp/$persist_dir/etc/ssh/ssh_host_ed25519_key" -C root@"$target_hostname" -N ""
# ssh-keygen -t ed25519 -f "$temp/$persist_dir/etc/ssh/ssh_host_ed25519_key" -C "$target_user"@"$target_hostname" -N ""
# Set the correct permissions so sshd will accept the key
chmod 600 "$temp/$persist_dir/etc/ssh/ssh_host_ed25519_key"
echo "Adding ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
# This will fail if we already know the host, but that's fine
ssh-keyscan -p "$ssh_port" "$target_destination" >>~/.ssh/known_hosts || true
###
# nixos-anywhere installation
###
cd nixos-installer
# disko expects a passphrase on /tmp/disko-password, so we set it for now and will update the passphrase later
green "Preparing a temporary password for disko."
$ssh_root_cmd "/bin/sh -c 'echo passphrase > /tmp/disko-password'"
# copy our repo there via rsync for speed
green "Syncing nix-config to $target_hostname"
sync root "$PWD"
$ssh_root_cmd "nixos-generate-config --no-filesystems --root /mnt"
$scp_cmd root@"$target_destination":/mnt/etc/nixos/hardware-configuration.nix ../hosts/"$target_hostname"/hardware-configuration.nix
sync root "$PWD"
# --extra-files here picks up the ssh host key we generated earlier and puts it onto the target machine
# FIXME: Double check that it will delete them?
SHELL=/bin/sh nix run github:nix-community/nixos-anywhere -- --ssh-port "$ssh_port" --extra-files "$temp" --flake .#"$target_hostname" root@"$target_destination"
echo "Updating ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
# This will fail if we already know the host, but that's fine
ssh-keyscan -p "$ssh_port" "$target_destination" >>~/.ssh/known_hosts || true
# FIXME: Do we need this? I get errors:
# /etc/tmpfiles.d/journal-nocow.conf:26: Failed to resolve specifier: uninitialized /etc/ detected, skipping.
# And there is no /etc/machine-id after first rebuild...
if [ -n "$persist_dir" ]; then
$ssh_root_cmd "cp /etc/machine-id $persist_dir/etc/machine-id || true"
$ssh_root_cmd "cp -R /etc/ssh/ $persist_dir/etc/ssh/ || true"
fi
cd -
}
function generate_age_keys() {
green "Generating an age key based on the new ssh_host_ed25519_key."
target_key=$(ssh-keyscan -p "$ssh_port" -t ssh-ed25519 "$target_destination" 2>&1 | rg ssh-ed25519 | cut -f2- -d" ")
age_key=$(nix shell nixpkgs#ssh-to-age.out -c sh -c "echo $target_key | ssh-to-age")
if grep -qv '^age1' <<<"$age_key"; then
red "The result from generated age key does not match the expected format."
yellow "Result: $age_key"
yellow "Expected format: age10000000000000000000000000000000000000000000000000000000000"
exit 1
else
echo "$age_key"
fi
green "Updating nix-secrets/.sops.yaml"
cd ../nix-secrets
SOPS_FILE=".sops.yaml"
sed -i "{
# Remove any * and & entries for this host
/[*&]$target_hostname/ d;
# Inject a new age: entry
# n matches the first line following age: and p prints it, then we transform it while reusing the spacing
/age:/{n; p; s/\(.*- \*\).*/\1$target_hostname/};
# Inject a new hosts: entry
/&hosts:/{n; p; s/\(.*- &\).*/\1$target_hostname $age_key/}
}" $SOPS_FILE
green "Updating nix-secrets/.sops.yaml"
cd -
just rekey
green "Updating flake lock on source machine with new .sops.yaml info"
nix flake lock --update-input nix-secrets
}
# Validate required options
if [ -z "${target_hostname}" ] || [ -z "${target_destination}" ] || [ -z "${ssh_key}" ]; then
red "ERROR: -n, -d, and -k are all required"
echo
help_and_exit
fi
# Clear the keys, since they should be newly generated for the iso
green "Wiping known_hosts of $target_destination"
sed -i "/$target_hostname/d; /$target_destination/d" ~/.ssh/known_hosts
if yes_or_no "Do you want to run nixos-anywhere installation?"; then
nixos_anywhere
fi
if yes_or_no "Do you want to run age key generation?"; then
generate_age_keys
fi
if yes_or_no "Do you want to add ssh host fingerprints for gitlab and github? If this is the first time running this script on $target_hostname, this will be required for the following steps?"; then
if [ "$target_user" == "root" ]; then
home_path="/root"
else
home_path="/home/$target_user"
fi
green "Adding ssh host fingerprints for gitlab and github"
$ssh_cmd "mkdir -p $home_path/.ssh/; ssh-keyscan -t ssh-ed25519 gitlab.com github.com >>$home_path/.ssh/known_hosts"
fi
if yes_or_no "Do you want to copy your full nix-config and private keys to $target_hostname?"; then
echo "Adding ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
# This will fail if we already know the host, but that's fine
ssh-keyscan -p "$ssh_port" "$target_destination" >>~/.ssh/known_hosts || true
green "Copying full nix-config to $target_hostname"
sync "$target_user" "$PWD"
green "Copying full nix-secrets to $target_hostname"
sync "$target_user" ../nix-secrets
if yes_or_no "Do you want to rebuild immediately?"; then
green "Rebuilding nix-config on $target_hostname"
$ssh_cmd "cd nix-config && sudo nixos-rebuild --show-trace switch --flake .#$target_hostname"
fi
else
echo
green "NixOS was succcefully installed!"
echo "Post-install config build instructions:"
echo "To copy nix-config from this machine to the $target_hostname, run the following command from ~/nix-config"
echo "just sync $target_user $target_destination"
echo "To rebuild, sign into $target_hostname and run the following command from ~/nix-config"
echo "cd nix-config"
echo "just rebuild"
echo
fi
if yes_or_no "You can now commit and push the nix-config, which includes the hardware-configuration.nix for $target_hostname?"; then
(pre-commit run --all-files 2>/dev/null || true) &&
git add hosts/"$target_hostname"/hardware-configuration.nix && (git commit -m "feat: hardware-configuration.nix for $target_hostname" || true) && git push
fi
#TODO prune all previous generations?
green "Success!"

16
scripts/check-sops.sh Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
# FIXME: Make this better
sops_result=$(journalctl --no-pager --no-hostname --since "10 minutes ago" |
tac |
awk '!flag; /Starting sops-nix activation/{flag = 1};' |
tac |
grep sops)
# If we don't have "Finished sops-nix activation." in the logs, then we failed
if [[ ! $sops_result =~ "Finished sops-nix activation" ]]; then
echo "sops-nix failed to activate"
echo "$sops_result"
exit 1
fi

View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
if [ ! -z $1 ]; then
export HOST=$1
else
export HOST=$(hostname)
fi
sudo nixos-rebuild --show-trace --impure --flake .#$HOST switch

View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
if [ ! -z $1 ]; then
export HOST=$1
else
export HOST=$(hostname)
fi
sudo nixos-rebuild --impure --flake .#$HOST switch

View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
if [ -e $1 ]; then
HOST=$1
else
HOST=$(hostname)
fi
sudo nixos-rebuild --flake .#$HOST install

View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
sudo nixos-rebuild switch -I nixos-config=configuration.nix

35
shell.nix Normal file
View File

@ -0,0 +1,35 @@
#################### DevShell ####################
#
# Custom shell for bootstrapping on new hosts, modifying nix-config, and secrets management
{ pkgs ? # If pkgs is not defined, instantiate nixpkgs from locked commit
let
lock = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.nixpkgs.locked;
nixpkgs = fetchTarball {
url = "https://github.com/nixos/nixpkgs/archive/${lock.rev}.tar.gz";
sha256 = lock.narHash;
};
in
import nixpkgs { overlays = [ ]; }
, ...
}: {
default = pkgs.mkShell {
NIX_CONFIG = "extra-experimental-features = nix-command flakes repl-flake";
nativeBuildInputs = builtins.attrValues {
inherit (pkgs)
# Required for pre-commit hook 'nixpkgs-fmt' only on Darwin
# REF: <https://discourse.nixos.org/t/nix-shell-rust-hello-world-ld-linkage-issue/17381/4>
libiconv
nix
home-manager
git
just
pre-commit
age
ssh-to-age
sops;
};
};
}

22
simple-shell.nix Normal file
View File

@ -0,0 +1,22 @@
{ pkgs ? import <nixpkgs> {}
}: {
default = pkgs.mkShell {
NIX_CONFIG = "extra-experimental-features = nix-command flakes repl-flake";
nativeBuildInputs = builtins.attrValues {
inherit (pkgs)
# Required for pre-commit hook 'nixpkgs-fmt' only on Darwin
# REF: <https://discourse.nixos.org/t/nix-shell-rust-hello-world-ld-linkage-issue/17381/4>
libiconv
nix
home-manager
git
just
pre-commit
age
ssh-to-age
sops;
};
};
}

View File

@ -0,0 +1,35 @@
{
config,
inputs,
pkgs,
lib,
...
}: let
inherit (config.networking) hostName;
# Only enable auto upgrade if current config came from a clean tree
# This avoids accidental auto-upgrades when working locally.
isClean = inputs.self ? rev;
in {
system.autoUpgrade = {
enable = isClean;
dates = "hourly";
flags = [
"--refresh"
];
# flake = "git://m7.rs/nix-config?ref=release-${hostName}";
# TODO: public?
flake = "git://git.mattmor.in/Madmin/nix-config-priv";
};
# Only run if current config (self) is older than the new one.
systemd.services.nixos-upgrade = lib.mkIf config.system.autoUpgrade.enable {
serviceConfig.ExecCondition = lib.getExe (
pkgs.writeShellScriptBin "check-date" ''
lastModified() {
nix flake metadata "$1" --refresh --json | ${lib.getExe pkgs.jq} '.lastModified'
}
test "$(lastModified "${config.system.autoUpgrade.flake}")" -gt "$(lastModified "self")"
''
);
};
}

View File

@ -0,0 +1,47 @@
# This file (and the global directory) holds config that i use on all hosts
{ inputs, outputs, configLib, ... }: {
imports = (configLib.scanPaths ./.)
++ [ inputs.home-manager.nixosModules.home-manager ]
++ (builtins.attrValues outputs.nixosModules);
home-manager.extraSpecialArgs = {
inherit inputs outputs;
};
nixpkgs = {
# you can add global overlays here
overlays = builtins.attrValues outputs.overlays;
config.allowUnfree = true;
};
# Fix for qt6 plugins
# TODO: maybe upstream this?
environment.profileRelativeSessionVariables = {
QT_PLUGIN_PATH = ["/lib/qt-6/plugins"];
};
hardware.enableRedistributableFirmware = true;
networking.domain = "mattmor.in";
security.sudo.extraConfig = ''
Defaults timestamp_timeout=120 # only ask for password every 2h
# Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic.
# Defaults env_keep + =SSH_AUTH_SOCK
'';
# Increase open file limit for sudoers
security.pam.loginLimits = [
{
domain = "@wheel";
item = "nofile";
type = "soft";
value = "524288";
}
{
domain = "@wheel";
item = "nofile";
type = "hard";
value = "1048576";
}
];
}

View File

@ -0,0 +1,96 @@
{
pkgs,
theme,
...
}: {
home.packages = with pkgs; [
libsixel
# for displaying images
];
programs.foot = {
enable = true;
server.enable = false;
settings = {
main = {
app-id = "foot";
title = "foot";
locked-title = "no";
term = "xterm-256color";
font = "Geist Mono:size=10.5";
vertical-letter-offset = "-0.75";
pad = "12x21 center";
resize-delay-ms = 100;
notify = "notify-send -a \${app-id} -i \${app-id} \${title} \${body}";
selection-target = "primary";
# box-drawings-uses-font-glyphs = "yes";
dpi-aware = "yes";
bold-text-in-bright = "no";
word-delimiters = ",`|:\"'()[]{}<>";
};
cursor = {
style = "beam";
beam-thickness = 2;
};
scrollback = {
lines = 10000;
multiplier = 3;
};
bell = {
urgent = "yes";
notify = "yes";
command = "notify-send bell";
command-focused = "no";
};
url = {
launch = "xdg-open \${url}";
label-letters = "sadfjklewcmpgh";
osc8-underline = "url-mode";
protocols = "http, https, ftp, ftps, file, gemini, gopher, irc, ircs";
uri-characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.,~:;/?#@!$&%*+=\"'()[]";
};
colors = with theme.colors; {
alpha = "0.75";
foreground = text;
background = base;
regular0 = surface1;
regular1 = red;
regular2 = green;
regular3 = yellow;
regular4 = blue;
regular5 = pink;
regular6 = teal;
regular7 = subtext1;
bright0 = surface2;
bright1 = red;
bright2 = green;
bright3 = yellow;
bright4 = blue;
bright5 = pink;
bright6 = teal;
bright7 = subtext0;
};
mouse = {
hide-when-typing = "yes";
};
key-bindings = {
show-urls-launch = "Control+Shift+u";
unicode-input = "Control+Shift+i";
};
mouse-bindings = {
selection-override-modifiers = "Shift";
primary-paste = "BTN_MIDDLE";
select-begin = "BTN_LEFT";
select-begin-block = "Control+BTN_LEFT";
select-extend = "BTN_RIGHT";
select-extend-character-wise = "Control+BTN_RIGHT";
select-word = "BTN_LEFT-2";
select-word-whitespace = "Control+BTN_LEFT-2";
#select-row = "BTN_LEFT-3";
};
};
};
}

View File

@ -0,0 +1,23 @@
{
programs.hyprland = {
enable = true;
nvidiaPatches = true;
xwayland.enable = true;
};
environment.sessionVariables = {
If # your cursor becomes invisible
WLR_NO_HARDWARE_CURSORS = "1";
# Hint electron apps to use wayland
NIXOS_OZONE_WL = "1";
};
hardware = {
Opengl
opengl.enable = true;
# Most wayland compositors need this
nvidia.modesetting.enable = true;
};
}

View File

@ -0,0 +1,4 @@
{ lib, ... }: {
i18n.defaultLocale = lib.mkDefault "en_US.UTF-8";
time.timeZone = lib.mkDefault "Europe/Amsterdam";
}

View File

@ -0,0 +1,6 @@
# https://github.com/Mic92/nix-ld
{
programs.nix-ld = {
enable = true;
};
}

View File

@ -0,0 +1,61 @@
{
inputs,
lib,
pkgs,
...
}: {
nix = {
# https://github.com/NixOS/nix/issues/9579
# https://github.com/NixOS/nix/pull/9547
package = pkgs.inputs.nix.nix;
# Add each flake input as a registry
# To make nix3 commands consistent with the flake
registry = lib.mapAttrs (_: value: {flake = value;}) inputs;
# This will add your inputs to the system's legacy channels
# Making legacy nix commands consistent as well, awesome!
nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;
settings = {
substituters = lib.mkAfter ["https://cache.great-hyperlobic-omnicognate-neutron-wrangler.space"];
trusted-public-keys = ["cache.great-hyperlobic-omnicognate-neutron-wrangler.space:kszZ/NSwE/TjhOcPPQ16IuUiuRSisdiIwhKZCxguaWg="]; #TODO: Setup cache and change this
trusted-users = [
"root"
"@wheel"
];
# Deduplicate and optimize nix store
auto-optimise-store = lib.mkDefault true;
experimental-features = [
"nix-command"
"flakes"
"repl-flake"
"ca-derivations"
];
# See https://jackson.dev/post/nix-reasonable-defaults/
connect-timeout = 5;
log-lines = 25;
min-free = 128000000; # 128MB
max-free = 1000000000; # 1GB
warn-dirty = false;
system-features = [
"kvm"
"big-parallel"
"nixos-test"
];
flake-registry = ""; # Disable global flake registry
};
# garbage collection
gc = {
automatic = true;
dates = "weekly";
# Keep the last 3 generations
options = "--delete-older-than +3";
};
};
}

View File

@ -0,0 +1,29 @@
{ config, inputs, pkgs, lib, ... }:
let
inherit (config.networking) hostName;
# Only enable auto upgrade if current config came from a clean tree
# This avoids accidental auto-upgrades when working locally.
isClean = inputs.self ? rev;
in
{
system.autoUpgrade = {
enable = isClean;
dates = "hourly";
flags = [
"--refresh"
];
flake = "git://github.com/EmergentMind/nix-config?ref=release-${hostName}";
};
# Only run if current config (self) is older than the new one.
systemd.services.nixos-upgrade = lib.mkIf config.system.autoUpgrade.enable {
serviceConfig.ExecCondition = lib.getExe (
pkgs.writeShellScriptBin "check-date" ''
lastModified() {
nix flake metadata "$1" --refresh --json | ${lib.getExe pkgs.jq} '.lastModified'
}
test "$(lastModified "${config.system.autoUpgrade.flake}")" -gt "$(lastModified "self")"
''
);
};
}

View File

@ -0,0 +1,2 @@
# FIXME this is intentionally empty and is a hack to get configLib.scanPaths not to barf when default.nix doesn't exist in this dir. Need to modify
{}

View File

@ -0,0 +1,72 @@
# hosts level sops. see home/[user]/common/optional/sops.nix for home/user level
{ pkgs, inputs, config, configVars, ... }:
let
secretsDirectory = builtins.toString inputs.nix-secrets;
# FIXME: Switch to a configLib function
homeDirectory =
if pkgs.stdenv.isLinux
then "/home/${configVars.username}"
else "/Users/${configVars.username}";
in
{
imports = [
inputs.sops-nix.nixosModules.sops
];
sops = {
defaultSopsFile = "${secretsDirectory}/secrets.yaml";
validateSopsFiles = false;
age = {
# automatically import host SSH keys as age keys
sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
# this will use an age key that is expected to already be in the filesystem
keyFile = "/var/lib/sops-nix/key.txt";
# generate a new key if the key specified above does not exist
generateKey = true;
};
# secrets will be output to /run/secrets
# e.g. /run/secrets/msmtp-password
# secrets required for user creation are handled in respective ./users/<username>.nix files
# because they will be output to /run/secrets-for-users and only when the user is assigned to a host.
secrets = {
# For home-manager a separate age key is used to decrypt secrets and must be placed onto the host. This is because
# the user doesn't have read permission for the ssh service private key. However, we can bootstrap the age key from
# the secrets decrypted by the host key, which allows home-manager secrets to work without manually copying over
# the age key.
"age_keys/${config.networking.hostName}" = {
owner = config.users.users.${configVars.username}.name;
inherit (config.users.users.${configVars.username}) group;
# We need to ensure the entire directory structure is that of the user...
path = "${homeDirectory}/.config/sops/age/keys.txt";
};
# ta-password to /run/secrets-for-users/ so it can be used to create the user
"${configVars.username}/password".neededForUsers = true;
#FIXME move to mstmp.nix and also have host and address being assigned to configVars as per fidgetingbits
msmtp-host = { };
msmtp-address = { };
msmtp-password = { };
# extract to default pam-u2f authfile location for passwordless sudo. see ../optional/yubikey
"yubico/u2f_keys" = {
path = "/home/${configVars.username}/.config/Yubico/u2f_keys";
};
};
};
# The containing folders are created as root and if this is the first ~/.config/ entry,
# the ownership is busted and home-manager can't target because it can't write into .config...
# FIXME: We might not need this depending on how https://github.com/Mic92/sops-nix/issues/381 is fixed
system.activationScripts.sopsSetAgeKeyOwnwership = let
ageFolder = "${homeDirectory}/.config/sops/age";
user = config.users.users.${configVars.username}.name;
group = config.users.users.${configVars.username}.group;
in ''
mkdir -p ${ageFolder} || true
chown -R ${user}:${group} ${homeDirectory}/.config
'';
}

View File

@ -0,0 +1,12 @@
#
# This is a basic enablement of zsh at the host level as a safe guard
# in case enabling zsh as a home-manager module (see /home/ta/core/cli)
# at the user level fails for some reason.
#
{
programs.zsh = {
enable = true;
enableCompletion = true;
};
}

View File

@ -0,0 +1,153 @@
# NOTE: ... is needed because dikso passes diskoFile
{
lib,
disk ? [ "/dev/vda" ],
withSwap ? false,
swapSize,
configVars,
...
}:
### inspiration: https://github.com/chewblacka/nixos/blob/main/disko-config.nix
let
number_of_disks = if (builtins.length disks < 3)
then builtins.length disks
else throw "Error. Too many disks passed to disko.";
in
{
disko.devices = {
disk = {
vda = {
type = "disk";
device = builtins.elemAt disks 0;
content = {
type = "gpt";
partitions = {
ESP = {
# name = "ESP";
priority = 1;
start = "1MiB";
end = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ]
};
};
root = {
# name = "root";
start = "9G";
end = "100%";
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
subvolumes =
if (number_of_disks == 1) then
{
"@" = { };
"@/root" = {
mountpoint = "/";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/home" = {
mountpoint = "/home";
mountOptions = [ "compress=zstd" ];
};
"@/nix" = {
mountpoint = "/nix";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@persist" = {
mountpoint = "${configVars.persistFolder}";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/var-lib" = {
mountpoint = "/var/lib";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/var-log" = {
mountpoint = "/var/log";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/var-tmp" = {
mountpoint = "/var/tmp";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@swap" = lib.mkIf withSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = "${swapSize}G";
};
}
else
{
"@" = { };
"@/root" = {
mountpoint = "/";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/nix" = {
mountpoint = "/nix";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/persist" = {
mountpoint = "/persist";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/var-lib" = {
mountpoint = "/var/lib";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/var-log" = {
mountpoint = "/var/log";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/var-tmp" = {
mountpoint = "/var/tmp";
mountOptions = [ "compress=zstd" "noatime" ];
};
# TODO: Check if this is correct implementation
"@swap" = lib.mkIf withSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = "${swapSize}G";
};
};
};
};
};
};
};
vdb = if (number_of_disks == 1) then {}
else
{
type = "disk";
device = builtins.elemAt disks 1;
content = {
type = "gpt";
partitions = {
DATA = {
# name = "DATA";
start = "1MiB";
end = "100%";
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
subvolumes = {
"@" = {
mountpoint = "/DATA";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@/home" = {
mountpoint = "/home";
mountOptions = [ "compress=zstd" ];
};
};
};
};
};
};
};
};
};
}

View File

@ -0,0 +1,93 @@
# NOTE: ... is needed because dikso passes diskoFile
{
lib,
disk ? [ "/dev/vda" ],
withSwap ? true,
swapSize ? "16",
...
}:
{
disko.devices = {
disk = {
disk0 = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
ESP = {
# name = "ESP";
priority = 1;
start = "1M";
end = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ];
};
};
luks = {
# name = "root";
size = "100%";
content = {
type = "luks";
name = "crypted";
# disable settings.keyFile if you want to use interactive password entry
#passwordFile = "/tmp/secret.key"; # Interactive
settings = {
allowDiscards = true;
keyFile = "/tmp/secret.key";
};
additionalKeyFiles = [ "/tmp/additionalSecret.key" ];
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
# Subvolumes must set a mountpoint in order to be mounted,
# unless their parent is mounted
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@home" = {
mountpoint = "/home";
mountOptions = [ "compress=zstd" ];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@persist" = {
mountpoint = "/persist";
mountOptions = [ "compress=zstd"
"noatime"
];
};
"@var-lib" = {
mountpoint = "/var/lib";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@var-log" = {
mountpoint = "/var/log";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@var-tmp" = {
mountpoint = "/var/tmp";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@swap" = lib.mkIf withSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = "${swapSize}G";
};
};
};
};
};
};
};
};
};
};
}

View File

@ -0,0 +1,94 @@
# NOTE: ... is needed because dikso passes diskoFile
{
lib,
disk ? [ "/dev/vda" ],
withSwap ? true,
swapSize ? "16",
...
}:
{
disko.devices = {
disk = {
disk0 = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
ESP = {
# name = "ESP";
priority = 1;
start = "1M";
end = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ];
};
};
luks = {
# name = "root";
size = "100%";
content = {
type = "luks";
name = "crypted";
# disable settings.keyFile if you want to use interactive password entry
passwordFile = "/tmp/secret.key"; # Interactive
settings = {
allowDiscards = true;
# keyFile = "/tmp/secret.key";
};
additionalKeyFiles = [ "/tmp/hdd.key" ];
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
# Subvolumes must set a mountpoint in order to be mounted,
# unless their parent is mounted
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@home" = {
mountpoint = "/home";
mountOptions = [ "compress=zstd" ];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@persist" = {
mountpoint = "/persist";
mountOptions = [ "compress=zstd"
"noatime"
];
};
"@var-lib" = {
mountpoint = "/var/lib";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@var-log" = {
mountpoint = "/var/log";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@var-tmp" = {
mountpoint = "/var/tmp";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@swap" = lib.mkIf withSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = "${swapSize}G";
};
};
};
};
};
};
};
};
};
};
}

View File

@ -0,0 +1,96 @@
# NOTE: ... is needed because dikso passes diskoFile
{
lib,
disk ? [ "/dev/vda" ],
withSwap ? false,
swapSize,
configVars,
...
}:
{
disko.devices = {
disk = {
disk0 = {
type = "disk";
device = "/dev/disk/by-uuid/0A48C597-F95A-4187-BF57-83B45AE41327";
content = {
type = "gpt";
partitions = {
ESP = {
# name = "ESP";
priority = 1;
start = "1M";
end = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ];
};
};
luks = {
# name = "root";
size = "100%";
content = {
type = "luks";
name = "crypted";
# disable settings.keyFile if you want to use interactive password entry
#passwordFile = "/tmp/secret.key"; # Interactive
settings = {
allowDiscards = true;
keyFile = "/tmp/secret.key";
};
additionalKeyFiles = [ "/tmp/additionalSecret.key" ];
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
# Subvolumes must set a mountpoint in order to be mounted,
# unless their parent is mounted
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@home" = {
mountpoint = "/home";
mountOptions = [ "compress=zstd" ];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@persist" = {
mountpoint = "${configVars.persistFolder}";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@var-lib" = {
mountpoint = "/var/lib";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@var-log" = {
mountpoint = "/var/log";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@var-tmp" = {
mountpoint = "/var/tmp";
mountOptions = [ "compress=zstd" "noatime" ];
};
"@swap" = lib.mkIf withSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = "${swapSize}G";
};
};
};
};
};
};
};
};
};
};
}

View File

@ -0,0 +1,23 @@
{ pkgs, ... }:
{
sound.enable = true;
hardware.pulseaudio.enable = false;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
wireplumber.enable = true;
jack.enable = true;
# use the example session manager (no others are packaged yet so this is enabled by default,
# no need to redefine it in your config for now)
# media-session.enable = true;
};
environment.systemPackages = builtins.attrValues {
inherit (pkgs)
pamixer# pulseaudio sound mixer
pavucontrol; # pulseaudio volume control
};
}

View File

@ -0,0 +1,31 @@
{
pkgs,
config,
...
}: {
console = {
useXkbConfig = true;
earlySetup = false;
};
boot = {
plymouth = {
enable = true;
theme = "spinner-monochrome";
themePackages = [
(pkgs.plymouth-spinner-monochrome.override {inherit (config.boot.plymouth) logo;})
];
};
loader.timeout = 0;
kernelParams = [
"quiet"
"loglevel=3"
"systemd.show_status=auto"
"udev.log_level=3"
"rd.udev.log_level=3"
"vt.global_cursor_default=0"
];
consoleLogLevel = 0;
initrd.verbose = false;
};
}

View File

@ -0,0 +1,77 @@
#
# FIXME check for dependency somehow? Requires the msmtp.nix option for email notifications
#
{ pkgs, lib, config, ... }:
let
# FIXME
# isEnabled = name: predicate: {
# assertion = predicate;
# message = "${name} should be enabled for the clamav.nix config to work correctly.";
# };
# Function to notify users and admin when a suspicious file is detected
notify-all-users = pkgs.writeScript "notify-all-users-of-sus-file"
''
#!/usr/bin/env bash
ALERT="Signature detected by clamav: $CLAM_VIRUSEVENT_VIRUSNAME in $CLAM_VIRUSEVENT_FILENAME"
# Send an alert to all graphical users.
for ADDRESS in /run/user/*; do
USERID=''${ADDRESS#/run/user/}
/run/wrappers/bin/sudo -u "#$USERID" DBUS_SESSION_BUS_ADDRESS="unix:path=$ADDRESS/bus" ${pkgs.libnotify}/bin/notify-send -i dialog-warning "Suspicious file" "$ALERT"
done
echo -e "To:$(hostname).alerts.net@hexagon.cx\n\nSubject: Suspicious file on $(hostname)\n\n$ALERT" | msmtp -a default alerts.net@hexagon.cx
'';
in
{
# FIXME
# assertions = lib.mapAttrsToList isEnabled {
# "hosts/common/optional/msmtp" = config.msmtp.enable;
# };
security.sudo = {
extraConfig =
''
clamav ALL = (ALL) NOPASSWD: SETENV: ${pkgs.libnotify}/bin/notify-send
'';
};
services = {
clamav = {
daemon = {
enable = true;
settings = {
# ClamAV configuration. Refer to <https://linux.die.net/man/5/clamd.conf>, for details on supported values.
OnAccessPrevention = false;
OnAccessExtraScanning = true;
OnAccessExcludeUname = "clamav";
VirusEvent = "${notify-all-users}";
User = "clamav";
};
};
updater = {
enable = true;
interval = "daily";
frequency = 2;
settings = {
# Refer to <https://linux.die.net/man/5/freshclam.conf>,for details on supported values.
};
};
# # TODO stage 3 checkback - this isn't currently available in stable but looks to be coming down the pipe https://github.com/NixOS/nixpkgs/commits/master/nixos/modules/services/security/clamav.nix
# fangfrisch = {
# enable = true;
# interval = "daily";
# };
# scanner = {
# # By default his runs using 10 cores, be sure
# enable = true;
# interval = "*-*-* 04:00:00"; # default
# scanDirectories = [
# # these are currently defaults from the nixos pkg maintainer for everything he thought was valid for nixos
# "/home" "/var/lib" "/tmp" "/etc" "/var/tmp"
# ];
# };
};
};
}

View File

@ -0,0 +1,44 @@
{ lib, config, ... }:
let
#FIXME: switch this to 10022 at some point. leaving it as 22 for now becuase I don't have time
# to add all the required matchblock entries
sshPort = 22;
# Sops needs access to the keys before the persist dirs are even mounted; so
# just persisting the keys won't work, we must point at /persist
hasOptinPersistence = false;
in
{
services.openssh = {
enable = true;
ports = [ sshPort ];
settings = {
# Harden
PasswordAuthentication = false;
PermitRootLogin = "no";
# Automatically remove stale sockets
StreamLocalBindUnlink = "yes";
# Allow forwarding ports to everywhere
GatewayPorts = "clientspecified";
};
hostKeys = [{
path = "${lib.optionalString hasOptinPersistence "/persist"}/etc/ssh/ssh_host_ed25519_key";
type = "ed25519";
}];
# Fix LPE vulnerability with sudo use SSH_AUTH_SOCK: https://github.com/NixOS/nixpkgs/issues/31611
authorizedKeysFiles = lib.mkForce ["/etc/ssh/authorized_keys.d/%u"];
};
# yubikey login / sudo
# this potentially causes a security issue that we mitigated above
security.pam = {
sshAgentAuth.enable = true;
services = {
sudo.u2fAuth = true;
};
};
networking.firewall.allowedTCPPorts = [ sshPort ];
}

View File

@ -0,0 +1,37 @@
{ config, pkgs, lib, ... }:
let
cfg = config.autoLogin;
in
{
# Declare custom options for conditionally enabling auto login
options.autoLogin = {
enable = lib.mkEnableOption "Enable automatic login";
username = lib.mkOption {
type = lib.types.str;
default = "guest";
description = "User to automatically login";
};
};
config = {
# environment.systemPackages = with pkgs; [ greetd.tuigreet ];
services.greetd = {
enable = true;
restart = true;
settings = {
default_session = {
command = "${pkgs.greetd.tuigreet}/bin/tuigreet --asterisks --time --time-format '%I:%M %p | %a %h | %F' --cmd Hyprland";
user = "ta";
};
initial_session = lib.mkIf cfg.enable {
command = "${pkgs.hyprland}/bin/Hyprland";
user = "${cfg.username}";
};
};
};
};
}

View File

@ -0,0 +1,9 @@
{
boot.loader = {
systemd-boot = {
enable = true;
consoleMode = "max";
};
efi.canTouchEfiVariables = true;
};
}

View File

@ -0,0 +1,25 @@
#
# Basic user for viewing media on gusto
#
{ pkgs, inputs, config, ... }:
{
# Decrypt media-password to /run/secrets-for-users/ so it can be used to create the user
sops.secrets.media-password.neededForUsers = true;
users.mutableUsers = false; #Required for password to be set via sops during system activation!
users.users.${configVars.username} = {
isNormalUser = true;
hashedPasswordFile = config.sops.secrets.media-password.path;
shell = pkgs.zsh; #default shell
extraGroups = [
"audio"
"video"
];
packages = [ pkgs.home-manager ];
};
# Import this user's personal/home configurations
home-manager.users.media = import ../../../../home/media/${config.networking.hostName}.nix;
}

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