Compare commits

...

2 commits

Author SHA1 Message Date
Geir Okkenhaug Jerstad
3715e542b2 feat: add little-rascal laptop configuration and deployment
- Add complete NixOS configuration for little-rascal laptop
- Include Niri window manager and CLI-focused setup
- Add hardware configuration for laptop hardware
- Include deployment script for little-rascal
- Update flake.nix to include little-rascal as build target
- Add deploy-rs configuration for little-rascal deployment

The little-rascal laptop is now fully integrated into the Home Lab
infrastructure with complete NixOS configuration management.
2025-06-30 11:40:31 +02:00
Geir Okkenhaug Jerstad
f42bae513c feat(lab-tool): integrate little-rascal laptop into Home Lab management
- Add little-rascal to lab-tool configuration with proper attributes
- Include little-rascal in machine management, SSH connectivity, and deployment targets
- Update README.md with examples including little-rascal
- Verify full integration: machines listing, status monitoring, SSH access, deployment ready

The little-rascal laptop is now fully managed through the unified lab-tool interface
alongside other Home Lab machines (congenital-optimist, sleeper-service, grey-area, reverse-proxy).
2025-06-30 11:40:10 +02:00
8 changed files with 388 additions and 52 deletions

12
flake.lock generated
View file

@ -54,11 +54,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1750776420,
"narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=",
"lastModified": 1751011381,
"narHash": "sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "30a61f056ac492e3b7cdcb69c1e6abdcf00e39cf",
"rev": "30e2e2857ba47844aa71991daa6ed1fc678bcbb7",
"type": "github"
},
"original": {
@ -70,11 +70,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1750838302,
"narHash": "sha256-aVkL3/yu50oQzi2YuKo0ceiCypVZpZXYd2P2p1FMJM4=",
"lastModified": 1750969886,
"narHash": "sha256-zW/OFnotiz/ndPFdebpo3X0CrbVNf22n4DjN2vxlb58=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7284e2decc982b81a296ab35aa46e804baaa1cfe",
"rev": "a676066377a2fe7457369dd37c31fd2263b662f4",
"type": "github"
},
"original": {

View file

@ -104,6 +104,7 @@
nixpkgs-fmt
git
emacs
unstable.claude-code # Claude Code CLI for AI assistance
];
shellHook = ''
echo "Home-lab development environment"
@ -116,6 +117,11 @@
echo ""
echo "Build with: nixos-rebuild build --flake .#<config>"
echo "Switch with: nixos-rebuild switch --flake .#<config>"
echo ""
echo "Available tools:"
echo " - claude-code: Claude AI CLI assistant"
echo " - nixd: Nix language server"
echo " - alejandra: Nix formatter"
'';
};
@ -133,6 +139,37 @@
echo "Tangle dotfiles with: emacs --batch -l org --eval \"(org-babel-tangle-file \\\"README.org\\\")\""
'';
};
# AI development shell with Claude Code and related tools
ai = nixpkgs.legacyPackages.${system}.mkShell {
buildInputs = with nixpkgs.legacyPackages.${system}; [
unstable.claude-code
git
emacs
nixd
alejandra
curl
jq
tree
];
shellHook = ''
echo "AI Development Environment"
echo "Available tools:"
echo " - claude-code: Claude AI CLI assistant"
echo " - git: Version control"
echo " - emacs: Text editor"
echo " - curl/jq: API testing tools"
echo " - tree: Directory structure visualization"
echo ""
echo "Claude Code usage:"
echo " claude-code --help # Show help"
echo " claude-code chat # Start interactive chat"
echo " claude-code apply # Apply code suggestions"
echo ""
echo "Configure Claude Code with your API key:"
echo " claude-code config set api-key YOUR_API_KEY"
'';
};
};
# Overlays for package customizations

View file

@ -1,6 +1,5 @@
# Little Rascal - Development Laptop Configuration
# Based on congenital-optimist with laptop-specific adjustments
{
config,
pkgs,
@ -11,38 +10,39 @@
}: {
imports = [
./hardware-configuration.nix
# Common modules
../../modules/common/base.nix
../../modules/common/nix.nix
../../modules/common/tty.nix
../../modules/common/emacs.nix
# Desktop
../../modules/desktop/niri.nix
../../modules/desktop/cosmic.nix
../../modules/desktop/fonts.nix
# Development
# Development
../../modules/development/tools.nix
../../modules/ai/claude-code.nix
# Users
../../modules/users/geir.nix
../../modules/users/common.nix
../../modules/users/shell-aliases.nix
# Virtualization
../../modules/virtualization/libvirt.nix
../../modules/virtualization/incus.nix
../../modules/virtualization/podman.nix
# Audio
../../modules/sound/pipewire.nix
# Network
../../modules/network/common.nix
../../modules/network/extraHosts.nix
# Security
../../modules/security/ssh-keys.nix
];
@ -50,26 +50,26 @@
networking = {
hostName = "little-rascal";
networkmanager.enable = true;
# Tailscale for home lab access
firewall = {
enable = true;
allowedUDPPorts = [ 41641 ]; # Tailscale
allowedTCPPorts = [ 22 ]; # SSH
allowedUDPPorts = [41641]; # Tailscale
allowedTCPPorts = [22]; # SSH
};
};
# Boot configuration
# Boot configuration
boot = {
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
timeout = 3;
};
kernelModules = [ "kvm-amd" "zram" ];
kernelModules = ["kvm-amd" "zram"];
tmp.cleanOnBoot = true;
# zram swap like other machines
kernel.sysctl."vm.swappiness" = 180;
};
@ -92,7 +92,7 @@
# Power management for laptop
power-profiles-daemon.enable = true;
upower.enable = true;
# Display manager
greetd = {
enable = true;
@ -103,12 +103,12 @@
};
};
};
# Essential services
tailscale.enable = true;
blueman.enable = true;
printing.enable = true;
# Location services for time zone
geoclue2.enable = true;
};
@ -123,4 +123,4 @@
# System version
system.stateVersion = "25.05";
}
}

View file

@ -1,9 +1,12 @@
# Hardware Configuration for Little Rascal
# Lenovo Yoga Slim 7 14ARE05 - AMD Ryzen 7 4700U
{ config, lib, pkgs, modulesPath, ... }:
{
config,
lib,
pkgs,
modulesPath,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
@ -18,25 +21,25 @@
"sd_mod"
"sdhci_pci"
];
kernelModules = [ ];
kernelModules = [];
};
kernelModules = [ "kvm-amd" ]; # AMD Ryzen system
extraModulePackages = [ ];
kernelModules = ["kvm-amd"]; # AMD Ryzen system
extraModulePackages = [];
};
# Filesystem configuration - TEMPLATE
# Update these paths and UUIDs after running nixos-generate-config
fileSystems = {
"/" = {
device = "/dev/disk/by-uuid/REPLACE-WITH-ROOT-UUID";
device = "/dev/disk/by-label/nixos";
fsType = "ext4";
};
"/boot" = {
device = "/dev/disk/by-uuid/REPLACE-WITH-BOOT-UUID";
device = "/dev/disk/by-label/BOOT";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
options = ["fmask=0022" "dmask=0022"];
};
};
@ -50,27 +53,27 @@
hardware = {
# CPU configuration - AMD Ryzen 7 4700U
cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
# Enable firmware updates
enableRedistributableFirmware = true;
# Graphics configuration - AMD Radeon Vega (integrated)
graphics = {
enable = true;
enable32Bit = true;
# AMD integrated graphics drivers
extraPackages = with pkgs; [
amdvlk # AMD Vulkan driver
rocmPackages.clr.icd # OpenCL support
amdvlk # AMD Vulkan driver
rocmPackages.clr.icd # OpenCL support
];
# 32-bit support for compatibility
extraPackages32 = with pkgs.driversi686Linux; [
amdvlk
];
};
# Bluetooth support for Intel AX200
bluetooth = {
enable = true;
@ -89,7 +92,7 @@
networking = {
# Enable NetworkManager for WiFi management
networkmanager.enable = true;
# Disable wpa_supplicant (using NetworkManager)
wireless.enable = false;
};
@ -122,4 +125,4 @@
# - Intel Wi-Fi 6 AX200 + Bluetooth
# - 128GB SSD storage
# - Currently running btrfs filesystem
}
}

View file

@ -0,0 +1,107 @@
# Minimal NixOS Configuration for little-rascal
# This is for initial installation - use deploy-rs to apply full config afterwards
{
config,
pkgs,
lib,
...
}: {
# Enable flakes for configuration deployment
nix.settings.experimental-features = ["nix-command" "flakes"];
# Boot configuration
boot = {
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
timeout = 3;
};
# Import hardware scan results
initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod"];
kernelModules = ["kvm-amd"];
# Clean tmp on boot
tmp.cleanOnBoot = true;
};
# Minimal file systems - you'll need to adjust this based on your disk setup
fileSystems."/" = {
device = "/dev/disk/by-label/nixos";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/BOOT";
fsType = "vfat";
};
# Basic networking
networking = {
hostName = "little-rascal";
networkmanager.enable = true;
# Open SSH port
firewall = {
enable = true;
allowedTCPPorts = [22];
allowedUDPPorts = [41641]; # Tailscale
};
};
# Essential services
services = {
# SSH for remote deployment
openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "prohibit-password";
PubkeyAuthentication = true;
};
};
# Tailscale for secure home lab access
tailscale.enable = true;
};
# Create admin user for deployment
users = {
mutableUsers = false;
users = {
root = {
# Add your SSH public key here for initial access
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPgzKS1N7+7+N1/8U8++1pl4hapDm6TOy0QhrfrYA8mz geir@geokkjer.eu-admin" # Admin key
];
};
geir = {
isNormalUser = true;
extraGroups = ["wheel" "networkmanager" "sudo"];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHukJK0Kc1YexvzF8PdqaqWNZdVffGoM6ePPMecrU6dM geir@geokkjer.eu-dev" # Dev key
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPgzKS1N7+7+N1/8U8++1pl4hapDm6TOy0QhrfrYA8mz geir@geokkjer.eu-admin" # Admin key for backup access
];
};
};
};
# Sudo configuration
security.sudo = {
enable = true;
wheelNeedsPassword = false;
};
# Basic packages for system management
environment.systemPackages = with pkgs; [
git
vim
htop
curl
wget
];
# System version
system.stateVersion = "25.05";
}

View file

@ -224,6 +224,21 @@ Provides structured configuration handling:
(hostname . "sleeper-service.tail807ea.ts.net")
(ssh-alias . "admin-sleeper")
(services . (nfs zfs storage)))
(grey-area
(type . remote)
(hostname . "grey-area.tail807ea.ts.net")
(ssh-alias . "admin-grey")
(services . (ollama forgejo git)))
(reverse-proxy
(type . remote)
(hostname . "reverse-proxy.tail807ea.ts.net")
(ssh-alias . "admin-reverse")
(services . (nginx proxy ssl)))
(little-rascal
(type . remote)
(hostname . "little-rascal.tail807ea.ts.net")
(ssh-alias . "little-rascal")
(services . (development niri desktop ai-tools)))
;; Additional machines...
))))
```
@ -332,8 +347,12 @@ guile -c "(use-modules (lab core)) (display \"Lab package loaded successfully\\n
;; Update flake inputs
(update-flake '((dry-run . #f)))
;; Deploy to machine
(execute-nixos-rebuild "sleeper-service" "switch"
;; Deploy to development laptop
(execute-nixos-rebuild "little-rascal" "switch"
'((dry-run . #f)))
;; Deploy to storage server
(execute-nixos-rebuild "sleeper-service" "boot"
'((dry-run . #f))))
(display "Environment validation failed\n"))
```
@ -351,10 +370,13 @@ scheme@(guile-user)> (use-modules (lab core) (utils logging))
scheme@(guile-user)> (set-log-level! 'debug)
;; Check machine status interactively
scheme@(guile-user)> (get-infrastructure-status "congenital-optimist")
scheme@(guile-user)> (get-infrastructure-status "little-rascal")
;; Test health checks
scheme@(guile-user)> (check-system-health "grey-area")
;; Test health checks for development machine
scheme@(guile-user)> (check-system-health "little-rascal")
;; Test SSH connectivity to laptop
scheme@(guile-user)> (test-ssh-connection "little-rascal")
```

View file

@ -37,7 +37,12 @@
(type . remote)
(hostname . "reverse-proxy.tail807ea.ts.net")
(ssh-alias . "admin-reverse")
(services . (nginx proxy ssl)))))
(services . (nginx proxy ssl)))
(little-rascal
(type . remote)
(hostname . "little-rascal.tail807ea.ts.net")
(ssh-alias . "little-rascal")
(services . (development niri desktop ai-tools)))))
(deployment . ((default-mode . "boot")
(timeout . 300)
(retry-count . 3)))

162
scripts/deploy-little-rascal.sh Executable file
View file

@ -0,0 +1,162 @@
#!/usr/bin/env bash
# Little Rascal NixOS Installation and Deployment Script
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
LAPTOP_HOSTNAME="little-rascal"
LAPTOP_IP="little-rascal.tail807ea.ts.net" # Or use IP address
SSH_USER="geir"
FLAKE_PATH="/home/geir/Home-lab"
echo -e "${BLUE}=== Little Rascal NixOS Deployment Helper ===${NC}"
echo
# Function to print colored output
print_step() {
echo -e "${GREEN}[STEP]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
# Check if we're running from the Home-lab directory
if [ ! -f "flake.nix" ]; then
print_error "Please run this script from the Home-lab directory"
exit 1
fi
# Menu selection
echo "What would you like to do?"
echo "1. Generate hardware configuration (run this on the laptop after minimal install)"
echo "2. Test SSH connection to laptop"
echo "3. Deploy full configuration to laptop"
echo "4. Check deployment status"
echo "5. Show manual installation steps"
echo
read -p "Enter your choice (1-5): " choice
case $choice in
1)
print_step "Generating hardware configuration..."
echo "Run this command ON THE LAPTOP after minimal NixOS installation:"
echo
echo -e "${YELLOW}sudo nixos-generate-config --show-hardware-config > hardware-configuration.nix${NC}"
echo
echo "Then copy the hardware-configuration.nix to this machine at:"
echo " $FLAKE_PATH/machines/little-rascal/hardware-configuration.nix"
;;
2)
print_step "Testing SSH connection to laptop..."
if ssh -o ConnectTimeout=5 $SSH_USER@$LAPTOP_IP "echo 'SSH connection successful!'" 2>/dev/null; then
print_info "✅ SSH connection to $LAPTOP_IP successful!"
# Check if Tailscale is running
if ssh $SSH_USER@$LAPTOP_IP "systemctl is-active tailscale" 2>/dev/null | grep -q "active"; then
print_info "✅ Tailscale is running on laptop"
else
print_warning "⚠️ Tailscale might not be running on laptop"
fi
else
print_error "❌ Cannot connect to $LAPTOP_IP via SSH"
echo "Make sure:"
echo " - The laptop is connected to the network"
echo " - SSH is enabled and running"
echo " - Your SSH key is properly configured"
echo " - Tailscale is connected (if using .ts.net address)"
fi
;;
3)
print_step "Deploying full configuration to laptop..."
# First, test the configuration builds locally
print_info "Building configuration locally first..."
if nixos-rebuild build --flake .#little-rascal; then
print_info "✅ Configuration builds successfully"
else
print_error "❌ Configuration failed to build"
exit 1
fi
# Deploy using deploy-rs
print_info "Deploying to laptop via deploy-rs..."
if deploy .#little-rascal; then
print_info "✅ Deployment successful!"
else
print_error "❌ Deployment failed"
print_info "You can try manual deployment with:"
echo " nixos-rebuild switch --flake .#little-rascal --target-host $SSH_USER@$LAPTOP_IP --use-remote-sudo"
fi
;;
4)
print_step "Checking deployment status..."
print_info "Current system generation on laptop:"
ssh $SSH_USER@$LAPTOP_IP "sudo nixos-rebuild list-generations | tail -5"
print_info "Current running configuration:"
ssh $SSH_USER@$LAPTOP_IP "readlink /run/current-system"
;;
5)
print_step "Manual installation steps:"
echo
echo -e "${YELLOW}1. Boot from NixOS installer ISO${NC}"
echo "2. Set up disk partitioning (example for UEFI system):"
echo " sudo parted /dev/nvme0n1 mklabel gpt"
echo " sudo parted /dev/nvme0n1 mkpart ESP fat32 1MiB 512MiB"
echo " sudo parted /dev/nvme0n1 set 1 esp on"
echo " sudo parted /dev/nvme0n1 mkpart primary 512MiB 100%"
echo
echo "3. Format partitions:"
echo " sudo mkfs.fat -F 32 -n BOOT /dev/nvme0n1p1"
echo " sudo mkfs.ext4 -L nixos /dev/nvme0n1p2"
echo
echo "4. Mount filesystems:"
echo " sudo mount /dev/disk/by-label/nixos /mnt"
echo " sudo mkdir -p /mnt/boot"
echo " sudo mount /dev/disk/by-label/BOOT /mnt/boot"
echo
echo "5. Generate and edit configuration:"
echo " sudo nixos-generate-config --root /mnt"
echo " sudo nano /mnt/etc/nixos/configuration.nix"
echo " # Copy minimal-configuration.nix content and adjust disk UUIDs"
echo
echo "6. Install NixOS:"
echo " sudo nixos-install"
echo
echo "7. Set root password and reboot:"
echo " sudo nixos-enter --root /mnt"
echo " passwd"
echo " exit"
echo " reboot"
echo
echo -e "${YELLOW}8. After reboot, connect to Tailscale and run this script again with option 3${NC}"
;;
*)
print_error "Invalid choice"
exit 1
;;
esac
echo
print_info "Done!"