Installation
How to install ParallelPath on your own Ubuntu server with one interactive script.
Server requirements
| Minimum | Recommended | |
|---|---|---|
| OS | Ubuntu Server 24.04 LTS (or newer) | Ubuntu Server 24.04 LTS / 26.04 LTS |
| CPU | 1 vCPU (x86-64 or ARM64) | 2+ vCPU |
| Memory | 1 GB RAM + 1 GB swap | 2-4 GB RAM |
| Disk | 10 GB free (SSD) | 40 GB+ SSD (documents and call recordings grow over time) |
| Network | Public IPv4, ports 80/443 | + UDP 3478 & 49160-49200 for call relaying; IPv6 welcome |
| Bandwidth | ~1 Mbps per relayed video call | Most calls go peer-to-peer and use no server bandwidth |
| DNS | A record for your (sub)domain | + AAAA record if you have IPv6 |
| Other | systemd 250+ (24.04 has 255) | A TPM2 chip seals keys to the hardware (rare on VPSes - not required) |
What uses what (typical small install, a handful of families):
| Component | Memory | Notes |
|---|---|---|
| ParallelPath app | 120-200 MB | Single process; capped by the installer at half your RAM (max 1.5 GB) |
| PostgreSQL | 60-150 MB | Socket-only, no network port |
| nginx | 10-30 MB | Shared with any sites you already host |
| coturn (calls) | 10-40 MB | Only works when a call can't connect directly |
| Built-in Tone Check | ~0 | Pure Python word lists - microseconds per message |
Optional local AI. If you want an AI model for Tone Check, run it on a separate machine (your desktop GPU, a home server or another VPS) with Ollama or any OpenAI-compatible server, and point ParallelPath at it in the admin portal. A 3-billion-parameter model on CPU needs roughly 4 cores and 4-8 GB RAM - too heavy for a small VPS, which is why the default checker is the lightweight built-in one. You can also use Anthropic Claude via its API.
Before you start
- A server running Ubuntu 24.04 LTS or newer, which you can SSH into with a sudo-capable account.
- A domain or subdomain with a DNS A record pointing to the server's public IP. You can install before DNS is ready and get the certificate later.
- Ports 80 and 443 open to the internet (and UDP 3478 + 49160-49200 for calls). The installer opens them in ufw for you; cloud firewalls (e.g. your VPS provider's panel) you must open yourself.
Run the installer
Copy the ParallelPath folder to the server (or download it from /source) and run:
sudo bash install.sh
The installer is interactive and explains each step. Nothing changes until you've answered every question and confirmed the summary. It's safe to run again - it remembers your answers and keeps existing data and keys.
What it checks first (pre-flight)
- Ubuntu version, CPU architecture, systemd version, TPM2 presence
- Memory and free disk space
- Whether nginx is already installed (and which sites it already serves)
- That ports 80/443 aren't taken by another web server
- Whether PostgreSQL and ufw are already in use
- This server's public addresses and SSH port (so the firewall never locks you out)
- That the clock is synchronised (two-step codes depend on it)
The questions
| Step | You choose |
|---|---|
| About your site | New standalone site on its own domain, or a subdomain of a site you already host on this server (e.g. coparent.example.com). The installer checks the name, checks DNS points at this server, and refuses if nginx already serves that name. |
| HTTPS certificate | Let's Encrypt (free, auto-renewing); reuse an existing certificate the installer found that already covers the name (including wildcard *.example.com certificates) - it shows days until expiry and the names covered; your own certificate files (checked: readable, covers the domain, not expired, key matches); or skip for now with a temporary self-signed certificate. |
| Admin account | Username, email and password for the separate server-admin portal, and optionally the IP addresses allowed to reach it. |
| Features | Calls on/off (installs the coturn relay), NAT public IP if needed, maximum upload size. |
| Encryption at rest (required) | Only the size of the encrypted LUKS2 volume. Encryption can't be turned off: the database and file store always live inside it, and the app refuses to start if its data isn't on an encrypted volume. |
| Optional SMTP for invitations and alerts (never message content). With email set up, password-reset links go straight to the person - never to an admin. | |
| Protection | ufw firewall, fail2ban, automatic security updates. |
| Backups & recovery keys | Daily or weekly at a time you choose, how many to keep, and optional copies to a folder (mounted NAS/USB) and/or another server over SFTP (the installer generates a dedicated SSH key, shows it to you and tests the connection). Then a recovery passphrase (16+ characters) that encrypts your recovery-key bundle. |
Then you get a review of everything that will happen.
What it does
- Installs only the packages needed (Python, PostgreSQL, nginx, and optionally coturn, certbot, fail2ban, cryptsetup).
- Creates a dedicated
parallelpathsystem user with no shell and no home. - Creates the encrypted volume (LUKS2, argon2id) and seals its key with systemd-creds (TPM2 when present). It unlocks automatically at boot. A separate LUKS recovery passphrase is generated for emergencies.
- Generates the master key, backup key and call-relay secret, sealed with systemd-creds, and builds the encrypted recovery-key bundle
/root/parallelpath-recovery.ppexport(PBKDF2-SHA256 + AES-256-GCM with your recovery passphrase). The keys are never written to disk in plain text - only in memory while the bundle is made. - Sets up PostgreSQL: a dedicated database inside the encrypted volume, two roles (schema owner and a least-privilege runtime role), socket-only, password-less peer authentication, and triggers that make evidence tables append-only.
- Installs the application read-only to
/opt/parallelpathand builds the public source manifest (with a secret scan). - Installs sandboxed systemd services and the AppArmor profile.
- Adds one nginx site for your domain - testing the configuration first and rolling back automatically if nginx rejects it, so your other sites are never affected.
- Gets or installs the certificate, and installs a renewal hook.
- Configures coturn, the firewall, fail2ban and automatic updates.
- Configures scheduled backups and their destinations, and copies the recovery bundle to them.
- Creates your first admin account.
- Runs health checks and prints your links and next steps.
Recovery keys - what to keep and where
| Item | Where it is | What it's for |
|---|---|---|
Recovery bundle parallelpath-recovery.ppexport |
/root/ and each backup destination |
Contains the master key, backup key and LUKS recovery passphrase - encrypted. |
| Recovery passphrase | Only in your head / password manager | Opens the bundle. Nobody can recover it for you. |
Backups parallelpath-*.ppbak |
/var/backups/parallelpath + destinations |
Encrypted database + file store. Useless without the keys from the bundle. |
Open the bundle any time at https://your-domain/decrypt-export - it runs in your browser and nothing is uploaded. Keep at least one copy of the bundle and your backups away from the server, and the passphrase separate from both.
Everything is logged to /var/log/parallelpath-install.log.
Installing with Docker instead
Prefer containers? See Docker - the same security in hardened Ubuntu 24.04 containers, set up by sudo bash docker/setup.sh.
Installing alongside an existing website
ParallelPath is designed to share a server with other sites:
- It adds a single file,
/etc/nginx/sites-available/parallelpath.conf, that only answers for your chosen (sub)domain.nginx.confand your other sites are not touched. - The app listens only on
127.0.0.1(default port 8471, or the next free port). - It uses its own PostgreSQL database and roles. If PostgreSQL was already installed, its network settings are left as they were.
- Firewall rules are only added.
- If you already have a wildcard certificate (e.g.
*.example.com) the installer offers to reuse it for a subdomain. Otherwise it gets a separate Let's Encrypt certificate just for the subdomain using the webroot method - certbot never edits your nginx files.
Example - subdomain of your main site: choose "A subdomain of an existing site", enter example.com and coparent, add a DNS A record for coparent.example.com, and choose Let's Encrypt.
Running ParallelPath under a path (e.g.
example.com/coparent) isn't supported - it needs its own (sub)domain for its security cookies and headers.
After installing
- Copy the recovery bundle off the server (if you didn't set a backup destination), e.g. from your PC:
bash scp you@your-server:/root/parallelpath-recovery.ppexport .(Copy it to a readable place first withsudo cp /root/parallelpath-recovery.ppexport /tmp/ && sudo chown $USER /tmp/parallelpath-recovery.ppexport.) Check you can open it at/decrypt-exportwith your passphrase. - Open
https://your-domain/admin, sign in and set up two-step verification. - In Accounts, invite the first parent.
Getting the certificate later
If you skipped HTTPS or DNS wasn't ready:
sudo ppctl tls
This re-runs only the certificate step: it re-checks DNS, lists certificates already on the server that cover your domain, and lets you choose Let's Encrypt, an existing certificate or your own files.
Upgrading
sudo bash install.sh --upgrade # from the new version's folder
Upgrades keep all settings, keys and data. The previous code is kept in /opt/parallelpath/src.old. Database schema changes are applied automatically.
Uninstalling
sudo bash /opt/parallelpath/src/install.sh --uninstall
This removes the application, services and nginx site but keeps all data, keys and backups unless you type DELETE EVERYTHING at the final prompt.
Troubleshooting
| Problem | Try |
|---|---|
| Let's Encrypt failed | Check DNS (dig +short your-domain) points to this server and port 80 is open in any cloud firewall, then sudo ppctl tls. |
| Site shows a certificate warning | You're on the temporary certificate - run sudo ppctl tls. |
| "Application didn't start" | sudo ppctl logs 100 |
| Two-step codes always fail | The server or phone clock is wrong: timedatectl / sudo timedatectl set-ntp true. |
| Calls connect but no video/audio | Open UDP 3478 and 49160-49200 in your provider's firewall; if the server is behind NAT, re-run the installer and give the public IP. |
| nginx test failed | The installer rolled back. See the nginx: [emerg] line in /var/log/parallelpath-install.log. |