- HTML 57.5%
- JavaScript 42.3%
- Dockerfile 0.2%
Replace the hardcoded STACK_ID "15" / ENDPOINT_ID "3" with secrets.PORTAINER_STACK_ID / secrets.PORTAINER_ENDPOINT_ID, so the deploy target isn't baked into the workflow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .forgejo/workflows | ||
| public | ||
| server | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
Claude Family Chat
A self-hosted chat app that lets your family share access to Claude — each person gets their own private conversation history. Your API key stays on the server.
Quick Start
1. Get an API key
Sign up at console.anthropic.com and create an API key.
2. Edit docker-compose.yml
Open docker-compose.yml and fill in:
ANTHROPIC_API_KEY: "sk-ant-your-actual-key"
USERS: '{"alice":"password1","bob":"password2"}'
SESSION_SECRET: "any-long-random-string"
3. Run it
docker compose up -d
The app is now running at http://localhost:3000
On your home network, other devices can reach it at http://YOUR-LOCAL-IP:3000
(Find your IP with ipconfig on Windows or ifconfig / ip addr on Mac/Linux)
The Admin Page
Admins get a dedicated page at /admin (a ⚙ Admin link appears in the
sidebar). From there you can, without ever editing the deploy or restarting:
- Manage users — add a user directly (username + temporary password), or
generate a one-time invite link (
/join?token=…) the new person opens to set their own password. Delete users and grant/revoke admin. - View usage & cost — per-user token usage and per–group-chat usage (group chats are tracked separately), with period filters and cost estimates.
- Manage shared chats — create, edit (title / members / prompt), and delete.
- Edit configuration — the default system prompt, model, max-history, and the Anthropic & Brave API keys (masked, with reveal). Changes take effect immediately.
Everything here is stored in the SQLite database (/data/app.db).
Managing Users
Users and the admin flag are stored in a small SQLite database (/data/app.db),
with passwords hashed (scrypt) — they're never stored in plaintext. Day-to-day
user management happens on the Admin Page; the environment
variables below are only used to bootstrap an empty database on first run.
First run: set USERS and ADMIN_USER so the first accounts (including your
admin) exist. On the very first boot with an empty database, these are imported
automatically:
USERS: '{"mom":"secure-pass","dad":"another-pass","kid1":"their-pass"}'
ADMIN_USER: 'mom'
After the first boot the database is the source of truth — changes to
USERS / ADMIN_USER are ignored once any user exists. Manage users from the
Admin Page instead. (To re-seed from scratch, wipe the data volume with
docker compose down -v.)
Environment Variables
Most settings now live in the database and are edited on the Admin Page.
The variables below seed the database on first boot only (when their value
isn't set in the DB yet); afterward the DB wins and the admin page is where you
change them. Only the infrastructure variables (SESSION_SECRET, DB_FILE,
PORT) are read from the environment on every boot.
| Variable | Default | Description |
|---|---|---|
ANTHROPIC_API_KEY |
(required first boot) | Your Anthropic API key. Seeds the DB, then editable on the Admin Page |
USERS |
{} |
JSON object of username→password pairs. First boot only — ignored once any user exists |
ADMIN_USER |
(none) | Username to mark as admin when seeding. First boot only |
BRAVE_API_KEY |
(none) | Brave Search API key (enables web search). Seeds the DB, then editable on the Admin Page |
CLAUDE_MODEL |
claude-sonnet-4-6 |
Default model. Seeds the DB, then editable on the Admin Page |
MAX_HISTORY |
100 |
Max messages kept per chat. Seeds the DB, then editable on the Admin Page |
SYSTEM_PROMPT |
(helpful-assistant prompt with tool guidance) | Default system prompt. Seeds the DB, then editable on the Admin Page |
SESSION_SECRET |
change-me-in-production |
Secret for signing session cookies — change this! Read from env every boot |
DB_FILE |
/data/app.db |
Path to the SQLite database. Read from env every boot |
PORT |
3000 |
Port the server listens on. Read from env every boot |
Data & Privacy
- Conversation histories are saved in a Docker volume (
chat-data) — they persist across restarts - User accounts and runtime config (API keys, system prompt, model) live in a SQLite database (
/data/app.db) on the same volume; passwords are hashed (scrypt), never stored in plaintext - Each user's history is completely isolated from other users
- Your API key is only on the server; it's never sent to the browser (admins can reveal it on the Admin Page)
- To wipe all history and accounts:
docker compose down -v(deletes the volume)
Monitoring Costs
Keep an eye on your API usage at console.anthropic.com/usage. Set a spending limit under Settings → Limits to avoid surprises.
Updating
docker compose pull # if using a registry image
docker compose up -d --build
Running on a Raspberry Pi or Home Server
Works great on any always-on machine. Just open port 3000 in your firewall/router if you want access outside your home network (consider adding HTTPS via a reverse proxy like Caddy or nginx in that case).