Compare commits

..

7 commits

Author SHA1 Message Date
ida
154aa0359d add icmp and outbound rules
previously icmp was not on either inbound or outbound. there were
also no outbound rules whatsoever. this may have been causing issues
when creating a vm in a team with no base-firewall rules.
2025-03-28 20:20:08 +00:00
ida
6f8ada2978 make machine create use enviroment variables for vm size and region
this will allow us to make a prompt for selecting the appropriate
size and region for each user when creating a config.
2025-03-28 20:19:01 +00:00
ida
3e7416f71c minor typographical change
the e wasn't capitalized
2025-03-28 20:18:21 +00:00
ida
d54acd2d08 move version prompt to deploy.sh
this will allow us to feed automate.sh via ssh's stdin inside of
deploy.sh as ssh will not open a virtual terminal when stdin is
not is not a terminal.
2025-03-28 20:15:43 +00:00
ida
79226a01ca add automated key-ing 2025-03-27 21:14:42 +00:00
ida
3fe32c42ba add droplet deployment 2025-03-27 17:39:00 +00:00
ida
cf64fec4ae change readme 2025-03-27 12:31:15 +00:00
3 changed files with 250 additions and 252 deletions

View file

@ -23,8 +23,8 @@ fi
# find the latest release of the requested version and download it # find the latest release of the requested version and download it
echo "downloading minecraft $VERSION..." echo "downloading minecraft $VERSION..."
RELEASE=`curl -s https://api.papermc.io/v2/projects/paper/versions/$VERSION/ | jq -r .builds[-1]` RELEASE=`curl -s https://papermc.io/api/v2/projects/paper/versions/$VERSION/ | jq -r .builds[-1]`
curl https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds/$RELEASE/downloads/paper-$VERSION-$RELEASE.jar -o paperclip.jar curl https://papermc.io/api/v2/projects/paper/versions/$VERSION/builds/$RELEASE/downloads/paper-$VERSION-$RELEASE.jar -o paperclip.jar
echo "preparing..." # making sure things have the right owners echo "preparing..." # making sure things have the right owners
adduser --disabled-password --gecos "" mc adduser --disabled-password --gecos "" mc

250
deploy.sh
View file

@ -1,13 +1,259 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# required for the complex pipes in the machine function # required for the complex pipes in the machine function
shopt -s lastpipe shopt -s lastpipe
install_dir="$(dirname "$(readlink -f "$0")")" # find the install directory
source "$install_dir/functions.sh"
#TODO: add these to config create, probably with a select menu or something #TODO: add these to config create, probably with a select menu or something
size="s-2vcpu-4gb" size="s-2vcpu-4gb"
reigon="sfo3" reigon="sfo3"
config() {
local command="$1"; shift
case $command in
get)
echo 'Checking config...'
if [ -a "${XDG_CONFIG_HOME}/auto-mc-redux/conf" ]; then
source "${XDG_CONFIG_HOME}/auto-mc-redux/conf"
elif [ -a "$HOME/.config/auto-mc-redux/conf" ]; then
source "${HOME}/.config/auto-mc-redux/conf"
else
echo 'No config found!'
config create
fi
;;
create)
read -p "Enter your DigialOcean API token: " TOKEN
# this parameter expands to nothing if unset, or x if it is.
if [ -z ${XDG_CONFIG_HOME+x} ]; then
mkdir -p "${HOME}/.config/auto-mc-redux"
echo export TOKEN="${TOKEN}" > "${HOME}/.config/auto-mc-redux/conf"
chmod 600 "${HOME}/.config/auto-mc-redux/conf"
else
mkdir -p "${XDG_CONFIG_HOME}/auto-mc-redux"
echo export TOKEN="${TOKEN}" > "${XDG_CONFIG_HOME}/auto-mc-redux/conf"
chmod 600 "${XDG_CONFIG_HOME}/auto-mc-redux/conf"
fi
;;
esac
}
firewall(){
local command="$1"; shift
case $command in
# exits 0 if firewall with tag auto-mc exists, 1 if it does not
check)
echo 'Querying firewall rules...'
curl -s -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
https://api.digitalocean.com/v2/firewalls |\
jq -r .firewalls[].name | grep -q "^auto-mc$"
;;
create)
echo 'Creating firewall rule'
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d @- \
"https://api.digitalocean.com/v2/firewalls" <<-json
{
"name": "auto-mc",
"tags":["auto-mc"],
"inbound_rules": [
{
"protocol": "icmp",
"ports": "0",
"sources": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
},
{
"protocol": "tcp",
"ports": "25565",
"sources": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
},
{
"protocol": "udp",
"ports": "25565",
"sources": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
}
]
"outbound_rules": [
{
"protocol": "icmp",
"ports": "0",
"sources": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
},
{
"protocol": "tcp",
"ports": "0",
"sources": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
},
{
"protocol": "udp",
"ports": "0",
"sources": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
}
]
}
json
;;
esac
}
keys(){
local command="$1"; shift
case $command in
check)
echo "Checking DigitalOcean's keystore..."
curl -s -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/account/keys" |\
jq -r .ssh_keys[].public_key |\
while read remote_key; do
if grep -q "^$remote_key$" "$HOME/.ssh/"*.pub; then
authed_key="$remote_key"
fi
done
if [ "$authed_key" ]; then
echo "Local key already installed..."
ssh-keygen -l -E md5 -f <(echo "$authed_key") |\
cut -d':' -f 2- | cut -d' ' -f 1 | read fingerprint
export fingerprint
else
keys copy
fi
;;
copy)
key_file="$(find "$HOME/.ssh/"*.pub | sort | head -1)"
cat "$key_file" | read key
key_name=$(echo "$key" | cut --complement -d'@' -f 1)
echo "Copying key..."
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"name":"'"$key_name"'","public_key":"'"$key"'"}' \
"https://api.digitalocean.com/v2/account/keys" |
jq -r .ssh_key.fingerprint | read fingerprint
export fingerprint
echo "Key copied!"
;;
esac
}
machine(){
local command="$1"; shift
local arg="$1"; shift
case $command in
create)
# read isn't used in these pipelines because of job control shinanigans
echo 'Creating Droplet...'
curl -s -X POST \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $TOKEN" \
-d '{"name":"auto-mc",
"size":"'$size'",
"region":"'$reigon'",
"image":"ubuntu-24-10-x64",
"ssh_keys":["'$fingerprint'"],
"tags":["auto-mc"]}' \
"https://api.digitalocean.com/v2/droplets" |\
jq .droplet.id | read droplet
export droplet
echo 'Waiting for droplet to be active...'
while sleep 5; do
machine show status
if [ "$status" = 'active' ]; then
echo 'Droplet ready!'
break
fi
done
;;
destroy)
curl -s -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/droplets?tag_name=auto-mc"
;;
show)
case $arg in
ipv4)
curl -s -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/droplets/$droplet" |\
jq '.droplet.networks.v4[] | select(.type == "public")'
;;
status)
curl -s -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/droplets/$droplet" |\
jq -r .droplet.status | read status
export status
;;
esac
esac
}
versionprompt() {
# ask the user which version of minecraft they would like to install
echo "Which version of minecraft would you like to serve?"
echo -n "Version [$latest]:"
# have a timeout for user input handy for unattented installs
if ! read -t 30 version; then
version=$latest
echo "Timed out, defaulting to $latest..."
return 0
fi
if [ -n "$version" ]; then # check if the user wrote anything
echo "Probing..."
#validate user input
if ! curl -s https://api.papermc.io/v2/projects/paper/ |\
jq -r .versions | grep -q \"$version\"; then
echo "We cant find that version!"
echo "Either its not supported yet or you made an error, trying again..."
versionprompt
fi
else
version=$latest
echo "Defaulting to $latest..."
fi
}
config get config get
keys check keys check

View file

@ -1,248 +0,0 @@
config() {
local command="$1"; shift
case $command in
get)
echo 'Checking config...'
if [ -a "${XDG_CONFIG_HOME}/auto-mc-redux/conf" ]; then
source "${XDG_CONFIG_HOME}/auto-mc-redux/conf"
elif [ -a "$HOME/.config/auto-mc-redux/conf" ]; then
source "${HOME}/.config/auto-mc-redux/conf"
else
echo 'No config found!'
config create
fi
;;
create)
read -p "Enter your DigialOcean API token: " TOKEN
# this parameter expands to nothing if unset, or x if it is.
if [ -z ${XDG_CONFIG_HOME+x} ]; then
mkdir -p "${HOME}/.config/auto-mc-redux"
echo export TOKEN="${TOKEN}" > "${HOME}/.config/auto-mc-redux/conf"
chmod 600 "${HOME}/.config/auto-mc-redux/conf"
else
mkdir -p "${XDG_CONFIG_HOME}/auto-mc-redux"
echo export TOKEN="${TOKEN}" > "${XDG_CONFIG_HOME}/auto-mc-redux/conf"
chmod 600 "${XDG_CONFIG_HOME}/auto-mc-redux/conf"
fi
;;
esac
}
firewall(){
local command="$1"; shift
case $command in
# exits 0 if firewall with tag auto-mc exists, 1 if it does not
check)
echo 'Querying firewall rules...'
curl -s -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
https://api.digitalocean.com/v2/firewalls |\
jq -r .firewalls[].name | grep -q "^auto-mc$"
;;
create)
echo 'Creating firewall rule'
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d @- \
"https://api.digitalocean.com/v2/firewalls" <<-json
{
"name": "auto-mc",
"tags":["auto-mc"],
"inbound_rules": [
{
"protocol": "icmp",
"ports": "0",
"sources": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
},
{
"protocol": "tcp",
"ports": "25565",
"sources": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
},
{
"protocol": "udp",
"ports": "25565",
"sources": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
}
],
"outbound_rules": [
{
"protocol": "icmp",
"ports": "0",
"destinations": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
},
{
"protocol": "tcp",
"ports": "0",
"destinations": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
},
{
"protocol": "udp",
"ports": "0",
"destinations": {
"addresses": [
"0.0.0.0/0",
"::/0"
]
}
}
]
}
json
;;
esac
}
keys(){
local command="$1"; shift
case $command in
check)
echo "Checking DigitalOcean's keystore..."
curl -s -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/account/keys" |\
jq -r .ssh_keys[].public_key |\
while read remote_key; do
if grep -q "^$remote_key$" "$HOME/.ssh/"*.pub; then
authed_key="$remote_key"
fi
done
if [ "$authed_key" ]; then
echo "Local key already installed..."
ssh-keygen -l -E md5 -f <(echo "$authed_key") |\
cut -d':' -f 2- | cut -d' ' -f 1 | read fingerprint
export fingerprint
else
keys copy
fi
;;
copy)
key_file="$(find "$HOME/.ssh/"*.pub | sort | head -1)"
cat "$key_file" | read key
key_name=$(echo "$key" | cut --complement -d'@' -f 1)
echo "Copying key..."
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"name":"'"$key_name"'","public_key":"'"$key"'"}' \
"https://api.digitalocean.com/v2/account/keys" |
jq -r .ssh_key.fingerprint | read fingerprint
export fingerprint
echo "Key copied!"
;;
esac
}
machine(){
local command="$1"; shift
local arg="$1"; shift
case $command in
create)
# read isn't used in these pipelines because of job control shinanigans
echo 'Creating Droplet...'
curl -s -X POST \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $TOKEN" \
-d '{"name":"auto-mc",
"size":"'$size'",
"region":"'$reigon'",
"image":"ubuntu-24-10-x64",
"ssh_keys":["'$fingerprint'"],
"tags":["auto-mc"]}' \
"https://api.digitalocean.com/v2/droplets" |\
jq .droplet.id | read droplet
export droplet
echo 'Waiting for droplet to be active...'
while sleep 5; do
machine show status
if [ "$status" = 'active' ]; then
echo 'Droplet ready!'
break
fi
done
;;
destroy)
curl -s -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/droplets?tag_name=auto-mc"
;;
show)
case $arg in
ipv4)
curl -s -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/droplets/$droplet" |\
jq '.droplet.networks.v4[] | select(.type == "public")'
;;
status)
curl -s -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/droplets/$droplet" |\
jq -r .droplet.status | read status
export status
;;
esac
esac
}
versionprompt() {
# ask the user which version of minecraft they would like to install
echo "Which version of minecraft would you like to serve?"
echo -n "Version [$latest]:"
# have a timeout for user input handy for unattented installs
if ! read -t 30 version; then
version=$latest
echo "Timed out, defaulting to $latest..."
return 0
fi
if [ -n "$version" ]; then # check if the user wrote anything
echo "Probing..."
#validate user input
if ! curl -s https://api.papermc.io/v2/projects/paper/ |\
jq -r .versions | grep -q \"$version\"; then
echo "We cant find that version!"
echo "Either its not supported yet or you made an error, trying again..."
versionprompt
fi
else
version=$latest
echo "Defaulting to $latest..."
fi
}