aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmd/hpkg/with.go
blob: 21adeec49ae41771a01f724f863b529b53d08ce1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package main

import (
	"context"
	"strings"

	"hakurei.app/container"
	"hakurei.app/container/seccomp"
	"hakurei.app/hst"
	"hakurei.app/internal"
)

func withNixDaemon(
	ctx context.Context,
	action string, command []string, net bool, updateConfig func(config *hst.Config) *hst.Config,
	app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func(),
) {
	mustRunAppDropShell(ctx, updateConfig(&hst.Config{
		ID: app.ID,

		Path: pathShell,
		Args: []string{bash, "-lc", "rm -f /nix/var/nix/daemon-socket/socket && " +
			// start nix-daemon
			"nix-daemon --store / & " +
			// wait for socket to appear
			"(while [ ! -S /nix/var/nix/daemon-socket/socket ]; do sleep 0.01; done) && " +
			// create directory so nix stops complaining
			"mkdir -p /nix/var/nix/profiles/per-user/root/channels && " +
			strings.Join(command, " && ") +
			// terminate nix-daemon
			" && pkill nix-daemon",
		},

		Username: "hakurei",
		Shell:    pathShell,
		Data:     pathSet.homeDir,
		Dir:      pathDataData.Append(app.ID),
		ExtraPerms: []*hst.ExtraPermConfig{
			{Path: dataHome, Execute: true},
			{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
		},

		Identity: app.Identity,

		Container: &hst.ContainerConfig{
			Hostname:     formatHostname(app.Name) + "-" + action,
			Userns:       true, // nix sandbox requires userns
			HostNet:      net,
			SeccompFlags: seccomp.AllowMultiarch,
			Tty:          dropShell,
			Filesystem: []hst.FilesystemConfigJSON{
				{FilesystemConfig: &hst.FSBind{Target: container.AbsFHSEtc, Source: pathSet.cacheDir.Append("etc"), Special: true}},
				{FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath, Target: pathNix, Write: true}},
			},
			Link: []hst.LinkConfig{
				{pathCurrentSystem, app.CurrentSystem.String()},
				{pathBin, pathSwBin.String()},
				{container.AbsFHSUsrBin, pathSwBin.String()},
			},
		},
	}), dropShell, beforeFail)
}

func withCacheDir(
	ctx context.Context,
	action string, command []string, workDir *container.Absolute,
	app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func()) {
	mustRunAppDropShell(ctx, &hst.Config{
		ID: app.ID,

		Path: pathShell,
		Args: []string{bash, "-lc", strings.Join(command, " && ")},

		Username: "nixos",
		Shell:    pathShell,
		Data:     pathSet.cacheDir, // this also ensures cacheDir via shim
		Dir:      pathDataData.Append(app.ID, "cache"),
		ExtraPerms: []*hst.ExtraPermConfig{
			{Path: dataHome, Execute: true},
			{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
			{Path: workDir, Execute: true},
		},

		Identity: app.Identity,

		Container: &hst.ContainerConfig{
			Hostname:     formatHostname(app.Name) + "-" + action,
			SeccompFlags: seccomp.AllowMultiarch,
			Tty:          dropShell,
			Filesystem: []hst.FilesystemConfigJSON{
				{FilesystemConfig: &hst.FSBind{Target: container.AbsFHSEtc, Source: workDir.Append(container.FHSEtc), Special: true}},
				{FilesystemConfig: &hst.FSBind{Source: workDir.Append("nix"), Target: pathNix}},
				{FilesystemConfig: &hst.FSBind{Source: workDir, Target: hst.AbsTmp.Append("bundle")}},
			},
			Link: []hst.LinkConfig{
				{pathCurrentSystem, app.CurrentSystem.String()},
				{pathBin, pathSwBin.String()},
				{container.AbsFHSUsrBin, pathSwBin.String()},
			},
		},
	}, dropShell, beforeFail)
}

func mustRunAppDropShell(ctx context.Context, config *hst.Config, dropShell bool, beforeFail func()) {
	if dropShell {
		config.Args = []string{bash, "-l"}
		mustRunApp(ctx, config, beforeFail)
		beforeFail()
		internal.Exit(0)
	}
	mustRunApp(ctx, config, beforeFail)
}