···30 </section>
31 <section xml:id="sec-release-23.05-incompatibilities">
32 <title>Backward Incompatibilities</title>
33+ <itemizedlist>
34 <listitem>
35 <para>
36 <literal>carnix</literal> and <literal>cratesIO</literal> has
···40 and
41 <link xlink:href="https://github.com/kolloch/crate2nix">crate2nix</link>
42 instead.
43+ </para>
44+ </listitem>
45+ <listitem>
46+ <para>
47+ The EC2 image module no longer fetches instance metadata in
48+ stage-1. This results in a significantly smaller initramfs,
49+ since network drivers no longer need to be included, and
50+ faster boots, since metadata fetching can happen in parallel
51+ with startup of other services. This breaks services which
52+ rely on metadata being present by the time stage-2 is entered.
53+ Anything which reads EC2 metadata from
54+ <literal>/etc/ec2-metadata</literal> should now have an
55+ <literal>after</literal> dependency on
56+ <literal>fetch-ec2-metadata.service</literal>
57+ </para>
58+ </listitem>
59+ <listitem>
60+ <para>
61+ The EC2 image module previously detected and automatically
62+ mounted ext3-formatted instance store devices and partitions
63+ in stage-1 (initramfs), storing <literal>/tmp</literal> on the
64+ first discovered device. This behaviour, which only catered to
65+ very specific use cases and could not be disabled, has been
66+ removed. Users relying on this should provide their own
67+ implementation, and probably use ext4 and perform the mount in
68+ stage-2.
69+ </para>
70+ </listitem>
71+ <listitem>
72+ <para>
73+ The EC2 image module previously detected and activated
74+ swap-formatted instance store devices and partitions in
75+ stage-1 (initramfs). This behaviour has been removed. Users
76+ relying on this should provide their own implementation.
77 </para>
78 </listitem>
79 </itemizedlist>
+7
nixos/doc/manual/release-notes/rl-2305.section.md
···2223- `carnix` and `cratesIO` has been removed due to being unmaintained, use alternatives such as [naersk](https://github.com/nix-community/naersk) and [crate2nix](https://github.com/kolloch/crate2nix) instead.
24000000025## Other Notable Changes {#sec-release-23.05-notable-changes}
2627<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
···2223- `carnix` and `cratesIO` has been removed due to being unmaintained, use alternatives such as [naersk](https://github.com/nix-community/naersk) and [crate2nix](https://github.com/kolloch/crate2nix) instead.
2425+- The EC2 image module no longer fetches instance metadata in stage-1. This results in a significantly smaller initramfs, since network drivers no longer need to be included, and faster boots, since metadata fetching can happen in parallel with startup of other services.
26+ This breaks services which rely on metadata being present by the time stage-2 is entered. Anything which reads EC2 metadata from `/etc/ec2-metadata` should now have an `after` dependency on `fetch-ec2-metadata.service`
27+28+- The EC2 image module previously detected and automatically mounted ext3-formatted instance store devices and partitions in stage-1 (initramfs), storing `/tmp` on the first discovered device. This behaviour, which only catered to very specific use cases and could not be disabled, has been removed. Users relying on this should provide their own implementation, and probably use ext4 and perform the mount in stage-2.
29+30+- The EC2 image module previously detected and activated swap-formatted instance store devices and partitions in stage-1 (initramfs). This behaviour has been removed. Users relying on this should provide their own implementation.
31+32## Other Notable Changes {#sec-release-23.05-notable-changes}
3334<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+2-7
nixos/maintainers/scripts/ec2/amazon-image.nix
···4344 sizeMB = mkOption {
45 type = with types; either (enum [ "auto" ]) int;
46- default = if config.ec2.hvm then 2048 else 8192;
47 example = 8192;
48 description = lib.mdDoc "The size in MB of the image";
49 };
···60 ''
61 { modulesPath, ... }: {
62 imports = [ "''${modulesPath}/virtualisation/amazon-image.nix" ];
63- ${optionalString config.ec2.hvm ''
64- ec2.hvm = true;
65- ''}
66 ${optionalString config.ec2.efi ''
67 ec2.efi = true;
68 ''}
···129 pkgs = import ../../../.. { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package
130131 fsType = "ext4";
132- partitionTableType = if config.ec2.efi then "efi"
133- else if config.ec2.hvm then "legacy+gpt"
134- else "none";
135136 diskSize = cfg.sizeMB;
137
···4344 sizeMB = mkOption {
45 type = with types; either (enum [ "auto" ]) int;
46+ default = 2048;
47 example = 8192;
48 description = lib.mdDoc "The size in MB of the image";
49 };
···60 ''
61 { modulesPath, ... }: {
62 imports = [ "''${modulesPath}/virtualisation/amazon-image.nix" ];
00063 ${optionalString config.ec2.efi ''
64 ec2.efi = true;
65 ''}
···126 pkgs = import ../../../.. { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package
127128 fsType = "ext4";
129+ partitionTableType = if config.ec2.efi then "efi" else "legacy+gpt";
00130131 diskSize = cfg.sizeMB;
132
+13-82
nixos/modules/virtualisation/amazon-image.nix
···1011let
12 cfg = config.ec2;
13- metadataFetcher = import ./ec2-metadata-fetcher.nix {
14- inherit (pkgs) curl;
15- targetRoot = "$targetRoot/";
16- wgetExtraOptions = "-q";
17- };
18in
1920{
···31 config = {
3233 assertions = [
34- { assertion = cfg.hvm;
35- message = "Paravirtualized EC2 instances are no longer supported.";
36- }
37- { assertion = cfg.efi -> cfg.hvm;
38- message = "EC2 instances using EFI must be HVM instances.";
39- }
40 { assertion = versionOlder config.boot.kernelPackages.kernel.version "5.17";
41 message = "ENA driver fails to build with kernel >= 5.17";
42 }
43 ];
4445- boot.growPartition = cfg.hvm;
4647 fileSystems."/" = mkIf (!cfg.zfs.enable) {
48 device = "/dev/disk/by-label/nixos";
···64 boot.extraModulePackages = [
65 config.boot.kernelPackages.ena
66 ];
67- boot.initrd.kernelModules = [ "xen-blkfront" "xen-netfront" ];
68- boot.initrd.availableKernelModules = [ "ixgbevf" "ena" "nvme" ];
69- boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0,115200n8" "random.trust_cpu=on" ];
7071 # Prevent the nouveau kernel module from being loaded, as it
72 # interferes with the nvidia/nvidia-uvm modules needed for CUDA.
···74 # boot.
75 boot.blacklistedKernelModules = [ "nouveau" "xen_fbfront" ];
7677- # Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd.
78- boot.loader.grub.version = if cfg.hvm then 2 else 1;
79- boot.loader.grub.device = if (cfg.hvm && !cfg.efi) then "/dev/xvda" else "nodev";
80- boot.loader.grub.extraPerEntryConfig = mkIf (!cfg.hvm) "root (hd0)";
81 boot.loader.grub.efiSupport = cfg.efi;
82 boot.loader.grub.efiInstallAsRemovable = cfg.efi;
83 boot.loader.timeout = 1;
···87 terminal_input console serial
88 '';
8990- boot.initrd.network.enable = true;
91-92- # Mount all formatted ephemeral disks and activate all swap devices.
93- # We cannot do this with the ‘fileSystems’ and ‘swapDevices’ options
94- # because the set of devices is dependent on the instance type
95- # (e.g. "m1.small" has one ephemeral filesystem and one swap device,
96- # while "m1.large" has two ephemeral filesystems and no swap
97- # devices). Also, put /tmp and /var on /disk0, since it has a lot
98- # more space than the root device. Similarly, "move" /nix to /disk0
99- # by layering a unionfs-fuse mount on top of it so we have a lot more space for
100- # Nix operations.
101- boot.initrd.postMountCommands =
102- ''
103- ${metadataFetcher}
104-105- diskNr=0
106- diskForUnionfs=
107- for device in /dev/xvd[abcde]*; do
108- if [ "$device" = /dev/xvda -o "$device" = /dev/xvda1 ]; then continue; fi
109- fsType=$(blkid -o value -s TYPE "$device" || true)
110- if [ "$fsType" = swap ]; then
111- echo "activating swap device $device..."
112- swapon "$device" || true
113- elif [ "$fsType" = ext3 ]; then
114- mp="/disk$diskNr"
115- diskNr=$((diskNr + 1))
116- if mountFS "$device" "$mp" "" ext3; then
117- if [ -z "$diskForUnionfs" ]; then diskForUnionfs="$mp"; fi
118- fi
119- else
120- echo "skipping unknown device type $device"
121- fi
122- done
123-124- if [ -n "$diskForUnionfs" ]; then
125- mkdir -m 755 -p $targetRoot/$diskForUnionfs/root
126-127- mkdir -m 1777 -p $targetRoot/$diskForUnionfs/root/tmp $targetRoot/tmp
128- mount --bind $targetRoot/$diskForUnionfs/root/tmp $targetRoot/tmp
129-130- if [ "$(cat "$metaDir/ami-manifest-path")" != "(unknown)" ]; then
131- mkdir -m 755 -p $targetRoot/$diskForUnionfs/root/var $targetRoot/var
132- mount --bind $targetRoot/$diskForUnionfs/root/var $targetRoot/var
133-134- mkdir -p /unionfs-chroot/ro-nix
135- mount --rbind $targetRoot/nix /unionfs-chroot/ro-nix
136-137- mkdir -m 755 -p $targetRoot/$diskForUnionfs/root/nix
138- mkdir -p /unionfs-chroot/rw-nix
139- mount --rbind $targetRoot/$diskForUnionfs/root/nix /unionfs-chroot/rw-nix
140-141- unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot,max_files=32768 /rw-nix=RW:/ro-nix=RO $targetRoot/nix
142- fi
143- fi
144- '';
145-146- boot.initrd.extraUtilsCommands =
147- ''
148- # We need swapon in the initrd.
149- copy_bin_and_libs ${pkgs.util-linux}/sbin/swapon
150- '';
151152 # Allow root logins only using the SSH key that the user specified
153 # at instance creation time.
···165166 # Always include cryptsetup so that Charon can use it.
167 environment.systemPackages = [ pkgs.cryptsetup ];
168-169- boot.initrd.supportedFilesystems = [ "unionfs-fuse" ];
170171 # EC2 has its own NTP server provided by the hypervisor
172 networking.timeServers = [ "169.254.169.123" ];
···1011let
12 cfg = config.ec2;
0000013in
1415{
···26 config = {
2728 assertions = [
00000029 { assertion = versionOlder config.boot.kernelPackages.kernel.version "5.17";
30 message = "ENA driver fails to build with kernel >= 5.17";
31 }
32 ];
3334+ boot.growPartition = true;
3536 fileSystems."/" = mkIf (!cfg.zfs.enable) {
37 device = "/dev/disk/by-label/nixos";
···53 boot.extraModulePackages = [
54 config.boot.kernelPackages.ena
55 ];
56+ boot.initrd.kernelModules = [ "xen-blkfront" ];
57+ boot.initrd.availableKernelModules = [ "nvme" ];
58+ boot.kernelParams = [ "console=ttyS0,115200n8" "random.trust_cpu=on" ];
5960 # Prevent the nouveau kernel module from being loaded, as it
61 # interferes with the nvidia/nvidia-uvm modules needed for CUDA.
···63 # boot.
64 boot.blacklistedKernelModules = [ "nouveau" "xen_fbfront" ];
6566+ boot.loader.grub.device = if cfg.efi then "nodev" else "/dev/xvda";
00067 boot.loader.grub.efiSupport = cfg.efi;
68 boot.loader.grub.efiInstallAsRemovable = cfg.efi;
69 boot.loader.timeout = 1;
···73 terminal_input console serial
74 '';
7576+ systemd.services.fetch-ec2-metadata = {
77+ wantedBy = [ "multi-user.target" ];
78+ after = ["network-online.target"];
79+ path = [ pkgs.curl ];
80+ script = builtins.readFile ./ec2-metadata-fetcher.sh;
81+ serviceConfig.Type = "oneshot";
82+ serviceConfig.StandardOutput = "journal+console";
83+ };
000000000000000000000000000000000000000000000000000008485 # Allow root logins only using the SSH key that the user specified
86 # at instance creation time.
···9899 # Always include cryptsetup so that Charon can use it.
100 environment.systemPackages = [ pkgs.cryptsetup ];
00101102 # EC2 has its own NTP server provided by the hypervisor
103 networking.timeServers = [ "169.254.169.123" ];
···1-{ curl, targetRoot, wgetExtraOptions }:
2-# Note: be very cautious about dependencies, each dependency grows
3-# the closure of the initrd. Ideally we would not even require curl,
4-# but there is no reasonable way to send an HTTP PUT request without
5-# it. Note: do not be fooled: the wget referenced in this script
6-# is busybox's wget, not the fully featured one with --method support.
7-#
8-# Make sure that every package you depend on here is already listed as
9-# a channel blocker for both the full-sized and small channels.
10-# Otherwise, we risk breaking user deploys in released channels.
11-#
12-# Also note: OpenStack's metadata service for its instances aims to be
13-# compatible with the EC2 IMDS. Where possible, try to keep the set of
14-# fetched metadata in sync with ./openstack-metadata-fetcher.nix .
15-''
16- metaDir=${targetRoot}etc/ec2-metadata
17- mkdir -m 0755 -p "$metaDir"
18- rm -f "$metaDir/*"
19-20- get_imds_token() {
21- # retry-delay of 1 selected to give the system a second to get going,
22- # but not add a lot to the bootup time
23- ${curl}/bin/curl \
24- -v \
25- --retry 3 \
26- --retry-delay 1 \
27- --fail \
28- -X PUT \
29- --connect-timeout 1 \
30- -H "X-aws-ec2-metadata-token-ttl-seconds: 600" \
31- http://169.254.169.254/latest/api/token
32- }
33-34- preflight_imds_token() {
35- # retry-delay of 1 selected to give the system a second to get going,
36- # but not add a lot to the bootup time
37- ${curl}/bin/curl \
38- -v \
39- --retry 3 \
40- --retry-delay 1 \
41- --fail \
42- --connect-timeout 1 \
43- -H "X-aws-ec2-metadata-token: $IMDS_TOKEN" \
44- http://169.254.169.254/1.0/meta-data/instance-id
45- }
46-47- try=1
48- while [ $try -le 3 ]; do
49- echo "(attempt $try/3) getting an EC2 instance metadata service v2 token..."
50- IMDS_TOKEN=$(get_imds_token) && break
51- try=$((try + 1))
52- sleep 1
53- done
54-55- if [ "x$IMDS_TOKEN" == "x" ]; then
56- echo "failed to fetch an IMDS2v token."
57- fi
58-59- try=1
60- while [ $try -le 10 ]; do
61- echo "(attempt $try/10) validating the EC2 instance metadata service v2 token..."
62- preflight_imds_token && break
63- try=$((try + 1))
64- sleep 1
65- done
66-67- echo "getting EC2 instance metadata..."
68-69- wget_imds() {
70- wget ${wgetExtraOptions} --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" "$@";
71- }
72-73- wget_imds -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path
74- (umask 077 && wget_imds -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data)
75- wget_imds -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname
76- wget_imds -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key
77-''
···1+metaDir=/etc/ec2-metadata
2+mkdir -m 0755 -p "$metaDir"
3+rm -f "$metaDir/*"
4+5+get_imds_token() {
6+ # retry-delay of 1 selected to give the system a second to get going,
7+ # but not add a lot to the bootup time
8+ curl \
9+ --silent \
10+ --show-error \
11+ --retry 3 \
12+ --retry-delay 1 \
13+ --fail \
14+ -X PUT \
15+ --connect-timeout 1 \
16+ -H "X-aws-ec2-metadata-token-ttl-seconds: 600" \
17+ http://169.254.169.254/latest/api/token
18+}
19+20+preflight_imds_token() {
21+ # retry-delay of 1 selected to give the system a second to get going,
22+ # but not add a lot to the bootup time
23+ curl \
24+ --silent \
25+ --show-error \
26+ --retry 3 \
27+ --retry-delay 1 \
28+ --fail \
29+ --connect-timeout 1 \
30+ -H "X-aws-ec2-metadata-token: $IMDS_TOKEN" \
31+ -o /dev/null \
32+ http://169.254.169.254/1.0/meta-data/instance-id
33+}
34+35+try=1
36+while [ $try -le 3 ]; do
37+ echo "(attempt $try/3) getting an EC2 instance metadata service v2 token..."
38+ IMDS_TOKEN=$(get_imds_token) && break
39+ try=$((try + 1))
40+ sleep 1
41+done
42+43+if [ "x$IMDS_TOKEN" == "x" ]; then
44+ echo "failed to fetch an IMDS2v token."
45+fi
46+47+try=1
48+while [ $try -le 10 ]; do
49+ echo "(attempt $try/10) validating the EC2 instance metadata service v2 token..."
50+ preflight_imds_token && break
51+ try=$((try + 1))
52+ sleep 1
53+done
54+55+echo "getting EC2 instance metadata..."
56+57+get_imds() {
58+ # Intentionally no --fail here, so that we proceed even if e.g. a
59+ # 404 was returned (but we still fail if we can't reach the IMDS
60+ # server).
61+ curl --silent --show-error --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" "$@"
62+}
63+64+get_imds -o "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path
65+(umask 077 && get_imds -o "$metaDir/user-data" http://169.254.169.254/1.0/user-data)
66+get_imds -o "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname
67+get_imds -o "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key
···16 ../modules/testing/test-instrumentation.nix
17 ../modules/profiles/qemu-guest.nix
18 {
19- ec2.hvm = true;
20-21 # Hack to make the partition resizing work in QEMU.
22 boot.initrd.postDeviceCommands = mkBefore ''
23 ln -s vda /dev/xvda
···16 ../modules/testing/test-instrumentation.nix
17 ../modules/profiles/qemu-guest.nix
18 {
0019 # Hack to make the partition resizing work in QEMU.
20 boot.initrd.postDeviceCommands = mkBefore ''
21 ln -s vda /dev/xvda
+2
nixos/tests/patroni.nix
···166167 start_all()
16800169 with subtest("should bootstrap a new patroni cluster"):
170 wait_for_all_nodes_ready()
171
···166167 start_all()
168169+ etcd.wait_for_unit("etcd.service")
170+171 with subtest("should bootstrap a new patroni cluster"):
172 wait_for_all_nodes_ready()
173