#!/bin/sh
# Vestro agent installer.
#
# Connects this machine to your Vestro account and runs one MetaTrader 5
# terminal per trading account you connect. Your broker password is encrypted
# in your browser to a key generated here and never leaves this machine in a
# form we can read.
#
#   curl -sSL https://get.vestro.io | sh -s -- --token=enr_...
#
# Requires: a Linux machine with systemd, root, and Docker (installed if absent).
set -eu

TOKEN=""
CONTROL_PLANE="https://vestro.io"
VERSION="2026.09.1"
RUNTIME_IMAGE="registry.vestro.io/mt5-runtime@sha256:c56a239580cd9cf251745913c59eca7daa5c0ad7d504edd7348a2fe090f803ae"
REGISTRY="${RUNTIME_IMAGE%%/*}"

while [ $# -gt 0 ]; do
    case "$1" in
        --token=*) TOKEN="${1#--token=}" ;;
        --token)   TOKEN="${2:-}"; shift ;;
        --control-plane=*) CONTROL_PLANE="${1#--control-plane=}" ;;
        *) echo "unknown option: $1" >&2; exit 2 ;;
    esac
    shift
done

if [ -z "$TOKEN" ]; then
    echo "No enrolment token." >&2
    echo "Copy the command from your dashboard: it carries a --token= that is" >&2
    echo "good for thirty minutes and can only be used once." >&2
    exit 2
fi

if [ "$(id -u)" -ne 0 ]; then
    echo "Run this as root: it installs a systemd service and talks to Docker." >&2
    exit 1
fi

ARCH="$(uname -m)"
case "$ARCH" in
    x86_64|amd64) ARCH=amd64 ;;
    aarch64|arm64) ARCH=arm64 ;;
    *) echo "Unsupported architecture: $ARCH. Vestro runs on amd64 and arm64." >&2; exit 1 ;;
esac

if [ "$(uname -s)" != "Linux" ]; then
    echo "This installer is for Linux. MetaTrader 5 runs here under Wine, in a" >&2
    echo "container, which is why the host itself does not need to be Windows." >&2
    exit 1
fi

say() { printf '  %s\n' "$1"; }

echo "Installing the Vestro agent"

# Docker, because each trading account runs in its own container: one terminal
# per account, so one hanging terminal cannot touch another account.
if ! command -v docker >/dev/null 2>&1; then
    say "Docker is not installed; installing it"
    curl -fsSL https://get.docker.com | sh >/dev/null 2>&1 || {
        echo "Could not install Docker automatically. Install it and run this again." >&2
        exit 1
    }
fi
systemctl enable --now docker >/dev/null 2>&1 || true

say "Downloading the agent (${VERSION}, ${ARCH})"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
curl -fsSL -o "$TMP/vestro-agent" \
    "$CONTROL_PLANE/agent/vestro-agent-linux-${ARCH}" || {
    echo "Could not download the agent from $CONTROL_PLANE." >&2
    exit 1
}
chmod 0755 "$TMP/vestro-agent"
# Installed under /var/lib/vestro, not /usr/local/bin.
#
# The unit below sets ProtectSystem=full, which makes /usr read only, so an
# agent living there cannot replace itself when a newer build is published —
# and a fleet that cannot update is one that only gets fixes as fast as its
# owners happen to notice. /usr/local/bin keeps a symlink so the command is
# still where anyone would look for it.
mkdir -p /var/lib/vestro/bin
install -m 0755 "$TMP/vestro-agent" /var/lib/vestro/bin/vestro-agent
ln -sf /var/lib/vestro/bin/vestro-agent /usr/local/bin/vestro-agent

install -d -m 0700 /var/lib/vestro

# The token goes in a file rather than the unit, so it is not readable in
# `systemctl cat` or in the process list. It is single use and expires in
# thirty minutes, but there is no reason to leave it lying about either.
umask 077
cat > /etc/vestro.env <<ENV
VESTRO_CONTROL_PLANE=$CONTROL_PLANE
VESTRO_ENROLMENT_TOKEN=$TOKEN
VESTRO_STATE_DIR=/var/lib/vestro
ENV

cat > /etc/systemd/system/vestro-agent.service <<'UNIT'
[Unit]
Description=Vestro agent
Documentation=https://vestro.io/docs
After=network-online.target docker.service
Wants=network-online.target
Requires=docker.service

[Service]
Type=simple
EnvironmentFile=/etc/vestro.env
ExecStart=/var/lib/vestro/bin/vestro-agent
Restart=always
RestartSec=5
# The agent talks to Docker and writes only its own state directory.
ReadWritePaths=/var/lib/vestro
NoNewPrivileges=true
ProtectHome=true
ProtectSystem=full

[Install]
WantedBy=multi-user.target
UNIT

systemctl daemon-reload
systemctl enable --now vestro-agent >/dev/null 2>&1

say "Waiting for this machine to check in"
i=0
while [ $i -lt 30 ]; do
    if [ -f /var/lib/vestro/identity.json ]; then
        # The token has done its job and is now spent. Leaving it on disk is
        # dead weight that looks exactly like a live credential to anyone
        # reading the file later — including whoever inherits this machine.
        sed -i '/^VESTRO_ENROLMENT_TOKEN=/d' /etc/vestro.env 2>/dev/null || true

        # Fetch the trading image now, while someone is watching.
        #
        # The agent would pull it anyway the first time an account converges,
        # but that happens minutes later with the terminal on screen saying it
        # is starting, and a slow link turns into "it is broken". Doing it here
        # puts the wait where it is explained and where progress is visible.
        #
        # The credential is minted for this pull and expires in minutes. The
        # docker CLI has no per-pull auth flag, so it goes through the config
        # file and is removed again below — the agent's own pulls pass it as a
        # header and never write it down at all.
        say "Fetching the trading image (about 1.6GB, once per machine)"
        IDENTITY=/var/lib/vestro/identity.json
        AGENT_CREDENTIAL=$(tr ',' '\n' < "$IDENTITY" | sed -n 's/.*"agent_credential"[^"]*"\([^"]*\)".*/\1/p' | head -1)
        if [ -n "$AGENT_CREDENTIAL" ]; then
            printf '%s' "$AGENT_CREDENTIAL" | docker login "$REGISTRY" -u vestro --password-stdin >/dev/null 2>&1 || true
            docker pull "$RUNTIME_IMAGE" || echo "  Could not fetch it now; the agent will retry when it starts a terminal."
            # The agent authenticates each pull itself, so nothing needs this on disk.
            docker logout "$REGISTRY" >/dev/null 2>&1 || true
        fi
        echo
        echo "Done. This machine is connected to your Vestro account."
        echo "Your dashboard will show it as ready within a few seconds."
        echo
        echo "  logs:    journalctl -u vestro-agent -f"
        echo "  status:  systemctl status vestro-agent"
        exit 0
    fi
    i=$((i + 1))
    sleep 2
done

echo >&2
echo "The agent is installed but has not enrolled yet." >&2
echo "The token may have expired — they last thirty minutes and work once." >&2
echo "Check: journalctl -u vestro-agent -n 50" >&2
exit 1
