A RivetKit application template configured for deployment on AWS ECS (Fargate).
npm install
npm run devNote: This only deploys the actors. You need to deploy the frontend yourself.
- Go to the Rivet dashboard
- Under Connect Existing Project, click AWS ECS
- Configure datacenter, then click Next
- Copy the values shown for the next step
Set the environment variables from the Rivet dashboard:
export TF_VAR_rivet_endpoint="<paste from dashboard>"
export TF_VAR_rivet_namespace="<paste from dashboard>"
export TF_VAR_rivet_token="<paste from dashboard>"Then deploy:
cd terraform
terraform init
terraform applyThis will automatically build and push the Docker image.
To deploy updates, run terraform apply again.
cd terraform
terraform destroyNote: This only deploys the actors. You need to deploy the frontend yourself.
- Go to the Rivet dashboard
- Under Connect Existing Project, click AWS ECS
- Configure datacenter, then click Next
- Copy and run the environment variables shown:
export RIVET_ENDPOINT=<paste from dashboard>
export RIVET_NAMESPACE=<paste from dashboard>
export RIVET_TOKEN=<paste from dashboard>export AWS_REGION=us-east-1
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export APP_NAME=my-backendaws ecr create-repository --repository-name ${APP_NAME} --region ${AWS_REGION}
aws ecr get-login-password --region ${AWS_REGION} | \
docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.comdocker build --platform linux/amd64 -t ${APP_NAME} .
docker tag ${APP_NAME}:latest ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${APP_NAME}:latest
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${APP_NAME}:latestaws logs create-log-group --log-group-name /ecs/${APP_NAME} --region ${AWS_REGION}aws ecs create-cluster --cluster-name ${APP_NAME}-clusterIf you don't have an ecsTaskExecutionRole, create one:
aws iam create-role --role-name ecsTaskExecutionRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "ecs-tasks.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}'
aws iam attach-role-policy --role-name ecsTaskExecutionRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicycat > /tmp/task-def.json << EOF
{
"family": "${APP_NAME}",
"networkMode": "awsvpc",
"cpu": "256",
"memory": "512",
"requiresCompatibilities": ["FARGATE"],
"executionRoleArn": "arn:aws:iam::${AWS_ACCOUNT_ID}:role/ecsTaskExecutionRole",
"containerDefinitions": [{
"name": "${APP_NAME}",
"image": "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${APP_NAME}:latest",
"portMappings": [{"containerPort": 8080, "protocol": "tcp"}],
"environment": [
{"name": "RIVET_ENDPOINT", "value": "${RIVET_ENDPOINT}"},
{"name": "RIVET_NAMESPACE", "value": "${RIVET_NAMESPACE}"},
{"name": "RIVET_TOKEN", "value": "${RIVET_TOKEN}"}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/${APP_NAME}",
"awslogs-region": "${AWS_REGION}",
"awslogs-stream-prefix": "ecs"
}
},
"essential": true
}]
}
EOF
aws ecs register-task-definition --cli-input-json file:///tmp/task-def.jsonOption A: Use existing VPC
export VPC_ID=vpc-xxxxxxxxx
export SUBNET_ID=subnet-xxxxxxxxx
export SG_ID=sg-xxxxxxxxxOption B: Create new VPC
export VPC_ID=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --query 'Vpc.VpcId' --output text)
export SUBNET_ID=$(aws ec2 create-subnet --vpc-id ${VPC_ID} --cidr-block 10.0.0.0/24 --query 'Subnet.SubnetId' --output text)
export SG_ID=$(aws ec2 create-security-group --group-name ${APP_NAME}-sg --description "ECS security group" --vpc-id ${VPC_ID} --query 'GroupId' --output text)
export IGW_ID=$(aws ec2 create-internet-gateway --query 'InternetGateway.InternetGatewayId' --output text)
aws ec2 attach-internet-gateway --internet-gateway-id ${IGW_ID} --vpc-id ${VPC_ID}
export RTB_ID=$(aws ec2 describe-route-tables --filters Name=vpc-id,Values=${VPC_ID} --query 'RouteTables[0].RouteTableId' --output text)
aws ec2 create-route --route-table-id ${RTB_ID} --destination-cidr-block 0.0.0.0/0 --gateway-id ${IGW_ID}aws ecs create-service \
--cluster ${APP_NAME}-cluster \
--service-name ${APP_NAME} \
--task-definition ${APP_NAME} \
--desired-count 1 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[${SUBNET_ID}],securityGroups=[${SG_ID}],assignPublicIp=ENABLED}"docker build --platform linux/amd64 -t ${APP_NAME} .
docker tag ${APP_NAME}:latest ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${APP_NAME}:latest
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${APP_NAME}:latest
aws ecs update-service --cluster ${APP_NAME}-cluster --service ${APP_NAME} --force-new-deploymentUpdate /tmp/task-def.json with new values, then re-register and deploy:
aws ecs register-task-definition --cli-input-json file:///tmp/task-def.json
aws ecs update-service --cluster ${APP_NAME}-cluster --service ${APP_NAME} --task-definition ${APP_NAME} --force-new-deploymentaws ecs update-service --cluster ${APP_NAME}-cluster --service ${APP_NAME} --desired-count 0
aws ecs delete-service --cluster ${APP_NAME}-cluster --service ${APP_NAME}
aws ecs delete-cluster --cluster ${APP_NAME}-cluster
aws ecr delete-repository --repository-name ${APP_NAME} --force
aws logs delete-log-group --log-group-name /ecs/${APP_NAME}Your runner should appear as connected on the Rivet dashboard once the service is healthy.