Deploy Kan | Open Source Trello Alternative
Open source Trello alternative: kanban boards, Postgres, attachments
Postgres
Just deployed
/var/lib/postgresql/data
Just deployed
Migrate
Just deployed
Attachments
Bucket
Just deployed
Deploy and Host Kan on Railway
Kan is an open-source, Trello-style kanban board — workspaces, boards, lists, cards, labels, comments, checklists and attachments, with a Trello importer built in. This template deploys the whole thing from Kan's own official images: the web app, a one-shot database migrator, Postgres, and managed object storage for attachments.
About Hosting Kan
Three services and a bucket, all from official upstream images:
- Web — the Kan application (Next.js). Dashboard, boards, the REST/tRPC API the UI talks to, and email/password auth. The only service with a domain.
- Migrate — Kan ships its schema migrations as a separate
kan-migrateimage. This service runs them once on each deploy and then stops. The web image is distroless and never migrates on its own, so this is what creates the tables (upstream #402). - Postgres — accounts, workspaces, boards and every card, on a volume. Kan requires Postgres specifically.
- Bucket — Railway object storage for avatars and card attachments, uploaded straight from the browser.
All variables are filled in and described on the deploy screen. There is nothing you have to supply — open the URL, register, and the first account becomes your workspace owner.
Four things this template does that are worth knowing about:
The image is pinned, and here that is a data-safety feature, not a nicety. Both other Kan templates ship ghcr.io/kanbn/kan:latest. Kan's cross-version schema migrations have twice wiped users' workspaces on what looked like a routine image update (upstream #542, #445): the board is simply gone and you are asked to create a new one. A pinned tag (0.6.0) means a redeploy gives you exactly the version you already ran — no surprise upgrade under a live board. When you do want to move up, you bump the tag deliberately and back up first.
Attachments actually upload from the browser. The obvious way to self-host Kan is the one that ships no storage at all, so every avatar and attachment 404s — or bolts on a MinIO container on a volume nobody backs up. Here they go to a managed Railway bucket. Getting that right took one measurement worth repeating: Railway storage answers both S3 URL shapes, but only the host/bucket/key (path-style) form sends CORS headers, and Kan's editor uploads straight from the browser with a presigned PUT. With the other shape every upload is refused in the browser while curl cheerfully reports 200. Verified here by requesting a presigned URL through Kan's own API, uploading to it, and reading the preflight response back.
Migrations run without a broken container. Upstream's compose runs the migrator as a one-shot that exits — but on Railway a container that exits is a crashed container. This template runs Migrate as a proper job (it migrates, then stops clean and green) and points it at Postgres over the private network. The leading template routes its migrations through the public TCP proxy instead, paying egress for every one.
The database is private. No public TCP proxy on Postgres; it is reachable only from this project's private network. The web app connects over postgres.railway.internal.
Common Use Cases
- Team task boards: a self-hosted Trello for sprints, backlogs and pipelines, on a URL you control.
- Moving off Trello: the built-in importer pulls your existing Trello boards in (add a Trello API key).
- Client or project workspaces: separate workspaces per client, each with its own boards and members.
- Anything that cannot live in a vendor's cloud: boards under a policy that rules out a hosted SaaS.
Dependencies for Kan Hosting
Deployment Dependencies
- Kan — the upstream project and its official
kan/kan-migrateimages - Postgres for accounts, workspaces and board data
- An S3-compatible bucket for avatars and attachments
Implementation Details
- The first person to register owns the workspace. Kan signs in with email and password out of the box. Register first, then set
NEXT_PUBLIC_DISABLE_SIGN_UP=trueso nobody else can create an account on your instance. - Migrations are a separate service. Migrate applies pending migrations on each deploy and then stops — a stopped Migrate service is finished, not broken. After you bump the Kan image to a newer version, redeploy Migrate to run that version's migrations.
- Email is optional. Invites and notifications need SMTP; leave the
SMTP_*andEMAIL_FROMfields empty and Kan runs without them. SetNEXT_PUBLIC_DISABLE_EMAIL=trueto hide email-based features entirely. - Google sign-in and Trello import are opt-in.
GOOGLE_CLIENT_ID/SECRETadd Sign in with Google;TRELLO_APP_API_KEY/SECRETpower the board importer. All four are on the deploy screen, empty, and nothing breaks without them. - Rate limiting is in-memory. Kan uses Redis for distributed rate limiting when
REDIS_URLis set and falls back to an in-memory limiter otherwise — which is the right choice for a single-instance deployment. Add a Redis service and pointREDIS_URLat it only if you scale the web service to multiple replicas.
Resource Usage and Cost
Kan is a light stack: a Next.js web app and a Postgres database. Measured on an idle deployment it sits at a few hundred megabytes of RAM across the services, with a short spike on the first deploy while migrations run. Add the volume Postgres is given and whatever the bucket holds.
That puts a quiet instance at roughly $5–15/month — a cost that tracks how much you store and how busy the boards are, not merely uptime. A team's worth of boards and attachments is a small bill; it grows with the number of cards and the size of what you attach to them.
Why Deploy Kan on Railway?
Kan needs three things that are annoying to assemble by hand: somewhere to run the app, a Postgres database, and object storage the browser can upload attachments to directly over HTTPS. Railway supplies the storage as a managed bucket rather than a container you have to back up, keeps the database on a private network with no public exposure, and hands out the domain and certificate before the first deploy finishes. The migration step — the one that has cost other self-hosters their boards — is wired up here so it runs once, in order, and stops.
Template Content
Postgres
postgres:18.4-alpineAttachments
Bucket
