Skip to content

Instantly share code, notes, and snippets.

@Utopiah
Created June 14, 2022 05:21
Show Gist options
  • Save Utopiah/649403cfe518f3bd30d30694eb6a8a88 to your computer and use it in GitHub Desktop.
Save Utopiah/649403cfe518f3bd30d30694eb6a8a88 to your computer and use it in GitHub Desktop.
doctl-scaling-immers
#cloud-config
package_update: true
packages:
- ca-certificates
- curl
- gnupg
- lsb-release
- git
write_files:
- content: |
port=8081
domain=immers.ovh
hub=immers.benetou.fr
homepage=
name=Utopiah Immers Space
dbHost=mongodb
dbPort=27017
dbName=immers
smtpHost=smtp.example.com
smtpPort=587
[email protected]
smtpUser=apikey
smtpPassword=1234
monetizationPointer='$ilp.uphold.com/BYR4KPxJD6ey'
googleFont=Monoton
backgroundColor=#a6549d
backgroundImage=vapor.png
customCSS=
icon=vaporwave-icon.png
imageAttributionText=Vectors by Vecteezy
imageAttributionUrl=https://www.vecteezy.com/free-vector/vector
sessionSecret=
easySecret=
path: /root/immers-env
runcmd:
- sudo mkdir -p /etc/apt/keyrings
- curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
- cd /root && git clone https://github.com/immers-space/immers-app.git
- mv /root/immers-env /root/immers-app/immers/.env
- cd /root/immers-app/immers && docker compose up -d
# see result in /var/log/cloud-init-output.log
#!/bin/bash
SIMULATION=yes
#NAME=immers-via-doctl-with-cloudinit3
# could use numbers or list e.g Greek gods (had a link for it few weeks ago...)
# same for subdomains
# could use full domain as NAME
IMAGE=ubuntu-20-04-x64
SIZE=s-1vcpu-1gb
REGION=ams3
# some of the hardcoded ID (e.g ssh-key and domain record) could instead be picked dynamically
# relying on the JSON output, easier to parse safely with jq
SSHKEYs=29367540
USERDATAFILE=./cloud-init
#DOMAIN=testsubdomain3.fosdem-metaverse.ovh
ROOTDOMAIN=fosdem-metaverse.ovh
#SUBDOMAIN=testsubdomain3
# should match cloud-init
TAG=batchcreationtest
ENDPOINT=https://CHANGEME.ngrok.io
SERVERS="immers1 immers2 immers3"
if [ -z "$SIMULATION" ]; then
# should insure ngrok is running e.g
if [ -n "$(curl --silent $ENDPOINT/ready | grep ERR_NGROK_3200)" ];
then
echo ngrok endpoint unreachable, stopping
exit # could instead start it but would need the URL back
fi
fi
# should check on root domain
#ROOTDOMAIN=$(echo $DOMAIN | sed "s/\([A-Za-z0-9-]\+\.[A-Za-z0-9-]\+\)$/\1/")
#SUBDOMAIN=$(echo $DOMAIN | sed "s/\.$ROOTDOMAIN//")
for SERVER in $SERVERS; do
echo $SERVER.$ROOTDOMAIN
DOMAIN=$SERVER.$ROOTDOMAIN
NAME=$DOMAIN
SUBDOMAIN=$SERVER
if [ -z "$SUBDOMAIN" ];
then
RECORDID=$(doctl compute domain records list $ROOTDOMAIN -o json | jq '.[] | select (.type == "A").id')
else
RECORDID=$(doctl compute domain records list $ROOTDOMAIN -o json | jq '.[] | select (.type == "A" and .name == "'$SUBDOMAIN'").id')
fi
cat cloud-init-template | sed "s/immers.ovh/$DOMAIN/" > $USERDATAFILE
echo " - curl https://$DOMAIN" >> $USERDATAFILE # used to active HTTPS certificate registration from the Immers specific process
# might be too fast if the DNS propagation isn't ready at this point
echo " - curl $ENDPOINT/cloudinitready?servername=$NAME" >> $USERDATAFILE
# ping back home when done, e.g email or curl to ngrok then notify-send
sed -e "s|sessionSecret=|sessionSecret=$(openssl rand -base64 32)|" -i $USERDATAFILE
sed -e "s|easySecret=|easySecret=$(openssl rand -base64 32)|" -i $USERDATAFILE
# easySecret=$(openssl rand -base64 32)
cp $USERDATAFILE $(date +%s)
echo creating droplet
if [ $SIMULATION ]; then
echo doctl compute droplet create $NAME --image $IMAGE --size $SIZE --region $REGION --ssh-keys $SSHKEYs --user-data-file $USERDATAFILE --tag-name $TAG --wait # to drop for parallel creation
else
doctl compute droplet create $NAME --image $IMAGE --size $SIZE --region $REGION --ssh-keys $SSHKEYs --user-data-file $USERDATAFILE --tag-name $TAG --wait # to drop for parallel creation
fi
echo adding new IP to domain
SERVERIP=$(doctl compute droplet get $NAME --template {{.PublicIPv4}})
if [ -z "$SUBDOMAIN" ];
then
if [ "$RECORDID" != "" ]; # note that it would become a different logic when doing N servers and using subdomains
then
echo "A record existing, will update (no subdomain)"
CMD="doctl compute domain records update $DOMAIN --record-id $RECORDID --record-type A --record-data $SERVERIP"
else
echo "no A record existing, will create (no subdomain)"
CMD="doctl compute domain records create $DOMAIN --record-type A --record-data $SERVERIP --record-name @"
fi
else
if [ "$RECORDID" != "" ]; # note that it would become a different logic when doing N servers and using subdomains
then
echo A record existing, will update
CMD="doctl compute domain records update $ROOTDOMAIN --record-id $RECORDID --record-type A --record-data $SERVERIP"
else
echo no A record existing, will create
CMD="doctl compute domain records create $ROOTDOMAIN --record-type A --record-data $SERVERIP --record-name $SUBDOMAIN"
fi
fi
if [ $SIMULATION ]; then
echo $CMD
else
$CMD
fi
done
# if domain not available then should drop with error message
# clean up droplets (but not DNS records, could log those based on records in the current directory, could be useful anyway for a next step e.g load balancer)
# doctl compute droplet delete -f $(doctl compute droplet list -o json | jq '.[] | select(.tags) | select(.tags[] == "batchcreationtest").id')
# provide a number N to start
# consider doing in parallel to avoid waiting too long for N servers to start sequentially
# check resizing, including with period based logs with a threshold and metric (note that it needs rebooting)
# option of specifying region or making it distributed accross
# add subdomain rather than A record
# check tags for batch operations
# trigger action once payment received (see past Tweets on Hubs via Stripe hook)
# take about 3min in total
// nodejs server to notify when cloud server spawned and ready to be used
const fs = require('fs');
const express = require('express')
const cors = require('cors')
const https = require('https')
const path = require('path')
const {execSync} = require('child_process');
const app = express()
app.use(cors())
app.get('/ready', function(req, res){
res.json({"res":"yes"})
});
app.get('/cloudinitready', function(req, res){
execSync("notify-send "+req.query.servername+" ready")
res.json({"res":"notification sent"})
});
const port = 3456
app.listen(port, () =>
console.log('listening on port', port)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment