wip
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,3 +5,6 @@ result-*
|
||||
# Ignore automatically generated direnv output
|
||||
.direnv
|
||||
|
||||
# Ignore generated seed ISOs
|
||||
*.iso
|
||||
|
||||
|
||||
69
.gitlab-ci.yml
Normal file
69
.gitlab-ci.yml
Normal file
@@ -0,0 +1,69 @@
|
||||
stages:
|
||||
- build
|
||||
- upload
|
||||
- release
|
||||
|
||||
build-x86_64:
|
||||
stage: build
|
||||
image: ubuntu:24.04
|
||||
script:
|
||||
- apt-get update && apt-get install -y curl xz-utils sudo
|
||||
- curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux --no-confirm
|
||||
- . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
- nix build .#nixosConfigurations.sandbox.config.system.build.image --out-link result-x86_64
|
||||
- cp $(find -L result-x86_64 -name '*.qcow2') sandbox-x86_64.qcow2
|
||||
artifacts:
|
||||
paths:
|
||||
- sandbox-x86_64.qcow2
|
||||
expire_in: 1 week
|
||||
|
||||
build-aarch64:
|
||||
stage: build
|
||||
image: ubuntu:24.04
|
||||
tags:
|
||||
- aarch64
|
||||
allow_failure: true
|
||||
script:
|
||||
- apt-get update && apt-get install -y curl xz-utils sudo
|
||||
- curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux --no-confirm
|
||||
- . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
- nix build .#nixosConfigurations.sandbox-aarch64.config.system.build.image --out-link result-aarch64
|
||||
- cp $(find -L result-aarch64 -name '*.qcow2') sandbox-aarch64.qcow2
|
||||
artifacts:
|
||||
paths:
|
||||
- sandbox-aarch64.qcow2
|
||||
expire_in: 1 week
|
||||
|
||||
upload:
|
||||
stage: upload
|
||||
image: curlimages/curl:latest
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG
|
||||
script:
|
||||
- |
|
||||
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" \
|
||||
--upload-file sandbox-x86_64.qcow2 \
|
||||
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/sandbox/${CI_COMMIT_TAG}/sandbox-x86_64.qcow2"
|
||||
- |
|
||||
if [ -f sandbox-aarch64.qcow2 ]; then
|
||||
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" \
|
||||
--upload-file sandbox-aarch64.qcow2 \
|
||||
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/sandbox/${CI_COMMIT_TAG}/sandbox-aarch64.qcow2"
|
||||
fi
|
||||
|
||||
release:
|
||||
stage: release
|
||||
image: registry.gitlab.com/gitlab-org/release-cli:latest
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG
|
||||
script:
|
||||
- echo "Creating release $CI_COMMIT_TAG"
|
||||
release:
|
||||
tag_name: $CI_COMMIT_TAG
|
||||
description: "Sandbox VM $CI_COMMIT_TAG"
|
||||
assets:
|
||||
links:
|
||||
- name: sandbox-x86_64.qcow2
|
||||
url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/sandbox/${CI_COMMIT_TAG}/sandbox-x86_64.qcow2"
|
||||
- name: sandbox-aarch64.qcow2
|
||||
url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/sandbox/${CI_COMMIT_TAG}/sandbox-aarch64.qcow2"
|
||||
39
dist/make-seed.sh
vendored
Executable file
39
dist/make-seed.sh
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
echo "Usage: make-seed.sh <pubkey-file> [output.iso]"
|
||||
echo "Creates a seed ISO with the given SSH public key."
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ "${1:-}" ] || usage
|
||||
|
||||
PUBKEY_FILE="$1"
|
||||
OUTPUT="${2:-seed.iso}"
|
||||
|
||||
if [ ! -f "$PUBKEY_FILE" ]; then
|
||||
echo "error: public key file not found: $PUBKEY_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TMPDIR=$(mktemp -d)
|
||||
trap 'rm -rf "$TMPDIR"' EXIT
|
||||
|
||||
cp "$PUBKEY_FILE" "$TMPDIR/authorized_keys"
|
||||
|
||||
if command -v mkisofs >/dev/null 2>&1; then
|
||||
ISO_CMD="mkisofs"
|
||||
elif command -v genisoimage >/dev/null 2>&1; then
|
||||
ISO_CMD="genisoimage"
|
||||
else
|
||||
echo "error: mkisofs or genisoimage required"
|
||||
echo " linux: sudo apt install genisoimage"
|
||||
echo " macos: brew install cdrtools"
|
||||
echo " nix: nix shell nixpkgs#cdrtools"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$ISO_CMD" -quiet -V SEEDCONFIG -J -R -o "$OUTPUT" "$TMPDIR"
|
||||
|
||||
echo "seed ISO created: $OUTPUT"
|
||||
182
dist/run.sh
vendored
Executable file
182
dist/run.sh
vendored
Executable file
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# defaults
|
||||
SSH_PORT=2222
|
||||
MEMORY=8G
|
||||
CPUS=4
|
||||
PROJECTS=""
|
||||
CLAUDE_DIR=""
|
||||
SSH_KEY=""
|
||||
SEED_ISO=""
|
||||
IMAGE=""
|
||||
GUEST_ARCH=""
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: run.sh <image.qcow2> [options]
|
||||
|
||||
Options:
|
||||
--arch <arch> Guest architecture (auto-detected from image name)
|
||||
--ssh-key <key.pub> SSH public key (auto-generates seed ISO)
|
||||
--seed-iso <iso> Pre-built seed ISO (alternative to --ssh-key)
|
||||
--projects <path> Mount host directory as ~/projects in VM
|
||||
--claude-dir <path> Mount host .claude directory for auth
|
||||
--memory <size> VM memory (default: 8G)
|
||||
--cpus <n> VM CPUs (default: 4)
|
||||
--ssh-port <port> SSH port forward (default: 2222)
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ "${1:-}" ] || usage
|
||||
|
||||
IMAGE="$1"
|
||||
shift
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--arch) GUEST_ARCH="$2"; shift 2 ;;
|
||||
--ssh-key) SSH_KEY="$2"; shift 2 ;;
|
||||
--seed-iso) SEED_ISO="$2"; shift 2 ;;
|
||||
--projects) PROJECTS="$2"; shift 2 ;;
|
||||
--claude-dir) CLAUDE_DIR="$2"; shift 2 ;;
|
||||
--memory) MEMORY="$2"; shift 2 ;;
|
||||
--cpus) CPUS="$2"; shift 2 ;;
|
||||
--ssh-port) SSH_PORT="$2"; shift 2 ;;
|
||||
*) echo "unknown option: $1"; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ! -f "$IMAGE" ]; then
|
||||
echo "error: image not found: $IMAGE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# detect guest architecture from image filename if not specified
|
||||
if [ -z "$GUEST_ARCH" ]; then
|
||||
case "$IMAGE" in
|
||||
*aarch64*|*arm64*) GUEST_ARCH="aarch64" ;;
|
||||
*x86_64*|*amd64*) GUEST_ARCH="x86_64" ;;
|
||||
*)
|
||||
# fallback to host architecture
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64) GUEST_ARCH="x86_64" ;;
|
||||
aarch64|arm64) GUEST_ARCH="aarch64" ;;
|
||||
*) echo "error: cannot detect guest arch, use --arch"; exit 1 ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# normalize
|
||||
case "$GUEST_ARCH" in
|
||||
x86_64|amd64) GUEST_ARCH="x86_64" ;;
|
||||
aarch64|arm64) GUEST_ARCH="aarch64" ;;
|
||||
*) echo "error: unsupported architecture: $GUEST_ARCH"; exit 1 ;;
|
||||
esac
|
||||
|
||||
# platform detection
|
||||
HOST_ARCH=$(uname -m)
|
||||
OS=$(uname -s)
|
||||
ACCEL="tcg"
|
||||
|
||||
case "$OS" in
|
||||
Linux)
|
||||
[ -r /dev/kvm ] && ACCEL="kvm"
|
||||
;;
|
||||
Darwin)
|
||||
# hvf only works when guest matches host
|
||||
case "$HOST_ARCH" in
|
||||
aarch64|arm64) [ "$GUEST_ARCH" = "aarch64" ] && ACCEL="hvf" ;;
|
||||
x86_64|amd64) [ "$GUEST_ARCH" = "x86_64" ] && ACCEL="hvf" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$GUEST_ARCH" in
|
||||
x86_64) QEMU_BIN="qemu-system-x86_64" ;;
|
||||
aarch64) QEMU_BIN="qemu-system-aarch64" ;;
|
||||
esac
|
||||
|
||||
# auto-generate seed ISO from SSH key
|
||||
CLEANUP_SEED=""
|
||||
if [ -n "$SSH_KEY" ] && [ -z "$SEED_ISO" ]; then
|
||||
SEED_ISO=$(mktemp /tmp/seed-XXXXXX.iso)
|
||||
CLEANUP_SEED="$SEED_ISO"
|
||||
bash "$SCRIPT_DIR/make-seed.sh" "$SSH_KEY" "$SEED_ISO"
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
[ -n "$CLEANUP_SEED" ] && rm -f "$CLEANUP_SEED"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# build qemu command
|
||||
QEMU_ARGS=(
|
||||
"$QEMU_BIN"
|
||||
-accel "$ACCEL"
|
||||
-m "$MEMORY"
|
||||
-smp "$CPUS"
|
||||
-drive "file=$IMAGE,format=qcow2,snapshot=on"
|
||||
-nic "user,hostfwd=tcp::${SSH_PORT}-:22"
|
||||
-nographic
|
||||
)
|
||||
|
||||
# aarch64 guest needs machine type and uefi firmware
|
||||
if [ "$GUEST_ARCH" = "aarch64" ]; then
|
||||
if [ "$ACCEL" = "hvf" ]; then
|
||||
QEMU_ARGS+=(-machine virt -cpu host)
|
||||
else
|
||||
QEMU_ARGS+=(-machine virt -cpu max)
|
||||
fi
|
||||
|
||||
EFI_CODE=""
|
||||
for p in \
|
||||
/opt/homebrew/share/qemu/edk2-aarch64-code.fd \
|
||||
/usr/local/share/qemu/edk2-aarch64-code.fd \
|
||||
/usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
|
||||
/usr/share/AAVMF/AAVMF_CODE.fd; do
|
||||
[ -f "$p" ] && EFI_CODE="$p" && break
|
||||
done
|
||||
|
||||
if [ -z "$EFI_CODE" ]; then
|
||||
echo "error: aarch64 EFI firmware not found"
|
||||
echo " macos: brew install qemu"
|
||||
echo " linux: apt install qemu-efi-aarch64"
|
||||
exit 1
|
||||
fi
|
||||
QEMU_ARGS+=(-bios "$EFI_CODE")
|
||||
fi
|
||||
|
||||
# seed ISO
|
||||
if [ -n "$SEED_ISO" ]; then
|
||||
QEMU_ARGS+=(-drive "file=$SEED_ISO,format=raw,media=cdrom,readonly=on")
|
||||
fi
|
||||
|
||||
# 9p mounts
|
||||
if [ -n "$PROJECTS" ]; then
|
||||
QEMU_ARGS+=(
|
||||
-virtfs "local,path=$PROJECTS,mount_tag=projects,security_model=mapped-xattr,id=fs0"
|
||||
)
|
||||
fi
|
||||
|
||||
if [ -n "$CLAUDE_DIR" ]; then
|
||||
QEMU_ARGS+=(
|
||||
-virtfs "local,path=$CLAUDE_DIR,mount_tag=hostclaude,security_model=mapped-xattr,id=fs1"
|
||||
)
|
||||
# also mount parent home for .claude.json
|
||||
QEMU_ARGS+=(
|
||||
-virtfs "local,path=$(dirname "$CLAUDE_DIR"),mount_tag=hosthome,security_model=mapped-xattr,id=fs2,readonly=on"
|
||||
)
|
||||
fi
|
||||
|
||||
echo "---"
|
||||
echo "Guest: $GUEST_ARCH | Accel: $ACCEL"
|
||||
echo "SSH: ssh -A -p $SSH_PORT gordaina@localhost"
|
||||
echo "Password: sandbox"
|
||||
echo "---"
|
||||
|
||||
exec "${QEMU_ARGS[@]}"
|
||||
10
flake.nix
10
flake.nix
@@ -93,6 +93,16 @@
|
||||
system = "x86_64-linux";
|
||||
users = [ ];
|
||||
};
|
||||
|
||||
# nixos-rebuild build-image --image-variant qemu --flake .#sandbox
|
||||
sandbox = mkHost "sandbox" {
|
||||
system = "x86_64-linux";
|
||||
users = [ "gordaina" ];
|
||||
};
|
||||
sandbox-aarch64 = mkHost "sandbox" {
|
||||
system = "aarch64-linux";
|
||||
users = [ "gordaina" ];
|
||||
};
|
||||
};
|
||||
|
||||
nixosModules = import ./modules/nixos {
|
||||
|
||||
@@ -65,6 +65,7 @@ in
|
||||
base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-material-dark-medium.yaml";
|
||||
};
|
||||
|
||||
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
|
||||
|
||||
128
hosts/sandbox/configuration.nix
Normal file
128
hosts/sandbox/configuration.nix
Normal file
@@ -0,0 +1,128 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
inputs.self.nixosModules.vm-guest
|
||||
inputs.self.nixosModules.seed-ssh
|
||||
inputs.self.nixosModules.zsh
|
||||
inputs.self.nixosModules.localisation
|
||||
];
|
||||
|
||||
vm-guest = {
|
||||
enable = true;
|
||||
headless = true;
|
||||
};
|
||||
|
||||
seed-ssh = {
|
||||
enable = true;
|
||||
user = "gordaina";
|
||||
};
|
||||
|
||||
zsh.enable = true;
|
||||
|
||||
localisation = {
|
||||
enable = true;
|
||||
timeZone = "UTC";
|
||||
defaultLocale = "en_US.UTF-8";
|
||||
};
|
||||
|
||||
users = {
|
||||
groups.gordaina = {
|
||||
gid = 1000;
|
||||
};
|
||||
users.gordaina = {
|
||||
group = "gordaina";
|
||||
uid = 1000;
|
||||
isNormalUser = true;
|
||||
home = "/home/gordaina";
|
||||
createHome = true;
|
||||
password = "sandbox";
|
||||
shell = pkgs.zsh;
|
||||
extraGroups = [
|
||||
"wheel"
|
||||
"users"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# 9p mounts — silently fail if shares not provided at runtime
|
||||
fileSystems."/home/gordaina/projects" = {
|
||||
device = "projects";
|
||||
fsType = "9p";
|
||||
options = [
|
||||
"trans=virtio"
|
||||
"version=9p2000.L"
|
||||
"msize=65536"
|
||||
"nofail"
|
||||
"x-systemd.automount"
|
||||
"x-systemd.device-timeout=2s"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/mnt/host-claude" = {
|
||||
device = "hostclaude";
|
||||
fsType = "9p";
|
||||
options = [
|
||||
"trans=virtio"
|
||||
"version=9p2000.L"
|
||||
"msize=65536"
|
||||
"nofail"
|
||||
"x-systemd.automount"
|
||||
"x-systemd.device-timeout=2s"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/mnt/host-home" = {
|
||||
device = "hosthome";
|
||||
fsType = "9p";
|
||||
options = [
|
||||
"trans=virtio"
|
||||
"version=9p2000.L"
|
||||
"msize=65536"
|
||||
"nofail"
|
||||
"x-systemd.automount"
|
||||
"x-systemd.device-timeout=2s"
|
||||
"ro"
|
||||
];
|
||||
};
|
||||
|
||||
# pre-auth claude-code from host config
|
||||
systemd.services.claude-auth = {
|
||||
description = "Copy claude-code credentials from host mount";
|
||||
after = [ "local-fs.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = pkgs.writeShellScript "claude-auth" ''
|
||||
# skip if host mounts are not available
|
||||
if ! mountpoint -q /mnt/host-claude && ! mountpoint -q /mnt/host-home; then
|
||||
echo "no host mounts found, skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p /home/gordaina/.claude
|
||||
if mountpoint -q /mnt/host-claude; then
|
||||
cp -a /mnt/host-claude/. /home/gordaina/.claude/
|
||||
fi
|
||||
if mountpoint -q /mnt/host-home; then
|
||||
cp /mnt/host-home/.claude.json /home/gordaina/.claude.json || true
|
||||
fi
|
||||
chown -R gordaina:gordaina /home/gordaina/.claude /home/gordaina/.claude.json 2>/dev/null || true
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
claude-code
|
||||
git
|
||||
];
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
23
hosts/sandbox/hardware-configuration.nix
Normal file
23
hosts/sandbox/hardware-configuration.nix
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
autoResize = true;
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
# x86_64: bios/grub, aarch64: uefi/systemd-boot
|
||||
boot.loader.grub.device = lib.mkIf pkgs.stdenv.hostPlatform.isx86_64 (lib.mkDefault "/dev/vda");
|
||||
boot.loader.grub.enable = lib.mkIf pkgs.stdenv.hostPlatform.isAarch64 false;
|
||||
boot.loader.systemd-boot.enable = lib.mkIf pkgs.stdenv.hostPlatform.isAarch64 true;
|
||||
boot.loader.efi.canTouchEfiVariables = lib.mkIf pkgs.stdenv.hostPlatform.isAarch64 true;
|
||||
}
|
||||
12
justfile
12
justfile
@@ -36,3 +36,15 @@ iso:
|
||||
# garbage collect old generations
|
||||
clean:
|
||||
sudo nix-collect-garbage $(nix eval --raw -f ./nix.nix nix.gc.options)
|
||||
|
||||
# build sandbox VM image
|
||||
sandbox-build:
|
||||
nixos-rebuild build-image --image-variant qemu --flake .#sandbox
|
||||
|
||||
# run sandbox VM
|
||||
sandbox-run *ARGS:
|
||||
bash dist/run.sh $(find -L result -name '*.qcow2' | head -1) {{ARGS}}
|
||||
|
||||
# ssh into running sandbox
|
||||
sandbox-ssh:
|
||||
ssh -A -p 2222 gordaina@localhost
|
||||
|
||||
61
modules/nixos/seed-ssh.nix
Normal file
61
modules/nixos/seed-ssh.nix
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
seed-ssh = {
|
||||
enable = lib.mkEnableOption "SSH key injection from seed ISO";
|
||||
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "user to install authorized_keys for";
|
||||
};
|
||||
|
||||
label = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "SEEDCONFIG";
|
||||
description = "volume label of the seed ISO";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.seed-ssh.enable {
|
||||
systemd.services.seed-ssh = {
|
||||
description = "Install SSH authorized_keys from seed ISO";
|
||||
after = [ "local-fs.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart =
|
||||
let
|
||||
cfg = config.seed-ssh;
|
||||
inherit (cfg) user;
|
||||
inherit (config.users.users.${user}) home;
|
||||
in
|
||||
pkgs.writeShellScript "seed-ssh" ''
|
||||
DEVICE="/dev/disk/by-label/${cfg.label}"
|
||||
if [ ! -e "$DEVICE" ]; then
|
||||
echo "seed ISO not found, skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
MOUNT=$(mktemp -d)
|
||||
mount -o ro "$DEVICE" "$MOUNT"
|
||||
|
||||
mkdir -p "${home}/.ssh"
|
||||
cp "$MOUNT/authorized_keys" "${home}/.ssh/authorized_keys"
|
||||
chmod 700 "${home}/.ssh"
|
||||
chmod 600 "${home}/.ssh/authorized_keys"
|
||||
chown -R ${user}:${user} "${home}/.ssh"
|
||||
|
||||
umount "$MOUNT"
|
||||
rmdir "$MOUNT"
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
62
modules/nixos/vm-guest.nix
Normal file
62
modules/nixos/vm-guest.nix
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
||||
options = {
|
||||
vm-guest = {
|
||||
enable = lib.mkEnableOption "VM guest configuration";
|
||||
headless = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "run without display, serial console only";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.vm-guest.enable {
|
||||
services.qemuGuest.enable = true;
|
||||
services.spice-vdagentd.enable = lib.mkIf (!config.vm-guest.headless) true;
|
||||
|
||||
boot.kernelParams = lib.mkIf config.vm-guest.headless [ "console=ttyS0,115200" ];
|
||||
|
||||
# 9p for host file mounting
|
||||
boot.initrd.availableKernelModules = [
|
||||
"9p"
|
||||
"9pnet_virtio"
|
||||
];
|
||||
boot.kernelModules = [
|
||||
"9p"
|
||||
"9pnet_virtio"
|
||||
];
|
||||
|
||||
# ssh with agent forwarding for git and hot-mount
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
ports = [ 22 ];
|
||||
settings = {
|
||||
PasswordAuthentication = true;
|
||||
PermitRootLogin = "no";
|
||||
AllowAgentForwarding = true;
|
||||
StreamLocalBindUnlink = "yes";
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
useDHCP = true;
|
||||
firewall.allowedTCPPorts = [ 22 ];
|
||||
};
|
||||
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
curl
|
||||
wget
|
||||
htop
|
||||
sshfs
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
packages = inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system};
|
||||
in
|
||||
|
||||
{
|
||||
home.stateVersion = "24.11";
|
||||
|
||||
home.packages = [
|
||||
pkgs.git
|
||||
];
|
||||
|
||||
programs.neovim = {
|
||||
enable = true;
|
||||
vimAlias = true;
|
||||
defaultEditor = true;
|
||||
|
||||
package = inputs.neovim-nightly-overlay.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
|
||||
extraPackages = with pkgs; [
|
||||
# runtime deps
|
||||
fzf
|
||||
ripgrep
|
||||
gnumake
|
||||
gcc
|
||||
luajit
|
||||
|
||||
lua-language-server
|
||||
nil
|
||||
nixd
|
||||
|
||||
nixpkgs-fmt
|
||||
stylua
|
||||
|
||||
];
|
||||
|
||||
extraWrapperArgs = [
|
||||
"--suffix"
|
||||
"LD_LIBRARY_PATH"
|
||||
":"
|
||||
"${lib.makeLibraryPath [ pkgs.stdenv.cc.cc.lib ]}"
|
||||
];
|
||||
|
||||
};
|
||||
}
|
||||
21
users/gordaina/home-manager.nix
Normal file
21
users/gordaina/home-manager.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
home.stateVersion = "25.11";
|
||||
|
||||
home.packages = with pkgs; [
|
||||
git
|
||||
tmux
|
||||
ripgrep
|
||||
fd
|
||||
jq
|
||||
];
|
||||
|
||||
programs.neovim = {
|
||||
enable = true;
|
||||
vimAlias = true;
|
||||
defaultEditor = true;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user