Critical fixes: - Update APP_DB_VERSION to 234 to trigger migration (was 233) * Without this, the migration would never run * Migration is now correctly applied on server start Documentation improvements in MULTI_USER.md: - Clarify use of user_data table (OAuth v229) vs user_info (MFA) - Explain why users are NOT Becca entities: * Auth data should never be synced for security * Becca is for synchronized content only * Each instance needs isolated user databases - Document future sync support requirements - Add note about migration triggering mechanism This addresses eliandoran's comments on PR #7441: - Migration not applying due to version mismatch - Question about user_info vs user_data table - Concern about Becca entity model integration - Question about cross-instance synchronization
6.7 KiB
Multi-User Support for Trilium Notes
This document describes the multi-user functionality added to Trilium Notes.
Overview
Trilium now supports multiple users with role-based access control. Each user has their own credentials and can be assigned different roles (Admin, User, or Viewer).
Architecture
Database Schema
Multi-user support extends the existing user_data table (introduced in migration v229 for OAuth support).
Important Design Decisions:
-
Why
user_datatable? eliandoran asked about usinguser_infotable from MFA. We useuser_databecause it's the established table from OAuth migration (v229) with existing password hashing infrastructure. -
Why not Becca entities? Users are NOT implemented as Becca entities because:
- Becca entities are for synchronized content (notes, branches, attributes, etc.)
- User authentication data should never be synced across instances for security
- Each Trilium instance needs its own isolated user database
- Syncing user credentials would create massive security risks
-
Future sync support: When multi-user sync is implemented, it will need:
- Per-user sync credentials on each instance
- User-to-user mappings across instances
- Separate authentication from content synchronization
- This is documented as a future enhancement
user_data table fields:
tmpID: INTEGER primary keyusername: User's login nameemail: Optional email addressuserIDVerificationHash: Password hash (scrypt)salt: Password saltderivedKey: Key derivation saltuserIDEncryptedDataKey: Encrypted data key (currently unused)isSetup: 'true' or 'false' stringrole: 'admin', 'user', or 'viewer'isActive: 1 (active) or 0 (inactive)utcDateCreated: Creation timestamputcDateModified: Last modification timestamp
User Roles
- Admin: Full access to all notes and user management
- User: Can create, read, update, and delete their own notes
- Viewer: Read-only access to their notes
Migration (v234)
Migration Triggering: This migration runs automatically on next server start because the database version was updated to 234 in app_info.ts.
The migration automatically:
- Extends the
user_datatable with role and status fields - Adds
userIdcolumns to notes, branches, etapi_tokens, and recent_notes tables - Creates a default admin user from existing single-user credentials
- Associates all existing data with the admin user (tmpID=1)
- Maintains backward compatibility with single-user installations
Setup
For New Installations
On first login, set a password as usual. This creates the default admin user.
For Existing Installations
When you upgrade, the migration runs automatically:
- Your existing password becomes the admin user's password
- Username defaults to "admin"
- All your existing notes remain accessible
Creating Additional Users
After migration, you can create additional users via the REST API:
# Create a new user (requires admin privileges)
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-H "Cookie: connect.sid=YOUR_SESSION_COOKIE" \
-d '{
"username": "newuser",
"email": "user@example.com",
"password": "securepassword",
"role": "user"
}'
API Endpoints
All endpoints require authentication. Most require admin privileges.
List Users
GET /api/users
Query params: includeInactive=true (optional)
Requires: Admin
Get User
GET /api/users/:userId
Requires: Admin or own user
Create User
POST /api/users
Body: { username, email?, password, role? }
Requires: Admin
Update User
PUT /api/users/:userId
Body: { email?, password?, isActive?, role? }
Requires: Admin (or own user for email/password only)
Delete User
DELETE /api/users/:userId
Requires: Admin
Note: Soft delete (sets isActive=0)
Get Current User
GET /api/users/current
Requires: Authentication
Check Username Availability
GET /api/users/check-username?username=testuser
Requires: Authentication
Login
Single-User Mode
If only one user exists, login works as before (password-only).
Multi-User Mode
When multiple users exist:
- Username field appears on login page
- Enter username + password to authenticate
- Session stores user ID and role
Security
- Passwords are hashed using scrypt (N=16384, r=8, p=1)
- Each user has unique salt
- Sessions are maintained using express-session
- Users can only access their own notes (except admins)
Backward Compatibility
- Single-user installations continue to work without changes
- No username field shown if only one user exists
- Existing password continues to work after migration
- All existing notes remain accessible
Limitations
- No per-note sharing between users yet (planned for future)
- No user interface for user management (use API)
- Sync protocol not yet multi-user aware
- No user switching without logout
Future Enhancements
- UI for User Management: Add settings dialog for creating/managing users
- Note Sharing: Implement per-note sharing with other users
- Sync Support: Update sync protocol for multi-instance scenarios
- User Switching: Allow switching users without logout
- Groups: Add user groups for easier permission management
- Audit Log: Track user actions for security
Troubleshooting
Can't log in after migration
- Try username "admin" with your existing password
- Check server logs for migration errors
Want to reset admin password
- Stop Trilium
- Access document.db directly
- Update the user_data table manually
- Restart Trilium
Want to disable multi-user
Not currently supported. Once migrated, single-user mode won't work if additional users exist.
Technical Details
Files Modified
apps/server/src/migrations/0234__multi_user_support.ts- Migrationapps/server/src/services/user_management.ts- User management serviceapps/server/src/routes/api/users.ts- REST API endpointsapps/server/src/routes/login.ts- Multi-user login logicapps/server/src/services/auth.ts- Authentication middlewareapps/server/src/express.d.ts- Session type definitionsapps/server/src/assets/views/login.ejs- Login page UI
Testing
# Run tests
pnpm test
# Build
pnpm build
# Check TypeScript
pnpm --filter @triliumnext/server typecheck
Contributing
When extending multi-user support:
- Always test with both single-user and multi-user modes
- Maintain backward compatibility
- Update this documentation
- Add tests for new functionality
Support
For issues or questions:
- GitHub Issues: https://github.com/TriliumNext/Trilium/issues
- Discussions: https://github.com/orgs/TriliumNext/discussions