From 2f309b96fc50e327caae14dcda0b55e2e514f62b Mon Sep 17 00:00:00 2001 From: BookJJun-IJ Date: Mon, 13 Apr 2026 22:22:32 +0900 Subject: [PATCH 1/3] update Spliit expense sharing app --- Apps/Spliit/docker-compose.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Apps/Spliit/docker-compose.yml b/Apps/Spliit/docker-compose.yml index 903c60b..6465fa2 100644 --- a/Apps/Spliit/docker-compose.yml +++ b/Apps/Spliit/docker-compose.yml @@ -37,9 +37,10 @@ services: - NET_ADMIN db: - image: postgres:16-alpine + image: postgres:16.13-alpine container_name: spliit-db user: 0:0 + cpu_shares: 50 environment: POSTGRES_DB: spliit POSTGRES_USER: postgres @@ -56,9 +57,11 @@ services: memory: 512M spliit: - image: ghcr.io/spliit-app/spliit:1.19.0 + image: ghcr.io/spliit-app/spliit:1.19.1 container_name: spliit restart: unless-stopped + user: "0:0" + cpu_shares: 50 environment: TZ: $TZ POSTGRES_PRISMA_URL: postgresql://postgres:$APP_DEFAULT_PASSWORD@db:5432/spliit From 0dbe02b9943d2e30b632a39d0b40120711841845 Mon Sep 17 00:00:00 2001 From: BookJJun-IJ Date: Mon, 8 Jun 2026 17:52:13 +0900 Subject: [PATCH 2/3] fix spliit and add rationale.md --- Apps/Spliit/docker-compose.yml | 15 ++++----------- Apps/Spliit/rationale.md | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 11 deletions(-) create mode 100644 Apps/Spliit/rationale.md diff --git a/Apps/Spliit/docker-compose.yml b/Apps/Spliit/docker-compose.yml index 6465fa2..73eb72d 100644 --- a/Apps/Spliit/docker-compose.yml +++ b/Apps/Spliit/docker-compose.yml @@ -1,10 +1,10 @@ name: spliit services: nginxhashlock: - image: ghcr.io/yundera/nginx-hash-lock:latest + image: ghcr.io/yundera/nginx-hash-lock:1.0.7 container_name: spliit-nginxhashlock restart: unless-stopped - user: "root" + user: "0:0" environment: AUTH_HASH: $AUTH_HASH BACKEND_HOST: "spliit" @@ -31,15 +31,11 @@ services: cpu_shares: 80 networks: - pcs - privileged: true - cap_add: - - SYS_ADMIN - - NET_ADMIN db: image: postgres:16.13-alpine container_name: spliit-db - user: 0:0 + user: "0:0" cpu_shares: 50 environment: POSTGRES_DB: spliit @@ -57,7 +53,7 @@ services: memory: 512M spliit: - image: ghcr.io/spliit-app/spliit:1.19.1 + image: ghcr.io/spliit-app/spliit:1.19.0 container_name: spliit restart: unless-stopped user: "0:0" @@ -68,9 +64,6 @@ services: POSTGRES_URL_NON_POOLING: postgresql://postgres:$APP_DEFAULT_PASSWORD@db:5432/spliit networks: - pcs - cap_add: - - SYS_ADMIN - - NET_ADMIN deploy: resources: limits: diff --git a/Apps/Spliit/rationale.md b/Apps/Spliit/rationale.md new file mode 100644 index 0000000..f83f8bc --- /dev/null +++ b/Apps/Spliit/rationale.md @@ -0,0 +1,23 @@ +# Spliit — Rationale + +## What deviation / exception is being requested +All three services run as `user: 0:0` (root). The nginx-hash-lock sidecar gates web access with a hash-based authentication layer. + +## Why it is necessary +- **spliit**: The Node.js application runs Prisma database migrations on startup, which requires write access to the working directory. Running as non-root causes migration failures. +- **db (PostgreSQL)**: Requires root for database initialization and file ownership in `/var/lib/postgresql/data`. Standard practice for PostgreSQL containers. +- **nginxhashlock**: The nginx-hash-lock sidecar needs root to bind to port 80 and configure nginx. + +## Security mitigations in place +- All volumes map exclusively to `/DATA/AppData/$AppID/` — no access to user directories +- No privileged mode on any service +- Memory limits on all services (128M nginx, 512M db, 1G app) +- Web access gated by nginx-hash-lock sidecar (hash-based authentication) +- Database credentials use `$APP_DEFAULT_PASSWORD` (not hardcoded) + +## Alternatives considered and rejected +- `user: $PUID:$PGID` — Prisma migrations fail without root; PostgreSQL init requires root for data directory ownership + +## Data protection +- PostgreSQL data persists in `/DATA/AppData/$AppID/pgdata/` +- Data survives uninstall/reinstall From 991335f8eb923c17c0088efcd6e74801a9b79201 Mon Sep 17 00:00:00 2001 From: BookJJun-IJ Date: Thu, 30 Jul 2026 15:08:16 +0900 Subject: [PATCH 3/3] update spliit --- Apps/Spliit/docker-compose.yml | 60 ++++++++++++---------------------- Apps/Spliit/rationale.md | 11 ++++--- 2 files changed, 28 insertions(+), 43 deletions(-) diff --git a/Apps/Spliit/docker-compose.yml b/Apps/Spliit/docker-compose.yml index 73eb72d..1b6b9ef 100644 --- a/Apps/Spliit/docker-compose.yml +++ b/Apps/Spliit/docker-compose.yml @@ -1,37 +1,5 @@ name: spliit services: - nginxhashlock: - image: ghcr.io/yundera/nginx-hash-lock:1.0.7 - container_name: spliit-nginxhashlock - restart: unless-stopped - user: "0:0" - environment: - AUTH_HASH: $AUTH_HASH - BACKEND_HOST: "spliit" - BACKEND_PORT: "3000" - LISTEN_PORT: "80" - expose: - - 80 - labels: - caddy_0: spliit-${APP_DOMAIN} - caddy_0.import: gateway_tls - caddy_0.reverse_proxy: "{{upstreams 80}}" - caddy_1: spliit-${APP_PUBLIC_IP_DASH}.nip.io - caddy_1.import: gateway_tls - caddy_1.reverse_proxy: "{{upstreams 80}}" - caddy_2: spliit-${APP_PUBLIC_IP_DASH}.sslip.io - caddy_2.reverse_proxy: "{{upstreams 80}}" - depends_on: - - spliit - - db - deploy: - resources: - limits: - memory: 128M - cpu_shares: 80 - networks: - - pcs - db: image: postgres:16.13-alpine container_name: spliit-db @@ -58,10 +26,24 @@ services: restart: unless-stopped user: "0:0" cpu_shares: 50 + expose: + - 80 + labels: + caddy_0: spliit-${APP_DOMAIN} + caddy_0.import: gateway_tls + caddy_0.reverse_proxy: "{{upstreams 80}}" + caddy_1: spliit-${APP_PUBLIC_IP_DASH}.nip.io + caddy_1.import: gateway_tls + caddy_1.reverse_proxy: "{{upstreams 80}}" + caddy_2: spliit-${APP_PUBLIC_IP_DASH}.sslip.io + caddy_2.reverse_proxy: "{{upstreams 80}}" environment: + PORT: "80" TZ: $TZ POSTGRES_PRISMA_URL: postgresql://postgres:$APP_DEFAULT_PASSWORD@db:5432/spliit POSTGRES_URL_NON_POOLING: postgresql://postgres:$APP_DEFAULT_PASSWORD@db:5432/spliit + depends_on: + - db networks: - pcs deploy: @@ -78,7 +60,7 @@ x-casaos: architectures: - amd64 - arm64 - main: nginxhashlock + main: spliit webui_port: 80 author: Yundera Team category: Finance @@ -89,8 +71,8 @@ x-casaos: - https://cdn.jsdelivr.net/gh/Yundera/AppStore@main/Apps/Spliit/screenshot-2.png - https://cdn.jsdelivr.net/gh/Yundera/AppStore@main/Apps/Spliit/screenshot-3.png thumbnail: https://cdn.jsdelivr.net/gh/Yundera/AppStore@main/Apps/Spliit/thumbnail.png - index: /?hash=$AUTH_HASH - store_app_id: Spliit + index: / + store_app_id: spliit title: en_us: Spliit tagline: @@ -102,7 +84,7 @@ x-casaos: description: en_us: | Split expenses with friends - no signup, no hassle. Spliit is the simplest way to share expenses. Whether splitting dinner bills, vacation costs, or household expenses, everyone can see who owes what instantly. No accounts needed - just create a group and share the link. - + **Key features:** • Create expense groups in seconds • Add participants by name only @@ -110,7 +92,7 @@ x-casaos: • See optimized settlements (who pays whom) • Works on any device • Complete privacy - data stays on your server - + **Perfect for:** Roommates splitting rent, friends sharing vacation costs, couples managing household expenses, group dinners, or any shared activity. ko_kr: | 친구와 비용 분할 - 가입 없이, 번거로움 없이. Spliit은 비용을 공유하는 가장 간단한 방법입니다. 저녁 식사비, 휴가 비용, 가계 지출 등 누가 얼마를 빚졌는지 즉시 확인할 수 있습니다. @@ -130,7 +112,7 @@ x-casaos: 3. Add people (just their names) 4. Start adding expenses 5. Check "Balances" to see who owes whom - ----------------------------- + ----------------------------- Share the group link with friends - no signup needed! ko_kr: | ----------------------------- @@ -167,4 +149,4 @@ x-casaos: 3. Ajoutez des personnes (juste les noms) 4. Commencez à ajouter des dépenses 5. Vérifiez "Soldes" pour voir qui doit à qui - ----------------------------- \ No newline at end of file + ----------------------------- diff --git a/Apps/Spliit/rationale.md b/Apps/Spliit/rationale.md index f83f8bc..bc3d67b 100644 --- a/Apps/Spliit/rationale.md +++ b/Apps/Spliit/rationale.md @@ -1,22 +1,25 @@ # Spliit — Rationale ## What deviation / exception is being requested -All three services run as `user: 0:0` (root). The nginx-hash-lock sidecar gates web access with a hash-based authentication layer. +1. Both services run as `user: 0:0` (root). +2. Authentication is disabled — the app is publicly accessible without login. ## Why it is necessary - **spliit**: The Node.js application runs Prisma database migrations on startup, which requires write access to the working directory. Running as non-root causes migration failures. - **db (PostgreSQL)**: Requires root for database initialization and file ownership in `/var/lib/postgresql/data`. Standard practice for PostgreSQL containers. -- **nginxhashlock**: The nginx-hash-lock sidecar needs root to bind to port 80 and configure nginx. +- **No authentication**: Spliit is a collaborative expense-sharing app. Users create groups and share links with friends/family who need direct access without any account. Adding an authentication gate would break the core functionality — external participants would be unable to view or add expenses. ## Security mitigations in place - All volumes map exclusively to `/DATA/AppData/$AppID/` — no access to user directories - No privileged mode on any service -- Memory limits on all services (128M nginx, 512M db, 1G app) -- Web access gated by nginx-hash-lock sidecar (hash-based authentication) +- Memory limits on all services (512M db, 1G app) - Database credentials use `$APP_DEFAULT_PASSWORD` (not hardcoded) +- No sensitive data exposed — the app only handles expense group data +- Each group has a unique random URL that acts as a capability-based access control ## Alternatives considered and rejected - `user: $PUID:$PGID` — Prisma migrations fail without root; PostgreSQL init requires root for data directory ownership +- AppShield / nginx-hash-lock authentication — blocks external participants from accessing shared expense groups, breaking the app's core use case ## Data protection - PostgreSQL data persists in `/DATA/AppData/$AppID/pgdata/`