Initial commit: Aquarium Logbuch React/Vite App
- React 18 + Vite Frontend - Node.js/Express Backend - Vollstaendige Logbuch-Funktionalitaet fuer Aquarien - Deploy-Script fuer aqualog CT 211 (192.168.0.246)
This commit is contained in:
589
postgres-ha-install.sh
Normal file
589
postgres-ha-install.sh
Normal file
@@ -0,0 +1,589 @@
|
||||
#!/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 ""
|
||||
Reference in New Issue
Block a user