2025-12-04 01:00:41 +01:00
|
|
|
#!/bin/bash
|
|
|
|
|
#
|
|
|
|
|
# LetsBe Deployment Script
|
|
|
|
|
# Deploys the LetsBe setup to a remote server via SSH.
|
|
|
|
|
#
|
|
|
|
|
# Usage:
|
|
|
|
|
# ./start.sh --host 192.168.1.100 --password "mypassword" --action setup
|
|
|
|
|
# ./start.sh --host 192.168.1.100 --key ./id_ed25519 --action setup --tools "all"
|
|
|
|
|
# ./start.sh --host 192.168.1.100 --key ./id_ed25519 --action connect
|
|
|
|
|
# ./start.sh --config config.json
|
|
|
|
|
#
|
|
|
|
|
# Arguments:
|
|
|
|
|
# --host Server IP address (required)
|
|
|
|
|
# --port SSH port (default: 22, after setup: 22022)
|
|
|
|
|
# --password SSH password for root (initial setup)
|
|
|
|
|
# --key Path to SSH private key (for stefan user)
|
|
|
|
|
# --action "setup" or "connect" (required)
|
|
|
|
|
# --tools Tools to deploy (passed to setup.sh)
|
|
|
|
|
# --skip-ssl Skip SSL setup (passed to setup.sh)
|
|
|
|
|
# --config Path to JSON config file
|
|
|
|
|
# --json Inline JSON configuration
|
|
|
|
|
#
|
|
|
|
|
# JSON Config Format:
|
|
|
|
|
# {
|
|
|
|
|
# "host": "192.168.1.100",
|
|
|
|
|
# "port": 22,
|
|
|
|
|
# "password": "...",
|
|
|
|
|
# "key": "./id_ed25519",
|
|
|
|
|
# "action": "setup",
|
|
|
|
|
# "tools": "all",
|
|
|
|
|
# "skip_ssl": false,
|
|
|
|
|
# "customer": "acme",
|
|
|
|
|
# "domain": "acme.com",
|
2025-12-07 12:28:08 +01:00
|
|
|
# "company_name": "Acme Corp",
|
|
|
|
|
# "registration_token": "uuid-from-orchestrator"
|
2025-12-04 01:00:41 +01:00
|
|
|
# }
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
# =============================================================================
|
|
|
|
|
# CONFIGURATION DEFAULTS
|
|
|
|
|
# =============================================================================
|
|
|
|
|
|
|
|
|
|
SERVER_IP=""
|
|
|
|
|
SERVER_PORT="22"
|
|
|
|
|
SERVER_PASSWORD=""
|
|
|
|
|
SSH_KEY=""
|
|
|
|
|
ACTION=""
|
|
|
|
|
TOOLS=""
|
|
|
|
|
SKIP_SSL=""
|
|
|
|
|
ROOT_SSL=""
|
|
|
|
|
CONFIG_JSON=""
|
|
|
|
|
|
|
|
|
|
# env_setup.sh parameters
|
|
|
|
|
CUSTOMER=""
|
|
|
|
|
DOMAIN=""
|
|
|
|
|
COMPANY_NAME=""
|
|
|
|
|
|
2025-12-08 16:13:48 +01:00
|
|
|
# Docker registry authentication (optional)
|
2025-12-05 16:48:43 +01:00
|
|
|
DOCKER_USER=""
|
|
|
|
|
DOCKER_TOKEN=""
|
2025-12-08 16:13:48 +01:00
|
|
|
DOCKER_REGISTRY=""
|
2025-12-05 16:48:43 +01:00
|
|
|
|
2025-12-08 21:20:27 +01:00
|
|
|
# Gitea registry authentication (for private images)
|
|
|
|
|
GITEA_REGISTRY=""
|
|
|
|
|
GITEA_USER=""
|
|
|
|
|
GITEA_TOKEN=""
|
|
|
|
|
|
2025-12-04 01:00:41 +01:00
|
|
|
# =============================================================================
|
|
|
|
|
# HELPER FUNCTIONS
|
|
|
|
|
# =============================================================================
|
|
|
|
|
|
|
|
|
|
usage() {
|
|
|
|
|
echo "Usage: $0 --host IP --action [setup|connect] [options]"
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Required:"
|
|
|
|
|
echo " --host Server IP address"
|
|
|
|
|
echo " --action 'setup' or 'connect'"
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Authentication (one required for setup):"
|
|
|
|
|
echo " --password SSH password for root (initial setup)"
|
|
|
|
|
echo " --key Path to SSH private key"
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Optional:"
|
|
|
|
|
echo " --port SSH port (default: 22)"
|
|
|
|
|
echo " --tools Tools to deploy (comma-separated or 'all')"
|
|
|
|
|
echo " --skip-ssl Skip SSL certificate setup"
|
|
|
|
|
echo " --root-ssl Include root domain in SSL certificate"
|
|
|
|
|
echo " --customer Customer name for env_setup.sh"
|
|
|
|
|
echo " --domain Domain for env_setup.sh"
|
|
|
|
|
echo " --company Company name for env_setup.sh"
|
2025-12-05 16:48:43 +01:00
|
|
|
echo " --docker-user Docker Hub username (optional, to bypass rate limits)"
|
|
|
|
|
echo " --docker-token Docker Hub Personal Access Token (optional)"
|
2025-12-04 01:00:41 +01:00
|
|
|
echo ""
|
|
|
|
|
echo "JSON Input:"
|
|
|
|
|
echo " --config Path to JSON config file"
|
|
|
|
|
echo " --json Inline JSON configuration"
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Examples:"
|
|
|
|
|
echo " $0 --host 1.2.3.4 --password 'pass' --action setup --tools all"
|
|
|
|
|
echo " $0 --host 1.2.3.4 --key ./id_ed25519 --port 22022 --action connect"
|
|
|
|
|
echo " $0 --config config.json"
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_and_replace_ssh_key() {
|
|
|
|
|
local server_ip=$1
|
|
|
|
|
local server_port=$2
|
|
|
|
|
|
|
|
|
|
# Ensure ~/.ssh directory exists
|
|
|
|
|
mkdir -p ~/.ssh 2>/dev/null || true
|
|
|
|
|
chmod 700 ~/.ssh 2>/dev/null || true
|
|
|
|
|
|
|
|
|
|
# Remove old host key if it exists
|
|
|
|
|
ssh-keygen -R "[$server_ip]:$server_port" >/dev/null 2>&1 || true
|
|
|
|
|
ssh-keygen -R "$server_ip" >/dev/null 2>&1 || true
|
|
|
|
|
|
|
|
|
|
# Add current host key
|
|
|
|
|
ssh-keyscan -p "$server_port" "$server_ip" >> ~/.ssh/known_hosts 2>/dev/null || true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parse_json() {
|
|
|
|
|
local json="$1"
|
|
|
|
|
|
|
|
|
|
# Check if jq is available
|
|
|
|
|
if ! command -v jq &> /dev/null; then
|
|
|
|
|
echo "ERROR: jq is required for JSON parsing. Install with: apt install jq"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
SERVER_IP=$(echo "$json" | jq -r '.host // empty')
|
|
|
|
|
SERVER_PORT=$(echo "$json" | jq -r '.port // "22"')
|
|
|
|
|
SERVER_PASSWORD=$(echo "$json" | jq -r '.password // empty')
|
|
|
|
|
SSH_KEY=$(echo "$json" | jq -r '.key // empty')
|
|
|
|
|
ACTION=$(echo "$json" | jq -r '.action // empty')
|
2025-12-08 16:13:48 +01:00
|
|
|
# Handle tools as either array or string
|
|
|
|
|
TOOLS=$(echo "$json" | jq -r 'if .tools | type == "array" then .tools | join(",") elif .tools then .tools else empty end')
|
2025-12-04 01:00:41 +01:00
|
|
|
SKIP_SSL=$(echo "$json" | jq -r 'if .skip_ssl == true then "true" else "" end')
|
2025-12-08 16:13:48 +01:00
|
|
|
ROOT_SSL=$(echo "$json" | jq -r 'if .root_ssl == true then "true" else "" end')
|
2025-12-04 01:00:41 +01:00
|
|
|
CUSTOMER=$(echo "$json" | jq -r '.customer // empty')
|
|
|
|
|
DOMAIN=$(echo "$json" | jq -r '.domain // empty')
|
|
|
|
|
COMPANY_NAME=$(echo "$json" | jq -r '.company_name // empty')
|
2025-12-05 16:48:43 +01:00
|
|
|
DOCKER_USER=$(echo "$json" | jq -r '.docker_user // empty')
|
|
|
|
|
DOCKER_TOKEN=$(echo "$json" | jq -r '.docker_token // empty')
|
2025-12-08 16:13:48 +01:00
|
|
|
DOCKER_REGISTRY=$(echo "$json" | jq -r '.docker_registry // empty')
|
2025-12-08 21:20:27 +01:00
|
|
|
GITEA_REGISTRY=$(echo "$json" | jq -r '.gitea_registry // empty')
|
|
|
|
|
GITEA_USER=$(echo "$json" | jq -r '.gitea_user // empty')
|
|
|
|
|
GITEA_TOKEN=$(echo "$json" | jq -r '.gitea_token // empty')
|
2025-12-07 12:28:08 +01:00
|
|
|
|
|
|
|
|
# Registration token (can also be set via environment variable)
|
|
|
|
|
local json_token=$(echo "$json" | jq -r '.registration_token // empty')
|
2025-12-08 16:31:25 +01:00
|
|
|
[[ -n "$json_token" ]] && SYSADMIN_REGISTRATION_TOKEN="$json_token" || true
|
2025-12-04 01:00:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# =============================================================================
|
|
|
|
|
# ARGUMENT PARSING
|
|
|
|
|
# =============================================================================
|
|
|
|
|
|
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
|
|
case $1 in
|
|
|
|
|
--host)
|
|
|
|
|
SERVER_IP="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--port)
|
|
|
|
|
SERVER_PORT="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--password)
|
|
|
|
|
SERVER_PASSWORD="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--key)
|
|
|
|
|
SSH_KEY="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--action)
|
|
|
|
|
ACTION="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--tools)
|
|
|
|
|
TOOLS="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--skip-ssl)
|
|
|
|
|
SKIP_SSL="true"
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--root-ssl)
|
|
|
|
|
ROOT_SSL="true"
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--customer)
|
|
|
|
|
CUSTOMER="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--domain)
|
|
|
|
|
DOMAIN="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--company)
|
|
|
|
|
COMPANY_NAME="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
2025-12-05 16:48:43 +01:00
|
|
|
--docker-user)
|
|
|
|
|
DOCKER_USER="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--docker-token)
|
|
|
|
|
DOCKER_TOKEN="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
2025-12-04 01:00:41 +01:00
|
|
|
--config)
|
|
|
|
|
CONFIG_JSON=$(cat "$2")
|
|
|
|
|
parse_json "$CONFIG_JSON"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--json)
|
|
|
|
|
parse_json "$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--help|-h)
|
|
|
|
|
usage
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "Unknown option: $1"
|
|
|
|
|
usage
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# =============================================================================
|
|
|
|
|
# VALIDATION
|
|
|
|
|
# =============================================================================
|
|
|
|
|
|
|
|
|
|
if [[ -z "$SERVER_IP" ]]; then
|
|
|
|
|
echo "ERROR: --host is required"
|
|
|
|
|
usage
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ -z "$ACTION" ]]; then
|
|
|
|
|
echo "ERROR: --action is required (setup or connect)"
|
|
|
|
|
usage
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ "$ACTION" != "setup" && "$ACTION" != "connect" ]]; then
|
|
|
|
|
echo "ERROR: --action must be 'setup' or 'connect'"
|
|
|
|
|
usage
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# =============================================================================
|
|
|
|
|
# SSH COMMAND BUILDERS
|
|
|
|
|
# =============================================================================
|
|
|
|
|
|
|
|
|
|
# SSH options for reliable connections with keep-alive
|
|
|
|
|
SSH_OPTS="-o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=~/.ssh/known_hosts -o ConnectTimeout=30 -o ServerAliveInterval=15 -o ServerAliveCountMax=3"
|
|
|
|
|
|
|
|
|
|
# Build SSH/SCP commands based on auth method
|
|
|
|
|
if [[ -n "$SERVER_PASSWORD" ]]; then
|
|
|
|
|
# Password-based authentication (for initial root setup)
|
|
|
|
|
if ! command -v sshpass &> /dev/null; then
|
|
|
|
|
echo "ERROR: sshpass is required for password auth. Install with: apt install sshpass"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
SSH_CMD="sshpass -p '$SERVER_PASSWORD' ssh $SSH_OPTS -p $SERVER_PORT root@$SERVER_IP"
|
|
|
|
|
SCP_CMD="sshpass -p '$SERVER_PASSWORD' scp $SSH_OPTS -P $SERVER_PORT"
|
|
|
|
|
SSH_USER="root"
|
|
|
|
|
elif [[ -n "$SSH_KEY" ]]; then
|
|
|
|
|
# Key-based authentication (for stefan user)
|
|
|
|
|
if [[ ! -f "$SSH_KEY" ]]; then
|
|
|
|
|
echo "ERROR: SSH key file not found: $SSH_KEY"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
SSH_CMD="ssh $SSH_OPTS -i $SSH_KEY -p $SERVER_PORT stefan@$SERVER_IP"
|
|
|
|
|
SCP_CMD="scp $SSH_OPTS -i $SSH_KEY -P $SERVER_PORT"
|
|
|
|
|
SSH_USER="stefan"
|
|
|
|
|
else
|
|
|
|
|
echo "ERROR: Either --password or --key is required"
|
|
|
|
|
usage
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# =============================================================================
|
|
|
|
|
# MAIN EXECUTION
|
|
|
|
|
# =============================================================================
|
|
|
|
|
|
|
|
|
|
echo "=== LetsBe Deployment ==="
|
|
|
|
|
echo "Server: $SERVER_IP:$SERVER_PORT"
|
|
|
|
|
echo "Action: $ACTION"
|
|
|
|
|
echo "Auth: ${SSH_USER:-unknown}"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
# Update SSH known hosts
|
|
|
|
|
check_and_replace_ssh_key "$SERVER_IP" "$SERVER_PORT"
|
|
|
|
|
|
|
|
|
|
if [[ "$ACTION" == "setup" ]]; then
|
|
|
|
|
# =========================================================================
|
|
|
|
|
# SETUP MODE
|
|
|
|
|
# =========================================================================
|
|
|
|
|
|
|
|
|
|
if [[ "$SSH_USER" != "root" ]]; then
|
|
|
|
|
echo "WARNING: Setup typically requires root access for initial deployment."
|
|
|
|
|
echo "Proceeding with $SSH_USER user..."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
REMOTE_BASE="/opt/letsbe"
|
|
|
|
|
|
|
|
|
|
echo "[0/6] Creating remote directory structure..."
|
|
|
|
|
eval "$SSH_CMD 'mkdir -p ${REMOTE_BASE}/{scripts,env,stacks,nginx,config,data}'"
|
|
|
|
|
|
|
|
|
|
echo "[1/6] Uploading setup scripts..."
|
|
|
|
|
eval "$SCP_CMD env_setup.sh ${SSH_USER}@${SERVER_IP}:${REMOTE_BASE}/scripts/" 2>/dev/null || \
|
|
|
|
|
eval "$SCP_CMD env_setup.sh ${SSH_USER}@${SERVER_IP}:/tmp/"
|
|
|
|
|
|
|
|
|
|
eval "$SCP_CMD setup.sh ${SSH_USER}@${SERVER_IP}:${REMOTE_BASE}/scripts/" 2>/dev/null || \
|
|
|
|
|
eval "$SCP_CMD setup.sh ${SSH_USER}@${SERVER_IP}:/tmp/"
|
|
|
|
|
|
2025-12-05 16:48:43 +01:00
|
|
|
echo " Converting line endings to Unix format..."
|
|
|
|
|
eval "$SSH_CMD 'sed -i \"s/\r\$//\" ${REMOTE_BASE}/scripts/env_setup.sh ${REMOTE_BASE}/scripts/setup.sh 2>/dev/null || true'"
|
|
|
|
|
|
2025-12-04 01:00:41 +01:00
|
|
|
echo "[2/6] Uploading backups script..."
|
|
|
|
|
if ! eval "$SSH_CMD '[ -f ${REMOTE_BASE}/scripts/backups.sh ]'" 2>/dev/null; then
|
|
|
|
|
eval "$SCP_CMD backups.sh ${SSH_USER}@${SERVER_IP}:${REMOTE_BASE}/scripts/" 2>/dev/null || \
|
|
|
|
|
eval "$SCP_CMD backups.sh ${SSH_USER}@${SERVER_IP}:/tmp/"
|
2025-12-05 16:48:43 +01:00
|
|
|
|
|
|
|
|
echo " Converting line endings to Unix format..."
|
|
|
|
|
eval "$SSH_CMD 'sed -i \"s/\r\$//\" ${REMOTE_BASE}/scripts/backups.sh 2>/dev/null || true'"
|
2025-12-04 01:00:41 +01:00
|
|
|
else
|
|
|
|
|
echo " backups.sh already exists, skipping."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "[3/6] Uploading nginx configurations..."
|
|
|
|
|
# Check if nginx folder has .conf files (not just exists as empty dir)
|
|
|
|
|
if ! eval "$SSH_CMD 'ls ${REMOTE_BASE}/nginx/*.conf >/dev/null 2>&1'" 2>/dev/null; then
|
|
|
|
|
eval "$SCP_CMD -r nginx/* ${SSH_USER}@${SERVER_IP}:${REMOTE_BASE}/nginx/" 2>/dev/null || \
|
|
|
|
|
eval "$SCP_CMD -r nginx ${SSH_USER}@${SERVER_IP}:/tmp/"
|
|
|
|
|
else
|
|
|
|
|
echo " nginx configs already exist, skipping."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "[4/6] Uploading docker stacks..."
|
|
|
|
|
# Check if stacks folder has docker-compose files (not just exists as empty dir)
|
|
|
|
|
if ! eval "$SSH_CMD 'ls ${REMOTE_BASE}/stacks/*/docker-compose.yml >/dev/null 2>&1'" 2>/dev/null; then
|
|
|
|
|
eval "$SCP_CMD -r stacks/* ${SSH_USER}@${SERVER_IP}:${REMOTE_BASE}/stacks/" 2>/dev/null || \
|
|
|
|
|
eval "$SCP_CMD -r stacks ${SSH_USER}@${SERVER_IP}:/tmp/"
|
|
|
|
|
else
|
|
|
|
|
echo " stacks already exist, skipping."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "[5/6] Running env_setup.sh..."
|
|
|
|
|
if ! eval "$SSH_CMD '[ -f ${REMOTE_BASE}/.env_installed ]'" 2>/dev/null; then
|
|
|
|
|
# Build env_setup.sh arguments (escape values for nested shell)
|
|
|
|
|
ENV_ARGS=""
|
|
|
|
|
[[ -n "$CUSTOMER" ]] && ENV_ARGS="$ENV_ARGS --customer $(printf '%q' "$CUSTOMER")"
|
|
|
|
|
[[ -n "$DOMAIN" ]] && ENV_ARGS="$ENV_ARGS --domain $(printf '%q' "$DOMAIN")"
|
|
|
|
|
[[ -n "$COMPANY_NAME" ]] && ENV_ARGS="$ENV_ARGS --company $(printf '%q' "$COMPANY_NAME")"
|
2025-12-05 16:48:43 +01:00
|
|
|
[[ -n "$DOCKER_USER" ]] && ENV_ARGS="$ENV_ARGS --docker-user $(printf '%q' "$DOCKER_USER")"
|
2025-12-04 01:00:41 +01:00
|
|
|
|
2025-12-07 12:26:44 +01:00
|
|
|
# Build environment variables to pass to remote script
|
|
|
|
|
ENV_VARS=""
|
|
|
|
|
[[ -n "$SYSADMIN_REGISTRATION_TOKEN" ]] && ENV_VARS="SYSADMIN_REGISTRATION_TOKEN=$(printf '%q' "$SYSADMIN_REGISTRATION_TOKEN")"
|
|
|
|
|
|
2025-12-04 01:00:41 +01:00
|
|
|
if [[ -n "$ENV_ARGS" ]]; then
|
2025-12-07 12:26:44 +01:00
|
|
|
eval "$SSH_CMD \"$ENV_VARS bash ${REMOTE_BASE}/scripts/env_setup.sh $ENV_ARGS && touch ${REMOTE_BASE}/.env_installed\"" || \
|
|
|
|
|
eval "$SSH_CMD \"$ENV_VARS bash /tmp/env_setup.sh $ENV_ARGS && touch /tmp/.env_installed\""
|
2025-12-04 01:00:41 +01:00
|
|
|
else
|
|
|
|
|
echo " WARNING: No customer/domain/company provided. Skipping env_setup.sh"
|
|
|
|
|
echo " Run manually: env_setup.sh --customer X --domain Y --company Z"
|
|
|
|
|
fi
|
|
|
|
|
else
|
|
|
|
|
echo " env_setup.sh already ran, skipping."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Create initial backup before setup
|
|
|
|
|
if ! eval "$SSH_CMD '[ -f ${REMOTE_BASE}/initial_setup_backup.zip ]'" 2>/dev/null; then
|
|
|
|
|
echo " Creating initial setup backup..."
|
|
|
|
|
eval "$SSH_CMD 'apt-get update && apt-get install -y zip && cd ${REMOTE_BASE} && zip -r initial_setup_backup.zip stacks/* nginx/* scripts/backups.sh 2>/dev/null || true'"
|
|
|
|
|
eval "$SCP_CMD ${SSH_USER}@${SERVER_IP}:${REMOTE_BASE}/initial_setup_backup.zip ." 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "[6/6] Running setup.sh..."
|
|
|
|
|
if ! eval "$SSH_CMD '[ -f ${REMOTE_BASE}/.setup_installed ]'" 2>/dev/null; then
|
|
|
|
|
# Build setup.sh arguments
|
|
|
|
|
SETUP_ARGS=""
|
2025-12-05 16:48:43 +01:00
|
|
|
[[ -n "$TOOLS" ]] && SETUP_ARGS="$SETUP_ARGS --tools $(printf '%q' "$TOOLS")"
|
|
|
|
|
[[ -n "$DOMAIN" ]] && SETUP_ARGS="$SETUP_ARGS --domain $(printf '%q' "$DOMAIN")"
|
2025-12-04 01:00:41 +01:00
|
|
|
[[ "$SKIP_SSL" == "true" ]] && SETUP_ARGS="$SETUP_ARGS --skip-ssl"
|
|
|
|
|
[[ "$ROOT_SSL" == "true" ]] && SETUP_ARGS="$SETUP_ARGS --root-ssl"
|
2025-12-05 16:48:43 +01:00
|
|
|
[[ -n "$DOCKER_USER" ]] && SETUP_ARGS="$SETUP_ARGS --docker-user $(printf '%q' "$DOCKER_USER")"
|
|
|
|
|
[[ -n "$DOCKER_TOKEN" ]] && SETUP_ARGS="$SETUP_ARGS --docker-token $(printf '%q' "$DOCKER_TOKEN")"
|
2025-12-08 16:13:48 +01:00
|
|
|
[[ -n "$DOCKER_REGISTRY" ]] && SETUP_ARGS="$SETUP_ARGS --docker-registry $(printf '%q' "$DOCKER_REGISTRY")"
|
2025-12-08 21:20:27 +01:00
|
|
|
[[ -n "$GITEA_REGISTRY" ]] && SETUP_ARGS="$SETUP_ARGS --gitea-registry $(printf '%q' "$GITEA_REGISTRY")"
|
|
|
|
|
[[ -n "$GITEA_USER" ]] && SETUP_ARGS="$SETUP_ARGS --gitea-user $(printf '%q' "$GITEA_USER")"
|
|
|
|
|
[[ -n "$GITEA_TOKEN" ]] && SETUP_ARGS="$SETUP_ARGS --gitea-token $(printf '%q' "$GITEA_TOKEN")"
|
2025-12-04 01:00:41 +01:00
|
|
|
|
|
|
|
|
# Run setup.sh directly in foreground (connection stays alive with PermitRootLogin yes)
|
|
|
|
|
echo "Running setup.sh (this may take 10-15 minutes)..."
|
|
|
|
|
eval "$SSH_CMD 'bash ${REMOTE_BASE}/scripts/setup.sh $SETUP_ARGS && touch ${REMOTE_BASE}/.setup_installed'"
|
|
|
|
|
echo "Setup completed successfully!"
|
|
|
|
|
else
|
|
|
|
|
echo " setup.sh already ran, skipping."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo "=============================================="
|
|
|
|
|
echo " Setup Complete!"
|
|
|
|
|
echo "=============================================="
|
|
|
|
|
echo ""
|
|
|
|
|
echo "SSH is now on port 22022 with key-only auth."
|
|
|
|
|
echo "To connect: $0 --host $SERVER_IP --key ./id_ed25519 --port 22022 --action connect"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
elif [[ "$ACTION" == "connect" ]]; then
|
|
|
|
|
# =========================================================================
|
|
|
|
|
# CONNECT MODE
|
|
|
|
|
# =========================================================================
|
|
|
|
|
|
|
|
|
|
echo "Connecting to server..."
|
|
|
|
|
echo "(Disconnect with Ctrl+C or 'exit')"
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
# Try password auth first, then key auth
|
|
|
|
|
if [[ -n "$SERVER_PASSWORD" ]]; then
|
|
|
|
|
eval "$SSH_CMD" || {
|
|
|
|
|
echo "Password auth failed. Trying key auth..."
|
|
|
|
|
if [[ -n "$SSH_KEY" ]]; then
|
|
|
|
|
ssh -i "$SSH_KEY" -p "$SERVER_PORT" stefan@"$SERVER_IP"
|
|
|
|
|
else
|
|
|
|
|
echo "No SSH key provided. Connection failed."
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
elif [[ -n "$SSH_KEY" ]]; then
|
|
|
|
|
ssh -i "$SSH_KEY" -p "$SERVER_PORT" stefan@"$SERVER_IP" || {
|
|
|
|
|
echo "Key auth failed. Check SSH configuration."
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
fi
|
|
|
|
|
fi
|