nix/litten.brenise.dev/configuration.nix

622 lines
15 KiB
Nix

{ config, pkgs, lib, ... }:
let
importedVars = import ./variables.nix { inherit config pkgs lib; };
in
with importedVars;
{
nixpkgs.config = {
allowUnfreePredicate = pkg:
builtins.elem (lib.getName pkg) [
# "claude-code"
"obsidian"
"packer"
"reaper"
# "n8n"
"vscode"
"terraform"
"zoom"
# "charlatan3"
# "steam"
# "steam-original"
# "steam-unwrapped"
# "steam-run"
# "tokenizer.json" # goose-cli
];
};
nixpkgs.overlays = [
(self: super: {
# n8n = unstable.n8n;
ansible = super.ansible.overrideAttrs (oldAttrs: {
propagatedBuildInputs = oldAttrs.propagatedBuildInputs ++ [ super.python312Packages.jmespath ];
}); # Add jmespath to ansible build inputs
# https://blaukraut.info/
# charlatan3 = super.callPackage ./overlays/clap/charlatan3.nix { };
})
];
imports = [
./hardware-configuration.nix
<home-manager/nixos>
];
boot = {
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
};
hardware = {
bluetooth.enable = true;
keyboard.qmk.enable = true;
graphics = { # https://wiki.nixos.org/wiki/Accelerated_Video_Playback
enable = true;
extraPackages = with pkgs; [
intel-media-driver
];
};
};
networking = {
hostName = "${host_name}";
firewall.enable = false;
interfaces = {
enp100s0.ipv4.addresses = [{
address = "192.168.1.35";
prefixLength = 24;
}];
};
defaultGateway = {
address = "192.168.1.1";
interface = "enp100s0";
};
# TODO https://nixos.wiki/wiki/Encrypted_DNS
nameservers = [ "1.1.1.1" "8.8.8.8" ];
extraHosts = ''
192.168.1.1 shinx.${host_fqdn}
'';
localCommands = ''
ip route add 10.19.21.11/32 dev ${config.networking.defaultGateway.interface} via ${config.networking.defaultGateway.address} || true # timburr
ip route add 10.19.21.34/32 dev ${config.networking.defaultGateway.interface} via ${config.networking.defaultGateway.address} || true # weavile
'';
};
time.timeZone = "America/Los_Angeles";
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
# keyMap = "us";
useXkbConfig = true; # use xkbOptions in tty.
};
users = {
groups = {
glance = {};
};
users = {
root = {
openssh.authorizedKeys.keyFiles = [
/etc/nixos/ssh/authorized_keys
];
};
blee = {
openssh.authorizedKeys.keyFiles = [
/etc/nixos/ssh/authorized_keys
];
isNormalUser = true;
extraGroups = [
"wheel"
"adbusers"
"docker"
"glance"
];
packages = with pkgs; [
# unstable.goose-cli
mariadb
notify-client
gh
brave
chromium
element-desktop
firefox
haruna
gimp
gnumake
home-manager
jellyfin-media-player
kdePackages.kate #kwrite
kdePackages.kdenlive
kdePackages.kcalc
# libsForQt5.kcalc
# unstable.logseq # warning: https://github.com/logseq/logseq/issues/10851#issuecomment-2402925912
# unstable.ghostty
moonlight-qt
nmap
obs-studio
obsidian
# pavucontrol
qbittorrent
rclone
# rtorrent
sq
# synergy
tenacity
thunderbird
tor-browser
via
vlc
vscode
yt-dlp
zoom-us
# Build vim huge with clipboard support
(vim_configurable.overrideAttrs (oldAttrs: {
features = "huge";
}))
awscli2
aws-sam-cli
packer
terraform
ansible
python311
python311Packages.pip
python311Packages.ipython
libreoffice-qt
hunspell
hunspellDicts.en-us
# postman # nope, auth is broken
nodejs_20
yarn
deno
nix-init
nix-tree
nurl
# music apps
reaper
spek
];
};
glance = {
isSystemUser = true;
group = "glance";
home = "/var/lib/glance";
createHome = true;
description = "Glance service user";
# shell = pkgs.bash;
};
};
};
# home-manager.users.blee = { imports = [ ./home.nix ]; };
environment = {
systemPackages = with pkgs; [
arp-scan
binutils
coreutils
cryptsetup
curl
difftastic
dig
dnscontrol
dnsutils
doas
exiftool
ffmpeg
file
fzf
git
go
htop
iftop
imagemagick
iperf
jq
lego
libressl
lm_sensors
mediainfo
net-snmp # snmpwalk
netcat
nettools
nix-output-monitor
parted
pass
pciutils # lspci
psmisc
qrencode
rsync
screen
tcpdump
tmux
tree
unzip
vim
vulkan-tools
wget
whois
wireguard-tools
zbar
zip
];
shellInit = ''
pheonix() {
systemctl restart "$1"
journalctl -fu "$1"
}
'';
# vscode on Wayland
sessionVariables.NIXOS_OZONE_WL = "1";
# TODO: https://github.com/nix-community/plasma-manager
plasma6.excludePackages = with pkgs.kdePackages; [
plasma-browser-integration
];
etc."gitconfig".text = ''
[init]
defaultBranch = main
'';
};
programs = {
adb.enable = true;
appimage = {
enable = true;
binfmt = true;
package = pkgs.appimage-run.override {
extraPkgs = pkgs: [
pkgs.libthai # lume
];
};
};
# hyprland = {
# enable = true;
# xwayland.enable = true;
# };
fish.enable = true;
vim = {
enable = true;
defaultEditor = true;
};
bash = {
shellAliases = {
ll = "ls -lAF --classify --group-directories-first";
l = "ls -lF --classify --group-directories-first";
};
# https://nixos.wiki/wiki/Fish
interactiveShellInit = ''
if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
then
shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
fi
'';
};
mtr.enable = true;
gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
kdeconnect.enable = true;
chromium = {
enable = true;
extraOpts = {
"SpellcheckEnabled" = false;
"DefaultSearchProviderEnabled" = true;
"DefaultSearchProviderName" = "Kagi";
"DefaultSearchProviderSearchURL" = "https://kagi.com/search?q={searchTerms}";
"SearchSuggestEnabled" = false;
"DefaultSearchProviderSuggestURL" = "";
};
};
};
security = {
sudo.enable = false;
doas = {
enable = true;
extraRules = [
{
users = [ "blee" ];
persist = true;
}
];
};
};
services = {
openssh.enable = true;
udev.packages = [ pkgs.via ];
# https://discourse.nixos.org/t/bluetooth-a2dp-sink-not-showing-up-in-pulseaudio-on-nixos/32447/4?u=bleetube
pipewire = {
enable = true;
pulse.enable = true;
alsa.enable = true; # for tenacity
# jack.enable = true; # this might be useful for reaper, but enabling it breaks stereo audio for some reason
};
# avahi = { # for resolving start9 hostname
# enable = true;
# nssmdns4 = true; # Enable NSS support for mDNS
# };
syncthing = {
enable = true;
user = "blee";
dataDir = "/home/blee/Documents";
};
journald.extraConfig = "MaxRetentionSec=30day";
# https://github.com/NixOS/nixpkgs/blob/nixos-23.05/nixos/modules/services/monitoring/prometheus/exporters.nix
prometheus.exporters.node = {
enable = true;
port = 8030;
# openFirewall = true;
enabledCollectors = [
"cpu.info"
"interrupts"
"netstat"
"vmstat"
"systemd"
"tcpstat"
"processes"
];
};
caddy = {
enable = true;
package = caddyWithPlugins;
# logFormat = "output discard";
logFormat = "level DEBUG";
extraConfig = let
tlsConfig = ''
tls {
dns namecheap {
api_key {env.NAMECHEAP_API_KEY}
user {env.NAMECHEAP_API_USER}
api_endpoint https://api.namecheap.com/xml.response
}
}
'';
in ''
${host_fqdn} {
${tlsConfig}
reverse_proxy http://127.0.0.1:8034 # open-webui
# handle /files/* {
# root /mnt/usb/
# file_server browse
# }
}
${host_fqdn}:4430 {
${tlsConfig}
reverse_proxy http://127.0.0.1:8030 # node_exporter
}
${host_fqdn}:4432 {
${tlsConfig}
reverse_proxy http://127.0.0.1:8032 # glance
}
${host_fqdn}:4434 {
${tlsConfig}
reverse_proxy http://127.0.0.1:8034 # open-webui
}
${host_fqdn}:4435 {
${tlsConfig}
reverse_proxy http://127.0.0.1:8035 # mealie
}
${host_fqdn}:4436 {
${tlsConfig}
reverse_proxy http://127.0.0.1:8036 # litellm
}
:9999 {
respond "success"
}
'';
};
open-webui = {
enable = true;
port = 8034;
};
litellm = {
enable = true;
port = 8036;
environmentFile = litellmEnvFile;
settings = {
litellm_settings = {
set_verbose = true;
};
model_list = [
{
model_name = "grok-3";
litellm_params = {
model = "xai/grok-3-latest";
api_key = "os.environ/XAI_API_KEY"; # LiteLLM reads this env var
};
}
{
model_name = "deepseek-r1-distill-llama-70b";
litellm_params = {
model = "groq/deepseek-r1-distill-llama-70b";
api_key = "os.environ/GROK_API_KEY"; # LiteLLM reads this env var
};
}
{
model_name = "claude-3.5-sonnet";
litellm_params = {
model = "anthropic/claude-3-5-sonnet-latest";
api_key = "os.environ/ANTHROPIC_API_KEY"; # LiteLLM reads this env var
};
}
{
model_name = "gemini-2.0-flash";
litellm_params = {
model = "gemini/gemini-2.0-flash-exp";
api_key = "os.environ/GOOGLE_API_KEY"; # LiteLLM reads this env var
safety_settings = [
{ category = "HARM_CATEGORY_HARASSMENT"; threshold = "BLOCK_NONE"; }
{ category = "HARM_CATEGORY_HATE_SPEECH"; threshold = "BLOCK_NONE"; }
{ category = "HARM_CATEGORY_SEXUALLY_EXPLICIT"; threshold = "BLOCK_NONE"; }
{ category = "HARM_CATEGORY_DANGEROUS_CONTENT"; threshold = "BLOCK_NONE"; }
];
};
}
];
};
};
mealie = {
enable = true;
port = 8035;
# listenAddress = "127.0.0.1";
listenAddress = "0.0.0.0";
# package = unstable.mealie;
};
# n8n.enable = true;
strongswan = {
enable = false;
secrets = [
"/etc/nixos/ipsec.secrets"
];
connections = {
"aws-vpn" = {
type = "tunnel";
authby = "secret";
left = "%defaultroute";
leftsubnet = "0.0.0.0/0";
right = "${secrets.aws-vpn.tunnel-address}";
rightsubnet = "10.0.64.0/24"; # subnet-0f2b39fd2ed6a88d7 "private-lambda-us-west-2d"
ike = "aes256-sha2_256-modp2048!";
esp = "aes256-sha2_256!";
ikelifetime = "8h";
keylife = "1h";
keyingtries = "3";
auto = "start";
installpolicy = "yes"; # Install IPsec policies
routing = "yes"; # Install routes
dpdaction = "restart"; # Restart connection if peer is unreachable
dpddelay = "30s"; # Dead peer detection delay
closeaction = "restart"; # Restart connection if it drops
};
};
setup = {
charondebug = "esp 2, ike 2, cfg 2, net 2, enc 2";
};
};
desktopManager.plasma6.enable = true;
displayManager = {
sddm.enable = true;
sddm.wayland.enable = true;
#defaultSession = "plasmawayland";
};
xserver.enable = true;
};
systemd = {
services.glance = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
User = "glance";
Group = "glance";
WorkingDirectory = "/var/lib/glance";
# Environment = "LOG_LEVEL=debug"; # https://github.com/glanceapp/glance/issues/196
ExecStart = "${pkgs.glance}/bin/glance --config config.yaml";
};
};
services.ena-vpn = {
description = "ENA Corp VPN";
# wantedBy = [ "multi-user.target" ]; # 2fa required, avoid startup
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "simple";
User = "root";
ExecStart = "${pkgs.openfortivpn}/bin/openfortivpn -c /etc/openfortivpn/config";
};
};
services.mealie.environment = {
# https://docs.mealie.io/documentation/getting-started/installation/open-ai/
OPENAI_API_KEY = "${secrets.mealie.openai-api-key}";
};
# services.n8n.environment = {
# N8N_EDITOR_BASE_URL = "https://${host_fqdn}:4433";
# N8N_DIAGNOSTICS_ENABLED = "false"; # Also disables "Ask AI" in the code node
# N8N_HIRING_BANNER_ENABLED = "false";
# N8N_METRICS = "true";
# N8N_PORT = "8033";
# };
tmpfiles.rules = [
"d /srv/src 0775 root users - -"
];
};
# Create the OpenFortiVPN config directory and file
environment.etc = {
"openfortivpn/config" = {
text = ''
host = fortivpn.ena.net
port = 443
username = ${secrets.ena-vpn.username}
password = ${secrets.ena-vpn.password}
set-dns = 0
set-routes = 1
trusted-cert = fa59c235354ec625b0e560e4263b1eff793480f399a39b7f80b18fb865184ecd
'';
mode = "0600";
};
"ipsec.secrets" = {
text = ''
${secrets.aws-vpn.tunnel-address} : PSK "${secrets.aws-vpn.psk}"
'';
mode = "0600";
};
};
virtualisation.docker = {
enable = true;
rootless = {
enable = true;
setSocketVariable = true;
};
autoPrune = {
enable = true;
dates = "monthly";
};
};
system.stateVersion = "23.05";
}