Website: https://selflify.github.io/
Filesystem-backed admin panel for managing static SPA preview environments. Free and open source under the MIT license.
The project uses Yarn 4 as the package manager.
Implemented:
- Next.js App Router + TypeScript application
- Chakra UI dark admin shell
next-authcredentials auth- single source of truth in
runtime/selflify.config.jsonin production and.dev/selflify.config.jsonin the fixture stack - setup/login flow plus a combined
Sitesoverview instead of separate dashboard + sites lists - site details and global settings screens
- generated
runtime/Caddyfilewith zero-downtime reload hooks - Cloudflare DNS sync adapter
- config operations with revision checks, backups and rollback hooks
- cleanup script for stale preview deploys and orphaned site directories
- scheduled cleanup worker in
docker-compose - production
docker-compose.yml - development
docker-compose.dev.yml - dev fixture deploy directories in
.dev/var-www - application source under
src/
Useful local commands:
yarn lint
yarn lint:fix
yarn format
yarn format:check
yarn test:run
yarn test:coverage
yarn bootstrap:bundle- Install dependencies:
yarn install-
Ensure
AUTH_SECRETis set in.envor export it in your shell. -
Seed local dev runtime files once:
yarn dev:prepare- Start the app:
yarn dev --hostname 127.0.0.1 --port 3100The application will read runtime/selflify.config.json by default.
For the full local fixture stack, docker-compose.dev.yml points the app to .dev/selflify.config.json instead.
The base preview root comes from the active config file and defaults to /var/www.
If no admin account is configured yet, the app will redirect to /setup.
Useful optional overrides:
SELFLIFY_CADDY_CONFIG_PATH=./.dev/Caddyfile
SELFLIFY_CADDY_ADMIN_ADDRESS=http://caddy:2019
SELFLIFY_CADDY_CONTAINER=selflify-dev-caddy
SELFLIFY_BACKUP_ROOT=./.selflify/backups
SELFLIFY_BACKUP_KEEP=20
SELFLIFY_MOCK_CLOUDFLARE=1
SELFLIFY_SKIP_CADDY_RELOAD=0If you run yarn dev directly on your host and want fixture files instead of /var/www, add:
SELFLIFY_CONFIG_PATH=./.dev/selflify.config.json
SELFLIFY_PREVIEW_ROOT=./.dev/var-www
SELFLIFY_UPSTREAM=host.docker.internal:3000If you want to use a host-installed Caddy binary instead of the dev container, add:
SELFLIFY_CADDY_BIN=/usr/local/bin/caddyIn local development, the recommended behavior is:
- mock Cloudflare DNS operations
- allow real Caddy reloads inside the dev compose stack
- keep a small rolling backup set for config and Caddy snapshots
/setup: create the first account when the active config file does not have credentials yet/login: sign in with the configured credentials/sites: metrics + site inventory + site creation modal/sites/[site]: update the site, inspect deploys, remove preview deploys or delete the site/settings: domain, Caddy, Cloudflare and credentials settings
docker compose -f docker-compose.dev.yml up --buildThis runs:
selflifyonhttp://localhost:3000cleanupworker against/var/wwwmounted from.dev/var-wwwcaddyonhttp://localhost:8080
This is the full-fidelity development stack. It is the mode that correctly reflects preview directories, free-space reporting, masked token display and generated Caddy updates.
The dev stack uses:
.dev/selflify.config.example.jsonand.dev/Caddyfile.exampleas tracked templates.dev/selflify.config.jsonand.dev/Caddyfileas local seeded runtime files.dev/var-wwwfor stable and preview deploy directories
You can still run yarn dev --hostname 0.0.0.0 --port 3000 directly on the host for isolated UI
work, but that host-side mode is not the full preview stack unless you also override the filesystem
paths manually.
The dev stack now keeps container-native node_modules and .next volumes, so the Linux container
does not try to reuse host dependencies. This avoids the blank localhost:3000 / missing SWC
startup failures that happen when macOS host modules leak into the container.
Inside the containers, the base preview root is always /var/www.
In development, docker-compose.dev.yml mounts local fixture files from .dev/var-www into that path.
Caddy proxies the admin panel to the selflify service inside the compose network by default.
When you intentionally run host-side yarn dev, Selflify can still use docker exec selflify-dev-caddy caddy ... for validation and password hashing unless SELFLIFY_CADDY_BIN is explicitly overridden.
The repo contains minimal static fixture deploys for the current sites in .dev/var-www.
Examples:
.dev/var-www/app/stable/index.html.dev/var-www/app/pr-6825/index.html.dev/var-www/storybook/release-3-189-30/index.html
They exist so that local Caddy and the Sites screen can immediately see stable and preview deploy directories without waiting for real builds.
docker-compose.dev.yml and yarn dev:prepare seed local .dev/Caddyfile and .dev/selflify.config.json
from the tracked .example files if they do not exist yet. Those real runtime files are gitignored on purpose.
src/app: App Router pages, layouts, route handlers and server actionssrc/components: reusable admin UI building blockssrc/lib: auth, config, operations, filesystem and provider logicsrc/auth.ts:next-authwiring
The marketing site is now maintained separately in Selflify/selflify.github.io and published at https://selflify.github.io/.
Production rollout, migration, smoke checks and rollback steps are documented in docs/production-rollout.md.
To prepare a bootstrap bundle for fresh servers:
yarn bootstrap:bundleThis creates:
dist/bootstrap/install-selflify.shdist/bootstrap/selflify-bootstrap.tar.gz
Bootstrap templates live in bootstrap/:
bootstrap/selflify.config.template.jsonbootstrap/Caddyfile.template
Recommended distribution flow:
- Push
stabletogithub.com/Selflify/Selflify. - Let the bootstrap publish workflow upload release assets.
- Let users run a one-liner like:
curl -fsSL https://github.com/Selflify/Selflify/releases/latest/download/install-selflify.sh | bashWhat the installer does:
- installs Docker and the Docker Compose plugin
- downloads and extracts the bootstrap bundle into
/opt/selflifyby default - creates
.envwith generatedAUTH_SECRETandSELFLIFY_SETUP_TOKENvalues if it does not exist yet - creates initial
runtime/selflify.config.jsonandruntime/Caddyfilefrom templates if they do not exist yet - pulls public runtime images from
ghcr.io/selflify/* - starts the production stack with
docker compose pull && docker compose up -d - brings the panel up on
http://<server-ip>/setup, locked behindSELFLIFY_SETUP_TOKEN, so the first session can collect runtime settings - downloads
selflify-bootstrap.tar.gzfrom the latest GitHub release by default
Production images are published to GitHub Container Registry. After the first successful image publish,
make the ghcr.io/selflify/selflify, ghcr.io/selflify/selflify-cleanup and
ghcr.io/selflify/selflify-caddy packages public once in the GitHub UI. After that, fresh servers can
pull them without docker login.
The GitHub deploy workflow does not seed runtime config anymore. It expects the server to be bootstrapped
already, with runtime/selflify.config.json and runtime/Caddyfile persisted on disk.
What still happens in the UI after bootstrap:
- open
http://<server-ip>/setup - unlock setup with
SELFLIFY_SETUP_TOKENfrom/opt/selflify/.env - create the first account
- enter the main domain, public server IP and Caddy contact email
- paste the Cloudflare API token during first-start setup
- after setup, plain HTTP access on the server IP stops serving the panel directly; use the primary domain instead
cleanup-previews.sh now reads the active config path, removes stale preview directories for configured sites and purges orphaned site directories after TTL.
Optional overrides:
SELFLIFY_CONFIG_PATH=./runtime/selflify.config.json
SELFLIFY_PREVIEW_TTL_DAYS=30
SELFLIFY_ORPHAN_TTL_DAYS=30
SELFLIFY_CLEANUP_INTERVAL_SECONDS=86400