Versola is a platform that centralizes authentication, authorization, and account management, enabling teams to quickly build secure systems without developing their own identity infrastructure.
The name is inspired by the Italian word "verso", meaning the reverse (back) side. The suffix "la" was intentionally added to evoke flexibility and evolution. Secure authentication requires looking beyond the obvious.
- License: Versola Community License v1.0 — free for Internal Authentication (an Organization's own employees/contractors) by organizations with fewer than 50 employees, and for evaluation use by any organization. Authenticating customers or end users, or offering the Software as a hosted/managed identity service, is not permitted under this free tier regardless of organization size. See the license file for full terms.
Three Scala services share one codebase, plus a static admin SPA:
| Service | Role | Public-facing? |
|---|---|---|
auth |
OAuth 2.0 / OpenID Connect provider — authorization, token, introspection, JWKS, logout endpoints | Yes |
central |
Configuration store: tenants, clients, scopes, roles, permissions, forms, JWKS. Admin API. Source of truth auth syncs from. |
No — reached only through edge |
edge |
Authenticating/authorizing reverse proxy that offloads authn/authz from resource servers and API backends; also the login entry point for the admin console | Yes |
central-ui |
Admin dashboard SPA (not a Docker service — static assets served by nginx) | Yes |
util holds code shared across auth/central/edge (HTTP, JSON Schema, CEL, core types). Each service also has a -postgres-impl module (e.g. auth-postgres-impl) that wires the service to its PostgreSQL implementation and provides the runnable app.
For the full request-routing picture and why things are split this way, see deploy.md.
- Language: Scala 3, built with ZIO
- Database: PostgreSQL, migrated with Flyway
- Tracing: OpenTelemetry
- Secrets: OpenBao for managing per-environment secrets
- Admin UI: Lit, TypeScript, Vite (
central-ui), tested with Playwright and Vitest - Forms - Solid.js, TypeScript
- Packaging:
sbt-native-packager(JavaAppPackaging), Docker images published toghcr.io/versolauth/
Requires a JDK, sbt, Docker, scala-cli (for local config generation), and Node.js/npm (to build central-ui's login forms, which central needs to render /login/central-admin).
# 1. Generate local dev config for auth/central/edge (writes auth/dev/env.conf, etc.)
scala-cli run scripts/gen-env.scala # answer "local" at the Name prompt
# 2. Start Postgres
docker-compose -f services.yml up -d postgres
# 3. Run each service (in separate terminals)
# RUN_MIGRATIONS=true: each service otherwise only *validates* its schema on
# startup rather than applying migrations to it (deliberate for real
# deployments, see deploy.md's own RUN_MIGRATIONS section) -- against the
# fresh Postgres from step 2, that fails immediately with no schema to
# validate against.
PORT=9001 DPORT=9002 RUN_MIGRATIONS=true sbt -Denv.path=central/dev/env.conf "project central-postgres-impl; run"
PORT=9003 DPORT=9004 APORT=9007 RUN_MIGRATIONS=true sbt -Denv.path=auth/dev/env.conf "project auth-postgres-impl; run"
PORT=9005 DPORT=9006 RUN_MIGRATIONS=true sbt -Denv.path=edge/dev/env.conf "project edge-postgres-impl; run"Before starting central, build the login forms it serves:
cd central-ui
npm install
npm run build:forms # compiles forms into central/src/main/resources/formsThen open http://localhost:9005/login/central-admin (admin / Admin1234!, OTP 123456).
sbt test # unit tests for all modules
sbt e2e/test # end-to-end tests (run explicitly, not part of the default test loop)central-ui has its own suites: cd central-ui && npm run test:unit (Vitest) and npm run test:ui (Playwright).
├── auth/ # OAuth 2.1 / OIDC provider (+ auth/implementations/postgres, auth/open-api specs)
├── central/ # Configuration/admin service (+ central/implementations/postgres)
├── central-ui/ # Admin dashboard SPA (Vite/TypeScript) + login forms served by auth
├── edge/ # Authn/authz-offloading reverse proxy for resource servers/APIs; also the admin console entry point
├── util/ # Shared library code (+ util/implementations/postgres)
├── e2e/ # Cross-service end-to-end tests
├── docker/ # Dockerfiles for each service
├── scripts/gen-env.scala # Generates per-environment HOCON configs + secrets
├── project/ # sbt build config (Dependencies.scala, plugins)
├── develop.md # Local development, Docker builds, OpenBao secrets setup
└── deploy.md # Deployment runbook and troubleshooting
auth exposes its endpoints as OpenAPI specs under auth/open-api/ (authorize, token, introspect, revoke, jwks, userinfo, logout, par, metadata).
ci-cd.yml is the main build pipeline. It runs on every push/PR to main:
- Compile all modules and run the unit test suite (
sbt test) against a Postgres service container. - Stage
auth,centralandedge, then run the end-to-end suite (sbt e2e/test) against the staged services.