diff options
-rw-r--r-- | .envrc | 2 | ||||
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | docs/migrate_hetzner.md | 20 | ||||
-rw-r--r-- | modules/private/system.nix | 10 | ||||
-rw-r--r-- | modules/private/system/backup-2.nix | 20 | ||||
-rw-r--r-- | modules/private/system/dilion.nix | 91 | ||||
-rw-r--r-- | modules/private/system/eldiron.nix | 85 | ||||
-rw-r--r-- | modules/private/system/monitoring-1.nix | 19 | ||||
-rw-r--r-- | modules/secrets.nix | 13 | ||||
-rw-r--r-- | nixops/Makefile | 87 | ||||
-rw-r--r-- | nixops/default.nix | 11 | ||||
-rwxr-xr-x | nixops/scripts/setup | 16 | ||||
-rwxr-xr-x | nixops/scripts/with_env | 6 | ||||
m--------- | nixops/secrets | 0 | ||||
-rw-r--r-- | nixops/state/.gitkeep | 0 | ||||
-rw-r--r-- | overlays/default.nix | 1 | ||||
-rw-r--r-- | overlays/morph/default.nix | 5 | ||||
-rw-r--r-- | overlays/morph/verbose_nix.patch | 12 | ||||
-rw-r--r-- | shell.nix | 2 |
20 files changed, 195 insertions, 211 deletions
@@ -1,7 +1,5 @@ | |||
1 | # vim: filetype=bash | 1 | # vim: filetype=bash |
2 | export PASSWORD_STORE_DIR=$(expand_path nixops/secrets) | 2 | export PASSWORD_STORE_DIR=$(expand_path nixops/secrets) |
3 | export NIXOPS_STATE=$(expand_path nixops/state/immaeEu.nixops) | ||
4 | export NIXOPS_DEPLOYMENT=cef694f3-081d-11e9-b31f-0242ec186adf | ||
5 | export NIX_PATH=nixpkgs=$(cat $(expand_path nix/sources.json) | jq -r '."nixpkgs-nixops".url') | 3 | export NIX_PATH=nixpkgs=$(cat $(expand_path nix/sources.json) | jq -r '."nixpkgs-nixops".url') |
6 | 4 | ||
7 | export NIXOPS_ENV_LOADED=1 | 5 | export NIXOPS_ENV_LOADED=1 |
@@ -1,3 +1,4 @@ | |||
1 | /result* | 1 | /result* |
2 | /versions_log | 2 | /versions_log |
3 | .direnv/ | 3 | .direnv/ |
4 | /nixops/.gcroots | ||
@@ -1,8 +1,7 @@ | |||
1 | subrecipes = setup nix-info edit_env | 1 | subrecipes = setup nix-info edit_env |
2 | subrecipes += nixops ssh-eldiron ssh-backup-2 ssh-monitoring-1 | 2 | subrecipes += ssh-eldiron ssh-backup-2 ssh-monitoring-1 |
3 | subrecipes += info debug dry-run build upload deploy deploy-reboot reboot | 3 | subrecipes += debug build upload deploy deploy-reboot |
4 | subrecipes += list-generations delete-generations cleanup | 4 | subrecipes += list-generations delete-generations cleanup |
5 | subrecipes += pull_deployment deployment_is_set push_deployment | ||
6 | ${subrecipes}: | 5 | ${subrecipes}: |
7 | @$(MAKE) --no-print-directory -C nixops/ $@ | 6 | @$(MAKE) --no-print-directory -C nixops/ $@ |
8 | .PHONY: ${subrecipes} | 7 | .PHONY: ${subrecipes} |
diff --git a/docs/migrate_hetzner.md b/docs/migrate_hetzner.md deleted file mode 100644 index c7fbe20..0000000 --- a/docs/migrate_hetzner.md +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | nixops show a deprecation message at each deployment because hetzner | ||
2 | info is outdated. To fix it: | ||
3 | |||
4 | cp -a ~/.nixops ~/.nixops.bak | ||
5 | |||
6 | nixops export --all > all.json | ||
7 | |||
8 | network=$(cat all.json| jq -r '."cef694f3-081d-11e9-b31f-0242ec186adf".resources.eldiron."hetzner.networkInfo"' | jq -r -c '.networking.interfaces.eth0 = { "ipv4": { "addresses": [ { "address": .networking.interfaces.eth0.ipAddress, "prefixLength": .networking.interfaces.eth0.prefixLength } ] } }') | ||
9 | |||
10 | cat all.json | jq --arg network "$network" '."cef694f3-081d-11e9-b31f-0242ec186adf".resources.eldiron."hetzner.networkInfo" = $network' > all_new.json | ||
11 | |||
12 | nixops delete --force -d eldiron | ||
13 | |||
14 | nixops import < all_new.json | ||
15 | |||
16 | rm all.json all_new.json | ||
17 | |||
18 | *check that everything works*, then: | ||
19 | |||
20 | rm -rf ~/.nixops.bak | ||
diff --git a/modules/private/system.nix b/modules/private/system.nix index b667ee8..6b4ef6e 100644 --- a/modules/private/system.nix +++ b/modules/private/system.nix | |||
@@ -1,6 +1,12 @@ | |||
1 | { pkgs, lib, config, name, ... }: | 1 | { pkgs, lib, config, name, nodes, ... }: |
2 | { | 2 | { |
3 | config = { | 3 | config = { |
4 | networking.extraHosts = builtins.concatStringsSep "\n" | ||
5 | (lib.mapAttrsToList (n: v: "${v.config.hostEnv.ips.main.ip4} ${n}") nodes); | ||
6 | |||
7 | users.extraUsers.root.openssh.authorizedKeys.keyFiles = [ "${config.myEnv.privateFiles}/id_ed25519.pub" ]; | ||
8 | services.openssh.enable = true; | ||
9 | |||
4 | services.duplyBackup.profiles.system = { | 10 | services.duplyBackup.profiles.system = { |
5 | rootDir = "/var/lib"; | 11 | rootDir = "/var/lib"; |
6 | excludeFile = lib.mkAfter '' | 12 | excludeFile = lib.mkAfter '' |
@@ -73,6 +79,8 @@ | |||
73 | environment.systemPackages = [ | 79 | environment.systemPackages = [ |
74 | pkgs.git | 80 | pkgs.git |
75 | pkgs.vim | 81 | pkgs.vim |
82 | pkgs.rsync | ||
83 | pkgs.strace | ||
76 | ] ++ | 84 | ] ++ |
77 | (lib.optional (builtins.length (config.hostEnv.users pkgs) > 0) pkgs.home-manager); | 85 | (lib.optional (builtins.length (config.hostEnv.users pkgs) > 0) pkgs.home-manager); |
78 | 86 | ||
diff --git a/modules/private/system/backup-2.nix b/modules/private/system/backup-2.nix index a49c374..d1064c7 100644 --- a/modules/private/system/backup-2.nix +++ b/modules/private/system/backup-2.nix | |||
@@ -1,26 +1,22 @@ | |||
1 | { privateFiles }: | 1 | { privateFiles }: |
2 | { config, pkgs, resources, name, ... }: | 2 | { config, pkgs, resources, name, ... }: |
3 | { | 3 | { |
4 | deployment = { | ||
5 | targetUser = "root"; | ||
6 | targetHost = config.hostEnv.ips.main.ip4; | ||
7 | substituteOnDestination = true; | ||
8 | }; | ||
4 | boot.kernelPackages = pkgs.linuxPackages_latest; | 9 | boot.kernelPackages = pkgs.linuxPackages_latest; |
5 | myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; }; | 10 | myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; }; |
6 | 11 | ||
7 | imports = builtins.attrValues (import ../..); | 12 | imports = [ <nixpkgs/nixos/modules/profiles/qemu-guest.nix> ] ++ builtins.attrValues (import ../..); |
8 | |||
9 | deployment = { | ||
10 | targetEnv = "hetznerCloud"; | ||
11 | hetznerCloud = { | ||
12 | authToken = config.myEnv.hetznerCloud.authToken; | ||
13 | datacenter = "hel1-dc2"; | ||
14 | location ="hel1"; | ||
15 | serverType = "cx11"; | ||
16 | }; | ||
17 | }; | ||
18 | 13 | ||
19 | fileSystems = { | 14 | fileSystems = { |
20 | "/backup2" = { | 15 | "/backup2" = { |
21 | fsType = "ext4"; | 16 | fsType = "ext4"; |
22 | device = "UUID=b9425333-f567-435d-94d8-b26c22d93426"; | 17 | device = "UUID=b9425333-f567-435d-94d8-b26c22d93426"; |
23 | }; | 18 | }; |
19 | "/" = { device = "/dev/sda1"; fsType = "ext4"; }; | ||
24 | }; | 20 | }; |
25 | 21 | ||
26 | networking = { | 22 | networking = { |
@@ -34,6 +30,8 @@ | |||
34 | defaultGateway6 = { address = "fe80::1"; interface = "ens3"; }; | 30 | defaultGateway6 = { address = "fe80::1"; interface = "ens3"; }; |
35 | }; | 31 | }; |
36 | 32 | ||
33 | boot.loader.grub.device = "nodev"; | ||
34 | |||
37 | myServices.certificates.enable = true; | 35 | myServices.certificates.enable = true; |
38 | security.acme.certs."${name}" = { | 36 | security.acme.certs."${name}" = { |
39 | user = config.services.nginx.user; | 37 | user = config.services.nginx.user; |
diff --git a/modules/private/system/dilion.nix b/modules/private/system/dilion.nix index 5c24656..5abaac0 100644 --- a/modules/private/system/dilion.nix +++ b/modules/private/system/dilion.nix | |||
@@ -1,59 +1,81 @@ | |||
1 | { privateFiles }: | 1 | { privateFiles }: |
2 | { config, pkgs, name, lib, ... }: | 2 | { config, pkgs, name, lib, ... }: |
3 | { | 3 | { |
4 | boot.supportedFilesystems = [ "zfs" ]; | 4 | deployment = { |
5 | boot.kernelPackages = pkgs.linuxPackages_latest; | 5 | targetUser = "root"; |
6 | targetHost = config.hostEnv.ips.main.ip4; | ||
7 | substituteOnDestination = true; | ||
8 | }; | ||
9 | nixpkgs.system = lib.mkOverride 900 "x86_64-linux"; | ||
10 | boot = { | ||
11 | loader = { | ||
12 | grub = { | ||
13 | version = 2; | ||
14 | devices = [ "/dev/sda" "/dev/sdb" "/dev/sdc" "/dev/sdd" ]; | ||
15 | }; | ||
16 | timeout = 1; | ||
17 | }; | ||
18 | blacklistedKernelModules = [ "nvidiafb" ]; | ||
19 | supportedFilesystems = [ "zfs" ]; | ||
20 | kernelPackages = pkgs.linuxPackages_latest; | ||
21 | kernelModules = [ "kvm-intel" ]; | ||
22 | initrd.availableKernelModules = [ "ahci" "sd_mod" ]; | ||
23 | initrd.secrets = { | ||
24 | "/boot/pass.key" = "/boot/pass.key"; | ||
25 | }; | ||
26 | kernel.sysctl."vm.nr_hugepages" = 256; # for xmr-stak | ||
27 | }; | ||
28 | nix.maxJobs = 8; | ||
29 | powerManagement.cpuFreqGovernor = "powersave"; | ||
30 | hardware.enableRedistributableFirmware = true; | ||
31 | |||
6 | myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; }; | 32 | myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; }; |
7 | 33 | ||
34 | swapDevices = [ { label = "swap"; } ]; | ||
8 | fileSystems = { | 35 | fileSystems = { |
9 | "/" = lib.mkForce { fsType = "zfs"; device = "zpool/root"; }; | 36 | "/" = { fsType = "zfs"; device = "zpool/root"; }; |
10 | "/boot" = { fsType = "ext4"; device = "/dev/disk/by-uuid/fd1c511e-2bc0-49d5-b8bb-95e7e8c8c816"; }; | 37 | "/boot" = { fsType = "ext4"; device = "/dev/disk/by-uuid/fd1c511e-2bc0-49d5-b8bb-95e7e8c8c816"; }; |
11 | "/etc" = { fsType = "zfs"; device = "zpool/root/etc"; }; | 38 | "/etc" = { fsType = "zfs"; device = "zpool/root/etc"; }; |
12 | "/home" = { fsType = "zfs"; device = "zpool/root/home"; }; | 39 | "/home" = { fsType = "zfs"; device = "zpool/root/home"; }; |
13 | "/home/immae" = { fsType = "zfs"; device = "zpool/root/home/immae"; }; | 40 | "/home/immae" = { fsType = "zfs"; device = "zpool/root/home/immae"; }; |
14 | "/tmp" = { fsType = "zfs"; device = "zpool/root/tmp"; }; | 41 | "/tmp" = { fsType = "zfs"; device = "zpool/root/tmp"; }; |
15 | "/var" = { fsType = "zfs"; device = "zpool/root/var"; }; | 42 | "/var" = { fsType = "zfs"; device = "zpool/root/var"; }; |
43 | "/data" = { fsType = "ext4"; label = "data"; }; | ||
44 | "/nix" = { fsType = "ext4"; label = "nix"; }; | ||
16 | }; | 45 | }; |
17 | boot.initrd.secrets = { | 46 | |
18 | "/boot/pass.key" = "/boot/pass.key"; | 47 | services.udev.extraRules = '' |
19 | }; | 48 | ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="10:bf:48:7f:e6:3b", NAME="eth0" |
49 | ''; | ||
20 | 50 | ||
21 | networking = { | 51 | networking = { |
22 | hostId = "27c3048d"; # generated with head -c4 /dev/urandom | od -A none -t x4 | 52 | hostId = "27c3048d"; # generated with head -c4 /dev/urandom | od -A none -t x4 |
23 | firewall.enable = false; | 53 | firewall.enable = false; |
24 | interfaces."eth0".ipv4.addresses = pkgs.lib.attrsets.mapAttrsToList | 54 | interfaces."eth0".ipv4.addresses = |
25 | (n: ips: { address = ips.ip4; prefixLength = 32; }) | 55 | [ { address = config.hostEnv.ips.main.ip4; prefixLength = 27; } ] |
26 | (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips); | 56 | ++ pkgs.lib.attrsets.mapAttrsToList |
27 | interfaces."eth0".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList | 57 | (n: ips: { address = ips.ip4; prefixLength = 32; }) |
28 | (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or [])) | 58 | (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips); |
29 | config.hostEnv.ips); | 59 | interfaces."eth0".ipv6.addresses = |
60 | [ { address = "2a01:4f8:141:53e7::"; prefixLength = 64; } ] | ||
61 | ++ pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList | ||
62 | (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or [])) | ||
63 | config.hostEnv.ips); | ||
64 | defaultGateway = { address = "176.9.10.225"; interface = "eth0"; }; | ||
65 | defaultGateway6 = { address = "fe80::1"; interface = "eth0"; }; | ||
66 | nameservers = [ | ||
67 | "213.133.98.98" | ||
68 | "213.133.99.99" | ||
69 | "213.133.100.100" | ||
70 | "2a01:4f8:0:a0a1::add:1010" | ||
71 | "2a01:4f8:0:a102::add:9999" | ||
72 | "2a01:4f8:0:a111::add:9898" | ||
73 | ]; | ||
30 | }; | 74 | }; |
31 | 75 | ||
32 | myServices.ssh.modules = [ config.myServices.ssh.predefinedModules.regular ]; | 76 | myServices.ssh.modules = [ config.myServices.ssh.predefinedModules.regular ]; |
33 | imports = builtins.attrValues (import ../..); | 77 | imports = builtins.attrValues (import ../..); |
34 | 78 | ||
35 | deployment = { | ||
36 | targetEnv = "hetzner"; | ||
37 | hetzner = { | ||
38 | robotUser = config.myEnv.hetzner.user; | ||
39 | robotPass = config.myEnv.hetzner.pass; | ||
40 | mainIPv4 = config.hostEnv.ips.main.ip4; | ||
41 | partitions = '' | ||
42 | clearpart --all --initlabel --drives=sda,sdb,sdc,sdd | ||
43 | |||
44 | part swap --recommended --label=swap --fstype=swap --ondisk=sda | ||
45 | |||
46 | part raid.1 --grow --ondisk=sdc | ||
47 | part raid.2 --grow --ondisk=sdd | ||
48 | |||
49 | raid / --level=1 --device=md0 --fstype=ext4 --label=root raid.1 raid.2 | ||
50 | |||
51 | part /nix --grow --label=nix --ondisk=sda | ||
52 | part /data --grow --label=data --ondisk=sdb | ||
53 | ''; | ||
54 | }; | ||
55 | }; | ||
56 | |||
57 | system.nssModules = [ pkgs.libvirt ]; | 79 | system.nssModules = [ pkgs.libvirt ]; |
58 | system.nssDatabases.hosts = lib.mkForce [ "files" "libvirt_guest" "mymachines" "dns" "myhostname" ]; | 80 | system.nssDatabases.hosts = lib.mkForce [ "files" "libvirt_guest" "mymachines" "dns" "myhostname" ]; |
59 | programs.zsh.enable = true; | 81 | programs.zsh.enable = true; |
@@ -78,7 +100,6 @@ | |||
78 | } | 100 | } |
79 | ]; | 101 | ]; |
80 | 102 | ||
81 | boot.kernel.sysctl."vm.nr_hugepages" = 256; # for xmr-stak | ||
82 | system.activationScripts.libvirtd_exports = '' | 103 | system.activationScripts.libvirtd_exports = '' |
83 | install -m 0755 -o root -g root -d /var/lib/caldance | 104 | install -m 0755 -o root -g root -d /var/lib/caldance |
84 | ''; | 105 | ''; |
diff --git a/modules/private/system/eldiron.nix b/modules/private/system/eldiron.nix index 83e52b8..bb8bbfc 100644 --- a/modules/private/system/eldiron.nix +++ b/modules/private/system/eldiron.nix | |||
@@ -1,22 +1,45 @@ | |||
1 | { privateFiles }: | 1 | { privateFiles }: |
2 | { config, pkgs, lib, ... }: | 2 | { config, pkgs, lib, ... }: |
3 | { | 3 | { |
4 | boot.supportedFilesystems = [ "zfs" ]; | 4 | deployment = { |
5 | boot.kernelParams = ["zfs.zfs_arc_max=6442450944"]; | 5 | targetUser = "root"; |
6 | boot.kernelPackages = pkgs.linuxPackages_latest; | 6 | targetHost = config.hostEnv.ips.main.ip4; |
7 | substituteOnDestination = true; | ||
8 | }; | ||
9 | boot = { | ||
10 | kernelModules = [ "kvm-intel" ]; | ||
11 | blacklistedKernelModules = [ "nvidiafb" ]; | ||
12 | loader.timeout = 1; | ||
13 | loader.grub.devices = [ "/dev/sda" "/dev/sdb" ]; | ||
14 | kernel.sysctl = { | ||
15 | # https://github.com/Netflix/security-bulletins/blob/master/advisories/third-party/2019-001.md | ||
16 | "net.ipv4.tcp_sack" = 0; | ||
17 | }; | ||
18 | supportedFilesystems = [ "zfs" ]; | ||
19 | kernelParams = ["zfs.zfs_arc_max=6442450944"]; | ||
20 | kernelPackages = pkgs.linuxPackages_latest; | ||
21 | initrd.availableKernelModules = [ "ahci" "sd_mod" ]; | ||
22 | initrd.secrets = { | ||
23 | "/boot/pass.key" = "/boot/pass.key"; | ||
24 | }; | ||
25 | }; | ||
26 | services.udev.extraRules = '' | ||
27 | ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="c8:60:00:56:a0:88", NAME="eth0" | ||
28 | ''; | ||
29 | nix.maxJobs = 8; | ||
30 | powerManagement.cpuFreqGovernor = "powersave"; | ||
7 | myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; }; | 31 | myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; }; |
8 | 32 | ||
9 | fileSystems = { | 33 | fileSystems = { |
10 | "/" = lib.mkForce { fsType = "zfs"; device = "zpool/root"; }; | 34 | "/" = { fsType = "zfs"; device = "zpool/root"; }; |
11 | "/boot" = { fsType = "ext4"; device = "/dev/disk/by-uuid/e6bb18fb-ff56-4b5f-ae9f-e60d40dc0622"; }; | 35 | "/boot" = { fsType = "ext4"; device = "/dev/disk/by-uuid/e6bb18fb-ff56-4b5f-ae9f-e60d40dc0622"; }; |
12 | "/etc" = { fsType = "zfs"; device = "zpool/root/etc"; }; | 36 | "/etc" = { fsType = "zfs"; device = "zpool/root/etc"; }; |
13 | "/nix" = { fsType = "zfs"; device = "zpool/root/nix"; }; | 37 | "/nix" = { fsType = "zfs"; device = "zpool/root/nix"; }; |
14 | "/tmp" = { fsType = "zfs"; device = "zpool/root/tmp"; }; | 38 | "/tmp" = { fsType = "zfs"; device = "zpool/root/tmp"; }; |
15 | "/var" = { fsType = "zfs"; device = "zpool/root/var"; }; | 39 | "/var" = { fsType = "zfs"; device = "zpool/root/var"; }; |
16 | }; | 40 | }; |
17 | boot.initrd.secrets = { | 41 | swapDevices = [ { label = "swap1"; } { label = "swap2"; } ]; |
18 | "/boot/pass.key" = "/boot/pass.key"; | 42 | hardware.enableRedistributableFirmware = true; |
19 | }; | ||
20 | 43 | ||
21 | services.zfs = { | 44 | services.zfs = { |
22 | autoScrub = { | 45 | autoScrub = { |
@@ -27,20 +50,34 @@ | |||
27 | hostId = "8262ca33"; # generated with head -c4 /dev/urandom | od -A none -t x4 | 50 | hostId = "8262ca33"; # generated with head -c4 /dev/urandom | od -A none -t x4 |
28 | firewall.enable = true; | 51 | firewall.enable = true; |
29 | # 176.9.151.89 declared in nixops -> infra / tools | 52 | # 176.9.151.89 declared in nixops -> infra / tools |
30 | interfaces."eth0".ipv4.addresses = pkgs.lib.attrsets.mapAttrsToList | 53 | interfaces."eth0".ipv4.addresses = |
31 | (n: ips: { address = ips.ip4; prefixLength = 32; }) | 54 | pkgs.lib.attrsets.mapAttrsToList |
32 | (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips); | 55 | (n: ips: { address = ips.ip4; prefixLength = 32; }) |
56 | (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips) | ||
57 | ++ [ { address = config.hostEnv.ips.main.ip4; prefixLength = 27; } ]; | ||
33 | interfaces."eth0".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList | 58 | interfaces."eth0".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList |
34 | (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or [])) | 59 | (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or [])) |
35 | config.hostEnv.ips); | 60 | config.hostEnv.ips); |
61 | defaultGateway = "176.9.151.65"; | ||
62 | localCommands = '' | ||
63 | # FIXME: Those commands were added by nixops and may not be | ||
64 | # actually needed | ||
65 | ip -6 addr add '2a01:4f8:160:3445::/64' dev 'eth0' || true | ||
66 | ip -4 route change '176.9.151.64/27' via '176.9.151.65' dev 'eth0' || true | ||
67 | ip -6 route add default via 'fe80::1' dev eth0 || true | ||
68 | ''; | ||
69 | nameservers = [ | ||
70 | "213.133.98.98" | ||
71 | "213.133.99.99" | ||
72 | "213.133.100.100" | ||
73 | "2a01:4f8:0:a0a1::add:1010" | ||
74 | "2a01:4f8:0:a102::add:9999" | ||
75 | "2a01:4f8:0:a111::add:9898" | ||
76 | ]; | ||
36 | }; | 77 | }; |
37 | 78 | ||
38 | imports = builtins.attrValues (import ../..); | 79 | imports = builtins.attrValues (import ../..); |
39 | 80 | ||
40 | boot.kernel.sysctl = { | ||
41 | # https://github.com/Netflix/security-bulletins/blob/master/advisories/third-party/2019-001.md | ||
42 | "net.ipv4.tcp_sack" = 0; | ||
43 | }; | ||
44 | myServices.buildbot.enable = true; | 81 | myServices.buildbot.enable = true; |
45 | myServices.databases.enable = true; | 82 | myServices.databases.enable = true; |
46 | myServices.gitolite.enable = true; | 83 | myServices.gitolite.enable = true; |
@@ -76,26 +113,6 @@ | |||
76 | "${profile.host_key_type} ${profile.host_key}"; | 113 | "${profile.host_key_type} ${profile.host_key}"; |
77 | }; | 114 | }; |
78 | 115 | ||
79 | deployment = { | ||
80 | targetEnv = "hetzner"; | ||
81 | hetzner = { | ||
82 | robotUser = config.myEnv.hetzner.user; | ||
83 | robotPass = config.myEnv.hetzner.pass; | ||
84 | mainIPv4 = config.hostEnv.ips.main.ip4; | ||
85 | partitions = '' | ||
86 | clearpart --all --initlabel --drives=sda,sdb | ||
87 | |||
88 | part swap1 --recommended --label=swap1 --fstype=swap --ondisk=sda | ||
89 | part swap2 --recommended --label=swap2 --fstype=swap --ondisk=sdb | ||
90 | |||
91 | part raid.1 --grow --ondisk=sda | ||
92 | part raid.2 --grow --ondisk=sdb | ||
93 | |||
94 | raid / --level=1 --device=md0 --fstype=ext4 --label=root raid.1 raid.2 | ||
95 | ''; | ||
96 | }; | ||
97 | }; | ||
98 | |||
99 | services.cron = { | 116 | services.cron = { |
100 | enable = true; | 117 | enable = true; |
101 | mailto = "cron@immae.eu"; | 118 | mailto = "cron@immae.eu"; |
diff --git a/modules/private/system/monitoring-1.nix b/modules/private/system/monitoring-1.nix index c87c784..2241b2b 100644 --- a/modules/private/system/monitoring-1.nix +++ b/modules/private/system/monitoring-1.nix | |||
@@ -1,20 +1,15 @@ | |||
1 | { privateFiles }: | 1 | { privateFiles }: |
2 | { config, pkgs, resources, ... }: | 2 | { config, pkgs, resources, ... }: |
3 | { | 3 | { |
4 | deployment = { | ||
5 | targetUser = "root"; | ||
6 | targetHost = config.hostEnv.ips.main.ip4; | ||
7 | substituteOnDestination = true; | ||
8 | }; | ||
4 | boot.kernelPackages = pkgs.linuxPackages_latest; | 9 | boot.kernelPackages = pkgs.linuxPackages_latest; |
5 | myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; }; | 10 | myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; }; |
6 | 11 | ||
7 | imports = builtins.attrValues (import ../..); | 12 | imports = [ <nixpkgs/nixos/modules/profiles/qemu-guest.nix> ] ++ builtins.attrValues (import ../..); |
8 | |||
9 | deployment = { | ||
10 | targetEnv = "hetznerCloud"; | ||
11 | hetznerCloud = { | ||
12 | authToken = config.myEnv.hetznerCloud.authToken; | ||
13 | datacenter = "hel1-dc2"; | ||
14 | location ="hel1"; | ||
15 | serverType = "cx11"; | ||
16 | }; | ||
17 | }; | ||
18 | 13 | ||
19 | myServices.monitoring.enable = true; | 14 | myServices.monitoring.enable = true; |
20 | myServices.monitoring.master = true; | 15 | myServices.monitoring.master = true; |
@@ -29,6 +24,8 @@ | |||
29 | config.hostEnv.ips); | 24 | config.hostEnv.ips); |
30 | defaultGateway6 = { address = "fe80::1"; interface = "ens3"; }; | 25 | defaultGateway6 = { address = "fe80::1"; interface = "ens3"; }; |
31 | }; | 26 | }; |
27 | boot.loader.grub.device = "nodev"; | ||
28 | fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; }; | ||
32 | myServices.mailRelay.enable = true; | 29 | myServices.mailRelay.enable = true; |
33 | 30 | ||
34 | security.pki.certificateFiles = [ | 31 | security.pki.certificateFiles = [ |
diff --git a/modules/secrets.nix b/modules/secrets.nix index a2424e9..a149f02 100644 --- a/modules/secrets.nix +++ b/modules/secrets.nix | |||
@@ -61,14 +61,13 @@ | |||
61 | fi | 61 | fi |
62 | ''; | 62 | ''; |
63 | }; | 63 | }; |
64 | deployment.keys."secrets.tar" = { | 64 | system.extraDependencies = [ secrets ]; |
65 | deployment.secrets."secrets.tar" = { | ||
66 | source = "${secrets}"; | ||
67 | destination = "/run/keys/secrets.tar"; | ||
68 | owner.user = "root"; | ||
69 | owner.group = "root"; | ||
65 | permissions = "0400"; | 70 | permissions = "0400"; |
66 | # keyFile below is not evaluated at build time by nixops, so the | ||
67 | # `secrets` path doesn’t necessarily exist when uploading the | ||
68 | # keys, and nixops is unhappy. | ||
69 | user = "root${builtins.substring 10000 1 secrets}"; | ||
70 | group = "root"; | ||
71 | keyFile = "${secrets}"; | ||
72 | }; | 71 | }; |
73 | }; | 72 | }; |
74 | } | 73 | } |
diff --git a/nixops/Makefile b/nixops/Makefile index 18d48eb..0bebaf8 100644 --- a/nixops/Makefile +++ b/nixops/Makefile | |||
@@ -2,8 +2,6 @@ ifndef NIXOPS_ENV_LOADED | |||
2 | $(error "Please load environment with direnv") | 2 | $(error "Please load environment with direnv") |
3 | endif | 3 | endif |
4 | 4 | ||
5 | NIXOPS_PRIV = ./scripts/with_env nixops | ||
6 | |||
7 | ###### Current channel information | 5 | ###### Current channel information |
8 | nix-info: | 6 | nix-info: |
9 | @version=$$(nix eval --raw nixpkgs.lib.version) && \ | 7 | @version=$$(nix eval --raw nixpkgs.lib.version) && \ |
@@ -17,100 +15,69 @@ setup: | |||
17 | ./scripts/setup | 15 | ./scripts/setup |
18 | .PHONY: setup | 16 | .PHONY: setup |
19 | 17 | ||
20 | ###### Nixops regular tasks | 18 | ###### Morph regular tasks |
19 | PROFILE=/nix/var/nix/profiles/per-user/immae/morph/immaeEu | ||
21 | TARGET ?= | 20 | TARGET ?= |
22 | NIXOPS_ARGS ?= | 21 | MORPH_ARGS ?= |
23 | ifdef TARGET | 22 | ifdef TARGET |
24 | override NIXOPS_ARGS +=--include=$(TARGET) | 23 | # multiple targets: --on="{machine1,machine2}" (works with * glob too) |
24 | override MORPH_ARGS +=--on=$(TARGET) | ||
25 | endif | 25 | endif |
26 | SSH_ARGS ?= | 26 | SSH_ARGS ?= |
27 | 27 | ||
28 | edit_env: | 28 | edit_env: |
29 | pass edit Nixops/files/environment.nix || true | 29 | pass edit Nixops/files/environment.nix || true |
30 | 30 | ||
31 | nixops: | ||
32 | $(NIXOPS_PRIV) $(NIXOPS_ARGS) | ||
33 | |||
34 | ssh-eldiron: | 31 | ssh-eldiron: |
35 | $(NIXOPS_PRIV) ssh eldiron -- $(SSH_ARGS) | 32 | ./scripts/with_env bash -c 'ssh -i $$SSH_IDENTITY_FILE root@eldiron $(SSH_ARGS)' |
36 | 33 | ||
37 | ssh-dilion: | 34 | ssh-dilion: |
38 | $(NIXOPS_PRIV) ssh dilion -- $(SSH_ARGS) | 35 | ./scripts/with_env bash -c 'ssh -i $$SSH_IDENTITY_FILE root@dilion $(SSH_ARGS)' |
39 | 36 | ||
40 | ssh-backup-2: | 37 | ssh-backup-2: |
41 | $(NIXOPS_PRIV) ssh backup-2 -- $(SSH_ARGS) | 38 | ./scripts/with_env bash -c 'ssh -i $$SSH_IDENTITY_FILE root@backup-2 $(SSH_ARGS)' |
42 | 39 | ||
43 | ssh-monitoring-1: | 40 | ssh-monitoring-1: |
44 | $(NIXOPS_PRIV) ssh monitoring-1 -- $(SSH_ARGS) | 41 | ./scripts/with_env bash -c 'ssh -i $$SSH_IDENTITY_FILE root@monitoring-1 $(SSH_ARGS)' |
45 | |||
46 | info: | ||
47 | $(NIXOPS_PRIV) list | ||
48 | $(NIXOPS_PRIV) info | ||
49 | 42 | ||
50 | debug: | 43 | debug: |
51 | $(NIXOPS_PRIV) deploy --build-only --show-trace $(NIXOPS_ARGS) | 44 | ./scripts/with_env morph build --show-trace default.nix $(MORPH_ARGS) |
52 | |||
53 | dry-run: | ||
54 | $(NIXOPS_PRIV) deploy --dry-run $(NIXOPS_ARGS) | ||
55 | 45 | ||
56 | build: | 46 | build: |
57 | $(NIXOPS_PRIV) deploy --build-only $(NIXOPS_ARGS) | 47 | ./scripts/with_env morph build default.nix $(MORPH_ARGS) |
58 | 48 | ||
59 | upload: | 49 | upload: |
60 | $(NIXOPS_PRIV) deploy --copy-only $(NIXOPS_ARGS) | 50 | ./scripts/with_env morph push default.nix $(MORPH_ARGS) |
61 | 51 | ||
62 | deploy: | 52 | deploy: |
63 | $(NIXOPS_PRIV) deploy $(NIXOPS_ARGS) | 53 | ./scripts/with_env morph deploy default.nix switch --keep-result --upload-secrets $(MORPH_ARGS) |
54 | nix-env -p $(PROFILE) --set .gcroots/default.nix | ||
64 | 55 | ||
65 | deploy-reboot: | 56 | deploy-reboot: |
66 | $(NIXOPS_PRIV) deploy --force-reboot $(NIXOPS_ARGS) | 57 | ./scripts/with_env morph deploy default.nix boot --reboot --upload-secrets $(MORPH_ARGS) |
67 | 58 | ||
68 | reboot: | 59 | .PHONY: ssh-eldiron ssh-dilion ssh-monitoring-1 ssh-backup-2 debug build upload deploy deploy-reboot |
69 | $(NIXOPS_PRIV) reboot --include=$(TARGET) | ||
70 | .PHONY: nixops ssh-eldiron info debug dry-run build upload deploy deploy-reboot reboot | ||
71 | 60 | ||
72 | ###### Cleanup generations and garbage collection | 61 | ###### Cleanup generations and garbage collection |
73 | profile := $$($(NIXOPS_PRIV) info | grep "^Nix profile: " | sed -e "s/^Nix profile: //") | ||
74 | GEN ?= "+3" | 62 | GEN ?= "+3" |
75 | 63 | ||
76 | list-generations: | 64 | list-generations: |
77 | nix-env -p $(profile) --list-generations | 65 | nix-env -p $(PROFILE) --list-generations |
78 | $(NIXOPS_PRIV) ssh eldiron -- nix-env -p /nix/var/nix/profiles/system --list-generations | 66 | $(MAKE) ssh-eldiron SSH_ARGS="nix-env -p /nix/var/nix/profiles/system --list-generations" |
79 | .PHONY: list-generations | 67 | .PHONY: list-generations |
80 | 68 | ||
81 | delete-generations: | 69 | delete-generations: |
82 | nix-env -p $(profile) --delete-generations $(GEN) | 70 | nix-env -p $(PROFILE) --delete-generations $(GEN) |
83 | $(NIXOPS_PRIV) ssh eldiron -- nix-env -p /nix/var/nix/profiles/system --delete-generations $(GEN) | 71 | $(MAKE) ssh-eldiron SSH_ARGS="nix-env -p /nix/var/nix/profiles/system --delete-generations $(GEN)" |
84 | $(NIXOPS_PRIV) ssh dilion -- nix-env -p /nix/var/nix/profiles/system --delete-generations $(GEN) | 72 | $(MAKE) ssh-dilion SSH_ARGS="nix-env -p /nix/var/nix/profiles/system --delete-generations $(GEN)" |
85 | $(NIXOPS_PRIV) ssh backup-2 -- nix-env -p /nix/var/nix/profiles/system --delete-generations $(GEN) | 73 | $(MAKE) ssh-backup-2 SSH_ARGS="nix-env -p /nix/var/nix/profiles/system --delete-generations $(GEN)" |
86 | $(NIXOPS_PRIV) ssh monitoring-1 -- nix-env -p /nix/var/nix/profiles/system --delete-generations $(GEN) | 74 | $(MAKE) ssh-monitoring-1 SSH_ARGS="nix-env -p /nix/var/nix/profiles/system --delete-generations $(GEN)" |
87 | .PHONY: delete-generations | 75 | .PHONY: delete-generations |
88 | 76 | ||
89 | cleanup: delete-generations | 77 | cleanup: delete-generations |
90 | nix-store --gc | 78 | nix-store --gc |
91 | $(NIXOPS_PRIV) ssh eldiron -- nix-store --gc | 79 | $(MAKE) ssh-eldiron SSH_ARGS="nix-store --gc" |
92 | $(NIXOPS_PRIV) ssh dilion -- nix-store --gc | 80 | $(MAKE) ssh-dilion SSH_ARGS="nix-store --gc" |
93 | $(NIXOPS_PRIV) ssh backup-2 -- nix-store --gc | 81 | $(MAKE) ssh-backup-2 SSH_ARGS="nix-store --gc" |
94 | $(NIXOPS_PRIV) ssh monitoring-1 -- nix-store --gc | 82 | $(MAKE) ssh-monitoring-1 SSH_ARGS="nix-store --gc" |
95 | .PHONY: cleanup | 83 | .PHONY: cleanup |
96 | |||
97 | ###### Pull environment and deployment from remote | ||
98 | pull_deployment: | ||
99 | @if nixops info -d $(NIXOPS_DEPLOYMENT) 2>/dev/null >/dev/null ; then \ | ||
100 | echo "This will remove your current deployment file and recreate it!. Continue? [y/N]" && \ | ||
101 | read y && \ | ||
102 | [ "$$y" = "y" -o "$$y" = "Y" ] && \ | ||
103 | nixops delete --force -d $(NIXOPS_DEPLOYMENT); \ | ||
104 | fi | ||
105 | pass show Nixops/Deployment | nixops import | ||
106 | nixops modify -d $(NIXOPS_DEPLOYMENT) "$$(pwd)/default.nix" | ||
107 | .PHONY: pull_deployment | ||
108 | |||
109 | deployment_is_set: | ||
110 | nixops info -d $(NIXOPS_DEPLOYMENT) 2>/dev/null >/dev/null | ||
111 | .PHONY: deployment_is_set | ||
112 | |||
113 | ###### Push deployment information to password store | ||
114 | push_deployment: | ||
115 | nixops export | pass insert -m Nixops/Deployment | ||
116 | .PHONY: push | ||
diff --git a/nixops/default.nix b/nixops/default.nix index 56b86e8..7c6dd38 100644 --- a/nixops/default.nix +++ b/nixops/default.nix | |||
@@ -1,12 +1,7 @@ | |||
1 | { privateFiles ? ./. }: | 1 | let |
2 | privateFiles = <privateFiles>; | ||
3 | in | ||
2 | { | 4 | { |
3 | network = { | ||
4 | description = "Immae's network"; | ||
5 | enableRollback = true; | ||
6 | }; | ||
7 | |||
8 | # Used by hetzner cloud to provision machines | ||
9 | resources.sshKeyPairs.ssh-key = {}; | ||
10 | dilion = import ../modules/private/system/dilion.nix { inherit privateFiles; }; | 5 | dilion = import ../modules/private/system/dilion.nix { inherit privateFiles; }; |
11 | eldiron = import ../modules/private/system/eldiron.nix { inherit privateFiles; }; | 6 | eldiron = import ../modules/private/system/eldiron.nix { inherit privateFiles; }; |
12 | backup-2 = import ../modules/private/system/backup-2.nix { inherit privateFiles; }; | 7 | backup-2 = import ../modules/private/system/backup-2.nix { inherit privateFiles; }; |
diff --git a/nixops/scripts/setup b/nixops/scripts/setup index 22f43ce..e161e43 100755 --- a/nixops/scripts/setup +++ b/nixops/scripts/setup | |||
@@ -2,8 +2,6 @@ | |||
2 | 2 | ||
3 | set -euo pipefail | 3 | set -euo pipefail |
4 | 4 | ||
5 | MAKEFILE_DIR="$( cd "$( dirname $( dirname "${BASH_SOURCE[0]}" ))" >/dev/null 2>&1 && pwd )" | ||
6 | |||
7 | if ! which nix 2>/dev/null >/dev/null; then | 5 | if ! which nix 2>/dev/null >/dev/null; then |
8 | cat <<-EOF | 6 | cat <<-EOF |
9 | nix is needed, please install it: | 7 | nix is needed, please install it: |
@@ -62,20 +60,6 @@ if nix show-config --json | jq -e '.sandbox.value == "true"' >/dev/null; then | |||
62 | read y | 60 | read y |
63 | fi | 61 | fi |
64 | 62 | ||
65 | if ! make -C $MAKEFILE_DIR deployment_is_set 2>/dev/null >/dev/null; then | ||
66 | cat <<-EOF | ||
67 | Importing deployment file into nixops: | ||
68 | Continue? [y/N] | ||
69 | EOF | ||
70 | read y | ||
71 | if [ "$y" = "y" -o "$y" = "Y" ]; then | ||
72 | make -C $MAKEFILE_DIR pull_deployment | ||
73 | else | ||
74 | echo "Aborting" | ||
75 | exit 1 | ||
76 | fi | ||
77 | fi | ||
78 | |||
79 | cat <<-EOF | 63 | cat <<-EOF |
80 | All set up. | 64 | All set up. |
81 | Please make sure you’re using make commands when deploying | 65 | Please make sure you’re using make commands when deploying |
diff --git a/nixops/scripts/with_env b/nixops/scripts/with_env index 9882f78..f8e5537 100755 --- a/nixops/scripts/with_env +++ b/nixops/scripts/with_env | |||
@@ -5,12 +5,12 @@ if [ -z "$NIXOPS_ENV_LOADED" ]; then | |||
5 | exit 1; | 5 | exit 1; |
6 | fi | 6 | fi |
7 | 7 | ||
8 | umask 0077 | ||
8 | TEMP=$(mktemp -d /tmp/XXXXXX-nixops-files) | 9 | TEMP=$(mktemp -d /tmp/XXXXXX-nixops-files) |
9 | chmod go-rwx $TEMP | 10 | chmod go-rwx $TEMP |
10 | 11 | ||
11 | finish() { | 12 | finish() { |
12 | rm -rf "$TEMP" | 13 | rm -rf "$TEMP" |
13 | nixops set-args --unset privateFiles | ||
14 | } | 14 | } |
15 | 15 | ||
16 | trap finish EXIT | 16 | trap finish EXIT |
@@ -21,6 +21,8 @@ files=$(pass ls Nixops/files | sed -e '1d' -e 's/^.* //') | |||
21 | for file in $files; do | 21 | for file in $files; do |
22 | pass show "Nixops/files/$file" > $TEMP/$file | 22 | pass show "Nixops/files/$file" > $TEMP/$file |
23 | done | 23 | done |
24 | nixops set-args --argstr privateFiles "$TEMP" | 24 | |
25 | export NIX_PATH="privateFiles=$TEMP:$NIX_PATH" | ||
26 | export SSH_IDENTITY_FILE="$TEMP/id_ed25519" | ||
25 | 27 | ||
26 | "$@" | 28 | "$@" |
diff --git a/nixops/secrets b/nixops/secrets | |||
Subproject 79b991028b09aa59f719059de8dc1fba7d6b04f | Subproject def4146f0e703ca9a32735fbbc3820d6f9bb22e | ||
diff --git a/nixops/state/.gitkeep b/nixops/state/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/nixops/state/.gitkeep +++ /dev/null | |||
diff --git a/overlays/default.nix b/overlays/default.nix index 0c7c738..7444e15 100644 --- a/overlays/default.nix +++ b/overlays/default.nix | |||
@@ -32,5 +32,6 @@ | |||
32 | doing = import ./doing; | 32 | doing = import ./doing; |
33 | khal = import ./khal; | 33 | khal = import ./khal; |
34 | nix-direnv = import ./nix-direnv; | 34 | nix-direnv = import ./nix-direnv; |
35 | morph = import ./morph; | ||
35 | } | 36 | } |
36 | // import ./python-packages | 37 | // import ./python-packages |
diff --git a/overlays/morph/default.nix b/overlays/morph/default.nix new file mode 100644 index 0000000..ee59e25 --- /dev/null +++ b/overlays/morph/default.nix | |||
@@ -0,0 +1,5 @@ | |||
1 | self: super: { | ||
2 | morph = super.morph.overrideAttrs(old: { | ||
3 | patches = (old.patches or []) ++ [ ./verbose_nix.patch ]; | ||
4 | }); | ||
5 | } | ||
diff --git a/overlays/morph/verbose_nix.patch b/overlays/morph/verbose_nix.patch new file mode 100644 index 0000000..389a79c --- /dev/null +++ b/overlays/morph/verbose_nix.patch | |||
@@ -0,0 +1,12 @@ | |||
1 | diff --git a/nix/nix.go b/nix/nix.go | ||
2 | index bb63870..7fe04aa 100644 | ||
3 | --- a/nix/nix.go | ||
4 | +++ b/nix/nix.go | ||
5 | @@ -347,6 +347,7 @@ func Push(ctx *ssh.SSHContext, host Host, paths ...string) (err error) { | ||
6 | options := mkOptions(host) | ||
7 | for _, path := range paths { | ||
8 | args := []string{ | ||
9 | + "-v", | ||
10 | "copy", | ||
11 | path, | ||
12 | "--to", "ssh://" + userArg + host.TargetHost + keyArg, | ||
@@ -1,4 +1,4 @@ | |||
1 | { pkgs ? import <nixpkgs> { overlays = builtins.attrValues (import ./overlays); } }: | 1 | { pkgs ? import <nixpkgs> { overlays = builtins.attrValues (import ./overlays); } }: |
2 | pkgs.mkShell { | 2 | pkgs.mkShell { |
3 | buildInputs = [ pkgs.nixops pkgs.niv pkgs.pass pkgs.curl pkgs.shellcheck pkgs.jq pkgs.gnumake ]; | 3 | buildInputs = [ pkgs.morph pkgs.niv pkgs.pass pkgs.curl pkgs.shellcheck pkgs.jq pkgs.gnumake ]; |
4 | } | 4 | } |