Status: Planning
Last Updated: 2026-05-28
Each client partner gets their own dedicated VPS with PostgreSQL to hold their patient data. The VPS is the property of the client (whether we pay on their behalf or they pay the hosting provider directly). The main VPS configures and manages client VPS instances through WireGuard tunnels — no public ports are exposed on client VPSes.
Partners access their patient records through the GP Booking App running on the main VPS, which reaches into each client VPS's database through the tunnel.
┌──────────────────────────────────────────────────────────┐
│ MAIN VPS (this one) │
│ │
│ ┌────────────────────┐ ┌───────────────────────────┐ │
│ │ Keycloak │ │ GP Booking App (Django) │ │
│ │ (per-org realms) │ │ │ │
│ │ │ │ ┌─────────────────────┐ │ │
│ │ maple-surgery realm │ │ │ Postgres (main DB) │ │ │
│ │ oak-practice realm │ │ │ │ │ │
│ │ ... │ │ │ ─ CustomUser │ │ │
│ └────────────────────┘ │ │ ─ PartnerOrg │ │ │
│ │ │ ─ Tenant │ │ │
│ │ │ ─ FDW: Patient │──┼──┐
│ │ │ ─ FDW: ClinicalNote │ │ │
│ │ │ ─ FDW: Prescription │ │ │
│ │ │ ─ FDW: Appointment │ │ │
│ │ └─────────────────────┘ │ │
│ └───────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ WireGuard — tunnel hub (10.100.0.1/24) │ │
│ └────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
│
WireGuard tunnel (Postgres protocol only)
│
┌────────────────────┼────────────────────────────┐
│ │ │
┌───▼────────────────┐ │ ┌─────────────────────────▼──┐
│ CLIENT VPS (Maple) │ │ │ CLIENT VPS (Oak Practice) │
│ │ │ │ │
│ ┌───────────────┐ │ │ │ ┌────────────────────┐ │
│ │ Postgres │ │ │ │ │ Postgres │ │
│ │ │ │ │ │ │ │ │
│ │ ─ Patient │ │ │ │ │ ─ Patient │ │
│ │ ─ ClinicalNote│ │ │ │ │ ─ ClinicalNote │ │
│ │ ─ Prescription│ │ │ │ │ ─ Prescription │ │
│ │ ─ Appointment │ │ │ │ │ ─ Appointment │ │
│ │ ─ etc. │ │ │ │ │ ─ etc. │ │
│ └───────────────┘ │ │ │ └────────────────────┘ │
│ │ │ │ │
│ WireGuard peer │ │ │ WireGuard peer │
│ 10.100.0.2 │ │ │ 10.100.0.3 │
│ 0 public ports │ │ │ 0 public ports │
└─────────────────────┘ │ └──────────────────────────┘
| Data | Location | Notes |
|---|---|---|
CustomUser (all staff accounts) |
Main VPS | All accounts in one database, linked to org via org_id |
PartnerOrg, Tenant |
Main VPS | System configuration |
| Django internals (sessions, auth tokens, etc.) | Main VPS | Standard Django tables |
| Keycloak realms | Main VPS | Per-org realms as currently configured |
Patient |
Client VPS | Core patient demographics |
ClinicalNote |
Client VPS | Historical clinical notes |
Prescription |
Client VPS | Prescription records |
Appointment |
Client VPS | Appointment records |
PatientHealthProfile |
Client VPS | Patient health profiles |
| Patient user accounts (future) | Main VPS | CustomUser entries, same as staff — clinical data routes via org_id |
Foreign Data Wrappers (FDW) are a PostgreSQL-native feature — no extra software needed. They allow one Postgres database to access tables on another Postgres server as if they were local.
{slug}.gp.veripath.co.ukorg_idCustomUser)Patient.objects.filter(org_id=...)Patient is an FDW foreign table → forwards query through WireGuard to client VPS/opt/migrate-clients.sh — loops through all active client tunnels| Component | Tunnel IP | Role |
|---|---|---|
| Main VPS | 10.100.0.1/24 |
Hub — routes to all client peers |
| Client VPS (Maple Surgery) | 10.100.0.2/32 |
Peer — only talks to main VPS |
| Client VPS (Oak Practice) | 10.100.0.3/32 |
Peer — only talks to main VPS |
| Client VPS (...) | 10.100.0.x/32 |
Peer — sequential allocation |
Client VPS security:
10.100.0.x)pg_hba.conf allows connections only from 10.100.0.1 (the main VPS)/opt/provision-client-vps.sh — automated client VPS setup script/opt/migrate-clients.sh — runs Django migrations on all active client VPSes and refreshes FDW definitions on the main VPSCustomUser accounts on main VPS (same as staff)org_id/opt/provision-client-vps.sh)# Usage: /opt/provision-client-vps.sh maple-surgery "10.100.0.2"
1. Spin up VPS (provider-specific)
2. Install Postgres + WireGuard
3. Generate WireGuard key pair for client
4. Configure WireGuard peer on both ends
5. Create Postgres database and user for the booking app
6. Create patient schema tables (run relevant Django migrations)
7. Set up FDW server on main VPS pointing to client
8. Import foreign schema
9. Register client VPS in PartnerOrg model (connection details)
10. Report success