User Handling

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_handling is active, access_token is used only to authenticate users by comparing it to the user’s access token. This can be useful when the Hister admin sets app.access_token in 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:

  1. Log in to the Hister web interface in the same browser.
  2. 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]
FlagDescription
--adminGrant 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]
FlagDescription
--tokenAlso 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]
FlagDescription
--username NEWRename the user to NEW.
--regen-tokenGenerate a new access token and print it. Invalidates the old one.
--toggle-adminToggle 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.com or ^https?://(login|mail)\. but no ^foo.com
  • /login$ would not match https://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/reindex rebuilds 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-user output by default; use --token to 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-user or remove the provider from the configuration.
  • Enable server.oauth_only: true to enforce OAuth-only login and prevent password authentication. Per-user access tokens and the global app.access_token remain 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.