2016-07-12 01:26:07 +02:00
|
|
|
#!/usr/bin/env bash
|
2022-01-12 22:30:09 +01:00
|
|
|
set -eu
|
|
|
|
set -o pipefail
|
2016-07-12 01:26:07 +02:00
|
|
|
|
2022-01-12 22:30:09 +01:00
|
|
|
SERVER=${1:-}
|
|
|
|
ROLES=${2:-}
|
|
|
|
BRANCH=${3:-}
|
2020-07-15 20:54:57 +02:00
|
|
|
if [ -z "$SERVER" ] || [ -z "$ROLES" ]; then
|
|
|
|
echo "USAGE: $0 server roles [branch]"
|
|
|
|
echo
|
2016-07-12 01:26:07 +02:00
|
|
|
echo "Installs an empty Ubuntu server in AWS with a Zulip server role."
|
2020-07-15 20:54:57 +02:00
|
|
|
echo
|
|
|
|
echo " * server is the local part of the hostname (e.g. postgres0)"
|
2020-10-20 02:49:54 +02:00
|
|
|
echo " * roles is a comma-separated list of Puppet rules to be passed to scripts/lib/install"
|
2020-10-20 04:10:17 +02:00
|
|
|
echo " E.g. 'zulip::profile::postgresql'"
|
2020-07-15 20:54:57 +02:00
|
|
|
echo " * branch is used to override the default branch to install from."
|
|
|
|
echo
|
|
|
|
echo "Reads configuration from $HOME/.zulip-install-server.conf, which should look like:"
|
|
|
|
echo
|
|
|
|
echo "[repo]"
|
|
|
|
echo "repo_url=git@github.com:zulip/zulip.git"
|
2021-09-01 00:15:31 +02:00
|
|
|
echo "branch=main"
|
2020-07-15 20:54:57 +02:00
|
|
|
echo "[aws]"
|
|
|
|
echo "zone_id=Z2U988IEXAMPLE"
|
|
|
|
echo "security_groups=sg-01234567"
|
|
|
|
echo "image_id=ami-0dc45e3d9be6ab7b5"
|
|
|
|
echo "instance_type=m4.large"
|
|
|
|
echo "ssh_secret_id=prod/git/deploy"
|
2016-07-12 01:26:07 +02:00
|
|
|
exit 1
|
|
|
|
fi
|
2016-07-21 06:33:16 +02:00
|
|
|
set -x
|
2016-07-12 01:26:07 +02:00
|
|
|
|
2020-07-15 20:54:57 +02:00
|
|
|
cd "$(dirname "$0")"
|
2016-07-12 01:26:07 +02:00
|
|
|
|
2021-06-25 03:24:21 +02:00
|
|
|
source ./bootstrap-awscli.sh
|
2016-07-12 01:26:07 +02:00
|
|
|
|
2020-07-15 20:54:57 +02:00
|
|
|
zulip_install_config_file="$HOME/.zulip-install-server.conf"
|
|
|
|
if [ ! -f "$zulip_install_config_file" ]; then
|
|
|
|
echo "No configuration file found in $zulip_install_config_file"
|
2016-07-21 06:33:36 +02:00
|
|
|
exit 1
|
|
|
|
fi
|
2021-05-18 19:58:45 +02:00
|
|
|
|
2020-07-15 20:54:57 +02:00
|
|
|
REPO_URL=$(crudini --get "$zulip_install_config_file" repo repo_url)
|
|
|
|
if [ -z "$BRANCH" ]; then
|
|
|
|
BRANCH=$(crudini --get "$zulip_install_config_file" repo default_branch)
|
2019-06-13 23:01:47 +02:00
|
|
|
fi
|
2016-07-12 01:26:07 +02:00
|
|
|
|
2021-05-18 19:58:45 +02:00
|
|
|
function lookup() {
|
|
|
|
KEY="$1"
|
|
|
|
crudini --get "$zulip_install_config_file" "aws-$ROLES" "$KEY" 2>/dev/null \
|
|
|
|
|| crudini --get "$zulip_install_config_file" aws "$KEY"
|
|
|
|
}
|
|
|
|
|
|
|
|
AWS_ZONE_ID=$(lookup zone_id)
|
|
|
|
SECURITY_GROUPS=$(lookup security_groups)
|
|
|
|
AMI_ID=$(lookup image_id)
|
|
|
|
INSTANCE_TYPE=$(lookup instance_type)
|
2022-01-12 22:23:42 +01:00
|
|
|
IAM_PROFILE=$(lookup iam_profile)
|
2021-05-18 19:58:45 +02:00
|
|
|
SSH_SECRET_ID=$(lookup ssh_secret_id)
|
2022-01-12 22:26:15 +01:00
|
|
|
AZ=$(lookup availability_zone)
|
2022-01-12 22:29:10 +01:00
|
|
|
DISK_SIZE=$(lookup disk_size)
|
2020-07-15 20:54:57 +02:00
|
|
|
|
|
|
|
# Verify it doesn't exist already
|
2020-10-15 04:55:57 +02:00
|
|
|
ZONE_NAME=$($AWS route53 get-hosted-zone --id "$AWS_ZONE_ID" | jq -r '.HostedZone.Name')
|
|
|
|
HOSTNAME="$SERVER.${ZONE_NAME%?}" # Remove trailing .
|
2020-07-15 20:54:57 +02:00
|
|
|
EXISTING_RECORDS=$($AWS route53 list-resource-record-sets \
|
2020-10-15 04:55:57 +02:00
|
|
|
--hosted-zone-id "$AWS_ZONE_ID" \
|
|
|
|
--query "ResourceRecordSets[?Name == '$HOSTNAME.']" \
|
|
|
|
| jq '. | length')
|
2020-07-15 20:54:57 +02:00
|
|
|
if [ "$EXISTING_RECORDS" != "0" ]; then
|
|
|
|
echo "$HOSTNAME already exists!"
|
|
|
|
exit 1
|
2017-10-06 06:57:18 +02:00
|
|
|
fi
|
2016-07-12 01:26:07 +02:00
|
|
|
|
2022-01-12 22:30:33 +01:00
|
|
|
# https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html
|
2022-01-12 22:24:39 +01:00
|
|
|
# shellcheck disable=SC2206 # We intentionally split $SECURITY_GROUPS
|
2022-01-12 22:20:56 +01:00
|
|
|
EXTRA_ARGS+=(
|
2022-01-12 22:23:42 +01:00
|
|
|
--iam-instance-profile "Name=\"$IAM_PROFILE\""
|
2022-01-12 22:20:56 +01:00
|
|
|
--image-id "$AMI_ID"
|
|
|
|
--instance-type "$INSTANCE_TYPE"
|
2022-01-12 22:24:39 +01:00
|
|
|
--security-group-ids $SECURITY_GROUPS
|
2022-01-12 22:20:56 +01:00
|
|
|
--monitoring Enabled=true
|
2022-01-12 22:26:15 +01:00
|
|
|
--placement "AvailabilityZone=$AZ"
|
2022-01-12 22:29:10 +01:00
|
|
|
--block-device-mappings "DeviceName=/dev/sda1,Ebs={VolumeSize=$DISK_SIZE,VolumeType=gp3,Throughput=125,Iops=3000,Encrypted=true}"
|
2022-01-12 22:20:56 +01:00
|
|
|
)
|
2021-05-18 21:31:30 +02:00
|
|
|
|
2020-07-15 20:54:57 +02:00
|
|
|
# Build up the provisioning script
|
|
|
|
BOOTDATA=$(mktemp)
|
|
|
|
{
|
|
|
|
echo "#!/bin/bash"
|
|
|
|
echo "SERVER=$SERVER"
|
|
|
|
echo "HOSTNAME=$HOSTNAME"
|
|
|
|
echo "ROLES=$ROLES"
|
|
|
|
echo "REPO_URL=$REPO_URL"
|
|
|
|
echo "BRANCH=$BRANCH"
|
|
|
|
echo "SSH_SECRET_ID=$SSH_SECRET_ID"
|
2021-06-25 03:24:21 +02:00
|
|
|
sed '/^AWS=/ r ./bootstrap-awscli.sh' bootstrap-aws-installer
|
2020-10-15 04:55:57 +02:00
|
|
|
} >>"$BOOTDATA"
|
2020-07-15 20:54:57 +02:00
|
|
|
|
2021-05-18 05:37:39 +02:00
|
|
|
TAG_ROLE_NAMES=$(echo "$ROLES" | perl -pe 's/\w+::profile::(\w+)/$1/g')
|
|
|
|
TAGS="[{Key=Name,Value=$SERVER},{Key=role,Value=\"$TAG_ROLE_NAMES\"}]"
|
2020-07-15 20:54:57 +02:00
|
|
|
INSTANCE_DATA=$($AWS ec2 run-instances \
|
2020-10-15 04:55:57 +02:00
|
|
|
--tag-specifications "ResourceType=instance,Tags=$TAGS" \
|
2021-05-18 21:31:30 +02:00
|
|
|
"${EXTRA_ARGS[@]}" \
|
2020-10-15 04:55:57 +02:00
|
|
|
--user-data "file://$BOOTDATA")
|
2020-07-15 20:54:57 +02:00
|
|
|
INSTANCEID=$(echo "$INSTANCE_DATA" | jq -r .Instances[0].InstanceId)
|
|
|
|
|
|
|
|
# Wait for public IP assignment
|
|
|
|
PUBLIC_DNS_NAME=""
|
|
|
|
while [ -z "$PUBLIC_DNS_NAME" ]; do
|
|
|
|
sleep 1
|
|
|
|
PUBLIC_DNS_NAME=$($AWS ec2 describe-instances --instance-ids "$INSTANCEID" \
|
2020-10-15 04:55:57 +02:00
|
|
|
| jq -r .Reservations[0].Instances[0].PublicDnsName)
|
2020-07-15 20:54:57 +02:00
|
|
|
done
|
|
|
|
|
|
|
|
# Add the hostname to the zone
|
|
|
|
ROUTE53_CHANGES=$(mktemp)
|
2020-10-15 04:55:57 +02:00
|
|
|
cat >"$ROUTE53_CHANGES" <<EOF
|
2020-07-15 20:54:57 +02:00
|
|
|
{
|
|
|
|
"Comment": "Add the $HOSTNAME CNAME record",
|
|
|
|
"Changes": [
|
|
|
|
{
|
|
|
|
"Action": "CREATE",
|
|
|
|
"ResourceRecordSet": {
|
|
|
|
"Name": "$HOSTNAME",
|
|
|
|
"Type": "CNAME",
|
|
|
|
"TTL": 300,
|
|
|
|
"ResourceRecords": [{"Value": "$PUBLIC_DNS_NAME"}]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
2016-07-12 01:26:07 +02:00
|
|
|
EOF
|
2020-07-15 20:54:57 +02:00
|
|
|
$AWS route53 change-resource-record-sets --hosted-zone-id "$AWS_ZONE_ID" --change-batch "file://$ROUTE53_CHANGES"
|
|
|
|
rm "$ROUTE53_CHANGES"
|
2016-07-12 01:26:07 +02:00
|
|
|
|
|
|
|
set +x
|
2020-07-15 20:54:57 +02:00
|
|
|
echo
|
|
|
|
echo
|
|
|
|
echo ">>> Install started successfully! Provisioning takes 5-6min."
|
|
|
|
echo " sleep 360 && ssh root@$HOSTNAME"
|