{ 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 = literalDocBook ''
The default configuration imports user-data if applicable and
(modulesPath + "/virtualisation/digital-ocean-config.nix").
'';
description = ''
A path to a configuration file which will be placed at
/etc/nixos/configuration.nix 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 ];
}