mirror of
https://github.com/bitwarden/server.git
synced 2026-06-01 11:45:20 -05:00
* chore(deps): remove Node.js community plugin * refactor(AppHost): integrate web frontend with Aspire JS hosting * docs(AppHost): update web frontend and Aspire documentation * feat(AppHost): configure Azurite emulator with persistent data volume * docs(AppHost): fix ClientsPath description to reference worktrees section * fix(Apphost): run dotnet format
216 lines
12 KiB
Markdown
216 lines
12 KiB
Markdown
# Aspire AppHost
|
|
|
|
.NET Aspire orchestrates the entire Bitwarden server local development environment — supporting
|
|
infrastructure and the Bitwarden application services — from a single command, replacing the
|
|
manual docker-compose workflow.
|
|
|
|
## Prerequisites
|
|
|
|
| Requirement | Notes |
|
|
|------------------------|----------------------------------------------------------------------------------------------------------------------------------|
|
|
| .NET SDK 10 | Required by Aspire |
|
|
| Docker Desktop | Runs the supporting infrastructure containers |
|
|
| PowerShell (`pwsh`) | Used by migration and secrets scripts |
|
|
| Completed server setup | `dev/secrets.json` must exist — follow the [setup guide](https://contributing.bitwarden.com/getting-started/server/guide/) first |
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
cd AppHost
|
|
dotnet run
|
|
```
|
|
|
|
The Aspire dashboard opens automatically in your browser. All resources start in dependency order;
|
|
the services wait for the database and secrets setup to finish before launching.
|
|
|
|
## What Gets Started
|
|
|
|
| Resource | Type | Purpose |
|
|
|---------------------|---------------------------|---------------------------------------------------------------------------|
|
|
| `setup-secrets` | Executable | Runs `dev/setup_secrets.ps1` — applies `dev/secrets.json` to all projects |
|
|
| `mssql` | SQL Server 2022 container | Persistent data volume, port 1433 |
|
|
| `run-db-migrations` | Executable | Runs `dev/migrate.ps1` against `vault_dev` (or `self_host_dev`) |
|
|
| `azurite` | Azure Storage emulator | Blob :10000 · Queue :10001 · Table :10002 · persistent data volume |
|
|
| `azurite-setup` | Executable | Runs `dev/setup_azurite.ps1` after Azurite is ready |
|
|
| `mailcatcher` | Container | SMTP :10250 · Web UI :1080 |
|
|
| `redis` | Container | Redis with AOF persistence, port 6379 |
|
|
| `idp` | SimpleSAMLphp container | SAML IdP for SSO testing (**explicit start** from the dashboard) |
|
|
| `admin` | .NET project | Admin portal |
|
|
| `api` | .NET project | Main API (waits for Azurite) |
|
|
| `billing` | .NET project | Billing service |
|
|
| `events` | .NET project | Events service (waits for Azurite) |
|
|
| `eventsProcessor` | .NET project | Events processor (waits for Azurite) |
|
|
| `icons` | .NET project | Icons service |
|
|
| `identity` | .NET project | Identity / auth service |
|
|
| `notifications` | .NET project | Notifications service (waits for Azurite) |
|
|
| `scim` | .NET project | SCIM provisioning service |
|
|
| `sso` | .NET project | SSO service |
|
|
|
|
## Configuration
|
|
|
|
All configuration lives in `appsettings.Development.json`(see [Security](#security--do-not-commit-local-settings-or-tokens)).
|
|
|
|
### Service Ports
|
|
|
|
Each service's `BasePort` is pre-filled in `appsettings.Development.json` to match the port
|
|
defined in each service's own `Properties/launchSettings.json`. No action is needed unless a port
|
|
conflicts with something else on your machine — in that case override it via user secrets:
|
|
|
|
```bash
|
|
dotnet user-secrets set "Services:api:BasePort" "4001"
|
|
```
|
|
|
|
### Database Password
|
|
|
|
```bash
|
|
dotnet user-secrets set "Database:Password" "<your-sa-password>"
|
|
```
|
|
|
|
### Full Configuration Reference
|
|
|
|
| Key | Default | Description |
|
|
|-----------------------------|------------------------------------|--------------------------------------------------------------------------------------|
|
|
| `SelfHost` | `false` | Switch to self-hosted mode (see [Self-Hosted Mode](#self-hosted-mode)) |
|
|
| `ClientsPath` | `../../clients/apps` | Path to the `clients` repo's `apps/` directory (see [Git Worktrees](#git-worktrees)) |
|
|
| `WorkingDirectory` | `../dev` | Directory where dev scripts are resolved |
|
|
| `Services:<name>:BasePort` | see `appsettings.Development.json` | HTTP port for each service; pre-filled to match each service's `launchSettings.json` |
|
|
| `Database:Image` | `mssql/server:2022-latest` | Docker image for SQL Server |
|
|
| `Database:Port` | `1433` | Host port mapped to the SQL Server container |
|
|
| `Database:Password` | _(empty)_ | SA password for the SQL Server container |
|
|
| `Database:SelfHostPassword` | _(empty)_ | SA password used in self-hosted mode |
|
|
| `Scripts:DbMigration` | `migrate.ps1` | Migration script filename (relative to `WorkingDirectory`) |
|
|
| `Scripts:AzuriteSetup` | `setup_azurite.ps1` | Azurite setup script filename |
|
|
| `Scripts:SecretsSetup` | `setup_secrets.ps1` | Secrets setup script filename |
|
|
| `MailCatcher:Image` | `sj26/mailcatcher:latest` | Docker image for MailCatcher |
|
|
| `MailCatcher:SmtpPort` | `10250` | Host SMTP port |
|
|
| `MailCatcher:WebPort` | `1080` | MailCatcher web UI port |
|
|
| `NgrokAuthToken` | _(empty)_ | ngrok auth token (used only when ngrok plugin is enabled) |
|
|
| `WebFrontend:Port` | `8080` | Web frontend port |
|
|
| `WebFrontend:Url` | `https://bitwarden.test:8080` | Web frontend URL shown in the dashboard |
|
|
|
|
## Optional Features
|
|
|
|
### Web Frontend
|
|
|
|
Runs the web client alongside the server services. Requires the Bitwarden
|
|
[clients](https://github.com/bitwarden/clients) repo cloned as a sibling to `server`.
|
|
|
|
1. If the clients repo is not at `../../clients/apps`, override the path:
|
|
|
|
```bash
|
|
dotnet user-secrets set "ClientsPath" "<path/to/clients/apps>"
|
|
```
|
|
|
|
2. Run `dotnet run` as normal. The `web-frontend` resource starts with **explicit start** — open
|
|
the Aspire dashboard and start it manually when you're ready.
|
|
|
|
### Ngrok (Billing Webhook Tunneling)
|
|
|
|
Exposes the billing service through a public ngrok tunnel, useful for testing Stripe webhooks
|
|
locally.
|
|
|
|
1. Create an `AppHost.csproj.user` file next to `AppHost.csproj` (it is covered by `.gitignore`):
|
|
|
|
```xml
|
|
<Project>
|
|
<PropertyGroup>
|
|
<EnableNgrokCommunityPlugin>true</EnableNgrokCommunityPlugin>
|
|
</PropertyGroup>
|
|
</Project>
|
|
```
|
|
|
|
2. Set your ngrok auth token:
|
|
|
|
```bash
|
|
dotnet user-secrets set "NgrokAuthToken" "<your-ngrok-auth-token>"
|
|
```
|
|
|
|
3. The `billing-webhook-ngrok-endpoint` resource starts with **explicit start** — launch it from
|
|
the Aspire dashboard when you need the tunnel active.
|
|
|
|
## Dynamic Additional Projects
|
|
|
|
Load an extra project into the orchestration without touching source files — useful for temporary
|
|
integrations or in-progress work:
|
|
|
|
```bash
|
|
# Add a project
|
|
dotnet user-secrets set "AdditionalProjects:<name>:Path" "<relative/path/to/Project.csproj>"
|
|
|
|
# Optionally wire it as a reference into an existing service
|
|
dotnet user-secrets set "AdditionalProjects:<name>:ReferencedBy:0" "api"
|
|
```
|
|
|
|
Replace `<name>` with any identifier you choose. Multiple `ReferencedBy` entries are indexed (`0`,
|
|
`1`, `2`, …).
|
|
|
|
## Self-Hosted Mode
|
|
|
|
Switch to a self-hosted database configuration:
|
|
|
|
```bash
|
|
dotnet user-secrets set "SelfHost" "true"
|
|
dotnet user-secrets set "Database:SelfHostPassword" "<password>"
|
|
```
|
|
|
|
In self-hosted mode:
|
|
- The database name changes from `vault_dev` to `self_host_dev`
|
|
- The migration script receives the `-self-hosted` flag
|
|
- Each service's effective port becomes `BasePort + 1`
|
|
|
|
## Aspire Dashboard
|
|
|
|
The dashboard opens automatically when you run the AppHost. You can also navigate to it directly:
|
|
|
|
| Profile | URL |
|
|
|-----------------|---------------------------|
|
|
| HTTPS (default) | `https://localhost:17271` |
|
|
| HTTP | `http://localhost:15055` |
|
|
|
|
The dashboard shows live resource status, structured logs, distributed traces, and environment
|
|
variables for every resource.
|
|
|
|
## Security — Do Not Commit Local Settings or Tokens
|
|
|
|
> **Warning:** Never commit local configuration values or secrets to the repository.
|
|
|
|
- `appsettings.Development.json` is checked in with intentionally empty defaults. Local overrides
|
|
belong in **user secrets**, not in that file — edits to it will appear in `git diff` and risk
|
|
accidental commit.
|
|
- `Database:Password`, `Database:SelfHostPassword`, and `NgrokAuthToken` are sensitive — always
|
|
store them with `dotnet user-secrets`, never in any `appsettings.*.json` file.
|
|
- User secrets are stored outside the repo in your OS profile, keyed by the `UserSecretsId` in
|
|
`AppHost.csproj`, and are never tracked by git.
|
|
- If you create an `appsettings.local.json`, add it to `.gitignore` before writing any values
|
|
to it.
|
|
|
|
## Git Worktrees
|
|
|
|
Path-based settings resolve relative to where you run `dotnet run`. If your worktree lives in
|
|
a different location than the main checkout, those paths won't resolve correctly. Use absolute
|
|
paths for any such setting:
|
|
|
|
- **`ClientsPath`** defaults to `../../clients/apps` — override if your worktree is not
|
|
alongside the `clients` repo:
|
|
|
|
```bash
|
|
dotnet user-secrets set "ClientsPath" "<absolute/path/to/clients/apps>"
|
|
```
|
|
|
|
- **`AdditionalProjects:<name>:Path`** — use an absolute path when adding projects via user
|
|
secrets in a worktree:
|
|
|
|
```bash
|
|
dotnet user-secrets set "AdditionalProjects:<name>:Path" "<absolute/path/to/Project.csproj>"
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
| Symptom | Fix |
|
|
|----------------------------------|---------------------------------------------------------------------------------------|
|
|
| Secrets not applied to services | Re-run `setup-secrets` from the Aspire dashboard, or verify `dev/secrets.json` exists |
|
|
| SQL Server container won't start | Confirm Docker Desktop is running and port 1433 is free |
|
|
| Migrations fail immediately | Ensure `pwsh` (PowerShell) is on your `$PATH` |
|
|
| Port conflicts on startup | Set the conflicting `Services:<name>:BasePort` to a free port via user secrets |
|
|
| Services stuck waiting | Check the dashboard logs for `setup-secrets` or `run-db-migrations` errors |
|