laptop-config/modules/laptop.nix

217 lines
5.1 KiB
Nix

{ config, pkgs, ... }:
{
imports = [ ../hardware-configuration.nix ./emulation.nix ];
# === System Packages ===
environment.systemPackages = with pkgs; [
# Core development tools
qmd
nodejs
bun
git
zsh
curl
wget
# System utilities
htop
fastfetch
ripgrep
fd
jq
tree
tmux
unzip
neovim
# SSH essentials
openssh
mosh
# Network debugging
bind
traceroute
mtr
netcat
# SMB/CIFS mount support
cifs-utils
mount-truenas-shared
# Windows apps via Wine
wineWow64Packages.stable
];
# DNS fallback (Tailscale MagicDNS sometimes blocks public resolvers)
networking.nameservers = [ "1.1.1.1" "8.8.8.8" ];
# Passwordless sudo for sscoble
security.sudo.extraRules = [
{ groups = [ "wheel" ]; commands = [ { command = "ALL"; options = [ "NOPASSWD" ]; } ]; }
];
# === Network Shares ===
# TrueNAS "Shared" volume — tries LAN IP first, falls back to Tailscale
# Credentials stored at /etc/nixos/smb-credentials (NOT in repo)
systemd.tmpfiles.rules = [
"d /mnt/shared 0755 root root -"
];
systemd.services.mount-truenas-shared = {
description = "Mount TrueNAS Shared SMB volume";
after = [ "network-online.target" "tailscaled.service" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${pkgs.mount-truenas-shared}/bin/mount-truenas-shared";
ExecStop = "${pkgs.mount-truenas-shared}/bin/mount-truenas-shared umount";
};
};
nixpkgs.overlays = [
(final: prev: {
mount-truenas-shared = prev.writeShellScriptBin "mount-truenas-shared" ''
set -o pipefail
SHARE="Shared"
MOUNTPOINT="/mnt/shared"
CREDENTIALS="/etc/nixos/smb-credentials"
MOUNT_OPTS="credentials=$CREDENTIALS,vers=3.0,uid=1000,gid=100,nodfs,noperm,iocharset=utf8,file_mode=0644,dir_mode=0755"
LAN_IP="192.168.168.93"
TAILSCALE_IP="100.70.3.101"
# Already mounted?
if grep -qs "$MOUNTPOINT" /proc/mounts; then
exit 0
fi
# Find a reachable NAS
SERVER=""
timeout 2 bash -c "</dev/tcp/$LAN_IP/445" 2>/dev/null && SERVER="$LAN_IP"
if [ -z "$SERVER" ]; then
timeout 2 bash -c "</dev/tcp/$TAILSCALE_IP/445" 2>/dev/null && SERVER="$TAILSCALE_IP"
fi
CMD="''${1:-mount}"
case "$CMD" in
mount)
if [ -z "$SERVER" ]; then
echo "No NAS reachable (tried $LAN_IP and $TAILSCALE_IP) — mount deferred"
exit 0
fi
echo "Mounting $SHARE from $SERVER..."
mount -t cifs "//$SERVER/$SHARE" "$MOUNTPOINT" -o "$MOUNT_OPTS"
;;
umount)
if grep -qs "$MOUNTPOINT" /proc/mounts; then
umount "$MOUNTPOINT"
fi
;;
esac
'';
})
];
# === Shell ===
programs.zsh = {
enable = true;
autosuggestions.enable = true;
syntaxHighlighting.enable = true;
shellAliases = {
ll = "ls -la";
la = "ls -A";
l = "ls -CF";
nix-rebuild = "sudo nixos-rebuild switch --flake ~/laptop-config#laptop";
nix-clean = "sudo nix-collect-garbage -d && nix-collect-garbage -d";
vault-search = "qmd query";
pi-run = "pi";
};
ohMyZsh = {
enable = true;
plugins = [ "git" "node" "npm" "ssh-agent" "sudo" "history" ];
theme = "robbyrussell";
};
};
# Default to zsh
users.defaultUserShell = pkgs.zsh;
# === SSH ===
programs.ssh = {
startAgent = true;
extraConfig = ''
Host n97-mini
HostName 192.168.168.41
User sscoble
ForwardAgent yes
IdentityFile ~/.ssh/id_ed25519
Host n97-mini-ext
HostName os.scoble.me
Port 22
User sscoble
ForwardAgent yes
IdentityFile ~/.ssh/id_ed25519
Host forgejo
HostName os.scoble.me
User git
IdentityFile ~/.ssh/id_ed25519
'';
};
# === Fonts (for pi TUI) ===
fonts.packages = with pkgs; [
nerd-fonts.jetbrains-mono
nerd-fonts.fira-code
];
# === Nix Settings ===
nix = {
settings = {
experimental-features = [ "nix-command" "flakes" ];
auto-optimise-store = true;
};
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
};
# === User ===
users.users.sscoble = {
isNormalUser = true;
description = "Scott Scoble";
extraGroups = [ "networkmanager" "wheel" "docker" ];
shell = pkgs.zsh;
packages = with pkgs; [
neovim
tmux
ripgrep
fd
bat
eza
delta
];
};
# === Locale ===
time.timeZone = "America/Los_Angeles";
i18n.defaultLocale = "en_US.UTF-8";
# === SSH Server ===
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
openFirewall = true;
};
# === Boot ===
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
}