diff options
Diffstat (limited to 'nixos/modules/virtualisation/digital-ocean-init.nix')
-rw-r--r-- | nixos/modules/virtualisation/digital-ocean-init.nix | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/nixos/modules/virtualisation/digital-ocean-init.nix b/nixos/modules/virtualisation/digital-ocean-init.nix new file mode 100644 index 00000000000..02f4de009fa --- /dev/null +++ b/nixos/modules/virtualisation/digital-ocean-init.nix @@ -0,0 +1,95 @@ +{ config, pkgs, lib, ... }: +with lib; +let + cfg = config.virtualisation.digitalOcean; + defaultConfigFile = pkgs.writeText "digitalocean-configuration.nix" '' + { modulesPath, lib, ... }: + { + imports = lib.optional (builtins.pathExists ./do-userdata.nix) ./do-userdata.nix ++ [ + (modulesPath + "/virtualisation/digital-ocean-config.nix") + ]; + } + ''; +in { + options.virtualisation.digitalOcean.rebuildFromUserData = mkOption { + type = types.bool; + default = true; + example = true; + description = "Whether to reconfigure the system from Digital Ocean user data"; + }; + options.virtualisation.digitalOcean.defaultConfigFile = mkOption { + type = types.path; + default = defaultConfigFile; + defaultText = '' + The default configuration imports user-data if applicable and + <literal>(modulesPath + "/virtualisation/digital-ocean-config.nix")</literal>. + ''; + description = '' + A path to a configuration file which will be placed at + <literal>/etc/nixos/configuration.nix</literal> and be used when switching to + a new configuration. + ''; + }; + + config = { + systemd.services.digitalocean-init = mkIf cfg.rebuildFromUserData { + description = "Reconfigure the system from Digital Ocean userdata on startup"; + wantedBy = [ "network-online.target" ]; + unitConfig = { + ConditionPathExists = "!/etc/nixos/do-userdata.nix"; + After = [ "digitalocean-metadata.service" "network-online.target" ]; + Requires = [ "digitalocean-metadata.service" ]; + X-StopOnRemoval = false; + }; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + restartIfChanged = false; + path = [ pkgs.jq pkgs.gnused pkgs.gnugrep pkgs.systemd config.nix.package config.system.build.nixos-rebuild ]; + environment = { + HOME = "/root"; + NIX_PATH = concatStringsSep ":" [ + "/nix/var/nix/profiles/per-user/root/channels/nixos" + "nixos-config=/etc/nixos/configuration.nix" + "/nix/var/nix/profiles/per-user/root/channels" + ]; + }; + script = '' + set -e + echo "attempting to fetch configuration from Digital Ocean user data..." + userData=$(mktemp) + if jq -er '.user_data' /run/do-metadata/v1.json > $userData; then + # If the user-data looks like it could be a nix expression, + # copy it over. Also, look for a magic three-hash comment and set + # that as the channel. + if nix-instantiate --parse $userData > /dev/null; then + channels="$(grep '^###' "$userData" | sed 's|###\s*||')" + printf "%s" "$channels" | while read channel; do + echo "writing channel: $channel" + done + + if [[ -n "$channels" ]]; then + printf "%s" "$channels" > /root/.nix-channels + nix-channel --update + fi + + echo "setting configuration from Digital Ocean user data" + cp "$userData" /etc/nixos/do-userdata.nix + if [[ ! -e /etc/nixos/configuration.nix ]]; then + install -m0644 ${cfg.defaultConfigFile} /etc/nixos/configuration.nix + fi + else + echo "user data does not appear to be a Nix expression; ignoring" + exit + fi + + nixos-rebuild switch + else + echo "no user data is available" + fi + ''; + }; + }; + meta.maintainers = with maintainers; [ arianvp eamsden ]; +} |