# 02-splitpro.md

kstack:
  book: Centerpoint Home Lab
  chapter: Finance
  page: SplitPro
  tags: [splitpro, expenses, splitting, authentik, postgres, step-ca]
---

## Overview

SplitPro is a self-hosted shared expense splitting app — an open-source
alternative to Splitwise. It tracks group expenses, calculates balances, and
supports multi-currency via the Frankfurter exchange rate provider. Authentik
OIDC provides authentication. Email invites are handled via Gmail SMTP. The
Step-CA root certificate is injected so SplitPro can make HTTPS calls to
internal `*.home.local` services. External-only route.

## Access

| Type     | URL                                        | Auth                          |
|----------|--------------------------------------------|-------------------------------|
| External | `https://splitpro.jeevesconsults.ca`       | Authentik OIDC + GeoBlock + CrowdSec |

SplitPro handles its own OIDC redirect to Authentik — Traefik does not apply
`authentik-auth@docker` ForwardAuth. Authentication is managed natively by the
Next.js `next-auth` library.

## Containers

| Container     | Image                             | Role                |
|---------------|-----------------------------------|---------------------|
| `splitpro`    | `ossapps/splitpro:latest`         | Web application     |
| `splitpro-db` | `ossapps/postgres:17.7-trixie`    | PostgreSQL 17 database |

### splitpro (application)

**Runtime:** Node.js 22 (Next.js)

**Key environment variables:**

| Variable                         | Value / Notes                                                    |
|----------------------------------|------------------------------------------------------------------|
| `NEXTAUTH_URL`                   | `https://splitpro.jeevesconsults.ca`                             |
| `NEXTAUTH_SECRET`                | **REDACTED**                                                     |
| `AUTHENTIK_ID`                   | `xA8pjyG7s4LsnmRKp9Wn9H9v8oUpawBAMvmEF9tT`                      |
| `AUTHENTIK_SECRET`               | **REDACTED**                                                     |
| `AUTHENTIK_ISSUER`               | `https://auth.jeevesconsults.ca/application/o/splitpro`          |
| `OIDC_ALLOW_DANGEROUS_EMAIL_LINKING` | `1`                                                          |
| `DATABASE_URL`                   | **REDACTED** (includes PostgreSQL password)                      |
| `POSTGRES_USER`                  | `splitpro`                                                       |
| `POSTGRES_DB`                    | `splitpro`                                                       |
| `POSTGRES_PORT`                  | `5432`                                                           |
| `EMAIL_SERVER_HOST`              | `smtp.gmail.com`                                                 |
| `EMAIL_SERVER_PORT`              | `587`                                                            |
| `EMAIL_SERVER_USER`              | `jeeves5454@gmail.com`                                           |
| `EMAIL_SERVER_PASSWORD`          | **REDACTED**                                                     |
| `FROM_EMAIL`                     | `splitpro@jeevesconsults.ca`                                     |
| `ENABLE_SENDING_INVITES`         | `true`                                                           |
| `DISABLE_EMAIL_SIGNUP`           | `false`                                                          |
| `CURRENCY_RATE_PROVIDER`         | `frankfurter`                                                    |
| `DEFAULT_HOMEPAGE`               | `/balances`                                                      |
| `CACHE_RETENTION_INTERVAL`       | `2 days`                                                         |
| `CLEAR_CACHE_CRON_RULE`          | `0 2 * * 0` (Sunday 2am)                                         |
| `UPLOAD_MAX_FILE_SIZE_MB`        | `10`                                                             |
| `NODE_EXTRA_CA_CERTS`            | `/etc/ssl/certs/step-ca-root.crt`                                |
| `PORT`                           | `3000`                                                           |

**Bind mounts:**

| Host Path                                                    | Container Path                  | Purpose                    |
|--------------------------------------------------------------|---------------------------------|----------------------------|
| `/home/jeeves/docker/splitpro/uploads`                       | `/app/uploads`                  | Receipt and document uploads |
| `/home/jeeves/docker/step-ca/config/certs/root_ca.crt`      | `/etc/ssl/certs/step-ca-root.crt` | Step-CA root trust injection |

### splitpro-db (PostgreSQL 17)

**Image:** `ossapps/postgres:17.7-trixie`

A PostgreSQL 17 image published by the SplitPro project (based on the
official `postgres:17` Debian image).

| Variable         | Value       |
|------------------|-------------|
| `POSTGRES_USER`  | `splitpro`  |
| `POSTGRES_DB`    | `splitpro`  |
| `POSTGRES_PASSWORD` | **REDACTED** |
| `POSTGRES_PORT`  | `5432`      |

**Bind mounts:**

| Host Path                           | Container Path             |
|-------------------------------------|----------------------------|
| `/home/jeeves/docker/splitpro/db`   | `/var/lib/postgresql/data` |

## Traefik Labels

```yaml
traefik.http.routers.splitpro-external.rule: Host(`splitpro.jeevesconsults.ca`)
traefik.http.routers.splitpro-external.entrypoints: websecure
traefik.http.routers.splitpro-external.tls.certresolver: letsencrypt
traefik.http.routers.splitpro-external.middlewares: plex-geoblock@file,crowdsec-bouncer@file
traefik.http.routers.splitpro-external.service: splitpro-svc
traefik.http.services.splitpro-svc.loadbalancer.server.port: 3000
```

## Notes / Gotchas

- `OIDC_ALLOW_DANGEROUS_EMAIL_LINKING: 1` allows Authentik OIDC logins to
  link to existing accounts by matching email address. Required if users were
  created before OIDC was enabled, or if local signup is still active.
- `NODE_EXTRA_CA_CERTS` injects the Step-CA root certificate into Node.js' TLS
  trust chain. This is required if SplitPro makes any HTTPS calls to internal
  `*.home.local` endpoints (e.g., if integrated with other internal services).
- `DATABASE_URL` in the container environment contains the PostgreSQL password
  in plaintext — treat this as sensitive.
- Currency rates are fetched from `api.frankfurter.app` (public, no API key
  required).

---
*Last Updated: 2026-06-17*