Builtin Authentication
Builtin authentication provides user management with role-based access control (RBAC) using JWT tokens.
Features
- User Management: Create, update, and delete users through the web UI
- Role-Based Access Control: Four roles with different permission levels
- JWT Authentication: Secure token-based authentication
- Password Management: Users can change their own passwords; admins can reset any user's password
- API Key Management: Create and manage API keys for programmatic access with role-based permissions
Roles
| Role | Permissions |
|---|---|
admin | Full access including user management |
manager | Create, edit, delete, run, and stop DAGs |
operator | Run and stop DAGs (execute only) |
viewer | Read-only access to DAGs and execution history |
Configuration
YAML Configuration
# ~/.config/dagu/config.yaml
auth:
mode: builtin
builtin:
admin:
username: admin
# password: optional - auto-generated if not set
token:
secret: your-secure-random-secret-key
ttl: 24h
# Optional: API token for programmatic access (works alongside JWT)
token:
value: your-api-tokenToken TTL Format
The ttl field uses Go's duration format. Valid time units are:
| Unit | Description | Example |
|---|---|---|
ns | nanoseconds | 1000000ns |
us (or µs) | microseconds | 1000us |
ms | milliseconds | 1000ms |
s | seconds | 3600s |
m | minutes | 60m |
h | hours | 24h |
Note: Days (d) and weeks (w) are not supported. Use hours instead.
Common TTL examples:
| Duration | Value |
|---|---|
| 1 hour | 1h |
| 8 hours | 8h |
| 24 hours (1 day) | 24h |
| 7 days | 168h |
| 30 days | 720h |
| 365 days | 8760h |
You can also combine units: 1h30m, 2h45m30s
Environment Variables
# Required
export DAGU_AUTH_MODE=builtin
export DAGU_AUTH_TOKEN_SECRET=your-secure-random-secret-key
# Optional - admin credentials
export DAGU_AUTH_ADMIN_USERNAME=admin # default: admin
export DAGU_AUTH_ADMIN_PASSWORD= # auto-generated if not set
# Optional - token settings
export DAGU_AUTH_TOKEN_TTL=24h # default: 24h
dagu start-allInitial Setup
On first startup with builtin auth enabled:
- If no users exist, an admin user is automatically created
- If
DAGU_AUTH_ADMIN_PASSWORDis not set, a secure password is auto-generated and printed to stdout:
================================================================================
ADMIN USER CREATED
Username: admin
Password: <auto-generated-password>
NOTE: Please change this password immediately!
================================================================================- Use these credentials to log in and access the user management page
API Access
Login
# Get JWT token
curl -X POST http://localhost:8080/api/v2/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "your-password"}'
# Response:
# {"token": "eyJhbG...", "user": {"id": "...", "username": "admin", "role": "admin"}}Using the Token
# Include token in Authorization header
curl -H "Authorization: Bearer eyJhbG..." \
http://localhost:8080/api/v2/dagsGet Current User
curl -H "Authorization: Bearer eyJhbG..." \
http://localhost:8080/api/v2/auth/meChange Password (Self)
curl -X POST http://localhost:8080/api/v2/auth/change-password \
-H "Authorization: Bearer eyJhbG..." \
-H "Content-Type: application/json" \
-d '{"currentPassword": "old-pass", "newPassword": "new-pass"}'User Management (Admin Only)
List Users
curl -H "Authorization: Bearer eyJhbG..." \
http://localhost:8080/api/v2/usersCreate User
curl -X POST http://localhost:8080/api/v2/users \
-H "Authorization: Bearer eyJhbG..." \
-H "Content-Type: application/json" \
-d '{"username": "newuser", "password": "secure-pass", "role": "operator"}'Update User
curl -X PUT http://localhost:8080/api/v2/users/{user-id} \
-H "Authorization: Bearer eyJhbG..." \
-H "Content-Type: application/json" \
-d '{"role": "manager"}'Reset User Password (Admin)
curl -X PUT http://localhost:8080/api/v2/users/{user-id}/password \
-H "Authorization: Bearer eyJhbG..." \
-H "Content-Type: application/json" \
-d '{"newPassword": "new-secure-pass"}'Delete User
curl -X DELETE http://localhost:8080/api/v2/users/{user-id} \
-H "Authorization: Bearer eyJhbG..."Disable/Enable User
Disabled users cannot log in or access the API, but their account is preserved:
# Disable a user
curl -X PATCH http://localhost:8080/api/v2/users/{user-id} \
-H "Authorization: Bearer eyJhbG..." \
-H "Content-Type: application/json" \
-d '{"isDisabled": true}'
# Enable a user
curl -X PATCH http://localhost:8080/api/v2/users/{user-id} \
-H "Authorization: Bearer eyJhbG..." \
-H "Content-Type: application/json" \
-d '{"isDisabled": false}'Note: You can also disable/enable users from the web UI via the user management page. This is useful for revoking access without deleting the user account.
Docker Compose Example
services:
dagu:
image: ghcr.io/dagu-org/dagu:latest
environment:
- DAGU_AUTH_MODE=builtin
- DAGU_AUTH_TOKEN_SECRET=change-me-to-secure-random-string
# Password auto-generated on first run, printed to stdout
ports:
- "8080:8080"
volumes:
- dagu-data:/var/lib/dagu
volumes:
dagu-data:Important Notes
Basic Auth Ignored: When
auth.modeis set tobuiltin, anyauth.basicconfiguration is ignored. A warning will be logged. Use the builtin admin credentials instead.API Token Support: API tokens (
auth.token.value) work alongside builtin auth for programmatic access without requiring JWT login.yamlauth: mode: builtin builtin: token: secret: your-jwt-secret token: value: your-api-token # Use with: curl -H "Authorization: Bearer your-api-token"
Security Notes
- Token Secret: Use a strong, random secret (at least 32 characters). This is used to sign JWT tokens.
- Password Requirements: Minimum 8 characters
- Token Expiry: Tokens expire after the configured TTL (default: 24 hours)
- V1 API: The V1 API is disabled when builtin auth is enabled (use V2 API)
- Terminal Access: The web-based terminal is disabled by default. Enable with
terminal.enabled: trueonly in trusted environments. See Terminal Configuration. - Audit Logging: Security events (logins, user changes, API key operations) are logged by default. See Audit Logging.
API Key Management
Builtin authentication includes full API key management capabilities. API keys provide programmatic access with role-based permissions, ideal for CI/CD pipelines, automation scripts, and service-to-service communication.
Quick Start
# Create an API key via the API (requires admin JWT token)
curl -X POST http://localhost:8080/api/v2/api-keys \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "ci-pipeline", "role": "operator"}'
# Use the API key
curl -H "Authorization: Bearer dagu_your-api-key-here" \
http://localhost:8080/api/v2/dagsKey Features
- Role Assignment: Each API key has its own role (admin, manager, operator, viewer)
- Usage Tracking: See when each key was last used
- Web UI Management: Create and manage keys from Settings > API Keys
- Secure Storage: Keys are hashed; the full key is only shown once at creation
For detailed documentation, see API Keys.
OIDC/SSO Login
Builtin authentication supports OIDC/SSO login, allowing users to authenticate via enterprise identity providers (Google, Okta, Auth0, Keycloak, etc.) while maintaining Dagu's user management and RBAC system.
Enabling OIDC
OIDC is automatically enabled when all required fields (clientId, clientSecret, clientUrl, issuer) are configured. No explicit enabled flag is needed.
auth:
mode: builtin
builtin:
admin:
username: admin
token:
secret: your-jwt-secret
ttl: 24h
oidc:
clientId: your-client-id
clientSecret: your-client-secret
clientUrl: https://dagu.example.com
issuer: https://accounts.google.com
scopes: ["openid", "profile", "email"]
# autoSignup defaults to true - users are auto-created on first login
allowedDomains: ["company.com"]
whitelist: ["partner@external.com"]
buttonLabel: "Login with SSO"
roleMapping:
defaultRole: viewer # Role for new users when no mapping matchesEnvironment Variables
# OIDC configuration (auto-enabled when all required fields are set)
export DAGU_AUTH_OIDC_CLIENT_ID=your-client-id
export DAGU_AUTH_OIDC_CLIENT_SECRET=your-client-secret
export DAGU_AUTH_OIDC_CLIENT_URL=https://dagu.example.com
export DAGU_AUTH_OIDC_ISSUER=https://accounts.google.com
# Optional settings
export DAGU_AUTH_OIDC_AUTO_SIGNUP=true # default: true
export DAGU_AUTH_OIDC_DEFAULT_ROLE=viewer # default: viewer
export DAGU_AUTH_OIDC_ALLOWED_DOMAINS=company.com,other.com # comma-separated
export DAGU_AUTH_OIDC_WHITELIST=user@example.com # comma-separated
export DAGU_AUTH_OIDC_BUTTON_LABEL="Login with SSO"Configuration Fields
| Field | Description | Default |
|---|---|---|
clientId | OAuth2 client ID from your OIDC provider | Required |
clientSecret | OAuth2 client secret | Required |
clientUrl | Base URL of your Dagu instance | Required |
issuer | OIDC provider URL | Required |
scopes | OAuth2 scopes to request | ["openid", "profile", "email"] |
autoSignup | Auto-create users on first OIDC login | true |
allowedDomains | Email domains allowed to authenticate | All domains |
whitelist | Specific email addresses always allowed | None |
buttonLabel | Text displayed on the SSO login button | "Login with SSO" |
roleMapping.defaultRole | Role assigned to new users when no mapping matches | viewer |
Note: allowedDomains, whitelist, and scopes can be specified as either YAML lists or comma-separated strings. This is especially useful for environment variables.
Auto-Signup
When autoSignup is enabled (the default), users authenticating via OIDC for the first time are automatically created in Dagu with the role specified by roleMapping.defaultRole. This eliminates the need to pre-create user accounts.
When autoSignup is disabled, users must exist in Dagu before they can log in via OIDC.
Domain Filtering
Use allowedDomains to restrict OIDC login to specific email domains:
oidc:
allowedDomains: ["company.com", "subsidiary.com"]Users with emails outside these domains will be denied access.
Email Whitelist
Use whitelist to allow specific email addresses:
oidc:
whitelist: ["allowed@example.com", "admin@example.com"]Access Control Logic:
- If
whitelistis set: only emails in the whitelist are allowed - If
allowedDomainsis set: only emails from those domains are allowed - If both are set: email must match whitelist OR domain must match allowedDomains
- If neither is set: all authenticated emails are allowed
# Example: Allow company.com domain + specific external partners
oidc:
allowedDomains: ["company.com"]
whitelist: ["partner@external.com", "contractor@other.com"]Role Mapping
Map IdP groups to Dagu roles for automatic role assignment:
oidc:
roleMapping:
defaultRole: viewer # Role when no mapping matches (default: viewer)
groupsClaim: groups # Claim containing user's groups
groupMappings:
admins: admin # IdP group -> Dagu role
developers: manager
ops: operator
everyone: viewer
roleAttributeStrict: false # Deny login if no role matched
skipOrgRoleSync: false # Sync roles on every loginRole Mapping Options:
| Field | Description | Default |
|---|---|---|
defaultRole | Role assigned when no mapping matches | viewer |
groupsClaim | JWT claim containing group membership | groups |
groupMappings | Map of IdP group names to Dagu roles | None |
roleAttributePath | jq expression for advanced role extraction | None |
roleAttributeStrict | Deny login when no valid role is found | false |
skipOrgRoleSync | Only assign role on first login | false |
Example with jq expression:
roleMapping:
defaultRole: viewer
roleAttributePath: 'if (.groups | contains(["admins"])) then "admin" elif (.groups | contains(["devs"])) then "manager" else "viewer" end'How It Works
- User clicks "Login with SSO" on the login page
- Redirected to OIDC provider for authentication
- After successful authentication, Dagu validates the token
- If
autoSignupis enabled and user doesn't exist, a new user is created - Role is determined by
roleMapping(if configured) ordefaultRole - User receives a JWT token for the Dagu session
Notes
- OIDC users are managed alongside local users in the same user database
- OIDC users can also authenticate with their Dagu password if one is set
- Admin users can manage all users (OIDC and local) from the web UI
- The callback URL is
{clientUrl}/oidc-callback
Comparison with Other Auth Methods
| Feature | Basic Auth | Token Auth | OIDC (standalone) | Builtin (Recommended) |
|---|---|---|---|---|
| User Management | No | No | No | Yes |
| Role-Based Access | No | No | No | Yes |
| Password Change | No | No | No | Yes |
| Multiple Users | No | No | Yes | Yes |
| API Key Management | No | No | No | Yes |
| SSO/OIDC Login | No | No | Yes | Yes |
| Role Mapping from IdP | No | No | No | Yes |
| Self-Hosted | Yes | Yes | Yes | Yes |
Recommendation: Use auth.mode: builtin for production deployments. Enable OIDC under builtin mode for SSO while retaining full user management and RBAC capabilities.
