UMA NWC Docker Image
The UMA NWC Docker image is a pre-built Docker image that handles all of the Nostr Wallet Connect
communication, budget management, connection setup and management UI, etc. It is configurable via environment variables
to control UI branding, database storage, supported NWC commands, and more. You can find the code for the image in
this github repo along with steps for running it from
source. The image is also available on Github Container Registry at
ghcr.io/uma-universal-money-address/uma-nwc-server
.You can pull the image with:
docker pull ghcr.io/uma-universal-money-address/uma-nwc-server:latest
Other tags include
main
for the tip of tree and vX.Y.Z
for specific versions. Releases are tagged in the Github repo
and latest
is updated with each tagged release.You also use the image as a base for your own Dockerfile to add customizations or additional services by using this
image in the
FROM
directive:FROM ghcr.io/uma-universal-money-address/uma-nwc-server:latest
Of course, you can also use the image directly with
docker run
:docker run -p 8080:8081 \
-e QUART_CONFIG=config/prod.py \
ghcr.io/uma-universal-money-address/uma-nwc-server:latest
The next section will cover what goes in that
QUART_CONFIG
file and other environment variables you can use to configure
the image.The docker image is built using the Quart web framework, which is a Python
async web framework. Quart can be configured with a config file
that sets up variables used by the application. At runtime, you can pass in a file path to the
QUART_CONFIG
environment
variable to tell Quart where to find the configuration file. The github repo includes some sample config files that you
can use as a starting point or when running locally during development. See
this directory for those configs.The quart config file can set the many variables that control the behavior of the NWC server. Here is an example configuration:
import os
# You can connect to any string that's a valid SQLAlchemy connection string.
DATABASE_URI: str = f"postgresql://{db_username}@{db_endpoint}/{db_name}"
# For AWS RDS, you can use something like the following settings:
# DATABASE_URI: str = f"postgresql+psycopg://{db_username}@{db_endpoint}/{db_name}?sslmode=verify-full&sslrootcert=/etc/vasp_secrets/rds-ca.pem"
# DATABASE_MODE = "rds"
# For local development, you can use a sqlite database:
# DATABASE_URI: str = "sqlite+aiosqlite:///" + os.path.join(
# os.getcwd(), "instance", "nwc.sqlite"
# )
# It's a good practice to set secrets up in your secrets manager. For example, helm can mount a secret as a file:
# Create your own constant nostr private key via `openssl rand -hex 32`. Save it somewhere safe!
with open("/etc/secrets/nostr_privkey.pem") as f:
NOSTR_PRIVKEY = f.read().strip()
# A secret key for encrypting cookies.
with open("/etc/secrets/secret.key") as f:
SECRET_KEY = f.read().strip()
# The public key for verifying JWTs from the VASP. See the next section for how to generate this.
UMA_VASP_JWT_PUBKEY = "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs/o5+uQbTjL3chynL4wXgUg2R9\nq9UU8I5mEovUf86QZ7kOBIjJwqnzD1omageEHWwHdBO6B+dFabmdT9POxg==\n-----END PUBLIC KEY-----"
# The URL to the VASP's login page. This is where the NWC image will redirect users to login.
UMA_VASP_LOGIN_URL = "https://examplevasp.com/login/umaauth"
# The URL to the VASP's token exchange endpoint. This is where the NWC image will exchange the user's
# short-lived JWT for a long-lived one. See NWC Container Auth Token Exchange.
UMA_VASP_TOKEN_EXCHANGE_URL = "https://examplevasp.com/umanwc/token"
# The base URL of the VASP's API where you set up the OpenAPI schema as described in "VASP UMA Auth API Schema".
# This is where the NWC image will send requests to the VASP.
VASP_UMA_API_BASE_URL = "https://examplevasp.com/umanwc"
# A name and logo for the VASP that will be displayed in the Permission and Connection Management UI.
VASP_NAME = "Example VASP"
VASP_LOGO_URL = "https://examplevasp.com/logo.png"
# The nostr relay where your NWC image will send and receive messages. For development, you can use Alby's public relay.
# See the "Running a Relay" guide for more details.
RELAY = "wss://relay.getalby.com/v1"
# The URL of the NWC image's root domain.
NWC_APP_ROOT_URL = "https://nwc.examplevasp.com"
# The NWC commands that your VASP supports. This should be a list of strings from the list below that
# corresond to the endpoints you implemented in the OpenAPI schema.
VASP_SUPPORTED_COMMANDS = [
"pay_invoice",
"make_invoice",
"lookup_invoice",
"get_balance",
"get_budget",
"get_info",
"list_transactions",
"pay_keysend",
"lookup_user",
"fetch_quote",
"execute_quote",
"pay_to_address",
]
The NWC image uses a SQL database to store connection information, budgets, and other data. The database is configured with
the
DATABASE_URI
variable in the config file. The image supports any database that is supported by SQLAlchemy. For
example, you can use a local sqlite database for development or a managed database like AWS RDS for production. The
database schema is managed by the image and will be created automatically when the image is run. See above for some
example database configurations.If your database of choice is not supported, please file an issue in the github repo to request support. Alternatively,
we're happy to accept pull requests that add support for additional databases if you'd like to contribute.
The NWC image includes a management UI that allows users to manage their connections, budgets, and permissions. The UI is
configurable with the
VASP_NAME
and VASP_LOGO_URL
currently. The UI is intentionally generic to minimize
branding conflicts. We may add more branding options (colors, etc.) in the future if there is demand for it. Please file
an issue in the github repo if you have a specific request.You may want to allow your users to manage their UMA Auth connections from your website. To do this, you can link to the
management UI with the following URL (replace
nwc.examplevasp.com
with the URL of your NWC image):https://nwc.examplevasp.com/connections
UMA uses a configuration document similar to OpenID Connect's discovery document to describe the endpoints and capabilities
of the VASP. In UMA Auth, this document is used by client applications to find the authentication and token endpoints, as
well as some metadata about the VASP. See
UMAD-10
for a full spec on this file. You'll need to serve a JSON response at
/.well-known/uma-configuration
on your
VASP server domain. For example, if you'd hosted the docker image at https://nwc.examplevasp.com/
, and your user's UMA
addresses are $<user>@examplevasp.com
, you would need to respond to
GET https://examplevasp.com/.well-known/uma-configuration
with something like:{
"name": "Cool Example VASP",
"uma_major_versions": [0, 1],
// The auth endpoint in the NWC image is /oauth/auth.
"authorization_endpoint": "https://nwc.examplevasp.com/oauth/auth",
// The token endpoint in the NWC image is /oauth/token.
"token_endpoint": "https://nwc.examplevasp.com/oauth/token",
// The connection management endpoint in the NWC image is /connections.
"connection_management_endpoint": "https://nwc.examplevasp.com/connections",
// The revocation endpoint in the NWC image is /oauth/revoke.
"revocation_endpoint": "https://nwc.examplevasp.com/oauth/revoke",
// Should always be "authorization_code" for UMA Auth.
"grant_types_supported": ["authorization_code"],
// Should always be S256 for UMA Auth.
"code_challenge_methods_supported": ["S256"],
}
This is an example Helm chart that you can use to deploy the NWC image to a Kubernetes cluster. The chart includes
configmaps and secrets for the configuration file and secrets that the NWC image needs to run. You can use this as a
starting point for your own deployment.
deployment.yaml
:apiVersion: apps/v1
kind: Deployment
metadata:
name: nwc
spec:
replicas: 1
selector:
matchLabels:
app: nwc
template:
metadata:
labels:
app: nwc
spec:
containers:
- name: nwc
image: ghcr.io/uma-universal-money-address/uma-nwc-server:latest
ports:
- containerPort: 8081
env:
- name: QUART_CONFIG
value: /etc/nwc/config.py
volumeMounts:
- name: nwc-secrets
mountPath: /etc/secrets
- name: nwc-config
mountPath: /etc/nwc
volumes:
- name: nwc-secrets
secret:
secretName: nwc-secrets
- name: nwc-config
configMap:
name: nwc-config
configmap.yaml
:apiVersion: v1
kind: ConfigMap
metadata:
name: nwc-config
data:
config.py: |
import os
DATABASE_URI: str = f"postgresql+psycopg://{db_username}@{db_endpoint}/{db_name}"
# ... other config variables
secrets.yaml
(you can use helm-secrets to manage secrets in Helm):apiVersion: v1
kind: Secret
metadata:
name: nwc-secrets
data:
nostr_privkey.pem: <base64 encoded private key>
secret.key: <base64 encoded secret key>
values.yaml
:db_username: "mydbuser"
db_endpoint: "mydbcluster.us-west-2.rds.amazonaws.com"
db_name: "mydbname"
Chart.yaml
:apiVersion: v2
name: nwc
description: "UMA NWC Server"
version: 0.1.0