https://github.com/thunderbird/thunderbird-accounts
Thunderbird Accounts
https://github.com/thunderbird/thunderbird-accounts
Last synced: about 1 month ago
JSON representation
Thunderbird Accounts
- Host: GitHub
- URL: https://github.com/thunderbird/thunderbird-accounts
- Owner: thunderbird
- License: mpl-2.0
- Created: 2024-11-08T21:23:12.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-06-12T19:19:06.000Z (12 months ago)
- Last Synced: 2025-06-12T20:48:48.138Z (12 months ago)
- Language: Python
- Size: 5.32 MB
- Stars: 6
- Watchers: 6
- Forks: 1
- Open Issues: 26
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Thunderbird Accounts
> [!IMPORTANT]
> Thunderbird Accounts is still in active development and is not ready for any active use.
[](https://pro-services-docs.thunderbird.net/en/latest/?badge=latest)
There is codebase documentation available at [https://pro-services-docs.thunderbird.net/en/latest](https://pro-services-docs.thunderbird.net/en/latest).
This project uses [uv](https://github.com/astral-sh/uv).
Thunderbird Accounts is a Django 5.2 application. Please read up on Django before diving in.
Docker is the recommended way to run the server.
## Services & Ports used
During development it's great to have these handy!
| Service | Exposed Port | Remarks |
|------------|--------------|-----------------------------------------------|
| postgres | 5433 | Accounts DB |
| kcpostgres | 5434 | Keycloak DB |
| redis | 6380 | Redis |
| redis | 8071 | Redis Insights |
| accounts | 8087 | Accounts Web |
| flower | 5555 | Celery task monitoring |
| vite-dev | 5173 | Used on Account's frontend for hot-reloading. |
| mailpit | 8025 | Mailpit Web |
| mailpit | 1025 | Mailpit SMTP |
| stalwart | 443 | Stalwart Admin |
| stawart | 8080 | Stalwart Admin |
| stalwart | 8081 | Stalwart JMAP |
| stalwart | 143 | Stalwart IMAP |
| stalwart | 993 | Stalwart IMAP TLS |
| stalwart | 25 | Stalwart SMTP |
| stalwart | 465 | Stalwart SMTP TLS |
## Before you begin
Make sure you have [uv](https://github.com/astral-sh/uv) up and running.
## Getting Started
Ensure you have uv setup and the project bootstrapped by running:
```bash
uv sync
uv run bootstrap.py
```
This will create a virtual environment if needed and sync the latest project dependencies to your local environment.
The project comes with some optional dependencies such as cli tools, tools for building the docs, and tools for working
with our Subscription app powered by Paddle.
These can be installed be appending `--extra ` like so:
```bash
uv sync --extra cli --extra docs --extra subscription
```
## Re-bootstrapping the project
If you find your environment in a troubled state (it happens) you can add the option `--from-scratch` to bootstrap like
so:
```bash
uv run bootstrap.py --from-scratch
```
This will overwrite your local `.env` with the contents of `.env.example`, copy over a fresh copy of the stalwart config
from `config.toml.example` to `mail/etc/config.toml` and delete your stalwart's internal db `mail/data`.
Additionally, you'll want to remove the volumes for both postgres and kcpostgres to clear accounts and keycloak's
database.
## OIDC / Authentication
Accounts integrates [mozilla-django-oidc](https://github.com/mozilla/mozilla-django-oidc). Included in this repo is a
basic development config for keycloak, and a keycloak environment defined in docker-compose.yml. There's nothing
stopping you from using a different OIDC provider. Please refer to the package documentation and your local `.env` file
for settings you may need to change.
## Running
Once you have the project bootstrapped you'll want to actually run the project via docker:
```bash
docker compose up --build -V
```
(Note: If you're not attached to the docker group you may need to add sudo before the above command.)
The first boot may take a while as:
* Keycloak imports realm / user information from `keycloak/data/import`
* Accounts runs the required database migrations
* Accounts pulls the latest Paddle product and subscription information (if you have the Paddle setup.)
Please wait until the containers are fully booted before continuing.
## Logging in
A variety of basic development admin accounts are provided to help folks boot the project and start working.
### Accounts / Thunderbird Pro Dashboard
You can access the login / dashboard at [http://localhost:8087/](http://localhost:8087/). If you
are not logged in you will be taken to a keycloak login screen. You can use the following credentials to proceed:
```
Username: admin@example.org
Password: admin
```
From here you can create an email account.
The default admin user is also setup you use Django's admin panel available
at [http://localhost:8087/admin/](http://localhost:8087/admin/).
### Stalwart
Stalwart is located at [http://localhost:8080/](http://localhost:8080/). Currently, there is
a [bug](https://github.com/stalwartlabs/webadmin/issues/52) preventing instances connected to an external OIDC directory
server from logging into the admin panel.
If you need to access the admin panel you can modify your `mail/etc/config.toml` and edit `[storage].directory` from
`kc` to `internal`, and restart the docker container.
From there you can login with the following credentials:
```
Username: admin
Password: accounts
```
You generally won't need to connect to Stalwart's admin panel unless you need to verify account status or debug api
calls. Make sure to change the `[storage].directory` key back to `kc` and restart the docker container when you're
finished.
### Keycloak
Keycloak is the auth/OIDC provider that is setup by default. Two realms are imported the default `master` realm and the
`tbpro` realm.
If you like to login to Keycloak's admin interface you can access that at [http://keycloak:8999/admin/master/console/](http://keycloak:8999/admin/master/console/)
with the following credentials:
```
Username: admin
Password: admin
```
From there you can switch to the tbpro realm and access settings that will affect Account's and Stalwart's login.
Additionally, you can access a simple user management portal under the tbpro realm available
at [http://keycloak:8999/realms/tbpro/account](http://keycloak:8999/realms/tbpro/account). Since this within the tbpro
realm you can login to any account you created for accounts including admin@example.org.
## Legal Documents
Legal documents (Terms of Service, Privacy Policy) are stored as markdown source files under
`assets/legal/` and served to the frontend as pre-rendered HTML within `src/thunderbird_accounts/legal/templates/`.
### Directory structure
```
assets/legal/
├── tos/
│ └── v1.0/
│ ├── en.md # Markdown source (source of truth)
└── privacy/
└── v1.0/
├── en.md
src/thunderbird_accounts/legal/templates/
├── tos/
│ └── v1.0/
│ └── en.html # Pre-rendered HTML (served by the API)
└── privacy/
└── v1.0/
└── en.html
```
Each version directory can contain multiple locale files (e.g. `de.md`, `fr.md`). The API falls
back to `en.html` when a requested locale is not available.
### Adding a new document version
1. Create a new versioned directory, e.g. `assets/legal/tos/v2.0/`
2. Write the markdown source file, e.g. `en.md`
3. Run the conversion command to generate the HTML:
```bash
uv run python manage.py convert_legal_docs
```
4. Commit both the `.md` and `.html` files
5. In Django admin, create or update the `LegalDocument` record -- set `content_path` (e.g.
`tos/v2.0`), `version`, and check `is_current`. Saving will automatically unset `is_current` on
the previous version of the same document type.
6. If adding new locales, update the SUPPORTED_LEGAL_LANGUAGES value in settings.py
### Regenerating HTML from markdown
If you edit an existing markdown file, re-run the conversion command to update the HTML:
```bash
uv run python manage.py convert_legal_docs
```
This converts all `*.md` files under `assets/legal/` and writes a sibling `.html` for each.
## Creating additional apps
Apps are feature of django we can use to create re-usable modules with. We mostly just use them to separate out and
organize components.
Apps can depend on and/or require other internal apps, there's no hard rule here.
Ensure to nest all internal apps inside `src/thunderbird_accounts` by appending the destination path after the command:
`mkdir -p src/thunderbird_accounts/ && ./manage.py startapp src/thunderbird_accounts/`
Once the app is created go to `src/thunderbird_accounts//apps.py` and prepend `thunderbird_accounts.` to
AuthConfig.name so it looks like `thunderbird_accounts.`.
## Building documentation locally
Ensure you have the requirements in docs installed and run the following command in the project's root folder:
```shell
sphinx-build docs build
```
## Feature Flags
Feature flags are stored in `localStorage` and read at runtime to toggle UI behavior.
| Key | Values | Description |
| --- | ------ | ----------- |
| `feature.show-connect-now` | `true` | Shows the "Connect Now" action card on the desktop panel, which launches Thunderbird Desktop via a custom protocol URL. |
| `feature.phase` | `2` | Enables phase 2 UI: QR code setup flow on mobile and the "Connect Now" card on desktop, replacing the auto-config placeholders. |
## Running tests
Make sure that the containers are already running.
To run all tests:
```shell
docker compose exec backend uv run python manage.py test
```
To run tests for a specific module:
```shell
docker compose exec backend uv run manage.py test thunderbird_accounts.client.tests
```
## Running the E2E tests
Please see the [E2E tests README](./test/e2e/README.md).
## Accessing the Flower Web Interface
We run Flower to surface information about Celery tasks. This service exposes a web interface on
port 5555. In development, you can access this at `http://localhost:5555` after bringing services
online with `docker-compose`. In Thunderbird's live (protected) environments, we have to create an
SSH proxy through a bastion.
How to build a bastion is documented in the Pulumi config files themselves. Once you have one that
allows traffic from your IP, you'll need to gather some info:
- Your bastion's public IP address (`$BASTION_IP`)
- The DNS address for the Flower load balancer in the environment (`$FLOWER_LB_DBS`)
- An available local port to forward through, let's say `8443`.
Open an SSH proxy to the bastion server:
```bash
ssh -L 8443:$FLOWER_LB_DNS:443 ec2-user@$BASTION_IP
```
Our live environments all use TLS, so you will need to browse to https://localhost:8443/. You will
have to push past an SSL certificate hostname mismatch alert, but then you will find yourself at the
Flower landing page, listing Celery workers on the network.