aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2022-11-29 13:01:46 +0100
committerAlex Auvolat <alex@adnab.me>2022-11-29 13:01:46 +0100
commitfa49c13513ae5ab66157c634de244fdcf0a6cc1d (patch)
tree32508ecd16e0183767ecb7dd4bbeca82eccfdb0a
parentec3eba576a1a9574c6a2be8d90d973badb34f455 (diff)
downloadnomad-driver-nix2-fa49c13513ae5ab66157c634de244fdcf0a6cc1d.tar.gz
nomad-driver-nix2-fa49c13513ae5ab66157c634de244fdcf0a6cc1d.zip
Works better and better, write some examples
-rw-r--r--example/agent.hcl1
-rw-r--r--example/example-batch.hcl46
-rw-r--r--example/example-service.hcl35
-rw-r--r--example/example.hcl24
-rw-r--r--example/example2.hcl28
-rw-r--r--nix2/driver.go39
-rw-r--r--nix2/nix.go14
7 files changed, 123 insertions, 64 deletions
diff --git a/example/agent.hcl b/example/agent.hcl
index 740c221..dc3c2f5 100644
--- a/example/agent.hcl
+++ b/example/agent.hcl
@@ -5,5 +5,6 @@ client {
plugin "nix2-driver" {
config {
+ default_nixpkgs = "github:nixos/nixpkgs/nixos-22.05"
}
}
diff --git a/example/example-batch.hcl b/example/example-batch.hcl
new file mode 100644
index 0000000..a4dc946
--- /dev/null
+++ b/example/example-batch.hcl
@@ -0,0 +1,46 @@
+job "nix2-example-batch" {
+ datacenters = ["dc1"]
+ type = "batch"
+
+ group "example" {
+ # Simple example: how to run a binary from a Nixpkgs package
+ # By default, this will use nixpkgs from github:nixos/nixpkgs/nixos-22.05
+ # as a base system, as defined in the agent config file.
+ # This could be overridden by setting nixpkgs = "another flake"
+ # inside the config {} block
+ task "nix-hello" {
+ driver = "nix2"
+
+ config {
+ packages = [
+ "hello" # equivalent to "github:nixos/nixpkgs/nixos-22.05#hello"
+ ]
+ command = "hello"
+ }
+ }
+
+ # This example show how to setup root CA certificates so that jobs
+ # can do TLS connections
+ # Here, a Nix profile is built using packages curl and cacert from nixpkgs.
+ # Because the cacert package is included, the ca-bundle.crt file is added to
+ # /etc in that profile. Then, the nix2 driver binds all files from that
+ # profile in the root directory, making ca-bundle.crt available directly under /etc.
+ # Reference: see https://gist.github.com/CMCDragonkai/1ae4f4b5edeb021ca7bb1d271caca999
+ task "nix-curl-ssl" {
+ driver = "nix2"
+
+ config {
+ packages = [
+ "curl", "cacert"
+ ]
+ command = "curl"
+ args = [
+ "https://nixos.org"
+ ]
+ }
+ env = {
+ SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt"
+ }
+ }
+ }
+}
diff --git a/example/example-service.hcl b/example/example-service.hcl
new file mode 100644
index 0000000..18dde44
--- /dev/null
+++ b/example/example-service.hcl
@@ -0,0 +1,35 @@
+job "nix2-example-service" {
+ datacenters = ["dc1"]
+ type = "service"
+
+ group "example" {
+ # This task defines a server that runs a simple python file server on port 8080,
+ # which allows to explore the contents of the filesystem namespace as visible
+ # by processes that run inside the task.
+ # A bunch of utilities are included as well, so that you can exec into the container
+ # and explore what's inside by yourself.
+ task "nix-python-serve-http" {
+ driver = "nix2"
+
+ config {
+ packages = [
+ "python3",
+ "bash",
+ "coreutils",
+ "curl",
+ "nix",
+ "git",
+ "cacert",
+ "strace",
+ "gnugrep",
+ "mount",
+ ]
+ command = "python3"
+ args = [ "-m", "http.server", "8080" ]
+ }
+ env = {
+ SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt"
+ }
+ }
+ }
+}
diff --git a/example/example.hcl b/example/example.hcl
deleted file mode 100644
index dee0e0e..0000000
--- a/example/example.hcl
+++ /dev/null
@@ -1,24 +0,0 @@
-job "example" {
- datacenters = ["dc1"]
- type = "batch"
-
- group "example" {
- task "test-nix-hello" {
- driver = "nix2"
-
- config {
- command = "sh"
- args = [
- "-c",
- "pwd; ls -l *; mount; hello"
- ]
- packages = [
- "github:NixOS/nixpkgs#coreutils",
- "github:NixOS/nixpkgs#bash",
- "github:NixOS/nixpkgs#hello"
- ]
- }
- user = "lx"
- }
- }
-}
diff --git a/example/example2.hcl b/example/example2.hcl
deleted file mode 100644
index 8b56f8a..0000000
--- a/example/example2.hcl
+++ /dev/null
@@ -1,28 +0,0 @@
-job "example2" {
- datacenters = ["dc1"]
- type = "service"
-
- group "example" {
- task "server" {
- driver = "nix2"
-
- config {
- packages = [
- "github:nixos/nixpkgs#python3",
- "github:nixos/nixpkgs#bash",
- "github:nixos/nixpkgs#coreutils",
- "github:nixos/nixpkgs#curl",
- "github:nixos/nixpkgs#nix",
- "github:nixos/nixpkgs#git",
- "github:nixos/nixpkgs#cacert",
- "github:nixos/nixpkgs#strace",
- "github:nixos/nixpkgs#gnugrep",
- "github:nixos/nixpkgs#mount",
- ]
- command = "python3"
- args = [ "-m", "http.server", "8080" ]
- }
- user = "lx"
- }
- }
-}
diff --git a/nix2/driver.go b/nix2/driver.go
index 833e515..610baab 100644
--- a/nix2/driver.go
+++ b/nix2/driver.go
@@ -68,6 +68,10 @@ var (
hclspec.NewAttr("default_ipc_mode", "string", false),
hclspec.NewLiteral(`"private"`),
),
+ "default_nixpkgs": hclspec.NewDefault(
+ hclspec.NewAttr("default_nixpkgs", "string", false),
+ hclspec.NewLiteral(`"github:nixos/nixpkgs/nixos-22.05"`),
+ ),
"allow_caps": hclspec.NewDefault(
hclspec.NewAttr("allow_caps", "list(string)", false),
hclspec.NewLiteral(capabilities.HCLSpecLiteral),
@@ -89,6 +93,7 @@ var (
"ipc_mode": hclspec.NewAttr("ipc_mode", "string", false),
"cap_add": hclspec.NewAttr("cap_add", "list(string)", false),
"cap_drop": hclspec.NewAttr("cap_drop", "list(string)", false),
+ "nixpkgs": hclspec.NewAttr("nixpkgs", "string", false),
"packages": hclspec.NewAttr("packages", "list(string)", false),
})
@@ -153,6 +158,9 @@ type Config struct {
// exec-based task drivers.
DefaultModeIPC string `codec:"default_ipc_mode"`
+ // Nixpkgs flake to use
+ DefaultNixpkgs string `codec:"default_nixpkgs"`
+
// AllowCaps configures which Linux Capabilities are enabled for tasks
// running on this node.
AllowCaps []string `codec:"allow_caps"`
@@ -204,6 +212,9 @@ type TaskConfig struct {
// Must be "private" or "host" if set.
ModeIPC string `codec:"ipc_mode"`
+ // Nixpkgs flake to use
+ Nixpkgs string `codec:"nixpkgs"`
+
// CapAdd is a set of linux capabilities to enable.
CapAdd []string `codec:"cap_add"`
@@ -488,7 +499,19 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
user := cfg.User
if user == "" {
- user = "0"
+ user = "nobody"
+ }
+
+ // Determine the nixpkgs version to use.
+ nixpkgs := driverConfig.Nixpkgs
+ if nixpkgs == "" {
+ nixpkgs = d.config.DefaultNixpkgs
+ }
+ // Use that repo for all packages not specified from a flake already.
+ for i := range driverConfig.Packages {
+ if !strings.Contains(driverConfig.Packages[i], "#") {
+ driverConfig.Packages[i] = nixpkgs + "#" + driverConfig.Packages[i]
+ }
}
// Prepare NixOS packages and setup a bunch of read-only mounts
@@ -498,19 +521,27 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
AllocID: cfg.AllocID,
TaskName: cfg.Name,
Timestamp: time.Now(),
- Message: "Building Nix packages and preparing NixOS state",
+ Message: fmt.Sprintf(
+ "Building Nix packages and preparing NixOS state (using nixpkgs from flake: %s)",
+ nixpkgs,
+ ),
Annotations: map[string]string{
"packages": strings.Join(driverConfig.Packages, " "),
},
})
taskDirs := cfg.TaskDir()
- systemMounts, err := prepareNixPackages(taskDirs.Dir, driverConfig.Packages)
+ systemMounts, err := prepareNixPackages(taskDirs.Dir, driverConfig.Packages, nixpkgs)
if err != nil {
return nil, nil, err
}
// Some files are necessary and should be taken from outside if not present already
- for _, f := range []string{ "/etc/resolv.conf", "/etc/passwd", "/etc/nsswitch.conf" } {
+ etcpaths := []string{
+ "/etc/nsswitch.conf", // Necessary for most things
+ "/etc/passwd", // Necessary for username/UID lookup
+ "/etc/resolv.conf", // Necessary for DNS resolution
+ }
+ for _, f := range etcpaths {
if _, ok := systemMounts[f]; !ok {
systemMounts[f] = f
}
diff --git a/nix2/nix.go b/nix2/nix.go
index 7a86934..5b94065 100644
--- a/nix2/nix.go
+++ b/nix2/nix.go
@@ -2,11 +2,11 @@ package nix2
import (
"bytes"
- "path/filepath"
"encoding/json"
"fmt"
"os"
"os/exec"
+ "path/filepath"
"github.com/hashicorp/nomad/helper/pluginutils/hclutils"
)
@@ -15,13 +15,13 @@ const (
closureNix = `
{ path }:
let
- nixpkgs = builtins.getFlake "github:nixos/nixpkgs/nixos-22.05";
+ nixpkgs = builtins.getFlake "%s";
inherit (nixpkgs.legacyPackages.x86_64-linux) buildPackages;
in buildPackages.closureInfo { rootPaths = builtins.storePath path; }
`
)
-func prepareNixPackages(taskDir string, packages []string) (hclutils.MapStrStr, error) {
+func prepareNixPackages(taskDir string, packages []string, nixpkgs string) (hclutils.MapStrStr, error) {
mounts := make(hclutils.MapStrStr)
profileLink := filepath.Join(taskDir, "current-profile")
@@ -31,7 +31,7 @@ func prepareNixPackages(taskDir string, packages []string) (hclutils.MapStrStr,
}
closureLink := filepath.Join(taskDir, "current-closure")
- closure, err := nixBuildClosure(profileLink, closureLink)
+ closure, err := nixBuildClosure(profileLink, closureLink, nixpkgs)
if err != nil {
return nil, fmt.Errorf("Build of the flakes failed: %v", err)
}
@@ -59,8 +59,6 @@ func prepareNixPackages(taskDir string, packages []string) (hclutils.MapStrStr,
}
}
- mounts[filepath.Join(closure, "registration")] = "/registration"
-
requisites, err := nixRequisites(closure)
if err != nil {
return nil, fmt.Errorf("Couldn't determine flake requisites: %v", err)
@@ -98,14 +96,14 @@ func nixBuildProfile(flakes []string, link string) (string, error) {
}
}
-func nixBuildClosure(profile string, link string) (string, error) {
+func nixBuildClosure(profile string, link string, nixpkgs string) (string, error) {
cmd := exec.Command(
"nix",
"--extra-experimental-features", "nix-command",
"--extra-experimental-features", "flakes",
"build",
"--out-link", link,
- "--expr", closureNix,
+ "--expr", fmt.Sprintf(closureNix, nixpkgs),
"--impure",
"--no-write-lock-file",
"--argstr", "path", profile)