first commit
CI / lint-and-test (push) Canceled after 0s

This commit is contained in:
Alberto-Audrix committed 2026-07-28 08:55:05 +07:00
commit 32a36cceff
444 files changed
+67186

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
# How to Sync Database from Server
## Quick Start
### Mac / Windows (WSL2 or Git Bash)
Run this single command from the project root:
```bash
./scripts/update-local-db-from-server.sh
```
That's it! Your local database now matches production.
> The script uses hardcoded defaults for `nvidia-admin@103.215.13.55`. To override, set environment variables before running.
## First Time Setup
1. Make sure Docker Desktop is running
2. Copy the docker override file:
```bash
cp docker-compose.override.local.example docker-compose.override.yml
```
3. Test SSH access:
```bash
ssh nvidia-admin@103.215.13.55
```
## What Each Script Does
- **`update-local-db-from-server.sh`** - Full sync (download + restore). Use this one.
- **`fetch-prod-db.sh`** - Only downloads backup to `./backups/`
- **`restore-postgres-local.sh`** - Only restores a backup file to local database
## Troubleshooting
**"Permission denied" error?**
- Make sure you can SSH: `ssh nvidia-admin@103.215.13.55`
**"docker: command not found"?**
- Start Docker Desktop
**Windows users:**
- Use WSL2, Git Bash, or PowerShell with WSL installed
- Run from the project root folder
## Pro Tip: Create an Alias
Add to `~/.zshrc` (Mac) or `~/.bashrc` (Windows/Linux):
```bash
alias sync-db='./scripts/update-local-db-from-server.sh'
```
Then from anywhere in the project, just type: `sync-db`
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env sh
# Daily PostgreSQL backup via Docker Compose (database service).
# Run from anywhere: uses project root next to this script.
# Cron example (2:15 AM): 15 2 * * * /path/to/repo/scripts/backup-postgres.sh
set -e
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
PROJECT_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
cd "$PROJECT_ROOT"
BACKUP_DIR="${BACKUP_DIR:-$PROJECT_ROOT/backups}"
KEEP_DAYS="${KEEP_DAYS:-14}"
mkdir -p "$BACKUP_DIR"
STAMP=$(date +%Y%m%d-%H%M%S)
OUT="$BACKUP_DIR/dashboard_db-$STAMP.sql.gz"
# TCP + password avoids peer-auth issues when exec runs as non-postgres user
docker compose exec -T database sh -c \
'PGPASSWORD="$POSTGRES_PASSWORD" pg_dump -h 127.0.0.1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" --no-owner --no-acl' \
| gzip -c > "$OUT"
echo "Backup written: $OUT"
# Drop backups older than KEEP_DAYS (optional)
if [ -n "$KEEP_DAYS" ] && [ "$KEEP_DAYS" -gt 0 ] 2>/dev/null; then
find "$BACKUP_DIR" -maxdepth 1 -name 'dashboard_db-*.sql.gz' -type f -mtime "+$KEEP_DAYS" -delete 2>/dev/null || true
fi
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# Run on your Mac: creates a fresh backup on the server, then downloads it
# into ./backups/ (never writes to production data — only pg_dump read).
#
# Usage:
# REMOTE_USER=nvidia-admin \
# REMOTE_HOST=103.215.13.55 \
# REMOTE_PROJECT_DIR=/home/nvidia-admin/LABS/dashboard-solusi-ai-peternakan-ayam \
# ./scripts/fetch-prod-db.sh
#
# Then: ./scripts/restore-postgres-local.sh --reset
set -e
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
PROJECT_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
cd "$PROJECT_ROOT"
# Default values (can be overridden with environment variables)
: "${REMOTE_USER:=nvidia-admin}"
: "${REMOTE_HOST:=103.215.13.55}"
: "${REMOTE_PROJECT_DIR:=/home/nvidia-admin/LABS/dashboard-solusi-ai-peternakan-ayam}"
mkdir -p "$PROJECT_ROOT/backups"
QDIR=$(printf '%q' "$REMOTE_PROJECT_DIR")
echo "Running backup on server..."
ssh "${REMOTE_USER}@${REMOTE_HOST}" "cd ${QDIR} && ./scripts/backup-postgres.sh"
echo "Finding newest remote backup..."
REMOTE_LATEST=$(ssh "${REMOTE_USER}@${REMOTE_HOST}" "ls -t ${QDIR}/backups/dashboard_db-*.sql.gz 2>/dev/null | head -1")
if [ -z "$REMOTE_LATEST" ]; then
echo "No dashboard_db-*.sql.gz found under ${REMOTE_PROJECT_DIR}/backups on server."
exit 1
fi
LOCAL_NAME=$(basename "$REMOTE_LATEST")
echo "Downloading ${REMOTE_LATEST} -> backups/${LOCAL_NAME}"
scp "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_LATEST}" "$PROJECT_ROOT/backups/${LOCAL_NAME}"
echo "Saved: $PROJECT_ROOT/backups/${LOCAL_NAME}"
echo "Next: ./scripts/restore-postgres-local.sh --reset backups/${LOCAL_NAME}"
echo "Or next time run only: ./scripts/update-local-db-from-server.sh (same REMOTE_* env)."
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env sh
# Restore a gzip SQL backup (same format as scripts/backup-postgres.sh) into the
# local Docker database. Use --reset to wipe the local volume first (recommended
# for a clean clone). Does not contact production.
#
# Usage:
# cp docker-compose.override.local.example docker-compose.override.yml # once
# docker compose up -d database
# ./scripts/restore-postgres-local.sh --reset [path/to/dashboard_db-*.sql.gz]
#
# If you omit the file path, the newest ./backups/dashboard_db-*.sql.gz is used.
set -e
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
PROJECT_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
cd "$PROJECT_ROOT"
RESET=0
BACKUP_FILE=
for arg in "$@"; do
case "$arg" in
--reset) RESET=1 ;;
-*) echo "Unknown option: $arg"; exit 1 ;;
*) BACKUP_FILE=$arg ;;
esac
done
if [ -z "$BACKUP_FILE" ]; then
BACKUP_FILE=$(ls -t "$PROJECT_ROOT"/backups/dashboard_db-*.sql.gz 2>/dev/null | head -1)
fi
if [ -z "$BACKUP_FILE" ] || [ ! -f "$BACKUP_FILE" ]; then
echo "No backup file found. Run ./scripts/fetch-prod-db.sh or pass a .sql.gz path."
exit 1
fi
BACKUP_FILE=$(CDPATH= cd -- "$(dirname -- "$BACKUP_FILE")" && pwd)/$(basename -- "$BACKUP_FILE")
if [ "$RESET" != 1 ]; then
echo "Refusing to restore without --reset (avoids a messy mix of old + dump data)."
echo "Run: $0 --reset \"$BACKUP_FILE\""
exit 1
fi
echo "Stopping stack and removing LOCAL Docker volumes for this project..."
docker compose down -v
echo "Starting database..."
docker compose up -d database
echo "Waiting for Postgres (TCP on 127.0.0.1:5432 inside container)..."
i=0
while [ "$i" -lt 90 ]; do
if docker compose exec -T database sh -c 'pg_isready -h 127.0.0.1 -p 5432 -U "$POSTGRES_USER" -d "$POSTGRES_DB"' >/dev/null 2>&1; then
break
fi
i=$((i + 1))
sleep 1
done
if [ "$i" -eq 90 ]; then
echo "Database did not become ready in time."
exit 1
fi
echo "Restoring from $BACKUP_FILE ..."
# Use Unix socket (no -h): matches pg_isready-without-TCP race on Docker Desktop; avoids connection refused to 127.0.0.1
gunzip -c "$BACKUP_FILE" | docker compose exec -T database sh -c \
'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=1'
echo "Local database restored. Use DB_HOST=127.0.0.1 DB_PORT=5432 (with override) in .env for development."
echo "Do not point these credentials at production."
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# One command to refresh your LOCAL Docker Postgres from the server:
# runs a read-only pg_dump on the server, downloads it, resets the local volume, restores.
#
# Prerequisite once on your Mac:
# cp docker-compose.override.local.example docker-compose.override.yml
#
# Usage (set paths to match your server):
# REMOTE_USER=nvidia-admin \
# REMOTE_HOST=103.215.13.55 \
# REMOTE_PROJECT_DIR=/home/nvidia-admin/path/to/dashboard-solusi-ai-peternakan-ayam \
# ./scripts/update-local-db-from-server.sh
#
# Does not modify production data. ./scripts/fetch-prod-db.sh and
# ./scripts/restore-postgres-local.sh remain available if you want only one step.
set -euo pipefail
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
PROJECT_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
# Default values (can be overridden with environment variables)
: "${REMOTE_USER:=nvidia-admin}"
: "${REMOTE_HOST:=103.215.13.55}"
: "${REMOTE_PROJECT_DIR:=/home/nvidia-admin/LABS/dashboard-solusi-ai-peternakan-ayam}"
export REMOTE_USER REMOTE_HOST REMOTE_PROJECT_DIR
"$SCRIPT_DIR/fetch-prod-db.sh"
LATEST=$(ls -t "$PROJECT_ROOT"/backups/dashboard_db-*.sql.gz 2>/dev/null | head -1)
if [ -z "$LATEST" ] || [ ! -f "$LATEST" ]; then
echo "No local backup found after fetch."
exit 1
fi
"$SCRIPT_DIR/restore-postgres-local.sh" --reset "$LATEST"
echo "Local database is now a copy of the latest server backup."