136 lines
4.1 KiB
Bash
Executable File

provision_vps() {
LABEL="$1"
REGION="$2"
TYPE="$3"
IMAGE="$4"
ROOT_PASS="${5:-$(openssl rand -base64 16)}"
if [[ "$LINODE_API_TOKEN" == "REPLACE_WITH_YOUR_LINODE_API_TOKEN" ]]; then
echo "❌ Error: You must set your LINODE_API_TOKEN at the top of this script."
exit 1
fi
CLOUD_INIT=$(cat <<EOF
#cloud-config
hostname: genesis-vps
manage_etc_hosts: true
write_files:
- path: /usr/local/bin/genesis_squeaky.sh
permissions: '0755'
content: |
#!/bin/bash
set -e
GEN_HOSTNAME="genesis-vps-$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 6)"
LOGDIR="/home/doc/vpslogs"
LOGFILE="$LOGDIR/$GEN_HOSTNAME.log"
IP_ADDR=$(hostname -I | awk '{print $1}')
iptables -A OUTPUT -p icmp --icmp-type time-exceeded -j DROP
iptables -A INPUT -p udp --dport 33434:33534 -j DROP
iptables -A INPUT -p tcp --dport 33434:33534 -j DROP
hostnamectl set-hostname "$GEN_HOSTNAME"
sed -i "s/^127.0.1.1.*/127.0.1.1 $GEN_HOSTNAME/" /etc/hosts
systemctl stop linode-cloudinit 2>/dev/null || true
systemctl disable linode-cloudinit 2>/dev/null || true
touch /etc/cloud/cloud-init.disabled
rm -rf /etc/cloud /var/lib/cloud /var/log/cloud-init.log
rm -f /etc/motd /etc/update-motd.d/linode
rm -rf /usr/share/linode*
rm -f /etc/apt/sources.list.d/linode.list
apt remove --purge -y linode-cli linode-config 2>/dev/null || true
echo "[genesisctl] Attempting to log to Krang via webhook..." >> /var/log/genesis-harden.log
curl -s -X POST -H "Content-Type: application/json" \
-d "{\"host\": \"$GEN_HOSTNAME\", \"ip\": \"$IP_ADDR\", \"timestamp\": \"$(date)\"}" \
http://krang.core.sshjunkie.com:8080/genesislog >> /var/log/genesis-harden.log 2>&1 || echo "[genesisctl] Krang webhook logging failed" >> /var/log/genesis-harden.log
touch /var/log/genesis-hardened.ok
runcmd:
- [ bash, /usr/local/bin/genesis_squeaky.sh ]
EOF
)
USER_DATA=$(echo "$CLOUD_INIT" | base64 -w 0)
echo "Provisioning VPS '$LABEL' in $REGION with type $TYPE and image $IMAGE..."
TMP_FILE=$(mktemp)
JSON_PAYLOAD=$(cat <<EOF
{
"label": "$LABEL",
"region": "$REGION",
"type": "$TYPE",
"image": "$IMAGE",
"authorized_users": [],
"root_pass": "$ROOT_PASS",
"booted": true,
"metadata": {
"user_data": "$USER_DATA"
}
}
EOF
)
HTTP_STATUS=$(curl -s -o "$TMP_FILE" -w "%{http_code}" -X POST https://api.linode.com/v4/linode/instances \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $LINODE_API_TOKEN" \
-d "$JSON_PAYLOAD")
echo -e "\n--- HTTP STATUS: $HTTP_STATUS ---"
echo "--- RAW RESPONSE: ---"
cat "$TMP_FILE"
if [[ "$HTTP_STATUS" != "200" && "$HTTP_STATUS" != "201" ]]; then
echo -e "\n❌ Failed to provision VPS (HTTP $HTTP_STATUS)"
jq . "$TMP_FILE"
exit 1
fi
echo -e "\n✅ VPS provisioned:"
IP=$(jq -r '.ipv4[0]' "$TMP_FILE")
LINODE_ID=$(jq -r '.id' "$TMP_FILE")
echo "Label: $LABEL"
echo "IP Address: $IP"
echo "Root Password: $ROOT_PASS"
# Add DNS record to Cloudflare
echo "📡 Adding A record for $LABEL.$CF_DOMAIN$IP..."
echo "[DEBUG] CF_API_TOKEN=$CF_API_TOKEN"
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @<(cat <<JSON
{
"type": "A",
"name": "$LABEL.$CF_DOMAIN",
"content": "$IP",
"ttl": 120,
"proxied": false
}
JSON
) | jq '.success, .errors, .messages'
echo "⏳ Waiting indefinitely for DNS to propagate before setting rDNS..."
i=1
while true; do
CURRENT_IP=$(dig +short "$LABEL.$CF_DOMAIN")
if [[ "$CURRENT_IP" == "$IP" ]]; then
echo "✅ A record resolved. Setting rDNS..."
curl -s -X PUT "https://api.linode.com/v4/linode/instances/$LINODE_ID/ips/$IP" \
-H "Authorization: Bearer $LINODE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"rdns": "'"$LABEL.$CF_DOMAIN"'"}'
break
fi
echo "⏳ Attempt $i: DNS not ready. Waiting 15s..."
sleep 15
((i++))
done
echo "$LINODE_ID|$IP|$LABEL" >> /home/doc/vpslogs/pending_rdns.log
}