Add K3s dev deployment setup for single-node VPS
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>
This commit is contained in:
235
deploy-k3s-dev/scripts/00-init.sh
Executable file
235
deploy-k3s-dev/scripts/00-init.sh
Executable file
@@ -0,0 +1,235 @@
|
||||
#!/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 ""
|
||||
Reference in New Issue
Block a user