Admin & Access Guide
Administrators control users, folders, and security policies through Settings. This guide walks through the workflows for onboarding admins, managing users, configuring access control, and ensuring data stays protected.
First admin & workspace lock
- During first launch (after you run your Compose file) the Setup screen appears automatically. Create your first local user account and workspace password.
- That account becomes an admin automatically; the backend prevents removing or demoting the final admin.
- The workspace password protects the UI until a user unlocks it. Trusted sessions may remember the password for a short time depending on your session settings.
User management
- Navigate to Settings → Admin → Users to add local users, assign roles, and reset passwords.
- Resetting a password signs that account out of every session it has open, on every device — the sessions opened with a password and the ones opened through the identity provider alike. Someone changing their own password from Settings → Password is signed out everywhere except where they made the change. A changed
AUTH_ADMIN_PASSWORDdoes the same to the administrator at the next start; the same value set again at each restart signs nobody out. - One thing a password change does not end: the tokens already handed to ONLYOFFICE and Collabora for documents open at that moment. Those are signed rather than stored, so there is nothing on the server to withdraw. Each reaches the one file it was minted for, with the rights it was minted with, and expires on its own — within 12 hours for ONLYOFFICE, 6 for Collabora. Reopening the document asks for a new one, which the new password governs. To end them sooner, change
ONLYOFFICE_SECRETorCOLLABORA_SECRETand restart: every token signed with the old value stops working at once, for everyone. - When
USER_VOLUMES=true, each user profile includes a Volumes tab for assigning per-user volumes. See User volumes. - Local users store credentials in the SQLite database inside your
/configmount. - People sign in with either their email address or their username, in the same box. Case does not matter for either.
- A username has to name one account to be usable for signing in. NextExplorer refuses a new account, or a rename, that would take a username another account already has — but an installation upgraded from an older version may already hold duplicates, because the username is derived from the local part of the address (
alice@example.comandalice@other.orgboth becomealice). Where a username answers for more than one account it signs nobody in, and those accounts use their email address instead. Give one of them a different username in Settings → Admin → Users to free it. - Two-factor authentication is each person's to turn on, in Settings → Two-factor: a QR code for any authenticator app, one code to prove the phone kept the secret, and ten recovery codes shown once. From then on that account's sign-in asks for a code after the password. The user list says who has it on. When somebody loses both the phone and the codes, an administrator takes it off for them — the same person who could already reset that account's password — and the account signs in with its password alone until it is set up again. With OIDC the second factor belongs to the provider, and this is for local passwords only.
- Passkeys are each person's to add, in Settings → Passkeys: a fingerprint, a face or a device PIN instead of a password. The device keeps the key and never hands it over, and what it signs names this site — so a passkey cannot be typed into a page pretending to be this one, read over a shoulder, or replayed anywhere else. A passkey that was unlocked to be used is already two things (the device, and whoever can unlock it), so it answers an account's second factor on its own; one used without unlocking still asks for the code. Passkeys are for local accounts, like the second factor; with
AUTH_MODE=oidcthey are not offered.- The browser decides where this can work. A passkey is bound to a hostname, and browsers refuse to make one on a page that is not secure or on an address that is not a name: over plain
http, or athttps://192.168.1.10, the page says so instead of offering a button. Reach the server over https, or throughlocalhost, to add one. - An installation reached through two hostnames has to pick one. A passkey made on
files.example.comis refused onfiles.lan, by design.PUBLIC_URLsettles it where it is set;WEBAUTHN_RP_IDsettles it explicitly. Change either one and the passkeys already made stop working — they belong to the name they were made on. - The last way in is protected. An account with no password is refused the removal of its last passkey, and removing any passkey asks for the password when the account has one.
- When the device that held the passkey is gone, an administrator takes every passkey off that account — the same deliberate act, by the same person, as taking somebody's second factor off. What is left is an account that signs in with its password and adds a passkey again from whatever device is in front of it.
- The browser decides where this can work. A passkey is bound to a hostname, and browsers refuse to make one on a page that is not secure or on an address that is not a name: over plain
- Promote trusted accounts to admin inside the UI—note that demotions are blocked when it would remove the last admin.
- When OIDC is enabled, users are created automatically on first login (unless
OIDC_AUTO_CREATE_USERS=false) and elevated to admin if theirgroups,roles, orentitlementsclaims match any of the names insideOIDC_ADMIN_GROUPS.
Access control policies
- Settings → Access Control lets you define rules with the following types:
rw– Read/write access (default). Applies when no rule matches.ro– Read-only access; uploads and edits are disabled for every account except administrators.hidden– Keeps the volume/folder out of listings and search, and refuses it by its address too — for everyone, administrators included.
- Rules use the logical root (e.g.,
Projects/Team), the path NextExplorer shows with the volume first — not the path of the mount on the host or in the container. The folder button beside the field chooses it for you, and a path that names no folder is flagged with the one probably meant. - Rules evaluate in defined order, so place more specific rules above general ones.
- Recursive rules apply to subfolders when the recursion checkbox is enabled.
Sharing & guest access
- Users with access to a folder or file can create share links from the toolbar Share button; shares respect Access Control rules and can be read-only or read/write.
- Anyone-with-link shares can be opened by guests via
/share/:tokenURLs; guests are confined to the shared path and cannot see other volumes or personal folders. - User-specific shares require authentication and are visible from the Shares → Shared with me view; revoking a user’s access to the underlying path (via Access Control or account removal) effectively revokes their ability to use the link.
Security & logging
- Authentication can be fully disabled for trusted networks via Settings → Security, but enabling protects all API routes.
- Sessions survive restarts: without
SESSION_SECRET, the secret generated at the first start is kept in/config/session-secret. SetSESSION_SECRET(orSESSION_SECRET_FILE) to choose it, or for several replicas. - Persistent sessions: By default, users stay logged in for 30 days even after closing their browser. Configure
SESSION_MAX_AGE_DAYSto adjust this duration (e.g.,7for weekly re-authentication,90for extended sessions). - Two-factor secrets are kept unreadable in
app.db, under a key drawn into/config/totp-keyat the first use. A copy of the database on its own — a backup, a support ticket — is not a set of working authenticators. Losing that key costs authenticators, not accounts: recovery codes are hashed and go on working, and whoever uses one signs in and sets their phone up again. - The activity log is off unless you ask for it, in Settings → Activity log. On, it writes down sign-ins (including the ones that were refused, and the name that was tried) and sign-outs; files downloaded, uploaded, sent to the trash, restored and removed for good; what left through a share link — and what arrived through one — and from which link; shares created and deleted; account changes, whether somebody's own (password, second factor, passkey) or an administrator's (an account created, renamed, given roles, or removed); and which settings were changed, including this switch itself. Each line carries who, what, when, the address it came from, and whether it worked. Behind a reverse proxy — or in a container reached from its own host — that address is only the person's if
TRUST_PROXYsays the proxy may be believed; see the reverse proxy guide. Only administrators can read it.- Nothing before it was switched on is in it. The log is a record kept from the moment it is asked for, not a history reconstructed afterwards.
- Lines are kept for the retention set beside the switch (90 days by default,
ACTIVITY_RETENTION_DAYSto start elsewhere) and swept hourly, whether the log is on or off — switching it off lets the disk go back rather than freezing yesterday's rows. Empty the log removes everything at once — and leaves one line saying who emptied it, when, and how many rows went, because a record that can be taken away without a trace is worth less than the rows it lost. - It lives in
app.db, so it is in the same backup as everything else. It has no foreign key to the accounts: what somebody did while their account existed is exactly what a log is for, and deleting the account does not take it away. - Nothing here can fail a request. A line that cannot be written is reported in the server's own log and the download, the sign-in or the deletion carries on.
- Http logging toggles (
ENABLE_HTTP_LOGGING,LOG_LEVEL,DEBUG) help surface suspicious activity; send container logs to a centralized system for audits.
Backups & persistence
/confighousesapp.db— accounts, shares, settings, and the records of the trash and file versions —logos/, the logo uploaded in Branding,session-secret, the secret sessions are signed with whenSESSION_SECRETis not set — a/configrestored without it signs everyone out once — andtotp-key, which is what makes the two-factor secrets inapp.dbreadable. Back it up before upgrades. Copyapp.dbwith the container stopped, or together withapp.db-wal: a copy ofapp.dbalone can miss what was written last.- Back up
app.dband the volumes together. The trash and file versions keep their content in each volume’s.nextexplorerfolder and their records inapp.db; one restored without the other leaves items that cannot be restored, or content nothing lists. app-config.jsonin/configheld settings and favorites in early releases, and is only read whenapp.dbis created, to carry them into it. Settings are read fromapp.dbalone: a read that fails is refused rather than answered from that file, and a current installation keeps nothing in it.app.dbgives back the space its deletions free. SQLite keeps freed pages inside the file, so a large deletion used to leaveapp.db— and every backup of it — at its largest size. An hourly pass now hands free space back once more than 16 MB of it has built up, and the write-ahead log is cut back to 64 MB after a checkpoint. A database created by an earlier release is rewritten once, at the first start, to make this possible; the log says how large it was before and after. The same pass coversindex.dbandsessions.dbin/cache.- Records nobody needs any more are purged too: ONLYOFFICE document keys past their expiry, every hour, and each trash zone’s events beyond its newest thousand.
/cacheholds what can be made again: thumbnails and RAW previews — each kept within its limit, with what a crash left of them removed — sessions, andindex.db— the search index and the folder sizes. Nothing in it needs a backup. Deleting it signs everyone out and costs a pass over the volumes to rebuild the indexes, so keep it on a persistent mount: without one, every new container reads the volumes again.- A save, an ONLYOFFICE download, an extraction, a compression, or a copy or move across disks stopped half-way by a restart leaves a hidden temporary file, extraction folder or archive in the volume: what is still being written never sits under the name it is meant to take. Each is recorded in
/cache/in-flightwhile it runs, and the next start removes what an interrupted one left, and only that. A/cachecleared in between loses the record, and the leftover stays for you to delete. - An installation upgraded from 3.6.0 or earlier has its indexes moved out of
app.dbinto/cache/index.dbat the first start, as they are — the volumes are not read again for it — andapp.dbis rewritten without them. - When upgrading, run
docker compose pullfollowed bydocker compose up -d. An installation that started on 1.1.7 or earlier keptapp.dbin/cache; nothing moves it to/configany more, so copy it there by hand first; the server warns at start when it finds such a file there. Links namedapp.db,app-config.jsonorextensionsleft in/cacheby 1.1.8 to 2.0.2 are unused and can be deleted.
