Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/noelzappy/vaulx/llms.txt

Use this file to discover all available pages before exploring further.

Vaulx uses a built-in user system backed by PostgreSQL. Admins can create and manage accounts directly from the /admin/users panel, assigning one of three roles to each user. On first boot, the server automatically seeds a single admin account from environment variables so there is always a way in. Every user action that modifies an account — including role changes, deactivations, and password updates — is recorded in the audit log.

User model

Each user is stored in the users table. The schema is defined in migrations/001_initial.up.sql:
CREATE TABLE users (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email         TEXT UNIQUE NOT NULL,
  name          TEXT NOT NULL,
  role          TEXT NOT NULL CHECK (role IN ('admin', 'editor', 'viewer')),
  password_hash TEXT NOT NULL,
  active        BOOLEAN NOT NULL DEFAULT TRUE,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
FieldTypeNotes
idUUIDAuto-generated primary key
emailTEXTUnique — login identifier
nameTEXTDisplay name shown in the sidebar
roleTEXTOne of admin, editor, or viewer
password_hashTEXTbcrypt hash at DefaultCost
activeBOOLEANtrue by default; set false to block login
created_atTIMESTAMPTZSet automatically on insert

Admin seeding on first boot

When the server starts and the users table is empty, seed.AdminUser is called automatically. It reads SEED_ADMIN_EMAIL and SEED_ADMIN_PASSWORD from the environment and creates a single admin account with the name "Admin". If either variable is missing, seeding is skipped with a log warning. On subsequent starts the seed is a no-op — it only runs when COUNT(*) = 0.
SEED_ADMIN_EMAIL=admin@yourdomain.com
SEED_ADMIN_PASSWORD=Ch4ngeMe99
Change SEED_ADMIN_PASSWORD to a strong, unique value before exposing Vaulx publicly. The seed step passes the password directly to bcrypt — no minimum-length check is enforced at seed time.

Creating a user (admin only)

1

Open the admin panel

Navigate to /admin/users. Only users with role = 'admin' can access this page; all others receive a 403 Access denied response.
2

Submit the create-user form

Fill in all required fields and submit to POST /admin/users. On success the server redirects back to /admin/users. If the email is already in use you receive a 409 Conflict response.
Route: POST /admin/users
email
string
required
The user’s email address. Must be unique across all accounts.
name
string
required
The user’s display name shown in the UI.
role
string
required
One of viewer, editor, or admin.
RoleCan do
viewerBrowse and download files they have access to
editorUpload files, create/rename/soft-delete their own files and folders, create share links
adminEverything — manage users, hard-delete files, grant permissions, view audit log
password
string
required
Plain-text password hashed with bcrypt DefaultCost before storage. The server does not enforce a minimum length at this endpoint — use a strong password as a matter of practice.

Listing users

Route: GET /admin/users Admin-only. Returns an HTML page showing every account in the system ordered by created_at DESC, including each user’s email, display name, role, and active status. Non-admin requests receive 403.

Updating a user

Route: PATCH /admin/users/{userID} Admins can update a user’s role, their active status, or both in a single request. Supply only the fields you want to change; omitted fields are left untouched. On success the response includes an HX-Trigger header that fires a showToast event with the message "User updated".
role
string
New role for the user. Must be one of viewer, editor, or admin. Omit to leave the current role unchanged.
active
string
Pass "true" to re-enable a deactivated account or "false" to deactivate an active one. Omit to leave active status unchanged.

Deactivating a user

Setting active=false via PATCH /admin/users/{userID} immediately blocks the user from logging in. The GetUserByEmail query enforces active = true at the database level:
-- name: GetUserByEmail :one
SELECT * FROM users
WHERE email = $1 AND active = true
LIMIT 1;
Any subsequent login attempt with a deactivated account will fail at the authentication query even if the password is correct. Existing sessions are not automatically invalidated, but deactivated users cannot initiate any new session.
Deactivating an admin account while it is the only admin will lock you out of the admin panel. Always ensure at least one other active admin account exists before deactivating an admin.

Profile self-service

Any authenticated user can view and update their own profile without admin involvement.
Route: GET /profileRenders the profile page showing the current user’s name, email, and role. Accepts an optional ?success=name or ?success=password query parameter to display a confirmation message after a successful update.
All passwords are hashed with bcrypt.GenerateFromPassword at bcrypt.DefaultCost before being written to the database. Plain-text passwords are never stored. The session cookie is refreshed after a successful name change so the sidebar reflects the update without a re-login.

Build docs developers (and LLMs) love