---
title: "Deploy Peppermint | (Just Updated) Helpdesk and Ticketing System, Zendesk Alternative, Admin Preset"
description: "Peppermint helpdesk and ticketing system on PostgreSQL, admin preset"
category: "Other"
url: https://railway.com/deploy/peppermint-or-just-updated-helpdesk-and-
---

# Deploy Peppermint | (Just Updated) Helpdesk and Ticketing System, Zendesk Alternative, Admin Preset

Peppermint helpdesk and ticketing system on PostgreSQL, admin preset

**[Deploy Peppermint | (Just Updated) Helpdesk and Ticketing System, Zendesk Alternative, Admin Preset on Railway](https://railway.com/template/peppermint-or-just-updated-helpdesk-and-)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/peppermint-or-just-updated-helpdesk-and-/manifest.json

- **Creator:** SuperSlowSloth
- **Category:** Other

## Template content

### postgres

- **Image:** postgres:17.10-alpine

### peppermint

- **Image:** ghcr.io/bon5co/peppermint-railway:0.5.5@sha256:bc650c52650aa66f21355c6e075421cefaef7408fe69fcebcae2c3c3efff753d
- **Health check:** /
- **Public domain:** Yes

## Documentation

# Deploy and Host Peppermint on Railway

**Built for an LLM agent to deploy and use.** The deploy form has no fields to fill: the admin login, the session signing key and the database password are generated at deploy time, PostgreSQL stores the tickets on a volume, and upstream's default `admin@admin.com` / `1234` login does not exist on this deploy. Peppermint is an open-source, self-hosted helpdesk and ticket management system, a Zendesk alternative: collect support requests, assign engineers, track status and keep a client list.

## About Hosting Peppermint

This template runs two services: **peppermint** (the web app and its API on one public domain, with a volume at `/apps/api/uploads` for ticket attachments) and **postgres** (PostgreSQL 17 with a volume mounted at `/var/lib/postgresql`). Tickets, users, clients and settings live in PostgreSQL, so they survive redeploys of either service.

**Ready from boot.** Upstream seeds an administrator with the email `admin@admin.com` and the password `1234`, so a stock public deploy is an open admin console. This template runs the migrations and the seed before the app listens and then renames that account to the generated `ADMIN_EMAIL` with the generated `ADMIN_PASSWORD`, so the default login is never reachable. `SECRET` signs every session token and is generated per deploy instead of upstream's example value. The telemetry call to PostHog is removed.

**Using it.** Sign in at `/api/v1/auth/login` for a token, send it as a Bearer header, and create tickets with `POST /api/v1/ticket/create`. Staff sign in to the web interface at the public URL with the same email and password. The public submit form posts to `/api/v1/ticket/public/create`, which accepts tickets with no credential by design, so anyone with the URL can file a ticket. Email notifications and inbound mail need an SMTP or IMAP server, configured in the admin settings after deploy. The upstream repository is archived and read-only; this template pins its last published image.

### Agent contract

- Public URL: `https://RAILWAY_PUBLIC_DOMAIN` (the generated domain of the `peppermint` service)
- Private URL: `http://peppermint.railway.internal:8080`
- Credentials: the variables `ADMIN_EMAIL` and `ADMIN_PASSWORD` on the `peppermint` service
- Auth: `POST /api/v1/auth/login` with a JSON body `{"email","password"}` returns `{"token"}`; send it as `Authorization: Bearer $TOKEN`. A write without a token or with a wrong token answers `401`. `POST /api/v1/ticket/public/create` is the public submit form and takes no credential.
- Health: `GET /` returns 200

```bash
#!/bin/sh
# needs: RAILWAY_PUBLIC_DOMAIN, ADMIN_EMAIL, ADMIN_PASSWORD (variables of the peppermint service); also curl
B="https://$RAILWAY_PUBLIC_DOMAIN"
J="Content-Type: application/json"
curl -s -o /dev/null -w "health: %{http_code}\n" "$B/"
TOKEN=$(curl -s -X POST -H "$J" -d "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASSWORD\"}" "$B/api/v1/auth/login" | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
if [ -n "$TOKEN" ]; then echo "login: ok"; else echo "login: FAILED"; fi
T='{"name":"agent","title":"contract check","detail":"created by the Agent contract snippet","email":"agent@example.com","priority":"low","type":"support"}'
curl -s -o /dev/null -w "write with token: %{http_code}\n" -X POST -H "$J" -H "Authorization: Bearer $TOKEN" -d "$T" "$B/api/v1/ticket/create"
curl -s -o /dev/null -w "write without key: %{http_code}\n" -X POST -H "$J" -d "$T" "$B/api/v1/ticket/create"
curl -s -o /dev/null -w "write with wrong key: %{http_code}\n" -X POST -H "$J" -H "Authorization: Bearer ${TOKEN}x" -d "$T" "$B/api/v1/ticket/create"
curl -s -o /dev/null -w "read without key: %{http_code}\n" "$B/api/v1/tickets/open"
curl -s -o /dev/null -w "read with token: %{http_code}\n" -H "Authorization: Bearer $TOKEN" "$B/api/v1/tickets/open"
curl -s -o /dev/null -w "default admin login: %{http_code}\n" -X POST -H "$J" -d '{"email":"admin@admin.com","password":"1234"}' "$B/api/v1/auth/login"
```

A fresh deploy prints `health: 200`, `login: ok`, `write with token: 200`, `write without key: 401`, `write with wrong key: 401`, `read without key: 401`, `read with token: 200` and `default admin login: 401`.

## Why Deploy Peppermint 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 Peppermint 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.

- **Agent-ready** - no deployer fields, a contract block and one script that proves login, a create, the refusal of a write without a token and the dead default login.
- **No default credentials** - the stock `admin@admin.com` / `1234` account is replaced before the app listens.
- **Data survives redeploys** - tickets sit in PostgreSQL on a volume and attachments on a second volume.
- **Pinned** - the upstream image and the PostgreSQL image are pinned by digest or exact tag.
- **No per-agent pricing** - unlimited agents, tickets and clients on your own domain.

## Common Use Cases

- **Internal IT helpdesk** - staff file requests and engineers work the queue.
- **Customer support tickets** - a public submit form feeding one shared inbox.
- **Zendesk alternative for a small team** - ticket assignment, status and client records without per-seat fees.
- **Agent-driven support automation** - create and update tickets from scripts or an LLM agent over the REST API.

## Dependencies for Peppermint Hosting

- The peppermint service and a PostgreSQL service with a volume, both created by the template. A custom domain and an SMTP server are optional.

### Deployment Dependencies

- [Peppermint repository](https://github.com/Peppermint-Lab/peppermint)
- [Official Docker image](https://hub.docker.com/r/pepperlabs/peppermint)
- [Wrapper image source](https://github.com/bon5co/peppermint-railway)


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — 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/peppermint-or-just-updated-helpdesk-and-
