Self-Hosting Unitae on a VPS in 10 Minutes
8 min read
You want to know exactly where your congregation’s data lives. Not a promise from a hosting provider — you want to SSH into the machine and see the database yourself. Good. In ten minutes, you’ll have a running Unitae instance on your own server, behind your own domain, with every feature unlocked. The entire source code is on GitHub under AGPL-3.0, and the self-hosted version is identical to managed.
What you need
A VPS with at least 1 vCPU, 1 GB RAM, and 20 GB of storage. A Hetzner CX21 at around €4/month works well. Ubuntu 22.04 LTS or Debian 12 recommended. You also need a domain name with an A record pointing to your server, Docker and Docker Compose installed, and an SMTP provider for emails (Resend’s free tier is sufficient).
On your local machine, you only need SSH access to the server and a text editor. Everything else happens on the server itself.
Clone and configure
SSH into your server, clone the repository, and copy the environment file. Set APP_URL to your full URL (e.g. https://unitae.your-congregation.org). Generate SESSION_SECRET with openssl rand -hex 32. Configure SMTP_HOST, SMTP_PORT, SMTP_USER, and SMTP_PASS for your email provider. DATABASE_URL and REDIS_URL are pre-configured for the Docker Compose containers.
# Clone the repository
git clone https://github.com/Unitae/unitae.git && cd unitae
# Copy the environment file
cp .env.example .env
# Edit .env with your values
nano .env
Start Unitae
Run docker compose up -d to start the full stack. Once containers are running, apply migrations and seed data. Unitae is now running on port 8080. If anything fails, docker compose logs web shows the application logs. Common issues are a malformed DATABASE_URL or a missing SESSION_SECRET.
docker compose up -d
docker compose exec app pnpm prisma migrate deploy
docker compose exec app pnpm prisma db seed
✓ Unitae is running on localhost:8080
Add your domain and TLS
Caddy is the recommended reverse proxy — it handles Let’s Encrypt certificates automatically. Create a Caddyfile with one line: your domain reverse-proxying to localhost:8080. Start Caddy, point your DNS A record, and HTTPS is live within minutes.
Make sure ports 80 and 443 are open in your firewall, and close port 8080 to external traffic now that it is proxied.
First login and setup
Navigate to your domain. The setup screen walks you through creating your admin account and configuring your congregation. Then work through the onboarding checklist: set your territory structure, invite the territory servant and secretary, and create your first territory card.
Invite other members from the Publishers section. Each invitation sends an email with a link to create an account. Members receive access appropriate to their role — publishers see their own territories and reports, elders with admin roles can access congregation-wide data.
Keeping it updated
Updating is three steps: git pull, docker compose up -d --build, then run migrations. Subscribe to GitHub releases to be notified of new versions. For backups, add a daily cron job that dumps PostgreSQL to a file and copies it offsite. Keep at least seven days of backups and test restores periodically. You now have a self-hosted instance that is entirely yours — and if you contribute improvements back, every congregation using Unitae benefits.