From a2e3eee48fc5c6721f9aad8bd521e7c38600c8e0 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 13 Jan 2023 02:13:36 +0100 Subject: [PATCH] CmdSystem: init --- src/nix/system-activate.md | 8 ++ src/nix/system-apply.md | 15 +++ src/nix/system-boot.md | 16 +++ src/nix/system-build.md | 7 ++ src/nix/system.cc | 203 +++++++++++++++++++++++++++++++++++++ src/nix/system.md | 7 ++ 6 files changed, 256 insertions(+) create mode 100644 src/nix/system-activate.md create mode 100644 src/nix/system-apply.md create mode 100644 src/nix/system-boot.md create mode 100644 src/nix/system-build.md create mode 100644 src/nix/system.cc create mode 100644 src/nix/system.md diff --git a/src/nix/system-activate.md b/src/nix/system-activate.md new file mode 100644 index 000000000..cdf842854 --- /dev/null +++ b/src/nix/system-activate.md @@ -0,0 +1,8 @@ +R""( + +# Description + +This command activates NixOS configurations. + +)"" + diff --git a/src/nix/system-apply.md b/src/nix/system-apply.md new file mode 100644 index 000000000..df6c82167 --- /dev/null +++ b/src/nix/system-apply.md @@ -0,0 +1,15 @@ +R""( + +# Description + +This command activates NixOS configurations and sets it as the default boot configuration. + +The `profile` parameter is used to specify the system profile to use. + +The default system profile is `/nix/var/nix/profiles/system`. + +A system profile named `hello` would be located at `/nix/var/nix/profiles/system-profiles/hello`. + +)"" + + diff --git a/src/nix/system-boot.md b/src/nix/system-boot.md new file mode 100644 index 000000000..3214baa9f --- /dev/null +++ b/src/nix/system-boot.md @@ -0,0 +1,16 @@ +R""( + +# Description + +This command sets the given NixOS configuration as the default boot configuration. It will be activated on the next boot. + +The `profile` parameter is used to specify the system profile to use. + +The default system profile is `/nix/var/nix/profiles/system`. + +A system profile named `hello` would be located at `/nix/var/nix/profiles/system-profiles/hello`. + +)"" + + + diff --git a/src/nix/system-build.md b/src/nix/system-build.md new file mode 100644 index 000000000..2040dcf20 --- /dev/null +++ b/src/nix/system-build.md @@ -0,0 +1,7 @@ +R""( + +# Description + +This command builds NixOS configurations. The default attribute name is the current system hostname. + +)"" diff --git a/src/nix/system.cc b/src/nix/system.cc new file mode 100644 index 000000000..421cc9071 --- /dev/null +++ b/src/nix/system.cc @@ -0,0 +1,203 @@ +#include "command.hh" +#include "activatables.hh" +#include "progress-bar.hh" + +using namespace nix; + +void executePrivileged(std::string program, Strings args) { + stopProgressBar(); + restoreProcessContext(); + args.push_front(program); + auto exe = program; + auto privCmds = Strings { + "doas", + "sudo" + }; + bool isRoot = getuid() == 0; + for (auto privCmd : privCmds) { + if(!isRoot) { + args.push_front(privCmd); + exe = privCmd; + } + execvp(exe.c_str(), stringsToCharPtrs(args).data()); + if(!isRoot) + args.pop_front(); + } + + throw SysError("unable to execute privilege elevation helper (tried %s)", concatStringsSep(", ", privCmds)); +} + +struct SystemCommand : ActivatableCommand +{ + SystemCommand() + : ActivatableCommand("config.system.build.toplevel") + {} + + Strings getDefaultFlakeAttrPaths() override + { + char hostname[1024]; + hostname[1023] = '\0'; + gethostname(hostname, 1024); + Strings res{ + "nixosConfigurations." + std::string(hostname), + }; + return res; + } + + Strings getDefaultFlakeAttrPathPrefixes() override + { + Strings res{"nixosConfigurations."}; + return res; + } + +}; + +struct SystemActivationCommand : ActivationCommand, MixProfile +{ + SystemActivationCommand(std::string activationType, std::string selfCommandName) + : ActivationCommand(activationType, selfCommandName) + { } + + void run(nix::ref store) override + { + auto out = buildActivatable(store); + + if (getuid() != 0) { + Strings args { + "system", selfCommandName, + store->printStorePath(out) + }; + if (profile) { + args.push_back("--profile"); + args.push_back(profile.value()); + } + executePrivileged(getSelfExe().value_or("nix"), args); + } else { + if (!profile) { + profile = settings.nixStateDir + "/profiles/system"; + } else { + auto systemProfileBase = settings.nixStateDir + "/profiles/system-profiles"; + if (!pathExists(systemProfileBase)) { + createDirs(systemProfileBase); + } + profile = systemProfileBase + "/" + profile.value(); + } + updateProfile(out); + executePrivileged(profile.value() + "/bin/switch-to-configuration", Strings{activationType}); + } + } +}; + +struct CmdSystemBuild : ActivatableBuildCommand +{ + std::string description() override + { + return "build a NixOS system configuration"; + } + + std::string doc() override + { + return + #include "system-build.md" + ; + } +}; + +struct CmdSystemActivate : SystemCommand, MixDryRun +{ + CmdSystemActivate() + { + } + + std::string description() override + { + return "activate a NixOS system configuration"; + } + + std::string doc() override + { + return + #include "system-activate.md" + ; + } + void run(nix::ref store) override + { + auto out = buildActivatable(store); + + executePrivileged(store->printStorePath(out) + "/bin/switch-to-configuration", Strings{dryRun ? "dry-activate" : "test"}); + } +}; + +struct CmdSystemApply : SystemActivationCommand +{ + CmdSystemApply() : SystemActivationCommand("switch", "apply") + { + } + + std::string description() override + { + return "activate a NixOS system configuration and make it the default boot configuration"; + } + + std::string doc() override + { + return + #include "system-apply.md" + ; + } +}; + +struct CmdSystemBoot : SystemActivationCommand +{ + CmdSystemBoot() : SystemActivationCommand("boot","boot") + { + } + + std::string description() override + { + return "make a NixOS configuration the default boot configuration"; + } + + std::string doc() override + { + return + #include "system-boot.md" + ; + } +}; + +struct CmdSystem : NixMultiCommand +{ + CmdSystem() + : MultiCommand({ + {"build", []() { return make_ref(); }}, + {"activate", []() { return make_ref(); }}, + {"apply", []() { return make_ref(); }}, + {"boot", []() { return make_ref(); }}, + }) + { + } + + std::string description() override + { + return "manage NixOS systems"; + } + + std::string doc() override + { + return + #include "system.md" + ; + } + + void run() override + { + if (!command) + throw UsageError("'nix system' requires a sub-command."); + settings.requireExperimentalFeature(Xp::NixCommand); + command->second->prepare(); + command->second->run(); + } +}; + +static auto rCmdSystem = registerCommand("system"); diff --git a/src/nix/system.md b/src/nix/system.md new file mode 100644 index 000000000..de2b64647 --- /dev/null +++ b/src/nix/system.md @@ -0,0 +1,7 @@ +R""( + +# Description + +This is a group of commands for managing NixOS system configurations. + +)""