cloud-config.yaml (281 lines of code) (raw):
#cloud-config
write_files:
- path: "/etc/teamcity/update.sh"
permissions: 0755
content: |
#!/bin/bash
while true
do
STATUS=$(curl -s -o /etc/teamcity/tags -w '%{http_code}' -H Metadata:true "http://169.254.169.254/metadata/instance/compute/tags?api-version=2017-08-01&format=text")
if [ $STATUS -eq 200 ]; then
VERSION=$(cat /etc/teamcity/tags | sed -n 's/.*teamcity-version\:\([^;]\+\).*/\1/p')
if [[ ! -z "$VERSION" ]]; then
TEAMCITY_VERSION="TEAMCITY_VERSION=$VERSION"
CURRENT_VERSION=$(at /etc/teamcity/version)
if [ "$TEAMCITY_VERSION" != "$CURRENT_VERSION" ]; then
echo "TeamCity version has changed to $VERSION"
echo "$TEAMCITY_VERSION" > /etc/teamcity/version
/usr/bin/docker pull jetbrains/teamcity-server:${VERSION}
/usr/bin/docker pull jetbrains/teamcity-agent:${VERSION}
fi
fi
fi
sleep 60
done
- path: "/etc/teamcity/database.properties"
content: |
# Database: MySQL
connectionUrl=jdbc:mysql://%RDSHost%/%RDSDataBase%?useSSL=true&requireSSL=false
connectionProperties.user=teamcity@%RDSHost%
connectionProperties.password=%RDSPassword%
maxConnections=50
testOnBorrow=true
- path: "/etc/teamcity/disabled-plugins.xml"
content: |
<?xml version="1.0" encoding="UTF-8"?>
<disabled-plugins>
<disabled-plugin name="cloud-amazon" />
<disabled-plugin name="s3-artifact-storage" />
<disabled-plugin name="vsphere" />
</disabled-plugins>
- path: "/etc/teamcity/hostname"
content: |
DOMAIN_NAME=%DomainName%
- path: "/etc/teamcity/check-certificate.sh"
permissions: 0755
content: |
#!/bin/bash
attempt=0
while docker exec letsencrypt /app/cert_status | grep ${DOMAIN_NAME} > /dev/null; [[ $? -ne 0 ]]; do
retry_in_mins=$((3**$attempt))
echo "Will try to renew certificate for ${DOMAIN_NAME} in $retry_in_mins minutes"
sleep $((60 * $retry_in_mins))
echo "Trying to renew certificate for ${DOMAIN_NAME}..."
docker exec letsencrypt /app/signal_le_service
sleep 30
attempt=$(($attempt + 1))
done
- path: "/etc/teamcity/download-file.sh"
permissions: 0755
content: |
#!/bin/bash
attempt=0
until $(curl --output $2 --silent --fail $1); do
retry_in_secs=$((3**$attempt))
echo "Will try to download file $1 in $retry_in_secs minutes"
sleep $retry_in_secs
echo "Trying to download file $1..."
attempt=$(($attempt + 1))
done
- path: "/etc/flatcar/update.conf"
content: |
REBOOT_STRATEGY="off"
flatcar:
units:
- name: "format-mnt-data.service"
enable: true
content: |
[Unit]
Requires=network-online.target
Before=teamcity-server.service mnt-data.mount
RequiresMountsFor=/dev/mapper
ConditionPathExists=!/dev/mapper/app-data
[Service]
Type=oneshot
ExecStart=/bin/bash -c \
'/usr/sbin/pvcreate /dev/disk/azure/scsi1/lun0 && \
/usr/sbin/vgcreate app /dev/disk/azure/scsi1/lun0 && \
/usr/sbin/lvcreate -l 100%%FREE -n data app && \
/usr/sbin/mkfs.ext4 /dev/mapper/app-data'
[Install]
WantedBy=multi-user.target
- name: "mnt-data.mount"
enable: true
content: |
[Unit]
Before=teamcity-server.service
After=format-mnt-data.service
Requires=format-mnt-data.service
ConditionVirtualization=!container
Conflicts=umount.target
[Mount]
What=/dev/mapper/app-data
Where=/mnt/data
Type=ext4
Options=
[Install]
RequiredBy=teamcity-server.service
- name: "get-mysql-connector.service"
enable: true
content: |
[Unit]
Before=teamcity-server.service
After=mnt-data.mount
Requires=mnt-data.mount
ConditionPathExists=!/mnt/data/teamcity-server/data/lib/jdbc/mysql-connector-java-bin.jar
[Service]
Type=oneshot
ExecStart=/bin/mkdir -p /mnt/data/teamcity-server/data/lib/jdbc
ExecStart=/bin/bash /etc/teamcity/download-file.sh \
https://repo.maven.apache.org/maven2/mysql/mysql-connector-java/5.1.47/mysql-connector-java-5.1.47.jar \
/mnt/data/teamcity-server/data/lib/jdbc/mysql-connector-java-bin.jar
[Install]
WantedBy=multi-user.target
- name: "get-azure-plugins.service"
enable: true
content: |
[Unit]
Before=teamcity-server.service
After=mnt-data.mount
Requires=mnt-data.mount
ConditionPathExists=!/mnt/data/teamcity-server/data/plugins/azure-plugins.txt
[Service]
Type=oneshot
ExecStart=/bin/mkdir -p /mnt/data/teamcity-server/data/plugins
ExecStart=/bin/bash /etc/teamcity/download-file.sh \
https://raw.githubusercontent.com/JetBrains/teamcity-azure-template/master/azure-plugins.txt \
/mnt/data/teamcity-server/data/plugins/azure-plugins.txt
ExecStart=/bin/bash -c 'cd /mnt/data/teamcity-server/data/plugins && curl -K azure-plugins.txt'
[Install]
WantedBy=multi-user.target
- name: "prepare-config.service"
enable: true
content: |
[Unit]
Before=teamcity-server.service
After=mnt-data.mount
Requires=mnt-data.mount network-online.target
ConditionPathExists=!/mnt/data/teamcity-server/data/config
[Service]
Type=oneshot
ExecStart=/bin/mkdir -p /mnt/data/teamcity-server/data/config
ExecStart=/bin/mv /etc/teamcity/database.properties /mnt/data/teamcity-server/data/config/
ExecStart=/bin/mv /etc/teamcity/disabled-plugins.xml /mnt/data/teamcity-server/data/config/
[Install]
WantedBy=multi-user.target
- name: "teamcity-update.service"
command: "start"
content: |
[Unit]
After=docker.service
Before=teamcity-server.service teamcity-agent.service
Requires=docker.service network-online.target
[Service]
ExecStart=/bin/sh /etc/teamcity/update.sh
Restart=always
[Install]
WantedBy=multi-user.target
- name: "teamcity-server.service"
command: "start"
content: |
[Unit]
Description=TeamCity Server
After=docker.service mnt-data.mount get-mysql-connector.service get-azure-plugins.service prepare-config.service teamcity-update.service letsencrypt.service
Requires=docker.service mnt-data.mount get-mysql-connector.service get-azure-plugins.service prepare-config.service teamcity-update.service letsencrypt.service
[Service]
TimeoutStartSec=1200s
EnvironmentFile=/etc/teamcity/version
EnvironmentFile=/etc/teamcity/hostname
ExecStartPre=/bin/sh -c "docker images --filter 'before=jetbrains/teamcity-server:${TEAMCITY_VERSION}' --format '{{.ID}} {{.Repository}}' | grep 'jetbrains/teamcity-server' | grep -Eo '^[^ ]+' | xargs -r docker rmi"
ExecStartPre=/usr/bin/docker create \
-e TEAMCITY_SERVER_MEM_OPTS="-Xmx$(($(grep MemTotal /proc/meminfo | awk '{print $2}') / 2))k -XX:MaxPermSize=270m -XX:ReservedCodeCacheSize=350m" \
-e VIRTUAL_PORT=8111 \
-e VIRTUAL_HOST=${DOMAIN_NAME} \
-e LETSENCRYPT_HOST=${DOMAIN_NAME} %DomainOwnerEmailEnv% \
-v /mnt/data/teamcity-server/data:/data/teamcity_server/datadir \
-v /mnt/data/teamcity-server/logs:/opt/teamcity/logs \
-v /mnt/resource/teamcity-server/temp:/opt/teamcity/temp \
--name teamcity-server \
jetbrains/teamcity-server:${TEAMCITY_VERSION}
ExecStartPre=/bin/sh -c "echo 'azure' > dist && docker cp dist teamcity-server:/opt/teamcity/webapps/ROOT/WEB-INF/DistributionType.txt && rm dist"
ExecStart=/usr/bin/docker start teamcity-server -a
ExecStop=-/usr/bin/docker exec teamcity-server /opt/teamcity/bin/teamcity-server.sh stop 60
ExecStopPost=-/usr/bin/docker stop teamcity-server
ExecStopPost=-/usr/bin/docker rm teamcity-server
Restart=always
[Install]
WantedBy=multi-user.target
- name: "teamcity-agent.service"
command: "start"
content: |
[Unit]
Description=TeamCity Agent
After=teamcity-server.service teamcity-update.service
Requires=docker.service teamcity-server.service teamcity-update.service
[Service]
TimeoutStartSec=1200s
EnvironmentFile=/etc/teamcity/version
EnvironmentFile=/etc/teamcity/hostname
ExecStartPre=/bin/sh -c "docker images --filter 'before=jetbrains/teamcity-agent:${TEAMCITY_VERSION}' --format '{{.ID}} {{.Repository}}' | grep 'jetbrains/teamcity-agent' | grep -Eo '^[^ ]+' | xargs -r docker rmi"
ExecStart=/usr/bin/docker run \
-v /mnt/data/teamcity-agent/conf:/opt/buildagent/conf \
-v /mnt/data/teamcity-agent/logs:/opt/buildagent/logs \
-v /mnt/data/teamcity-agent/plugins:/opt/buildagent/plugins \
-v /mnt/data/teamcity-agent/system:/opt/buildagent/system \
-v /mnt/resource/teamcity-agent/temp:/opt/buildagent/temp \
-v /mnt/resource/teamcity-server/temp:/opt/teamcity/temp \
-v /mnt/data/teamcity-agent/tools:/opt/buildagent/tools \
--privileged \
-e DOCKER_IN_DOCKER=start \
-e SERVER_URL=https://${DOMAIN_NAME} \
-e AGENT_NAME=Default \
--name teamcity-agent \
jetbrains/teamcity-agent:${TEAMCITY_VERSION}
ExecStop=-/usr/bin/docker exec teamcity-agent /opt/buildagent/bin/agent.sh stop
ExecStopPost=-/usr/bin/docker stop teamcity-agent
ExecStopPost=-/usr/bin/docker rm teamcity-agent
Restart=always
[Install]
WantedBy=multi-user.target
- name: "nginx.service"
command: "start"
content: |
[Unit]
Description=NGINX reverse proxy
Requires=docker.service
[Service]
TimeoutStartSec=1200s
ExecStartPre=/bin/mkdir -p /opt/domains/certs
ExecStartPre=/bin/mkdir -p /opt/domains/vhost.d
ExecStartPre=/bin/mkdir -p /opt/domains/nginx/html
ExecStart=/usr/bin/docker run \
-p 80:80 \
-p 443:443 \
-v /opt/domains/certs:/etc/nginx/certs:ro \
-v /opt/domains/vhost.d:/etc/nginx/vhost.d \
-v /opt/domains/nginx/html:/usr/share/nginx/html \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
--name nginx \
jwilder/nginx-proxy
ExecStop=-/usr/bin/docker stop nginx
ExecStopPost=-/usr/bin/docker rm nginx
Restart=always
[Install]
WantedBy=multi-user.target
- name: "letsencrypt.service"
command: "start"
content: |
[Unit]
Description=Let's Encrypt
Requires=docker.service nginx.service
After=nginx.service
[Service]
TimeoutStartSec=1200s
ExecStart=/usr/bin/docker run \
-v /opt/domains/certs:/etc/nginx/certs:rw \
--volumes-from nginx \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--name letsencrypt \
jrcs/letsencrypt-nginx-proxy-companion
ExecStop=-/usr/bin/docker stop letsencrypt
ExecStopPost=-/usr/bin/docker rm letsencrypt
Restart=always
[Install]
WantedBy=multi-user.target
- name: "report-waiter-status.service"
enable: true
command: "start"
content: |
[Unit]
Requires=docker.service teamcity-server.service nginx.service letsencrypt.service
ConditionPathExists=!/etc/teamcity/waiter
[Service]
Type=oneshot
EnvironmentFile=/etc/teamcity/hostname
ExecStartPre=/bin/bash /etc/teamcity/check-certificate.sh
ExecStart=/bin/bash -c "until $(curl --output /dev/null --silent --fail https://${DOMAIN_NAME}); do echo 'Waiting for success response from ${DOMAIN_NAME}'; sleep 10; done;"
ExecStartPost=/bin/touch /etc/teamcity/waiter
[Install]
WantedBy=multi-user.target