Change-Id: I6c6847fac56f0a9a1a2209792e00a3aec5e672b9 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10809 Autosubmit: aspen <root@gws.fyi> Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI Reviewed-by: lukegb <lukegb@tvl.fyi>
		
			
				
	
	
		
			208 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { depot, pkgs, lib, ... }:
 | |
| 
 | |
| # mostly stolen from espes
 | |
| 
 | |
| { name
 | |
| , instanceType
 | |
| , configuration
 | |
| , prefix ? "${name}_"
 | |
| , region ? "us-east-2"
 | |
| , rootVolumeSizeGb ? 50
 | |
| , securityGroupId ? null
 | |
| , extraIngressPorts ? [ ]
 | |
| }:
 | |
| 
 | |
| let
 | |
|   os = depot.ops.nixos.nixosFor ({ modulesPath, ... }: {
 | |
|     imports = [
 | |
|       (pkgs.path + "/nixos/modules/virtualisation/amazon-image.nix")
 | |
|       configuration
 | |
|     ];
 | |
| 
 | |
|     ec2.hvm = true;
 | |
|     networking.hostName = name;
 | |
|     # TODO: remove this once the terraform tls provider supports ed25519 keys
 | |
|     # https://github.com/hashicorp/terraform-provider-tls/issues/26
 | |
|     services.openssh.extraConfig = ''
 | |
|       PubkeyAcceptedKeyTypes=+ssh-rsa
 | |
|       PubkeyAcceptedAlgorithms=+ssh-rsa
 | |
|     '';
 | |
|   });
 | |
| 
 | |
|   targetUser = "root";
 | |
| 
 | |
|   ec2Amis = import "${pkgs.path}/nixos/modules/virtualisation/ec2-amis.nix";
 | |
| 
 | |
|   osRoot = os.config.system.build.toplevel;
 | |
| 
 | |
|   osRootPath = builtins.unsafeDiscardStringContext (toString osRoot.outPath);
 | |
|   drvPath = builtins.unsafeDiscardStringContext (toString osRoot.drvPath);
 | |
| 
 | |
|   machineResource = "aws_instance.${prefix}machine";
 | |
| 
 | |
|   recursiveMerge = builtins.foldl' lib.recursiveUpdate { };
 | |
| 
 | |
|   securityGroupId' =
 | |
|     if isNull securityGroupId
 | |
|     then "\${aws_security_group.${prefix}group.id}"
 | |
|     else securityGroupId;
 | |
| in
 | |
| recursiveMerge [
 | |
|   (lib.optionalAttrs (isNull securityGroupId) {
 | |
|     resource.aws_security_group."${prefix}group" = {
 | |
|       provider = "aws.${region}";
 | |
|       vpc_id = null;
 | |
| 
 | |
|       # terraform isn't good about knowing what other resources depend on
 | |
|       # security groups
 | |
|       lifecycle.create_before_destroy = true;
 | |
|     };
 | |
| 
 | |
|     resource.aws_security_group_rule.all_egress = {
 | |
|       provider = "aws.${region}";
 | |
|       security_group_id = securityGroupId';
 | |
|       type = "egress";
 | |
|       protocol = "-1";
 | |
|       from_port = 0;
 | |
|       to_port = 0;
 | |
|       cidr_blocks = [ "0.0.0.0/0" ];
 | |
|       ipv6_cidr_blocks = [ "::/0" ];
 | |
| 
 | |
|       description = null;
 | |
|       prefix_list_ids = null;
 | |
|       self = null;
 | |
|     };
 | |
|   })
 | |
|   rec {
 | |
|     data.external.my_ip = {
 | |
|       program = [
 | |
|         (pkgs.writeShellScript "my_ip" ''
 | |
|           ${pkgs.jq}/bin/jq \
 | |
|             -n \
 | |
|             --arg ip "$(curl ifconfig.me)" \
 | |
|             '{"ip":$ip}'
 | |
|         '')
 | |
|       ];
 | |
|     };
 | |
| 
 | |
|     resource.aws_security_group_rule.provision_ssh_access = {
 | |
|       provider = "aws.${region}";
 | |
|       security_group_id = securityGroupId';
 | |
|       type = "ingress";
 | |
|       protocol = "TCP";
 | |
|       from_port = 22;
 | |
|       to_port = 22;
 | |
|       cidr_blocks = [ "\${data.external.my_ip.result.ip}/32" ];
 | |
|       ipv6_cidr_blocks = [ ];
 | |
|       description = null;
 | |
|       prefix_list_ids = null;
 | |
|       self = null;
 | |
|     };
 | |
| 
 | |
|     resource.tls_private_key."${prefix}key" = {
 | |
|       algorithm = "RSA";
 | |
|     };
 | |
| 
 | |
|     resource.aws_key_pair."${prefix}generated_key" = {
 | |
|       provider = "aws.${region}";
 | |
|       key_name = "generated-key-\${sha256(tls_private_key.${prefix}key.public_key_openssh)}";
 | |
|       public_key = "\${tls_private_key.${prefix}key.public_key_openssh}";
 | |
|     };
 | |
| 
 | |
|     resource.aws_instance."${prefix}machine" = {
 | |
|       provider = "aws.${region}";
 | |
|       ami = ec2Amis."21.05"."${region}".hvm-ebs;
 | |
|       instance_type = instanceType;
 | |
|       vpc_security_group_ids = [ securityGroupId' ];
 | |
|       key_name = "\${aws_key_pair.${prefix}generated_key.key_name}";
 | |
|       root_block_device = {
 | |
|         volume_size = rootVolumeSizeGb;
 | |
|         tags.Name = name;
 | |
|       };
 | |
|       tags.Name = name;
 | |
|     };
 | |
| 
 | |
|     resource.null_resource."${prefix}deploy_nixos" = {
 | |
|       triggers = {
 | |
|         # deploy if the machine is recreated
 | |
|         machine_id = "\${${machineResource}.id}";
 | |
| 
 | |
|         # deploy on os changes
 | |
|         os_drv = drvPath;
 | |
|       };
 | |
| 
 | |
|       connection = {
 | |
|         type = "ssh";
 | |
|         host = "\${${machineResource}.public_ip}";
 | |
|         user = targetUser;
 | |
|         private_key = "\${tls_private_key.${prefix}key.private_key_pem}";
 | |
|       };
 | |
| 
 | |
|       # do the actual deployment
 | |
|       provisioner = [
 | |
|         # wait till ssh is up
 | |
|         { remote-exec.inline = [ "true" ]; }
 | |
| 
 | |
|         # copy the nixos closure
 | |
|         {
 | |
|           local-exec.command = ''
 | |
|             export PATH="${pkgs.openssh}/bin:$PATH"
 | |
| 
 | |
|             scratch="$(mktemp -d)"
 | |
|             trap 'rm -rf -- "$scratch"' EXIT
 | |
| 
 | |
|             # write out ssh key
 | |
|             echo -n "''${tls_private_key.${prefix}key.private_key_pem}" > $scratch/id_rsa.pem
 | |
|             chmod 0600 $scratch/id_rsa.pem
 | |
| 
 | |
|             export NIX_SSHOPTS="\
 | |
|                 -o StrictHostKeyChecking=no\
 | |
|                 -o UserKnownHostsFile=/dev/null\
 | |
|                 -o GlobalKnownHostsFile=/dev/null\
 | |
|                 -o IdentityFile=$scratch/id_rsa.pem"
 | |
| 
 | |
|             nix-build ${drvPath}
 | |
|             nix-copy-closure \
 | |
|               --to ${targetUser}@''${${machineResource}.public_ip} \
 | |
|               ${osRootPath} \
 | |
|               --gzip \
 | |
|               --use-substitutes
 | |
|           '';
 | |
|         }
 | |
| 
 | |
|         # activate it
 | |
|         {
 | |
|           remote-exec.inline = [
 | |
|             # semicolons mandatory
 | |
|             ''
 | |
|               set -e;
 | |
|               nix-env --profile /nix/var/nix/profiles/system --set ${osRootPath};
 | |
|               ${osRootPath}/bin/switch-to-configuration switch;
 | |
|             ''
 | |
|           ];
 | |
|         }
 | |
|       ];
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   {
 | |
|     resource.aws_security_group_rule = builtins.listToAttrs (map
 | |
|       (port: {
 | |
|         name = "ingress_${toString port}";
 | |
|         value = {
 | |
|           provider = "aws.${region}";
 | |
|           security_group_id = securityGroupId';
 | |
|           type = "ingress";
 | |
|           protocol = "TCP";
 | |
|           from_port = port;
 | |
|           to_port = port;
 | |
|           cidr_blocks = [ "0.0.0.0/0" ];
 | |
|           ipv6_cidr_blocks = [ ];
 | |
|           description = null;
 | |
|           prefix_list_ids = null;
 | |
|           self = null;
 | |
|         };
 | |
|       })
 | |
|       extraIngressPorts);
 | |
|   }
 | |
| ]
 |