diff --git a/nixos/infrastructure/default.nix b/nixos/infrastructure/default.nix index 239a3d2ae..80f711f4c 100644 --- a/nixos/infrastructure/default.nix +++ b/nixos/infrastructure/default.nix @@ -4,6 +4,7 @@ imports = [ ./container.nix + ./dev-vm.nix ./testing.nix ./flyingcircus-physical.nix ./flyingcircus-virtual.nix @@ -12,7 +13,7 @@ options = with lib; { flyingcircus.infrastructureModule = mkOption { - type = types.enum [ "testing" "flyingcircus" "flyingcircus-physical" "virtualbox" "container" ]; + type = types.enum [ "testing" "flyingcircus" "flyingcircus-physical" "virtualbox" "container" "dev-vm" ]; default = "testing"; example = "flyingcircus"; description = "Load config module for specific infrastructure."; diff --git a/nixos/infrastructure/dev-vm.nix b/nixos/infrastructure/dev-vm.nix new file mode 100644 index 000000000..7587c5f28 --- /dev/null +++ b/nixos/infrastructure/dev-vm.nix @@ -0,0 +1,213 @@ +{ config, lib, ... }: + +let + fclib = config.fclib; + + # Only check "visible" roles, skipping roles that are marked as removed by + # `mkRemovedOptionModule` or manually set to `visible = false`. + # The `tryEval` is needed because visiting the role option throws an error if + # the option is declared by `mkRemovedOptionModule`. + visibleFCRoles = (lib.filterAttrs + (n: v: (builtins.tryEval v.enable.visible or true).value) + config.flyingcircus.roles); +in +{ + config = lib.mkMerge [ + (lib.mkIf (config.flyingcircus.infrastructureModule == "dev-vm") { + boot = { + initrd.kernelModules = [ + "virtio_blk" + "virtio_console" + "virtio_net" + "virtio_pci" + "virtio_rng" + "virtio_scsi" + "i6300esb" + ]; + + kernelParams = [ + "console=ttyS0" + "nosetmode" + ]; + + loader.grub = { + device = "/dev/disk/device-by-alias/root"; + fsIdentifier = "provided"; + gfxmodeBios = "text"; + }; + growPartition = true; + }; + + fileSystems."/" = { + device = "/dev/disk/by-label/root"; + autoResize = true; + fsType = "xfs"; + }; + + services.udev.extraRules = '' + # GRUB boot device should be device-by-alias/root + SUBSYSTEM=="block", KERNEL=="vda", SYMLINK+="disk/device-by-alias/root" + ''; + + networking = { + hostName = fclib.mkPlatform config.flyingcircus.enc.name; + + firewall.allowedTCPPorts = [ 80 ]; + firewall.allowPing = true; + }; + + flyingcircus.agent.enable = false; + flyingcircus.agent.collect-garbage = lib.mkForce false; + + services.timesyncd.servers = [ "pool.ntp.org" ]; + services.telegraf.enable = false; + + systemd.services."network-addresses-ethsrv" = { + wantedBy = [ "multi-user.target" ]; + script = '' + echo "Ready." + ''; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + }; + + environment.sessionVariables = { NIX_REMOTE = "daemon"; }; + + services.mongodb.bind_ip = "[::]"; + + services.postgresql.settings.listen_addresses = lib.mkOverride 20 "0.0.0.0,::"; + services.postgresql.settings.fsync = "off"; + services.postgresql.settings.full_page_writes = "off"; + services.postgresql.settings.synchronous_commit = "off"; + + flyingcircus.roles.antivirus.listenAddresses = [ "[::]" ]; + + flyingcircus.roles.coturn.hostName = config.networking.hostName; + flyingcircus.roles.coturn.config.listening-ips = [ "[::]" ]; + + flyingcircus.roles.memcached.listenAddresses = [ "0.0.0.0" "[::]" ]; + + flyingcircus.roles.mailserver.smtpBind4 = [ "127.0.0.1" ]; + flyingcircus.roles.mailserver.smtpBind6 = [ "::1" ]; + flyingcircus.roles.mailserver.explicitSmtpBind = false; + + flyingcircus.roles.mysql.listenAddresses = [ "::" ]; + + flyingcircus.roles.webproxy.listenAddresses = [ "[::]" ]; + + flyingcircus.services.nginx.defaultListenAddresses = [ "0.0.0.0" "[::]" ]; + flyingcircus.services.redis.listenAddresses = [ "[::]" ]; + flyingcircus.services.rabbitmq.listenAddress = "::"; + + services.mysql.settings.mysqld = { + # We don't really care about the data and this speeds up things. + innodb_flush_method = "nosync"; + + innodb_buffer_pool_size = "200M"; + innodb_log_buffer_size = "64M"; + innodb_file_per_table = 1; + innodb_read_io_threads = 1; + innodb_write_io_threads = 1; + # Percentage. Probably needs local tuning depending on the workload. + innodb_change_buffer_max_size = 50; + innodb_doublewrite = 1; + innodb_log_file_size = "64M"; + innodb_log_files_in_group = 2; + }; + + services.redis.bind = lib.mkForce "0.0.0.0 ::"; + + # This is the insecure key pair to allow bootstrapping containers. + # -----BEGIN OPENSSH PRIVATE KEY----- + # b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW + # QyNTUxOQAAACBnO1dnNsxT0TJfP4Jgb9fzBJXRLiWrvIx44cftqs4mLAAAAJjYNRR+2DUU + # fgAAAAtzc2gtZWQyNTUxOQAAACBnO1dnNsxT0TJfP4Jgb9fzBJXRLiWrvIx44cftqs4mLA + # AAAEDKN3GvoFkLLQdFN+Blk3y/+HQ5rvt7/GALRAWofc/LFGc7V2c2zFPRMl8/gmBv1/ME + # ldEuJau8jHjhx+2qziYsAAAAEHJvb3RAY3QtZGlyLWRldjIBAgMEBQ== + # -----END OPENSSH PRIVATE KEY----- + + # ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGc7V2c2zFPRMl8/gmBv1/MEldEuJau8jHjhx+2qziYs root@ct-dir-dev2 + + users.users.root.password = ""; + + time.timeZone = fclib.mkPlatformOverride "Europe/Berlin"; + + flyingcircus.encServices = [ + { service = "nfs_rg_share-server"; + address = config.networking.hostName; + } + ]; + + flyingcircus.encServiceClients = [ + { service = "nfs_rg_share-server"; + node = config.networking.hostName; + } + ]; + + flyingcircus.users.userData = [ + { class = "human"; + gid = 100; + home_directory = "/home/developer"; + id = 1000; + login_shell = "/bin/bash"; + name = "Developer"; + # password: vagrant + password = "$5$xS9kX8R5VNC0g$ZS7QkUYTk/61dUyUgq9r0jLAX1NbiScBT5v1PODz4UC"; + permissions = { container = [ "admins" "login" "manager" "sudo-srv" ]; }; + ssh_pubkey = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGc7V2c2zFPRMl8/gmBv1/MEldEuJau8jHjhx+2qziYs root@ct-dir-dev2" + ]; + uid = "developer";} + { class = "service"; + gid = 100; + home_directory = "/srv/s-dev"; + id = 1001; + login_shell = "/bin/bash"; + password = "*"; + name = "s-dev"; + ssh_pubkey = [] ; + permissions = { container = []; }; + uid = "s-dev"; } ]; + + flyingcircus.users.permissions = [ + { description = "commit to VCS repository"; + id = 2029; + name = "code"; } + { description = "perform interactive or web logins (e.g., ssh, monitoring)"; + id = 502; + name = "login"; } + { description = "access web statistics"; + id = 2046; + name = "stats"; } + { description = "sudo to service user"; + id = 2028; + name = "sudo-srv"; } + { description = "sudo to root"; + id = 10; + name = "wheel"; } + { description = "Manage users of RG"; + id = 2272; + name = "manager"; } ]; + + users.users.developer = { + # Make the human user a service user, too so that we can place stuff in + # /etc/local/nixos for provisioning. + extraGroups = [ "service" "login" ]; + }; + + flyingcircus.passwordlessSudoRules = [ + { # Grant unrestricted access to developer + commands = [ "ALL" ]; + users = [ "developer" ]; + } + ]; + + system.activationScripts.relaxHomePermissions = lib.stringAfter [ "users" ] '' + mkdir -p /nix/var/nix/profiles/per-user/s-dev + chown s-dev: /nix/var/nix/profiles/per-user/s-dev + ''; + }) ]; + +} diff --git a/nixos/roles/default.nix b/nixos/roles/default.nix index f093f08b9..128a635a9 100644 --- a/nixos/roles/default.nix +++ b/nixos/roles/default.nix @@ -1,14 +1,18 @@ { config, lib, ... }: - -with builtins; - let + # Map list of roles to a list of attribute sets enabling each role. + # Turn the list of role names (["a", "b"]) into an attribute set + # ala { = { enable = true;}; } + roleSet = lib.listToAttrs ( + map (role: { name = role; value = { enable = true; }; }) + config.flyingcircus.active-roles); fclib = config.fclib; in { imports = with lib; [ ./antivirus.nix ./backyserver.nix ./coturn.nix + ./consul ./docker.nix ./ceph/mon.nix ./ceph/osd.nix @@ -17,40 +21,37 @@ in { ./external_net ./elasticsearch.nix ./gitlab.nix + ./graylog.nix ./jitsi + ./kibana.nix ./k3s + ./kvm.nix ./lamp.nix + ./loghost ./mailout.nix ./mailserver.nix - ./matomo.nix ./memcached.nix ./mongodb.nix ./mysql.nix ./nfs.nix ./nginx.nix - ./opensearch.nix - ./opensearch_dashboards.nix ./postgresql.nix ./rabbitmq.nix ./redis.nix + ./sensuserver.nix ./servicecheck.nix - ./slurm ./statshost ./webdata_blackbee.nix ./webgateway.nix ./webproxy.nix - # Removed - (mkRemovedOptionModule [ "flyingcircus" "roles" "graylog" "enable" ] "Last platform version that supported graylog/loghost was 22.05.") - (mkRemovedOptionModule [ "flyingcircus" "roles" "loghost" "enable" ] "Last platform version that supported graylog/loghost was 22.05.") - (mkRemovedOptionModule [ "flyingcircus" "roles" "loghost-location" "enable" ] "Last platform version that supported graylog/loghost was 22.05.") - (mkRemovedOptionModule [ "flyingcircus" "roles" "mysql" "rootPassword" ] "Change the root password via MySQL and modify secret files.") - (mkRemovedOptionModule [ "flyingcircus" "roles" "statshost" "enable" ] "Use flyingcircus.roles.statshost-global.enable instead.") - (mkRemovedOptionModule [ "flyingcircus" "roles" "statshostproxy" "enable" ] "Use flyingcircus.roles.statshost-location-proxy.enable instead.") - - # Renamed - (mkRenamedOptionModule [ "flyingcircus" "roles" "elasticsearch" "dataDir" ] [ "services" "elasticsearch" "dataDir" ]) + (mkRemovedOptionModule [ "flyingcircus" "roles" "mysql" "rootPassword" ] "Change the root password via MySQL and modify secret files") + (mkRenamedOptionModule [ "flyingcircus" "roles" "rabbitmq38" ] [ "flyingcircus" "roles" "rabbitmq" ]) + (mkRenamedOptionModule [ "flyingcircus" "roles" "redis4" ] [ "flyingcircus" "roles" "redis" ]) + (mkRenamedOptionModule [ "flyingcircus" "roles" "statshost" "enable" ] [ "flyingcircus" "roles" "statshost-global" "enable" ]) (mkRenamedOptionModule [ "flyingcircus" "roles" "statshost" "globalAllowedMetrics" ] [ "flyingcircus" "roles" "statshost-global" "allowedMetricPrefixes" ]) + (mkRenamedOptionModule [ "flyingcircus" "roles" "statshostproxy" ] [ "flyingcircus" "roles" "statshost-location-proxy" ]) + (mkRenamedOptionModule [ "flyingcircus" "roles" "kibana" "enable" ] [ "flyingcircus" "roles" "kibana6" "enable" ]) ]; options = { @@ -61,17 +62,7 @@ in { }; config = { - # Map list of roles to a list of attribute sets enabling each role. - # Turn the list of role names (["a", "b"]) into an attribute set - # ala { = { enable = true;}; } - # Roles are ignored if the initial run marker of fc-agent is still present - # to get the new system ready for SSH connections more quickly and reliably. - flyingcircus.roles = - (lib.optionalAttrs - (!pathExists "/etc/nixos/fc_agent_initial_run") - (lib.listToAttrs ( - map (role: { name = role; value = { enable = true; }; }) - config.flyingcircus.active-roles))); + flyingcircus.roles = roleSet; }; } diff --git a/nixos/roles/devhost/container.nix b/nixos/roles/devhost/container.nix new file mode 100644 index 000000000..fee66df8e --- /dev/null +++ b/nixos/roles/devhost/container.nix @@ -0,0 +1,309 @@ +{ config, lib, pkgs, ... }: + +with builtins; + +let + cfg = config.flyingcircus.roles.devhost; + fclib = config.fclib; + + testedRoles = attrNames (lib.filterAttrs (n: v: v.supportsContainers or true) + config.flyingcircus.roles); + excludedRoles = attrNames + (lib.filterAttrs (n: v: !(v.supportsContainers or true)) + config.flyingcircus.roles); + + containersFromDir = dir: + with lib; + (map (filename: fromJSON (readFile "${dir}/${filename}")) + (filter (filename: hasSuffix ".json" filename) + (attrNames (readDirMaybe dir)))); + + allContainers = (containersFromDir "/etc/devhost") + ++ (containersFromDir "/etc/devserver"); + + enabledContainers = with lib; + (filter (container: container.enabled or true) allContainers); + + container_script = pkgs.writeShellScriptBin "fc-build-dev-container" '' + #!/bin/sh + set -ex + + action=''${1?need to specify action} + container=''${2?need to specify container name} + + manage_alias_proxy=${lib.boolToString cfg.enableAliasProxy} + + case "$action" in + destroy) + nixos-container destroy $container || true + # We can not leave the nginx config in place because this will + # make nginx stumble over non-resolveable names. + rm -f /etc/devhost/$container.json + if [ "$manage_alias_proxy" == true ]; then + fc-manage -v -b + fi + ;; + ensure) + channel_url=''${3?need to specify channel url} + channel_path=''${channel_url#file://} + aliases=''${4} + if ! nixos-container status $container; then + workdir=$(mktemp -d) + cd $workdir + echo $workdir + cp ${./container-base.nix} configuration.nix + cp ${./container-local.nix} local.nix + sed -i -e "s/__HOSTNAME__/$container/" local.nix + nix-build --option restrict-eval true -I . -I $channel_path -I nixos-config=configuration.nix --no-build-output "" -A system + system=$(readlink result) + nixos-container create $container --system-path $system + nixos-container start $container + cp local.nix /var/lib/containers/$container/etc/nixos/local.nix + else + nixos-container start $container + fi + mkdir -p /nix/var/nix/profiles/per-container/$container/per-user/root/ + jq -n --arg channel_url "$channel_url" '{parameters: {environment_url: $channel_url, environment: "container"}}' > /var/lib/containers/$container/etc/nixos/enc.json + # This touches the file and also ensures that we get updates on + # the aliases if needed. + container_ip=$(nixos-container show-ip $container) + jq -n --arg container "$container" \ + --arg aliases "$aliases" \ + --arg ip "$container_ip" \ + '{name: $container, ip: $ip, aliases: ($aliases | split(" ")), enabled: true}' \ + > /etc/devhost/$container.json + if [ "$manage_alias_proxy" == true ]; then + fc-manage -v -b + fi + esac + ''; + readDirMaybe = path: if (pathExists path) then readDir path else { }; + clean_script = fclib.python3BinFromFile ./fc-devhost-clean-containers.py; + + makeContainerTestScriptForRole = (role: + pkgs.writeShellScript "check_devhost_with_${role}" '' + #!/bin/sh + set -euxo pipefail + + record_exit() { + rv=$? + directory=/var/tmp/sensu/devhost/${role} + mkdir -p $directory + echo $rv > ''${directory}/state + journalctl _SYSTEMD_INVOCATION_ID=`systemctl show -p InvocationID --value fc-devhost-test-${role}` > ''${directory}/log + exit 0 + } + trap record_exit EXIT + + export PATH=/run/wrappers/bin:/root/.nix-profile/bin:/etc/profiles/per-user/root/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin + + container=devhosttest + + fc-build-dev-container destroy $container + + # Avoid duplicate nixexprs.tar.xz but ensure its there. + url=${cfg.testingChannelURL} + url=''${url%/nixexprs.tar.xz}/nixexprs.tar.xz + url=$(curl --head -Ls -o /dev/null -w %{url_effective} $url) + + fc-build-dev-container ensure $container $url "www" + + cat > /var/lib/containers/$container/etc/local/nixos/container.nix <<__EOF__ + { ... }: + { + flyingcircus.roles.${role}.enable = true; + } + __EOF__ + + nixos-container run $container -- fc-manage -c + + fc-build-dev-container destroy $container + + ''); +in lib.mkMerge [ + (lib.mkIf (cfg.enable && cfg.virtualisationType == "container") { + environment.systemPackages = [ container_script clean_script ]; + + security.sudo.extraRules = lib.mkAfter [{ + commands = [{ + command = "${container_script}/bin/fc-build-dev-container"; + options = [ "NOPASSWD" ]; + }]; + groups = [ "service" "users" ]; + }]; + + systemd.tmpfiles.rules = [ "d /etc/devhost/" ]; + + networking.extraHosts = '' + # static entries for devhost containers to avoid nginx issues + # if containers are not running. + # + # This could be a problem with duplicate entries, but I think + # we'll be fine. + '' + (lib.concatMapStringsSep "\n" + (container: "${container.ip} ${container.name}") + (filter (container: container ? ip) allContainers)); + + services.nginx.virtualHosts = if cfg.enableAliasProxy then + (let + suffix = cfg.publicAddress; + containers = + filter (container: container.aliases != [ ]) enabledContainers; + generateContainerVhost = container: { + name = "${container.name}.${suffix}"; + value = { + serverAliases = map (alias: "${alias}.${container.name}.${suffix}") + container.aliases; + forceSSL = true; + enableACME = true; + locations."/" = { proxyPass = "https://${container.name}"; }; + }; + }; + in builtins.listToAttrs (map generateContainerVhost containers)) + else + { }; + + systemd.services."container@".serviceConfig = { + TimeoutStartSec = lib.mkForce "1min"; + }; + + # Start containers on system startup, ensure they get started before + # nginx. + + systemd.services.fc-devhost-start-containers = { + description = "Start containers on boot."; + wantedBy = [ "multi-user.target" ]; + wants = [ "network.target" ]; + after = [ "network.target" ]; + before = [ "nginx.service" ]; + restartIfChanged = false; + stopIfChanged = false; + + path = [ pkgs.nixos-container ]; + script = '' + # Start all enabled containers. + + # be verbose about what you're doing + set -x + + # Allow individual containers to have problems but start + # all others. We have to set +e here explicitly as the script + # will be generated with a #!.../bin/bash -e header + set +e + + '' + lib.concatMapStringsSep "\n" + (container: "nixos-container start ${container.name}") + enabledContainers; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + }; + + # Automated clean up / shut down + + systemd.services.fc-devhost-clean-containers = { + description = "Clean up old/unused devhost containers."; + environment = { PYTHONUNBUFFERED = "1"; }; + path = with pkgs; [ clean_script nixos-container ]; + script = "fc-devhost-clean-containers"; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = false; + }; + }; + + systemd.timers.fc-devhost-clean-containers = + lib.mkIf cfg.cleanupContainers { + wantedBy = [ "timers.target" ]; + timerConfig = { OnCalendar = "*-*-* 03:00:00"; }; + }; + }) + + (lib.mkIf cfg.testing { + + security.acme.server = + "https://acme-staging-v02.api.letsencrypt.org/directory"; + + flyingcircus.services.sensu-client.checks = listToAttrs (map (role: { + name = "devhost_testsuite_${role}"; + value = { + notification = "DevHost test suite – ${role}"; + command = (let + check_command = pkgs.writeShellScript "check" '' + set -e + cat /var/tmp/sensu/devhost/${role}/log + exit $(" -A system - system=$(readlink result) - nixos-container create $container --system-path $system - nixos-container start $container - cp local.nix /var/lib/containers/$container/etc/nixos/local.nix - else - nixos-container start $container - fi - mkdir -p /nix/var/nix/profiles/per-container/$container/per-user/root/ - jq -n --arg channel_url "$channel_url" '{parameters: {environment_url: $channel_url, environment: "container"}}' > /var/lib/containers/$container/etc/nixos/enc.json - # This touches the file and also ensures that we get updates on - # the aliases if needed. - container_ip=$(nixos-container show-ip $container) - jq -n --arg container "$container" \ - --arg aliases "$aliases" \ - --arg ip "$container_ip" \ - '{name: $container, ip: $ip, aliases: ($aliases | split(" ")), enabled: true}' \ - > /etc/devhost/$container.json - if [ "$manage_alias_proxy" == true ]; then - fc-manage -v -b - fi - esac - ''; - readDirMaybe = path: if (pathExists path) then readDir path else {}; - clean_script = fclib.python3BinFromFile ./fc-devhost-clean-containers.py; - - makeContainerTestScriptForRole = (role: pkgs.writeShellScript "check_devhost_with_${role}" '' - #!/bin/sh - set -euxo pipefail - - record_exit() { - rv=$? - directory=/var/tmp/sensu/devhost/${role} - mkdir -p $directory - echo $rv > ''${directory}/state - journalctl _SYSTEMD_INVOCATION_ID=`systemctl show -p InvocationID --value fc-devhost-test-${role}` > ''${directory}/log - exit 0 - } - trap record_exit EXIT - - export PATH=/run/wrappers/bin:/root/.nix-profile/bin:/etc/profiles/per-user/root/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin - - container=devhosttest - - fc-build-dev-container destroy $container - - # Avoid duplicate nixexprs.tar.xz but ensure its there. - url=${cfg.testingChannelURL} - url=''${url%/nixexprs.tar.xz}/nixexprs.tar.xz - url=$(curl --head -Ls -o /dev/null -w %{url_effective} $url) - - fc-build-dev-container ensure $container $url "www" - - cat > /var/lib/containers/$container/etc/local/nixos/container.nix <<__EOF__ - { ... }: - { - flyingcircus.roles.${role}.enable = true; - } - __EOF__ - - nixos-container run $container -- fc-manage -c - - fc-build-dev-container destroy $container - ''); in - { + imports = [ + ./container.nix + ./vm.nix + ]; + options = { flyingcircus.roles.devhost = { enable = lib.mkEnableOption "Enable our container-based development host"; + + virtualisationType = lib.mkOption { + type = lib.types.enum [ "vm" "container" ]; + default = "container"; + }; + supportsContainers = fclib.mkDisableContainerSupport; enableAliasProxy = lib.mkOption { @@ -161,45 +58,6 @@ in flyingcircus.roles.webgateway.enable = true; - environment.systemPackages = [ - container_script - clean_script - ]; - - security.sudo.extraRules = lib.mkAfter [ - { commands = [ { command = "${container_script}/bin/fc-build-dev-container"; options = [ "NOPASSWD" ]; } ]; - groups = [ "service" "users" ]; - } ]; - - systemd.tmpfiles.rules = [ - "d /etc/devhost/" - ]; - - # BBB can be removed after a grace period - flyingcircus.activationScripts.devhost-migrate-old-config-dir = '' - if [ -d "/etc/devserver" ]; then - # Be defensive about whether tmpfiles has already created - # devhost entry and expect that it might already exist - # but might not. `mv`ing the directory would break in that - # case. - mkdir -p /etc/devhost - mv /etc/devserver/* /etc/devhost/ - rmdir /etc/devserver - fi - ''; - - # BBB can be removed after a grace period - flyingcircus.activationScripts.devhost-migrate-ip-config = '' - set -x - cd /etc/devhost - for filename in *.json; do - container=''${filename%.json} - ${pkgs.jq}/bin/jq \ - --arg ip $(${pkgs.nixos-container}/bin/nixos-container show-ip $container) \ - -r '. + {ip:$ip}' "$filename" | ${pkgs.moreutils}/bin/sponge "$filename" - done - ''; - boot.kernel.sysctl = { "net.ipv4.ip_forward" = 1; # Increase inotify limits to avoid running out of them when @@ -209,179 +67,6 @@ in "fs.inotify.max_user_watches" = 16384; }; networking.nat.internalInterfaces = ["ve-+"]; - - networking.extraHosts = '' - # static entries for devhost containers to avoid nginx issues - # if containers are not running. - # - # This could be a problem with duplicate entries, but I think - # we'll be fine. - '' + (lib.concatMapStringsSep "\n" - (container: "${container.ip} ${container.name}") - (filter (container: container ? ip) allContainers)); - - services.nginx.virtualHosts = if cfg.enableAliasProxy then ( - let - suffix = cfg.publicAddress; - containers = filter (container: container.aliases != []) enabledContainers; - generateContainerVhost = container: - { name = "${container.name}.${suffix}"; - value = { - serverAliases = map - (alias: "${alias}.${container.name}.${suffix}") - container.aliases; - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "https://${container.name}"; - }; - }; - }; - in - builtins.listToAttrs (map generateContainerVhost containers)) - else {}; - - systemd.services."container@".serviceConfig = { TimeoutStartSec = lib.mkForce "1min"; }; - - # Start containers on system startup, ensure they get started before - # nginx. - - systemd.services.fc-devhost-start-containers = { - description = "Start containers on boot."; - wantedBy = [ "multi-user.target" ]; - wants = [ "network.target" ]; - after = [ "network.target" ]; - before = [ "nginx.service" ] ; - restartIfChanged = false; - stopIfChanged = false; - - path = [ pkgs.nixos-container ]; - script = '' - # Start all enabled containers. - - # be verbose about what you're doing - set -x - - # Allow individual containers to have problems but start - # all others. We have to set +e here explicitly as the script - # will be generated with a #!.../bin/bash -e header - set +e - - '' + lib.concatMapStringsSep "\n" - (container: "nixos-container start ${container.name}") - enabledContainers; - - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - }; - - # Automated clean up / shut down - - systemd.services.fc-devhost-clean-containers = { - description = "Clean up old/unused devhost containers."; - environment = { - PYTHONUNBUFFERED = "1"; - }; - path = with pkgs; [ clean_script nixos-container ]; - script = "fc-devhost-clean-containers"; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = false; - }; - }; - - systemd.timers.fc-devhost-clean-containers = lib.mkIf cfg.cleanupContainers { - wantedBy = [ "timers.target" ]; - timerConfig = { - OnCalendar = "*-*-* 03:00:00"; - }; - }; - - }) - - (lib.mkIf cfg.testing { - - security.acme.server = "https://acme-staging-v02.api.letsencrypt.org/directory"; - - flyingcircus.services.sensu-client.checks = listToAttrs (map (role: { - name = "devhost_testsuite_${role}"; - value = { - notification = "DevHost test suite – ${role}"; - command = (let check_command = pkgs.writeShellScript "check" '' - set -e - cat /var/tmp/sensu/devhost/${role}/log - exit $(> $out/nix-support/hydra-build-products + ''; + }; + }; +} + diff --git a/release/make-disk-image.nix b/release/make-disk-image.nix index 4908e9afe..899c6583b 100644 --- a/release/make-disk-image.nix +++ b/release/make-disk-image.nix @@ -36,6 +36,8 @@ , name ? "nixos-disk-image" +, filename-prefix ? "nixos" + , # Disk image format, one of qcow2, qcow2-compressed, vpc, raw. format ? "raw" @@ -53,7 +55,7 @@ let format' = format; in let compress = optionalString (format' == "qcow2-compressed") "-c"; - filename = "nixos." + { + filename = "${filename-prefix}." + { qcow2 = "qcow2"; vpc = "vhd"; raw = "img";