Running locally¶
This page runs the service on your machine, from a virtual environment or in a Docker container. The service reads its configuration from the environment variables at the end of this page; Deployment describes how the production container sets them.
What a local run changes¶
With real AWS keys, a local run changes the production account
The service has no local or mock mode. It acts on the AWS account that
its keys belong to, and on the MSK cluster that DEFAULT_SERVERS
names:
- IAM:
POST /api/v3/userandPOST /api/v3/keycreate IAM users, policies and access keys, and theDELETEroutes delete them. When the service's keys table holds no key for the caller,POST /api/v3/keydeletes every access key the caller's IAM user holds before it creates a new one. No variable changes where the IAM users go. - DynamoDB: without
KEYS_TABLE_NAME,USERS_TABLE_NAMEandNAMESPACE_TABLE_NAME, the service reads and writes the production tables. - MSK: with
DEFAULT_SERVERSset, the topic routes create and delete topics on that cluster, and the consumer routes read from it.
IAM users and namespaces are named after the caller's Globus identity.
If you call a local service with the Globus identity you use with the
production service, it acts on the same IAM user as production and,
with DEFAULT_SERVERS set, on the same topics.
Keep a local run away from production data¶
The test tables keep the service's records out of the production tables, but they do not isolate IAM. IAM users, policies and access keys always go to the account that the AWS keys belong to, named after the caller's Globus identity.
-
Point the three tables at the test tables, which the live tests also use.
.env.exampledoes this:KEYS_TABLE_NAME=test-diaspora-keys-table USERS_TABLE_NAME=test-diaspora-users-table NAMESPACE_TABLE_NAME=test-diaspora-namespace-tableIf a table name is misspelt, the service creates a new table with that name in the account at its first write.
-
Leave
DEFAULT_SERVERSunset unless you need the cluster. The topic routes then change only the service's records, and creating a consumer or recreating a topic fails withKafka endpoint is not configured. - Call the service with a Globus identity that has no resources in the production service. By default the SDK requests tokens only for the production service's Globus client (Call the API). A local service that takes SDK tokens therefore runs with the production client, and the SDK signs you in with your own Globus identity, the one production also knows.
- When you are done, and only for an identity that has no resources in
production, call
DELETE /api/v3/user. It deletes the IAM user, its policy, its access keys, its default namespace and that namespace's topics. For an identity you also use with production, it deletes the production IAM user and policy.
If you call a local service on the test tables with an identity that has a
key in production, your first POST /api/v3/key finds no key in the test
keys table. It deletes the access keys of your production IAM user and
creates a new one. Clients that hold your old key, such as the SDK on your
machine, can no longer connect to the cluster. The production keys table
still holds the deleted key, and the production service's
POST /api/v3/key keeps returning it with fresh set to false. To
recover, call DELETE /api/v3/key on the production service, then
POST /api/v3/key there: the first deletes the IAM user's keys and the
stored key, and the second creates and stores a new one. After that, a
local DELETE /api/v3/key or DELETE /api/v3/user with that identity
still acts on the production IAM user, whatever the test tables hold. A
local POST /api/v3/key keeps returning the deleted key from the test
keys table. No route removes that item without also deleting the IAM
user's keys, so delete it from the table directly.
To check only that the service starts, run it with the placeholder values
of the unit tests (Run the unit tests locally).
It makes no AWS call and serves its API documentation at /. API requests
with a well-formed token reach Globus but not AWS, and fail: Globus
rejects the placeholder client credentials, so they get 500
(Authentication lists the other
answers).
Set up¶
The service needs Python 3.14, which CI and the container image run. A full local run also needs AWS keys for the service's account and the ID and secret of the service's Globus confidential client. Without them, you can run the unit tests and start the service with placeholders.
Install the locked dependencies, the service and the locked dev tools, as CI does (Dependencies):
python3.14 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
pip install --no-deps -e .
pip install -r requirements-dev.txt -c requirements.txt
cp .env.example .env
The required values are keys for the production service's AWS account
and the production service's Globus client, so read
What a local run changes before you fill them
in. Fill in the required values in .env, which git ignores. Write each value
without quotes and without a trailing comment: docker run --env-file
takes every value literally.
Run from the virtual environment¶
In development mode, with reloading on code changes:
As the container runs it, with gunicorn and one Uvicorn worker:
(set -a; . ./.env; set +a; exec gunicorn --bind 127.0.0.1:8000 -k web_service.worker.Worker --graceful-timeout 30 web_service.main:app)
The parentheses run each command in a subshell, so the values from .env
stay out of your shell. Run one worker only: the service keeps consumer
instances in the worker's memory
(One worker). gunicorn reads its worker count
from WEB_CONCURRENCY and extra options from GUNICORN_CMD_ARGS, so a
value of either in your shell can change the number of workers.
The API documentation is at http://127.0.0.1:8000/.
Run in Docker¶
Build the image from the repository root, then run it with .env:
docker build -t diaspora-service -f web_service/Dockerfile .
docker run --rm -p 127.0.0.1:8000:8000 --env-file .env diaspora-service
The Dockerfile pins the platform linux/amd64, which Lightsail runs. The
image runs the service as a user other than root. To have the service
report the commit in its version, as deployed images do, add
--build-arg GIT_SHA="$(git rev-parse HEAD)" to docker build
(Releases).
Call the API¶
Every API route needs two headers: subject, the caller's Globus identity ID,
and authorization, a Globus bearer token. The service accepts a token
only when it names SERVER_CLIENT_ID in its audience and carries the
scope https://auth.globus.org/scopes/<SERVER_CLIENT_ID>/action_all. The
API reference shows how to get both headers with the
Diaspora Event SDK. By default the SDK requests tokens for the production
service's Globus client, so its tokens work with a local service only when
SERVER_CLIENT_ID is that client's ID.
Environment variables¶
The service checks the required variables when web_service.main is
imported. A missing or empty one stops it with
AssertionError: <NAME> environment variable is not set.
| Variable | Required | Default | What it does |
|---|---|---|---|
AWS_ACCESS_KEY_ID |
yes | The AWS access key the service uses for IAM, DynamoDB and MSK. | |
AWS_SECRET_ACCESS_KEY |
yes | The secret of that key. | |
SERVER_CLIENT_ID |
yes | The ID of the Globus confidential client that tokens must be issued for. | |
SERVER_SECRET |
yes | The secret of that client, used to introspect tokens. | |
AWS_ACCOUNT_ID |
yes | The account in the ARNs of the IAM policies the service writes. | |
AWS_ACCOUNT_REGION |
yes | The region of the DynamoDB tables and the MSK cluster. | |
MSK_CLUSTER_NAME |
yes | The cluster named in those IAM policies. | |
DEFAULT_SERVERS |
no | unset | The MSK bootstrap brokers for IAM authentication, as comma-separated host:port pairs. The service returns it to users with their key. Unset, the service makes no Kafka calls. |
KEYS_TABLE_NAME |
no | diaspora-keys-table |
The DynamoDB table of access keys. |
USERS_TABLE_NAME |
no | diaspora-users-table |
The DynamoDB table of the namespaces each user owns. |
NAMESPACE_TABLE_NAME |
no | diaspora-namespace-table |
The DynamoDB table of the topics in each namespace. |
MAX_TOPICS_PER_NAMESPACE |
no | 50 |
The most topics a namespace may hold. A value that is not a whole number of at least 1 is logged and replaced by 50. |
CONSUMER_INSTANCE_TIMEOUT_MS |
no | 300000 (5 minutes) |
How long a consumer instance may sit idle before the service closes it. A value that is not an integer, including an empty one, stops the service at start with a ValueError. |
IAM_USER_PERMISSIONS_BOUNDARY_ARN |
no | unset | The ARN of a managed policy that the service sets as the permissions boundary of every IAM user it creates. Production leaves it unset; the live tests set it (Testing). |
The AWS SDK reads the two key variables itself, and with them
AWS_SESSION_TOKEN when you use temporary credentials.