first commit
This commit is contained in:
2
.env
Normal file
2
.env
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
POSTGRES_PASSWORD=heel-goed-wachtwoord
|
||||||
|
PGADMIN_PASSWORD=heel-goed-wachtwoord
|
||||||
188
README.md
Normal file
188
README.md
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
# PostgreSQL Infrastructure Setup
|
||||||
|
|
||||||
|
This folder contains the Docker-based PostgreSQL infrastructure running on the internal server (`192.168.1.159`).
|
||||||
|
It provides a production-ready PostgreSQL instance, optional pgAdmin UI, and a simple automated backup mechanism.
|
||||||
|
|
||||||
|
The setup is designed to be:
|
||||||
|
|
||||||
|
- persistent (volume-backed database storage)
|
||||||
|
- LAN-accessible (port `5432`)
|
||||||
|
- isolated from Traefik (database does not use reverse proxy)
|
||||||
|
- easy to operate (`docker compose up -d`)
|
||||||
|
- safe (controlled permissions and separate admin password)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
infra/postgres/
|
||||||
|
docker-compose.yml → main PostgreSQL service
|
||||||
|
.env → database credentials (not committed)
|
||||||
|
data/ → PostgreSQL data directory (automatically created)
|
||||||
|
backup/ → SQL dumps created by backup containers
|
||||||
|
pgadmin/ → optional pgAdmin admin UI exposed via Traefik
|
||||||
|
backup/ → backup runner files (optional)
|
||||||
|
```
|
||||||
|
|
||||||
|
`data/` and `backup/` are *not* included in version control.
|
||||||
|
They are created on the server when the stack is deployed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Run on the target server (`Tour`, 192.168.1.159):
|
||||||
|
|
||||||
|
- Docker
|
||||||
|
- Docker Compose v2
|
||||||
|
- Access to the `traefik-net` Docker network (only if pgAdmin is used)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Environment File
|
||||||
|
|
||||||
|
Create `.env` inside this directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
POSTGRES_PASSWORD=<strong_password_here>
|
||||||
|
PGADMIN_PASSWORD=<admin_ui_password_if_pgadmin_enabled>
|
||||||
|
```
|
||||||
|
|
||||||
|
Recommended permissions:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod 600 .env
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Initial Setup
|
||||||
|
|
||||||
|
Run these commands on the server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/infra/postgres
|
||||||
|
mkdir -p data backup
|
||||||
|
```
|
||||||
|
|
||||||
|
Ensure correct directory ownership:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo chown -R $USER:$USER data backup
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Starting the Stack
|
||||||
|
|
||||||
|
Start PostgreSQL:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Check status:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
|
||||||
|
```
|
||||||
|
postgres-db Up (healthy) 0.0.0.0:5432->5432/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Connecting to PostgreSQL
|
||||||
|
|
||||||
|
Connection string:
|
||||||
|
|
||||||
|
```
|
||||||
|
postgresql://auction:<password>@192.168.1.159:5432/auctiondb
|
||||||
|
```
|
||||||
|
|
||||||
|
Test:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
psql "postgresql://auction:<password>@192.168.1.159:5432/auctiondb"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## pgAdmin (Optional)
|
||||||
|
|
||||||
|
If pgAdmin is deployed via Traefik, access it at:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://pgadmin.appmodel.nl/
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `postgres-db` as the hostname inside pgAdmin.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backup Strategy
|
||||||
|
|
||||||
|
SQL dumps are stored in:
|
||||||
|
|
||||||
|
```
|
||||||
|
infra/postgres/backup/
|
||||||
|
```
|
||||||
|
|
||||||
|
Daily backups produce files like:
|
||||||
|
|
||||||
|
```
|
||||||
|
backup_YYYY-MM-DD_HH-MM.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
Restore example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
psql -U auction -d auctiondb < backup_file.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stopping or Updating
|
||||||
|
|
||||||
|
Stop:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
Update:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Disaster Recovery
|
||||||
|
|
||||||
|
To rebuild the database:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
mv data data_old_$(date +%s)
|
||||||
|
docker compose up -d
|
||||||
|
psql -U auction -d auctiondb < backup/latest.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
Possible extensions:
|
||||||
|
|
||||||
|
- Flyway migration container
|
||||||
|
- Auto schema sync for Python + Quarkus
|
||||||
|
- Monitoring exporters
|
||||||
|
- Retention policy for backups
|
||||||
|
- Migration from SQLite to PostgreSQL
|
||||||
|
|
||||||
14
backup/backup.sh
Normal file
14
backup/backup.sh
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
DATE=$(date +"%Y-%m-%d_%H-%M")
|
||||||
|
FILENAME="backup_$DATE.sql"
|
||||||
|
|
||||||
|
echo "Dumping database to $FILENAME"
|
||||||
|
|
||||||
|
/usr/bin/pg_dump \
|
||||||
|
-h postgres-db \
|
||||||
|
-U auction \
|
||||||
|
auctiondb \
|
||||||
|
> /backup/$FILENAME
|
||||||
|
|
||||||
|
# optional: keep only 14 days
|
||||||
|
find /backup -type f -mtime +14 -delete
|
||||||
19
backup/docker-compose.yml
Normal file
19
backup/docker-compose.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
pgbackup:
|
||||||
|
image: postgres:16
|
||||||
|
container_name: postgres-backup
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PGPASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ../postgres/backup:/backup
|
||||||
|
- ./backup.sh:/backup.sh
|
||||||
|
|
||||||
|
entrypoint: [ "bash", "-c", "echo 'Starting backup scheduler'; while true; do /backup.sh; sleep 86400; done" ]
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
25
docker-compose.yml
Normal file
25
docker-compose.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16
|
||||||
|
container_name: postgres-db
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: auctiondb
|
||||||
|
POSTGRES_USER: auction
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "5432:5432" # LAN only, safe inside 192.168.1.x
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ./data:/var/lib/postgresql/data
|
||||||
|
- ./backup:/backup
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U auction -d auctiondb"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 2s
|
||||||
|
retries: 10
|
||||||
105
install_postgres.sh
Normal file
105
install_postgres.sh
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== PostgreSQL Infra Installer ==="
|
||||||
|
|
||||||
|
# Detect working directory (should be infra/postgres)
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
echo "Using infra directory: $SCRIPT_DIR"
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# 1. Ensure directories exist
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
echo "→ Creating required directories..."
|
||||||
|
mkdir -p data
|
||||||
|
mkdir -p backup
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# 2. Permissions
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
echo "→ Setting directory permissions..."
|
||||||
|
sudo chown -R "$USER:$USER" data backup
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# 3. Create .env if missing
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
if [ ! -f ".env" ]; then
|
||||||
|
echo "→ Creating .env file..."
|
||||||
|
cat <<EOF > .env
|
||||||
|
POSTGRES_PASSWORD=$(openssl rand -hex 16)
|
||||||
|
PGADMIN_PASSWORD=$(openssl rand -hex 16)
|
||||||
|
EOF
|
||||||
|
echo "Generated random passwords in .env"
|
||||||
|
else
|
||||||
|
echo "→ .env file already exists; skipping creation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Current .env:"
|
||||||
|
cat .env
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# 4. Verify Docker & Docker Compose
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
echo "→ Checking Docker installation..."
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
echo "ERROR: Docker is not installed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "→ Checking Docker Compose..."
|
||||||
|
if ! docker compose version &> /dev/null; then
|
||||||
|
echo "ERROR: Docker Compose V2 is not installed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# 5. Start PostgreSQL stack
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
echo "→ Starting PostgreSQL Docker stack..."
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
echo "→ Waiting for PostgreSQL to report healthy status..."
|
||||||
|
sleep 3
|
||||||
|
docker ps --filter "name=postgres-db"
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# 6. Setup backup container
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
echo "→ Checking backup service..."
|
||||||
|
|
||||||
|
if [ -d "backup" ] && [ -f "backup/docker-compose.yml" ]; then
|
||||||
|
echo "→ Starting backup runner..."
|
||||||
|
cd backup
|
||||||
|
docker compose up -d
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
else
|
||||||
|
echo "⚠ Backup runner folder missing. Expected: ./backup/docker-compose.yml"
|
||||||
|
echo "Skipping backup setup."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# 7. Summary
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "===================================================="
|
||||||
|
echo " PostgreSQL Infra Installed Successfully"
|
||||||
|
echo "===================================================="
|
||||||
|
echo "Host machine: $(hostname)"
|
||||||
|
echo "Database port: 5432 (LAN accessible)"
|
||||||
|
echo "Data dir: $SCRIPT_DIR/data"
|
||||||
|
echo "Backups: $SCRIPT_DIR/backup/"
|
||||||
|
echo ""
|
||||||
|
echo "Connection string:"
|
||||||
|
echo " postgresql://auction:<POSTGRES_PASSWORD>@192.168.1.159:5432/auctiondb"
|
||||||
|
echo ""
|
||||||
|
echo "Start/Stop commands:"
|
||||||
|
echo " docker compose up -d"
|
||||||
|
echo " docker compose down"
|
||||||
|
echo ""
|
||||||
|
echo "If pgAdmin is enabled, visit:"
|
||||||
|
echo " https://pgadmin.appmodel.nl/"
|
||||||
|
echo ""
|
||||||
|
echo "Done."
|
||||||
29
pgadmin/docker-compose.yml
Normal file
29
pgadmin/docker-compose.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
pgadmin:
|
||||||
|
image: dpage/pgadmin4:8
|
||||||
|
container_name: pgadmin
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PGADMIN_DEFAULT_EMAIL: admin@appmodel.nl
|
||||||
|
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD}
|
||||||
|
PGADMIN_CONFIG_SERVER_MODE: "True"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ./data:/var/lib/pgadmin
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- traefik-net
|
||||||
|
- default
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.pgadmin.rule=Host(`pgadmin.appmodel.nl`)"
|
||||||
|
- "traefik.http.routers.pgadmin.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.pgadmin.tls.certresolver=letsencrypt"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik-net:
|
||||||
|
external: true
|
||||||
Reference in New Issue
Block a user