Configuring MolnOS
MolnOS is designed to be straightforward to configure while giving you control when you need it. This guide covers everything from the bare minimum to advanced configuration scenarios.
Configuration Overview
Section titled “Configuration Overview”MolnOS can be configured in three ways, with priorities from highest to lowest:
- CLI flags (e.g.,
molnos start --port 8080) - Environment variables (e.g.,
PORT=8080) - Configuration file (
molnos.config.json)
This flexibility means you can choose the approach that fits your deployment:
- Use config files for local development or VMs where you manage files directly
- Use environment variables for cloud platforms, containers, or CI/CD pipelines
- Use CLI flags for quick overrides during testing
Required Configuration
Section titled “Required Configuration”To run MolnOS, you must provide these values:
Authentication Configuration
Section titled “Authentication Configuration”MolnOS supports two authentication methods. Choose one or use both:
Option 1: Email-Based Magic Links (Passwordless)
Section titled “Option 1: Email-Based Magic Links (Passwordless)”email.host- Your SMTP server hostnameemail.user- SMTP username (typically your email address)email.password- SMTP password or app-specific password
Option 2: OAuth Providers
Section titled “Option 2: OAuth Providers”Configure OAuth to eliminate SMTP dependencies:
oauth.presets- Quick setup for Google, GitHub, Microsoft, GitLaboauth.custom- Self-hosted providers (Keycloak, Authentik, etc.)
See OAuth Authentication below for full details.
Configuring the Data Path (Recommended)
Section titled “Configuring the Data Path (Recommended)”molnos.dataPath- The path to application data (default:data)
Configuring the Initial User (Required)
Section titled “Configuring the Initial User (Required)”molnos.initialUser.userName- The initial user’s namemolnos.initialUser.email- The email address to the initial user (receives first sign-in link)
Configuration File
Section titled “Configuration File”The configuration file is the most common way to set up MolnOS, especially for local development and self-hosted deployments.
Creating the Configuration File
Section titled “Creating the Configuration File”molnos initThis creates molnos.config.json in your current directory with a template similar to this:
{ "$schema": "https://schemas.molnos.cloud/schema-config-v1.json", "email": { "emailSubject": "Sign In To MolnOS", "user": "my_user@my_domain.net", "password": "my_password", "host": "smtp.my_host.net", "port": 465, "secure": true }, "molnos": { "dataPath": "data", "initialUser": { "userName": "User", "email": "me@my_domain.net" } }, "auth": { "jwtSecret": "your-jwt-secret", "consoleUrl": "https://localhost:8000" }, "server": { "allowedDomains": ["*"] }}Editor Support with JSON Schema
Section titled “Editor Support with JSON Schema”Add the $schema property to get autocomplete and validation in VSCode and other editors:
{ "$schema": "https://schemas.molnos.cloud/schema-config-v1.json", "molnos": { ... }}This gives you:
- Autocomplete for all configuration options
- Inline documentation when hovering over properties
- Validation errors for invalid values before you run MolnOS
Environment Variables
Section titled “Environment Variables”Environment variables are ideal for cloud deployments, containers, and CI/CD pipelines where you don’t want to manage configuration files.
Email Configuration
Section titled “Email Configuration”| Environment Variable | Description | Default |
|---|---|---|
EMAIL_HOST | SMTP server hostname | - |
EMAIL_USER | SMTP username | - |
EMAIL_PASSWORD | SMTP password | - |
EMAIL_PORT | SMTP port | 465 |
EMAIL_SECURE | Use SSL/TLS (true/false) | true |
EMAIL_SUBJECT | Subject line for sign-in emails | "Sign In To MolnOS" |
Authentication Configuration
Section titled “Authentication Configuration”| Environment Variable | Description | Default |
|---|---|---|
AUTH_JWT_SECRET | Secret key for JWT signing | "your-jwt-secret" |
CONSOLE_URL | URL where users complete sign-in | "http://127.0.0.1:8000" |
Server Configuration
Section titled “Server Configuration”| Environment Variable | Description | Default |
|---|---|---|
PORT | Port to listen on | 3000 |
HOST | Host to bind to | "localhost" |
ALLOWED_DOMAINS | Comma-separated list of allowed CORS origins | "http://127.0.0.1:8080" |
Storage Configuration
Section titled “Storage Configuration”| Environment Variable | Description | Default |
|---|---|---|
DATA_PATH | Directory for application data | "data" |
STORAGE_KEY | Encryption key for sensitive data | - |
MolnOS Configuration
Section titled “MolnOS Configuration”| Environment Variable | Description | Default |
|---|---|---|
INITIAL_USER_NAME | Organization name for initial setup | - |
INITIAL_USER_EMAIL | Admin email for initial setup | - |
SIGNED_URL_SECRET | Custom secret value for signed URLs | Withheld |
Example: Cloud Deployment with Environment Variables
Section titled “Example: Cloud Deployment with Environment Variables”In your App Platform configuration, add these environment variables:
CONSOLE_URL=https://molnos.yourcompany.comALLOWED_DOMAINS=https://molnos.yourcompany.comINITIAL_USER_NAME=Your CompanyEMAIL_HOST=smtp.gmail.comEMAIL_PASSWORD=your-app-passwordEMAIL_PORT=465EMAIL_SECURE=trueAUTH_JWT_SECRET=your-secure-random-stringPass environment variables when running your container:
docker run -d \ -e EMAIL_HOST=smtp.gmail.com \ -e EMAIL_PASSWORD=your-app-password \ -e EMAIL_PORT=465 \ -e EMAIL_SECURE=true \ -e AUTH_JWT_SECRET=your-secure-random-string \ -e CONSOLE_URL=https://molnos.yourcompany.com \ -e INITIAL_USER_NAME="Your Company" \ -e ALLOWED_DOMAINS=https://molnos.yourcompany.com \ -p 3000:3000 \ molnos:latestAdd environment variables to your service file:
[Service]Environment="CONSOLE_URL=https://molnos.yourcompany.com"Environment="ALLOWED_DOMAINS=https://molnos.yourcompany.com"Environment="INITIAL_USER_NAME=User Name"Environment="EMAIL_HOST=smtp.gmail.com"Environment="EMAIL_PASSWORD=your-app-password"Environment="EMAIL_PORT=465"Environment="EMAIL_SECURE=true"Environment="AUTH_JWT_SECRET=your-secure-random-string"CLI Flags
Section titled “CLI Flags”CLI flags provide the highest priority and are useful for quick overrides during development or testing.
Authentication Flags
Section titled “Authentication Flags”--jwtSecret <secret> JWT secret for token signing--magicLinkExpirySeconds <seconds> Magic link expiry time--jwtExpirySeconds <seconds> JWT expiry time--refreshTokenExpirySeconds <secs> Refresh token expiry time--maxActiveSessions <number> Max concurrent sessions--consoleUrl <url> Application URL for sign-in completionEmail Flags
Section titled “Email Flags”--emailSubject <subject> Email subject line--emailHost <hostname> SMTP server hostname--emailUser <username> SMTP username--emailPassword <password> SMTP password--emailPort <port> SMTP port number--emailSecure Use SSL/TLS (flag, no value)--emailMaxRetries <number> Max retry attemptsServer Flags
Section titled “Server Flags”--port <port> Port to listen on--host <hostname> Host to bind to--allowed <domain1,domain2,...> Comma-separated allowed domainsExamples of allowed domains:
// Allow specific domains (recommended for production)"allowedDomains": [ "https://molnos.example.com", "https://app.example.com"]
// Allow all domains (development only)"allowedDomains": ["*"]
// Allow localhost for development"allowedDomains": [ "http://localhost:8000", "http://localhost:3000"]Storage Flags
Section titled “Storage Flags”--db <directory> Database directory path (auth)--encryptionKey <key> Encryption key for storage (auth)MolnOS Flags
Section titled “MolnOS Flags”--data-path <path> Path to application data--initialUserId <id> Initial user ID (auto-generated if not set)--initialUserName <name> Initial user name--initialUserEmail <email> Initial user email addressExample: Override Port
Section titled “Example: Override Port”molnos start --port 8080Configuration Priority
Section titled “Configuration Priority”When the same setting is provided in multiple ways, MolnOS uses this priority order:
- CLI flags (highest priority)
- Environment variables
- Configuration file
- Default values (lowest priority)
Example Priority Resolution
Section titled “Example Priority Resolution”If you have:
- Config file:
"port": 3000 - Environment variable:
PORT=8080 - CLI flag:
--port 9000
MolnOS will use port 9000 (CLI flag wins).
OAuth Authentication
Section titled “OAuth Authentication”OAuth support enables authentication without SMTP dependencies, providing autonomy from external email providers. You can use common providers (Google, GitHub) or self-hosted solutions (Keycloak, Authentik) for complete sovereignty.
Quick Setup with Common Providers
Section titled “Quick Setup with Common Providers”For Google, GitHub, Microsoft, or GitLab, use the preset configuration in this style:
{ "oauth": { "presets": { "google": { "clientId": "your-google-client-id", "clientSecret": "your-google-client-secret", "redirectUri": "https://your-domain.com/auth/oauth/google/callback" }, "github": { "clientId": "your-github-client-id", "clientSecret": "your-github-client-secret", "redirectUri": "https://your-domain.com/auth/oauth/github/callback" } } }}Self-Hosted Provider Setup
Section titled “Self-Hosted Provider Setup”For complete sovereignty, use self-hosted OAuth providers:
{ "oauth": { "custom": [ { "id": "keycloak", "name": "Company SSO", "authorizationUrl": "https://auth.company.com/realms/main/protocol/openid-connect/auth", "tokenUrl": "https://auth.company.com/realms/main/protocol/openid-connect/token", "userInfoUrl": "https://auth.company.com/realms/main/protocol/openid-connect/userinfo", "clientId": "molnos-core", "clientSecret": "your-secret", "redirectUri": "https://your-domain.com/auth/oauth/keycloak/callback", "scopes": "openid email profile" } ] }}Hybrid Authentication
Section titled “Hybrid Authentication”Combine OAuth and magic links for maximum flexibility:
{ "email": { "host": "smtp.gmail.com", "password": "app-password" }, "oauth": { "presets": { "google": { "clientId": "...", "clientSecret": "...", "redirectUri": "https://your-domain.com/auth/oauth/google/callback" } } }}OAuth Configuration Options
Section titled “OAuth Configuration Options”Rate Limiting
Section titled “Rate Limiting”Control OAuth authentication attempts (optional):
{ "oauth": { "rateLimiting": { "maxAttempts": 10, "windowMs": 900000 } }}maxAttempts- Maximum requests per window (default: 10)windowMs- Time window in milliseconds (default: 900000 = 15 minutes)
State Token Expiry
Section titled “State Token Expiry”Configure CSRF protection token expiry (optional):
{ "oauth": { "stateExpirySeconds": 600 }}Default: 600 seconds (10 minutes)
OAuth Endpoints
Section titled “OAuth Endpoints”When OAuth is configured, these endpoints become available:
GET /auth/oauth/providers- List available OAuth providersGET /auth/oauth/{provider}- Initiate OAuth flow (e.g.,/auth/oauth/google)GET /auth/oauth/{provider}/callback- OAuth callback handler
Setting Up OAuth Providers
Section titled “Setting Up OAuth Providers”- Go to Google Cloud Console
- Create or select a project
- Enable Google+ API
- Create OAuth 2.0 credentials for a web application
- Add authorized JavaScript origin:
http://localhost:8000(for local) - Add authorized redirect URI:
http://localhost:3000/auth/oauth/google/callback(for local) - Copy Client ID and Client Secret to your MolnOS config
- Go to GitHub Settings → Developer settings → OAuth Apps
- Click “New OAuth App”
- Set Authorization callback URL:
https://your-domain.com/auth/oauth/github/callback - Copy Client ID and generate Client Secret
- Add to your configuration
- Log into your Keycloak admin console
- Select your realm
- Go to Clients → Create
- Set Client ID (e.g., “molnos-core”)
- Enable “Standard Flow”
- Add Valid Redirect URIs:
https://your-domain.com/auth/oauth/keycloak/callback - Copy Client ID and Secret to your config
OAuth Security Features
Section titled “OAuth Security Features”All OAuth flows include:
- CSRF Protection: State parameter validation with IP binding
- Rate Limiting: Per-IP request throttling (10 req/15min default)
- HTTPS Enforcement: OAuth endpoints require HTTPS in production
- Token Security: OAuth tokens never stored, only user info extracted
- Automatic Cleanup: Expired state tokens removed automatically
Complete Configuration Reference
Section titled “Complete Configuration Reference”Here’s a fully documented configuration file showing all available options:
{ "email": { "emailSubject": "Sign In To MolnOS", "password": "your-smtp-password", "host": "smtp.gmail.com", "port": 465, "secure": true }, "oauth": { "presets": { "google": { "clientId": "your-google-client-id", "clientSecret": "your-google-client-secret", "redirectUri": "https://molnos.yourcompany.com/auth/oauth/google/callback" } }, "custom": [ { "id": "keycloak", "name": "Company SSO", "authorizationUrl": "https://auth.company.com/auth", "tokenUrl": "https://auth.company.com/token", "userInfoUrl": "https://auth.company.com/userinfo", "clientId": "molnos", "clientSecret": "your-secret", "redirectUri": "https://molnos.yourcompany.com/auth/oauth/keycloak/callback", "scopes": "openid email profile" } ], "stateExpirySeconds": 600, "rateLimiting": { "maxAttempts": 10, "windowMs": 900000 } }, "molnos": { "dataPath": "data", "initialUser": { "userName": "User Name", }, "rateLimit": { "global": { "enabled": false, "requestsPerMinute": 0 } }, "signedUrlSecret": "my-signed-url-secret-value-here" }, "auth": { "jwtSecret": "your-secret-key-change-this", "magicLinkExpirySeconds": 900, "jwtExpirySeconds": 900, "refreshTokenExpirySeconds": 604800, "maxActiveSessions": 3, "consoleUrl": "https://molnos.yourcompany.com" }, "server": { "port": 3000, "host": "localhost", "allowedDomains": [ "https://molnos.yourcompany.com" ] }, "storage": { "databaseDirectory": "molnosdb", "encryptionKey": "" }}Configuration Validation
Section titled “Configuration Validation”When you start MolnOS, it validates your configuration and provides helpful error messages if required fields are missing:
$ molnos startError: Missing email.host valueError: Missing email.user valueError: Missing email.password valueError: Missing molnos.initialUser.userName valueError: Missing molnos.initialUser.email valueThis ensures you can’t accidentally start MolnOS with incomplete configuration.
Common Configuration Scenarios
Section titled “Common Configuration Scenarios”Local Development
Section titled “Local Development”Goal: Quick setup for testing on your laptop using Mailpit as the SMPT server.
{ "email": { "emailSubject": "Sign In To MolnOS", "password": "your-smtp-password", "host": "localhost", "port": 1025, "secure": false }, "auth": { "jwtSecret": "your-secret-key-change-this", "consoleUrl": "http://localhost:8000" }, "server": { "allowedDomains": ["*"] }, "molnos": { "dataPath": "data", "initialUser": { "userName": "User", } }}Production VPS/VM
Section titled “Production VPS/VM”Goal: Secure production deployment on your infrastructure
{ "email": { "password": "secure-app-password", "host": "smtp.gmail.com", "port": 465, "secure": true }, "auth": { "jwtSecret": "generated-with-openssl-rand-base64-32", "consoleUrl": "https://molnos.yourcompany.com", "jwtExpirySeconds": 3600, "refreshTokenExpirySeconds": 2592000 }, "server": { "allowedDomains": [ "https://molnos.yourcompany.com" ] }, "molnos": { "dataPath": "data", "initialUser": { "userName": "User Name", } }}Cloud Platform (Using Environment Variables)
Section titled “Cloud Platform (Using Environment Variables)”Goal: Deploy on DigitalOcean, AWS, or similar without managing config files
Set these environment variables in your platform’s dashboard:
# RequiredEMAIL_HOST=smtp.sendgrid.netEMAIL_USER=apikeyEMAIL_PASSWORD=your-sendgrid-api-keyINITIAL_USER_NAME="Your Company"
# ImportantAUTH_JWT_SECRET=your-secure-random-stringCONSOLE_URL=https://molnos.yourcompany.comALLOWED_DOMAINS=https://molnos.yourcompany.com
# OptionalEMAIL_PORT=465EMAIL_SECURE=truePORT=3000Fully Autonomous (OAuth Only)
Section titled “Fully Autonomous (OAuth Only)”Goal: Eliminate SMTP dependency using self-hosted OAuth
{ "oauth": { "custom": [ { "id": "keycloak", "name": "Internal SSO", "authorizationUrl": "https://sso.company.internal/realms/main/protocol/openid-connect/auth", "tokenUrl": "https://sso.company.internal/realms/main/protocol/openid-connect/token", "userInfoUrl": "https://sso.company.internal/realms/main/protocol/openid-connect/userinfo", "clientId": "molnos-core", "clientSecret": "your-keycloak-secret", "redirectUri": "https://molnos.company.internal/auth/oauth/keycloak/callback", "scopes": "openid email profile" } ] }, "auth": { "jwtSecret": "generated-with-openssl-rand-base64-32", "consoleUrl": "https://molnos.company.internal" }, "molnos": { "dataPath": "data", "initialUser": { "userName": "Admin", } }}Note: Email configuration is completely optional when OAuth is configured.
Security Recommendations
Section titled “Security Recommendations”JWT Secret
Section titled “JWT Secret”Always generate a strong, random JWT secret:
openssl rand -base64 32Never commit secrets to version control. Use environment variables or secret management tools.
Storage Encryption Key
Section titled “Storage Encryption Key”If you provide a storage.encryptionKey, MolnOS encrypts sensitive data at rest. Generate it the same way:
openssl rand -base64 32CORS Configuration
Section titled “CORS Configuration”In production, never use "allowedDomains": ["*"]. Always specify exact domains:
"allowedDomains": [ "https://molnos.yourcompany.com"]Rate Limiting
Section titled “Rate Limiting”Configure rate limiting to protect your services from abuse. Rate limits can be set globally for all services or individually per service.
Global Rate Limiting
Section titled “Global Rate Limiting”Apply the same rate limit to all services:
{ "molnos": { "dataPath": "data", "rateLimit": { "global": { "enabled": true, "requestsPerMinute": 60 } } }}Service-Specific Rate Limiting
Section titled “Service-Specific Rate Limiting”Override global settings for individual services (Functions, Databases, Storage, Sites, Observability):
{ "molnos": { "dataPath": "data", "rateLimit": { "global": { "enabled": true, "requestsPerMinute": 60 }, "services": { "functions": { "enabled": true, "requestsPerMinute": 120 }, "databases": { "enabled": true, "requestsPerMinute": 100 }, "storage": { "enabled": false, "requestsPerMinute": 0 } } } }}Service-specific settings always override global settings. If a service doesn’t have specific settings, it inherits from the global configuration.
Service Endpoints
Section titled “Service Endpoints”By default, MolnOS services run on localhost with predefined ports:
| Service | Default Port |
|---|---|
| Storage | 3001 |
| Functions | 3002 |
| Sites | 3003 |
| Databases | 3004 |
| Observability | 3005 |
You can customize these endpoints for distributed deployments or to avoid port conflicts.
Custom Service Ports
Section titled “Custom Service Ports”Override default ports for individual services:
{ "molnos": { "dataPath": "data", "services": { "databases": { "port": 5004 }, "storage": { "port": 5001 } } }}Distributed Deployment
Section titled “Distributed Deployment”Run services on different hosts for microservices-style deployments:
{ "molnos": { "dataPath": "data", "services": { "databases": { "host": "db.internal", "port": 3004 }, "storage": { "host": "storage.internal", "port": 3001 }, "functions": { "host": "compute.internal", "port": 3002 } } }}Services without explicit configuration inherit server.host (or 127.0.0.1) and use their default ports.
Secure (HTTPS) Service Connections
Section titled “Secure (HTTPS) Service Connections”For distributed deployments where services communicate over a network, you can enable HTTPS for individual services using the secure property:
{ "molnos": { "dataPath": "data", "services": { "databases": { "host": "db.example.com", "port": 443, "secure": true }, "storage": { "host": "storage.example.com", "port": 443, "secure": true }, "functions": { "host": "localhost", "port": 3002 } } }}In this example, the databases and storage services use HTTPS (https://db.example.com:443), while the functions service uses HTTP (http://localhost:3002). This is useful when some services are deployed behind a TLS-terminating load balancer or reverse proxy.
Service Endpoint Configuration Reference
Section titled “Service Endpoint Configuration Reference”| Property | Description | Default |
|---|---|---|
services.<service>.host | Service host address | server.host |
services.<service>.port | Service port number | See table below |
services.<service>.secure | Use HTTPS instead of HTTP | false |
Where <service> is one of: storage, functions, sites, databases, or observability.
Default ports:
| Service | Default Port |
|---|---|
| Storage | 3001 |
| Functions | 3002 |
| Sites | 3003 |
| Databases | 3004 |
| Observability | 3005 |
Cluster Mode (Multi-Host)
Section titled “Cluster Mode (Multi-Host)”MolnOS supports distributing capabilities across multiple hosts using cluster mode. A core node handles routing and management while worker nodes run specific capabilities like Functions or Storage.
Cluster Modes
Section titled “Cluster Modes”| Mode | Description |
|---|---|
standalone | Default. All capabilities run locally on a single host. |
core | Routes requests to configured remote workers. Runs Identity, Management, and non-delegated capabilities locally. |
worker | Runs only the specified capabilities. Validates cluster secret on incoming requests. |
Core Node Configuration
Section titled “Core Node Configuration”The core node routes requests to worker nodes based on capability:
{ "molnos": { "dataPath": "data", "cluster": { "mode": "core", "secret": "your-shared-cluster-secret", "workers": { "functions": { "url": "http://functions-worker:3002", "timeoutMs": 5000, "healthCheckPath": "/health", "healthCheckIntervalMs": 30000 }, "storage": { "url": "http://storage-worker:3001" } } } }}Worker Node Configuration
Section titled “Worker Node Configuration”Worker nodes only start the capabilities they’re assigned. They don’t need email, OAuth, initial user, or even dataPath configuration since they don’t handle identity—the core node manages authentication:
{ "molnos": { "cluster": { "mode": "worker", "secret": "your-shared-cluster-secret", "capabilities": ["functions"] } }}Cluster Configuration Reference
Section titled “Cluster Configuration Reference”| Property | Description | Default |
|---|---|---|
cluster.mode | Node mode: standalone, core, or worker | standalone |
cluster.secret | Shared secret for inter-node authentication | — |
cluster.capabilities | Capabilities this worker handles (worker mode only) | — |
cluster.workers | Worker registry mapping capabilities to endpoints (core mode only) | — |
Worker endpoint options:
| Property | Description | Default |
|---|---|---|
url | Worker base URL (required) | — |
timeoutMs | Request timeout in milliseconds | 5000 |
healthCheckPath | Health check endpoint path | /health |
healthCheckIntervalMs | Health check interval | 30000 |
Security
Section titled “Security”The core and workers authenticate using a shared secret passed via the X-MolnOS-Cluster-Secret header. Always use a strong, randomly generated secret. For production deployments, use HTTPS between nodes.
Health Checking
Section titled “Health Checking”The core node monitors worker health automatically. After 3 consecutive health check failures, a worker is marked unhealthy and requests return 503 Service Unavailable. Workers recover automatically when health checks succeed again.
Example: Functions on Separate Host
Section titled “Example: Functions on Separate Host”Core node (main.example.com):
{ "molnos": { "dataPath": "data", "cluster": { "mode": "core", "secret": "s3cr3t-k3y", "workers": { "functions": { "url": "http://compute.example.com:3000" } } } }}Worker node (compute.example.com):
{ "molnos": { "cluster": { "mode": "worker", "secret": "s3cr3t-k3y", "capabilities": ["functions"] } }}Requests to /functions/* on the core are proxied to the worker. The worker validates the cluster secret and processes the request.
Service Management in Cluster Mode
Section titled “Service Management in Cluster Mode”Service management (start/stop/restart) works transparently across the cluster. When you manage a service assigned to a remote worker, the core automatically forwards the command to the appropriate worker node.
Console → Core management API → Core forwards to Worker- The same API endpoints work regardless of where the service runs
- Workers validate the cluster secret before accepting management commands
- If a worker is unreachable, the management operation returns an error