diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 00000000..7ffa9fd5 --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,6 @@ +{ + "image": "std-vscode", + "settings": { + "terminal.integrated.shell.linux": "/bin/bash" + } +} \ No newline at end of file diff --git a/cells/_automation/containers.nix b/cells/_automation/containers.nix new file mode 100644 index 00000000..ac55571d --- /dev/null +++ b/cells/_automation/containers.nix @@ -0,0 +1,37 @@ +{ + inputs, + cell, +}: let + inherit (inputs.cells) nixpkgs lib; + l = nixpkgs.lib // builtins; +in { + dev = lib.ops.mkDevOCI { + name = "docker.io/std-dev"; + tag = "latest"; + devshell = cell.devshells.default; + labels = { + title = "std-dev"; + version = "0.1.0"; + url = "https://github.com/divnix"; + source = "https://github.com/divnix"; + description = '' + A prepackaged container for hacking on std + ''; + }; + }; + vscode = lib.ops.mkDevOCI { + name = "docker.io/std-vscode"; + tag = "latest"; + devshell = cell.devshells.default; + vscode = true; + labels = { + title = "std-dev"; + version = "0.1.0"; + url = "https://github.com/divnix"; + source = "https://github.com/divnix"; + description = '' + A prepackaged vscode devcontainer for hacking on std + ''; + }; + }; +} diff --git a/cells/lib/ops.nix b/cells/lib/ops.nix index 00236962..01d22f85 100644 --- a/cells/lib/ops.nix +++ b/cells/lib/ops.nix @@ -18,13 +18,7 @@ in { mkUser = import ./ops/mkUser.nix {inherit inputs cell;}; writeScript = import ./ops/writeScript.nix {inherit inputs cell;}; - mkOCI = import ./ops/mkOCI.nix { - inherit cell; - inputs = requireInput "n2c" "github:nlewo/nix2container" "std.lib.ops.mkOCI"; - }; - - mkStandardOCI = import ./ops/mkStandardOCI.nix { - inherit cell; - inputs = requireInput "n2c" "github:nlewo/nix2container" "std.lib.ops.mkStandardOCI"; - }; + mkOCI = import ./ops/mkOCI.nix {inherit inputs cell;}; + mkDevOCI = import ./ops/mkDevOCI.nix {inherit inputs cell;}; + mkStandardOCI = import ./ops/mkStandardOCI.nix {inherit inputs cell;}; } diff --git a/cells/lib/ops/mkDevOCI.nix b/cells/lib/ops/mkDevOCI.nix new file mode 100644 index 00000000..c45ce563 --- /dev/null +++ b/cells/lib/ops/mkDevOCI.nix @@ -0,0 +1,261 @@ +{ + inputs, + cell, +}: let + inherit (inputs) nixpkgs std; + l = nixpkgs.lib // builtins; + n2c = inputs.n2c.packages.nix2container; +in + /* + Creates a "development" OCI image from a devshell + + Args: + name: The name of the image. + devshell: The devshell derivation used to populate /nix/store + runtimeShell: The default shell to use in the container + user: The name to use for the container user + vscode: If true, makes this image compatible with vscode devcontainers + slim: If true, omits including nixpkgs and some common development tools + tag: Optional tag of the image (defaults to output hash) + pkgs: Additional pkgs to include in the image (symlinked to /bin) + setup: A list of additional setup tasks to run to configure the container. + perms: A list of permissions to set for the container. + labels: An attribute set of labels to set for the container. The keys are + automatically prefixed with "org.opencontainers.image". + options: Additional options to pass to nix2container.buildImage. + + Returns: + An OCI container image (created with nix2container). + */ + { + name, + devshell, + runtimeShell ? nixpkgs.bashInteractive, + vscode ? false, + slim ? false, + user ? "user", + tag ? "", + pkgs ? [], + setup ? [], + perms ? [], + labels ? {}, + options ? {}, + }: let + # vscode defaults to "vscode" as the user + user' = + if vscode + then "vscode" + else user; + + # Determine proper shell configuration file based on runtime shell + # Only bash/zsh are supported currently + shellName = builtins.unsafeDiscardStringContext (l.baseNameOf (l.getExe runtimeShell)); + shellConfigs = { + bash = "bashrc"; + zsh = "zshrc"; + }; + + # Configure local user + setupUser = cell.ops.mkUser { + user = user'; + group = user'; + uid = "1000"; + gid = "1000"; + shell = l.getExe runtimeShell; + withHome = true; + withRoot = true; + }; + + # Configure direnv, git, and nix + setupEnv = + cell.ops.mkSetup "container" + [ + { + regex = "/tmp"; + mode = "0777"; + } + ] + '' + # Setup tmp folder + mkdir -p $out/tmp + + # Enable nix flakes + mkdir -p $out/etc + echo "sandbox = false" > $out/etc/nix.conf + echo "experimental-features = nix-command flakes" >> $out/etc/nix.conf + + # Increase warn timeout and whitelist all paths + cat >$out/etc/direnv.toml << EOF + [global] + warn_timeout = "10m" + [whitelist] + prefix = [ "/" ] + EOF + + # Add direnv shim + cat >$out/etc/${shellConfigs.${shellName}} << EOF + eval "\$(direnv hook ${shellName})" + EOF + + # Put local profile in path + echo 'export PATH="$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:$PATH"' >> $out/etc/${shellConfigs.${shellName}} + + # Optionally configure starship + cat >>$out/etc/${shellConfigs.${shellName}} << EOF + ${l.optionalString (! slim) ''eval "\$(starship init ${shellName})"''} + EOF + + # Disable git safe directory + cat >$out/etc/gitconfig < to support installing additional packages + "NIX_PATH=nixpkgs=${nixpkgs.path}" + ]); + Volumes = l.optionalAttrs vscode {"/vscode" = {};}; + } + // (l.optionalAttrs (! vscode) {WorkingDir = "/work";}); + }; + } diff --git a/cells/lib/ops/mkOperable.nix b/cells/lib/ops/mkOperable.nix index 1591a0ed..77286c21 100644 --- a/cells/lib/ops/mkOperable.nix +++ b/cells/lib/ops/mkOperable.nix @@ -45,7 +45,7 @@ in }; # Configure debug environment - banner = nixpkgs.runCommandNoCC "debug-banner" {} '' + banner = nixpkgs.runCommand "debug-banner" {} '' ${nixpkgs.figlet}/bin/figlet -f banner "STD Debug" > $out ''; debug = cell.ops.writeScript { diff --git a/cells/lib/ops/mkSetup.nix b/cells/lib/ops/mkSetup.nix index 4a4c950b..877c79fc 100644 --- a/cells/lib/ops/mkSetup.nix +++ b/cells/lib/ops/mkSetup.nix @@ -17,7 +17,7 @@ in A setup task. */ name: perms: contents: let - setup = nixpkgs.runCommandNoCC "oci-setup-${name}" {} contents; + setup = nixpkgs.runCommand "oci-setup-${name}" {} contents; perms' = l.map (p: p // { path = setup; }) perms; in setup diff --git a/cells/lib/ops/mkUser.nix b/cells/lib/ops/mkUser.nix index 069ca941..a41afe64 100644 --- a/cells/lib/ops/mkUser.nix +++ b/cells/lib/ops/mkUser.nix @@ -23,6 +23,7 @@ in uid, group, gid, + shell ? "", withHome ? false, withRoot ? false, }: let @@ -48,7 +49,7 @@ in cell.ops.mkSetup "users" perms '' mkdir -p $out/etc/pam.d - echo "${user}:x:${uid}:${gid}::" > $out/etc/passwd + echo "${user}:x:${uid}:${gid}::${l.optionalString withHome "/home/${user}"}:${shell}" > $out/etc/passwd echo "${user}:!x:::::::" > $out/etc/shadow echo "${group}:x:${gid}:" > $out/etc/group diff --git a/cells/lib/ops/writeShellEntrypoint.nix b/cells/lib/ops/writeShellEntrypoint.nix index 7136500e..78d3b4d7 100644 --- a/cells/lib/ops/writeShellEntrypoint.nix +++ b/cells/lib/ops/writeShellEntrypoint.nix @@ -44,7 +44,7 @@ }; mkDebugOCI = entrypoint: name: let - debug-banner = nixpkgs.runCommandNoCC "debug-banner" {} '' + debug-banner = nixpkgs.runCommand "debug-banner" {} '' ${nixpkgs.figlet}/bin/figlet -f banner "STD Debug" > $out ''; debug-tools = with nixpkgs.pkgsStatic; [busybox]; diff --git a/dogfood.nix b/dogfood.nix index 11013502..5c38fca3 100644 --- a/dogfood.nix +++ b/dogfood.nix @@ -31,6 +31,7 @@ growOn { # _automation (blockTypes.devshells "devshells") (blockTypes.nixago "nixago") + (blockTypes.containers "containers") # (blockTypes.tasks "tasks") # TODO: implement properly # _tests diff --git a/flake.lock b/flake.lock index bfd21a85..858760d1 100644 --- a/flake.lock +++ b/flake.lock @@ -63,11 +63,26 @@ }, "flake-utils": { "locked": { - "lastModified": 1656928814, - "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", "owner": "numtide", "repo": "flake-utils", - "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { @@ -79,11 +94,11 @@ "mdbook-kroki-preprocessor": { "flake": false, "locked": { - "lastModified": 1655670640, - "narHash": "sha256-JjqdxftHBjABTkOpFl3cWUJtc/KGwkQ3NRWGLjH2oUs=", + "lastModified": 1661755005, + "narHash": "sha256-1TJuUzfyMycWlOQH67LR63/ll2GDZz25I3JfScy/Jnw=", "owner": "JoelCourtney", "repo": "mdbook-kroki-preprocessor", - "rev": "bb6e607437ecc3f22fd9036acee6b797a5b45dbc", + "rev": "93adb5716d035829efed27f65f2f0833a7d3e76f", "type": "github" }, "original": { @@ -92,6 +107,27 @@ "type": "github" } }, + "n2c": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1665039323, + "narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, "nixago": { "inputs": { "flake-utils": [ @@ -120,11 +156,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1658311025, - "narHash": "sha256-GqagY5YmaZB3YaO41kKcQhe5RcpS83wnsW8iCu5Znqo=", + "lastModified": 1665087388, + "narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "cd8d1784506a7c7eb0796772b73437e0b82fad57", + "rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7", "type": "github" }, "original": { @@ -147,9 +183,7 @@ "microvm": [ "blank" ], - "n2c": [ - "blank" - ], + "n2c": "n2c", "nixago": "nixago", "nixpkgs": "nixpkgs", "yants": "yants" @@ -162,11 +196,11 @@ ] }, "locked": { - "lastModified": 1645126146, - "narHash": "sha256-XQ1eg4gzXoc7Tl8iXak1uCt3KnsTyxqPtLE+vOoDnrQ=", + "lastModified": 1660507851, + "narHash": "sha256-BKjq7JnVuUR/xDtcv6Vm9GYGKAblisXrAgybor9hT/s=", "owner": "divnix", "repo": "yants", - "rev": "77df2be1b3cce9f571c6cf451f786b266a6869cc", + "rev": "0b895ca02a8fa72bad50b454cb3e7d8a66407c96", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index ad378829..0e525025 100644 --- a/flake.nix +++ b/flake.nix @@ -11,6 +11,8 @@ inputs.dmerge.url = "github:divnix/data-merge"; inputs.dmerge.inputs.nixlib.follows = "nixpkgs"; inputs.dmerge.inputs.yants.follows = "yants"; + inputs.n2c.url = "github:nlewo/nix2container"; + inputs.n2c.inputs.nixpkgs.follows = "nixpkgs"; inputs.blank.url = "github:divnix/blank"; /* Auxiliar inputs used in builtin libraries or for the dev environment. @@ -31,7 +33,6 @@ # Placeholder inputs that can be overloaded via follows microvm.follows = "blank"; - n2c.follows = "blank"; makes.follows = "blank"; }; outputs = inputs: let