Bumps the npm_and_yarn group with 1 update in the / directory: [turbo](https://github.com/vercel/turborepo). Updates `turbo` from 2.9.1 to 2.9.14 - [Release notes](https://github.com/vercel/turborepo/releases) - [Changelog](https://github.com/vercel/turborepo/blob/main/RELEASE.md) - [Commits](https://github.com/vercel/turborepo/compare/v2.9.1...v2.9.14) --- updated-dependencies: - dependency-name: turbo dependency-version: 2.9.14 dependency-type: direct:development dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <support@github.com>
Stoat Admin
Stoat Admin is a lightweight self-hosted moderation and invite dashboard for a Stoat chat instance. It runs as a separate Podman Compose stack, joins the Stoat network to talk to MongoDB directly, and now ships with a dedicated admin-proxy Caddy service that terminates HTTPS for the admin stack with Caddy's internal CA.
Features
- Single-admin login with Argon2id password hashing and SQLite-backed sessions
- Invite creation, revocation, and acceptance tracking
- User listing, lookup, ban, unban, and scheduled deletion actions
- Dashboard stats for users, pending invites, and recent bans
pnpmworkspace with Turborepo coordinating cross-package tasks- Example Podman Compose, s6 service directories, and GitHub Actions workflows
Project Layout
.
├── api/ # Express + TypeScript backend
├── proxy/ # Caddy + Coraza reverse proxy image
├── web/ # Vite + React frontend and static image build
├── deploy/s6/ # Example s6 service directories and systemd unit
├── compose.yml # Production-oriented compose file
├── compose.override.example.yml
├── docs/ # Design and task references
└── .env.example
Admin Setup
To create the admin user, run this command inside the admin container
node dist/seed.js --username admin --password <your-password>
Prerequisites
- Node 22+
pnpmvia Corepack- Turborepo is installed through the workspace dependencies
- A Stoat deployment with MongoDB reachable on the shared container network
invite_only = truein Stoat'sRevolt.toml- Podman or Docker-compatible compose support
- A hostname for the admin dashboard that resolves on your WireGuard/private network
- A way to trust Caddy's internal root CA on the admin devices that will access the dashboard
Quick Start
- Enable
pnpm:
corepack enable
- Install dependencies:
pnpm install
- Copy the environment template and fill in the real values:
cp .env.example .env
- Seed the admin account from the root workspace:
pnpm seed -- --username admin --password '<strong-password>'
- Run both packages together through Turborepo:
pnpm dev
Useful targeted variants:
pnpm dev:api
pnpm dev:web
Configuration
| Variable | Description |
|---|---|
MONGODB |
MongoDB connection string for the Stoat database |
RESEND_API_KEY |
Resend API key for invite delivery |
RESEND_FROM_EMAIL |
Sender address for invite messages |
SESSION_SECRET |
Express session signing secret |
INSTANCE_URL |
Public Stoat URL used in invite links |
INSTANCE_NAME |
Human-readable instance name used in copy |
ADMIN_API_PORT |
Listen port for admin-api |
ADMIN_WEB_ORIGIN |
Exact HTTPS browser origin allowed by CORS |
ADMIN_HOSTNAME |
Hostname served by the dedicated Caddy proxy |
ADMIN_BIND_IP |
Compose bind IP for the proxy's published ports |
ADMIN_HTTP_PORT |
Published HTTP port for redirect handling |
ADMIN_HTTPS_PORT |
Published HTTPS port for the admin dashboard |
ADMIN_WEB_API_URL |
Optional frontend API override outside compose |
Deployment
The repo ships with a standalone compose.yml that expects an external stoat_default network. Update the network name if your Stoat stack uses a different one.
For local compose use, the proxy defaults to https://localhost:9443 and http://localhost:9080. For deployed hosts, set ADMIN_HOSTNAME to the real admin name and switch ADMIN_HTTP_PORT/ADMIN_HTTPS_PORT to 80/443 or use compose.override.example.yml as a starting point.
The deployment topology is:
admin-proxyis built from proxy/Dockerfile, publishes the configured HTTP and HTTPS ports, issues a private certificate from Caddy's internal CA, applies Coraza, and reverse-proxies/api/*toadmin-apiand everything else toadmin-web.admin-webandadmin-apiare no longer published directly on the host.admin-webserves the built Vite bundle privately on the admin network.admin-apistays attached to the shared Stoat network for MongoDB access and also joins a private admin network used by the proxy.
Before starting the stack, point ADMIN_HOSTNAME at the host running admin-proxy on your WireGuard/private network and set ADMIN_WEB_ORIGIN to https://<that-hostname>.
After the proxy has started once, install Caddy's root CA on each admin device before browsing to the dashboard. One way to export it is:
docker compose exec admin-proxy sh -c 'cat /data/caddy/pki/authorities/local/root.crt' > admin-proxy-root.crt
Then import admin-proxy-root.crt into the OS/browser trust store for the devices that should access the dashboard.
For supervised deployments:
- Install
s6 - Copy
deploy/s6/stoatanddeploy/s6/stoat-admininto/etc/s6-services - Adjust service paths and network names
- Copy
deploy/s6/s6-services.serviceinto/etc/systemd/system/ - Enable the unit:
sudo systemctl daemon-reload
sudo systemctl enable --now s6-services
Common operations:
s6-svc -r /etc/s6-services/stoat-admin
s6-svc -d /etc/s6-services/stoat-admin
s6-svc -u /etc/s6-services/stoat-admin
s6-svstat /etc/s6-services/stoat-admin
tail -f /var/log/s6/stoat-admin/current | s6-tai64nlocal
Development Notes
- The backend uses SQLite for admin credentials, audit logs, and invite metadata, and MongoDB for Stoat state.
- In the composed deployment, the frontend always uses same-origin
/apirequests throughadmin-proxy;VITE_API_URLis only useful outside compose. - Root task orchestration is handled by Turborepo through turbo.json.
- The current repo state is a first implementation slice based on the design docs in docs/stoat-admin-design.md and docs/stoat-admin-tasks.md.
Contributing
Keep infrastructure-specific values out of committed files. Prefer changes that preserve the split between the standalone admin stack and the main Stoat stack.