···3030 </section>
3131 <section xml:id="sec-release-23.05-incompatibilities">
3232 <title>Backward Incompatibilities</title>
3333- <itemizedlist spacing="compact">
3333+ <itemizedlist>
3434 <listitem>
3535 <para>
3636 <literal>carnix</literal> and <literal>cratesIO</literal> has
···4040 and
4141 <link xlink:href="https://github.com/kolloch/crate2nix">crate2nix</link>
4242 instead.
4343+ </para>
4444+ </listitem>
4545+ <listitem>
4646+ <para>
4747+ The EC2 image module no longer fetches instance metadata in
4848+ stage-1. This results in a significantly smaller initramfs,
4949+ since network drivers no longer need to be included, and
5050+ faster boots, since metadata fetching can happen in parallel
5151+ with startup of other services. This breaks services which
5252+ rely on metadata being present by the time stage-2 is entered.
5353+ Anything which reads EC2 metadata from
5454+ <literal>/etc/ec2-metadata</literal> should now have an
5555+ <literal>after</literal> dependency on
5656+ <literal>fetch-ec2-metadata.service</literal>
5757+ </para>
5858+ </listitem>
5959+ <listitem>
6060+ <para>
6161+ The EC2 image module previously detected and automatically
6262+ mounted ext3-formatted instance store devices and partitions
6363+ in stage-1 (initramfs), storing <literal>/tmp</literal> on the
6464+ first discovered device. This behaviour, which only catered to
6565+ very specific use cases and could not be disabled, has been
6666+ removed. Users relying on this should provide their own
6767+ implementation, and probably use ext4 and perform the mount in
6868+ stage-2.
6969+ </para>
7070+ </listitem>
7171+ <listitem>
7272+ <para>
7373+ The EC2 image module previously detected and activated
7474+ swap-formatted instance store devices and partitions in
7575+ stage-1 (initramfs). This behaviour has been removed. Users
7676+ relying on this should provide their own implementation.
4377 </para>
4478 </listitem>
4579 </itemizedlist>
+7
nixos/doc/manual/release-notes/rl-2305.section.md
···22222323- `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.
24242525+- 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.
2626+ 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`
2727+2828+- 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.
2929+3030+- 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.
3131+2532## Other Notable Changes {#sec-release-23.05-notable-changes}
26332734<!-- 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
···43434444 sizeMB = mkOption {
4545 type = with types; either (enum [ "auto" ]) int;
4646- default = if config.ec2.hvm then 2048 else 8192;
4646+ default = 2048;
4747 example = 8192;
4848 description = lib.mdDoc "The size in MB of the image";
4949 };
···6060 ''
6161 { modulesPath, ... }: {
6262 imports = [ "''${modulesPath}/virtualisation/amazon-image.nix" ];
6363- ${optionalString config.ec2.hvm ''
6464- ec2.hvm = true;
6565- ''}
6663 ${optionalString config.ec2.efi ''
6764 ec2.efi = true;
6865 ''}
···129126 pkgs = import ../../../.. { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package
130127131128 fsType = "ext4";
132132- partitionTableType = if config.ec2.efi then "efi"
133133- else if config.ec2.hvm then "legacy+gpt"
134134- else "none";
129129+ partitionTableType = if config.ec2.efi then "efi" else "legacy+gpt";
135130136131 diskSize = cfg.sizeMB;
137132
+13-82
nixos/modules/virtualisation/amazon-image.nix
···10101111let
1212 cfg = config.ec2;
1313- metadataFetcher = import ./ec2-metadata-fetcher.nix {
1414- inherit (pkgs) curl;
1515- targetRoot = "$targetRoot/";
1616- wgetExtraOptions = "-q";
1717- };
1813in
19142015{
···3126 config = {
32273328 assertions = [
3434- { assertion = cfg.hvm;
3535- message = "Paravirtualized EC2 instances are no longer supported.";
3636- }
3737- { assertion = cfg.efi -> cfg.hvm;
3838- message = "EC2 instances using EFI must be HVM instances.";
3939- }
4029 { assertion = versionOlder config.boot.kernelPackages.kernel.version "5.17";
4130 message = "ENA driver fails to build with kernel >= 5.17";
4231 }
4332 ];
44334545- boot.growPartition = cfg.hvm;
3434+ boot.growPartition = true;
46354736 fileSystems."/" = mkIf (!cfg.zfs.enable) {
4837 device = "/dev/disk/by-label/nixos";
···6453 boot.extraModulePackages = [
6554 config.boot.kernelPackages.ena
6655 ];
6767- boot.initrd.kernelModules = [ "xen-blkfront" "xen-netfront" ];
6868- boot.initrd.availableKernelModules = [ "ixgbevf" "ena" "nvme" ];
6969- boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0,115200n8" "random.trust_cpu=on" ];
5656+ boot.initrd.kernelModules = [ "xen-blkfront" ];
5757+ boot.initrd.availableKernelModules = [ "nvme" ];
5858+ boot.kernelParams = [ "console=ttyS0,115200n8" "random.trust_cpu=on" ];
70597160 # Prevent the nouveau kernel module from being loaded, as it
7261 # interferes with the nvidia/nvidia-uvm modules needed for CUDA.
···7463 # boot.
7564 boot.blacklistedKernelModules = [ "nouveau" "xen_fbfront" ];
76657777- # Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd.
7878- boot.loader.grub.version = if cfg.hvm then 2 else 1;
7979- boot.loader.grub.device = if (cfg.hvm && !cfg.efi) then "/dev/xvda" else "nodev";
8080- boot.loader.grub.extraPerEntryConfig = mkIf (!cfg.hvm) "root (hd0)";
6666+ boot.loader.grub.device = if cfg.efi then "nodev" else "/dev/xvda";
8167 boot.loader.grub.efiSupport = cfg.efi;
8268 boot.loader.grub.efiInstallAsRemovable = cfg.efi;
8369 boot.loader.timeout = 1;
···8773 terminal_input console serial
8874 '';
89759090- boot.initrd.network.enable = true;
9191-9292- # Mount all formatted ephemeral disks and activate all swap devices.
9393- # We cannot do this with the ‘fileSystems’ and ‘swapDevices’ options
9494- # because the set of devices is dependent on the instance type
9595- # (e.g. "m1.small" has one ephemeral filesystem and one swap device,
9696- # while "m1.large" has two ephemeral filesystems and no swap
9797- # devices). Also, put /tmp and /var on /disk0, since it has a lot
9898- # more space than the root device. Similarly, "move" /nix to /disk0
9999- # by layering a unionfs-fuse mount on top of it so we have a lot more space for
100100- # Nix operations.
101101- boot.initrd.postMountCommands =
102102- ''
103103- ${metadataFetcher}
104104-105105- diskNr=0
106106- diskForUnionfs=
107107- for device in /dev/xvd[abcde]*; do
108108- if [ "$device" = /dev/xvda -o "$device" = /dev/xvda1 ]; then continue; fi
109109- fsType=$(blkid -o value -s TYPE "$device" || true)
110110- if [ "$fsType" = swap ]; then
111111- echo "activating swap device $device..."
112112- swapon "$device" || true
113113- elif [ "$fsType" = ext3 ]; then
114114- mp="/disk$diskNr"
115115- diskNr=$((diskNr + 1))
116116- if mountFS "$device" "$mp" "" ext3; then
117117- if [ -z "$diskForUnionfs" ]; then diskForUnionfs="$mp"; fi
118118- fi
119119- else
120120- echo "skipping unknown device type $device"
121121- fi
122122- done
123123-124124- if [ -n "$diskForUnionfs" ]; then
125125- mkdir -m 755 -p $targetRoot/$diskForUnionfs/root
126126-127127- mkdir -m 1777 -p $targetRoot/$diskForUnionfs/root/tmp $targetRoot/tmp
128128- mount --bind $targetRoot/$diskForUnionfs/root/tmp $targetRoot/tmp
129129-130130- if [ "$(cat "$metaDir/ami-manifest-path")" != "(unknown)" ]; then
131131- mkdir -m 755 -p $targetRoot/$diskForUnionfs/root/var $targetRoot/var
132132- mount --bind $targetRoot/$diskForUnionfs/root/var $targetRoot/var
133133-134134- mkdir -p /unionfs-chroot/ro-nix
135135- mount --rbind $targetRoot/nix /unionfs-chroot/ro-nix
136136-137137- mkdir -m 755 -p $targetRoot/$diskForUnionfs/root/nix
138138- mkdir -p /unionfs-chroot/rw-nix
139139- mount --rbind $targetRoot/$diskForUnionfs/root/nix /unionfs-chroot/rw-nix
140140-141141- unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot,max_files=32768 /rw-nix=RW:/ro-nix=RO $targetRoot/nix
142142- fi
143143- fi
144144- '';
145145-146146- boot.initrd.extraUtilsCommands =
147147- ''
148148- # We need swapon in the initrd.
149149- copy_bin_and_libs ${pkgs.util-linux}/sbin/swapon
150150- '';
7676+ systemd.services.fetch-ec2-metadata = {
7777+ wantedBy = [ "multi-user.target" ];
7878+ after = ["network-online.target"];
7979+ path = [ pkgs.curl ];
8080+ script = builtins.readFile ./ec2-metadata-fetcher.sh;
8181+ serviceConfig.Type = "oneshot";
8282+ serviceConfig.StandardOutput = "journal+console";
8383+ };
1518415285 # Allow root logins only using the SSH key that the user specified
15386 # at instance creation time.
···1659816699 # Always include cryptsetup so that Charon can use it.
167100 environment.systemPackages = [ pkgs.cryptsetup ];
168168-169169- boot.initrd.supportedFilesystems = [ "unionfs-fuse" ];
170101171102 # EC2 has its own NTP server provided by the hypervisor
172103 networking.timeServers = [ "169.254.169.123" ];
···11-{ curl, targetRoot, wgetExtraOptions }:
22-# Note: be very cautious about dependencies, each dependency grows
33-# the closure of the initrd. Ideally we would not even require curl,
44-# but there is no reasonable way to send an HTTP PUT request without
55-# it. Note: do not be fooled: the wget referenced in this script
66-# is busybox's wget, not the fully featured one with --method support.
77-#
88-# Make sure that every package you depend on here is already listed as
99-# a channel blocker for both the full-sized and small channels.
1010-# Otherwise, we risk breaking user deploys in released channels.
1111-#
1212-# Also note: OpenStack's metadata service for its instances aims to be
1313-# compatible with the EC2 IMDS. Where possible, try to keep the set of
1414-# fetched metadata in sync with ./openstack-metadata-fetcher.nix .
1515-''
1616- metaDir=${targetRoot}etc/ec2-metadata
1717- mkdir -m 0755 -p "$metaDir"
1818- rm -f "$metaDir/*"
1919-2020- get_imds_token() {
2121- # retry-delay of 1 selected to give the system a second to get going,
2222- # but not add a lot to the bootup time
2323- ${curl}/bin/curl \
2424- -v \
2525- --retry 3 \
2626- --retry-delay 1 \
2727- --fail \
2828- -X PUT \
2929- --connect-timeout 1 \
3030- -H "X-aws-ec2-metadata-token-ttl-seconds: 600" \
3131- http://169.254.169.254/latest/api/token
3232- }
3333-3434- preflight_imds_token() {
3535- # retry-delay of 1 selected to give the system a second to get going,
3636- # but not add a lot to the bootup time
3737- ${curl}/bin/curl \
3838- -v \
3939- --retry 3 \
4040- --retry-delay 1 \
4141- --fail \
4242- --connect-timeout 1 \
4343- -H "X-aws-ec2-metadata-token: $IMDS_TOKEN" \
4444- http://169.254.169.254/1.0/meta-data/instance-id
4545- }
4646-4747- try=1
4848- while [ $try -le 3 ]; do
4949- echo "(attempt $try/3) getting an EC2 instance metadata service v2 token..."
5050- IMDS_TOKEN=$(get_imds_token) && break
5151- try=$((try + 1))
5252- sleep 1
5353- done
5454-5555- if [ "x$IMDS_TOKEN" == "x" ]; then
5656- echo "failed to fetch an IMDS2v token."
5757- fi
5858-5959- try=1
6060- while [ $try -le 10 ]; do
6161- echo "(attempt $try/10) validating the EC2 instance metadata service v2 token..."
6262- preflight_imds_token && break
6363- try=$((try + 1))
6464- sleep 1
6565- done
6666-6767- echo "getting EC2 instance metadata..."
6868-6969- wget_imds() {
7070- wget ${wgetExtraOptions} --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" "$@";
7171- }
7272-7373- wget_imds -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path
7474- (umask 077 && wget_imds -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data)
7575- wget_imds -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname
7676- wget_imds -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key
7777-''
···11+metaDir=/etc/ec2-metadata
22+mkdir -m 0755 -p "$metaDir"
33+rm -f "$metaDir/*"
44+55+get_imds_token() {
66+ # retry-delay of 1 selected to give the system a second to get going,
77+ # but not add a lot to the bootup time
88+ curl \
99+ --silent \
1010+ --show-error \
1111+ --retry 3 \
1212+ --retry-delay 1 \
1313+ --fail \
1414+ -X PUT \
1515+ --connect-timeout 1 \
1616+ -H "X-aws-ec2-metadata-token-ttl-seconds: 600" \
1717+ http://169.254.169.254/latest/api/token
1818+}
1919+2020+preflight_imds_token() {
2121+ # retry-delay of 1 selected to give the system a second to get going,
2222+ # but not add a lot to the bootup time
2323+ curl \
2424+ --silent \
2525+ --show-error \
2626+ --retry 3 \
2727+ --retry-delay 1 \
2828+ --fail \
2929+ --connect-timeout 1 \
3030+ -H "X-aws-ec2-metadata-token: $IMDS_TOKEN" \
3131+ -o /dev/null \
3232+ http://169.254.169.254/1.0/meta-data/instance-id
3333+}
3434+3535+try=1
3636+while [ $try -le 3 ]; do
3737+ echo "(attempt $try/3) getting an EC2 instance metadata service v2 token..."
3838+ IMDS_TOKEN=$(get_imds_token) && break
3939+ try=$((try + 1))
4040+ sleep 1
4141+done
4242+4343+if [ "x$IMDS_TOKEN" == "x" ]; then
4444+ echo "failed to fetch an IMDS2v token."
4545+fi
4646+4747+try=1
4848+while [ $try -le 10 ]; do
4949+ echo "(attempt $try/10) validating the EC2 instance metadata service v2 token..."
5050+ preflight_imds_token && break
5151+ try=$((try + 1))
5252+ sleep 1
5353+done
5454+5555+echo "getting EC2 instance metadata..."
5656+5757+get_imds() {
5858+ # Intentionally no --fail here, so that we proceed even if e.g. a
5959+ # 404 was returned (but we still fail if we can't reach the IMDS
6060+ # server).
6161+ curl --silent --show-error --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" "$@"
6262+}
6363+6464+get_imds -o "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path
6565+(umask 077 && get_imds -o "$metaDir/user-data" http://169.254.169.254/1.0/user-data)
6666+get_imds -o "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname
6767+get_imds -o "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key
···1616 ../modules/testing/test-instrumentation.nix
1717 ../modules/profiles/qemu-guest.nix
1818 {
1919- ec2.hvm = true;
2020-2119 # Hack to make the partition resizing work in QEMU.
2220 boot.initrd.postDeviceCommands = mkBefore ''
2321 ln -s vda /dev/xvda
+2
nixos/tests/patroni.nix
···166166167167 start_all()
168168169169+ etcd.wait_for_unit("etcd.service")
170170+169171 with subtest("should bootstrap a new patroni cluster"):
170172 wait_for_all_nodes_ready()
171173