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:
| Field | Notes |
|---|---|
| Setup token | Paste the token from the server log |
| First name / Last name | Your name |
| Used as your login username | |
| Password | Must be at least 8 characters, with at least one uppercase letter, one lowercase letter, and one digit |
| Confirm password | Must 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.
The bootstrap token lives only in memory. If you restart the application before completing setup, a new token is generated and printed again.
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: DENYandframe-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: falserather than emitting them twice; duplicatedX-Frame-Optionsis ignored by some browsers.
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.