|
# Add user to passwordless sudo |
|
|
|
sudo groupadd wheel |
|
sudo usermod -aG wheel user |
|
echo '%wheel ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/wheel-nopasswd |
|
sudo chmod 0440 /etc/sudoers.d/wheel-nopasswd |
|
|
|
# Install Caddy, and start its process |
|
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl |
|
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg |
|
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list |
|
chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg |
|
chmod o+r /etc/apt/sources.list.d/caddy-stable.list |
|
sudo apt update |
|
sudo apt install caddy |
|
|
|
# Install Docker |
|
sudo apt update |
|
sudo apt install ca-certificates curl |
|
sudo install -m 0755 -d /etc/apt/keyrings |
|
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc |
|
sudo chmod a+r /etc/apt/keyrings/docker.asc |
|
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF |
|
Types: deb |
|
URIs: https://download.docker.com/linux/debian |
|
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME") |
|
Components: stable |
|
Signed-By: /etc/apt/keyrings/docker.asc |
|
EOF |
|
sudo apt update |
|
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin |
|
sudo usermod -aG docker user |
|
|
|
# Add vim and rsync |
|
sudo apt install vim rsync |
|
|
|
# Add owner for /var/www |
|
sudo mkdir -p /var/www |
|
sudo chown -R root:www-data /var/www |
|
sudo chmod -R 2755 /var/www |
|
|
|
# Set up Caddy config |
|
sudo mkdir -p /etc/caddy/sites/ |
|
sudo tee /etc/caddy/Caddyfile > /dev/null << 'EOF' |
|
{ |
|
log { |
|
level WARN |
|
} |
|
} |
|
|
|
import sites/*.caddyfile |
|
EOF |
|
caddy validate --config /etc/caddy/Caddyfile && sudo systemctl reload caddy |
|
|
|
# Define the scripts |
|
sudo tee /bin/add-site > /dev/null << 'EOS' |
|
#!/bin/bash |
|
set -e |
|
if [[ $# -ne 2 ]]; then |
|
echo "Usage: add-site hostname port" >&2 |
|
echo "e.g. add-site test.com 8080" >&2 |
|
exit 1 |
|
fi |
|
DEPLOY_HOSTNAME="$1" |
|
DEPLOY_PORT="$2" |
|
if [[ "$DEPLOY_HOSTNAME" == */* || "$DEPLOY_HOSTNAME" == "." || "$DEPLOY_HOSTNAME" == ".." ]]; then |
|
echo "Invalid hostname: $DEPLOY_HOSTNAME" >&2 |
|
exit 1 |
|
fi |
|
if ! [[ "$DEPLOY_PORT" =~ ^[0-9]+$ ]] || (( DEPLOY_PORT < 1 || DEPLOY_PORT > 65535 )); then |
|
echo "Invalid port: $DEPLOY_PORT" >&2 |
|
exit 1 |
|
fi |
|
CONFIG_FILENAME="/etc/caddy/sites/$DEPLOY_HOSTNAME.caddyfile" |
|
NEW_CONF=$(cat <<EOF |
|
# add-site $DEPLOY_HOSTNAME $DEPLOY_PORT |
|
$DEPLOY_HOSTNAME { |
|
reverse_proxy 127.0.0.1:$DEPLOY_PORT |
|
} |
|
EOF |
|
) |
|
if ! sudo -n true 2>/dev/null; then |
|
echo "Permission denied, cannot update Caddy configuration" >&2 |
|
exit 1 |
|
fi |
|
if sudo test -f "$CONFIG_FILENAME"; then |
|
OLD_CONF=$(sudo cat "$CONFIG_FILENAME") |
|
HAD_CONF=1 |
|
else |
|
OLD_CONF="" |
|
HAD_CONF=0 |
|
fi |
|
if [[ $HAD_CONF -eq 1 && "$NEW_CONF" == "$OLD_CONF" ]]; then |
|
echo "No change needed for Caddy configuration" >&2 |
|
exit 0 |
|
fi |
|
sudo tee "$CONFIG_FILENAME" > /dev/null <<< "$NEW_CONF" |
|
if caddy validate --config /etc/caddy/Caddyfile; then |
|
sudo systemctl reload caddy |
|
echo "Updated Caddy configuration" >&2 |
|
elif [[ $HAD_CONF -eq 1 ]]; then |
|
sudo tee "$CONFIG_FILENAME" > /dev/null <<< "$OLD_CONF" |
|
echo "Caddy configuration invalid, restored previous $CONFIG_FILENAME" >&2 |
|
exit 1 |
|
else |
|
sudo rm -f "$CONFIG_FILENAME" |
|
echo "Caddy configuration invalid, removed $CONFIG_FILENAME" >&2 |
|
exit 1 |
|
fi |
|
EOS |
|
sudo chmod ugo+rx /bin/add-site |
|
|
|
sudo tee /bin/remove-site > /dev/null << 'EOS' |
|
#!/bin/bash |
|
set -e |
|
if [[ $# -ne 1 ]]; then |
|
echo "Usage: remove-site hostname" >&2 |
|
echo "e.g. remove-site test.com" >&2 |
|
exit 1 |
|
fi |
|
DEPLOY_HOSTNAME="$1" |
|
if [[ "$DEPLOY_HOSTNAME" == */* || "$DEPLOY_HOSTNAME" == "." || "$DEPLOY_HOSTNAME" == ".." ]]; then |
|
echo "Invalid hostname: $DEPLOY_HOSTNAME" >&2 |
|
exit 1 |
|
fi |
|
CONFIG_FILENAME="/etc/caddy/sites/$DEPLOY_HOSTNAME.caddyfile" |
|
if ! sudo -n true 2>/dev/null; then |
|
echo "Permission denied, cannot update Caddy configuration" >&2 |
|
exit 1 |
|
fi |
|
if ! sudo test -f "$CONFIG_FILENAME"; then |
|
echo "No change needed for Caddy configuration" >&2 |
|
exit 0 |
|
fi |
|
OLD_CONF=$(sudo cat "$CONFIG_FILENAME") |
|
sudo rm -f "$CONFIG_FILENAME" |
|
if caddy validate --config /etc/caddy/Caddyfile; then |
|
sudo systemctl reload caddy |
|
echo "Updated Caddy configuration" >&2 |
|
else |
|
sudo tee "$CONFIG_FILENAME" > /dev/null <<< "$OLD_CONF" |
|
echo "Caddy configuration invalid after removal, restored $CONFIG_FILENAME" >&2 |
|
exit 1 |
|
fi |
|
EOS |
|
sudo chmod ugo+rx /bin/remove-site |
|
|
|
sudo tee /bin/list-sites > /dev/null << 'EOS' |
|
#!/bin/bash |
|
set -e |
|
shopt -s nullglob |
|
CONFIGS=(/etc/caddy/sites/*.caddyfile) |
|
SITES="" |
|
if [[ ${#CONFIGS[@]} -gt 0 ]]; then |
|
SITES=$(head -n1 -q "${CONFIGS[@]}" | grep '^# add-site' || true) |
|
fi |
|
if [[ -z "$SITES" ]]; then |
|
echo "No sites configured" >&2 |
|
exit 0 |
|
fi |
|
printf '%s\n' "$SITES" |
|
EOS |
|
sudo chmod ugo+rx /bin/list-sites |
Todo: add notes about creating new users. Fairly simple:
Add new keypair