First Devnet Deployment
Run self-hosted SDP on devnet, sign in to the dashboard, create a local wallet, and verify API access.
Take a fresh self-hosted install from healthy containers to a first devnet workflow: dashboard sign-in, a local custody wallet, a wallet-scoped API key, and an authenticated API call.
Start after the Quickstart. This path runs on devnet with the local signer. Set up a provider's signing later, when you harden the deployment.
The public devnet RPC endpoint is fine for smoke tests, but it can rate-limit you or miss data that balance-heavy wallet views need. Use a dedicated devnet endpoint from your RPC provider before you rely on this flow.
Confirm the stack is healthy
From the directory that holds compose.yml and .env:
cd ~/sdp
docker compose up -d
docker compose ps
curl http://localhost:8787/healthThe health check returns JSON with "status": "ok". The dashboard is at http://localhost:3000, the API at http://localhost:8787, and these docs at http://localhost:3001.
Configure Clerk for dashboard sign-in
In your Clerk development application, follow the Clerk setup guide:
- Turn on Organizations.
- Customize the session token (Sessions → Customize session token) with the guide's claims. Without
org_id, the API refuses every dashboard request. - Copy the publishable key, secret key, and issuer for the configurator.
- Give the API a public HTTPS URL, because Clerk can't reach
localhost. To test locally, reserve a free static domain at dashboard.ngrok.com/domains and runngrok http --url=<your-domain> 8787. - Add a webhook endpoint at
https://<your-domain>/webhooks/clerk/link-orgs, subscribed to the events the guide lists. Copy its signing secret forCLERK_WEBHOOK_SECRET.
The API starts without CLERK_WEBHOOK_SECRET, but this tutorial needs it. The webhook is how SDP learns the settings you add to the organization in Clerk, including the one that turns on the local signer.
Generate the devnet .env
Open the configurator, keep its defaults, and fill in:
SOLANA_RPC_DEFAULT_DEVNET_API_KEY_URL: your devnet RPC endpoint.- The Clerk publishable key, secret key, issuer, and webhook secret.
The signing step keeps the local signer and generates its CUSTODY_PRIVATE_KEY in your browser. SDP offers the local signer only while that key is set. Save the file as ~/sdp/.env, then restart the stack:
cd ~/sdp
docker compose up -dSign in to the dashboard
Open http://localhost:3000, sign in through Clerk, and create an organization when prompted. SDP creates it with you as its admin, along with a sandbox project and a production project.
If requests fail after sign-in, read the failing request's 401 response. Clerk token missing organization means the session token lacks the org_id claim, and Clerk token has no usable email claim means its email claim is wrong: fix the session token customization.
If Clerk's webhook deliveries fail, check the API logs:
docker compose logs -f sdp-apiwebhooks: refused a Clerk webhook with an invalid signature means CLERK_WEBHOOK_SECRET doesn't match the endpoint's signing secret. Clerk's delivery log shows the same refusal as Invalid webhook signature.
Turn on the local signer
The local signer needs a per-organization activation. In the Clerk dashboard, open your organization's private metadata (Organizations → your organization → Metadata → Private) and add:
{ "sdp": { "providerOverrides": { "custody": { "local": true } } } }The organization.updated webhook brings it into SDP. Until it does, choosing the local signer returns 403 with Local requires manual activation for this organization.
Create a local custody wallet
In the dashboard, open Wallets, choose the local provider, and create a wallet named Devnet local wallet.
This step needs the dashboard. Setting up a custody provider takes wallets.configure, which no API key can hold, so an organization admin does it signed in. After that, a key with wallets.manage can create more wallets with POST /v1/wallets.
Create a wallet-scoped API key
Open API keys and create a key in the sandbox project. Under Permissions, grant at least wallets.read. Under Access, choose Selected wallets and select Devnet local wallet: it's the only wallet the key can sign with.
Copy the full key when the dashboard shows it. SDP shows it only once.
Verify the key can read wallets
Call your self-hosted API with the new key:
export SDP_API_KEY="sf_..."
curl "http://localhost:8787/v1/wallets?view=summary" \
-H "Authorization: Bearer $SDP_API_KEY"The response includes Devnet local wallet. You now have a self-hosted devnet stack with dashboard sign-in, local custody signing, and an API key bound to the wallet it may sign with.
Next steps
- Use the Environment reference to move from localhost defaults to real domains, an external Postgres, or an external Redis.
- Read Upgrade and backup before you keep data you care about in the stack.
- Use External co-signers when a provider needs a signing process outside the default stack.