diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 2cee8cb502aa..e0d614e61bfb 100755 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -309,6 +309,7 @@ ./services/security/haveged.nix ./services/security/tor.nix ./services/security/torsocks.nix + ./services/system/cloud-init.nix ./services/system/dbus.nix ./services/system/kerberos.nix ./services/system/nscd.nix diff --git a/nixos/modules/services/system/cloud-init.nix b/nixos/modules/services/system/cloud-init.nix new file mode 100644 index 000000000000..0ef31ef8a8b9 --- /dev/null +++ b/nixos/modules/services/system/cloud-init.nix @@ -0,0 +1,152 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.services.cloud-init; + path = with pkgs; [ cloud-init nettools utillinux e2fsprogs shadow dmidecode openssh ]; + configFile = pkgs.writeText "cloud-init.cfg" '' +users: + - root + +disable_root: false +preserve_hostname: false + +cloud_init_modules: + - migrator + - seed_random + - bootcmd + - write-files + - growpart + - resizefs + - set_hostname + - update_hostname + - update_etc_hosts + - ca-certs + - rsyslog + - users-groups + +cloud_config_modules: + - emit_upstart + - disk_setup + - mounts + - ssh-import-id + - set-passwords + - timezone + - disable-ec2-metadata + - runcmd + - ssh + +cloud_final_modules: + - rightscale_userdata + - scripts-vendor + - scripts-per-once + - scripts-per-boot + - scripts-per-instance + - scripts-user + - ssh-authkey-fingerprints + - keys-to-console + - phone-home + - final-message + - power-state-change +''; +in +{ + options = { + + services.cloud-init = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable the cloud-init service. This services reads + configuration metadata in a cloud environment and configures + the machine according to this metadata. + + This configuration is not completely compatible with the + NixOS way of doing configuration, as configuration done by + cloud-init might be overriden by a subsequent nixos-rebuild + call. However, some parts of cloud-init fall outside of + NixOS's responsibility, like filesystem resizing and ssh + public key provisioning, and cloud-init is useful for that + parts. Thus, be wary that using cloud-init in NixOS might + come as some cost. + ''; + }; + + }; + + }; + + config = mkIf cfg.enable { + + systemd.services.cloud-init-local = + { description = "Initial cloud-init job (pre-networking)"; + wantedBy = [ "multi-user.target" ]; + wants = [ "local-fs.target" ]; + after = [ "local-fs.target" ]; + path = path; + serviceConfig = + { Type = "oneshot"; + ExecStart = "${pkgs.cloud-init}/bin/cloud-init -f ${configFile} init --local"; + RemainAfterExit = "yes"; + TimeoutSec = "0"; + StandardOutput = "journal+console"; + }; + }; + + systemd.services.cloud-init = + { description = "Initial cloud-init job (metadata service crawler)"; + wantedBy = [ "multi-user.target" ]; + wants = [ "local-fs.target" "cloud-init-local.service" "sshd.service" "sshd-keygen.service" ]; + after = [ "local-fs.target" "network.target" "cloud-init-local.service" ]; + before = [ "sshd.service" "sshd-keygen.service" ]; + requires = [ "network.target "]; + path = path; + serviceConfig = + { Type = "oneshot"; + ExecStart = "${pkgs.cloud-init}/bin/cloud-init -f ${configFile} init"; + RemainAfterExit = "yes"; + TimeoutSec = "0"; + StandardOutput = "journal+console"; + }; + }; + + systemd.services.cloud-config = + { description = "Apply the settings specified in cloud-config"; + wantedBy = [ "multi-user.target" ]; + wants = [ "network.target" ]; + after = [ "network.target" "syslog.target" "cloud-config.target" ]; + + path = path; + serviceConfig = + { Type = "oneshot"; + ExecStart = "${pkgs.cloud-init}/bin/cloud-init -f ${configFile} modules --mode=config"; + RemainAfterExit = "yes"; + TimeoutSec = "0"; + StandardOutput = "journal+console"; + }; + }; + + systemd.services.cloud-final = + { description = "Execute cloud user/final scripts"; + wantedBy = [ "multi-user.target" ]; + wants = [ "network.target" ]; + after = [ "network.target" "syslog.target" "cloud-config.service" "rc-local.service" ]; + requires = [ "cloud-config.target" ]; + path = path; + serviceConfig = + { Type = "oneshot"; + ExecStart = "${pkgs.cloud-init}/bin/cloud-init -f ${configFile} modules --mode=final"; + RemainAfterExit = "yes"; + TimeoutSec = "0"; + StandardOutput = "journal+console"; + }; + }; + + systemd.targets.cloud-config = + { description = "Cloud-config availability"; + requires = [ "cloud-init-local.service" "cloud-init.service" ]; + }; + }; +} diff --git a/pkgs/tools/virtualization/cloud-init/default.nix b/pkgs/tools/virtualization/cloud-init/default.nix new file mode 100644 index 000000000000..48eb68242e1e --- /dev/null +++ b/pkgs/tools/virtualization/cloud-init/default.nix @@ -0,0 +1,34 @@ +{ lib, pythonPackages, fetchurl }: + +let version = "0.7.6"; + +in pythonPackages.buildPythonPackage rec { + name = "cloud-init-0.7.6"; + namePrefix = ""; + + src = fetchurl { + url = "https://launchpad.net/cloud-init/trunk/${version}/+download/cloud-init-${version}.tar.gz"; + sha256 = "1mry5zdkfaq952kn1i06wiggc66cqgfp6qgnlpk0mr7nnwpd53wy"; + }; + + preBuild = '' + patchShebangs ./tools + + substituteInPlace setup.py \ + --replace /usr $out \ + --replace /etc $out/etc \ + --replace /lib/systemd $out/lib/systemd \ + ''; + + pythonPath = with pythonPackages; [ cheetah jinja2 prettytable + oauth pyserial configobj pyyaml argparse requests jsonpatch ]; + + setupPyInstallFlags = ["--init-system systemd"]; + + meta = { + homepage = http://cloudinit.readthedocs.org; + description = "provides configuration and customization of cloud instance"; + maintainers = [ lib.maintainers.madjar ]; + platforms = lib.platforms.all; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index bf5777cd0c9b..14af4411bc19 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -665,6 +665,8 @@ let ccnet = callPackage ../tools/networking/ccnet { }; + cloud-init = callPackage ../tools/virtualization/cloud-init { }; + consul = callPackage ../servers/consul { inherit ruby rubyLibs; }; diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index c334cb2ee63c..6f9051405f67 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -2755,6 +2755,42 @@ let }; }; + jsonpatch = buildPythonPackage rec { + name = "jsonpatch-1.8"; + + src = pkgs.fetchurl { + url = "https://pypi.python.org/packages/source/j/jsonpatch/jsonpatch-1.8.tar.gz"; + sha256 = "0xhp6prvk219vnzixbj231wymd458nqbnmsf5fn4252092prvig5"; + }; + + propagatedBuildInputs = with self; [ six jsonpointer ]; + + meta = { + description = "Apply JSON-Patches (RFC 6902)"; + homepage = "https://github.com/stefankoegl/python-json-patch"; + license = stdenv.lib.licenses.bsd3; + platforms = stdenv.lib.platforms.all; + }; + }; + + jsonpointer = buildPythonPackage rec { + name = "jsonpointer-1.4"; + + src = pkgs.fetchurl { + url = "https://pypi.python.org/packages/source/j/jsonpointer/jsonpointer-1.4.tar.gz"; + sha256 = "1d0555smqwdbi0nm48hyqzywb9m2jlz5izgv56ll3zk7viz3b7fb"; + }; + + #propagatedBuildInputs = with self; [ six jsonpointer ]; + + meta = { + description = "Identify specific nodes in a JSON document (RFC 6901)"; + homepage = "https://github.com/stefankoegl/python-json-pointer"; + license = stdenv.lib.licenses.bsd3; + platforms = stdenv.lib.platforms.all; + }; + }; + jsonwatch = buildPythonPackage rec { name = "jsonwatch-0.2.0"; @@ -6136,6 +6172,22 @@ let }; }; + oauth = buildPythonPackage (rec { + name = "oauth-1.0.1"; + + src = pkgs.fetchurl { + url = "http://pypi.python.org/packages/source/o/oauth/oauth-1.0.1.tar.gz"; + sha256 = "0pdgi35hczsslil4890xqawnbpdazkgf2v1443847h5hy2gq2sg7"; + }; + + meta = { + homepage = "http://code.google.com/p/oauth"; + description = "Library for OAuth version 1.0a."; + license = licenses.mit; + platforms = stdenv.lib.platforms.all; + }; + }); + oauth2 = buildPythonPackage (rec { name = "oauth2-1.5.211"; disabled = isPy3k;