User handling enables multiple independent users to share a single Hister instance. Each user has their own credentials, their own isolated search index, and their own access token for API clients. User handling is disabled by default, making Hister fully backward compatible. Existing single-user setups require no changes.
Activation
Set user_handling: true in the app section of your configuration file:
app:
user_handling: true Note: When
user_handlingis active,access_tokenis used only to authenticate users by comparing it to the user’s access token. This can be useful when the Hister admin setsapp.access_tokenin the configuration file to their personal access token in order to execute command-line Hister commands as the admin user.
After enabling user handling, restart the server and create at least one user account before attempting to log in.
Authentication
Web Interface
When user handling is enabled, the web interface presents a login page to unauthenticated visitors. Enter your username and password to log in. Your session is maintained via a secure HTTP-only cookie valid for one year.
If OAuth providers are configured, the login page also shows Sign in with <Provider> buttons. See OAuth Login below.
OAuth Login
Hister supports signing in via GitHub, Google, or any OpenID Connect provider when server.oauth is configured. No password is required for OAuth accounts.
When a user signs in via OAuth for the first time, Hister automatically creates a local account linked to their provider identity (GitHub login name, Google email, or OIDC preferred username). Subsequent logins with the same provider identity reuse the same account.
OAuth accounts work identically to password accounts: they have their own isolated search index, personal access token, rules, and aliases. An OAuth user can generate a personal access token from their profile page to use with the CLI or browser extension.
See the OAuth section of the configuration docs for setup instructions.
OAuth-Only Mode
Setting server.oauth_only: true disables password logins entirely. Only OAuth sign-in is accepted through the web interface. The login page hides the credential form and shows only the OAuth provider buttons.
This is useful when you want to enforce a single sign-on policy and prevent users from bypassing it with locally-set passwords.
The global app.access_token and per-user personal access tokens continue to work even when oauth_only is enabled, so API clients and CLI tools are unaffected.
See the OAuth-Only Mode section of the configuration docs for the full configuration reference.
Browser Extension
The extension authenticates by copying the session cookies from the already-logged-in web interface:
- Log in to the Hister web interface in the same browser.
- Click the Authenticate Extension button in the extension popup (or options page).
The extension will copy the active session cookies from the web UI. All pages indexed through the extension are stored under your user account.
API / Command-Line Client
The hister CLI and any API client can authenticate using the personal access token via the X-Access-Token header:
curl -H "X-Access-Token: <your-token>" http://localhost:4433/api/stats When using the hister CLI with user handling, pass your token with the -t flag:
hister -t <your-token> search "query" User Management Commands
All user management commands require user_handling: true in the configuration and direct access to the Hister server host (they operate on the database directly, not over the API).
create-user
Create a new user account. Prompts interactively for a password (minimum 8 characters).
hister create-user USERNAME [--admin] | Flag | Description |
|---|---|
--admin | Grant the user admin privileges. |
delete-user
Permanently delete a user account (soft delete).
hister delete-user USERNAME show-user
Display information about a user account.
hister show-user USERNAME [--token] | Flag | Description |
|---|---|
--token | Also display the user’s access token. |
Example output:
Username: alice
ID: 1
Admin: yes
Created at: 2026-03-26 09:00:00
Updated at: 2026-03-26 09:00:00 update-user
Modify an existing user account. At least one flag must be provided.
hister update-user USERNAME [--username NEW] [--regen-token] [--toggle-admin] | Flag | Description |
|---|---|
--username NEW | Rename the user to NEW. |
--regen-token | Generate a new access token and print it. Invalidates the old one. |
--toggle-admin | Toggle admin status on or off. |
Flags may be combined. When --username is used together with other flags, the rename is applied first.
Per-User Rules and Aliases
When user handling is enabled, each user has their own set of rules and aliases stored in the database. Changes made through the web UI or API affect only the authenticated user’s rules and do not modify the configuration file.
- Skip rules: URLs matching a user’s skip rules are silently ignored when indexing, just as in single-user mode.
- Priority rules: A user’s priority rules boost matching results to the top of their search results.
- Versioning rules: URLs matching a user’s versioning rules have their content diffed and stored on each re-index.
- Search aliases: Aliases defined by a user apply only to that user’s searches.
Users can view and edit their rules and aliases through the Rules tab in the web interface, or via the API endpoints.
In single-user mode (user handling disabled), rules and aliases continue to be read from and written to the configuration file on disk.
Regexp
Skip rules apply upon the full URL (from protocol to the query-string parameters) and limited
- Anchoring must include the protocol: Eg
^https://foo.comor^https?://(login|mail)\.but no^foo.com /login$would not matchhttps://foo.com/login?auth=1- URL hash is removed (
https://foo.com/#active-tab->https://foo.com/) - Query-string parameters are not reordered and barely stripped (only
utm_*at the moment) - Go regular expression does not support look-ahead/look-behind regexp.
Admin Users
Admin users have access to privileged operations. Currently, the following endpoints require admin privileges:
POST /api/reindexrebuilds the entire full-text search index.
Non-admin users receive 403 Forbidden when attempting to call admin-only endpoints.
Grant or revoke admin status using create-user --admin (at creation time) or update-user --toggle-admin (at any time).
Single User Compatibility
Hister reserves user ID 0 for unauthenticated use. Documents indexed without user handling enabled are stored under user ID 0 and remain visible to all authenticated users after the feature is turned on. This means you can enable user handling on an existing instance without losing access to previously indexed content.
Document Isolation
Each user’s indexed documents are stored with their user ID. Searches are automatically scoped to:
- Documents indexed by the authenticated user.
- Documents indexed without user handling enabled (user ID
0). These act as a shared, read-only baseline visible to everyone.
Users cannot see each other’s documents.
The document count shown on the home page reflects the authenticated user’s own document count rather than the total across all users.
Personal Access Tokens
Every user account has a personal access token used for API authentication. Tokens are random and stored in the database.
- Generate a new token from the web UI (Profile → Generate Token) or via
hister update-user --regen-token. - Generating a new token immediately invalidates the previous one. Update any clients (browser extension, scripts) accordingly.
- Tokens are not displayed in
show-useroutput by default; use--tokento reveal them.
Profile API
The /api/profile endpoint returns information about the currently authenticated user:
{
"user_id": 1,
"username": "alice",
"is_admin": true
} Security Considerations
- Passwords are hashed with bcrypt before storage and are never returned by any API.
- Sessions are stored in signed HTTP-only cookies. The signing key is derived from Hister’s secret key file.
- Personal access tokens bypass session cookies and can be used in scripts. Keep them secret and regenerate them if compromised.
- OAuth state tokens are single-use random values stored in the session cookie. They prevent cross-site request forgery during the OAuth redirect flow.
- OAuth accounts have no password set. If you need to disable an OAuth user’s access, use
hister delete-useror remove the provider from the configuration. - Enable
server.oauth_only: trueto enforce OAuth-only login and prevent password authentication. Per-user access tokens and the globalapp.access_tokenremain valid for API and CLI access. - User handling is intended for a trusted group of users on a shared instance (family, team). For public-facing deployments, place Hister behind a reverse proxy with HTTPS.