Parents get a real push notification when a kid checks off a task (false->true transitions only, fire-and-forget, degrades gracefully with no VAPID keys configured). Dashboard is a fully installable iOS/Android PWA; each child's kiosk link gets its own dynamic per-token manifest so "Add to Home Screen" opens straight into their board in standalone mode. Kiosk view is reworked for tablets: safe-area-aware full-bleed layout, the whole task row is now tappable (previously only the 24px checkbox was, well under Apple's touch-target minimum), and app icons are generated by a small dependency-free PNG encoder (no image tooling available in this environment). Push requires real HTTPS (iOS Safari won't allow it otherwise) - README and UNRAID.md cover VAPID setup and the HTTPS prerequisite.
178 lines
6.8 KiB
Markdown
178 lines
6.8 KiB
Markdown
# Running on Unraid
|
|
|
|
This app has no native/compiled dependencies (it uses Node's built-in
|
|
`node:sqlite`), so it builds and runs on Unraid's stock Docker exactly like
|
|
anywhere else. `docker-compose.unraid.yml` builds straight from the Gitea
|
|
repo — Docker/BuildKit clones it itself as part of the build, so you don't
|
|
need to check out the source on the array at all, and there's no deploy
|
|
key involved in this path.
|
|
|
|
## 1. Make the repo readable over HTTP
|
|
|
|
The compose file's `build.context` is a Git URL
|
|
(`https://git.oservr.com/ort/KCal.git#main`) — Docker fetches that itself
|
|
at build time. This is a read-only clone, same as any anonymous `git
|
|
clone`, so the repo needs to allow anonymous HTTP read access:
|
|
|
|
In Gitea: **repo → Settings → Visibility → Public** (save).
|
|
|
|
No token, no key, no extra permission grant — public visibility is
|
|
sufficient for a read-only clone.
|
|
|
|
## 2. Create the appdata data folder
|
|
|
|
```bash
|
|
mkdir -p /mnt/user/appdata/kids-calendar
|
|
```
|
|
|
|
This is where the SQLite database will live — the compose file
|
|
bind-mounts it in, instead of using a Docker-managed named volume, so it
|
|
shows up normally in Unraid's Docker tab and gets picked up by appdata
|
|
backup plugins (e.g. CA Backup/Restore) like any other app's data.
|
|
|
|
## 3. Deploy
|
|
|
|
### Via Compose Manager Plus (recommended)
|
|
|
|
1. Docker → Compose → **Add Stack**, name it `kids-calendar`.
|
|
2. In the **Compose** tab, paste:
|
|
|
|
```yaml
|
|
services:
|
|
kids-calendar:
|
|
build:
|
|
context: https://git.oservr.com/ort/KCal.git#main
|
|
dockerfile: Dockerfile
|
|
container_name: kids-calendar
|
|
ports:
|
|
- "3007:3007"
|
|
volumes:
|
|
- /mnt/user/appdata/kids-calendar:/app/data
|
|
environment:
|
|
- SESSION_SECRET=${SESSION_SECRET:?set a long random value in .env}
|
|
- COOKIE_SECURE=${COOKIE_SECURE:-false}
|
|
- DISABLE_PUBLIC_SIGNUP=${DISABLE_PUBLIC_SIGNUP:-false}
|
|
- VAPID_PUBLIC_KEY=${VAPID_PUBLIC_KEY:-}
|
|
- VAPID_PRIVATE_KEY=${VAPID_PRIVATE_KEY:-}
|
|
- VAPID_SUBJECT=${VAPID_SUBJECT:-}
|
|
restart: unless-stopped
|
|
```
|
|
|
|
3. In the **ENV** tab, set:
|
|
```
|
|
SESSION_SECRET=<output of: openssl rand -hex 32>
|
|
COOKIE_SECURE=false
|
|
DISABLE_PUBLIC_SIGNUP=false
|
|
```
|
|
Leave the three `VAPID_*` vars unset for now unless you're setting up
|
|
push notifications and already have real HTTPS in front of this stack —
|
|
see "Push notifications" below.
|
|
4. **Compose Up**. First run builds the image (a minute or so — it's
|
|
cloning the repo and running `npm install`), then the container starts
|
|
on port 3007.
|
|
|
|
### Via terminal (no plugin needed)
|
|
|
|
You only need the one compose file and a `.env` next to it — not a full
|
|
checkout, since Docker fetches the source itself:
|
|
|
|
```bash
|
|
mkdir -p /mnt/user/appdata/kids-calendar-src
|
|
cd /mnt/user/appdata/kids-calendar-src
|
|
curl -o docker-compose.unraid.yml \
|
|
https://git.oservr.com/ort/KCal/raw/branch/main/docker-compose.unraid.yml
|
|
cat > .env <<EOF
|
|
SESSION_SECRET=$(openssl rand -hex 32)
|
|
COOKIE_SECURE=false
|
|
DISABLE_PUBLIC_SIGNUP=false
|
|
VAPID_PUBLIC_KEY=
|
|
VAPID_PRIVATE_KEY=
|
|
VAPID_SUBJECT=
|
|
EOF
|
|
docker compose -f docker-compose.unraid.yml up -d --build
|
|
```
|
|
|
|
## 4. Use it
|
|
|
|
Open `http://<unraid-ip>:3007/signup.html`, create the first parent
|
|
account, invite your spouse, add your kids, build out calendars, and grab
|
|
each child's kiosk link from the dashboard for their tablet.
|
|
|
|
## Updating
|
|
|
|
Docker re-clones the repo's `main` branch fresh every time you build —
|
|
there's no separate `git pull` step. Just re-run the build:
|
|
|
|
- **Compose Manager Plus**: right-click the stack → **Update & Rebuild**
|
|
(or **Build & Up** if stopped).
|
|
- **Terminal**: `docker compose -f docker-compose.unraid.yml up -d --build`
|
|
from the folder in the terminal steps above.
|
|
|
|
Either way, your data in `/mnt/user/appdata/kids-calendar` is untouched.
|
|
|
|
## Prefer not to make the repo public?
|
|
|
|
If you'd rather keep `KCal` private, the alternative is authenticating the
|
|
git-context fetch with a Gitea access token instead of flipping visibility
|
|
— generate a read-only token in Gitea, then reference it via compose
|
|
variable substitution so it isn't hardcoded in the file itself:
|
|
|
|
```yaml
|
|
build:
|
|
context: https://${GITEA_USER}:${GITEA_TOKEN}@git.oservr.com/ort/KCal.git#main
|
|
```
|
|
with `GITEA_USER`/`GITEA_TOKEN` set in the stack's ENV tab (or `.env` for
|
|
the terminal path) instead of `SESSION_SECRET`'s neighbors above. Ask if
|
|
you want this wired up instead.
|
|
|
|
## Reverse proxy / access from outside your LAN
|
|
|
|
If you're exposing this beyond your home network (e.g. via Swag or Nginx
|
|
Proxy Manager, both common on Unraid) with a real HTTPS certificate:
|
|
|
|
- Point the proxy at `http://<unraid-ip>:3007` internally.
|
|
- Set `COOKIE_SECURE=true` (ENV tab, or `.env` for the terminal path) and
|
|
rebuild — otherwise login cookies won't be marked secure and some
|
|
browsers/proxies will refuse to send them back over HTTPS.
|
|
- Once your household(s) exist, consider setting
|
|
`DISABLE_PUBLIC_SIGNUP=true` so `/signup.html` stops accepting new
|
|
households.
|
|
|
|
This same real-HTTPS setup is also the prerequisite for push notifications
|
|
below — Swag and Nginx Proxy Manager both produce real Let's Encrypt certs
|
|
given a domain, so if you've already followed this section, you qualify.
|
|
|
|
## Push notifications
|
|
|
|
Optional: parents get a real push notification (not just the silent
|
|
polling-based update) when a kid checks off a task on the kiosk.
|
|
|
|
**Needs the real HTTPS from the section above already in place** — a
|
|
self-signed cert doesn't satisfy iOS, and plain `http://<unraid-ip>:3007`
|
|
won't work for this feature at all, even though the rest of the app is
|
|
fine over plain HTTP on your LAN.
|
|
|
|
Once HTTPS is confirmed working through your reverse proxy:
|
|
|
|
1. Generate a VAPID keypair — from the Unraid terminal:
|
|
`docker run --rm node:22-alpine npx web-push generate-vapid-keys`.
|
|
2. Set `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `VAPID_SUBJECT`
|
|
(`mailto:you@example.com`) in the stack's **ENV** tab (or `.env` for the
|
|
terminal path), then rebuild (**Update & Rebuild**, or
|
|
`docker compose -f docker-compose.unraid.yml up -d --build`).
|
|
3. On the dashboard (loaded through your HTTPS domain, not the bare
|
|
`http://<unraid-ip>:3007`), each parent clicks "Enable notifications on
|
|
this device" — per-device, so repeat on every phone/computer.
|
|
|
|
On iPhone/iPad, Safari only allows push for web apps added to the Home
|
|
Screen — tap Share → Add to Home Screen on the dashboard first, then open
|
|
the app icon and enable notifications from there. The dashboard explains
|
|
this in place if needed. Regenerating the VAPID keypair invalidates every
|
|
existing subscription, so treat it as a one-time setup step.
|
|
|
|
## Backups
|
|
|
|
Since data lives at `/mnt/user/appdata/kids-calendar` (a plain file, the
|
|
SQLite database), it's covered by whatever you already use to back up
|
|
`/mnt/user/appdata` — no special-casing needed.
|