Skip to main content

First-Run Setup

When Wayd starts with an empty database it generates a one-time bootstrap token and prints it to the application log. This token lets you create the first administrator account without any pre-existing credentials — solving the chicken-and-egg problem of needing an admin to configure identity providers.

Once an admin account exists the token is invalidated and the setup page returns 404.

Step 1 — Start the application​

Run Wayd using any of the standard options. On first boot you will see a message like this in the logs:

============================================================
WAYD FIRST-RUN SETUP
============================================================
No users exist. Use the token below to create the first
admin account.

UI: <your-app-url>/setup
API: POST /api/auth/setup

Token: <bootstrap-token>

This token is valid for the lifetime of this process only.
Restart the application to generate a new token.
============================================================

Copy the token value — you will need it in the next step.

Step 2 — Complete setup​

Navigate to <your-app-url>/setup in a browser. The page will not load (404) if setup has already been completed.

Fill in the form:

FieldNotes
Setup tokenPaste the token from the server log
First name / Last nameYour name
EmailUsed as your login username
PasswordMust be at least 8 characters, with at least one uppercase letter, one lowercase letter, and one digit
Confirm passwordMust match exactly

Click Create admin account. On success you are logged in immediately as an administrator with no forced password change.

Step 3 — Configure authentication​

With your admin account you can now:

  • Add an identity provider — Settings → Access → Identity Providers. Lets your team log in via Microsoft Entra ID or another OIDC provider. See Configuration → Identity providers.
  • Invite users — Settings → Access → Users → Create User.
Token expired?

The bootstrap token lives only in memory. If you restart the application before completing setup, a new token is generated and printed again.

API alternative

If you prefer to complete setup without a browser, POST directly to the API:

curl -X POST <api-url>/api/auth/setup \
-H "Content-Type: application/json" \
-d '{
"token": "<bootstrap-token>",
"firstName": "Admin",
"lastName": "User",
"email": "admin@example.com",
"password": "YourPassword1"
}'

A successful response returns a Wayd JWT + refresh token identical to a normal login response.

Step 4 — Verify security headers (deployed environments)​

Security headers ship on by default and need no configuration. For anything beyond local development, confirm they survive your ingress — a proxy, CDN or WAF in front of Wayd can strip or overwrite response headers:

curl -sI https://<api-url>/alive | grep -iE 'x-frame|x-content|referrer|permissions|content-security'

You should see all five:

X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=(), microphone=()

If any are missing, your edge is stripping them — fix it there rather than working around it in the app.

Two things you may need to change, both covered in Configuration → Security Headers:

  • Wayd must be embedded in an iframe (an intranet portal, another app). X-Frame-Options: DENY and frame-ancestors 'none' block this by design. This is a deliberate clickjacking defence — the app has destructive controls behind a permission claim, so only relax it if you genuinely need framing, and prefer naming the specific parent origin over allowing all.
  • Your edge already sets these headers. Set Enable: false rather than emitting them twice; duplicated X-Frame-Options is ignored by some browsers.
HSTS is not enabled

Wayd does not send Strict-Transport-Security by default, and Azure Container Apps ingress does not add it either. If you terminate TLS at a Front Door or Application Gateway, enable it there. See Configuration → HSTS is off by default before turning it on anywhere — it is a browser-side latch that cannot be recalled.