Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AZhur771/pivpn-web/llms.txt

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

PiVPN Web uses session-cookie-based authentication backed by express-session. Sessions are persisted in SQLite via TypeormStore, so they survive process restarts as long as a stable SECRET environment variable is configured. The session cookie is issued with httpOnly: true and sameSite: strict. The secure flag is only set when the IS_SECURE environment variable is present, which is appropriate when the server sits behind a TLS-terminating proxy.

How It Works

  1. POST /api/session with a JSON body containing username and password.
  2. The server looks up the user in SQLite and verifies the supplied password against its bcrypt hash.
  3. On success, a Set-Cookie header in the response delivers your session cookie.
  4. Include that cookie in every subsequent request to authenticate.
  5. Call DELETE /api/session to invalidate the session and log out.

Log In

Send your credentials as a JSON body to create a session:
curl -c cookies.txt -X POST http://localhost:3001/api/session \
  -H 'Content-Type: application/json' \
  -d '{"username": "admin", "password": "yourpassword"}'
The -c cookies.txt flag tells curl to save the returned Set-Cookie header to a cookie jar file. On success the server responds with 204 No Content.
username
string
required
The account login name. Corresponds to the ADMIN_USER, VIEWER_USER, or TECH_USER environment variable used when provisioning the account.
password
string
required
The account password in plain text. The server compares it against the bcrypt-hashed value stored in SQLite.
If either field is missing the server returns 500 with { "error": "Missing username" } or { "error": "Missing password" }. If the credentials are wrong it returns 500 with { "error": "Wrong username or password" }. Pass the saved cookie jar on every authenticated request with the -b flag:
curl -b cookies.txt http://localhost:3001/api/wireguard/client-status

Check Session Info

GET /api/session tells you whether the current cookie represents an authenticated session and, if so, which user is logged in:
curl -b cookies.txt http://localhost:3001/api/session
When authenticated, the response is:
{
  "authenticated": true,
  "username": "pi",
  "hostname": "raspberrypi",
  "isAdmin": true
}
When no valid session exists:
{ "authenticated": false }
authenticated
boolean
true if the request carries a valid, recognised session cookie; false otherwise.
username
string
The SSH username used to connect to the PiVPN host (the SSH_USER environment variable). Only present when authenticated is true.
hostname
string
The hostname of the PiVPN server, obtained by running hostname over SSH. Only present when authenticated is true.
isAdmin
boolean
true if the logged-in account has admin privileges; false for viewer accounts. Only present when authenticated is true.

Role-Based Access

The isAdmin field in the session response determines what operations the authenticated user may perform:
  • isAdmin: true — full access, including write operations: creating clients, deleting clients, enabling/disabling clients.
  • isAdmin: false — read-only access. Calling any admin-only endpoint returns 403 Forbidden with { "error": "Not enough rights" }.
See the endpoint table for which endpoints require admin privileges.

Log Out

Destroy the active session by sending a DELETE request. The server removes the session from SQLite and returns 204 No Content.
curl -b cookies.txt -X DELETE http://localhost:3001/api/session
The session secret is randomly generated at startup when the SECRET environment variable is not set. This means all active sessions are invalidated every time the container or process restarts. Set a stable, secret SECRET environment variable in your deployment to preserve sessions across restarts:
SECRET=your-long-random-secret-here
When making API requests from a browser-hosted web app on the same origin, pass credentials: 'include' in your fetch() calls so the browser automatically sends and receives the session cookie:
const res = await fetch('/api/wireguard/client-status', {
  method: 'GET',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
});
This is exactly how the built-in PiVPN Web frontend communicates with the API.

Build docs developers (and LLMs) love