nixops-aws
nixops-aws copied to clipboard
Manual ec2 example fails
I copied the files from https://nixos.org/nixops/manual/#sec-deploying-to-ec2, and only changed the accessKeyId. Unfortunately I get this error:
> nixops create ./load-balancer.nix ./load-balancer-ec2.nix -d load-balancer-ec2
created deployment ‘7d8239f3-0d5b-11ea-89e6-02428c63fe0c’
7d8239f3-0d5b-11ea-89e6-02428c63fe0c
> nixops deploy -d load-balancer-ec2
error: I don't know an AMI for virtualisation type pv-ebs with instance type m1.small
(use '--show-trace' to show detailed location information)
error: evaluation of the deployment specification failed
Next I tried switching to region = "us-west-2"
and deployment.ec2.instanceType = "t2.micro";
. Now I get the same error for each instance:
error: Multiple exceptions (3):
* backend1: EC2ResponseError: 400 Bad Request
<?xml version="1.0" encoding="UTF-8"?>
<Response><Errors><Error><Code>VPCResourceNotSpecified</Code><Message>The specified instance type can only be used in a VPC. A subnet ID or network interface ID is required to carry out the request.</Message></Error></Errors><RequestID>8f4346fb-3a7e-4263-b0d1-17acd0a0d446</RequestID></Response>
Anyone know what tweaks need to be made so the manual example works? Thanks!
Edit: after some googling, it appears this may be because newer AWS accounts have a default VPC but older ones do not. https://github.com/hashicorp/terraform/issues/4367. That said, it would be nice if the example was "more" declarative
Edit2: I just made a new AWS account and this did not resolve the issue. Appears the basic example needs to show configuring a VPC
For anyone that gets stuck, here's a configuration for AWS now that VPC must be specified. Hope it saves someone a few hours :). Would be great to update the manual with a working example. I based this off of https://github.com/nh2/nixops-tutorial and https://github.com/NixOS/nixops-aws/blob/master/examples/vpc.nix.
nginx-server-ec2.nix:
let
region = "us-west-2";
accessKeyId = "my-access-key"; # symbolic name looked up in ~/.ec2-keys or a ~/.aws/credentials profile name
# We must declare an AWS Subnet for each Availability Zone
# because Subnets cannot span AZs.
subnets = [
{ name = "nixops-vpc-subnet-a"; cidr = "10.0.0.0/19"; zone = "${region}a"; }
{ name = "nixops-vpc-subnet-b"; cidr = "10.0.32.0/19"; zone = "${region}b"; }
{ name = "nixops-vpc-subnet-c"; cidr = "10.0.64.0/19"; zone = "${region}c"; }
{ name = "nixops-vpc-subnet-d"; cidr = "10.0.96.0/19"; zone = "${region}d"; }
];
domain = "example.com";
ec2 = { resources, ... }: {
deployment.targetEnv = "ec2";
deployment.ec2.accessKeyId = accessKeyId;
deployment.ec2.region = region;
deployment.ec2.subnetId = resources.vpcSubnets.nixops-vpc-subnet-c;
deployment.ec2.instanceType = "t2.micro";
deployment.ec2.keyPair = resources.ec2KeyPairs.my-key-pair;
deployment.ec2.associatePublicIpAddress = true;
deployment.ec2.elasticIPv4 = resources.elasticIPs.eip;
deployment.ec2.ebsBoot = true;
deployment.ec2.ebsInitialRootDiskSize = 20;
deployment.ec2.securityGroupIds = [ "allow-ssh" "allow-http" ];
};
lib = (import <nixpkgs> {}).lib;
in
{
nginx-server = ec2;
resources = {
# Provision an EC2 key pair.
ec2KeyPairs.my-key-pair =
{ inherit region accessKeyId; };
# create security groups
ec2SecurityGroups.allow-ssh = { resources, ... }: {
inherit region accessKeyId;
name = "allow-ssh";
description = "allow-ssh";
vpcId = resources.vpc.nixops-vpc;
rules = [
{ fromPort = 22; toPort = 22; sourceIp = "0.0.0.0/0"; }
];
};
ec2SecurityGroups.allow-http = { resources, ... }: {
inherit region accessKeyId;
name = "allow-http";
description = "allow-http";
vpcId = resources.vpc.nixops-vpc;
rules = [
{ fromPort = 80; toPort = 80; sourceIp = "0.0.0.0/0"; }
{ fromPort = 443; toPort = 443; sourceIp = "0.0.0.0/0"; }
];
};
# configure VPC
vpc.nixops-vpc = {
inherit region accessKeyId;
instanceTenancy = "default";
enableDnsSupport = true;
enableDnsHostnames = true;
cidrBlock = "10.0.0.0/16";
tags.Source = "NixOps";
};
vpcSubnets =
let
makeSubnet = {cidr, zone}:
{ resources, ... }: {
inherit region zone accessKeyId;
vpcId = resources.vpc.nixops-vpc;
cidrBlock = cidr;
mapPublicIpOnLaunch = true;
tags.Source = "NixOps";
};
in
builtins.listToAttrs
(map
({ name, cidr, zone }: lib.nameValuePair name (makeSubnet { inherit cidr zone; }) )
subnets
);
vpcRouteTables = {
route-table = { resources, ... }: {
inherit accessKeyId region;
vpcId = resources.vpc.nixops-vpc;
};
};
vpcRoutes = {
igw-route = { resources, ... }: {
inherit region accessKeyId;
routeTableId = resources.vpcRouteTables.route-table;
destinationCidrBlock = "0.0.0.0/0";
gatewayId = resources.vpcInternetGateways.nixops-igw;
};
};
vpcRouteTableAssociations =
let
association = subnetName: { resources, ... }: {
inherit accessKeyId region;
subnetId = resources.vpcSubnets."${subnetName}";
routeTableId = resources.vpcRouteTables.route-table;
};
in
builtins.listToAttrs
(map
({ name, ... }: lib.nameValuePair "association-${name}" (association name) )
subnets
);
vpcInternetGateways.nixops-igw = { resources, ... }: {
inherit accessKeyId region;
vpcId = resources.vpc.nixops-vpc;
};
# Optional: static IP address
elasticIPs.eip = {
inherit region accessKeyId;
vpc = true;
};
};
}
nginx-server.nix:
{
# special NixOps config
network = {
description = "Nginx server";
enableRollback = true;
};
# end special NixOps config
# from https://gist.github.com/nh2/28bce850755cf14bd7749ea78e4238ab
/* boot.kernelModules = [ "tcp_bbr" ]; # faster tcp kernel support
# Enable BBR congestion control
boot.kernel.sysctl."net.ipv4.tcp_congestion_control" = "bbr"; */
nginx-server = { config, pkgs, ... }: {
networking.firewall.enable = true;
# Reject instead of drop.
networking.firewall.rejectPackets = true;
networking.firewall.allowedTCPPorts = [
22
80 # nginx
443 # nginx
];
services.nginx = {
enable = true;
/* virtualHosts."${domain}" = {
enableACME = true;
}; */
};
};
}
Then:
> nixops create ./nginx-server.nix ./nginx-server-ec2.nix -d nginx-server-ec2
> nixops deploy -d nginx-server-ec2