Skip to content

Commit ab971bb

Browse files
committed
first commit
0 parents  commit ab971bb

File tree

6 files changed

+177
-0
lines changed

6 files changed

+177
-0
lines changed

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
INSTALL ?= install
2+
NIXOS_SHELL ?= $(shell nix-build --no-out-link default.nix)
3+
4+
all:
5+
6+
test:
7+
QEMU_NET_OPTS="hostfwd=tcp::2222-:22" QEMU_OPTS="--smp 2 -m 1024" $(NIXOS_SHELL)/bin/nixos-shell example-vm.nix
8+
9+
install:
10+
$(INSTALL) -D bin/nixos-shell $(DESTDIR)$(PREFIX)/bin/nixos-shell
11+
$(INSTALL) -D share/nixos-shell/nixos-shell.nix $(DESTDIR)$(PREFIX)/share/nixos-shell/nixos-shell.nix

README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# nixos-shell
2+
3+
* Spawns a headless vm based on a `vm.nix` file in the current directory.
4+
* Mounts `$HOME` and the user's nix profile into the container
5+
* No ugly qemu SDL window, no serial console with incorrect terminal dimension.
6+
* If a tmux session is available, the console is will be spawned in a new tmux pane,
7+
while the qemu interface will be started in the current active pane
8+
9+
Example `vm.nix`:
10+
11+
```nix
12+
{ pkgs, ...}: {
13+
boot.kernelPackages = pkgs.linuxPackages_latest;
14+
}
15+
```
16+
17+
## USAGE
18+
19+
Start a vm:
20+
21+
```console
22+
$ nixos-shell
23+
```
24+
25+
or
26+
27+
```console
28+
$ nixos-shell some-nix-module.nix
29+
```
30+
31+
Quit the vm:
32+
33+
```console
34+
$vm> poweroff
35+
```
36+
37+
or in the qemu console:
38+
39+
```console
40+
quit
41+
```
42+
43+
Forward a port:
44+
45+
```console
46+
$ QEMU_NET_OPTS="hostfwd=tcp::2222-:22" nixos-shell
47+
```
48+
49+
More RAM:
50+
51+
```
52+
$ QEMU_OPTS="-m 1024" nixos-shell
53+
```
54+
55+
More CPUs:
56+
57+
```
58+
$ QEMU_OPTS="--smp 2" nixos-shell
59+
```

bin/nixos-shell

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
6+
export QEMU_KERNEL_PARAMS="console=ttyS0 ${QEMU_KERNEL_PARAMS:-}"
7+
export QEMU_PATH=${PATH:-}
8+
if [[ -z "${QEMU_SHELL:-}" ]] && [[ -n "$SHELL" ]]; then
9+
export QEMU_SHELL=$(basename "$SHELL")
10+
fi
11+
12+
nixos_config=vm.nix
13+
if [[ $# -gt 0 ]]; then
14+
nixos_config=$1
15+
shift
16+
fi
17+
export QEMU_NIXOS_CONFIG=$(readlink -f "$nixos_config")
18+
19+
qemu_tty=/dev/null
20+
tmux_pane_pid=
21+
if [[ -n "${TMUX:-}" ]] && command -v tmux >/dev/null 2>&1; then
22+
tmux_session=($(tmux new-window -P -F '#{pane_tty} #{pane_pid}' "sleep 99999999999"))
23+
qemu_tty=${tmux_session[0]}
24+
tmux_pane_pid=${tmux_session[1]}
25+
export QEMU_OPTS="-nographic -chardev tty,id=pts2,path=$qemu_tty -device isa-serial,chardev=pts2 ${QEMU_OPTS:-}"
26+
else
27+
export QEMU_OPTS="-nographic -serial mon:stdio ${QEMU_OPTS:-}"
28+
fi
29+
30+
build_succeed=
31+
cleanup() {
32+
if [[ -n "$build_succeed" ]]; then
33+
rm -f result
34+
fi
35+
if [[ -n "$tmux_pane_pid" ]]; then
36+
kill "$tmux_pane_pid"
37+
fi
38+
}
39+
trap cleanup EXIT SIGINT SIGQUIT ERR
40+
41+
export QEMU_OPTS="$QEMU_OPTS -virtfs local,path=/home/,security_model=none,mount_tag=home"
42+
nix_profile="/nix/var/nix/profiles/per-user/$USER/profile/"
43+
if [[ -d $nix_profile ]]; then
44+
export QEMU_OPTS="$QEMU_OPTS -virtfs local,path=$nix_profile,security_model=none,mount_tag=nixprofile"
45+
fi
46+
47+
nixos-rebuild -I "nixos-config=$script_dir/../share/nixos-shell/nixos-shell.nix" "$@" build-vm 2>&1 | tee "$qemu_tty"
48+
build_succeed=1
49+
./result/bin/run-*-vm

default.nix

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
with import <nixpkgs> {};
2+
stdenv.mkDerivation {
3+
name = "env";
4+
src = ./.;
5+
buildInputs = [ bash ];
6+
preConfigure = ''
7+
export PREFIX=$out
8+
'';
9+
}

example-vm.nix

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{ pkgs, ...}: {
2+
boot.kernelPackages = pkgs.linuxPackages_latest;
3+
services.openssh.enable = true;
4+
}

share/nixos-shell/nixos-shell.nix

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{ lib, config, pkgs, ... }:
2+
# ./run-vm.sh -I nixos-config=./test-vm.nix
3+
let
4+
home = builtins.getEnv "HOME";
5+
user = builtins.getEnv "USER";
6+
pwd = builtins.getEnv "PWD";
7+
shell = builtins.getEnv "QEMU_SHELL";
8+
path = builtins.getEnv "QEMU_PATH";
9+
nixos_config = builtins.getEnv "QEMU_NIXOS_CONFIG";
10+
term = builtins.getEnv "TERM";
11+
in {
12+
users.extraUsers.root = {
13+
# Allow the user to login as root without password.
14+
initialHashedPassword = "";
15+
shell = pkgs.${shell} or pkgs.bashInteractive;
16+
home = lib.mkVMOverride (if home != "" then home else "/root");
17+
};
18+
services.mingetty.helpLine = ''
19+
Log in as "root" with an empty password.
20+
'';
21+
22+
# build-vm overrides our filesystem settings in nixos-config
23+
# cache=loose -> bad idea? Well, at least it is fast!1!!
24+
boot.initrd.postMountCommands = ''
25+
mkdir -p $targetRoot/home
26+
mount -t 9p home $targetRoot/home -o trans=virtio,version=9p2000.L,cache=loose
27+
${lib.optionalString (user != "") ''
28+
mkdir -p $targetRoot/nix/var/nix/profiles/per-user/${user}/profile/
29+
mount -t 9p nixprofile $targetRoot/nix/var/nix/profiles/per-user/${user}/profile/ -o trans=virtio,version=9p2000.L,cache=loose
30+
''}
31+
'';
32+
environment.loginShellInit = ''
33+
# fix terminal size
34+
eval "$(${pkgs.xterm}/bin/resize)"
35+
36+
${lib.optionalString (pwd != "") "cd '${pwd}' 2>/dev/null"}
37+
${lib.optionalString (term != "") "export TERM='${term}'"}
38+
${lib.optionalString (path != "") "export PATH=${path}:$PATH"}
39+
'';
40+
41+
systemd.services."serial-getty@ttyS0".enable = true;
42+
networking.firewall.enable = false;
43+
44+
imports = lib.optional (nixos_config != "") nixos_config;
45+
}

0 commit comments

Comments
 (0)