---
title: "Deploy Zammad Help Desk - Self-Hosted Zendesk Alternative"
description: "Helpdesk ticketing, shared inbox, SLAs. Zendesk/Freshdesk alternative."
category: "Other"
url: https://railway.com/deploy/zammad-help-desk
---

# Deploy Zammad Help Desk - Self-Hosted Zendesk Alternative

Helpdesk ticketing, shared inbox, SLAs. Zendesk/Freshdesk alternative.

**[Deploy Zammad Help Desk - Self-Hosted Zendesk Alternative on Railway](https://railway.com/template/zammad-help-desk)**

- **Creator:** ProCode
- **Category:** Other
- **Total deploys:** 14

## Template content

### Postgres https://devicons.railway.app/i/postgresql.svg

- **Image:** postgres:17.11-alpine

### Zammad Nginx https://github.com/zammad.png

- **Image:** ghcr.io/zammad/zammad:7.1.2
- **Start command:** `bash -c 'set -e; cd /opt/zammad; : "${NGINX_PORT:=8080}"; : "${NGINX_SERVER_NAME:=_}"; : "${NGINX_SERVER_SCHEME:=\$scheme}"; : "${NGINX_CLIENT_MAX_BODY_SIZE:=50M}"; : "${ZAMMAD_RAILSSERVER_HOST:=zammad-rails.railway.internal}"; : "${ZAMMAD_RAILSSERVER_PORT:=3000}"; : "${ZAMMAD_WEBSOCKET_HOST:=zammad-websocket.railway.internal}"; : "${ZAMMAD_WEBSOCKET_PORT:=6042}"; NS=$(grep "^nameserver" --max-count 1 < /etc/resolv.conf | awk "{print \$2}"); case "$NS" in *:*) [ "${NS#[}" = "$NS" ] && NS="[$NS]";; esac; echo "resolver $NS valid=5s;" > /etc/nginx/conf.d/resolver.conf; sed -e "s#\(listen\)\(.*\)80#\1\2${NGINX_PORT}#g" -e "s#proxy_set_header X-Forwarded-Proto .*;#proxy_set_header X-Forwarded-Proto ${NGINX_SERVER_SCHEME};#g" -e "s#proxy_pass http://zammad-railsserver;#set \$zammad_railsserver_url http://${ZAMMAD_RAILSSERVER_HOST}:${ZAMMAD_RAILSSERVER_PORT}; proxy_pass \$zammad_railsserver_url;#g" -e "s#proxy_pass http://zammad-websocket;#set \$zammad_websocket_url http://${ZAMMAD_WEBSOCKET_HOST}:${ZAMMAD_WEBSOCKET_PORT}; proxy_pass \$zammad_websocket_url;#g" -e "s#server_name .*#server_name ${NGINX_SERVER_NAME};#g" -e "s#client_max_body_size .*#client_max_body_size ${NGINX_CLIENT_MAX_BODY_SIZE};#g" -e "s#/var/log/nginx/zammad.\(access\|error\).log#/dev/stdout#g" < contrib/nginx/zammad.conf > /etc/nginx/sites-enabled/default; exec /usr/sbin/nginx -g "daemon off;"'`
- **Health check:** /
- **Public domain:** Yes

### Memcached https://github.com/memcached.png

- **Image:** memcached:1.6.45-alpine
- **Start command:** `memcached -m 256M`

### Zammad Scheduler https://github.com/zammad.png

- **Image:** ghcr.io/zammad/zammad:7.1.2
- **Start command:** `bash -c "cd /opt/zammad && exec /opt/zammad/bin/docker-entrypoint zammad-scheduler"`

### Redis https://devicons.railway.app/i/redis.svg

- **Image:** redis:8.8-alpine

### Zammad Rails https://github.com/zammad.png

- **Image:** ghcr.io/zammad/zammad:7.1.2
- **Start command:** `bash -c "cd /opt/zammad && /opt/zammad/bin/docker-entrypoint zammad-init && exec /opt/zammad/bin/docker-entrypoint zammad-railsserver"`

### Zammad Websocket https://github.com/zammad.png

- **Image:** ghcr.io/zammad/zammad:7.1.2
- **Start command:** `bash -c "cd /opt/zammad && exec /opt/zammad/bin/docker-entrypoint zammad-websocket"`

## Documentation

# Deploy and Host Zammad Help Desk on Railway

Zammad is an open source helpdesk and customer support system, and a self-hosted alternative to
Zendesk and Freshdesk. It turns email, web forms and chat into one shared inbox with ticketing,
SLAs, triggers and automations, a knowledge base, reporting and full text search. Self hosting it
normally costs a weekend of Docker Compose work; this template deploys the whole tested stack in
one click, so you own your support data without doing that work.

## About Hosting Zammad Help Desk

Zammad runs as four application roles from the same image: a Rails web app, a scheduler for background
jobs and email polling, a websocket server for real time updates, and an nginx reverse proxy; backed
by PostgreSQL, Redis and Memcached. The startup order for the services is important, because the DB
must be migrated and seeded before the application roles start, and Railway has no depends_on and no
shared volumes between services. The private network is also IPv6 only, which a stock nginx config
will not resolve on.

This template solves all these challenges, and is updated and tested regularly. The init step is included
in the Rails start command and the other roles restart until the DB responds, so the stack runs
in the right order. Attachments and settings live in PostgreSQL, which makes everything work without
a shared file volume. nginx's custom start command works with the IPv6 resolver address correctly.
PostgreSQL gets a persistent volume. The DB password is generated fresh on every deployment.
The public URL is on the nginx service - the rest stay on the private network.

Additionally, Health Checks are set up on the ngninx service, and Docker images are pinned to versions
that have been tested, and are periodically updated - vs using a "latest" image that may point to
something else as you redeploy to a new environment, causing unexpected failures.

## Common Use Cases

- **Customer support shared inbox**: turn a support address into tracked, assignable tickets with
  SLAs, triggers and automations
- **Internal IT or HR help desk**: a request tracking system with a self service knowledge base
- **Leaving a SaaS help desk**: a data private replacement for Zendesk or Freshdesk that you fully
  own, with importers for moving your existing tickets across
- **Data residency requirements**: customer conversations stay in infrastructure and a region you
  choose

## How to Use Zammad Help Desk After Deployment

1. Let the first deploy finish. It runs database migrations and seeding, so it takes several
   minutes longer than later deploys (about 5 minutes for me), and services restart during that window.
2. Optionally assign a custom URL to the `Zammad Nginx` service (port remains 8080), or else copy
   the generated Railway URL assigned to it - this is the URL to access Zammad with.
3. **First run**: Open Zammad in your browser (URL in step 2), and complete the setup wizard to
   create your admin user and your organization.
4. Set the Base URL to your Railway domain under **Administration _(Settings Icon)_ → Settings → System**.
5. Connect a mailbox under **Administration _(Settings Icon)_ → Channels → Email** over IMAP and SMTP
   to start turning email into tickets.
6. Invite your agents, and review the SLA and trigger defaults before you point real customers at
   it.

## Dependencies for Zammad Help Desk Hosting

- PostgreSQL: the system of record for tickets, users, attachments and settings
- Redis: websocket/ActionCable backend and session store
- Memcached: application cache
- An email account with IMAP and SMTP access: optional, but it is how most teams feed the inbox

### Deployment Dependencies

- [Zammad project site](https://zammad.org)
- [Zammad documentation](https://docs.zammad.org)
- [Zammad source on GitHub, AGPL-3.0](https://github.com/zammad/zammad)
- [Official Zammad Docker images](https://github.com/zammad/zammad-docker-compose)

### Implementation Details

- **Lite build.** Elasticsearch is disabled, so Zammad uses its built in database search and the
  stack boots on a modest plan. To add advanced search later, deploy an Elasticsearch service and
  set ELASTICSEARCH_ENABLED to true, plus ELASTICSEARCH_HOST and ELASTICSEARCH_PORT, on each of the
  four Zammad roles.
- **Storage.** Attachments are kept in PostgreSQL, not on a disk - which makes the application roles
  stateless. For a very large attachment library, switch to S3 under **Administration _(Settings Icon)_ → Settings → System → Storage**.
- **What it costs to run.** In my testing, about 12$/month - your mileage may vary.
- **Redeploys interrupt briefly.** Railway stops the old container before starting the new one, so
  a burst of 502s during a redeploy is expected.
- **How to Upgrade:** The template never changes a deployment that already exists. To upgrade,
  manually raise the Zammad image tag on your own services when you want a newer release; your data
  is in PostgreSQL, so this should work. Note that I do periodically update this template and test that
  all the service versions are compatible with each other, so you might be able to use the versions on
  the latest template. Railway can also update image based services on its own (per service, under
  **Settings → Source → Configure Auto Updates**). If you use it here, enable it on all four Zammad
  roles with the same schedule or leave it off entirely: the roles run one shared image and must stay
  on the same tag, and updates landing at different times would leave them on mismatched versions.
  On the Hobby plan there is no automatic pre-update volume backup, so back up before enabling.
- **License.** Zammad is AGPL-3.0, and self hosting your own instance is exactly the case the
  license is written for.

## Is Zammad Free?

Yes. Zammad is open source under AGPL-3.0, with no agent limit and no per seat license, so the
software itself costs nothing however many people you put on it. On Railway you pay only for the
infrastructure that the seven services and one volume use. The Zammad project also sells a hosted
version and a support subscription - not required for this template, but supporting them is encouraged.

## Zammad vs a SaaS Help Desk

|                      | This template                 | Zendesk or Freshdesk  |
| -------------------- | ----------------------------- | --------------------- |
| Where the data lives | your own Railway project      | the vendor's cloud    |
| License              | AGPL-3.0, open source         | proprietary           |
| Cost model           | infrastructure only           | per agent, per month  |
| Agent limit          | none                          | set by your plan tier |
| Custom domain        | yes                           | yes                   |
| Migrating in         | importers included, see below | not applicable        |

Zammad ships importers for **Zendesk, Freshdesk, Kayako and OTRS**, so moving an existing help desk
across is supported. If you are comparing open source options, FreeScout is also AGPL-3.0 and osTicket
is GPL-2.0; Zammad's distinguishing features are the websocket driven real time interface and the built
in migration importers.

## FAQ

**What is Zammad used for?**
Tracking customer or internal support requests. Email, web forms and chat land in one shared inbox,
become tickets, and get routed, escalated and answered by a team with SLAs and automations.

**Is Zammad a good Zendesk alternative?**
It covers the core Zendesk workflow, shared inbox, ticketing, SLAs, automations, knowledge base and
reporting, and it is self hosted, so your conversation history stays in infrastructure you control.
Importers make it practical to switch to Zammad.

**Can I migrate my existing tickets?**
Yes, from Zendesk, Freshdesk, Kayako and OTRS. Run the import from Zammad's admin interface once
the instance is up.

**Why is the first deploy slower than later ones?**
The first boot creates the schema and seeds the database before the application roles can start.
Roles that come up early restart until the database is ready, which is intentional.

**Do I need Elasticsearch?**
No. This build runs Zammad's built in database search, which is fine for typical volumes. Add
Elasticsearch when your archive grows large enough that search gets slow.

**Can I use my own domain?**
Yes. Add your custom domain to the `Zammad Nginx` service in Railway, then update the Base URL in
**Administration _(Settings Icon)_  → Settings → System** to match it.

## Why Deploy Zammad Help Desk on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your
infrastructure so you don't have to deal with configuration, while allowing you to vertically and
horizontally scale it.

By deploying Zammad Help Desk on Railway, you are one step closer to supporting a complete
full-stack application with minimal burden. Host your servers, databases, AI agents, and more on
Railway.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — [Jul'26] Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/zammad-help-desk
