+3
-5
docs/hacking.md
+3
-5
docs/hacking.md
···
60
60
ideally in a `.envrc` with [direnv](https://direnv.net) so you
61
61
don't lose it.
62
62
63
-
You can now start a lightweight NixOS VM using
64
-
`nixos-shell` like so:
63
+
You can now start a lightweight NixOS VM like so:
65
64
66
65
```bash
67
-
nix run .#vm
68
-
# or nixos-shell --flake .#vm
66
+
nix run --impure .#vm
69
67
70
-
# hit Ctrl-a + c + q to exit the VM
68
+
# type `poweroff` at the shell to exit the VM
71
69
```
72
70
73
71
This starts a knot on port 6000, a spindle on port 6555
+22
-27
flake.nix
+22
-27
flake.nix
···
175
175
program = ''${tailwind-watcher}/bin/run'';
176
176
};
177
177
vm = let
178
-
system =
178
+
guestSystem =
179
179
if pkgs.stdenv.hostPlatform.isAarch64
180
-
then "aarch64"
181
-
else "x86_64";
182
-
183
-
nixos-shell = pkgs.nixos-shell.overrideAttrs (old: {
184
-
patches =
185
-
(old.patches or [])
186
-
++ [
187
-
# https://github.com/Mic92/nixos-shell/pull/94
188
-
(pkgs.fetchpatch {
189
-
name = "fix-foreign-vm.patch";
190
-
url = "https://github.com/Mic92/nixos-shell/commit/113e4cc55ae236b5b0b1fbd8b321e9b67c77580e.patch";
191
-
hash = "sha256-eauetBK0wXAOcd9PYbExokNCiwz2QyFnZ4FnwGi9VCo=";
192
-
})
193
-
];
194
-
});
180
+
then "aarch64-linux"
181
+
else "x86_64-linux";
195
182
in {
196
183
type = "app";
197
-
program = toString (pkgs.writeShellScript "vm" ''
198
-
${nixos-shell}/bin/nixos-shell --flake .#vm-${system} --guest-system ${system}-linux
199
-
'');
184
+
program =
185
+
(pkgs.writeShellApplication {
186
+
name = "launch-vm";
187
+
text = ''
188
+
rootDir=$(jj --ignore-working-copy root || git rev-parse --show-toplevel) || (echo "error: can't find repo root?"; exit 1)
189
+
cd "$rootDir"
190
+
191
+
mkdir -p nix/vm-data/{knot,repos,spindle,spindle-logs}
192
+
193
+
export TANGLED_VM_DATA_DIR="$rootDir/nix/vm-data"
194
+
exec ${pkgs.lib.getExe
195
+
(import ./nix/vm.nix {
196
+
inherit nixpkgs self;
197
+
system = guestSystem;
198
+
hostSystem = system;
199
+
}).config.system.build.vm}
200
+
'';
201
+
})
202
+
+ /bin/launch-vm;
200
203
};
201
204
gomod2nix = {
202
205
type = "app";
···
257
260
imports = [./nix/modules/spindle.nix];
258
261
259
262
services.tangled-spindle.package = lib.mkDefault self.packages.${pkgs.system}.spindle;
260
-
};
261
-
nixosConfigurations.vm-x86_64 = import ./nix/vm.nix {
262
-
inherit self nixpkgs;
263
-
system = "x86_64-linux";
264
-
};
265
-
nixosConfigurations.vm-aarch64 = import ./nix/vm.nix {
266
-
inherit self nixpkgs;
267
-
system = "aarch64-linux";
268
263
};
269
264
};
270
265
}
+52
-16
nix/vm.nix
+52
-16
nix/vm.nix
···
1
1
{
2
2
nixpkgs,
3
3
system,
4
+
hostSystem,
4
5
self,
5
6
}: let
6
7
envVar = name: let
···
16
17
self.nixosModules.knot
17
18
self.nixosModules.spindle
18
19
({
20
+
lib,
19
21
config,
20
22
pkgs,
21
23
...
22
24
}: {
23
-
nixos-shell = {
24
-
inheritPath = false;
25
-
mounts = {
26
-
mountHome = false;
27
-
mountNixProfile = false;
28
-
};
29
-
};
30
-
virtualisation = {
25
+
virtualisation.vmVariant.virtualisation = {
26
+
host.pkgs = import nixpkgs {system = hostSystem;};
27
+
28
+
graphics = false;
31
29
memorySize = 2048;
32
30
diskSize = 10 * 1024;
33
31
cores = 2;
···
51
49
guest.port = 6555;
52
50
}
53
51
];
52
+
sharedDirectories = {
53
+
# We can't use the 9p mounts directly for most of these
54
+
# as SQLite is incompatible with them. So instead we
55
+
# mount the shared directories to a different location
56
+
# and copy the contents around on service start/stop.
57
+
knotData = {
58
+
source = "$TANGLED_VM_DATA_DIR/knot";
59
+
target = "/mnt/knot-data";
60
+
};
61
+
spindleData = {
62
+
source = "$TANGLED_VM_DATA_DIR/spindle";
63
+
target = "/mnt/spindle-data";
64
+
};
65
+
spindleLogs = {
66
+
source = "$TANGLED_VM_DATA_DIR/spindle-logs";
67
+
target = "/var/log/spindle";
68
+
};
69
+
};
54
70
};
55
71
services.getty.autologinUser = "root";
56
72
environment.systemPackages = with pkgs; [curl vim git sqlite litecli];
57
-
systemd.tmpfiles.rules = let
58
-
u = config.services.tangled-knot.gitUser;
59
-
g = config.services.tangled-knot.gitUser;
60
-
in [
61
-
"d /var/lib/knot 0770 ${u} ${g} - -" # Create the directory first
62
-
"f+ /var/lib/knot/secret 0660 ${u} ${g} - KNOT_SERVER_SECRET=${envVar "TANGLED_VM_KNOT_SECRET"}"
63
-
];
64
73
services.tangled-knot = {
65
74
enable = true;
66
75
motd = "Welcome to the development knot!\n";
67
76
server = {
68
-
secretFile = "/var/lib/knot/secret";
77
+
secretFile = builtins.toFile "knot-secret" ("KNOT_SERVER_SECRET=" + (envVar "TANGLED_VM_KNOT_SECRET"));
69
78
hostname = "localhost:6000";
70
79
listenAddr = "0.0.0.0:6000";
71
80
};
···
81
90
provider = "sqlite";
82
91
};
83
92
};
93
+
};
94
+
users = {
95
+
# So we don't have to deal with permission clashing between
96
+
# blank disk VMs and existing state
97
+
users.${config.services.tangled-knot.gitUser}.uid = 666;
98
+
groups.${config.services.tangled-knot.gitUser}.gid = 666;
99
+
100
+
# TODO: separate spindle user
101
+
};
102
+
systemd.services = let
103
+
mkDataSyncScripts = source: target: {
104
+
enableStrictShellChecks = true;
105
+
106
+
preStart = lib.mkBefore ''
107
+
mkdir -p ${target}
108
+
${lib.getExe pkgs.rsync} -a ${source}/ ${target}
109
+
'';
110
+
111
+
postStop = lib.mkAfter ''
112
+
${lib.getExe pkgs.rsync} -a ${target}/ ${source}
113
+
'';
114
+
115
+
serviceConfig.PermissionsStartOnly = true;
116
+
};
117
+
in {
118
+
knot = mkDataSyncScripts "/mnt/knot-data" config.services.tangled-knot.stateDir;
119
+
spindle = mkDataSyncScripts "/mnt/spindle-data" (builtins.dirOf config.services.tangled-spindle.server.dbPath);
84
120
};
85
121
})
86
122
];