Objective: Enhance the KMI Kali Linux qcow2 image build to pre-install mise and lix/nix dependencies, eliminating cloud-init bootstrap overhead and enabling immediate nix develop capability on VM boot.
Rationale: Current cloud-init workflow performs expensive operations (mise install, nix install, git clone, trust operations) on every VM creation. Pre-baking these dependencies into the base image reduces VM bootstrap time from minutes to seconds.
Target Image: containercraft/kali:2025-3-dev
- Source:
kmi/images/kali-linux/env.sh: Build configuration (URLs, checksums, arch)virt.sysprep: Package installation and system configuration
- Build Tool:
kmi/hack/customize.sh(libguestfs + virt-sysprep) - CI/CD: CircleCI (
kmi/.circleci/config.yml)
# From kubevirt/kali-kalilix-userdata.yaml (lines 47-57)
- sudo -u kali bash -c 'curl https://mise.run | sh'
- sudo -u kali git clone https://github.com/usrbinkat/kalilix.git /home/kali/.kalilix
- sudo -u kali bash -c 'cd /home/kali/.kalilix && /home/kali/.local/bin/mise trust ...'
- sudo -u kali bash -c 'export PATH="/home/kali/.local/bin:$PATH" && cd /home/kali/.kalilix && mise run bootstrap'
- sudo -u kali bash -c 'cd /home/kali/.kalilix && source /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && nix develop .#full --command true'
- sudo -u kali bash -c 'echo "export PATH=\"\$HOME/.local/bin:\$PATH\"" >> /home/kali/.bashrc'
- sudo -u kali bash -c 'echo "[ -f /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ] && source /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh" >> /home/kali/.bashrc'Post-Boot Command (single step):
nix develop github:usrbinkat/kalilix#fullNo Prerequisites: VM boots with mise and nix pre-configured, ready for immediate flake development.
- Analyze KMI build pipeline architecture
- Review virt-sysprep capabilities and limitations
- Identify package dependencies for Debian-based Kali
- Design /etc/skel/.bashrc integration approach
- Validate mise installation method for offline/VM context
- Validate lix/nix multi-user installation in virt-sysprep
File: kmi/images/kali-linux/virt.sysprep
Action: Add required packages for mise installation
- Add
curlto package list (may already be present) - Add
ca-certificatesfor HTTPS downloads - Add
xz-utilsfor mise binary extraction (if needed) - Verify DNS configuration is set correctly (lines 7-8)
Changes Required:
# Line 11 - Update install command to include mise dependencies
install cloud-init,cloud-initramfs-growroot,openssh-server,qemu-guest-agent,python3,tmux,git,vim,btop,curl,ca-certificates,xz-utilsValidation:
- Confirm packages are available in Kali repos
- Test installation doesn't conflict with existing packages
File: kmi/images/kali-linux/virt.sysprep
Action: Add mise installation commands
- Download mise installer script
- Install mise for root user (for /etc/skel configuration)
- Verify mise binary is in expected location
- Set proper permissions on mise binary
Implementation Approach:
# Add after line 18 (after apt-get clean)
# Install mise for system-wide template
run-command curl -fsSL https://mise.run | MISE_INSTALL_PATH=/usr/local/bin sh
run-command chmod 755 /usr/local/bin/mise
# Alternative: Direct binary download (more reliable for offline builds)
run-command curl -fsSL https://github.com/jdx/mise/releases/latest/download/mise-latest-linux-x64 -o /usr/local/bin/mise
run-command chmod 755 /usr/local/bin/miseValidation Steps:
- Verify mise binary is executable
- Test
mise --versionworks in chroot context - Confirm mise is in system PATH
Notes:
- Using /usr/local/bin ensures mise is available system-wide
- virt-sysprep
run-commandexecutes in chroot context - Network access available via
--networkflag in virt-sysprep call (line 202-207 in customize.sh)
File: kmi/images/kali-linux/virt.sysprep
Action: Configure mise activation in default user shell profile
- Create or append to /etc/skel/.bashrc
- Add mise activation hook
- Add PATH configuration for mise-installed tools
- Ensure configuration is idempotent
Implementation:
# Add after mise installation
# Configure mise activation in /etc/skel/.bashrc for all new users
run-command mkdir -p /etc/skel
append-line /etc/skel/.bashrc:# Mise (polyglot runtime manager) initialization
append-line /etc/skel/.bashrc:# Auto-loads tools based on .mise.toml and .env files
append-line /etc/skel/.bashrc:export PATH="$HOME/.local/bin:$PATH"
append-line /etc/skel/.bashrc:if command -v mise >/dev/null 2>&1; then
append-line /etc/skel/.bashrc: eval "$(mise activate bash)"
append-line /etc/skel/.bashrc:fi
append-line /etc/skel/.bashrc:Alternative Approach (using write command):
# Using write command for multi-line content
write /etc/skel/.bashrc.mise:# Mise (polyglot runtime manager) initialization
append-line /etc/skel/.bashrc.mise:# Auto-loads tools based on .mise.toml and .env files
append-line /etc/skel/.bashrc.mise:export PATH="$HOME/.local/bin:$PATH"
append-line /etc/skel/.bashrc.mise:if command -v mise >/dev/null 2>&1; then
append-line /etc/skel/.bashrc.mise: eval "$(mise activate bash)"
append-line /etc/skel/.bashrc.mise:fi
run-command cat /etc/skel/.bashrc.mise >> /etc/skel/.bashrc
run-command rm /etc/skel/.bashrc.miseValidation:
- Verify /etc/skel/.bashrc exists and is readable
- Test configuration doesn't break default bash startup
- Confirm PATH modifications don't conflict
File: kmi/images/kali-linux/virt.sysprep
Action: Add packages required for Nix multi-user installation
- Add
sudo(may already be present) - Add
systemd(should already be present on Kali) - Add
bash(should already be present) - Verify no conflicts with existing package list
Required Packages (most likely already present):
# These are typically already installed on Kali, but verify:
sudo, systemd, bash, curl, xz-utils, ca-certificatesValidation:
- Confirm systemd is enabled and will start on boot
- Verify /etc/systemd/system directory exists
File: kmi/images/kali-linux/virt.sysprep
Action: Install Lix/Nix in multi-user mode with systemd service
- Download Lix installer
- Execute multi-user installation
- Enable nix-daemon.service for systemd
- Configure nix-daemon to start on boot
- Verify /nix directory structure is created
Implementation Strategy:
Option A: Direct Lix Installation (Preferred - Official Lix Installer)
# Install Lix (Nix fork) in multi-user mode
# The installer needs to run non-interactively
run-command curl -sSf -L https://install.lix.systems/lix | sh -s -- install --no-confirm
# Enable nix-daemon service
run-command systemctl enable nix-daemon.service
# Create /nix/var/nix/profiles/default/etc/profile.d directory if needed
run-command mkdir -p /nix/var/nix/profiles/default/etc/profile.dOption B: Standard Nix Multi-User Installation (Fallback)
# Install Nix in multi-user mode
run-command curl -L https://nixos.org/nix/install | sh -s -- --daemon --yes
# Enable nix-daemon service
run-command systemctl enable nix-daemon.serviceOption C: Manual Lix Installation (Most Control)
# Download Lix installer
run-command curl -sSf -L https://install.lix.systems/lix/lix-installer-x86_64-linux -o /tmp/lix-installer
run-command chmod +x /tmp/lix-installer
# Run installer in non-interactive mode
run-command /tmp/lix-installer install --no-confirm
# Clean up installer
run-command rm /tmp/lix-installer
# Enable systemd service
run-command systemctl enable nix-daemon.serviceValidation Steps:
- Verify /nix directory exists with proper ownership
- Confirm /nix/var/nix/daemon-socket/socket exists
- Check nix-daemon.service is enabled:
systemctl is-enabled nix-daemon - Verify /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh exists
- Test nix binary is in /nix/var/nix/profiles/default/bin/nix
Critical Considerations:
- virt-sysprep runs in chroot, so systemd isn't running during build
- Use
systemctl enablenotsystemctl start(activation happens on first boot) - Nix installer may require /run/systemd/system to exist
- May need to create build-time directories:
/run/systemd/system,/var/lib/systemd
Pre-requisites for Nix Installer:
# Create systemd directories if they don't exist
run-command mkdir -p /run/systemd/system
run-command mkdir -p /var/lib/systemdFile: kmi/images/kali-linux/virt.sysprep
Action: Configure Nix daemon profile sourcing in default user shell
- Append Nix initialization to /etc/skel/.bashrc
- Add conditional sourcing (only if nix-daemon.sh exists)
- Ensure configuration works with mise configuration
- Test order of operations (PATH, mise, nix)
Implementation:
# Add after mise configuration in /etc/skel/.bashrc
# Configure Nix daemon profile in /etc/skel/.bashrc for all new users
append-line /etc/skel/.bashrc:# Nix package manager initialization
append-line /etc/skel/.bashrc:# Source the multi-user Nix daemon profile
append-line /etc/skel/.bashrc:if [ -f /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then
append-line /etc/skel/.bashrc: source /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
append-line /etc/skel/.bashrc:fi
append-line /etc/skel/.bashrc:Complete /etc/skel/.bashrc Content:
# Mise (polyglot runtime manager) initialization
# Auto-loads tools based on .mise.toml and .env files
export PATH="$HOME/.local/bin:$PATH"
if command -v mise >/dev/null 2>&1; then
eval "$(mise activate bash)"
fi
# Nix package manager initialization
# Source the multi-user Nix daemon profile
if [ -f /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then
source /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
fiValidation:
- Verify proper shell initialization order
- Test PATH includes both mise and nix binaries
- Confirm no conflicts between mise and nix PATH entries
File: kmi/images/kali-linux/virt.sysprep
Action: Pre-configure kali user's home directory with Nix profile
Note: The kali user already exists in the Kali Linux image (default user with UID 1000)
- Verify kali user exists (should be default in Kali image)
- Copy /etc/skel/.bashrc to /home/kali/.bashrc if needed
- Set proper ownership on /home/kali/.bashrc
- Create /home/kali/.local/bin directory
- Set proper permissions on kali home directory
Implementation:
# The kali user should already exist in Kali Linux
# Ensure .bashrc is configured (it may already be via /etc/skel)
run-command cp -n /etc/skel/.bashrc /home/kali/.bashrc || true
run-command chown kali:kali /home/kali/.bashrc
run-command chmod 644 /home/kali/.bashrc
# Create .local/bin directory for kali user
run-command mkdir -p /home/kali/.local/bin
run-command chown -R kali:kali /home/kali/.local
run-command chmod 755 /home/kali/.local /home/kali/.local/binValidation:
- Verify /home/kali exists
- Confirm /home/kali/.bashrc has correct ownership
- Check /home/kali/.local/bin directory exists and is in PATH
File: kmi/images/kali-linux/env.sh
Action: Verify VIRT_SYSPREP_OPERATIONS setting
Current Setting (line 9):
VIRT_SYSPREP_OPERATIONS=logfiles,bash-history,tmp-files,customizeAnalysis:
customizeoperation: REQUIRED - enables our virt.sysprep scriptlogfiles: Cleans log files (safe to keep)bash-history: Cleans bash history (safe to keep)tmp-files: Cleans temporary files (safe to keep)- Does NOT include
user-accountoperation (good - preserves kali user)
Action:
- Confirm current operations are appropriate
- Verify
customizeoperation is present (REQUIRED) - No changes needed unless testing reveals issues
File: kmi/hack/customize.sh
Action: Verify virt-sysprep has network access for downloads
Current Configuration (line 202-207):
# Customize Disk Image
sudo virt-sysprep \
--verbose \
--network \ # <-- ALREADY ENABLED
--add "${QCOW2_TMPFILE}" \
--commands-from-file images/"${FLAVOR}"/virt.sysprep \
--enable "${VIRT_SYSPREP_OPERATIONS}"Validation:
-
--networkflag is present (enables curl downloads) - Test DNS resolution works in virt-sysprep context
- Confirm no proxy configuration needed
File: kmi/hack/customize.sh
Action: Ensure sufficient disk space for Nix installation
Current Setting (line 189):
# Grow disk size
qemu-img resize "${QCOW2_TMPFILE}" +20GAnalysis:
- Nix installation requires ~2-5GB for base system
- Base Kali image is already sized for OS + tools
- +20G should be sufficient for Nix + mise
- Could increase to +30G for safety
Recommendation:
- Keep current +20G (monitor during testing)
- Consider increasing to +30G if Nix store grows large
- Validate final image size doesn't exceed 64Gi limit
Optional Change:
# Grow disk size (increased for Nix store)
qemu-img resize "${QCOW2_TMPFILE}" +30GFile: kmi/.circleci/config.yml
Action: Verify CI/CD pipeline handles increased build requirements
Current Configuration (lines 420-443):
# Start Kali Linux #
- customize:
name: customize-<< matrix.flavor >>-<< matrix.arch >>
matrix:
parameters:
flavor: *_kali-flavors
arch: [amd64]
- cradle:
requires:
- customize-<< matrix.flavor >>-amd64
name: cradle-<< matrix.flavor >>
matrix:
parameters:
flavor: *_kali-flavors
- trigger-tests:
requires:
- cradle-<< matrix.flavor >>
name: trigger-<< matrix.flavor >>-promotion
matrix:
parameters:
flavor: *_kali-flavors
# End Kali Linux #Current Resource Class (lines 710-718):
# AMD64 Runner
amd64:
machine:
enabled: true
image: ubuntu-2204:2025.09.1
environment:
DOCKER_CLI_EXPERIMENTAL: enabled
resource_class: xlarge # 8 vCPUs, 32GB RAMAnalysis:
- Current: xlarge (8 vCPU, 32GB RAM)
- Nix installation may require more time, not necessarily more resources
- Network downloads may increase build time
- Caching should help with rebuild times
Action:
- Monitor first CI/CD build time with Nix installation
- Evaluate if timeout needs adjustment (line 616: 90m no_output_timeout)
- Consider if resource class upgrade needed (unlikely)
Potential Optimization:
- Add CircleCI cache key for Nix installation artifacts (if slow)
- Consider pre-downloading Lix installer in cache step
Location: Development machine with KMI repository
Prerequisites:
- libguestfs-tools installed (
apt install guestfs-tools) - qemu-img available
- Sufficient disk space (~100GB for build artifacts)
- Network connectivity for downloads
Test Steps:
Step 5.1.1: Clean Local Build
cd kmi/
FLAVOR=kali-linux ARCH=amd64 bash hack/customize.shValidation Checkpoints:
- Build completes without errors
- mise installation succeeds (check logs for "mise")
- Nix installation succeeds (check logs for "nix")
- DNS resolution works (no curl failures)
- Final qcow2 file is created:
kali-linux-amd64.qcow2 - File size is reasonable (check if < 64Gi)
Step 5.1.2: Inspect Built Image
# Mount image and inspect
sudo virt-inspector -a kali-linux-amd64.qcow2
# Check if mise is installed
sudo virt-cat -a kali-linux-amd64.qcow2 /usr/local/bin/mise > /dev/null && echo "mise: OK"
# Check if nix is installed
sudo virt-cat -a kali-linux-amd64.qcow2 /nix/var/nix/profiles/default/bin/nix > /dev/null && echo "nix: OK"
# Check /etc/skel/.bashrc configuration
sudo virt-cat -a kali-linux-amd64.qcow2 /etc/skel/.bashrc | grep -E "(mise|nix)"
# Check kali user .bashrc
sudo virt-cat -a kali-linux-amd64.qcow2 /home/kali/.bashrc | grep -E "(mise|nix)"
# Check nix-daemon.service is enabled
sudo virt-cat -a kali-linux-amd64.qcow2 /etc/systemd/system/multi-user.target.wants/nix-daemon.service > /dev/null && echo "nix-daemon enabled: OK"Validation Checklist:
- /usr/local/bin/mise exists and is executable
- /nix/var/nix/profiles/default/bin/nix exists
- /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh exists
- /etc/skel/.bashrc contains mise activation
- /etc/skel/.bashrc contains nix sourcing
- /home/kali/.bashrc is configured correctly
- nix-daemon.service is enabled
- /nix directory structure exists with proper ownership
Location: Development machine with KVM/QEMU
Prerequisites:
- libvirt and qemu-kvm installed
- Network bridge configured (or use default NAT)
- Built kali-linux-amd64.qcow2 from Task 5.1
Test Steps:
Step 5.2.1: Create Test VM
# Copy image to libvirt images directory
sudo cp kali-linux-amd64.qcow2 /var/lib/libvirt/images/kali-test.qcow2
# Create VM using virt-install (no cloud-init)
sudo virt-install \
--name kali-test \
--ram 4096 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/kali-test.qcow2,bus=virtio \
--network network=default \
--graphics vnc \
--import \
--os-variant debian11 \
--noautoconsoleStep 5.2.2: Boot and Console Access
# Connect to VM console
sudo virsh console kali-test
# Or use VNC
virt-viewer kali-testStep 5.2.3: Login and Validation
# Login as kali user (default password: kali)
# After login, verify shell initialization
# Test 1: Check mise is available
mise --version
# Test 2: Check nix is available
nix --version
# Test 3: Check nix daemon is running
systemctl status nix-daemon
# Test 4: Check PATH includes mise and nix
echo $PATH | grep -E "(mise|nix)"
# Test 5: Verify .bashrc was sourced
type mise
type nix
# Test 6: Test nix flake command (THE ULTIMATE TEST)
nix flake show github:usrbinkat/kalilix
# Test 7: Enter nix development shell
nix develop github:usrbinkat/kalilix#full --command bash -c "echo 'Success: Nix shell works!'"Validation Checklist:
- VM boots successfully
- Login works (kali/kali)
- mise command is available
- nix command is available
- nix-daemon.service is running
- PATH includes /nix/var/nix/profiles/default/bin
-
nix flake showworks without errors -
nix develop github:usrbinkat/kalilix#fullworks - No cloud-init required for any of the above
Step 5.2.4: Performance Baseline
# Time the nix develop command (should be faster than cloud-init approach)
time nix develop github:usrbinkat/kalilix#full --command bash -c "echo 'Success'"
# Expected: < 30 seconds for first run (with network fetch)
# Expected: < 5 seconds for subsequent runs (cached)Cleanup:
sudo virsh destroy kali-test
sudo virsh undefine kali-test
sudo rm /var/lib/libvirt/images/kali-test.qcow2Location: Kubernetes cluster with KubeVirt
Prerequisites:
- KubeVirt cluster accessible
- kubectl configured
- Updated kali-linux image pushed to container registry (or use local build)
- SSH public key secret exists:
kargo-sshpubkey-kali
Test Steps:
Step 5.3.1: Build and Push Test Image
# After local testing passes, build OCI container image
cd kmi/
docker buildx bake kali-linux --load
# Tag with test label
docker tag containercraft/kali:latest containercraft/kali:2025-3-test
# Push to registry (or use local registry for testing)
docker push containercraft/kali:2025-3-testStep 5.3.2: Update Test Manifest
# Create test version of kubevirt manifest
cp kubevirt/kali-2025-3-golden-image.yaml kubevirt/kali-2025-3-golden-image-test.yaml
# Update image reference to test version
sed -i 's|containercraft/kali:2025-3-dev|containercraft/kali:2025-3-test|g' kubevirt/kali-2025-3-golden-image-test.yamlStep 5.3.3: Deploy Test Golden Image
# Deploy golden image
kubectl apply -f kubevirt/kali-2025-3-golden-image-test.yaml
# Monitor import progress
kubectl get dv kali-2025-3-golden-image -w
# Wait for completion
kubectl wait --for=condition=Ready dv/kali-2025-3-golden-image --timeout=30mStep 5.3.4: Create Minimal Test Cloud-Init
Create kubevirt/kali-test-userdata.yaml:
#cloud-config
hostname: kalilix-test
fqdn: kalilix-test.home.arpa
ssh_pwauth: true
disable_root: false
chpasswd:
list: |
root:kc2admin
kali:kali
expire: False
users:
- default
- name: kali
gecos: Kalilix Test User
shell: /bin/bash
lock_passwd: false
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
groups: adm,cdrom,dip,sudo,docker
growpart:
mode: auto
devices: ["/"]
ignore_growroot_disabled: true
timezone: UTC
# CRITICAL: No mise or nix installation - testing pre-baked dependencies
runcmd:
# Only test commands - no installation
- mise --version
- nix --version
- systemctl status nix-daemon
- nix flake show github:usrbinkat/kalilix
- echo "$(date) - Test complete: mise and nix pre-installed" > /home/kali/test-complete
- chown kali:kali /home/kali/test-completeStep 5.3.5: Create Test Secret
kubectl create secret generic kali-test-userdata \
--from-file=userdata=kubevirt/kali-test-userdata.yaml \
--namespace=default \
--dry-run=client -o yaml | kubectl apply -f -Step 5.3.6: Deploy Test VM
Update kubevirt/kali-kalilix-flake-minimal.yaml to use test userdata:
# Create test VM manifest
cp kubevirt/kali-kalilix-flake-minimal.yaml kubevirt/kali-kalilix-flake-minimal-test.yaml
# Update to use test userdata
sed -i 's|kali-kalilix-userdata|kali-test-userdata|g' kubevirt/kali-kalilix-flake-minimal-test.yaml
# Deploy test VM
kubectl apply -f kubevirt/kali-kalilix-flake-minimal-test.yamlStep 5.3.7: Monitor VM Creation
# Watch VM creation
kubectl get vm,vmi,dv,pvc -l app=kalilix-kali -w
# Check events
kubectl get events --sort-by='.lastTimestamp' | grep kalilix
# Monitor cloud-init progress
kubectl get vmi kalilix-kali -o jsonpath='{.status.phase}'Step 5.3.8: Validation
# Get VM IP
VM_IP=$(kubectl get vmi kalilix-kali -o jsonpath='{.status.interfaces[0].ipAddress}')
echo "VM IP: $VM_IP"
# Wait for cloud-init to complete
ssh kali@$VM_IP 'cloud-init status --wait'
# Check test results
ssh kali@$VM_IP 'cat /home/kali/test-complete'
# Verify mise and nix
ssh kali@$VM_IP 'mise --version'
ssh kali@$VM_IP 'nix --version'
# Check nix daemon
ssh kali@$VM_IP 'systemctl status nix-daemon'
# Test nix develop command
ssh kali@$VM_IP 'nix develop github:usrbinkat/kalilix#full --command bash -c "echo Success"'
# Check cloud-init logs for any errors
ssh kali@$VM_IP 'cat /var/log/cloud-init-output.log' | grep -i errorValidation Checklist:
- Golden image import completes successfully
- VM clone from golden image succeeds
- VM boots and becomes Running
- Cloud-init completes without errors
- mise command works immediately (no installation in cloud-init)
- nix command works immediately (no installation in cloud-init)
- nix-daemon is running
-
nix developworks for remote flake - Bootstrap time is significantly reduced (< 2 minutes vs 10+ minutes)
- No git clone or mise trust commands needed in cloud-init
Performance Comparison:
# Old approach (from cloud-init-output.log):
# Expected: 10-15 minutes (mise install + nix install + bootstrap)
# New approach:
# Expected: < 2 minutes (cloud-init + nix develop cache)Cleanup:
kubectl delete vm kalilix-kali
kubectl delete dv kalilix-kali-root kali-2025-3-golden-image
kubectl delete secret kali-test-userdataLocation: CircleCI (triggered by git push)
Prerequisites:
- All local testing passes (Tasks 5.1-5.3)
- Changes committed to feature branch
- CircleCI configured for repository
Test Steps:
Step 5.4.1: Push to Feature Branch
git checkout -b feat/kali-mise-nix-prebake
git add kmi/images/kali-linux/virt.sysprep
git add kmi/images/kali-linux/env.sh # if modified
git add TASKS.kmi-kali-linux-qcow2-mise-and-lix-nix-dependencies-enhancement-task-checkbox-project-design-implementation-living-document.md
git commit -m "feat(kmi): prebake mise and nix into kali linux image
- Install mise via direct binary download in virt-sysprep
- Install lix/nix multi-user with systemd daemon
- Configure /etc/skel/.bashrc with mise and nix initialization
- Configure kali user home directory
- Enable nix-daemon.service for boot
This eliminates cloud-init bootstrap overhead and enables immediate
nix develop capability on VM boot.
Refs: TASKS.kmi-kali-linux-qcow2-mise-and-lix-nix-dependencies-enhancement-task-checkbox-project-design-implementation-living-document.md"
git push origin feat/kali-mise-nix-prebakeStep 5.4.2: Monitor CircleCI Build
# Open CircleCI dashboard
# Watch build progress for kali-linux flavor
# Monitor these jobs:
# 1. customize-kali-linux-amd64 (virt-sysprep execution)
# 2. cradle-kali-linux (OCI image creation)
# 3. trigger-kali-linux-promotion (test trigger)Validation Checkpoints:
- customize-kali-linux-amd64 job succeeds
- mise installation logs show success
- nix installation logs show success
- No network timeout errors
- No DNS resolution errors
- qcow2 artifact is created and cached
- cradle-kali-linux job succeeds
- OCI image is pushed to registry
- Total build time is within acceptable range (< 90 minutes)
Step 5.4.3: Check Build Artifacts
# Download built image from CircleCI artifacts (if available)
# Or pull from registry
docker pull containercraft/kali:latest
# Inspect image
docker run --rm -it containercraft/kali:latest bash -c "mise --version && nix --version"Location: GitHub Actions (triggered by CircleCI)
Prerequisites:
- CircleCI build completes successfully
- GHA test workflow is triggered
Validation:
- GitHub Actions test workflow starts
- kind cluster is created
- KubeVirt is installed
- Test VM is deployed using new image
- VM boots successfully
- Tests pass (SSH connectivity, guest agent, etc.)
Monitoring:
# Monitor GHA workflow via GitHub UI
# Or use gh CLI
gh run list --workflow=test.yml
gh run view <run-id> --logValidation Checklist:
- GHA workflow triggered by CircleCI
- Test VM deploys successfully
- SSH test passes
- Guest agent test passes
- Custom test for mise/nix availability passes (if added)
Location: GitHub repository
Prerequisites:
- All testing phases complete successfully (5.1-5.5)
- No regressions observed
- Performance improvements confirmed
PR Checklist:
- Create PR from feature branch to main
- Title:
feat(kmi): prebake mise and nix into kali linux image - Description includes:
- Summary of changes
- Performance improvements
- Testing results
- Link to TASKS document
- Before/after comparison (cloud-init time)
- Request review from maintainers
- Link to successful CI/CD builds
- Update any relevant documentation
PR Description Template:
## Summary
Pre-install mise and lix/nix dependencies into the Kali Linux KMI image, eliminating cloud-init bootstrap overhead.
## Changes
- Install mise via direct binary download in virt-sysprep
- Install lix/nix multi-user with systemd daemon
- Configure /etc/skel/.bashrc with mise and nix initialization
- Configure kali user home directory with proper shell initialization
- Enable nix-daemon.service for automatic startup on boot
## Performance Improvements
- VM bootstrap time: **10-15 minutes → < 2 minutes** (85% reduction)
- Immediate `nix develop` capability without cloud-init
- No git clone or mise trust operations needed
- Faster development environment activation
## Testing
- ✅ Local build testing (virt-sysprep)
- ✅ Local VM boot testing (libvirt)
- ✅ KubeVirt deployment testing
- ✅ CircleCI build validation
- ✅ GitHub Actions test validation
## Breaking Changes
None. This is backwards compatible. VMs can still use cloud-init for additional configuration.
## Documentation
See: `TASKS.kmi-kali-linux-qcow2-mise-and-lix-nix-dependencies-enhancement-task-checkbox-project-design-implementation-living-document.md`
## Related Issues
Refs: usrbinkat/kalilix cloud-init optimizationLocation: Main branch
Prerequisites:
- PR approved by maintainers
- All CI/CD checks pass
- No merge conflicts
Actions:
- Merge PR to main branch
- Monitor production CircleCI build
- Verify production image is pushed to registry
- Validate production image tags:
containercraft/kali:latestcontainercraft/kali:2025-3containercraft/kali:2025-3-dev(if dev tag is used)
Production Validation:
# Pull production image
docker pull containercraft/kali:latest
# Verify mise and nix are present
docker run --rm containercraft/kali:latest bash -c "mise --version && nix --version && systemctl is-enabled nix-daemon"Location: usrbinkat/kalilix repository
Prerequisites:
- Production KMI image available
- New image tested and validated
Actions:
- Update
kubevirt/kali-kalilix-userdata.yaml - Remove mise installation commands
- Remove nix installation commands
- Remove mise trust commands
- Remove .bashrc configuration commands
- Keep only essential cloud-init commands:
- Package updates
- Docker setup
- MOTD
- Test command:
nix develop github:usrbinkat/kalilix#full
Simplified Cloud-Init Example:
#cloud-config
hostname: kalilix-kali
fqdn: kalilix-kali.home.arpa
ssh_pwauth: true
disable_root: false
chpasswd:
list: |
root:kc2admin
kali:kali
expire: False
users:
- default
- name: kali
gecos: Kalilix Development User
shell: /bin/bash
lock_passwd: false
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
groups: adm,cdrom,dip,sudo,docker
growpart:
mode: auto
devices: ["/"]
ignore_growroot_disabled: true
timezone: UTC
package_update: true
package_upgrade: true
package_reboot_if_required: true
packages:
- vim
- git
- curl
- jq
- build-essential
- qemu-guest-agent
- docker.io
- docker-compose
runcmd:
- chown -R kali:kali /home/kali
- chmod 700 /home/kali/.ssh
- chmod 600 /home/kali/.ssh/authorized_keys
- chown kali:kali /home/kali/.ssh/authorized_keys
- systemctl enable --now qemu-guest-agent
- sleep 4
- systemctl restart qemu-guest-agent
- systemctl enable --now docker
- systemctl restart docker
- usermod -aG docker kali
# Test mise and nix are available (no installation needed!)
- sudo -u kali mise --version
- sudo -u kali nix --version
# Pre-build the full development environment
- sudo -u kali bash -c 'nix develop github:usrbinkat/kalilix#full --command true'
- |
cat > /etc/motd <<'EOF'
╔═══════════════════════════════════════════════════════════╗
║ ║
║ Kalilix Development Environment ║
║ Kali Linux 2025.3 with Lix/Nix Flakes ║
║ ║
║ User: kali ║
║ Kalilix: ~/.kalilix/ ║
║ ║
║ Quick Start: ║
║ nix develop github:usrbinkat/kalilix#full ║
║ nix develop github:usrbinkat/kalilix#python ║
║ ║
╚═══════════════════════════════════════════════════════════╝
EOF
- echo "$(date) - Kalilix ready - mise and nix pre-installed" > /home/kali/kalilix-ready
- chown kali:kali /home/kali/kalilix-ready
final_message: "Kalilix development environment ready on Kali Linux after $UPTIME seconds"Lines Removed (from original):
- Lines 47-57: mise install, trust, bootstrap commands
- Lines 56-57: .bashrc configuration (now in image)
Lines Added:
- Lines 47-48: Test mise/nix availability
- Line 49: Pre-build flake environment
Validation:
- Cloud-init is significantly shorter
- No installation commands for mise or nix
- Test commands verify pre-installed tools
- nix develop command pre-builds environment
Location: Production Kubernetes cluster
Prerequisites:
- Production KMI image available:
containercraft/kali:latest - Updated kalilix manifests committed
- Golden image updated to production tag
Actions:
- Update golden image reference if needed
- Deploy updated golden image
- Deploy test VM with simplified cloud-init
- Validate performance improvements
- Monitor for issues
Deployment Commands:
# Update golden image to use production tag
kubectl delete dv kali-2025-3-golden-image # if exists
kubectl apply -f kubevirt/kali-2025-3-golden-image.yaml
# Wait for import
kubectl wait --for=condition=Ready dv/kali-2025-3-golden-image --timeout=30m
# Deploy production VM
kubectl apply -k kubevirt/
# Monitor
kubectl get vm,vmi,dv,pvc -l app=kalilix-kali -wProduction Validation:
- VM boots in < 2 minutes
- Cloud-init completes without errors
- mise is immediately available
- nix is immediately available
- nix-daemon is running
-
nix develop github:usrbinkat/kalilix#fullworks - Performance improvements confirmed
Files to Update:
7.1.1: KMI README.md
- Add note about pre-installed mise and nix in Kali image
- Update "Available Images" table with new features
- Add performance notes for Kali image
7.1.2: Kalilix README.md
- Update quick start instructions
- Note that mise and nix are pre-installed in KubeVirt deployments
- Update bootstrap time estimates
- Simplify installation instructions for KubeVirt
7.1.3: KubeVirt Deployment Comments
- Update
kubevirt/kustomization.yamlcomments - Update
kubevirt/kali-2025-3-golden-image.yamlcomments - Update
kubevirt/kali-kalilix-flake-minimal.yamlcomments - Add notes about pre-installed dependencies
Document Performance Improvements:
Before Enhancement:
Cloud-Init Bootstrap Time: 10-15 minutes
Steps:
1. Boot VM (30s)
2. Install mise (60s)
3. Install nix (120s)
4. Git clone kalilix (30s)
5. Mise trust operations (30s)
6. Mise run bootstrap (180s)
7. Nix develop (240s)
Total: ~12 minutes
After Enhancement:
Cloud-Init Bootstrap Time: < 2 minutes
Steps:
1. Boot VM (30s)
2. Nix develop pre-build (60s)
3. Ready (30s)
Total: < 2 minutes
Improvement: 85% reduction in bootstrap time
Metrics to Track:
- Image build time (CI/CD)
- Image size increase (acceptable overhead)
- VM boot time
- Cloud-init completion time
- Time to
nix developready state - User feedback/adoption
Final Steps:
- Mark all tasks as complete
- Archive TASKS document to project docs
- Create GitHub issue/discussion for community feedback
- Update changelog with enhancement
- Tag release if appropriate (e.g.,
v1.x.0)
Risk: Nix multi-user installer may fail in chroot environment without running systemd
Likelihood: Medium Impact: High (blocks entire enhancement)
Mitigation:
- Test nix installer early in local build (Task 5.1)
- Have fallback to manual nix installation
- Create systemd directories before installation
- Use
--no-confirmflag for non-interactive install - Fallback: Use single-user nix if multi-user fails
Contingency:
# If multi-user fails, use single-user installation
run-command curl -L https://nixos.org/nix/install | sh -s -- --no-daemonRisk: DNS resolution or network access may fail during build
Likelihood: Low Impact: High (no downloads possible)
Mitigation:
- Verified
--networkflag is present in customize.sh - DNS resolution configured in virt.sysprep (lines 7-8)
- Test network access early in local build
- Use fallback DNS (1.1.1.1, 8.8.8.8)
Contingency:
- Pre-download mise and nix installers
- Include binaries in repository or CDN
- Use offline installation method
Risk: Adding Nix store increases image size beyond acceptable limits
Likelihood: Medium Impact: Medium (slower downloads, storage costs)
Mitigation:
- Monitor image size during local testing
- Use
virt-sparsify(already in customize.sh) - Only install base nix, not full environment
- Increased disk resize from +20G to +30G
- Consider nix garbage collection in build
Acceptable Limits:
- Base image: ~5.6GB (current)
- With mise + nix: < 10GB (acceptable)
- Compressed in registry: < 5GB (target)
Risk: /etc/skel/.bashrc modifications may not apply to existing kali user
Likelihood: Low Impact: Low (kali user won't have config)
Mitigation:
- Explicitly copy /etc/skel/.bashrc to /home/kali/ (Task 3.4)
- Set proper ownership and permissions
- Test both new user creation and existing user
Risk: nix-daemon.service may not start on boot
Likelihood: Low Impact: High (nix commands fail)
Mitigation:
- Use
systemctl enable(notstart) in virt-sysprep - Validate service is enabled after build (Task 5.1.2)
- Add verification command in cloud-init as safety net
Contingency Cloud-Init:
runcmd:
- systemctl is-enabled nix-daemon || systemctl enable nix-daemon
- systemctl is-active nix-daemon || systemctl start nix-daemonRisk: Build time increases beyond CircleCI timeout limits
Likelihood: Low Impact: Medium (build fails, need to retry or adjust)
Mitigation:
- Current timeout: 90 minutes (adequate)
- Mise install: < 30 seconds
- Nix install: < 5 minutes
- Total increase: < 10 minutes
- Monitor first CI/CD build closely
Contingency:
- Increase timeout to 120 minutes if needed
- Cache mise and nix binaries in CircleCI cache
- Upgrade resource class if build is CPU-bound
- Mise is installed and available in PATH
- Nix is installed (multi-user mode)
- nix-daemon.service is enabled and starts on boot
- /etc/skel/.bashrc configures mise and nix
- /home/kali/.bashrc inherits configuration
- VM boots without cloud-init installation steps
-
nix develop github:usrbinkat/kalilix#fullworks immediately
- Image build completes successfully in CI/CD
- Image size increase < 100% (target: < 5GB increase)
- VM boot time < 2 minutes (vs 10-15 minutes previously)
- Cloud-init simplified (removed ~10 commands)
- No regressions in existing functionality
- All tests pass (local, KubeVirt, CI/CD, GHA)
- Documentation updated
- Code review approved
-
Pre-build Nix Flake Environments
- Pre-cache common flake outputs in image
- Reduces first
nix developtime - Trade-off: Larger image size
-
Mise Tool Pre-installation
- Pre-install common mise tools (python, node, etc.)
- Configure mise.toml in image
- Faster project setup
-
Extend to Other Distros
- Apply same pattern to Ubuntu, Debian, Fedora images
- Standardize mise + nix across all KMI images
- Consistent developer experience
-
Binary Cache Configuration
- Configure cachix or custom binary cache in image
- Faster nix package downloads
- Reduced build times
- Add image size tracking to CI/CD
- Monitor build time trends
- Track VM boot time metrics
- User feedback collection
- Mise Documentation
- Lix Installation Guide
- Nix Multi-User Installation
- virt-sysprep Manual
- libguestfs Recipes
kmi/images/kali-linux/virt.sysprepkmi/images/kali-linux/env.shkmi/hack/customize.shkmi/.circleci/config.ymlkubevirt/kali-kalilix-userdata.yamlkubevirt/kali-2025-3-golden-image.yamlkubevirt/kali-kalilix-flake-minimal.yaml
# Build local image
FLAVOR=kali-linux ARCH=amd64 bash hack/customize.sh
# Inspect built image
sudo virt-inspector -a kali-linux-amd64.qcow2
sudo virt-cat -a kali-linux-amd64.qcow2 /etc/skel/.bashrc
# Test in libvirt
sudo virt-install --name kali-test --import ...
# Deploy to KubeVirt
kubectl apply -f kubevirt/kali-2025-3-golden-image.yaml
kubectl wait --for=condition=Ready dv/kali-2025-3-golden-image
kubectl apply -k kubevirt/
# Build and push OCI image
docker buildx bake kali-linux --push- Created comprehensive task document
- Defined 7 phases with detailed sub-tasks
- Identified risks and mitigation strategies
- Established success criteria
- Begin Phase 2: Mise installation integration
- All phases complete
- Production deployment successful
Total Tasks: TBD (count after finalization) Completed: 6 (Phase 1) In Progress: 0 Remaining: TBD
Estimated Effort: 16-24 hours (1-3 days) Estimated Timeline: 1 week (with testing and validation)
Document Status: DRAFT - Ready for Implementation Last Updated: 2025-01-10 Owner: Kalilix Development Team Reviewers: TBD