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