#!/bin/sh
#
# quickstart.sh
#
# Alpine Linux host provisioning. Run once on a fresh server.
# Push the entire hosts/alpine/ directory via scp first:
#
#   scp -r hosts/alpine/ root@your-server:/root/alpine
#   ssh root@your-server "cd /root/alpine && sh quickstart.sh"
#

set -e

# Install dependencies
apk update
apk upgrade
apk add \
    neovim \
    rsync \
    git \
    ip6tables \
    iptables \
    ufw \
    restic \
    docker \
    docker-cli-buildx \
    docker-compose

# Configure firewall
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 80/udp   # http3
ufw allow 443/tcp
ufw allow 443/udp  # http3
ufw --force enable

# Install configuration files
cp etc/apk/repositories /etc/apk/repositories && chmod 644 /etc/apk/repositories
cp etc/periodic/daily/apk-autoupgrade /etc/periodic/daily/apk-autoupgrade && chmod 700 /etc/periodic/daily/apk-autoupgrade
cp etc/periodic/daily/restic-autobackup /etc/periodic/daily/restic-autobackup && chmod 700 /etc/periodic/daily/restic-autobackup
cp root/server-health-check.sh /root/server-health-check.sh && chmod 700 /root/server-health-check.sh
cp root/restore.sh /root/restore.sh && chmod 700 /root/restore.sh

# Create directory structure
mkdir -p /srv/git /srv/docker /srv/data
mkdir -p /root/.restic && chmod 700 /root/.restic

echo ""
echo "** Place restic credentials before backups will run: **"
echo "   /root/.restic/password   restic repo password (chmod 600)"
echo "   /root/.restic/b2-env     exports B2_ACCOUNT_ID and B2_ACCOUNT_KEY (chmod 600)"
echo ""

# Provision each project from projects.conf
while IFS='|' read -r name repo branch has_data has_migrate; do
    # Skip comments and blank lines
    case "$name" in \#*|"") continue ;; esac

    echo "--- Provisioning $name ---"

    # Bare git repo for push-to-deploy
    if [ ! -d "/srv/git/${name}.git" ]; then
        git init --bare "/srv/git/${name}.git"
    fi

    # Working clone for docker-compose
    if [ ! -d "/srv/docker/${name}" ]; then
        git clone "git@github.com:${repo}.git" "/srv/docker/${name}" -b "$branch"
    fi

    # Data directory
    if [ "$has_data" = "yes" ] && [ ! -d "/srv/data/${name}" ]; then
        mkdir -p "/srv/data/${name}"
    fi

    # .env file from sample if it exists
    if [ ! -f "/srv/docker/${name}/.env" ] && [ -f "/srv/docker/${name}/samplefiles/env.sample" ]; then
        cp "/srv/docker/${name}/samplefiles/env.sample" "/srv/docker/${name}/.env"
        echo "  ** Review and edit /srv/docker/${name}/.env **"
    fi

    # Post-receive hook
    cat > "/srv/git/${name}.git/hooks/post-receive" << HOOK
#!/bin/sh

while read oldrev newrev ref; do
  if [ "\$ref" = "refs/heads/${branch}" ]; then
    unset GIT_DIR
    START_TIME=\$(date +%s)
    cd /srv/docker/${name}
    git pull
    docker compose up --build --detach
    # Reattach every container in the project to the shared edge network.
    # Resolved via \`compose ps\` (not \`${name}\`) so this works regardless
    # of the compose service name or container_name override.
    for cid in \$(docker compose ps -q); do
      docker network connect bythewood-edge "\$cid" 2>/dev/null || true
    done
HOOK

    if [ "$has_migrate" = "yes" ]; then
        cat >> "/srv/git/${name}.git/hooks/post-receive" << 'MIGRATE'
    docker compose exec -T web python3 manage.py migrate --noinput
MIGRATE
    fi

    cat >> "/srv/git/${name}.git/hooks/post-receive" << TAIL
    docker container prune --force
    docker image prune --force
    END_TIME=\$(date +%s)
    echo "Total build time: \$((END_TIME - START_TIME))s"
  fi
done
TAIL

    chmod +x "/srv/git/${name}.git/hooks/post-receive"

done < srv/projects.conf

# Start services and add to startup
rc-update add ufw boot && rc-service ufw start
rc-update add docker boot && rc-service docker start

# Shared edge network: Caddy and every project's web container attach here so
# Caddy can reverse_proxy by container name. Created idempotently; the
# post-receive hooks reattach project containers after each rebuild.
docker network create bythewood-edge 2>/dev/null || true

# Caddy runs as a container, not on the host. Bind-mount the Caddyfile so
# `docker compose exec caddy caddy reload` picks up edits without a rebuild.
# /srv/data/caddy holds ACME certs and account keys; backed up via restic
# along with every other /srv/data/<project>/ directory.
mkdir -p /srv/docker/caddy /srv/data/caddy
cp srv/caddy/docker-compose.yml /srv/docker/caddy/docker-compose.yml
cp srv/caddy/Caddyfile /srv/docker/caddy/Caddyfile
( cd /srv/docker/caddy && docker compose up --detach )

echo ""
echo "Server provisioned. Review .env files in /srv/docker/*/  before starting containers."
echo "Add server remotes to your local repos:  git remote add server root@this-server:/srv/git/PROJECT.git"
