Skip to content

About

Deploy your own simpleSuite backend and frontends with Docker Compose. Open-source, self-hostable, and privacy-first.

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Repository files navigation

simpleSuite logo

simpleSuite — Self-Hosting

Deploy your own simpleSuite backend and frontends with Docker Compose. Open-source, self-hostable, and privacy-first.

License Stars Issues


What is this?

This repo contains everything needed to self-host the simpleSuite ecosystem — a free, open-source alternative to hosted productivity and budgeting apps. Run your own Supabase-compatible backend (and optionally the frontends) on your own hardware with a single docker compose up.

Two deployment modes:


An Open-Source Alternative To

  • Supabase Cloud (managed)
  • Firebase
  • Appwrite
  • PocketBase
  • Hosted YNAB / Todoist / Notion backends

Supported Apps

App Frontend Repo Hosted URL
simpleBudget simplesuite/simplebudget budget.simplesuite.dev
simpleTracker simplesuite/simpletracker tracker.simplesuite.dev

Both apps share the same Supabase backend. A single self-hosted instance supports both.


Quick Start

# 1. Clone this repo
git clone https://github.com/simplesuite/simplesuite-selfhost.git
cd simplesuite-selfhost

# 2. Create and populate your environment file
cp deploy/.env.example deploy/.env
cd deploy && bash scripts/generate-secrets.sh && cd ..

# 3. Start the backend
docker compose -f deploy/compose.yml up -d

# 4. (Optional) Start with a frontend included
#    Set FRONTEND_APP in deploy/.env to: simplebudget or simpletracker
docker compose -f deploy/compose.yml -f deploy/compose.frontend.yml up -d

The API gateway will be available at http://localhost:8000.
The frontend (if enabled) will be at http://localhost:8080.


Prerequisites

Requirement Notes
Docker + Compose v2 docker compose version should return 2.x+
Bash shell Git Bash on Windows; native on macOS/Linux
openssl, base64 Required by the secret generator script

Windows users: Run all bash commands from Git Bash, not PowerShell or CMD.


Backend-Only Setup

Run your own Supabase-compatible backend while using the hosted frontends.

cp deploy/.env.example deploy/.env
cd deploy && bash scripts/generate-secrets.sh && cd ..
docker compose -f deploy/compose.yml up -d

Verify everything is healthy:

docker compose -f deploy/compose.yml ps

Then open the hosted frontend and use the Config Backend page to enter:

  • URL: http://localhost:8000 (or your server's address)
  • Anon Key: The ANON_KEY value from deploy/.env

This works for both simpleBudget and simpleTracker — they share the same backend.


Full Self-Hosting

Run the entire stack — backend and frontend — on your own machine.

cp deploy/.env.example deploy/.env
cd deploy && bash scripts/generate-secrets.sh && cd ..

# Edit deploy/.env to set which app to deploy:
#   FRONTEND_APP=simplebudget   (default)
#   FRONTEND_APP=simpletracker

docker compose -f deploy/compose.yml -f deploy/compose.frontend.yml up -d

Open http://localhost:8080 in your browser.

The frontend container clones the latest source from the selected app's repo, builds it, and serves it via Caddy. The config.js is auto-generated from your .env values at container startup — no manual configuration needed.

Hosting Both Frontends

To self-host both apps simultaneously, use the all-frontends compose file:

docker compose -f deploy/compose.yml -f deploy/compose.allfrontends.yml up -d

This starts:


Environment Variables

All config lives in deploy/.env. Run generate-secrets.sh to auto-fill secrets.

Variable Default Scope Description
SUPABASE_PUBLIC_URL http://localhost:8000 Public Kong API gateway URL (browser-accessible)
ANON_KEY (generated) Public Browser-safe JWT for unauthenticated API access
SERVICE_ROLE_KEY (generated) Private Elevated JWT — bypasses RLS
JWT_SECRET (generated) Private Signs all JWTs
POSTGRES_PASSWORD (generated) Private Database password
DASHBOARD_USERNAME admin Optional Studio dashboard username
DASHBOARD_PASSWORD (generated) Optional Studio dashboard password
VAPID_PUBLIC_KEY (empty) Push Web Push public key (injected into frontend)
VAPID_PRIVATE_KEY (empty) Private/Push Web Push private key (used by notify worker)
VAPID_SUBJECT mailto:admin@example.com Push Contact email for push service operators
CHECK_INTERVAL_MS 900000 Push How often the worker checks for due items (ms)
FRONTEND_APP simplebudget Frontend Which app to build: simplebudget or simpletracker
FRONTEND_PORT 8080 Frontend Port for single-app mode (compose.frontend.yml)
SIMPLEBUDGET_PORT 8080 Frontend simpleBudget port for both-apps mode (compose.allfrontends.yml)
SIMPLETRACKER_PORT 8081 Frontend simpleTracker port for both-apps mode (compose.allfrontends.yml)

Security

Safe for browsers Never expose
SUPABASE_PUBLIC_URL SERVICE_ROLE_KEY
ANON_KEY JWT_SECRET
VAPID_PUBLIC_KEY VAPID_PRIVATE_KEY
POSTGRES_PASSWORD
  • deploy/.env is in .gitignore — never commit it.
  • The frontend container only receives SUPABASE_PUBLIC_URL and ANON_KEY.

Database Access

Connect with pgAdmin or any Postgres client:

Setting Value
Host localhost
Port 5432
Database postgres
Username supabase_admin
Password Your POSTGRES_PASSWORD

Updating

git pull origin main

# Backend-only
docker compose -f deploy/compose.yml down
docker compose -f deploy/compose.yml up -d

# Full stack (rebuilds frontend with latest source)
docker compose -f deploy/compose.yml -f deploy/compose.frontend.yml down
docker compose -f deploy/compose.yml -f deploy/compose.frontend.yml up -d --build

Migrations run automatically on every startup.


Remote Access with Tailscale

The simplest way to access your instance from other devices — no port forwarding, no reverse proxy, automatic HTTPS.

tailscale serve 8000          # Expose API gateway
tailscale serve --https 8080  # Expose frontend

Update SUPABASE_PUBLIC_URL in deploy/.env to your Tailscale URL and restart.


Push Notifications (Optional)

Send push reminders to users' devices — even when the app isn't open. The notification worker checks for due tasks (simpleTracker) and upcoming transactions (simpleBudget) on a schedule and delivers Web Push notifications to subscribed devices.

How It Works

  1. Users toggle "Notifications" in the app settings → browser subscribes to push and stores credentials in the push_subscriptions table.
  2. The notify-worker container runs every 15 minutes (configurable), queries PostgREST for due/overdue items, and sends Web Push to all active subscriptions.
  3. The Service Worker in each app receives the push and shows a native notification — works on desktop and mobile, even when the app tab is closed.

Setup

VAPID keys are generated automatically by the generate-secrets.sh script (the same one that creates your JWT and database secrets). If you've already run it before adding push support, just run it again — it only fills in missing values:

cd deploy && bash scripts/generate-secrets.sh && cd ..

Verify the keys were added to your deploy/.env:

grep VAPID deploy/.env

Then restart the stack:

docker compose -f deploy/compose.yml down
docker compose -f deploy/compose.yml up -d --build

The notify-worker service starts automatically alongside the rest of the backend. The VAPID public key is injected into the frontend's config.js at container startup.

Configuration

Variable Default Description
VAPID_PUBLIC_KEY (empty — push disabled) Public key shared with browsers
VAPID_PRIVATE_KEY (empty) Private key for signing push messages
VAPID_SUBJECT mailto:admin@example.com Contact URI for push service operators
CHECK_INTERVAL_MS 900000 (15 min) How often the worker checks for due items

Note: If VAPID_PUBLIC_KEY or VAPID_PRIVATE_KEY are not set, the notify worker will exit on startup with an error message. Push notifications are fully opt-in — the rest of the stack works fine without them.

What Gets Notified

App Trigger Notification
simpleTracker Tasks due today or overdue "2 Task Reminders — 1 overdue, 1 due today"
simpleBudget Transactions scheduled for tomorrow "Transaction Reminder — Tomorrow: Rent ($1500.00)"

For Supabase Cloud Users

The same worker can run against Supabase Cloud — just point the env vars at your project:

POSTGREST_URL=https://yourproject.supabase.co/rest/v1
SERVICE_ROLE_KEY=your-service-role-key
VAPID_PUBLIC_KEY=...
VAPID_PRIVATE_KEY=...

You can run the worker as a standalone container, a cron job, or on any serverless platform that supports scheduled execution.

Disabling Push Notifications

Simply remove (or leave empty) the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY from your .env. The worker won't start, and the frontends won't show the push subscription option to users.


Troubleshooting

Postgres won't start
docker compose -f deploy/compose.yml logs postgres

Ensure POSTGRES_PASSWORD is set. To reset completely:

docker compose -f deploy/compose.yml down -v
docker compose -f deploy/compose.yml up -d
Migration errors
docker compose -f deploy/compose.yml logs migrations

To re-run from scratch (destroys data):

docker compose -f deploy/compose.yml down -v
docker compose -f deploy/compose.yml up -d
GoTrue (auth) fails
docker compose -f deploy/compose.yml logs gotrue

Usually caused by role passwords not being set. Fix with a full reset:

docker compose -f deploy/compose.yml down -v
docker compose -f deploy/compose.yml up -d
CORS errors in browser

Handled by the Kong CORS plugin in deploy/kong.yml. If a header is blocked, add it to the headers list and restart:

docker compose -f deploy/compose.yml restart kong
Complete reset
docker compose -f deploy/compose.yml down -v
rm deploy/.env
cp deploy/.env.example deploy/.env
cd deploy && bash scripts/generate-secrets.sh && cd ..
docker compose -f deploy/compose.yml up -d
Notify worker not sending notifications
docker compose -f deploy/compose.yml logs notify-worker

Common causes:

  • VAPID keys not set — the worker exits immediately with "Missing required env var" message. Generate keys with npx web-push generate-vapid-keys.
  • No subscriptions in database — users need to enable notifications in the app settings first.
  • PostgREST not reachable — ensure the worker can reach http://postgrest:3000 (default internal URL).
  • Expired subscriptions — the worker automatically removes 410/404 subscriptions. If all subscriptions are expired, no notifications will be sent.

Check subscription count:

docker compose -f deploy/compose.yml exec postgres psql -U postgres -c "SELECT app, count(*) FROM push_subscriptions GROUP BY app;"

Architecture

                    ┌─────────────────────────────────────────┐
                    │            Docker Compose                │
                    │                                         │
 Browser ──────────►│  Kong :8000 (API Gateway)               │
                    │    ├── /rest/v1/* → PostgREST :3000      │
                    │    └── /auth/v1/* → GoTrue :9999         │
                    │                                         │
                    │  Postgres :5432                          │
                    │  Migrations (runs once at startup)       │
                    │                                         │
                    │  notify-worker (every 15min)             │
                    │    └── PostgREST → Web Push delivery     │
                    │                                         │
                    │  Frontend :8080 (optional, Caddy)        │
                    └─────────────────────────────────────────┘

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GNU AGPL v3.

About

Deploy your own simpleSuite backend and frontends with Docker Compose. Open-source, self-hostable, and privacy-first.

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

Languages