From f72413e14c8ec430a145e003cb43d316de81de97 Mon Sep 17 00:00:00 2001 From: pacien Date: Wed, 9 Nov 2022 17:06:05 +0100 Subject: lib.mkSandboxSystem: add function to generate vm --- flake.nix | 1 + lib/mk-sandbox-system.nix | 88 ++++++++++++++++++++++++++++++++++++++++++++ readme.md | 93 +++++++++++++++++++++++++++++++++++------------ 3 files changed, 158 insertions(+), 24 deletions(-) create mode 100644 lib/mk-sandbox-system.nix diff --git a/flake.nix b/flake.nix index 57a6896..3b09a54 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,7 @@ outputs = { self }: { lib = { mkDevShell = import ./lib/mk-dev-shell.nix; + mkSandboxSystem = import ./lib/mk-sandbox-system.nix; }; }; } diff --git a/lib/mk-sandbox-system.nix b/lib/mk-sandbox-system.nix new file mode 100644 index 0000000..6135a01 --- /dev/null +++ b/lib/mk-sandbox-system.nix @@ -0,0 +1,88 @@ +{ nixpkgs +, system +, name ? "sandbox" +, user ? "dummy" +, config ? { } +}: + +with nixpkgs.lib; + +let + pkgs = import nixpkgs { inherit system; }; + +in rec { + + nixosConfigurations.${name} = nixosSystem { + inherit system; + + modules = [ + (nixpkgs + "/nixos/modules/profiles/minimal.nix") + { environment.noXlibs = false; } # avoid mass rebuild + + (nixpkgs + "/nixos/modules/profiles/qemu-guest.nix") + (nixpkgs + "/nixos/modules/virtualisation/qemu-vm.nix") + + ({ config, lib, pkgs, ... }: { + + system.stateVersion = mkDefault "22.05"; + + networking = { + hostName = name; + firewall.enable = mkDefault false; + }; + + users.users.${user} = { + isNormalUser = mkDefault true; + password = mkDefault ""; + extraGroups = mkDefault [ "wheel" ]; + }; + + security.sudo.wheelNeedsPassword = mkDefault false; + + services.getty = { + autologinUser = mkDefault user; + helpLine = mkDefault '' + Press to terminate the virtual machine. + The working directory on the host is mounted to /mnt. + ''; + }; + + virtualisation = { + graphics = mkDefault false; + diskImage = mkDefault "$(mktemp).qcow2"; + + sharedDirectories.host = { + source = "$SHARED_CWD"; + target = "/mnt"; + }; + + # Uncomment when this is merged: + # https://github.com/NixOS/nixpkgs/pull/200225 + #restrictNetwork = mkDefault true; + }; + }) + + config + ]; + }; + + packages.${name} = nixosConfigurations.${name}.config.system.build.vm; + + apps.${name} = { + type = "app"; + program = toString (pkgs.writeShellScript "sandbox-vm" '' + # Isolate from network + # Stopgap solution until this is merged: + # https://github.com/NixOS/nixpkgs/pull/200225 + QEMU_NET_OPTS="restrict=yes,''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS}" + export QEMU_NET_OPTS + + # Save current directory for mounting in VM + SHARED_CWD=$PWD + export SHARED_CWD + + ${packages.${name}}/bin/run-${name}-vm + ''); + }; + +} diff --git a/readme.md b/readme.md index e4ba8dd..853c3cc 100644 --- a/readme.md +++ b/readme.md @@ -23,36 +23,81 @@ Functions documentation provided as comments below. outputs = { self, nixpkgs, flake-utils, flaky-utils }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; - in { + in pkgs.lib.fold pkgs.lib.recursiveUpdate { } [ + + { + # Convenience development shell providing some tools. + # + # The binaries made available and the environment variable set are + # printed when entering the shell. + # + # The user's default shell is used instead of Bash (sacrifying a bit of + # reproducibility for convenience). + # + devShell = flaky-utils.lib.mkDevShell { + inherit pkgs; + + tools = with pkgs; [ + postgresql_14 + pgcli + ]; + + envVars = rec { + PGDATA = "$PWD/development_database/pgdata"; + PGHOST = "$PWD/development_database"; + PGPORT = "5432"; + PGDATABASE = "app"; + DATABASE_URL = "postgresql:///${PGDATABASE}?host=${PGHOST}"; + }; + + shell = null; + }; + } - # Convenience development shell providing some tools. + # Convenience isolated environment using a QEMU virtual machine. # - # The binaries made available and the environment variable set are printed - # when entering the shell. + # This defines a triplet of nixosConfiguration, package and app with the + # given name, so that the virtual machine can be launched using + # a command like `nix run .#sandbox`. # - # The user's default shell is used instead of Bash (sacrifying a bit of - # reproducibility for convenience). + # By default, the VM is launched in the current console without a graphical + # interface, dropping to a shell for the default dummy user within. # - devShell = flaky-utils.lib.mkDevShell { - inherit pkgs; - - tools = with pkgs; [ - postgresql_14 - pgcli - ]; - - envVars = rec { - PGDATA = "$PWD/development_database/pgdata"; - PGHOST = "$PWD/development_database"; - PGPORT = "5432"; - PGDATABASE = "app"; - DATABASE_URL = "postgresql:///${PGDATABASE}?host=${PGHOST}"; - }; + # The current working directory from which the Flake is run is mounted and + # made available within the virtual machine in /mnt. The root filesystem + # is ephemeral (written to a temporary file in /tmp). + # + # The virtual machine's network is isolated by default: it cannot access + # the Internet nor the host's local network. Ports may nevertheless be + # forwarded explicitly from host to guest and vice-versa. + # + (flaky-utils.lib.mkSandboxSystem { + inherit nixpkgs system; + + name = "sandbox"; + user = "dummy"; - shell = null; - }; + config = { + virtualisation.forwardPorts = [ + { from = "host"; host.port = 5432; guest.port = 5432; } # postgres + ]; + + services.postgresql = { + enable = true; + enableTCPIP = true; + + authentication = '' + host all all 0.0.0.0/0 trust + ''; + + initialScript = pkgs.writeText "init.sql" '' + create role dummy login superuser; + ''; + }; + }; + }) - }); + ]); } ``` -- cgit v1.2.3