What this covers
How user accounts work in Scriptor 2.0:
- Profile: the logged-in user editing their own account.
- Passwords: changing your own password from the Profile form, and recovering when you forget the only admin password the install created.
- Multi-user: the current state (one user per install, no add/delete UI) and the two workarounds.
Walkthrough
Edit your own profile
- Click Profile in the top-right menu.
- The form shows three editable fields: Username, Email, and (optionally) New password / Confirm password.
- Change what you want to change.
- Username changes are allowed; the new name has to be unique among editor users.
- Email is required and validated for shape.
- Leave the password fields empty to keep your current password; fill both to change it (the two must match).
- Click Save.
The change takes effect immediately. A password change does not log you out of the current session.
Change your password
The same Profile form is the way to change your password.
- Open Profile.
- Type the new password in New password (8 characters minimum).
- Type it again in Confirm password.
- Click Save.
If the two do not match, or the new one is too short, the form returns an error and the password stays unchanged.
Recover when you forgot the password and you are the only admin
There is no "forgot password" email flow, and bin/scriptor install refuses to run on a seeded database. Two paths get
you back in:
Path A: update the password hash directly in SQLite (preserves all data)
-
Generate a fresh bcrypt hash for the new password:
php -r "echo password_hash('your-new-strong-password', PASSWORD_BCRYPT) . PHP_EOL;"Copy the output (a string starting with
$2y$10$...). -
Back up the database first (always; see Backup and restore):
cp data/imanager.db data/imanager.db.bak -
Update the admin row. The password field is stored inside the item's JSON
datablob, either as a plain string (the bcrypt hash on its own) or as a{__class, password, salt}wrapper; the simplest reset overwrites it with a plain hash:sqlite3 data/imanager.db \ "UPDATE items SET data = json_set(data, '\$.password', '<paste-hash-here>') WHERE name = 'admin'" -
Log in with
adminand the new password.
Path B: wipe the database and re-install (loses all content)
If nothing on the site matters yet (a fresh install you have not used) and you would rather not touch SQL:
rm data/imanager.db
SCRIPTOR_ADMIN_PASSWORD='your-new-strong-password' \
php bin/scriptor install --yes
This rebuilds the database from scratch: new admin password, new Home page, no pages, no users, no files. Do not use this path on a site with content unless you have a backup ready.
Multi-user: the current state
Scriptor 2.0 does not ship a multi-user management UI. The install command creates exactly one admin user. The Profile module edits that user's own account. There is no "Add user" button, no "Delete user" action, no role editor.
This is a deliberate Phase 14 scope cut, not a bug. A future iManager 2.x admin UI is expected to fill the gap; until then, two workarounds work today:
Workaround 1: edit the iManager database in PHP
A short PHP script using iManager's ItemRepository adds a
user row to the Users category:
<?php
// scripts/add-editor-user.php (run from project root with `php scripts/add-editor-user.php`)
require __DIR__ . '/../boot.php';
use Imanager\Domain\Item;
use Imanager\Storage\CategoryRepository;
use Imanager\Storage\ItemRepository;
use Scriptor\Boot\App;
$container = App::container();
$categories = $container->get(CategoryRepository::class);
$items = $container->get(ItemRepository::class);
$usersCategory = $categories->findBySlug('users');
if ($usersCategory === null) {
fwrite(STDERR, "Users category not found; is Scriptor installed?\n");
exit(1);
}
$passwordHash = password_hash('your-new-user-password', PASSWORD_BCRYPT);
$user = new Item(
id: null,
categoryId: $usersCategory->id,
name: 'jane',
data: [
'email' => 'jane@example.com',
'password' => $passwordHash,
],
);
$saved = $items->save($user);
echo "Created user id={$saved->id} name={$saved->name}\n";
Run it once, then log out and back in as the new user. The new account has the same permissions as the original admin (no role distinction exists in 2.0).
Workaround 2: separate Scriptor installs
If you need genuinely separate editors with isolated access,
run a separate Scriptor install per site. Each install has its
own admin password, its own data/imanager.db, its own
vendor/. Subdomain-per-editor or path-prefix-per-editor are
both workable.
For multi-editor on a single site that needs proper roles, wait for the iManager admin UI release that ships role-aware multi-user management.
What to check after
After a profile edit:
- Logging out and back in still works with the new credentials.
- The Profile form reloads with the updated values.
After a password change:
- The current session still works (no auto-logout).
- Logging in via the same credentials in a different browser succeeds.
After a recovery via Path A (SQLite update):
admin/ new password lets you in.- The page tree, files, and settings are unchanged from before the recovery.
After a recovery via Path B (wipe and re-install):
admin/ new password lets you in.- The site is back to a fresh install: Home page only, no other content. Restore the rest from backup if you have one.
After adding a user via the PHP script:
- The new user appears in
data/imanager.db(a sanity check withsqlite3 data/imanager.db "SELECT name FROM items WHERE categoryId = <users-category-id>"). - Logging out and in as the new user works.
Troubleshooting
"Error: a user with that name already exists" when changing username
The name you typed is taken. Names are unique across editor users; pick a different one.
"Invalid email format"
The email did not match the validator's shape. Type a normal
local@domain.tld form, no trailing whitespace.
Password change accepted but the new one is rejected on next login
You changed the password while logged into a different tab that still had the old session's CSRF token. The save succeeded; the next login from a fresh tab works. Close all editor tabs, log in again with the new password.
bin/scriptor install refuses with "already installed"
That is the expected refusal on a seeded database. Use Path A
(SQLite update) above instead. If you genuinely want a fresh
install, delete data/imanager.db first and then re-run.
sqlite3 command not installed
Most distros ship it as the sqlite3 package
(apt install sqlite3, brew install sqlite, apk add sqlite).
For Docker, run the SQL through docker exec:
docker exec scriptor-cms-site sqlite3 /var/www/html/data/imanager.db \
"UPDATE items SET data = json_set(data, '\$.password', '<hash>') WHERE name = 'admin'"
See also
- Site settings and theme switch: config keys that interact with auth (lockout duration, failed- attempt cap)
- Installed plugins: how plugin registrations interact with sessions
- Backup and restore: why you want a
recent backup of
data/imanager.dbbefore any user-row edit - Install Scriptor: the install command this topic uses for password recovery
- Editor UI tour: map of the Profile top-right menu item