Coolify Deployment
Deploy the complete LaWallet NWC stack from GitHub with Docker Compose, TLS, the NWC listener, and push-to-deploy.
Coolify can deploy the complete repository directly from
GitHub. This is the production layout used for LaWallet: Coolify builds the
root docker-compose.yml, runs Postgres, web, docs, OpenAPI, and the optional
NWC listener, then routes the public web service through its managed proxy.
This guide uses a domain such as wallet.example.com. Replace it with the
domain you control.
Before you start
- A Coolify server with a public IP address.
- A GitHub repository or fork of
lawalletio/lawallet-nwc. - A DNS
Arecord forwallet.example.compointing to the Coolify server. - Coolify reachable publicly over HTTPS. GitHub must be able to deliver the push webhook to it for automatic deployments.
Create the application
- In Coolify, create a project and choose New Resource → Application.
- Select the GitHub repository and the production branch (normally
main). For a public repository, the built-in Public GitHub source is enough; a GitHub App also works. - Choose the Docker Compose build pack.
- Set Docker Compose Location to
/docker-compose.ymland leave Base Directory as/. - Create the application. Do not deploy it until the environment variables below are saved.
The Compose file builds four public-facing/internal services plus Postgres:
| Service | Purpose | Public domain needed? |
|---|---|---|
web | LaWallet UI, REST API, LUD-16 endpoints | Yes |
listener | Long-lived NWC relay bridge | No — internal only |
postgres | Application and listener data | No — internal only |
docs / openapi | Documentation and OpenAPI surfaces | Optional |
Generate and import environment variables
From a local clone, generate the complete Compose environment:
bash scripts/generate-deployment-env.sh \
--mode compose \
--output lawallet.coolify.envOpen lawallet.coolify.env, copy every entry into Coolify's Environment
Variables editor, and mark the password and all variables ending in
_SECRET as secret. Delete the local copy after storing it in your encrypted
backup.
The file includes independent values for Postgres, JWT signing, the user-key
vault, the RemoteWallet/proxy NWC vault, and both listener authentication directions. It
also sets COMPOSE_PROFILES=listener and
LISTENER_URL=http://listener:4100.
See Environment Variables for a description of every value and rotation guidance.
COMPOSE_PROFILES=listener is important: without it Docker Compose does not
start the optional listener service. LISTENER_URL uses Docker's internal
service DNS, so it must remain http://listener:4100; it should not be exposed
as a public URL.
LISTENER_AUTH_SECRET and LISTENER_REQUEST_AUTH_SECRET are intentionally
different. Keeping them separate isolates listener-to-web webhook signing from
web-to-listener requests. Both must be supplied to the Compose deployment.
NWC_VAULT_SECRET is passed by Compose to both web and listener. Keep it stable
across upgrades and backups; changing it makes stored NWC credentials
unreadable. The NIP-57 receipt signer is an nsec configured in Admin →
Settings → NWC Services, not a Coolify environment variable.
Add the domain and TLS
In the application Domains / Compose domain configuration, assign the
domain to the web service with its internal port:
https://wallet.example.com:2288Enable Force HTTPS. Coolify requests and renews the TLS certificate after
the DNS record resolves to the server. The :2288 suffix tells Coolify which
container port to route to; visitors still use the normal HTTPS URL without a
port.
Do not add a public domain to postgres or listener. The listener is reached
by web over the Compose network and its /health endpoint is checked by
Docker Compose.
Deploy and verify
Click Deploy. The first deployment builds the images, waits for Postgres, runs Prisma migrations through the web container startup, and then starts the listener and web services.
Verify the public application after Coolify reports running:healthy:
curl https://wallet.example.com/api/health
# {"status":"ok","service":"web","database":"up"}In the deployment log, confirm that Coolify created and started both services:
Container listener-... Created
Container listener-... Started
Container web-... StartedThe listener is private by design. To check its integration after the first administrator setup, use Admin → Settings → NWC Services in LaWallet and run the connection test.
Enable automatic deploys
Enable Auto Deploy in the application's advanced settings. With a GitHub App source, Coolify manages push events automatically. For the public GitHub source used by this stack, configure a repository webhook instead:
- In Coolify's application webhook settings, copy the GitHub manual webhook URL and its secret.
- In GitHub, open Repository → Settings → Webhooks → Add webhook.
- Paste the Coolify URL, set the copied secret, select content type
application/json, enable SSL verification, and choose only the Push event. - Save it and confirm GitHub's initial
pingdelivery returns HTTP 200.
Every push to the configured branch now makes Coolify pull the new commit,
build the Compose images, and replace the stack. GitHub sends push events for
all branches, but Coolify deploys only the application's configured branch
(main in this guide).
Updating and rollback
- Push a commit to
mainto trigger the automatic deployment. - Use Coolify's Deployments history to inspect build logs and redeploy a known good commit if necessary.
- Back up the Postgres volume before destructive maintenance. The Compose database is the source of truth for both the web app and listener state.
For more detail on the listener's health endpoints, pairing, and failure modes, see NWC Listener Setup. For a local Compose or Docker Hub deployment, see Docker Deployment.