feat: ephvm improvements
This commit is contained in:
@@ -58,8 +58,11 @@
|
||||
neovim.dotfiles = inputs.nvim;
|
||||
};
|
||||
|
||||
# ensure .config exists with correct ownership before automount
|
||||
systemd.tmpfiles.rules = [ "d /home/matej/.config 0755 matej users -" ];
|
||||
|
||||
# writable claude config via 9p
|
||||
fileSystems."/home/matej/.claude" = {
|
||||
fileSystems."/home/matej/.config/claude" = {
|
||||
device = "claude";
|
||||
fsType = "9p";
|
||||
options = [
|
||||
@@ -70,23 +73,7 @@
|
||||
];
|
||||
};
|
||||
|
||||
# .claude.json passed via qemu fw_cfg
|
||||
boot.kernelModules = [ "qemu_fw_cfg" ];
|
||||
systemd.services.claude-json = {
|
||||
after = [ "systemd-modules-load.service" ];
|
||||
wants = [ "systemd-modules-load.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = pkgs.writeShellScript "claude-json" ''
|
||||
src="/sys/firmware/qemu_fw_cfg/by_name/opt/claude.json/raw"
|
||||
[ -f "$src" ] || exit 0
|
||||
cp "$src" /home/matej/.claude.json
|
||||
chown matej:users /home/matej/.claude.json
|
||||
'';
|
||||
};
|
||||
};
|
||||
environment.sessionVariables.CLAUDE_CONFIG_DIR = "/home/matej/.config/claude";
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
|
||||
8
justfile
8
justfile
@@ -33,13 +33,9 @@ build:
|
||||
iso:
|
||||
nixos-rebuild build-image --image-variant iso-installer --flake .#iso
|
||||
|
||||
# build ephemeral VM image
|
||||
ephvm-build:
|
||||
nixos-rebuild build-image --image-variant qemu --flake .#ephvm
|
||||
|
||||
# run ephemeral VM
|
||||
ephvm-run *ARGS:
|
||||
bash scripts/ephvm-run.sh $(find -L result -name '*.qcow2' | head -1) {{ARGS}}
|
||||
ephvm *ARGS:
|
||||
bash scripts/ephvm-run.sh {{ARGS}}
|
||||
|
||||
# ssh into running ephemeral VM
|
||||
ephvm-ssh port="2222":
|
||||
|
||||
@@ -20,7 +20,7 @@ in
|
||||
|
||||
prefix = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "mount_";
|
||||
default = "m_";
|
||||
description = "9p mount tag prefix to match";
|
||||
};
|
||||
|
||||
|
||||
@@ -5,18 +5,15 @@ SSH_PORT=2222
|
||||
MEMORY=8G
|
||||
CPUS=4
|
||||
MOUNTS=()
|
||||
CLAUDE_DIR=""
|
||||
CLAUDE_JSON=""
|
||||
IMAGE=""
|
||||
CLAUDE=false
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: ephvm-run.sh <image.qcow2> [options]
|
||||
Usage: ephvm-run.sh [options]
|
||||
|
||||
Options:
|
||||
--mount <path> Mount host directory into VM (repeatable)
|
||||
--claude <path> Mount claude config dir writable into VM
|
||||
--claude-json <path> Copy claude.json into mounted claude dir
|
||||
--claude Mount claude config dir (requires CLAUDE_CONFIG_DIR)
|
||||
--memory <size> VM memory (default: 8G)
|
||||
--cpus <n> VM CPUs (default: 4)
|
||||
--ssh-port <port> SSH port forward (default: 2222)
|
||||
@@ -24,25 +21,24 @@ EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ "${1:-}" ] || usage
|
||||
|
||||
IMAGE="$1"
|
||||
shift
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--mount) MOUNTS+=("$2"); shift 2 ;;
|
||||
--claude) CLAUDE_DIR="$2"; shift 2 ;;
|
||||
--claude-json) CLAUDE_JSON="$2"; shift 2 ;;
|
||||
--claude) CLAUDE=true; shift ;;
|
||||
--memory) MEMORY="$2"; shift 2 ;;
|
||||
--cpus) CPUS="$2"; shift 2 ;;
|
||||
--ssh-port) SSH_PORT="$2"; shift 2 ;;
|
||||
-h|--help) usage ;;
|
||||
*) echo "unknown option: $1"; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ! -f "$IMAGE" ]; then
|
||||
echo "error: image not found: $IMAGE"
|
||||
echo "building ephvm image..."
|
||||
IMAGE_DIR=$(nix build --no-link --print-out-paths .#nixosConfigurations.ephvm.config.system.build.images.qemu)
|
||||
IMAGE=$(find "$IMAGE_DIR" -name '*.qcow2' -print -quit)
|
||||
|
||||
if [ -z "$IMAGE" ]; then
|
||||
echo "error: no qcow2 image found in $IMAGE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -67,21 +63,25 @@ FS_ID=0
|
||||
for mount_path in "${MOUNTS[@]}"; do
|
||||
mount_path=$(realpath "$mount_path")
|
||||
name=$(basename "$mount_path")
|
||||
tag="m_${name:0:29}"
|
||||
QEMU_ARGS+=(
|
||||
-virtfs "local,path=$mount_path,mount_tag=mount_$name,security_model=none,id=fs${FS_ID}"
|
||||
-virtfs "local,path=$mount_path,mount_tag=$tag,security_model=none,id=fs${FS_ID}"
|
||||
)
|
||||
FS_ID=$((FS_ID + 1))
|
||||
done
|
||||
|
||||
if [ -n "$CLAUDE_DIR" ]; then
|
||||
CLAUDE_DIR=$(realpath "$CLAUDE_DIR")
|
||||
QEMU_ARGS+=(
|
||||
-virtfs "local,path=$CLAUDE_DIR,mount_tag=claude,security_model=none,id=fs${FS_ID}"
|
||||
)
|
||||
fi
|
||||
if [ "$CLAUDE" = true ]; then
|
||||
if [ -z "${CLAUDE_CONFIG_DIR:-}" ]; then
|
||||
echo "error: --claude requires CLAUDE_CONFIG_DIR to be set"
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "$CLAUDE_CONFIG_DIR"
|
||||
claude_dir=$(realpath "$CLAUDE_CONFIG_DIR")
|
||||
|
||||
if [ -n "$CLAUDE_JSON" ]; then
|
||||
QEMU_ARGS+=(-fw_cfg "name=opt/claude.json,file=$CLAUDE_JSON")
|
||||
QEMU_ARGS+=(
|
||||
-virtfs "local,path=$claude_dir,mount_tag=claude,security_model=none,id=fs${FS_ID}"
|
||||
)
|
||||
FS_ID=$((FS_ID + 1))
|
||||
fi
|
||||
|
||||
exec "${QEMU_ARGS[@]}"
|
||||
|
||||
Reference in New Issue
Block a user