snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
This commit is contained in:
235
tools/setup/install-aws-server
Executable file
235
tools/setup/install-aws-server
Executable file
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
USAGE: $0 [--roles=roles] [--branch=main] [--debug-key=username] server
|
||||
|
||||
Installs an empty Ubuntu server in AWS with a Zulip server role.
|
||||
|
||||
* server is the local part of the hostname (e.g. postgres0)
|
||||
|
||||
* roles is a comma-separated list of Puppet profile names; these
|
||||
will get 'kandra::profile::' prepended to them, and passed
|
||||
to scripts/lib/install -- e.g. 'postgresql'
|
||||
* branch is used to override the default branch to install from.
|
||||
* username is the name of the AWS SSH key pair to allow logins as
|
||||
'ubuntu' with during initial boot; this is purely for debugging the
|
||||
bootstrapping process.
|
||||
|
||||
Reads configuration from $HOME/.zulip-install-server.conf, which should look like:
|
||||
|
||||
[repo]
|
||||
repo_url=git@github.com:zulip/zulip.git
|
||||
[aws]
|
||||
zone_id=Z2U988IEXAMPLE
|
||||
security_groups=sg-01234567
|
||||
instance_type=m4.large
|
||||
EOF
|
||||
}
|
||||
|
||||
args="$(getopt -o '' --long help,branch:,roles:,debug-key: -n "$0" -- "$@")" || {
|
||||
usage >&2
|
||||
exit 1
|
||||
}
|
||||
eval "set -- $args"
|
||||
|
||||
BRANCH="production"
|
||||
ROLES="base"
|
||||
DEBUG_KEY=""
|
||||
while true; do
|
||||
case "$1" in
|
||||
--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--roles)
|
||||
shift
|
||||
ROLES="$1"
|
||||
shift
|
||||
;;
|
||||
--branch)
|
||||
shift
|
||||
BRANCH="$1"
|
||||
shift
|
||||
;;
|
||||
--debug-key)
|
||||
shift
|
||||
DEBUG_KEY="$1"
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SERVER="$1"
|
||||
|
||||
set -x
|
||||
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
./puppet/kandra/files/install-aws-cli
|
||||
AWS=/srv/zulip-aws-tools/bin/aws
|
||||
|
||||
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"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REPO_URL=$(crudini --get "$zulip_install_config_file" repo repo_url)
|
||||
|
||||
for role in ${ROLES//,/ }; do
|
||||
if ! [ -f "./puppet/kandra/manifests/profile/$role.pp" ]; then
|
||||
echo "No such role kandra::profile::$role !"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
FULL_ROLES=$(echo "$ROLES" | perl -pe '$_=join(",",map{"kandra::profile::$_"} split ",")')
|
||||
|
||||
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)
|
||||
read -r -a SECURITY_GROUPS <<<"$SECURITY_GROUPS"
|
||||
INSTANCE_TYPE=$(lookup instance_type)
|
||||
IAM_PROFILE=$(lookup iam_profile)
|
||||
AZ=$(lookup availability_zone)
|
||||
DISK_SIZE=$(lookup disk_size)
|
||||
|
||||
# Determine the architecture
|
||||
ARCH=$($AWS ec2 describe-instance-types --instance-types "$INSTANCE_TYPE" --query 'InstanceTypes[*].ProcessorInfo.SupportedArchitectures[0]' --output text)
|
||||
|
||||
# Lookup the latest 24.04 image
|
||||
AMI_ID=$($AWS ec2 describe-images --owners 099720109477 --filters 'Name=name,Values=ubuntu/images/hvm-ssd-gp3/ubuntu-*-24.04*' "Name=architecture,Values=$ARCH" --query 'sort_by(Images, &CreationDate)[-1].ImageId' --output text)
|
||||
|
||||
# Verify it doesn't exist already
|
||||
ZONE_NAME=$($AWS route53 get-hosted-zone --id "$AWS_ZONE_ID" | jq -r '.HostedZone.Name')
|
||||
HOSTNAME="$SERVER.${ZONE_NAME%?}" # Remove trailing .
|
||||
EXISTING_RECORDS=$($AWS route53 list-resource-record-sets \
|
||||
--hosted-zone-id "$AWS_ZONE_ID" \
|
||||
--query "ResourceRecordSets[?Name == '$HOSTNAME.']" \
|
||||
| jq '. | length')
|
||||
if [ "$EXISTING_RECORDS" != "0" ]; then
|
||||
echo "$HOSTNAME already exists!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DEVICES+=(
|
||||
"DeviceName=/dev/sda1,Ebs={VolumeSize=$DISK_SIZE,VolumeType=gp3,Throughput=125,Iops=3000,Encrypted=true}"
|
||||
)
|
||||
if [[ "$ROLES" == *"frontend"* ]]; then
|
||||
DEVICES+=(
|
||||
"DeviceName=/dev/sdf,Ebs={VolumeSize=100,VolumeType=gp3,Throughput=125,Iops=3000,Encrypted=true,DeleteOnTermination=True}"
|
||||
)
|
||||
fi
|
||||
|
||||
# https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html
|
||||
EXTRA_ARGS+=(
|
||||
--iam-instance-profile "Name=\"$IAM_PROFILE\""
|
||||
--image-id "$AMI_ID"
|
||||
--instance-type "$INSTANCE_TYPE"
|
||||
--security-group-ids "${SECURITY_GROUPS[@]}"
|
||||
--monitoring Enabled=true
|
||||
--placement "AvailabilityZone=$AZ"
|
||||
--block-device-mappings "${DEVICES[@]}"
|
||||
--metadata-options "InstanceMetadataTags=enabled"
|
||||
)
|
||||
|
||||
if [ -n "$DEBUG_KEY" ]; then
|
||||
EXTRA_ARGS+=(
|
||||
--key-name "$DEBUG_KEY"
|
||||
)
|
||||
fi
|
||||
|
||||
# Build up the provisioning script
|
||||
BOOTDATA=$(mktemp)
|
||||
{
|
||||
echo "#!/bin/bash"
|
||||
echo "SERVER=$SERVER"
|
||||
echo "HOSTNAME=$HOSTNAME"
|
||||
echo "FULL_ROLES=$FULL_ROLES"
|
||||
echo "REPO_URL=$REPO_URL"
|
||||
echo "BRANCH=$BRANCH"
|
||||
# Replace anything which looks like FOO="inline!bar/baz" with the
|
||||
# output of pack-local-script, which will make "$FOO" inside the
|
||||
# $BOOTDATA be the path to that script (smuggled inline and
|
||||
# unpacked before use).
|
||||
perl -ple 's|^(\w+)="inline!([^"]+)"|qx(./tools/setup/pack-local-script $1 $2)|e' ./tools/setup/bootstrap-aws-installer
|
||||
} >>"$BOOTDATA"
|
||||
|
||||
TAG_ROLE_NAMES="$ROLES"
|
||||
TAGS="[{Key=Name,Value=$SERVER},{Key=role,Value=\"$TAG_ROLE_NAMES\"}]"
|
||||
INSTANCE_DATA=$($AWS ec2 run-instances \
|
||||
--tag-specifications "ResourceType=instance,Tags=$TAGS" \
|
||||
"${EXTRA_ARGS[@]}" \
|
||||
--user-data "file://$BOOTDATA")
|
||||
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
|
||||
INSTANCE_DATA=$($AWS ec2 describe-instances --instance-ids "$INSTANCEID")
|
||||
PUBLIC_DNS_NAME=$(echo "$INSTANCE_DATA" | jq -r .Reservations[0].Instances[0].PublicDnsName)
|
||||
done
|
||||
|
||||
# Add the hostname to the zone
|
||||
ROUTE53_CHANGES=$(mktemp)
|
||||
cat >"$ROUTE53_CHANGES" <<EOF
|
||||
{
|
||||
"Comment": "Add the $HOSTNAME CNAME record",
|
||||
"Changes": [
|
||||
{
|
||||
"Action": "CREATE",
|
||||
"ResourceRecordSet": {
|
||||
"Name": "$HOSTNAME",
|
||||
"Type": "CNAME",
|
||||
"TTL": 300,
|
||||
"ResourceRecords": [{"Value": "$PUBLIC_DNS_NAME"}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
$AWS route53 change-resource-record-sets --hosted-zone-id "$AWS_ZONE_ID" --change-batch "file://$ROUTE53_CHANGES"
|
||||
rm "$ROUTE53_CHANGES"
|
||||
|
||||
# Add the name to the root volume
|
||||
VOLUME_ID=$(
|
||||
echo "$INSTANCE_DATA" | jq -r \
|
||||
'.Reservations[0].Instances[0].BlockDeviceMappings[]
|
||||
| select(.DeviceName == "/dev/sda1")
|
||||
| .Ebs.VolumeId'
|
||||
)
|
||||
$AWS ec2 create-tags --resources "$VOLUME_ID" --tags "Key=Name,Value=$SERVER root"
|
||||
|
||||
# Add volume name to tmp volume
|
||||
if [[ "$ROLES" == *"frontend"* ]]; then
|
||||
VOLUME_ID=$(
|
||||
echo "$INSTANCE_DATA" | jq -r \
|
||||
'.Reservations[0].Instances[0].BlockDeviceMappings[]
|
||||
| select(.DeviceName == "/dev/sdf")
|
||||
| .Ebs.VolumeId'
|
||||
)
|
||||
$AWS ec2 create-tags --resources "$VOLUME_ID" --tags "Key=Name,Value=$SERVER tmp"
|
||||
fi
|
||||
|
||||
set +x
|
||||
echo
|
||||
echo
|
||||
echo ">>> Install started successfully! Provisioning takes 5-6min."
|
||||
echo " sleep 360 && tsh ssh root@$HOSTNAME"
|
||||
Reference in New Issue
Block a user