
Deploy WAHA [Updated Oct '26]
WhatsApp HTTP API. No per-message fees. Sessions survive redeploys.
WAHA
Just deployed
/local
Deploy and Host WAHA on Railway
WAHA (WhatsApp HTTP API) turns WhatsApp into a REST API — send and receive messages, manage groups and contacts, wire up webhooks, run multiple sessions — without per-message fees or Meta Business approval. It's Apache-2.0, actively maintained, and has over 7,500 GitHub stars. This template deploys the official devlikeapro/waha image directly and fixes two real bugs found in Railway's own official WAHA template: a session-restart variable that doesn't exist in WAHA's codebase, and a healthcheck path that would 401 on every single probe.
About Hosting WAHA
This template runs devlikeapro/waha unmodified — no Dockerfile, no forked code, no custom start command. Everything this template adds is configuration: a pinned port that matches the domain's target port, a healthcheck path that's actually reachable without authentication, and the correct variable name for automatic session recovery after a redeploy.
Those sound like small details, but they're the difference between a template that looks configured and one that's actually been checked against the app's real behavior. Railway's reference waha-api template sets WAHA_RESTART_ALL_SESSIONS=True — a variable that doesn't exist anywhere in WAHA's source. It's silently ignored, which means a redeploy drops your WhatsApp session and nobody's told. This template uses the real variable, WHATSAPP_RESTART_ALL_SESSIONS, confirmed against WAHA's config.service.ts and verified live in deploy logs.
Common Use Cases
- Business messaging automation: order confirmations, appointment reminders, and support replies sent straight from your own backend, no per-message platform fee
- Chatbots and AI assistants: wire WAHA's webhooks into an LLM or workflow tool (n8n, Zapier, your own code) to auto-respond to incoming messages
- CRM and support-inbox integration: sync WhatsApp conversations into your existing ticketing or CRM system via REST calls and webhooks
- Multi-session WhatsApp gateways: run several WhatsApp numbers from one deployment, each as an independent session
Dependencies for WAHA Hosting
Running this template needs nothing beyond the container and one persistent volume — WAHA has no external database or separate services to wire up for the Core (free) tier used here. You bring a WhatsApp number to scan into a session via the dashboard, and whatever downstream system (webhook receiver, CRM, chatbot) you want WAHA to talk to.
Deployment Dependencies
Implementation Details
WAHA's Dockerfile exposes port 3000, and its config.service.ts resolves the actual listening port by checking PORT first, falling back to WHATSAPP_API_PORT (default 3000). Railway's reference template leaves PORT unset and hardcodes the domain's target port to 8080 instead, relying entirely on Railway's post-boot port auto-detection to reconcile the two. It happens to work, but it's one platform quirk away from a silent mismatch. This template sets PORT=3000 explicitly and generates the domain against that exact same port.
The healthcheck took closer reading. WAHA has a HealthController that does real work — checking free disk space on the media and session volumes — which made /health look like the obvious choice. Reading app.module.core.ts showed otherwise: the health route is registered with authApiKey: true, which wires WAHA's API-key middleware onto it. Since this template (like any sane deployment) sets WAHA_API_KEY, an unauthenticated request — exactly what Railway's healthcheck prober sends — gets rejected with 401 before the health logic ever runs. A healthcheck that always fails is worse than none at all. The one route registered with zero auth anywhere is /ping (confirmed in ping.controller.ts — no guards, just a static {"message": "pong"}), so that's what this template points the healthcheck at instead.
Why Deploy WAHA on Railway?
Railway removes the infrastructure WAHA would otherwise need you to manage yourself: TLS, a reverse proxy, a place for session data to survive a restart. Generate a domain and you have HTTPS; mount a volume and session data outlives every redeploy.
Beyond the platform, this template specifically fixes what breaks when you actually rely on the reference template's claims. "Sessions restart automatically" only means something if the variable it's wired to is real. "Healthy" only means something if Railway's probe can actually reach the endpoint it's checking. Both were broken in the official template and are fixed here, verified against the running app rather than assumed from the variable names.
What Was Verified
This wasn't verified by watching the deploy log turn green — it was verified by hitting the live endpoints directly. GET /ping returns 200 {"message":"pong"} with no headers, confirming the healthcheck path actually works pre-auth. GET /health returns 401 Unauthorized without an API key and 200 with one (its deep check reporting both the media and session volumes as healthy) — proof that using it as the healthcheck path, as the obvious choice would suggest, would have failed Railway's probe on every single deploy. GET / serves Swagger UI gated by the Swagger credentials; GET /dashboard serves the QR-login dashboard gated by its own credentials; GET /api/version (with the API key) confirms the WEBJS engine and its Chromium binary are both present and running.
The session-restart fix was verified in the deploy logs themselves: Restarting sessions with delay of 0 seconds... STOPPED sessions have been restarted. — a line that only appears because WHATSAPP_RESTART_ALL_SESSIONS is a variable WAHA's code actually reads. The reference template's WAHA_RESTART_ALL_SESSIONS produces no such line, because nothing in WAHA is listening for it.
Frequently Asked Questions
Why isn't /health used as the healthcheck path?
Because it requires the x-api-key header — it's registered with authApiKey: true in WAHA's own route configuration. Railway's healthcheck prober sends a plain, unauthenticated request, so pointing it at /health means every deploy gets marked unhealthy regardless of whether the app is actually fine. /ping is the one endpoint with no auth requirement anywhere in the app.
What's wrong with WAHA_RESTART_ALL_SESSIONS?
It isn't a real variable — a full search of WAHA's source code returns zero references to it anywhere. Setting it does nothing. The variable that actually controls automatic session restart after a redeploy is WHATSAPP_RESTART_ALL_SESSIONS, which this template uses instead.
Does this template modify WAHA's code?
No. It's the unmodified official devlikeapro/waha image — every difference from a bare docker run is in the environment variables and service configuration, not the application itself.
Which WhatsApp engine does this template use?
WEBJS (headless Chromium) by default, matching the reference template's proven-working behavior. If you're on a memory-constrained plan, WAHA's own docs recommend NOWEB — a lighter, browser-free engine — as a one-variable swap (WHATSAPP_DEFAULT_ENGINE=NOWEB).
Will my WhatsApp sessions survive a redeploy?
Yes — session data lives on a persistent volume mounted at /local, and WHATSAPP_RESTART_ALL_SESSIONS=True (the real variable, not the reference template's dead one) automatically reconnects stopped sessions once the new deployment boots.
Where can I download WAHA?
Source is on GitHub at github.com/devlikeapro/waha. Use this template to deploy the official Core image with the healthcheck and session-restart bugs already fixed, in one click.
Source for this template's docs: https://github.com/shruti060701/waha-railway
Template Content
WAHA
devlikeapro/waha