Coding ยท Infrastructure

Database Migration โ†’ home server

One session, no data loss โ€” the last piece of infrastructure standing between Stage 2 and Stage 3
Status
โœ… Complete ยท no data loss
Source
Mac ยท localhost:5432
Target
Home server ยท 192.168.2.42
Tables
16 ยท all intact
50
samples
30
composition records
170
XRD peaks
92
characterization records
4
synthesis route records

The alloy_lab PostgreSQL database moved from a local Docker container on the Mac to the home server. Mac, ML Desktop, and the server now share one canonical database โ€” no divergence risk, no manual syncing, always reachable on demand.

PostgreSQL 17 Docker pg_dump / pg_restore Wake-on-LAN SSH .env

Step by step

01Wake the server

Server was powered off โ€” woken via Wake-on-LAN from the ML Desktop.

wakeserver   # alias for: wakeonlan 2c:56:dc:74:c4:ff
ssh r@192.168.2.42

Boot to SSH-ready: ~60 seconds.

02PostgreSQL on the server

Fresh Docker container, postgres:17 โ€” matching the Mac's version exactly, to avoid any version-skew surprises during restore.

mkdir -p ~/docker/postgres/data

docker run -d \
  --name alloy-postgres \
  --restart unless-stopped \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=*** \
  -e POSTGRES_DB=alloy_lab \
  -v ~/docker/postgres/data:/var/lib/postgresql/data \
  -p 5432:5432 \
  postgres:17

Data volume mounted at ~/docker/postgres/data โ€” persists across container restarts and upgrades.

03Dump from the Mac

# Inside Mac's postgres container
docker exec -t postgres pg_dump \
  -U postgres -d alloy_lab \
  --no-owner --no-acl -F c \
  -f /tmp/alloy_lab_backup.dump

# Extract from container
docker cp postgres:/tmp/alloy_lab_backup.dump ~/alloy_lab_backup.dump
# Result: 71KB compressed dump

04Transfer and restore on the server

# Transfer
scp ~/alloy_lab_backup.dump r@192.168.2.42:~/

# Restore on server
docker cp ~/alloy_lab_backup.dump alloy-postgres:/tmp/
docker exec -t alloy-postgres pg_restore \
  -U postgres -d alloy_lab \
  --no-owner --no-acl -F c \
  /tmp/alloy_lab_backup.dump

All 16 tables restored, row counts matching the source exactly.

05Remote connections configured

# Allow connections from the local network (192.168.2.0/24)
docker exec alloy-postgres bash -c "
echo 'host alloy_lab postgres 192.168.2.0/24 md5' \
  >> /var/lib/postgresql/data/pg_hba.conf"

# Listen on all interfaces
docker exec alloy-postgres bash -c "
sed -i \"s/#listen_addresses = 'localhost'/listen_addresses = '*'/\" \
  /var/lib/postgresql/data/postgresql.conf"

docker restart alloy-postgres

06.env updated on the Mac

POSTGRES_HOST=192.168.2.42   # changed from localhost
POSTGRES_PORT=5432
POSTGRES_DB=alloy_lab
POSTGRES_USER=postgres
POSTGRES_PASSWORD=***
POSTGRES_SCHEMA=alloy_lab

07SSH set up on the ML Desktop

SSH server wasn't installed on the ML Desktop yet โ€” needed for the transfer/verification steps.

sudo apt install openssh-server
sudo systemctl enable ssh
sudo systemctl start ssh

ML Desktop IP confirmed: 192.168.2.210

08.env updated on the ML Desktop

Same change: POSTGRES_HOST=192.168.2.42

09Connections verified

MachineTargetResult
Mac192.168.2.42:5432โœ… Samples: 50
ML Desktop192.168.2.42:5432โœ… Samples: 50

10Live test โ€” a new sample, written straight to the server

Added a new sample via the desktop app while connected to the server DB, to confirm the full pipeline works end to end against the new home, not just that the data survived the copy:

Connected to database: alloy_lab  โœ…
Added sample: ExampleAlloy-20260903-001 (ID: 52)  โœ…
3 synthesis routes auto-saved  โœ…

Confirmed: calculator โ†’ screening โ†’ DB write, all working against the server.

11path_repair.py โ€” clean

โœ… All file paths in the database are valid โ€” nothing to repair.

Raw data files remain on the Mac Desktop for now. Path repair will be needed once data physically moves to server:/mnt/storage1/datasets/alloy_lab/ โ€” deferred to the data organization pass before Stage 3.

12Mac's old container decommissioned

docker stop postgres
docker rm postgres

Image kept temporarily as a safety net. Removable at Stage 3 start: docker rmi postgres:17

Final system architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Home Server  192.168.2.42  (AMD FX-4320, always-on)โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
โ”‚  โ”‚  Docker: alloy-postgres (postgres:17)           โ”‚ โ”‚
โ”‚  โ”‚  Port: 5432                                     โ”‚ โ”‚
โ”‚  โ”‚  Data: ~/docker/postgres/data  (persistent)     โ”‚ โ”‚
โ”‚  โ”‚  50 samples, 16 tables, full Stage 2 schema     โ”‚ โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ”‚  Storage1: 2.7TB  (datasets, training runs)          โ”‚
โ”‚  Storage2: 931GB  (repos, docs)                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                โ”‚  192.168.2.0/24 local network
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚                โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  M4 Mac      โ”‚  โ”‚  ML Desktop  192.168.2.210       โ”‚
โ”‚  .env:       โ”‚  โ”‚  .env:                           โ”‚
โ”‚  host=.42 โœ… โ”‚  โ”‚  host=.42 โœ…                     โ”‚
โ”‚  App + tools โ”‚  โ”‚  Ryzen 9900X + RTX 5060 Ti 16GB  โ”‚
โ”‚  Pi4/Pi5 hub โ”‚  โ”‚  Stage 3 ML training             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Open items (not urgent)

What this enables

A note on the journey

This migration closes a significant chapter. The alloy lab database project started as a way to replace scattered spreadsheets and manual file management with something structured, reproducible, and ML-ready. Stage 1 built the data capture layer. Stage 2 built the validated characterization pipelines โ€” XRD, VSM, SEM โ€” each instrument properly understood and integrated, not approximated. This migration puts the result in its permanent home.

The database now contains real, validated measurements from real samples, stored in a schema designed from the start to feed a machine learning model. That model is Stage 3 โ€” and the infrastructure to run it is ready.

"What started as a lab organization tool is now a research platform."
โ€” 3 September 2026