diff options
Diffstat (limited to 'modules/private/system')
-rw-r--r-- | modules/private/system/dilion.nix | 18 | ||||
-rw-r--r-- | modules/private/system/dilion/vms.nix | 146 | ||||
-rw-r--r-- | modules/private/system/dilion/vms/base_configuration.nix | 21 | ||||
-rw-r--r-- | modules/private/system/dilion/vms/base_image.nix | 94 | ||||
-rw-r--r-- | modules/private/system/dilion/vms/buildbot_configuration.nix | 67 |
5 files changed, 343 insertions, 3 deletions
diff --git a/modules/private/system/dilion.nix b/modules/private/system/dilion.nix index be8269e..a59d607 100644 --- a/modules/private/system/dilion.nix +++ b/modules/private/system/dilion.nix | |||
@@ -76,12 +76,24 @@ | |||
76 | }; | 76 | }; |
77 | 77 | ||
78 | myServices.ssh.modules = [ config.myServices.ssh.predefinedModules.regular ]; | 78 | myServices.ssh.modules = [ config.myServices.ssh.predefinedModules.regular ]; |
79 | imports = builtins.attrValues (import ../..); | 79 | imports = builtins.attrValues (import ../..) ++ [ ./dilion/vms.nix ]; |
80 | 80 | ||
81 | system.nssModules = [ pkgs.libvirt ]; | 81 | system.nssModules = [ pkgs.libvirt ]; |
82 | system.nssDatabases.hosts = lib.mkForce [ "files" "libvirt_guest" "mymachines" "dns" "myhostname" ]; | 82 | system.nssDatabases.hosts = lib.mkForce [ "files" "libvirt_guest" "mymachines" "dns" "myhostname" ]; |
83 | programs.zsh.enable = true; | 83 | programs.zsh.enable = true; |
84 | 84 | ||
85 | users.users.libvirt = { | ||
86 | hashedPassword = "!"; | ||
87 | shell = pkgs.bashInteractive; | ||
88 | isSystemUser = true; | ||
89 | group = "libvirtd"; | ||
90 | packages = [ pkgs.netcat-openbsd ]; | ||
91 | openssh.authorizedKeys.keyFiles = [ | ||
92 | "${privateFiles}/buildbot_ssh_key.pub" | ||
93 | ]; | ||
94 | openssh.authorizedKeys.keys = [ config.myEnv.sshd.rootKeys.ismael_flony ]; | ||
95 | }; | ||
96 | |||
85 | users.users.backup = { | 97 | users.users.backup = { |
86 | hashedPassword = "!"; | 98 | hashedPassword = "!"; |
87 | isSystemUser = true; | 99 | isSystemUser = true; |
@@ -118,7 +130,7 @@ | |||
118 | after = [ "network.target" ]; | 130 | after = [ "network.target" ]; |
119 | 131 | ||
120 | serviceConfig = { | 132 | serviceConfig = { |
121 | ExecStart = "${pkgs.socat}/bin/socat TCP-LISTEN:8022,fork TCP:nixops-99a7e1ba-54dc-11ea-a965-10bf487fe63b-caldance:22"; | 133 | ExecStart = "${pkgs.socat}/bin/socat TCP-LISTEN:8022,fork TCP:caldance:22"; |
122 | }; | 134 | }; |
123 | }; | 135 | }; |
124 | 136 | ||
@@ -170,7 +182,7 @@ | |||
170 | recommendedGzipSettings = true; | 182 | recommendedGzipSettings = true; |
171 | recommendedProxySettings = true; | 183 | recommendedProxySettings = true; |
172 | upstreams = { | 184 | upstreams = { |
173 | caldance.servers."nixops-99a7e1ba-54dc-11ea-a965-10bf487fe63b-caldance:3031" = {}; | 185 | caldance.servers."caldance:3031" = {}; |
174 | }; | 186 | }; |
175 | virtualHosts = { | 187 | virtualHosts = { |
176 | "dev.immae.eu" = { | 188 | "dev.immae.eu" = { |
diff --git a/modules/private/system/dilion/vms.nix b/modules/private/system/dilion/vms.nix new file mode 100644 index 0000000..8d5a57b --- /dev/null +++ b/modules/private/system/dilion/vms.nix | |||
@@ -0,0 +1,146 @@ | |||
1 | # inspired from https://nixos.wiki/wiki/Virtualization_in_NixOS | ||
2 | { config, pkgs, lib, ... }@args: | ||
3 | let | ||
4 | networks = { | ||
5 | immae = { | ||
6 | bridgeNumber = "1"; | ||
7 | ipRange = "192.168.100"; | ||
8 | }; | ||
9 | }; | ||
10 | guests = { | ||
11 | caldance = { | ||
12 | pool = "zfspool"; | ||
13 | cpus = "1"; | ||
14 | memory = "2"; | ||
15 | network = "immae"; | ||
16 | diskSize = "10GiB"; | ||
17 | extraDevicesXML = '' | ||
18 | <filesystem type="mount"> | ||
19 | <source dir="/var/lib/caldance"/> | ||
20 | <target dir="home"/> | ||
21 | </filesystem> | ||
22 | ''; | ||
23 | }; | ||
24 | buildbot = { | ||
25 | pool = "zfspool"; | ||
26 | cpus = "1"; | ||
27 | memory = "3"; | ||
28 | network = "immae"; | ||
29 | diskSize = "10GiB"; | ||
30 | destroyVolumeOnExit = true; | ||
31 | preStart = '' | ||
32 | if ! ${pkgs.libvirt}/bin/virsh pool-info --pool niximages &> /dev/null; then | ||
33 | pool-create-as --name niximages --type dir --target /etc/libvirtd/base-images/ | ||
34 | fi | ||
35 | if ! ${pkgs.libvirt}/bin/virsh pool-info --pool buildbot-disks &> /dev/null; then | ||
36 | mkdir -p /var/lib/libvirt/images/buildbot-disks | ||
37 | pool-create-as --name buildbot-disks --type dir --target /var/lib/libvirt/images/buildbot-disks | ||
38 | fi | ||
39 | ''; | ||
40 | }; | ||
41 | }; | ||
42 | toImage = f: "${import ./vms/base_image.nix f (args // { myEnv = config.myEnv; })}/nixos.qcow2"; | ||
43 | in | ||
44 | { | ||
45 | environment.etc."libvirtd/base-images/nixos.qcow2".source = toImage ./vms/base_configuration.nix; | ||
46 | environment.etc."libvirtd/base-images/buildbot.qcow2".source = toImage ./vms/buildbot_configuration.nix; | ||
47 | systemd.services = lib.mapAttrs' (name: guest: lib.nameValuePair "libvirtd-guest-${name}" { | ||
48 | after = [ "libvirtd.service" "libvirtd-network-${guest.network}.service" ]; | ||
49 | requires = [ "libvirtd.service" "libvirtd-network-${guest.network}.service" ]; | ||
50 | wantedBy = [ "multi-user.target" ]; | ||
51 | serviceConfig = { | ||
52 | Type = "oneshot"; | ||
53 | RemainAfterExit = "yes"; | ||
54 | }; | ||
55 | script = | ||
56 | let | ||
57 | xml = pkgs.writeText "libvirt-guest-${name}.xml" | ||
58 | '' | ||
59 | <domain type="kvm"> | ||
60 | <name>${name}</name> | ||
61 | <uuid>UUID</uuid> | ||
62 | <memory unit="GiB">${guest.memory}</memory> | ||
63 | <vcpu>${guest.cpus}</vcpu> | ||
64 | <os> | ||
65 | <type arch="x86_64">hvm</type> | ||
66 | </os> | ||
67 | <devices> | ||
68 | <emulator>/run/current-system/sw/bin/qemu-system-x86_64</emulator> | ||
69 | <disk type="volume"> | ||
70 | <source pool="${guest.pool}" volume="guest-${name}" /> | ||
71 | <target dev="vda" bus="virtio"/> | ||
72 | </disk> | ||
73 | ${guest.extraDevicesXML or ""} | ||
74 | <input type="keyboard" bus="usb"/> | ||
75 | <graphics type="vnc" port="-1" autoport="yes"/> | ||
76 | <interface type="network"> | ||
77 | <source network="${guest.network}" /> | ||
78 | </interface> | ||
79 | </devices> | ||
80 | <features> | ||
81 | <acpi/> | ||
82 | </features> | ||
83 | </domain> | ||
84 | ''; | ||
85 | in | ||
86 | guest.preStart or "" + '' | ||
87 | if ! ${pkgs.libvirt}/bin/virsh vol-key 'guest-${name}' --pool ${guest.pool} &> /dev/null; then | ||
88 | ${pkgs.libvirt}/bin/virsh vol-create-as --pool ${guest.pool} --name 'guest-${name}' --capacity '${guest.diskSize}' | ||
89 | volume_path=$(${pkgs.libvirt}/bin/virsh vol-path --pool ${guest.pool} --vol 'guest-${name}') | ||
90 | ${pkgs.qemu}/bin/qemu-img convert /etc/libvirtd/base-images/nixos.qcow2 $volume_path | ||
91 | fi | ||
92 | uuid="$(${pkgs.libvirt}/bin/virsh domuuid '${name}' || true)" | ||
93 | ${pkgs.libvirt}/bin/virsh define <(sed "s/UUID/$uuid/" '${xml}') | ||
94 | ${pkgs.libvirt}/bin/virsh start '${name}' | ||
95 | ''; | ||
96 | preStop = '' | ||
97 | ${pkgs.libvirt}/bin/virsh shutdown '${name}' | ||
98 | let "timeout = $(date +%s) + 10" | ||
99 | while [ "$(${pkgs.libvirt}/bin/virsh list --name | grep --count '^${name}$')" -gt 0 ]; do | ||
100 | if [ "$(date +%s)" -ge "$timeout" ]; then | ||
101 | # Meh, we warned it... | ||
102 | ${pkgs.libvirt}/bin/virsh destroy '${name}' | ||
103 | else | ||
104 | # The machine is still running, let's give it some time to shut down | ||
105 | sleep 0.5 | ||
106 | fi | ||
107 | done | ||
108 | '' + lib.optionalString (guest.destroyVolumeOnExit or false) '' | ||
109 | if ${pkgs.libvirt}/bin/virsh vol-key 'guest-${name}' --pool ${guest.pool} &> /dev/null; then | ||
110 | ${pkgs.libvirt}/bin/virsh vol-wipe --pool ${guest.pool} --vol 'guest-${name}' || true | ||
111 | ${pkgs.libvirt}/bin/virsh vol-delete --pool ${guest.pool} --vol 'guest-${name}' | ||
112 | fi | ||
113 | ''; | ||
114 | }) guests // (lib.mapAttrs' (name: network: lib.nameValuePair "libvirtd-network-${name}" { | ||
115 | after = [ "libvirtd.service" ]; | ||
116 | requires = [ "libvirtd.service" ]; | ||
117 | wantedBy = [ "multi-user.target" ]; | ||
118 | serviceConfig = { | ||
119 | Type = "oneshot"; | ||
120 | RemainAfterExit = "yes"; | ||
121 | }; | ||
122 | script = let | ||
123 | xml = pkgs.writeText "libvirt-network-${name}.xml" '' | ||
124 | <network> | ||
125 | <name>${name}</name> | ||
126 | <uuid>UUID</uuid> | ||
127 | <forward mode='nat' /> | ||
128 | <bridge name='virbr${network.bridgeNumber}' /> | ||
129 | <domain name='${name}' localOnly='yes'/> | ||
130 | <ip address='${network.ipRange}.1' netmask='255.255.255.0'> | ||
131 | <dhcp> | ||
132 | <range start='${network.ipRange}.2' end='${network.ipRange}.254'/> | ||
133 | </dhcp> | ||
134 | </ip> | ||
135 | </network> | ||
136 | ''; | ||
137 | in '' | ||
138 | uuid="$(${pkgs.libvirt}/bin/virsh net-uuid '${name}' || true)" | ||
139 | ${pkgs.libvirt}/bin/virsh net-define <(sed "s/UUID/$uuid/" '${xml}') | ||
140 | ${pkgs.libvirt}/bin/virsh net-start '${name}' | ||
141 | ''; | ||
142 | preStop = '' | ||
143 | ${pkgs.libvirt}/bin/virsh net-destroy '${name}' | ||
144 | ''; | ||
145 | }) networks); | ||
146 | } | ||
diff --git a/modules/private/system/dilion/vms/base_configuration.nix b/modules/private/system/dilion/vms/base_configuration.nix new file mode 100644 index 0000000..e2caba2 --- /dev/null +++ b/modules/private/system/dilion/vms/base_configuration.nix | |||
@@ -0,0 +1,21 @@ | |||
1 | { lib, config, ... }@args: | ||
2 | { | ||
3 | options.myEnv = (import ../../../environment.nix (args // { name = "dummy"; })).options.myEnv; | ||
4 | config = { | ||
5 | fileSystems."/".device = "/dev/disk/by-label/nixos"; | ||
6 | boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "virtio_balloon" "virtio_blk" "virtio_pci" "virtio_ring" ]; | ||
7 | boot.loader = { | ||
8 | grub = { | ||
9 | version = 2; | ||
10 | device = "/dev/vda"; | ||
11 | }; | ||
12 | timeout = 0; | ||
13 | }; | ||
14 | services.openssh.enable = true; | ||
15 | networking.firewall.allowedTCPPorts = [ 22 ]; | ||
16 | users = { | ||
17 | mutableUsers = false; | ||
18 | users.root.openssh.authorizedKeys.keys = [ config.myEnv.sshd.rootKeys.immae_dilion ]; | ||
19 | }; | ||
20 | }; | ||
21 | } | ||
diff --git a/modules/private/system/dilion/vms/base_image.nix b/modules/private/system/dilion/vms/base_image.nix new file mode 100644 index 0000000..8de8560 --- /dev/null +++ b/modules/private/system/dilion/vms/base_image.nix | |||
@@ -0,0 +1,94 @@ | |||
1 | configuration_file: { pkgs ? import <nixpkgs> {}, system ? builtins.currentSystem, myEnv, ... }: | ||
2 | let | ||
3 | config = (import <nixpkgs/nixos/lib/eval-config.nix> { | ||
4 | inherit system; | ||
5 | modules = [ { | ||
6 | myEnv = myEnv; | ||
7 | imports = [ configuration_file ]; | ||
8 | |||
9 | # We want our template image to be as small as possible, but the deployed image should be able to be | ||
10 | # of any size. Hence we resize on the first boot. | ||
11 | systemd.services.resize-main-fs = { | ||
12 | wantedBy = [ "multi-user.target" ]; | ||
13 | serviceConfig.Type = "oneshot"; | ||
14 | script = | ||
15 | '' | ||
16 | # Resize main partition to fill whole disk | ||
17 | echo ", +" | ${pkgs.utillinux}/bin/sfdisk /dev/vda --no-reread -N 1 | ||
18 | ${pkgs.parted}/bin/partprobe | ||
19 | # Resize filesystem | ||
20 | ${pkgs.e2fsprogs}/bin/resize2fs /dev/vda1 | ||
21 | ''; | ||
22 | }; | ||
23 | } ]; | ||
24 | }).config; | ||
25 | in pkgs.vmTools.runInLinuxVM ( | ||
26 | pkgs.runCommand "nixos-base-image" | ||
27 | { | ||
28 | memSize = 768; | ||
29 | preVM = | ||
30 | '' | ||
31 | mkdir $out | ||
32 | diskImage=image.qcow2 | ||
33 | ${pkgs.vmTools.qemu}/bin/qemu-img create -f qcow2 $diskImage 2G | ||
34 | mv closure xchg/ | ||
35 | ''; | ||
36 | postVM = | ||
37 | '' | ||
38 | echo compressing VM image... | ||
39 | ${pkgs.vmTools.qemu}/bin/qemu-img convert -c $diskImage -O qcow2 $out/nixos.qcow2 | ||
40 | ''; | ||
41 | buildInputs = [ pkgs.utillinux pkgs.perl pkgs.parted pkgs.e2fsprogs ]; | ||
42 | exportReferencesGraph = | ||
43 | [ "closure" config.system.build.toplevel ]; | ||
44 | } | ||
45 | '' | ||
46 | # Create the partition | ||
47 | parted /dev/vda mklabel msdos | ||
48 | parted /dev/vda -- mkpart primary ext4 1M -1s | ||
49 | |||
50 | # Format the partition | ||
51 | mkfs.ext4 -L nixos /dev/vda1 | ||
52 | mkdir /mnt | ||
53 | mount /dev/vda1 /mnt | ||
54 | |||
55 | for dir in dev proc sys; do | ||
56 | mkdir /mnt/$dir | ||
57 | mount --bind /$dir /mnt/$dir | ||
58 | done | ||
59 | |||
60 | storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure) | ||
61 | echo filling Nix store... | ||
62 | mkdir -p /mnt/nix/store | ||
63 | set -f | ||
64 | cp -prd $storePaths /mnt/nix/store | ||
65 | # The permissions will be set up incorrectly if the host machine is not running NixOS | ||
66 | chown -R 0:30000 /mnt/nix/store | ||
67 | |||
68 | mkdir -p /mnt/etc/nix | ||
69 | echo 'build-users-group = ' > /mnt/etc/nix/nix.conf | ||
70 | |||
71 | # Register the paths in the Nix database. | ||
72 | export USER=root | ||
73 | printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \ | ||
74 | chroot /mnt ${config.nix.package.out}/bin/nix-store --load-db | ||
75 | |||
76 | # Create the system profile to allow nixos-rebuild to work. | ||
77 | chroot /mnt ${config.nix.package.out}/bin/nix-env \ | ||
78 | -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} | ||
79 | |||
80 | # `nixos-rebuild' requires an /etc/NIXOS. | ||
81 | mkdir -p /mnt/etc/nixos | ||
82 | touch /mnt/etc/NIXOS | ||
83 | |||
84 | # `switch-to-configuration' requires a /bin/sh | ||
85 | mkdir -p /mnt/bin | ||
86 | ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh | ||
87 | |||
88 | # Generate the GRUB menu. | ||
89 | chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot | ||
90 | |||
91 | umount /mnt/{proc,dev,sys} | ||
92 | umount /mnt | ||
93 | '' | ||
94 | ) | ||
diff --git a/modules/private/system/dilion/vms/buildbot_configuration.nix b/modules/private/system/dilion/vms/buildbot_configuration.nix new file mode 100644 index 0000000..05b02d4 --- /dev/null +++ b/modules/private/system/dilion/vms/buildbot_configuration.nix | |||
@@ -0,0 +1,67 @@ | |||
1 | { pkgs, config, lib, ... }: | ||
2 | { | ||
3 | imports = [ | ||
4 | <nixpkgs/nixos/modules/profiles/qemu-guest.nix> | ||
5 | ./base_configuration.nix | ||
6 | ]; | ||
7 | systemd.services.buildbot-worker.serviceConfig.ExecStartPre = let | ||
8 | cfg = config.services.buildbot-worker; | ||
9 | script = pkgs.writeScript "decode-dmi" '' | ||
10 | #!${pkgs.stdenv.shell} | ||
11 | |||
12 | mkdir -vp "${cfg.buildbotDir}" | ||
13 | varfile=${cfg.buildbotDir}/variables | ||
14 | rm $varfile || true | ||
15 | echo "[DEFAULT]" > $varfile | ||
16 | strings=$(${pkgs.dmidecode}/bin/dmidecode --oem-string count) | ||
17 | for i in $(seq 1 $strings); do | ||
18 | ${pkgs.dmidecode}/bin/dmidecode --oem-string $i >> $varfile | ||
19 | done | ||
20 | chown -R ${cfg.user}:${cfg.group} ${cfg.buildbotDir} | ||
21 | ''; | ||
22 | in | ||
23 | lib.mkForce ["+${script}"]; | ||
24 | systemd.services.buildbot-worker.serviceConfig.ExecStart = let | ||
25 | cfg = config.services.buildbot-worker; | ||
26 | tacFile = pkgs.writeText "buildbot-worker.tac" '' | ||
27 | import os | ||
28 | from io import open | ||
29 | |||
30 | from buildbot_worker.bot import Worker | ||
31 | from twisted.application import service | ||
32 | |||
33 | basedir = '${cfg.buildbotDir}' | ||
34 | |||
35 | # note: this line is matched against to check that this is a worker | ||
36 | # directory; do not edit it. | ||
37 | application = service.Application('buildbot-worker') | ||
38 | |||
39 | import configparser | ||
40 | config = config = configparser.ConfigParser() | ||
41 | config.read("${cfg.buildbotDir}/variables") | ||
42 | master_url_split = config["DEFAULT"]["buildbot_master_url"].split(':') | ||
43 | buildmaster_host = master_url_split[0] | ||
44 | port = int(master_url_split[1]) | ||
45 | workername = config["DEFAULT"]["buildbot_worker_name"] | ||
46 | |||
47 | with open('${cfg.workerPassFile}', 'r', encoding='utf-8') as passwd_file: | ||
48 | passwd = passwd_file.read().strip('\r\n') | ||
49 | keepalive = ${toString cfg.keepalive} | ||
50 | umask = None | ||
51 | maxdelay = 300 | ||
52 | numcpus = None | ||
53 | allow_shutdown = None | ||
54 | |||
55 | s = Worker(buildmaster_host, port, workername, passwd, basedir, | ||
56 | keepalive, umask=umask, maxdelay=maxdelay, | ||
57 | numcpus=numcpus, allow_shutdown=allow_shutdown) | ||
58 | s.setServiceParent(application) | ||
59 | ''; | ||
60 | in | ||
61 | lib.mkForce "${cfg.package.pythonModule.pkgs.twisted}/bin/twistd --nodaemon --pidfile= --logfile - --python ${tacFile}"; | ||
62 | services.buildbot-worker = { | ||
63 | enable = true; | ||
64 | workerPass = config.myEnv.buildbot.workerPassword; | ||
65 | packages = [ pkgs.git pkgs.gzip pkgs.openssh ]; | ||
66 | }; | ||
67 | } | ||