Managing Users
Add, update, and remove Authelia users who can access your tunneled apps through TOTP two-factor authentication.
In Plain English
Every tunneled app in Portlama is protected by Authelia, a login system that requires a username, password, and a one-time code from an authenticator app. When you create a user in the Portlama panel, that person can log in to any of your tunneled apps. This guide covers the full lifecycle: creating users, enrolling them in two-factor authentication, changing passwords, and safely removing users.
Prerequisites
- A completed Portlama onboarding
- Access to the Portlama admin panel
- An authenticator app for TOTP enrollment (Google Authenticator, Authy, 1Password, etc.)
Step-by-Step
1. Open the Users Page
Log in to the Portlama admin panel at https://<ip>:9292.
Click Users in the sidebar navigation.
You see a list of existing users. After onboarding, there is one user: admin — the account created during provisioning.
2. Add a New User
Click the Add User button.
A form appears with these fields:
| Field | Required | Rules | Example |
|---|---|---|---|
| Username | Yes | 2-32 chars, lowercase alphanumeric with underscores and hyphens | alice |
| Display Name | Yes | 1-100 characters | Alice Johnson |
| Yes | Valid email address | alice@example.com | |
| Password | Yes | 8-128 characters | A strong, unique password |
| Groups | No | Optional list of group names | admins, developers |
Fill in the form and click Create User.
What happens behind the scenes:
- The panel validates all fields against the schema.
- The password is hashed with bcrypt (not argon2id — argon2id uses ~93 MB per hash and causes OOM kills on 512 MB droplets).
- The user record is written to
/etc/authelia/users.ymlusing an atomic write (write to temp file, then rename) to prevent corruption. - Authelia is reloaded to pick up the new user.
Expected result: The new user appears in the list. Share the username and password with the person — they need these to log in to your tunneled apps.
3. TOTP Enrollment
When a new user visits a Portlama-protected app for the first time:
- They are redirected to
auth.example.com. - They enter their username and password.
- Authelia presents a QR code for TOTP enrollment.
- They scan the QR code with their authenticator app.
- They enter the 6-digit code to verify.
- TOTP is now active. Every future login requires the code.
Walk a new user through this process:
- Share the tunnel URL (e.g.,
https://app.example.com) and their credentials. - Tell them to open the URL in their browser.
- They log in with the username and password you provided.
- They scan the QR code with Google Authenticator, Authy, 1Password, or any TOTP-compatible app.
- They enter the verification code.
- They are logged in and can access the app.
4. Reset a User's TOTP Secret
If a user loses access to their authenticator app (lost phone, new device), you can reset their TOTP secret so they can re-enroll.
- Go to the Users page.
- Find the user in the list.
- Click the Reset TOTP button next to the user.
- The panel generates a new TOTP secret and returns a TOTP URI.
- A QR code is displayed — the user scans it with their authenticator app.
What happens behind the scenes:
- The panel generates a new base32-encoded TOTP secret.
- The secret is written to Authelia's SQLite database (
/etc/authelia/db.sqlite3) via theauthelia storage user totp generateCLI command. TOTP secrets are stored in the database, not inusers.yml(thetotp_secretfield inusers.ymlis deprecated and ignored in Authelia v4.38+). - The TOTP URI is returned in the format
otpauth://totp/Portlama:<username>?secret=<secret>&issuer=Portlama&algorithm=SHA1&digits=6&period=30.
On their next login, the user enters a code from the new TOTP entry in their authenticator app. The old entry no longer works.
5. Change a User's Password
- Go to the Users page.
- Find the user and click Edit (or the edit icon).
- Enter a new password in the password field.
- Click Save.
The new password is hashed with bcrypt and written to users.yml. Authelia is reloaded. The user must use the new password on their next login.
You can also update the display name, email, and groups in the same edit form.
6. Update User Details
To change a user's display name, email, or group membership:
- Go to the Users page.
- Click Edit on the user.
- Modify the fields you want to change.
- Click Save.
Only the fields you change are updated — the password and TOTP secret remain the same unless explicitly changed.
7. Remove a User
- Go to the Users page.
- Click the Delete button next to the user you want to remove.
- Confirm the deletion.
Safety rule: You cannot delete the last user. Portlama enforces this to prevent locking everyone out of the tunneled apps. If you try to delete the last user, the panel returns an error: "Cannot delete the last user."
What happens behind the scenes:
- The panel removes the user from
users.yml(atomic write). - Authelia is reloaded.
- Any active sessions for that user expire naturally (Authelia does not have a "force logout" mechanism, but sessions have a timeout).
After deletion, the user can no longer log in to any tunneled app.
For Developers
User Storage
Users are stored in Authelia's users.yml file at /etc/authelia/users.yml. The file format is:
users:
admin:
displayname: Admin
email: admin@example.com
password: $2b$12$... # bcrypt hash
groups:
- admins
alice:
displayname: Alice Johnson
email: alice@example.com
password: $2b$12$...
groups: []Note: TOTP secrets are stored in Authelia's SQLite database (/etc/authelia/db.sqlite3), not in users.yml. The totp_secret field in users.yml is deprecated and ignored in Authelia v4.38+.
All writes to this file are atomic: write to a temp file, then rename. This prevents Authelia from reading a partially-written file.
API Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /api/users | List all users (sorted alphabetically, no sensitive fields) |
POST | /api/users | Create a new user |
PUT | /api/users/:username | Update user fields |
DELETE | /api/users/:username | Delete a user (not the last one) |
POST | /api/users/:username/reset-totp | Generate a new TOTP secret |
Create User Request
POST /api/users
{
"username": "alice",
"displayname": "Alice Johnson",
"email": "alice@example.com",
"password": "securepassword123",
"groups": ["developers"]
}Response:
{
"ok": true,
"user": {
"username": "alice",
"displayname": "Alice Johnson",
"email": "alice@example.com",
"groups": ["developers"]
}
}Update User Request
PUT /api/users/alice
{
"displayname": "Alice J.",
"password": "newpassword456"
}Only provided fields are updated. At least one field must be present.
Reset TOTP Response
POST /api/users/alice/reset-totp
{
"ok": true,
"totpUri": "otpauth://totp/Portlama:alice?secret=JBSWY3DPEHPK3PXP&issuer=Portlama"
}The totpUri is used to generate a QR code that the user scans with their authenticator app.
Validation Rules (Zod Schema)
| Field | Rules |
|---|---|
username | 2-32 chars, regex ^[a-z0-9_-]+$ |
displayname | 1-100 chars |
email | Valid email format |
password | 8-128 chars |
groups | Optional array of strings |
Password Hashing
Passwords are hashed with bcrypt at cost factor 12. The hashPassword() function in lib/authelia.js handles this. Argon2id is explicitly avoided because a single hash operation consumes ~93 MB of memory, which causes OOM kills on the 512 MB target droplet.
Authelia Reload
After every write to users.yml, the panel restarts Authelia:
sudo systemctl restart autheliaAuthelia reads users.yml on restart. If the restart fails, a warning is logged but the API request still succeeds — the user data is persisted and the next Authelia restart picks it up.
Quick Reference
| Action | Steps |
|---|---|
| Add user | Users page, "Add User", fill form, "Create User" |
| Edit user | Users page, "Edit" on user, modify fields, "Save" |
| Change password | Edit user, enter new password, "Save" |
| Reset TOTP | Users page, "Reset TOTP" on user, share QR code |
| Delete user | Users page, "Delete" on user, confirm |
| Constraint | Value |
|---|---|
| Username format | ^[a-z0-9_-]+$ |
| Username length | 2-32 characters |
| Password length | 8-128 characters |
| Password hashing | bcrypt (cost 12) |
| Minimum users | 1 (cannot delete last user) |
| TOTP algorithm | SHA1, 6 digits, 30-second period |
| User file | /etc/authelia/users.yml |