feat(deploy): add single-node compose migration for accounts

This commit is contained in:
Haitao Pan 2026-03-15 18:52:49 +08:00
parent c1df654cbe
commit 9f6d7b2d7d
8 changed files with 169 additions and 1 deletions

2
.gitignore vendored
View File

@ -70,3 +70,5 @@ account-export.yaml
# Security tooling reports
.gitleaks/
ansible/vars/*.host.yml
ansible/vars/*.vault.yml

13
ansible.cfg Normal file
View File

@ -0,0 +1,13 @@
[defaults]
inventory = ansible/inventory.ini
roles_path = ansible/roles:../github-org-cloud-neutral-toolkit/ansible/roles
host_key_checking = False
retry_files_enabled = False
interpreter_python = auto_silent
forks = 1
timeout = 30
[ssh_connection]
pipelining = True
transfer_method = piped
ssh_args = -o ControlMaster=no -o ControlPersist=no -o ServerAliveInterval=15 -o ServerAliveCountMax=3 -o IPQoS=none

9
ansible/inventory.ini Normal file
View File

@ -0,0 +1,9 @@
[server]
us-xhttp.svc.plus ansible_host=5.78.45.49 ansible_user=root
[all:vars]
ansible_port=22
ansible_user=root
ansible_host_key_checking=False
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_ssh_transfer_method=piped

View File

@ -0,0 +1,7 @@
- name: Deploy accounts.svc.plus to the single-node Docker Compose host
hosts: server
become: yes
gather_facts: yes
roles:
- role: accounts_compose_deploy

View File

@ -0,0 +1,21 @@
service_compose_service_slug: accounts
service_compose_image: REPLACE_IMAGE
service_compose_zone: svc.plus
service_compose_container_port: 8080
service_compose_git_short_commit: "{{ lookup('ansible.builtin.env', 'GIT_SHORT_COMMIT') | default('manual', true) }}"
service_compose_env_common:
CONFIG_TEMPLATE: /app/config/account.cloudrun.yaml
service_compose_deploy_targets:
- name: prod
deploy_subdomain_prefix: accounts
stable_domains:
- accounts.svc.plus
host_port: 18080
env: {}
- name: preview
deploy_subdomain_prefix: accounts-preview
stable_domains:
- accounts-preview.svc.plus
host_port: 18081
env: {}

View File

@ -0,0 +1,7 @@
- name: Load accounts compose defaults
ansible.builtin.include_vars:
file: "{{ role_path }}/defaults/main.yml"
- name: Delegate accounts deployment to the shared compose role
ansible.builtin.include_role:
name: shared_compose_service_deploy

View File

@ -0,0 +1,37 @@
# Copy to ansible/vars/accounts.host.yml (gitignored), or store the real values
# in an external Ansible Vault file and pass it with:
# ansible-playbook -D -C ansible/playbooks/deploy_accounts_compose.yml -e @/secure/path/accounts.vault.yml
service_compose_image: ghcr.io/YOUR_GITHUB_ORG/accounts:latest
service_compose_registry_server: ghcr.io
service_compose_registry_username: CHANGE_ME
service_compose_registry_password: CHANGE_ME
service_compose_env_common:
CONFIG_TEMPLATE: /app/config/account.cloudrun.yaml
INTERNAL_SERVICE_TOKEN: CHANGE_ME
DB_TLS_HOST: postgresql-aws.svc.plus
DB_TLS_PORT: "5443"
POSTGRES_USER: postgres
POSTGRES_PASSWORD: CHANGE_ME
DB_USER: postgres
DB_NAME: account
DB_PASSWORD: CHANGE_ME
SMTP_HOST: smtp.qq.com
SMTP_PORT: "587"
SMTP_FROM: XControl Account <noreply@svc.plus>
SMTP_USERNAME: CHANGE_ME
SMTP_PASSWORD: CHANGE_ME
service_compose_deploy_targets:
- name: prod
deploy_subdomain_prefix: accounts
stable_domains:
- accounts.svc.plus
host_port: 18080
env: {}
- name: preview
deploy_subdomain_prefix: accounts-preview
stable_domains:
- accounts-preview.svc.plus
host_port: 18081
image: ghcr.io/YOUR_GITHUB_ORG/accounts-preview:latest
env: {}

View File

@ -1,6 +1,70 @@
#!/usr/bin/env bash
set -euo pipefail
# -----------------------------------------------------------------------------
# Database tunnel bootstrap
# -----------------------------------------------------------------------------
USE_STUNNEL=0
STUNNEL_CONF="/etc/stunnel/stunnel.conf"
if [ -z "${DB_USER:-}" ] && [ -n "${POSTGRES_USER:-}" ]; then
export DB_USER="${POSTGRES_USER}"
fi
if [ -z "${DB_PASSWORD:-}" ] && [ -n "${POSTGRES_PASSWORD:-}" ]; then
export DB_PASSWORD="${POSTGRES_PASSWORD}"
fi
if [ -z "${POSTGRES_USER:-}" ] && [ -n "${DB_USER:-}" ]; then
export POSTGRES_USER="${DB_USER}"
fi
if [ -z "${POSTGRES_PASSWORD:-}" ] && [ -n "${DB_PASSWORD:-}" ]; then
export POSTGRES_PASSWORD="${DB_PASSWORD}"
fi
if [ -z "${DB_NAME:-}" ] && [ -n "${POSTGRES_DB:-}" ]; then
export DB_NAME="${POSTGRES_DB}"
fi
if [ -n "${DB_TLS_HOST:-}" ] && [ -n "${DB_TLS_PORT:-}" ]; then
USE_STUNNEL=1
export DB_HOST="${DB_HOST:-127.0.0.1}"
export DB_PORT="${DB_PORT:-15432}"
mkdir -p /etc/stunnel /var/run/stunnel
if [ -n "${DB_CA:-}" ]; then
printf '%s\n' "${DB_CA}" > /etc/stunnel/ca.pem
fi
cat > "${STUNNEL_CONF}" <<EOF
foreground = no
pid = /tmp/stunnel.pid
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
[postgres-client]
client = yes
accept = ${DB_HOST}:${DB_PORT}
connect = ${DB_TLS_HOST}:${DB_TLS_PORT}
verify = 2
EOF
if [ -f "/etc/stunnel/ca.pem" ]; then
echo "CAfile = /etc/stunnel/ca.pem" >> "${STUNNEL_CONF}"
elif [ -f "/etc/ssl/certs/ca-certificates.crt" ]; then
echo "CAfile = /etc/ssl/certs/ca-certificates.crt" >> "${STUNNEL_CONF}"
fi
if [ -n "${DB_TLS_SERVER_NAME:-}" ]; then
echo "checkHost = ${DB_TLS_SERVER_NAME}" >> "${STUNNEL_CONF}"
elif [ -n "${DB_TLS_HOST:-}" ]; then
echo "checkHost = ${DB_TLS_HOST}" >> "${STUNNEL_CONF}"
fi
fi
CONFIG_FILE="${CONFIG_PATH:-/etc/xcontrol/account.yaml}"
CONFIG_TEMPLATE="${CONFIG_TEMPLATE:-/app/config/account.yaml}"
mkdir -p "$(dirname "${CONFIG_FILE}")"
@ -31,10 +95,18 @@ if [ -n "${PORT:-}" ]; then
CONFIG_FILE="${tmp_cfg}"
fi
# Default to 127.0.0.1:15432 if not specified, to ensure we wait for stunnel
DB_HOST="${DB_HOST:-127.0.0.1}"
DB_PORT="${DB_PORT:-15432}"
if [ "${USE_STUNNEL}" -eq 1 ]; then
if ! command -v stunnel >/dev/null 2>&1; then
echo "stunnel is required but not installed" >&2
exit 1
fi
stunnel "${STUNNEL_CONF}"
fi
if [ -n "${DB_HOST:-}" ] && [ -n "${DB_PORT:-}" ]; then
if [ "${DB_HOST}" = "127.0.0.1" ] || [ "${DB_HOST}" = "localhost" ]; then
if command -v nc >/dev/null; then