Host 1 — Database host (RHEL 9)¶
Runs PostgreSQL 16 + TimescaleDB + pgvector. Accepts connections only from Host 2 (core). Nothing here needs the Rust toolchain.
Substitute: <CORE_HOST_IP> (Host 2's address), <DB_PASSWORD> (pick a real
one — do not keep the script default).
1. Get the schema + install script¶
You don't need the whole repo built here, just the SQL and the installer:
2. Install PostgreSQL 16 + TimescaleDB + pgvector¶
This adds the PGDG and TimescaleDB repos, installs the packages, initializes
the cluster, enables the timescaledb preload library, creates the
ironshep role/database, and applies sql/schema.sql. It's idempotent —
safe to re-run if a step fails partway.
Confirm:
sudo -u postgres /usr/pgsql-16/bin/psql -d ironshep -c '\dx'
# expect: timescaledb and vector both listed
3. Open Postgres to Host 2 only¶
By default Postgres listens on localhost only. Point it at this host's private interface and allow just Host 2's IP:
sudo tee -a /var/lib/pgsql/16/data/postgresql.conf > /dev/null <<'EOF'
listen_addresses = 'localhost,<THIS_HOST_PRIVATE_IP>'
EOF
echo "host ironshep ironshep <CORE_HOST_IP>/32 scram-sha-256" | \
sudo tee -a /var/lib/pgsql/16/data/pg_hba.conf
sudo systemctl restart postgresql-16
Replace <THIS_HOST_PRIVATE_IP> with this host's own address (the one Host 2
will dial), and <CORE_HOST_IP> with Host 2's address. Narrow the /32 to a
subnet only if Host 2's IP is expected to change.
4. Firewall¶
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<CORE_HOST_IP>/32" port port="5432" protocol="tcp" accept'
sudo firewall-cmd --reload
This opens 5432 to Host 2 specifically, not the whole network. SELinux stays Enforcing — nothing here needs a custom policy.
5. Double-check the password took¶
If you didn't set IRONSHEP_DB_PASS before running the installer, it used
the placeholder default. Fix that now:
Done¶
Hand <DB_PASSWORD> and this host's address to whoever configures Host 2 —
it goes into core.toml's [db] url or the IRONSHEP_DB_URL environment
variable there. Nothing further runs on this host; Postgres itself is the
whole job.
Troubleshooting¶
| Symptom | Likely cause |
|---|---|
| Host 2 gets "connection refused" | firewall rule missing, or listen_addresses not restarted |
| Host 2 gets "no pg_hba.conf entry" | wrong IP/CIDR in the pg_hba.conf line, or Host 2's outbound IP differs from what you expected (NAT) |
| Host 2 gets "password authentication failed" | password mismatch between here and Host 2's config |