Installing and Configuring SplitPro as a Docker Container on Raspberry Pi

SplitPro is an open-source, self-hosted alternative to Splitwise, designed for tracking and splitting expenses with friends, flatmates or family without handing your data over to third-party services. The project is fully open source, built with Next.js, and can be installed very easily using Docker.

Feature overview:

  • Individual (with one friend) or group expense management
  • Several ways to split: equally, by percentage, by shares, by exact amount, manual adjustments and settlements
  • Categories, multiple currencies, dates and attachments (receipts) for each expense
  • Support for negative expenses, useful for refunds and corrections
  • PWA app, installable on smartphones, with push notification support
  • Activity feed, including edits and deletions
  • Detailed balances, both per person and per group
  • Automatic currency conversion
  • Import friends and groups from Splitwise
  • Recurring expenses (requires the Postgres pg_cron extension)
  • Authentication via email (magic link), Google OAuth or an OIDC provider (Authentik, Keycloak, etc.)

You can find more information here (official website) or here (the project’s GitHub repository).

With that said, to install SplitPro as a Docker container you will of course need:

  • A Raspberry Pi (or any Linux host/NAS);
  • Docker and Docker Compose installed (here is a guide to installing it on a Raspberry Pi);
  • A DDNS hostname or a public IP address (for remote access);

With that said, create a folder that will contain the compose.yml file needed to create and configure our containers.

mkdir splitpro
cd splitpro
nano compose.yml

and enter the following (the official configuration recommended by the project, with Postgres already set up for recurring expenses thanks to pg_cron):

name: split-pro-prod

services:
  postgres:
    image: ossapps/postgres:17.7-trixie
    container_name: ${POSTGRES_CONTAINER_NAME:-splitpro-db}
    restart: always
    environment:
      - POSTGRES_USER=${POSTGRES_USER:?err}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?err}
      - POSTGRES_DB=${POSTGRES_DB:?err}
      - POSTGRES_PORT=${POSTGRES_PORT:-5432}
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
      interval: 10s
      timeout: 5s
      retries: 5
    command: >
      postgres
      -c shared_preload_libraries=pg_cron
      -c cron.database_name=${POSTGRES_DB:-splitpro}
      -c cron.timezone=UTC
    env_file: .env
    volumes:
      - database:/var/lib/postgresql/data

  splitpro:
    image: ossapps/splitpro:latest
    container_name: splitpro
    restart: always
    ports:
      - ${PORT:-3000}:${PORT:-3000}
    environment:
      - PORT=${PORT:-3000}
      # - HOSTNAME=0.0.0.0 # da scommentare se si utilizza un reverse proxy (es. NGINX Proxy Manager) tramite rete Docker interna
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - uploads:/app/uploads

volumes:
  database:
  uploads:

Once you have pasted the text, close the file by pressing CTRL+X, then type Y (or S, depending on your system language) and finally press ENTER to confirm.

As you can see, the compose.yml file refers to several environment variables that we will define in a .env file, so let’s create it:

nano .env

and enter the following, replacing the highlighted values with your own:

# Nome del container e credenziali del database Postgres
POSTGRES_CONTAINER_NAME=splitpro-db
POSTGRES_USER=postgres
POSTGRES_PASSWORD=una-password-sicura
POSTGRES_DB=splitpro
POSTGRES_PORT=5432
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@splitpro-db:5432/${POSTGRES_DB}

# Porta sulla quale verrĂ  pubblicata l'applicazione
PORT=3000

# Next Auth: chiave segreta utilizzata per firmare le sessioni
NEXTAUTH_SECRET=chiave-generata-con-openssl
NEXTAUTH_URL=http://IP-DEL-TUO-SERVER:3000

# Inviti e registrazione
ENABLE_SENDING_INVITES=false
DISABLE_EMAIL_SIGNUP=false

The NEXTAUTH_SECRET variable must be a secure random string: you can easily generate one from the terminal with the command:

openssl rand -base64 32

The NEXTAUTH_URL value, on the other hand, must match the address (IP or domain) you will use to reach SplitPro, including the port if you are not using a reverse proxy.

Configuring authentication

SplitPro does not offer a traditional username and password login: you need to configure at least one of the following sign-in methods by adding the relevant variables to the .env file:

  • Email (magic link), via an SMTP server: FROM_EMAIL, EMAIL_SERVER_HOST, EMAIL_SERVER_PORT, EMAIL_SERVER_USER, EMAIL_SERVER_PASSWORD
  • Google OAuth: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
  • OIDC (Authentik, Keycloak or a generic provider): AUTHENTIK_ID/AUTHENTIK_SECRET/AUTHENTIK_ISSUER, or the equivalent variables for Keycloak or a custom OIDC provider

Another optional feature is push notifications (required for the PWA app): to enable them, generate a pair of VAPID keys with the command

npx web-push generate-vapid-keys --json

and enter the resulting values in the WEB_PUSH_PUBLIC_KEY, WEB_PUSH_PRIVATE_KEY and WEB_PUSH_EMAIL variables (the latter is simply a contact email address required by the Web Push standard).

All the optional variables (including those for bank account integration via GoCardless or Plaid) are listed and documented in the .env.example file in the official repository.

Once you have finished editing the .env file, close it by pressing CTRL+X, then type Y (or S, depending on your system language) and finally press ENTER to confirm.

Now all that’s left is to bring up the containers with the following command:

docker compose up -d

The command downloads the official ossapps/postgres and ossapps/splitpro images and starts the two containers: thanks to the service_healthy condition set in compose.yml, SplitPro automatically waits for the Postgres database to be ready before starting.

You can check that everything has started correctly by viewing the logs with:

docker compose logs -f splitpro

wait a few seconds, then open your preferred web browser and type the following in the address bar:

http://[IP-DEL-TUO-SERVER]:3000

then sign in using the authentication method you configured earlier (email or Google), creating your first account.

To make this service accessible from outside your network, you need to forward, for example, external TCP port 443 to your server’s (LAN) IP on TCP port 3000. In addition, if your ISP (Internet Service Provider) gives you a dynamic IP, make sure you have configured DDNS (here is a guide to enabling and configuring it with DuckDNS), or that you have a static IP address with a registered domain name.

To expose SplitPro over HTTPS, I recommend installing and configuring NGINX Proxy Manager (here is a guide to installing it as a Docker container), connecting SplitPro to the same Docker network as the proxy and remembering to uncomment the HOSTNAME=0.0.0.0 line in compose.yml so that the service is also reachable through Docker’s internal network.

Enjoy!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top