113 lines
5.0 KiB
Bash
Executable File
113 lines
5.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
BUILD_HOST="${BUILD_HOST:-107}"
|
|
DEPLOY_HOST="${DEPLOY_HOST:-111}"
|
|
BUILD_PATH="${BUILD_PATH:-/opt/vpn-proxy-build}"
|
|
DEPLOY_PATH="${DEPLOY_PATH:-/opt/vpn-proxy}"
|
|
IMAGE_NAME="${IMAGE_NAME:-vpn-proxy-gateway}"
|
|
GIT_REF="$(git rev-parse --short HEAD 2>/dev/null || echo manual)"
|
|
IMAGE_TAG="${IMAGE_TAG:-${GIT_REF}-$(date +%Y%m%d%H%M%S)}"
|
|
GATEWAY_IMAGE="${GATEWAY_IMAGE:-${IMAGE_NAME}:${IMAGE_TAG}}"
|
|
BASE_IMAGE="${BASE_IMAGE:-vpn-proxy-runtime-base:bookworm-slim}"
|
|
RUNTIME_BASE_SOURCE_IMAGE="${RUNTIME_BASE_SOURCE_IMAGE:-mirror.gcr.io/library/debian:bookworm-slim}"
|
|
SINGBOX_VERSION="${SINGBOX_VERSION:-1.12.13}"
|
|
DOCKER_BUILD_PULL="${DOCKER_BUILD_PULL:-false}"
|
|
INSTALL_RUNTIME_DEPS="${INSTALL_RUNTIME_DEPS:-false}"
|
|
INSTALL_SINGBOX="${INSTALL_SINGBOX:-false}"
|
|
AUTO_BUILD_RUNTIME_BASE="${AUTO_BUILD_RUNTIME_BASE:-true}"
|
|
SSH_CONNECT_TIMEOUT="${SSH_CONNECT_TIMEOUT:-10}"
|
|
|
|
echo "Build host: ${BUILD_HOST}"
|
|
echo "Deploy host: ${DEPLOY_HOST}"
|
|
echo "Image: ${GATEWAY_IMAGE}"
|
|
echo "Base image: ${BASE_IMAGE}"
|
|
echo "Runtime base source: ${RUNTIME_BASE_SOURCE_IMAGE}"
|
|
|
|
ensure_known_host() {
|
|
local host="$1"
|
|
if [ "${host}" = "local" ]; then return 0; fi
|
|
local scan_host="${host#*@}"
|
|
scan_host="${scan_host%%:*}"
|
|
mkdir -p "${HOME}/.ssh"
|
|
chmod 700 "${HOME}/.ssh"
|
|
if ! ssh-keygen -F "${scan_host}" >/dev/null 2>&1; then
|
|
ssh-keyscan -H "${scan_host}" >> "${HOME}/.ssh/known_hosts"
|
|
fi
|
|
}
|
|
|
|
ssh_cmd() {
|
|
ssh \
|
|
-o BatchMode=yes \
|
|
-o ConnectTimeout="${SSH_CONNECT_TIMEOUT}" \
|
|
-o ServerAliveInterval=15 \
|
|
-o ServerAliveCountMax=4 \
|
|
"$@"
|
|
}
|
|
|
|
echo "Syncing source to ${BUILD_HOST}:${BUILD_PATH}"
|
|
if [ "${BUILD_HOST}" = "local" ]; then
|
|
BUILD_PATH="$(pwd)"
|
|
echo "Using local source at ${BUILD_PATH}"
|
|
else
|
|
ensure_known_host "${BUILD_HOST}"
|
|
ssh_cmd "${BUILD_HOST}" "mkdir -p '${BUILD_PATH}'"
|
|
rsync -az --delete \
|
|
-e "ssh -o BatchMode=yes -o ConnectTimeout=${SSH_CONNECT_TIMEOUT} -o ServerAliveInterval=15 -o ServerAliveCountMax=4" \
|
|
--exclude '.git' \
|
|
--exclude '.vpn-proxy' \
|
|
--exclude 'node_modules' \
|
|
--exclude 'dist' \
|
|
./ "${BUILD_HOST}:${BUILD_PATH}/"
|
|
fi
|
|
|
|
echo "Building image on ${BUILD_HOST}"
|
|
BUILD_COMMAND="set -e; echo 'Docker context:' \$(docker context show 2>/dev/null || true); docker info 2>/dev/null | sed -n '/HTTP Proxy:/p;/HTTPS Proxy:/p;/Name:/p'; cd '${BUILD_PATH}'; if ! docker image inspect '${BASE_IMAGE}' >/dev/null 2>&1; then if [ '${AUTO_BUILD_RUNTIME_BASE}' = 'true' ]; then echo 'Runtime base image ${BASE_IMAGE} is missing on ${BUILD_HOST}; building it now.'; BASE_IMAGE='${RUNTIME_BASE_SOURCE_IMAGE}' RUNTIME_BASE_IMAGE='${BASE_IMAGE}' SINGBOX_VERSION='${SINGBOX_VERSION}' ./scripts/build-runtime-base.sh; else echo 'Runtime base image ${BASE_IMAGE} is missing on ${BUILD_HOST}.'; echo 'Seed it once with: ./scripts/build-runtime-base.sh'; exit 1; fi; fi; npm ci && npm run build && docker build --pull='${DOCKER_BUILD_PULL}' --build-arg BASE_IMAGE='${BASE_IMAGE}' --build-arg SINGBOX_VERSION='${SINGBOX_VERSION}' --build-arg INSTALL_RUNTIME_DEPS='${INSTALL_RUNTIME_DEPS}' --build-arg INSTALL_SINGBOX='${INSTALL_SINGBOX}' -t '${GATEWAY_IMAGE}' ."
|
|
if [ "${BUILD_HOST}" = "local" ]; then
|
|
bash -lc "${BUILD_COMMAND}"
|
|
else
|
|
ensure_known_host "${BUILD_HOST}"
|
|
ssh_cmd "${BUILD_HOST}" "${BUILD_COMMAND}"
|
|
fi
|
|
|
|
echo "Loading image into ${DEPLOY_HOST}"
|
|
if [ "${BUILD_HOST}" = "local" ] && [ "${DEPLOY_HOST}" = "local" ]; then
|
|
docker image inspect "${GATEWAY_IMAGE}" >/dev/null
|
|
elif [ "${BUILD_HOST}" = "local" ]; then
|
|
ensure_known_host "${DEPLOY_HOST}"
|
|
echo "Checking SSH access to ${DEPLOY_HOST}"
|
|
ssh_cmd "${DEPLOY_HOST}" "true"
|
|
echo "Transferring image to ${DEPLOY_HOST}"
|
|
docker save "${GATEWAY_IMAGE}" | ssh_cmd "${DEPLOY_HOST}" "docker load"
|
|
elif [ "${DEPLOY_HOST}" = "local" ]; then
|
|
ensure_known_host "${BUILD_HOST}"
|
|
ssh_cmd "${BUILD_HOST}" "docker save '${GATEWAY_IMAGE}'" | docker load
|
|
else
|
|
ensure_known_host "${BUILD_HOST}"
|
|
ensure_known_host "${DEPLOY_HOST}"
|
|
ssh_cmd "${BUILD_HOST}" "docker save '${GATEWAY_IMAGE}'" | ssh_cmd "${DEPLOY_HOST}" "docker load"
|
|
fi
|
|
|
|
echo "Copying deploy script to ${DEPLOY_HOST}:${DEPLOY_PATH}"
|
|
if [ "${DEPLOY_HOST}" = "local" ]; then
|
|
mkdir -p "${DEPLOY_PATH}"
|
|
cp scripts/deploy-gateway.sh "${DEPLOY_PATH}/deploy-gateway.sh"
|
|
else
|
|
ensure_known_host "${DEPLOY_HOST}"
|
|
ssh_cmd "${DEPLOY_HOST}" "mkdir -p '${DEPLOY_PATH}'"
|
|
rsync -az \
|
|
-e "ssh -o BatchMode=yes -o ConnectTimeout=${SSH_CONNECT_TIMEOUT} -o ServerAliveInterval=15 -o ServerAliveCountMax=4" \
|
|
scripts/deploy-gateway.sh "${DEPLOY_HOST}:${DEPLOY_PATH}/deploy-gateway.sh"
|
|
fi
|
|
|
|
echo "Starting gateway on ${DEPLOY_HOST}"
|
|
if [ "${DEPLOY_HOST}" = "local" ]; then
|
|
cd "${DEPLOY_PATH}"
|
|
chmod +x ./deploy-gateway.sh
|
|
DEPLOY_PATH="${DEPLOY_PATH}" GATEWAY_IMAGE="${GATEWAY_IMAGE}" PULL_IMAGE=false ./deploy-gateway.sh
|
|
else
|
|
ensure_known_host "${DEPLOY_HOST}"
|
|
ssh_cmd "${DEPLOY_HOST}" \
|
|
"cd '${DEPLOY_PATH}' && chmod +x ./deploy-gateway.sh && DEPLOY_PATH='${DEPLOY_PATH}' GATEWAY_IMAGE='${GATEWAY_IMAGE}' PULL_IMAGE=false ./deploy-gateway.sh"
|
|
fi
|