Skip to content

Builtin Authentication

Builtin authentication provides user management with role-based access control (RBAC) using JWT tokens.

Pro License

User management and RBAC require a Dagu Pro license.

Features

  • User Management (Pro): Create, update, and delete users through the web UI
  • Role-Based Access Control (Pro): Five 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

RolePermissions
adminFull access including user management
managerCreate, edit, delete, run, and stop DAGs; can view audit logs
developerCreate, edit, delete, run, and stop DAGs
operatorRun and stop DAGs (execute only)
viewerRead-only access to DAGs and execution history

Configuration

YAML Configuration

yaml
# ~/.config/dagu/config.yaml
auth:
  mode: builtin  # default — can be omitted
  builtin:
    token:
      secret: your-secure-random-secret-key  # auto-generated if not set
      ttl: 24h
    initial_admin:              # optional — auto-create admin on first startup
      username: admin
      password: your-secure-password

Token TTL Format

The ttl field uses Go's duration format. Valid time units are:

UnitDescriptionExample
nsnanoseconds1000000ns
us (or µs)microseconds1000us
msmilliseconds1000ms
sseconds3600s
mminutes60m
hhours24h

Note: Days (d) and weeks (w) are not supported. Use hours instead.

Common TTL examples:

DurationValue
1 hour1h
8 hours8h
24 hours (1 day)24h
7 days168h
30 days720h
365 days8760h

You can also combine units: 1h30m, 2h45m30s

Environment Variables

bash
export DAGU_AUTH_MODE=builtin  # default — can be omitted

# Optional - token settings
export DAGU_AUTH_TOKEN_SECRET=your-secure-random-secret-key  # auto-generated if not set
export DAGU_AUTH_TOKEN_TTL=24h  # default: 24h

# Optional - auto-create admin on first startup (both required together)
export DAGU_AUTH_BUILTIN_INITIAL_ADMIN_USERNAME=admin
export DAGU_AUTH_BUILTIN_INITIAL_ADMIN_PASSWORD=your-secure-password

dagu start-all

Initial Setup

On first startup with builtin auth enabled and no users in the store:

Option A: Via config or environment variables (headless)

Set initial_admin.username and initial_admin.password in the config file or via DAGU_AUTH_BUILTIN_INITIAL_ADMIN_USERNAME and DAGU_AUTH_BUILTIN_INITIAL_ADMIN_PASSWORD environment variables. The server creates the admin user at startup and is immediately ready — no browser interaction required.

yaml
auth:
  mode: builtin
  builtin:
    initial_admin:
      username: admin
      password: a-strong-password-here

Both fields must be provided together. If only one is set, the server fails validation and does not start.

The admin is only created when the user store is empty (zero users). On subsequent restarts, the config is ignored and the existing users are untouched. If all users are deleted and the config is still present, the admin is re-created on the next restart.

If the password is shorter than 8 characters or the user store is unwritable, the server exits with a non-zero code. It does not fall back to the setup page.

The server emits a warning at startup if the password matches a known weak value (password, changeme, admin, dagu, 12345678).

Option B: Via the setup page (interactive)

  1. Visit the web UI — you will be redirected to the /setup page
  2. Create your initial admin account with a username and password
  3. After setup, you are automatically authenticated and redirected to the dashboard

API Access

Login

bash
# Get JWT token
curl -X POST http://localhost:8080/api/v1/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

bash
# Include token in Authorization header
curl -H "Authorization: Bearer eyJhbG..." \
  http://localhost:8080/api/v1/dags

Get Current User

bash
curl -H "Authorization: Bearer eyJhbG..." \
  http://localhost:8080/api/v1/auth/me

Change Password (Self)

bash
curl -X POST http://localhost:8080/api/v1/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

bash
curl -H "Authorization: Bearer eyJhbG..." \
  http://localhost:8080/api/v1/users

Create User

bash
curl -X POST http://localhost:8080/api/v1/users \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{"username": "newuser", "password": "secure-pass", "role": "operator"}'

Update User

bash
curl -X PUT http://localhost:8080/api/v1/users/{user-id} \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{"role": "manager"}'

Reset User Password (Admin)

bash
curl -X PUT http://localhost:8080/api/v1/users/{user-id}/password \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{"newPassword": "new-secure-pass"}'

Delete User

bash
curl -X DELETE http://localhost:8080/api/v1/users/{user-id} \
  -H "Authorization: Bearer eyJhbG..."

Disable/Enable User

Disabled users cannot log in or access the API, but their account is preserved:

bash
# Disable a user
curl -X PATCH http://localhost:8080/api/v1/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/v1/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

yaml
services:
  dagu:
    image: ghcr.io/dagu-org/dagu:latest
    environment:
      - DAGU_AUTH_MODE=builtin
      - DAGU_AUTH_TOKEN_SECRET=change-me-to-secure-random-string
      # Auto-create admin on first startup (remove after first run if desired)
      - DAGU_AUTH_BUILTIN_INITIAL_ADMIN_USERNAME=admin
      - DAGU_AUTH_BUILTIN_INITIAL_ADMIN_PASSWORD=${ADMIN_PASSWORD}
    ports:
      - "8080:8080"
    volumes:
      - dagu-data:/var/lib/dagu

volumes:
  dagu-data:

If DAGU_AUTH_BUILTIN_INITIAL_ADMIN_USERNAME and DAGU_AUTH_BUILTIN_INITIAL_ADMIN_PASSWORD are not set, the server shows the /setup page on first visit instead.

Important Notes

  • Basic vs Builtin: Basic auth (auth.mode=basic) and builtin auth (auth.mode=builtin) are mutually exclusive. When using builtin mode, basic auth credentials are not used.

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)
  • Legacy API: The old legacy API routes have been removed. All API access uses the current /api/v1 endpoints, which require authentication when builtin auth is enabled.
  • Terminal Access: The web-based terminal is disabled by default. Enable with terminal.enabled: true only 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

bash
# Create an API key via the API (requires admin JWT token)
curl -X POST http://localhost:8080/api/v1/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/v1/dags

Key Features

  • Role Assignment: Each API key has its own role (admin, manager, developer, 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 (Pro)

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 (client_id, client_secret, client_url, issuer) are configured. No explicit enabled flag is needed.

yaml
auth:
  mode: builtin
  builtin:
    token:
      secret: your-jwt-secret  # auto-generated if not set
      ttl: 24h
  oidc:
    client_id: your-client-id
    client_secret: your-client-secret
    client_url: https://dagu.example.com
    issuer: https://accounts.google.com
    scopes: ["openid", "profile", "email"]
    # auto_signup defaults to true - users are auto-created on first login
    allowed_domains: ["company.com"]
    whitelist: ["partner@external.com"]
    button_label: "Login with SSO"
    role_mapping:
      default_role: viewer  # Role for new users when no mapping matches

Environment Variables

bash
# 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

FieldDescriptionDefault
client_idOAuth2 client ID from your OIDC providerRequired
client_secretOAuth2 client secretRequired
client_urlBase URL of your Dagu instanceRequired
issuerOIDC provider URLRequired
scopesOAuth2 scopes to request["openid", "profile", "email"]
auto_signupAuto-create users on first OIDC logintrue
allowed_domainsEmail domains allowed to authenticateAll domains
whitelistSpecific email addresses always allowedNone
button_labelText displayed on the SSO login button"Login with SSO"
role_mapping.default_roleRole assigned to new users when no mapping matchesviewer

Note: allowed_domains, whitelist, and scopes can be specified as either YAML lists or comma-separated strings. This is especially useful for environment variables.

Auto-Signup

When auto_signup is enabled (the default), users authenticating via OIDC for the first time are automatically created in Dagu with the role specified by role_mapping.default_role. This eliminates the need to pre-create user accounts.

When auto_signup is disabled, users must exist in Dagu before they can log in via OIDC.

Domain Filtering

Use allowed_domains to restrict OIDC login to specific email domains:

yaml
oidc:
  allowed_domains: ["company.com", "subsidiary.com"]

Users with emails outside these domains will be denied access.

Email Whitelist

Use whitelist to allow specific email addresses:

yaml
oidc:
  whitelist: ["allowed@example.com", "admin@example.com"]

Access Control Logic:

  • If whitelist is set: only emails in the whitelist are allowed
  • If allowed_domains is set: only emails from those domains are allowed
  • If both are set: email must match whitelist OR domain must match allowed_domains
  • If neither is set: all authenticated emails are allowed
yaml
# Example: Allow company.com domain + specific external partners
oidc:
  allowed_domains: ["company.com"]
  whitelist: ["partner@external.com", "contractor@other.com"]

Role Mapping

Map IdP groups to Dagu roles for automatic role assignment:

yaml
oidc:
  role_mapping:
    default_role: viewer           # Role when no mapping matches (default: viewer)
    groups_claim: groups           # Claim containing user's groups
    group_mappings:
      admins: admin               # IdP group -> Dagu role
      developers: developer
      ops: operator
      everyone: viewer
    role_attribute_strict: false    # Deny login if no role matched
    skip_org_role_sync: false        # Sync roles on every login

Role Mapping Options:

FieldDescriptionDefault
default_roleRole assigned when no mapping matchesviewer
groups_claimJWT claim containing group membershipgroups
group_mappingsMap of IdP group names to Dagu rolesNone
role_attribute_pathjq expression for advanced role extractionNone
role_attribute_strictDeny login when no valid role is foundfalse
skip_org_role_syncOnly assign role on first loginfalse

Example with jq expression:

yaml
role_mapping:
  default_role: viewer
  role_attribute_path: 'if (.groups | contains(["admins"])) then "admin" elif (.groups | contains(["devs"])) then "developer" else "viewer" end'

How It Works

  1. User clicks "Login with SSO" on the login page
  2. Redirected to OIDC provider for authentication
  3. After successful authentication, Dagu validates the token
  4. If auto_signup is enabled and user doesn't exist, a new user is created
  5. Role is determined by role_mapping (if configured) or default_role
  6. 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 {client_url}/oidc-callback

Comparison with Other Auth Methods

FeatureBasic AuthToken AuthOIDC (standalone)Builtin (Recommended)
User ManagementNoNoNoYes
Role-Based AccessNoNoNoYes
Password ChangeNoNoNoYes
Multiple UsersNoNoYesYes
API Key ManagementNoNoNoYes
SSO/OIDC LoginNoNoYesYes
Role Mapping from IdPNoNoNoYes
Self-HostedYesYesYesYes

Builtin mode (auth.mode: builtin) is suitable for production deployments that require user management and RBAC. Enable OIDC under builtin mode for SSO while retaining full user management capabilities.

Released under the MIT License.