Files
authentik/website/docs/developer-docs/setup/full-dev-environment.mdx
Teffen Ellis e4ef898fec ci/web: run Playwright e2e suite on every PR
Boots the full authentik stack (postgres + Go server + Rust worker)
inside the existing ci-web workflow, applies migrations and the
test-admin user blueprint, then runs `corepack npm run --prefix web
test:e2e` against http://localhost:9000. Uploads the HTML report,
traces/videos, and authentik logs as artifacts on failure so reviewers
can debug without rerunning locally.

Also enables the HTML reporter and screenshot/video capture on CI in
playwright.config.js, and updates the full dev-environment docs to
point at the same npm scripts CI uses so local and CI runs stay in
lockstep.

Closes #21994

Co-Authored-By: Agent (authentik-i21994-better-mobile-tangelo) <279763771+playpen-agent@users.noreply.github.com>

ci/web: make test-admin blueprint self-contained

The previous blueprint used !Find to look up the authentik Admins group,
which raced against system/bootstrap.yaml and resolved to None when the
explicit apply_blueprint step ran before the worker had applied bootstrap.
The serializer rejected groups: [None] with Invalid pk "None".

Define the group in the same blueprint with state: present and reference
it via !KeyOf, so the test admin setup does not depend on any pre-existing
data. If bootstrap has already created the group, state: present is a
no-op on the identifiers; otherwise the group is created here.

Co-Authored-By: Agent (authentik-i21994-better-mobile-tangelo) <279763771+playpen-agent@users.noreply.github.com>

ci/web: format test-admin-user.yaml with prettier

Pick up the 4-space indent that web/'s prettier config enforces. The
file was added under issue #21994 with 2-space indent and tripped the
ci-web format check on push.

Co-Authored-By: Agent (authentik-i21994-better-mobile-tangelo) <279763771+playpen-agent@users.noreply.github.com>

Use parallelism.

Remove guard.

Reorder tests.

Ignore playwright-traces.

Update expected path.

Always parallel.

Flesh out types.

ci/web: post Playwright result comment + gated S3 upload + !cancelled() guards

Three reviewer-facing improvements to the e2e job:

1. Idempotent PR comment summarising Playwright pass/fail/flaky/skipped
   counts. Marker `<!-- playwright-result -->` lets re-runs edit the
   same comment instead of piling up. Skipped on fork PRs where the
   default GITHUB_TOKEN is read-only.

2. Optional S3 publish of the HTML report to
   `s3://authentik-playwright-artifacts/pr-<n>/run-<id>/attempt-<n>/`,
   gated behind `vars.PLAYWRIGHT_S3_ENABLED == 'true'`. The bucket is
   pending infra provisioning; the public URL pattern is already wired
   into the comment so flipping the variable on later requires no
   workflow changes. Borrows the OIDC + IAM role plumbing from
   `.github/workflows/release-publish.yml`.

3. Switch the failure-guarded reporting/upload steps to `!cancelled()`
   so a superseded (cancelled) run no longer emits failure-shaped noise,
   and so successful runs still produce the artifact bundle reviewers
   expect.

Adds the Playwright JSON reporter so the parse step can pull pass/fail
counts from `playwright-report/results.json` for the comment body.

Co-Authored-By: Agent (authentik-i21996-internal-achievable-raisin) <279763771+playpen-agent@users.noreply.github.com>

web/e2e: fix three regressions blocking the parallel suite

Locally and in CI the new `e2e (playwright)` job appeared to "hang"
under `fullyParallel: true` + `workers: "50%"`. The hang was actually
five tests sharing two unrelated bugs that all manifest as 30s test
timeouts; the cluster only *looks* like a parallelism issue because
multiple workers stall on the same wall-clock window. With these three
fixes the full suite is green in 1m48s on `--workers=2` (was: 5 failed
/ 17 passed in 5m30s).

1. `web/test/browser/600-providers.test.ts`
   PR #21647 dropped the `to:` argument on the `session.login()` call
   in this file's `beforeEach`. Without it, `SessionFixture.login()`
   waits for the auth-flow URL pattern to re-appear — which it does
   immediately, since we just navigated there — so the helper returns
   *before* the post-login redirect lands. The wizard buttons probed
   afterward live on `/if/admin/#/core/providers`, which the user never
   actually reaches; every test in the file then hits the 30s
   `beforeEach` timeout. Pin the destination explicitly, matching the
   shape of every other test file.

2. `web/src/admin/roles/ak-role-list.ts`
   The role-list row anchor had no aria-label, so its accessible name
   was the (random, generated) role name. `500-roles.test.ts` searches
   for that anchor with `getByRole("link", { name: "view details" })`
   — the same selector `400-groups.test.ts` uses against the group
   list, where `GroupListPage.row()` *does* set
   `aria-label="View details of group ..."`. Bring the role row to
   parity with groups; the test wasn't wrong, the UI was missing the
   accessibility hook.

3. `web/test/browser/500-roles.test.ts` ("Edit role from view page")
   The post-edit verification used `page.getByText(updatedName)`, but
   on the role view page the new name renders in two places (the
   "Role <name>" page-navbar heading and the description-list value),
   so the bare text match resolves to two elements and trips
   strict-mode. Add `{ exact: true }` so we assert the canonical value
   the edit wrote rather than the heading template.

Co-Authored-By: Agent (authentik-i21996-internal-achievable-raisin) <279763771+playpen-agent@users.noreply.github.com>

Use headless.
2026-05-05 18:40:48 +02:00

308 lines
9.5 KiB
Plaintext

---
title: Full development environment
sidebar_label: Full development
tags:
- development
- contributor
- backend
- frontend
- docker
---
import TabItem from "@theme/TabItem";
import Tabs from "@theme/Tabs";
## Prerequisites
Before you begin, ensure you have the following tools installed. You can run the [provided script](#3-installing-platform-specific-dependencies) below in **Installing platform-specific dependencies** to install these required tools.
- [Python](https://www.python.org/) (3.14)
- [uv](https://docs.astral.sh/uv/getting-started/installation/) (Latest stable release)
- [Rust](https://rust-lang.org/learn/get-started/) (We provide a `rust-toolchain.toml` file for the correct version, and we use the nightly toolchain to run formatting with rustfmt.)
- [Go](https://go.dev/) (1.26 or later)
- [Node.js](https://nodejs.org/en) (24 or later)
- [PostgreSQL](https://www.postgresql.org/) (16 or later)
- [Docker](https://www.docker.com/) (Latest Community Edition or Docker Desktop)
- [Docker Compose](https://docs.docker.com/compose/) (Compose v2)
- [Make](https://www.gnu.org/software/make/) (3 or later)
### Understanding the architecture
authentik is primarily a Django application running under gunicorn, proxied by a Go application that serves static files. Most functions and classes have type hints and docstrings. For better code navigation, we recommend installing a Python type-checking extension in your IDE.
## 1. Prepare your local working repository
Verify that you have a local working repository of authentik and that it is initialized and up-to-date with the [authentik repository](https://github.com/goauthentik/authentik).
Unless otherwise specified, all commands described below should be run from the project root of your local authentik repository.
## 2. Set up required services
authentik depends on several external services:
- [PostgreSQL](https://www.postgresql.org/) for database storage
- [Zenko CloudServer (S3)](https://www.zenko.io/cloudserver/) for object storage
- [Sentry Spotlight](https://spotlightjs.com/) for error tracking and visualization
The easiest way to set up these services is using the provided Docker Compose configuration:
```shell
docker compose -f scripts/compose.yml up -d
```
## 3. Installing platform-specific dependencies
<Tabs defaultValue="macOS">
<TabItem value="macOS">
Install the required native dependencies on macOS using Homebrew. You can edit the following command if you already have some of these and want to skip installing them again, or run `brew install --dry-run` to preview the changes:
```shell
brew install \
libxmlsec1 \
libpq \
pkg-config \
uv \
postgresql \
node@24 \
golangci-lint \
krb5
```
</TabItem>
<TabItem value="Linux">
For Debian/Ubuntu-based distributions (you can edit the following command if you already have some of these and want to skip installing them again):
```shell
pip install uv
sudo apt-get install -y \
libgss-dev \
krb5-config \
libkrb5-dev \
libxml2 \
libxslt1-dev \
libxmlsec1 \
xmlsec1 \
postgresql-server-dev-all \
postgresql
```
For other distributions (Red Hat, SUSE, Arch), adjust the package names as needed.
Install `golangci-lint` by following the [official installation instructions](https://golangci-lint.run/welcome/install/#other-ci).
</TabItem>
<TabItem value="Windows">
We're currently seeking community input on running the full development environment on Windows. If you have experience with this setup, please consider contributing to this documentation.
</TabItem>
</Tabs>
:::warning
[aws-lc-rs](https://github.com/aws/aws-lc-rs) currently has an [issue](https://github.com/aws/aws-lc-rs/issues/569) building its FIPS module with GCC >= 14. If you encounter this issue, you have two options:
- Use an older version of GCC.
- Install [Clang](https://clang.llvm.org) and `export AWS_LC_FIPS_SYS_CC=clang`.
:::
## 4. Set up the backend
:::info
All `make` commands must be executed from the root directory of your local authentik Git repository.
:::
### Install dependencies
Install all required JavaScript and Python dependencies and create an isolated Python environment:
```shell
make install
```
### Generate development configuration
Create a local configuration file that uses the local databases for development:
```shell
make gen-dev-config
```
### Initialize the database
Run all migrations with the following command:
```shell
make migrate
```
:::info
If you ever want to start over, use `make dev-reset`, which drops and restores the authentik PostgreSQL database to the state it was in after you ran `make migrate`.
:::
## 5. Running authentik
Now that the backend has been set up and built, you can start authentik. Run the following command from the root of your installation directory:
```shell
make run
```
:::info
The very first time authentik runs, it might need some time to clear the initial task queue. Adjust [`AUTHENTIK_WORKER__THREADS`](../../../install-config/configuration/#authentik_worker__threads) as required.
:::
### Hot-reloading
When `AUTHENTIK_DEBUG` is set to `true` (the default for the development environment), the authentik server automatically reloads whenever changes are made to the code.
Install [watchexec](https://github.com/watchexec/watchexec), and run:
```shell
make run-watch
```
## 6. Build the frontend
Even if you're not planning to develop the UI, you need to build the frontend because no compiled bundle is included by default. Run the following command to build the authentik UI:
```shell
make web-build
```
For real-time feedback you can view the UI as you make changes. Run this command and then in your browser go to http://localhost:9000/.
```shell
make web-watch
```
## 7. Initial setup
After the frontend build completes, set a password for the default admin user (**akadmin**):
1. Navigate to http://localhost:9000 in your browser.
2. Follow the prompts to set up your admin account.
From now on, you can access authentik at http://localhost:9000 using the credentials you defined in Step 2.
## Troubleshooting
### Recovery key
If you can no longer log in or the authentication flow repeats (perhaps due to an incorrectly configured stage or a failed flow import), you can create a recovery key by running this command in your terminal:
`uv run ak create_recovery_key 10 akadmin`
Copy the generated recovery key and paste it into the URL, after the domain. For example:
`http://localhost:9000/recovery/use-token/ChFk2nJKJKJKY9OdIc8yv6RCgpGYp5rdndBhR6qHoHoJoWDdlvLuvU/`
## End-to-End (E2E) Setup
authentik ships two end-to-end test suites:
- The Django/Selenium suite under `tests/e2e/` — driven by Django's test runner. It is exercised in CI by the `test-e2e` job in `ci-main.yml`.
- The browser-side Playwright suite under `web/test/browser/` — driven by `web/playwright.config.js`. It is exercised in CI by the `e2e (playwright)` job in `ci-web.yml` and runs against a live authentik server.
### Django/Selenium suite
Start the E2E test services with the following command:
```shell
docker compose -f tests/e2e/compose.yml up -d
```
You can then view the Selenium Chrome browser via http://localhost:7900/ using the password: `secret`.
Alternatively, you can connect directly via VNC on port `5900` using the password: `secret`.
:::info
When using Docker Desktop, host networking needs to be enabled via **Docker Settings** > **Resources** > **Network** > **Enable host networking**.
:::
### Playwright suite
The Playwright suite assumes that:
- An authentik stack is reachable at `http://localhost:9000` (override with `AK_TEST_RUNNER_PAGE_URL`).
- The blueprint at `web/test/blueprints/test-admin-user.yaml` has been applied so that the `test-admin@goauthentik.io` user (password `test-runner`) can log in.
Both prerequisites are satisfied by the standard full development environment described above, plus a one-off blueprint apply. From the repository root:
```shell
# Make the test admin blueprint discoverable by the worker, then start authentik.
mkdir -p blueprints/local
cp web/test/blueprints/test-admin-user.yaml blueprints/local/test-admin-user.yaml
# In separate terminals:
make run-server
make run-worker
```
Once the worker has applied the blueprint, install Playwright's browsers (one-time) and run the suite — these are the same npm scripts CI runs:
```shell
corepack npm exec --prefix web -- playwright install --with-deps chromium
corepack npm run --prefix web test:e2e
```
After a failing run, open the HTML report to inspect traces, screenshots, and (in CI) videos:
```shell
corepack npm exec --prefix web -- playwright show-report
```
In CI, the same artifacts are uploaded under the `playwright-report` and `playwright-traces` artifact names on the failed workflow run.
## Contributing code
### Before submitting a pull request
Ensure your code meets our quality standards by running:
1. **Code linting**:
```shell
make lint-fix
make lint
```
2. **Generate updated API documentation**:
```shell
make gen
```
3. **Format frontend code**:
```shell
make web
```
4. **Run tests**:
```shell
make test
```
You can run all these checks at once with:
```shell
make all
```
### Submitting your changes
After your code passes all checks, submit a pull request on [GitHub](https://github.com/goauthentik/authentik/pulls). Be sure to:
- Provide a clear description of your changes
- Reference any related issues
- Update any related documentation
- Follow our code and documentation [style guidelines](../../contributing/#style-guides)
- Include tests for your changes where appropriate
Thank you for contributing to authentik!