Mirrors the prod deploy-k3s/ setup but runs all services in-cluster on a single node: PostgreSQL (replaces Neon), MinIO S3-compatible storage (replaces B2), Redis, API, worker, and admin. Includes fully automated setup scripts (00-init through 04-verify), server hardening (SSH, fail2ban, ufw), Let's Encrypt TLS via Traefik, network policies, RBAC, and security contexts matching prod. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
236 lines
6.0 KiB
Bash
Executable File
236 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
DEPLOY_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
SECRETS_DIR="${DEPLOY_DIR}/secrets"
|
|
CONFIG_FILE="${DEPLOY_DIR}/config.yaml"
|
|
|
|
log() { printf '[init] %s\n' "$*"; }
|
|
warn() { printf '[init][warn] %s\n' "$*" >&2; }
|
|
die() { printf '[init][error] %s\n' "$*" >&2; exit 1; }
|
|
|
|
# --- Prerequisites ---
|
|
|
|
command -v openssl >/dev/null 2>&1 || die "Missing: openssl"
|
|
command -v python3 >/dev/null 2>&1 || die "Missing: python3"
|
|
|
|
echo ""
|
|
echo "============================================"
|
|
echo " honeyDue Dev Server — Initial Setup"
|
|
echo "============================================"
|
|
echo ""
|
|
echo "This script will:"
|
|
echo " 1. Generate any missing random secrets"
|
|
echo " 2. Ask for anything not already filled in"
|
|
echo " 3. Create config.yaml with everything filled in"
|
|
echo ""
|
|
|
|
mkdir -p "${SECRETS_DIR}"
|
|
|
|
# --- Generate random secrets (skip if already exist) ---
|
|
|
|
generate_if_missing() {
|
|
local file="$1" label="$2" cmd="$3"
|
|
if [[ -f "${file}" && -s "${file}" ]]; then
|
|
log " ${label} — already exists, keeping"
|
|
else
|
|
eval "${cmd}" > "${file}"
|
|
log " ${label} — generated"
|
|
fi
|
|
}
|
|
|
|
log "Checking secrets..."
|
|
generate_if_missing "${SECRETS_DIR}/secret_key.txt" "secrets/secret_key.txt" "openssl rand -base64 48"
|
|
generate_if_missing "${SECRETS_DIR}/postgres_password.txt" "secrets/postgres_password.txt" "openssl rand -base64 24"
|
|
generate_if_missing "${SECRETS_DIR}/minio_root_password.txt" "secrets/minio_root_password.txt" "openssl rand -base64 24"
|
|
generate_if_missing "${SECRETS_DIR}/email_host_password.txt" "secrets/email_host_password.txt" "echo PLACEHOLDER"
|
|
log " secrets/fcm_server_key.txt — skipped (Android not ready)"
|
|
generate_if_missing "${SECRETS_DIR}/apns_auth_key.p8" "secrets/apns_auth_key.p8" "echo ''"
|
|
|
|
REDIS_PW="$(openssl rand -base64 24)"
|
|
log " Redis password — generated"
|
|
|
|
# --- Collect only what's missing ---
|
|
|
|
ask() {
|
|
local var_name="$1" prompt="$2" default="${3:-}"
|
|
local val
|
|
if [[ -n "${default}" ]]; then
|
|
read -rp "${prompt} [${default}]: " val
|
|
val="${val:-${default}}"
|
|
else
|
|
read -rp "${prompt}: " val
|
|
fi
|
|
eval "${var_name}='${val}'"
|
|
}
|
|
|
|
echo ""
|
|
echo "--- Server ---"
|
|
ask SERVER_HOST "Server IP or SSH alias" "honeyDueDevUpdate"
|
|
[[ -n "${SERVER_HOST}" ]] || die "Server host is required"
|
|
ask SERVER_USER "SSH user" "root"
|
|
ask SSH_KEY "SSH key path" "~/.ssh/id_ed25519"
|
|
|
|
echo ""
|
|
echo "--- Container Registry (GHCR) ---"
|
|
ask GHCR_USER "GitHub username" "treytartt"
|
|
[[ -n "${GHCR_USER}" ]] || die "GitHub username is required"
|
|
ask GHCR_TOKEN "GitHub PAT (read:packages, write:packages)" "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"
|
|
[[ -n "${GHCR_TOKEN}" ]] || die "GitHub PAT is required"
|
|
|
|
echo ""
|
|
echo "--- TLS ---"
|
|
ask LE_EMAIL "Let's Encrypt email" "treytartt@fastmail.com"
|
|
|
|
echo ""
|
|
echo "--- Admin Panel ---"
|
|
ask ADMIN_USER "Admin basic auth username" "admin"
|
|
ADMIN_PW="$(openssl rand -base64 16)"
|
|
|
|
# --- Known values from existing Dokku setup ---
|
|
|
|
EMAIL_USER="treytartt@fastmail.com"
|
|
APNS_KEY_ID="9R5Q7ZX874"
|
|
APNS_TEAM_ID="V3PF3M6B6U"
|
|
|
|
log ""
|
|
log "Pre-filled from existing dev server:"
|
|
log " Email user: ${EMAIL_USER}"
|
|
log " APNS Key ID: ${APNS_KEY_ID}"
|
|
log " APNS Team ID: ${APNS_TEAM_ID}"
|
|
|
|
# --- Generate config.yaml ---
|
|
|
|
log "Generating config.yaml..."
|
|
|
|
cat > "${CONFIG_FILE}" <<YAML
|
|
# config.yaml — auto-generated by 00-init.sh
|
|
# This file is gitignored — never commit it with real values.
|
|
|
|
# --- Server ---
|
|
server:
|
|
host: "${SERVER_HOST}"
|
|
user: "${SERVER_USER}"
|
|
ssh_key: "${SSH_KEY}"
|
|
|
|
# --- Domains ---
|
|
domains:
|
|
api: devapi.myhoneydue.com
|
|
admin: devadmin.myhoneydue.com
|
|
base: dev.myhoneydue.com
|
|
|
|
# --- Container Registry (GHCR) ---
|
|
registry:
|
|
server: ghcr.io
|
|
namespace: "${GHCR_USER}"
|
|
username: "${GHCR_USER}"
|
|
token: "${GHCR_TOKEN}"
|
|
|
|
# --- Database (in-cluster PostgreSQL) ---
|
|
database:
|
|
name: honeydue_dev
|
|
user: honeydue
|
|
max_open_conns: 10
|
|
max_idle_conns: 5
|
|
max_lifetime: "600s"
|
|
|
|
# --- Email (Fastmail) ---
|
|
email:
|
|
host: smtp.fastmail.com
|
|
port: 587
|
|
user: "${EMAIL_USER}"
|
|
from: "honeyDue DEV <${EMAIL_USER}>"
|
|
use_tls: true
|
|
|
|
# --- Push Notifications ---
|
|
push:
|
|
apns_key_id: "${APNS_KEY_ID}"
|
|
apns_team_id: "${APNS_TEAM_ID}"
|
|
apns_topic: com.tt.honeyDue
|
|
apns_production: false
|
|
apns_use_sandbox: true
|
|
|
|
# --- Object Storage (in-cluster MinIO) ---
|
|
storage:
|
|
minio_root_user: honeydue
|
|
bucket: honeydue-dev
|
|
max_file_size: 10485760
|
|
allowed_types: "image/jpeg,image/png,image/gif,image/webp,application/pdf"
|
|
|
|
# --- Worker Schedules (UTC hours) ---
|
|
worker:
|
|
task_reminder_hour: 14
|
|
overdue_reminder_hour: 15
|
|
daily_digest_hour: 3
|
|
|
|
# --- Feature Flags ---
|
|
features:
|
|
push_enabled: true
|
|
email_enabled: false
|
|
webhooks_enabled: false
|
|
onboarding_emails_enabled: false
|
|
pdf_reports_enabled: true
|
|
worker_enabled: true
|
|
|
|
# --- Redis ---
|
|
redis:
|
|
password: "${REDIS_PW}"
|
|
|
|
# --- Admin Panel ---
|
|
admin:
|
|
basic_auth_user: "${ADMIN_USER}"
|
|
basic_auth_password: "${ADMIN_PW}"
|
|
|
|
# --- TLS ---
|
|
tls:
|
|
mode: letsencrypt
|
|
letsencrypt_email: "${LE_EMAIL}"
|
|
|
|
# --- Apple Auth / IAP ---
|
|
apple_auth:
|
|
client_id: "com.tt.honeyDue"
|
|
team_id: "${APNS_TEAM_ID}"
|
|
iap_key_id: ""
|
|
iap_issuer_id: ""
|
|
iap_bundle_id: ""
|
|
iap_key_path: ""
|
|
iap_sandbox: true
|
|
|
|
# --- Google Auth / IAP ---
|
|
google_auth:
|
|
client_id: ""
|
|
android_client_id: ""
|
|
ios_client_id: ""
|
|
iap_package_name: ""
|
|
iap_service_account_path: ""
|
|
YAML
|
|
|
|
# --- Summary ---
|
|
|
|
echo ""
|
|
echo "============================================"
|
|
echo " Setup Complete"
|
|
echo "============================================"
|
|
echo ""
|
|
echo "Generated:"
|
|
echo " config.yaml"
|
|
echo " secrets/secret_key.txt"
|
|
echo " secrets/postgres_password.txt"
|
|
echo " secrets/minio_root_password.txt"
|
|
echo " secrets/email_host_password.txt"
|
|
echo " secrets/fcm_server_key.txt"
|
|
echo " secrets/apns_auth_key.p8"
|
|
echo ""
|
|
echo "Admin panel credentials:"
|
|
echo " Username: ${ADMIN_USER}"
|
|
echo " Password: ${ADMIN_PW}"
|
|
echo " (save these — they won't be shown again)"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " ./scripts/01-setup-k3s.sh"
|
|
echo " ./scripts/02-setup-secrets.sh"
|
|
echo " ./scripts/03-deploy.sh"
|
|
echo " ./scripts/04-verify.sh"
|
|
echo ""
|