Server Setup¶
This guide walks you through setting up the YAAI server for local development. For production deployments, see Deployment.
Prerequisites¶
- Docker (for PostgreSQL, or bring your own)
- Python 3.11+ and uv (recommended) or pip
- Node.js 20+ (only for frontend development)
1. Install the server¶
This pulls in FastAPI, SQLAlchemy, scikit-learn, and all backend dependencies.
2. Start PostgreSQL¶
The simplest option is Docker Compose. Clone the repo and start only the database:
This starts PostgreSQL 16 on port 5431 (not the default 5432, to avoid conflicts with any local PostgreSQL).
Note
Bring your own PostgreSQL — If you already have a PostgreSQL instance, skip this step and configure DATABASE_URL to point to it.
3. Configure environment variables¶
Edit .env and set the values below. The defaults work for local development with the Docker Compose database.
Required variables¶
| Variable | Description | Example |
|---|---|---|
BASE_URL |
Public URL of your server (used for CORS, OAuth redirects, SA audience) | http://localhost:8000 |
DATABASE_URL |
Async connection string (asyncpg driver). Sync URL is derived automatically. | postgresql+asyncpg://aimon:changeme@localhost:5431/aimonitoring |
Note
The defaults in .env.example are fine for local development. For production, see the Deployment guide.
Optional variables¶
Secrets, bootstrap admin password, security headers, rate limiting and scheduler settings are described in the Configuration reference. Further common variables:
| Variable | Default | Description |
|---|---|---|
CORS_ALLOWED_ORIGINS |
(derived from BASE_URL) | Comma-separated allowed CORS origins. Only set if you need origins different from BASE_URL. |
AUTH_ENABLED |
true |
Master auth switch |
AUTH_LOCAL_ALLOW_REGISTRATION |
false |
Allow public user registration |
AUTH_SERVICE_ACCOUNTS_API_KEYS_ENABLED |
true |
Enable API key authentication |
Tip
Simplified configuration — Several settings are now auto-derived to reduce configuration burden:
- Sync DB URL — derived from
DATABASE_URL(replaces+asyncpgwith+psycopg2driver) - Local auth — enabled automatically unless Google OAuth is configured
- CORS origins — defaults to
BASE_URL - SA audience — defaults to
BASE_URL - Admin password — auto-generated and written to a 0600 file on first startup (never logged)
- JWT algorithm — hardcoded to HS256 (not configurable)
- Token expiry — hardcoded to 60 min (access) / 30 days (refresh)
4. Run database migrations and start the server¶
The server does not migrate the database on startup. Apply the migrations first, and again after every upgrade:
yaai.server.migrate is a pass-through to the Alembic CLI bound to the configured database: without arguments it runs upgrade head, otherwise it passes the arguments to Alembic (e.g. current, history, downgrade -1).
Then start the server:
On startup, the server checks that the database schema is at the latest migration and exits with an error if it is not. On first startup, it will also:
- Create a default admin account with the username
adminand a randomly generated password (written to a file, see Default admin account)
Open http://localhost:8000 -- you should see the login screen.
API docs are available at http://localhost:8000/docs (Swagger UI) in development. They are disabled by default when ENVIRONMENT=production (see API_DOCS_ENABLED).
Note
Upgrading from a version without projects: the migration creates a default project that contains all existing models and
makes every existing user a viewer of it, so everybody keeps reading all models (global owners keep full access).
Service accounts keep their per-model access. Downgrading fails if two projects contain models with the same name.
5. Start the frontend (development only)¶
For local development with frontend hot-reload, start the Vue dev server in a separate terminal:
The frontend runs on http://localhost:3000 and proxies /api requests to the backend on port 8000.
Tip
If you started the server via docker compose up -d, the frontend is already bundled and served from port 8000. You only need a separate frontend process for development with hot-reload.
6. Authentication¶
Out of the box, the server uses local authentication (username + password) with API key auth enabled for service accounts.
Projects and access¶
Models live in projects (see Core Concepts). Global owners create projects and add members (POST /api/v1/projects, POST /api/v1/projects/{id}/members); project owners manage the members of their own projects. Newly created users -- also those auto-created on their first Google login -- are not members of any project and see no models until they are added to one.
Default admin account¶
On first startup (when no users exist), the server creates an admin account:
- Username:
admin - Password:
BOOTSTRAP_ADMIN_PASSWORDif set, otherwise a random password written toBOOTSTRAP_ADMIN_PASSWORD_FILE(default./admin-initial-password.txtin the server's working directory) -- see Configuration.
Change the password immediately after first login and delete the file. With the repo's docker compose, the file lives in the container: docker compose exec backend cat /home/appuser/admin-initial-password.txt.
API keys¶
API keys are the primary way for SDK clients and services to authenticate. After logging in as admin:
- Create a service account via the API
- Generate an API key for that service account
- Use the key in requests:
X-API-Key: yaam_...
Google OAuth (optional)¶
To enable Google OAuth for browser-based login, set these variables:
AUTH_OAUTH_GOOGLE_ENABLED=true
AUTH_OAUTH_GOOGLE_CLIENT_ID=your-client-id
AUTH_OAUTH_GOOGLE_CLIENT_SECRET=your-client-secret
AUTH_OAUTH_GOOGLE_ALLOWED_DOMAINS=example.com,mycompany.com
AUTH_OAUTH_GOOGLE_AUTO_CREATE_USERS=true
AUTH_OAUTH_GOOGLE_OWNER_EMAILS=admin@example.com
AUTH_OAUTH_GOOGLE_VIEWER_EMAILS=user@example.com
AUTH_OAUTH_GOOGLE_OWNER_EMAILS and AUTH_OAUTH_GOOGLE_VIEWER_EMAILS are optional explicit overrides.
Users from AUTH_OAUTH_GOOGLE_ALLOWED_DOMAINS who are not in those lists are assigned
AUTH_OAUTH_GOOGLE_DEFAULT_ROLE (defaults to viewer).
Existing Google users can also call the API directly (SDK or gcloud auth print-identity-token) with a Google ID token.
The token's audience must be the OAuth client ID or one of AUTH_OAUTH_GOOGLE_TOKEN_AUDIENCES, which defaults
to the public gcloud CLI and Application Default Credentials client IDs. Tokens issued to any other application are rejected.
Important
When Google OAuth is enabled, local username/password authentication is automatically disabled. Users must sign in with their Google account.
Configure the OAuth redirect URI in Google Cloud Console to:
For local development this is http://localhost:8000/api/v1/auth/oauth/google/callback.
Note
Google OAuth only works when the frontend and backend share the same origin (same host and port). This works with Docker Compose or the hybrid approach below, but not with separate dev servers (frontend on :3000, backend on :8000).
Hybrid: build frontend locally, serve from backend¶
If you want Google OAuth without Docker but don't need frontend hot-reload:
cd frontend && npm run build-only && cd ..
cp -r frontend/dist/* yaai/server/static/
uv run uvicorn yaai.server.main:app --reload --reload-dir yaai --host 0.0.0.0 --port 8000
7. Load demo data¶
Two scripts are included to populate the server with sample models, inferences, and drift data:
# Via REST API
uv run scripts/generate_demo_data.py --drop-all --mode full --dataset all
# Via Python SDK
API_KEY=your_key uv run scripts/generate_demo_data_sdk.py --drop-all --mode full --dataset all
Troubleshooting¶
"Address already in use" on port 8000
: Another process is using port 8000 -- most likely the Docker backend container. Make sure you started only docker compose up db -d (not the full stack). Check with lsof -i :8000.
"FATAL: Database URL contains default credentials"
: You're running with ENVIRONMENT=production but haven't changed the default changeme password. Set DATABASE_URL with secure credentials.
"Database schema is not up to date" on startup
: The server no longer applies migrations automatically. Run uv run python -m yaai.server.migrate and start the server again.
Migrations fail
: Check that PostgreSQL is running and DATABASE_URL is correct.