Bootstrap & Authentication
These commands handle initial setup and CLI authentication.
porta init
Bootstrap the admin infrastructure. This is typically the first command you run after deploying Porta and running migrations.
porta initWhat it does:
- Creates the super-admin organization (
porta-admin) - Creates the admin application with granular RBAC permissions and roles
- Creates a shared PKCE-enabled public OIDC client used by the
portaCLI and the Porta Console over loopback - Creates the first admin user (prompts for email and password)
- Assigns the
porta-adminrole to the first user
Mode: Direct DB (connects directly to PostgreSQL and Redis)
Options:
| Flag | Description |
|---|---|
--database-url | Override DATABASE_URL |
--redis-url | Override REDIS_URL |
Example:
# Interactive — prompts for admin email and password
porta init
# With explicit database URL
porta init --database-url postgresql://user:pass@localhost:5432/portaWARNING
porta init should only be run once during initial deployment. Running it again will fail if the super-admin organization already exists.
Existing installations
porta init registers the console callbacks only on new installations. If the server was initialized before the Porta Console callback existed, register it once with the admin CLI:
porta client update <client-uuid> --redirect-uris "http://127.0.0.1/callback,http://localhost/callback,http://127.0.0.1/auth/callback,http://127.0.0.1/api/oidc/callback,http://localhost/api/oidc/callback"Find <client-uuid> in the ID column of porta client list --app <app-uuid> for the Porta Admin CLI client; get <app-uuid> from the ID column of porta app list for the Porta Admin application. The clientId returned by GET /api/admin/metadata is the public OIDC identifier used in authorization requests, not the internal UUID that porta client update accepts. The --redirect-uris option replaces the complete stored list, so include any custom redirect URIs you added alongside the five above.
porta login
Authenticate with the Porta server using OIDC Authorization Code + PKCE flow.
porta login [--server <url>] [--no-browser] [--client-id <id>]What it does:
- Fetches OIDC discovery metadata from
/api/admin/metadata - Generates a PKCE
code_verifierandcode_challenge - Browser mode (default on host): opens your browser, captures the authorization code via a temporary localhost callback server
- Manual mode (
--no-browseror auto-detected in Docker): prints the auth URL for you to open manually, then prompts you to paste the callback URL from your browser's address bar - Exchanges the code for access and refresh tokens
- Stores credentials at
~/.porta/credentials.json
The CLI requests the offline_access scope so the server issues a refresh token. The CLI uses this refresh token to silently obtain new access tokens as they expire (access tokens are short-lived — about 1 hour by default), so you do not have to run porta login again every hour.
The authorization request uses prompt=login consent. The login value forces fresh credential entry on every porta login; the consent value is required for offline_access to be granted — per OIDC Core §3.1.2.1, the provider ignores offline_access unless the request's prompt contains consent. Because Porta auto-consents first-party clients, the consent value adds no extra screen for the admin.
No refresh token issued
If the server does not return a refresh token, the CLI prints a warning:
Warning: the server did not issue a refresh token. You'll need to run
'porta login' again when the access token expires (~1h). Ensure the client
allows the 'refresh_token' grant and the 'offline_access' scope.This normally means the admin OIDC client is missing the refresh_token grant type or the offline_access scope. The client created by porta init is configured correctly; this warning is only expected for hand-edited or externally-provisioned clients. See Session Lifecycle for how Porta upgrades an existing grant to include offline_access.
Mode: HTTP
Options:
| Flag | Description |
|---|---|
--server | Porta server URL (default: https://porta.local:3443) |
--no-browser | Use manual mode — print URL instead of opening browser |
--client-id | Override the auto-discovered admin client ID |
Headless Environments
Use --no-browser when running the standalone CLI over SSH, in CI, or in another environment without a local browser.
Examples:
# Login on your local machine (opens browser automatically)
porta login
# Login to a remote server
porta login --server https://auth.example.com
# Force manual mode (SSH, CI, headless servers)
porta login --no-browserManual mode flow:
$ porta login --no-browser
Open this URL in your browser to log in:
https://porta.local:3443/porta-admin/auth?response_type=code&client_id=...
After logging in, your browser will redirect to a page that won't load.
Copy the full URL from your browser's address bar and paste it below.
Paste the callback URL: http://127.0.0.1:11111/callback?code=abc123&state=xyz
✅ Logged in as admin@example.comporta logout
Clear stored credentials.
porta logoutRemoves the ~/.porta/credentials.json file.
Mode: HTTP
porta whoami
Display information about the currently authenticated user.
porta whoamiOutput:
┌───────────┬──────────────────────────────────────┐
│ Field │ Value │
├───────────┼──────────────────────────────────────┤
│ User ID │ 550e8400-e29b-41d4-a716-446655440000 │
│ Email │ admin@example.com │
│ Org │ porta-admin │
│ Roles │ porta-admin │
│ Server │ https://porta.local:3443 │
└───────────┴──────────────────────────────────────┘Mode: HTTP — requires prior porta login.