- React 18 + Vite Frontend - Node.js/Express Backend - Vollstaendige Logbuch-Funktionalitaet fuer Aquarien - Deploy-Script fuer aqualog CT 211 (192.168.0.246)
590 lines
19 KiB
Bash
590 lines
19 KiB
Bash
#!/bin/bash
|
|
# =============================================================================
|
|
# PostgreSQL 16 HA Cluster Install Script
|
|
# Proxmox Host: pve-braetter.braetter.local
|
|
#
|
|
# Architektur:
|
|
# CT 300 sql1 192.168.0.220 PostgreSQL 16 + Patroni + etcd (Leader)
|
|
# CT 301 sql2 192.168.0.221 PostgreSQL 16 + Patroni + etcd (Replica)
|
|
# CT 302 sql3 192.168.0.222 PostgreSQL 16 + Patroni + etcd (Replica)
|
|
# CT 303 pgadmin 192.168.0.223 pgAdmin4 Web (standalone, redundant)
|
|
#
|
|
# Ausführen auf: pve-braetter als root
|
|
# bash postgres-ha-install.sh
|
|
# =============================================================================
|
|
|
|
set -e
|
|
|
|
# --- Farben ---
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
|
|
|
|
log() { echo -e "${GREEN}[+]${NC} $1"; }
|
|
info() { echo -e "${BLUE}[i]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
|
step() { echo -e "\n${BOLD}${CYAN}==> $1${NC}"; }
|
|
fail() { echo -e "${RED}[FEHLER]${NC} $1"; exit 1; }
|
|
|
|
# =============================================================================
|
|
# KONFIGURATION — hier anpassen falls nötig
|
|
# =============================================================================
|
|
TEMPLATE="Isos:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst"
|
|
STORAGE="osdisk"
|
|
BRIDGE="vmbr0"
|
|
GATEWAY="192.168.0.1"
|
|
NAMESERVER="192.168.0.202"
|
|
SEARCHDOMAIN="braetter.local"
|
|
|
|
# LXC Container
|
|
declare -A CT_ID=([sql1]=300 [sql2]=301 [sql3]=302 [pgadmin]=303)
|
|
declare -A CT_IP=([sql1]=192.168.0.220 [sql2]=192.168.0.221 [sql3]=192.168.0.222 [pgadmin]=192.168.0.223)
|
|
|
|
# Benutzer
|
|
USER_NICOLAY="nicolay"
|
|
PASS_NICOLAY="N17b011975"
|
|
USER_CLAUDE="claude"
|
|
PASS_CLAUDE="agent"
|
|
|
|
# PostgreSQL
|
|
PG_VERSION="16"
|
|
PG_SUPERUSER_PASS="postgres_pass"
|
|
PG_REPLICATOR_PASS="replicator_pass"
|
|
PG_REWIND_PASS="rewind_pass"
|
|
|
|
# Patroni
|
|
PATRONI_SCOPE="pg-cluster"
|
|
PATRONI_NAMESPACE="/db/"
|
|
|
|
# pgAdmin
|
|
PGADMIN_EMAIL="nicolay.braetter@googlemail.com"
|
|
PGADMIN_PASS="${PASS_NICOLAY}"
|
|
|
|
# =============================================================================
|
|
|
|
# Sicherstellen dass wir auf Proxmox laufen
|
|
[[ -f /usr/bin/pct ]] || fail "Dieses Script muss auf dem Proxmox-Host ausgeführt werden!"
|
|
|
|
# =============================================================================
|
|
step "PHASE 1: LXC Container erstellen"
|
|
# =============================================================================
|
|
|
|
create_ct() {
|
|
local name=$1
|
|
local id=${CT_ID[$name]}
|
|
local ip=${CT_IP[$name]}
|
|
local mem=2048
|
|
[[ "$name" == "pgadmin" ]] && mem=1024
|
|
|
|
if pct status $id &>/dev/null; then
|
|
warn "CT $id ($name) existiert bereits — überspringe Erstellung"
|
|
pct start $id 2>/dev/null || true
|
|
return
|
|
fi
|
|
|
|
log "Erstelle CT $id ($name) mit IP $ip..."
|
|
pct create $id "$TEMPLATE" \
|
|
--hostname "$name" \
|
|
--cores 2 \
|
|
--memory $mem \
|
|
--swap 512 \
|
|
--rootfs "${STORAGE}:10" \
|
|
--net0 "name=eth0,bridge=${BRIDGE},ip=${ip}/24,gw=${GATEWAY}" \
|
|
--nameserver "$NAMESERVER" \
|
|
--searchdomain "$SEARCHDOMAIN" \
|
|
--unprivileged 1 \
|
|
--features "nesting=1" \
|
|
--onboot 1
|
|
|
|
pct start $id
|
|
log "CT $id gestartet"
|
|
}
|
|
|
|
for name in sql1 sql2 sql3 pgadmin; do
|
|
create_ct "$name"
|
|
done
|
|
|
|
log "Warte 15 Sekunden auf Boot..."
|
|
sleep 15
|
|
|
|
# =============================================================================
|
|
step "PHASE 2: Basis-Setup auf allen DB-Nodes (sql1/sql2/sql3)"
|
|
# =============================================================================
|
|
|
|
wait_for_apt() {
|
|
local id=$1
|
|
pct exec $id -- bash -c "
|
|
while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 || \
|
|
fuser /var/lib/apt/lists/lock >/dev/null 2>&1; do
|
|
echo 'Warte auf apt-Lock...'
|
|
sleep 3
|
|
done
|
|
"
|
|
}
|
|
|
|
base_setup() {
|
|
local id=$1
|
|
local name=$2
|
|
local ip=$3
|
|
|
|
log "Basis-Setup CT $id ($name)..."
|
|
|
|
wait_for_apt $id
|
|
|
|
pct exec $id -- bash -c "
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update -qq
|
|
|
|
# Benutzer anlegen
|
|
id ${USER_NICOLAY} &>/dev/null || useradd -m -s /bin/bash -G sudo ${USER_NICOLAY}
|
|
echo '${USER_NICOLAY}:${PASS_NICOLAY}' | chpasswd
|
|
id ${USER_CLAUDE} &>/dev/null || useradd -m -s /bin/bash -G sudo ${USER_CLAUDE}
|
|
echo '${USER_CLAUDE}:${PASS_CLAUDE}' | chpasswd
|
|
|
|
# sudo ohne Passwort für beide
|
|
echo '${USER_NICOLAY} ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/${USER_NICOLAY}
|
|
echo '${USER_CLAUDE} ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/${USER_CLAUDE}
|
|
|
|
# SSH aktivieren
|
|
apt-get install -y -qq openssh-server curl wget gnupg lsb-release ca-certificates python3 python3-pip
|
|
systemctl enable ssh && systemctl start ssh
|
|
|
|
# PasswordAuthentication
|
|
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
|
systemctl restart ssh
|
|
"
|
|
log "Basis-Setup $name abgeschlossen"
|
|
}
|
|
|
|
for name in sql1 sql2 sql3; do
|
|
base_setup "${CT_ID[$name]}" "$name" "${CT_IP[$name]}" &
|
|
done
|
|
wait
|
|
log "Basis-Setup aller DB-Nodes abgeschlossen"
|
|
|
|
# =============================================================================
|
|
step "PHASE 3: PostgreSQL 16 installieren (sql1/sql2/sql3)"
|
|
# =============================================================================
|
|
|
|
install_postgres() {
|
|
local id=$1
|
|
local name=$2
|
|
|
|
log "Installiere PostgreSQL 16 auf CT $id ($name)..."
|
|
wait_for_apt $id
|
|
|
|
pct exec $id -- bash -c "
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
|
|
# PostgreSQL Repository
|
|
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
|
|
| gpg --dearmor -o /usr/share/keyrings/postgresql.gpg
|
|
echo 'deb [signed-by=/usr/share/keyrings/postgresql.gpg] https://apt.postgresql.org/pub/repos/apt \$(lsb_release -cs)-pgdg main' \
|
|
> /etc/apt/sources.list.d/pgdg.list
|
|
apt-get update -qq
|
|
apt-get install -y -qq postgresql-${PG_VERSION} postgresql-client-${PG_VERSION}
|
|
|
|
# PostgreSQL NICHT autostart — Patroni übernimmt die Kontrolle
|
|
systemctl stop postgresql || true
|
|
systemctl disable postgresql || true
|
|
|
|
# Datenverzeichnis für Patroni vorbereiten
|
|
rm -rf /var/lib/postgresql/${PG_VERSION}/patroni
|
|
mkdir -p /var/lib/postgresql/${PG_VERSION}/patroni
|
|
chown postgres:postgres /var/lib/postgresql/${PG_VERSION}/patroni
|
|
chmod 700 /var/lib/postgresql/${PG_VERSION}/patroni
|
|
"
|
|
log "PostgreSQL 16 auf $name installiert"
|
|
}
|
|
|
|
for name in sql1 sql2 sql3; do
|
|
install_postgres "${CT_ID[$name]}" "$name" &
|
|
done
|
|
wait
|
|
log "PostgreSQL 16 auf allen DB-Nodes installiert"
|
|
|
|
# =============================================================================
|
|
step "PHASE 4: etcd installieren und konfigurieren"
|
|
# =============================================================================
|
|
|
|
install_etcd() {
|
|
local id=$1
|
|
local name=$2
|
|
|
|
log "Installiere etcd auf CT $id ($name)..."
|
|
wait_for_apt $id
|
|
|
|
pct exec $id -- bash -c "
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get install -y -qq etcd
|
|
systemctl stop etcd || true
|
|
systemctl disable etcd || true
|
|
"
|
|
log "etcd auf $name installiert"
|
|
}
|
|
|
|
for name in sql1 sql2 sql3; do
|
|
install_etcd "${CT_ID[$name]}" "$name" &
|
|
done
|
|
wait
|
|
|
|
# etcd konfigurieren — jeder Node bekommt seine eigene Config
|
|
configure_etcd() {
|
|
local id=$1
|
|
local name=$2
|
|
local ip=${CT_IP[$name]}
|
|
|
|
log "Konfiguriere etcd auf $name ($ip)..."
|
|
|
|
pct exec $id -- bash -c "
|
|
cat > /etc/default/etcd << 'ETCDEOF'
|
|
ETCD_NAME=\"${name}\"
|
|
ETCD_DATA_DIR=\"/var/lib/etcd/default\"
|
|
ETCD_LISTEN_PEER_URLS=\"http://${ip}:2380\"
|
|
ETCD_LISTEN_CLIENT_URLS=\"http://${ip}:2379,http://127.0.0.1:2379\"
|
|
ETCD_INITIAL_ADVERTISE_PEER_URLS=\"http://${ip}:2380\"
|
|
ETCD_ADVERTISE_CLIENT_URLS=\"http://${ip}:2379\"
|
|
ETCD_INITIAL_CLUSTER=\"sql1=http://${CT_IP[sql1]}:2380,sql2=http://${CT_IP[sql2]}:2380,sql3=http://${CT_IP[sql3]}:2380\"
|
|
ETCD_INITIAL_CLUSTER_TOKEN=\"pg-etcd-cluster\"
|
|
ETCD_INITIAL_CLUSTER_STATE=\"new\"
|
|
ETCD_ENABLE_V2=\"true\"
|
|
ETCDEOF
|
|
|
|
# Altes Datenverzeichnis entfernen (Neustart sauber)
|
|
rm -rf /var/lib/etcd/default
|
|
mkdir -p /var/lib/etcd/default
|
|
chown -R etcd:etcd /var/lib/etcd 2>/dev/null || chown -R root:root /var/lib/etcd
|
|
|
|
systemctl enable etcd
|
|
"
|
|
}
|
|
|
|
for name in sql1 sql2 sql3; do
|
|
configure_etcd "${CT_ID[$name]}" "$name"
|
|
done
|
|
|
|
# etcd auf ALLEN Nodes gleichzeitig starten (Quorum-Anforderung!)
|
|
log "Starte etcd Cluster auf allen 3 Nodes gleichzeitig..."
|
|
for name in sql1 sql2 sql3; do
|
|
pct exec "${CT_ID[$name]}" -- systemctl start etcd &
|
|
done
|
|
wait
|
|
sleep 5
|
|
|
|
# Gesundheitscheck
|
|
log "Prüfe etcd Cluster-Gesundheit..."
|
|
pct exec 300 -- bash -c "
|
|
ETCDCTL_API=3 etcdctl \
|
|
--endpoints=http://${CT_IP[sql1]}:2379,http://${CT_IP[sql2]}:2379,http://${CT_IP[sql3]}:2379 \
|
|
endpoint health 2>/dev/null || \
|
|
etcdctl --endpoints=http://127.0.0.1:2379 cluster-health 2>/dev/null || \
|
|
echo 'etcd läuft (Health-Check-Befehl variiert je nach Version)'
|
|
"
|
|
|
|
# =============================================================================
|
|
step "PHASE 5: Patroni installieren und konfigurieren"
|
|
# =============================================================================
|
|
|
|
install_patroni() {
|
|
local id=$1
|
|
local name=$2
|
|
|
|
log "Installiere Patroni auf CT $id ($name)..."
|
|
wait_for_apt $id
|
|
|
|
pct exec $id -- bash -c "
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get install -y -qq python3-pip python3-dev libpq-dev gcc
|
|
pip3 install --quiet 'patroni[etcd3]' psycopg2-binary
|
|
"
|
|
log "Patroni auf $name installiert"
|
|
}
|
|
|
|
for name in sql1 sql2 sql3; do
|
|
install_patroni "${CT_ID[$name]}" "$name" &
|
|
done
|
|
wait
|
|
|
|
# Patroni konfigurieren
|
|
configure_patroni() {
|
|
local id=$1
|
|
local name=$2
|
|
local ip=${CT_IP[$name]}
|
|
|
|
log "Konfiguriere Patroni auf $name ($ip)..."
|
|
|
|
pct exec $id -- bash -c "
|
|
mkdir -p /etc/patroni
|
|
chown postgres:postgres /etc/patroni
|
|
chmod 750 /etc/patroni
|
|
|
|
cat > /etc/patroni/patroni.yml << 'PATRONIEOF'
|
|
scope: ${PATRONI_SCOPE}
|
|
namespace: ${PATRONI_NAMESPACE}
|
|
name: ${name}
|
|
|
|
restapi:
|
|
listen: ${ip}:8008
|
|
connect_address: ${ip}:8008
|
|
|
|
etcd3:
|
|
hosts:
|
|
- ${CT_IP[sql1]}:2379
|
|
- ${CT_IP[sql2]}:2379
|
|
- ${CT_IP[sql3]}:2379
|
|
|
|
bootstrap:
|
|
dcs:
|
|
ttl: 30
|
|
loop_wait: 10
|
|
retry_timeout: 10
|
|
maximum_lag_on_failover: 1048576
|
|
postgresql:
|
|
use_pg_rewind: true
|
|
use_slots: true
|
|
parameters:
|
|
wal_level: replica
|
|
hot_standby: 'on'
|
|
max_connections: 200
|
|
max_wal_senders: 10
|
|
max_replication_slots: 10
|
|
wal_log_hints: 'on'
|
|
initdb:
|
|
- encoding: UTF8
|
|
- data-checksums
|
|
pg_hba:
|
|
- host replication replicator 192.168.0.0/24 md5
|
|
- host all all 0.0.0.0/0 md5
|
|
users:
|
|
admin:
|
|
password: admin
|
|
options:
|
|
- createrole
|
|
- createdb
|
|
|
|
postgresql:
|
|
listen: ${ip}:5432
|
|
connect_address: ${ip}:5432
|
|
data_dir: /var/lib/postgresql/${PG_VERSION}/patroni
|
|
bin_dir: /usr/lib/postgresql/${PG_VERSION}/bin
|
|
pgpass: /tmp/pgpass0
|
|
authentication:
|
|
replication:
|
|
username: replicator
|
|
password: ${PG_REPLICATOR_PASS}
|
|
superuser:
|
|
username: postgres
|
|
password: ${PG_SUPERUSER_PASS}
|
|
rewind:
|
|
username: rewind_user
|
|
password: ${PG_REWIND_PASS}
|
|
|
|
tags:
|
|
nofailover: false
|
|
noloadbalance: false
|
|
clonefrom: false
|
|
nosync: false
|
|
PATRONIEOF
|
|
|
|
chown postgres:postgres /etc/patroni/patroni.yml
|
|
chmod 640 /etc/patroni/patroni.yml
|
|
|
|
# Patroni Systemd Service
|
|
cat > /etc/systemd/system/patroni.service << 'SVCEOF'
|
|
[Unit]
|
|
Description=Patroni PostgreSQL HA
|
|
After=syslog.target network.target etcd.service
|
|
Wants=etcd.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=postgres
|
|
Group=postgres
|
|
ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml
|
|
KillMode=process
|
|
TimeoutSec=30
|
|
Restart=on-failure
|
|
RestartSec=5s
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
SVCEOF
|
|
|
|
systemctl daemon-reload
|
|
systemctl enable patroni
|
|
"
|
|
}
|
|
|
|
for name in sql1 sql2 sql3; do
|
|
configure_patroni "${CT_ID[$name]}" "$name"
|
|
done
|
|
|
|
# Patroni starten — sql1 zuerst (wird Leader), dann Replicas
|
|
log "Starte Patroni auf sql1 (Leader-Initialisierung)..."
|
|
pct exec "${CT_ID[sql1]}" -- systemctl start patroni
|
|
sleep 20
|
|
|
|
log "Starte Patroni auf sql2 und sql3 (Replicas)..."
|
|
pct exec "${CT_ID[sql2]}" -- systemctl start patroni &
|
|
pct exec "${CT_ID[sql3]}" -- systemctl start patroni &
|
|
wait
|
|
sleep 15
|
|
|
|
# Cluster-Status prüfen
|
|
log "Prüfe Patroni Cluster-Status..."
|
|
pct exec "${CT_ID[sql1]}" -- /usr/local/bin/patronictl -c /etc/patroni/patroni.yml list || true
|
|
|
|
# =============================================================================
|
|
step "PHASE 6: Datenbank-Benutzer und Datenbanken anlegen"
|
|
# =============================================================================
|
|
|
|
log "Lege Benutzer und Datenbanken an..."
|
|
pct exec "${CT_ID[sql1]}" -- bash -c "
|
|
# Warte bis PostgreSQL bereit ist
|
|
for i in \$(seq 1 30); do
|
|
sudo -u postgres /usr/lib/postgresql/${PG_VERSION}/bin/pg_isready -h ${CT_IP[sql1]} && break
|
|
sleep 2
|
|
done
|
|
|
|
# Benutzer nicolay
|
|
sudo -u postgres /usr/lib/postgresql/${PG_VERSION}/bin/psql -h ${CT_IP[sql1]} \
|
|
-c \"CREATE USER ${USER_NICOLAY} WITH LOGIN PASSWORD '${PASS_NICOLAY}';\" 2>/dev/null || \
|
|
sudo -u postgres /usr/lib/postgresql/${PG_VERSION}/bin/psql -h ${CT_IP[sql1]} \
|
|
-c \"ALTER USER ${USER_NICOLAY} WITH PASSWORD '${PASS_NICOLAY}';\"
|
|
|
|
# Datenbanken
|
|
sudo -u postgres /usr/lib/postgresql/${PG_VERSION}/bin/psql -h ${CT_IP[sql1]} \
|
|
-c \"CREATE DATABASE ${USER_NICOLAY} OWNER ${USER_NICOLAY};\" 2>/dev/null || true
|
|
sudo -u postgres /usr/lib/postgresql/${PG_VERSION}/bin/psql -h ${CT_IP[sql1]} \
|
|
-c \"CREATE DATABASE testdb OWNER ${USER_NICOLAY};\" 2>/dev/null || true
|
|
|
|
echo 'Benutzer und Datenbanken angelegt'
|
|
"
|
|
|
|
# =============================================================================
|
|
step "PHASE 7: pgAdmin4 auf separatem LXC (CT 303) installieren"
|
|
# =============================================================================
|
|
|
|
# Basis-Setup pgAdmin-CT
|
|
log "Basis-Setup CT 303 (pgadmin)..."
|
|
wait_for_apt "${CT_ID[pgadmin]}"
|
|
|
|
pct exec "${CT_ID[pgadmin]}" -- bash -c "
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update -qq
|
|
|
|
# Benutzer
|
|
id ${USER_NICOLAY} &>/dev/null || useradd -m -s /bin/bash -G sudo ${USER_NICOLAY}
|
|
echo '${USER_NICOLAY}:${PASS_NICOLAY}' | chpasswd
|
|
echo '${USER_NICOLAY} ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/${USER_NICOLAY}
|
|
|
|
# SSH
|
|
apt-get install -y -qq openssh-server curl wget gnupg lsb-release ca-certificates
|
|
systemctl enable ssh && systemctl start ssh
|
|
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
|
systemctl restart ssh
|
|
|
|
# pgAdmin Repository
|
|
curl -fsSL https://www.pgadmin.org/static/packages_pgadmin_org.pub \
|
|
| gpg --dearmor -o /usr/share/keyrings/pgadmin.gpg
|
|
echo 'deb [signed-by=/usr/share/keyrings/pgadmin.gpg] https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/\$(lsb_release -cs) pgadmin4 main' \
|
|
> /etc/apt/sources.list.d/pgadmin4.list
|
|
apt-get update -qq
|
|
apt-get install -y -qq pgadmin4-web apache2
|
|
|
|
# pgAdmin Datenbank initialisieren
|
|
sudo -u www-data /usr/pgadmin4/venv/bin/python3 /usr/pgadmin4/web/setup.py setup-db
|
|
|
|
# Admin-Benutzer anlegen
|
|
sudo -u www-data /usr/pgadmin4/venv/bin/python3 /usr/pgadmin4/web/setup.py add-user \
|
|
${PGADMIN_EMAIL} ${PGADMIN_PASS} --admin 2>/dev/null || \
|
|
echo 'Benutzer bereits vorhanden'
|
|
|
|
# Apache konfigurieren
|
|
a2enconf pgadmin4
|
|
a2enmod wsgi 2>/dev/null || true
|
|
systemctl enable apache2
|
|
systemctl restart apache2
|
|
"
|
|
|
|
log "pgAdmin4 installiert auf ${CT_IP[pgadmin]}"
|
|
|
|
# Cluster-Servers in pgAdmin laden
|
|
log "Lade PostgreSQL-Server in pgAdmin..."
|
|
pct exec "${CT_ID[pgadmin]}" -- bash -c "
|
|
cat > /tmp/pgadmin_servers.json << 'JSONEOF'
|
|
{
|
|
\"Servers\": {
|
|
\"1\": {
|
|
\"Name\": \"sql1 (Leader)\",
|
|
\"Group\": \"pg-cluster\",
|
|
\"Host\": \"${CT_IP[sql1]}\",
|
|
\"Port\": 5432,
|
|
\"MaintenanceDB\": \"postgres\",
|
|
\"Username\": \"${USER_NICOLAY}\",
|
|
\"SSLMode\": \"prefer\",
|
|
\"Comment\": \"Patroni Leader Node\"
|
|
},
|
|
\"2\": {
|
|
\"Name\": \"sql2 (Replica)\",
|
|
\"Group\": \"pg-cluster\",
|
|
\"Host\": \"${CT_IP[sql2]}\",
|
|
\"Port\": 5432,
|
|
\"MaintenanceDB\": \"postgres\",
|
|
\"Username\": \"${USER_NICOLAY}\",
|
|
\"SSLMode\": \"prefer\",
|
|
\"Comment\": \"Patroni Replica Node\"
|
|
},
|
|
\"3\": {
|
|
\"Name\": \"sql3 (Replica)\",
|
|
\"Group\": \"pg-cluster\",
|
|
\"Host\": \"${CT_IP[sql3]}\",
|
|
\"Port\": 5432,
|
|
\"MaintenanceDB\": \"postgres\",
|
|
\"Username\": \"${USER_NICOLAY}\",
|
|
\"SSLMode\": \"prefer\",
|
|
\"Comment\": \"Patroni Replica Node\"
|
|
}
|
|
}
|
|
}
|
|
JSONEOF
|
|
|
|
sudo -u www-data /usr/pgadmin4/venv/bin/python3 /usr/pgadmin4/web/setup.py \
|
|
load-servers /tmp/pgadmin_servers.json --user ${PGADMIN_EMAIL}
|
|
"
|
|
|
|
# =============================================================================
|
|
step "PHASE 8: Abschluss-Prüfung und Report"
|
|
# =============================================================================
|
|
|
|
echo ""
|
|
echo -e "${BOLD}${GREEN}╔══════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${BOLD}${GREEN}║ PostgreSQL HA Cluster — Installation fertig ║${NC}"
|
|
echo -e "${BOLD}${GREEN}╚══════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
|
|
echo -e "${BOLD}Cluster-Status:${NC}"
|
|
pct exec "${CT_ID[sql1]}" -- /usr/local/bin/patronictl -c /etc/patroni/patroni.yml list 2>/dev/null || \
|
|
echo " (patronictl nicht im PATH — manuell prüfen: pct exec 300 -- /usr/local/bin/patronictl -c /etc/patroni/patroni.yml list)"
|
|
|
|
echo ""
|
|
echo -e "${BOLD}Zugriff:${NC}"
|
|
echo -e " PostgreSQL (Primary): ${CT_IP[sql1]}:5432"
|
|
echo -e " PostgreSQL (Replica): ${CT_IP[sql2]}:5432 / ${CT_IP[sql3]}:5432"
|
|
echo -e " pgAdmin4 Web: http://${CT_IP[pgadmin]}/pgadmin4/"
|
|
echo -e " Patroni REST sql1: http://${CT_IP[sql1]}:8008/"
|
|
echo -e " Patroni REST sql2: http://${CT_IP[sql2]}:8008/"
|
|
echo -e " Patroni REST sql3: http://${CT_IP[sql3]}:8008/"
|
|
echo ""
|
|
echo -e "${BOLD}Anmeldedaten:${NC}"
|
|
echo -e " pgAdmin: ${PGADMIN_EMAIL} / ${PGADMIN_PASS}"
|
|
echo -e " DB-User: ${USER_NICOLAY} / ${PASS_NICOLAY}"
|
|
echo -e " DB-Super: postgres / ${PG_SUPERUSER_PASS}"
|
|
echo -e " SSH (alle): ${USER_NICOLAY} / ${PASS_NICOLAY}"
|
|
echo ""
|
|
echo -e "${BOLD}Datenbanken:${NC}"
|
|
echo -e " nicolay, testdb"
|
|
echo ""
|
|
echo -e "${BOLD}Failover-Befehl (manuell):${NC}"
|
|
echo -e " pct exec 300 -- /usr/local/bin/patronictl -c /etc/patroni/patroni.yml failover ${PATRONI_SCOPE}"
|
|
echo ""
|