#!/bin/bash # # Executa deploy.sh em um host remoto via SSH. # # ./deploy-over-ssh.sh # # O script e o arquivo .env do checkout sao copiados somente para um # diretorio temporario no host remoto. A configuracao sensivel da aplicacao # continua no CONFIG_DIR daquele host; ela nunca passa pelo job nem pelo SSH. set -euo pipefail AMBIENTE="${1:-}" TAG="${2:-}" SSH_HOST="${SSH_HOST:-}" SSH_PORT="${SSH_PORT:-22}" SSH_USER="${SSH_USER:-}" SSH_PRIVATE_KEY="${SSH_PRIVATE_KEY:-}" SSH_KNOWN_HOSTS="${SSH_KNOWN_HOSTS:-}" REGISTRY="${REGISTRY:-192.168.0.41:3001}" REGISTRY_TOKEN="${REGISTRY_TOKEN:-}" REGISTRY_USER="${REGISTRY_USER:-${ACTOR:-}}" AQUI="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ENV_FILE="${AQUI}/${AMBIENTE}.env" log() { echo "[deploy-ssh] $*"; } fail() { echo "[deploy-ssh][ERRO] $*" >&2; exit 1; } [ -n "${AMBIENTE}" ] || fail "uso: $0 " [ -n "${TAG}" ] || fail "uso: $0 " [ -f "${ENV_FILE}" ] || fail "ambiente desconhecido: ${AMBIENTE} (esperado ${ENV_FILE})" [ -n "${SSH_HOST}" ] || fail "SSH_HOST nao definido" [ -n "${SSH_USER}" ] || fail "SSH_USER nao definido" [ -n "${SSH_PRIVATE_KEY}" ] || fail "SSH_PRIVATE_KEY nao definido" [ -n "${SSH_KNOWN_HOSTS}" ] || fail "SSH_KNOWN_HOSTS nao definido" [ -n "${REGISTRY_TOKEN}" ] || fail "REGISTRY_TOKEN nao definido" [ -n "${REGISTRY_USER}" ] || fail "REGISTRY_USER/ACTOR nao definido" command -v ssh >/dev/null || fail "cliente ssh nao encontrado no job" command -v scp >/dev/null || fail "cliente scp nao encontrado no job" TMP_LOCAL="$(mktemp -d)" KEY_FILE="${TMP_LOCAL}/id_ed25519" KNOWN_HOSTS_FILE="${TMP_LOCAL}/known_hosts" REMOTE_DIR="" cleanup() { local status=$? trap - EXIT if [ -n "${REMOTE_DIR}" ]; then ssh "${SSH_OPTS[@]}" "${SSH_USER}@${SSH_HOST}" \ "docker logout '${REGISTRY}' >/dev/null 2>&1 || true; rm -rf -- '${REMOTE_DIR}'" \ >/dev/null 2>&1 || true fi rm -rf -- "${TMP_LOCAL}" exit "${status}" } trap cleanup EXIT printf '%s\n' "${SSH_PRIVATE_KEY}" > "${KEY_FILE}" printf '%s\n' "${SSH_KNOWN_HOSTS}" > "${KNOWN_HOSTS_FILE}" chmod 600 "${KEY_FILE}" "${KNOWN_HOSTS_FILE}" SSH_OPTS=( -i "${KEY_FILE}" -p "${SSH_PORT}" -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile="${KNOWN_HOSTS_FILE}" ) SCP_OPTS=( -i "${KEY_FILE}" -P "${SSH_PORT}" -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile="${KNOWN_HOSTS_FILE}" ) log "conectando em ${SSH_USER}@${SSH_HOST}:${SSH_PORT}" REMOTE_DIR="$(ssh "${SSH_OPTS[@]}" "${SSH_USER}@${SSH_HOST}" 'umask 077; mktemp -d /tmp/conectasus-deploy.XXXXXX')" case "${REMOTE_DIR}" in /tmp/conectasus-deploy.*) ;; *) fail "diretorio temporario remoto inesperado: ${REMOTE_DIR}" ;; esac log "enviando script de deploy temporariamente" scp "${SCP_OPTS[@]}" \ "${AQUI}/deploy.sh" \ "${ENV_FILE}" \ "${SSH_USER}@${SSH_HOST}:${REMOTE_DIR}/" # O login e feito no host remoto porque o docker pull sera executado por ele. # A senha trafega pelo stdin e nao aparece na linha de comando nem nos logs. printf '%s' "${REGISTRY_TOKEN}" | \ ssh "${SSH_OPTS[@]}" "${SSH_USER}@${SSH_HOST}" \ "docker login '${REGISTRY}' -u '${REGISTRY_USER}' --password-stdin" >/dev/null log "executando deploy remoto de ${AMBIENTE}:${TAG}" ssh "${SSH_OPTS[@]}" "${SSH_USER}@${SSH_HOST}" \ "chmod 700 '${REMOTE_DIR}/deploy.sh' && '${REMOTE_DIR}/deploy.sh' '${AMBIENTE}' '${TAG}'" log "deploy remoto concluido"