Deploy It's a Plan (Single Host)
Linear and Plane alternative with AI agents, no custom domain needed
Just deployed
proxy
Just deployed
Just deployed
Just deployed
Just deployed
Just deployed
attachments
Bucket
Just deployed
Deploy and Host It's a Plan on Railway
It's a Plan is an open-source project tracker in the spirit of Linear and Plane: issues, boards, cycles, initiatives, docs and dashboards, with AI agents that pick up work, chat about it and report back. This template runs the whole stack on the free Railway domain the moment it deploys. No custom domain, no DNS and no variables to fill in.
About Hosting It's a Plan
It's a Plan ships as four images (api, web, worker, Telegram bot) plus Postgres and S3-compatible storage for attachments. The browser needs the web app and the API on one site so the login cookie works. Railway's *.up.railway.app domains are on the Public Suffix List, so a web and an API on two separate Railway subdomains cannot share a session, and sign-in bounces back to the login page.
This template solves that with a small Caddy proxy in front. It serves the web app at / and the API at /api on a single host, which is the "API on a path" mode the It's a Plan docs describe. The session cookie stays host-only (__Host- prefixed) and everything works on the generated domain.
Common Use Cases
- Issue tracking and sprint planning (cycles) for a product or engineering team
- A self-hosted Linear or Plane replacement that keeps your data in your own Postgres
- Letting AI agents triage, plan and work issues next to people, through the built-in agents and the MCP server
- Project docs, notes and dashboards in the same place as the work
Dependencies for It's a Plan Hosting
- Postgres 18 (Railway's SSL image, with a volume)
- A Railway storage bucket for attachments
- The official
ghcr.io/croffasia/itsaplan-*images - Caddy 2 (official image) as the single-host proxy
Deployment Dependencies
- Source: https://github.com/croffasia/itsaplan
- Self-hosting docs: https://github.com/croffasia/itsaplan/blob/main/docs/self-hosting.md
- Website: https://itsaplan.dev
Implementation Details
Services
| Service | Role |
|---|---|
| proxy | Public entry point. /api/* goes to api (prefix removed), OAuth discovery documents go to api, everything else goes to web |
| web | Next.js frontend, private |
| api | Elysia API on Bun, private. Runs database migrations on every start |
| worker | Webhooks, notifications, agent schedules and imports |
| bot | Telegram bot (long polling). Keep it at one replica |
| postgres | Database, with a volume |
| attachments | Railway bucket for uploaded files |
First run
Open the proxy's URL and click Sign up. The first account becomes the instance admin and gets God mode. There are no default credentials. After that, create a team and a project.
Lock it down once your team has joined: God mode → Authentication → Registration controls open sign-up and invite lifetime.
Configured in the app, not with variables
SMTP or Resend email, AI provider keys, Google sign-in and the Telegram bot token are set in God mode after you sign in. Provider keys are stored encrypted with APP_ENCRYPTION_KEY.
Secrets
BETTER_AUTH_SECRET, APP_ENCRYPTION_KEY, WORKER_INTERNAL_TOKEN and the database password are generated for every deploy. Do not change APP_ENCRYPTION_KEY later, or stored provider keys can no longer be decrypted.
Using your own domain
- Add the custom domain to the proxy service (Settings → Networking, port 8080).
- On the web service, set
APP_URL=https://plan.example.comandAPI_URL=https://plan.example.com/api. The api reads both from web. - Redeploy web and api.
Updates
The app images track latest, the newest release, with auto updates on between 02:00 and 06:00 UTC. The api applies migrations when it starts. Turn this off or pin a version per service under Settings → Source.
Troubleshooting
- Sign-in returns to the login page:
APP_URLandAPI_URLon web must be the same host as the one in your browser, with/apion the end ofAPI_URL. Redeploy web and api after changing them. - 502 from the proxy straight after the deploy: web or api is still starting. Wait a minute.
- An attachment uploads but will not open, and web logs show
ERR_INVALID_URL ... http://:3000: redeploy the web service soSERVICE_URL_APIpicks up the api's private address.
Scaling
api, web and worker are stateless. bot must stay at one replica, because Telegram hands each update to only one caller.
Why Deploy It's a Plan 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 It's a Plan 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.
Template Content
