Browse Source

fix(railway): listen on port 3000 and extend healthcheck for deploy

- Dockerfile: ENV PORT=3000 so app matches Railway target port; EXPOSE 3000
- main.ts: prefer process.env.PORT for PaaS (Railway/Heroku)
- railway.toml: healthcheckTimeout 120 -> 180s for migrate+seed startup
- ENV_KEYS.md: document PORT=3000 required on Railway
- .env.production.example: keep OPENROUTER placeholder

Co-authored-by: Cursor <cursoragent@cursor.com>
pull/6386/head
Yash Kuceriya 1 month ago
parent
commit
8914fbac99
  1. 2
      .env.production.example
  2. 4
      Dockerfile
  3. 2
      ENV_KEYS.md
  4. 6
      apps/api/src/main.ts
  5. 3
      railway.toml

2
.env.production.example

@ -21,5 +21,5 @@ NODE_ENV=production
PORT=3000 PORT=3000
# AGENT (OpenRouter) # AGENT (OpenRouter)
OPENROUTER_API_KEY=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 OPENROUTER_API_KEY=<your-openrouter-key-from-openrouter.ai>
OPENROUTER_MODEL=openai/gpt-4o-mini OPENROUTER_MODEL=openai/gpt-4o-mini

4
Dockerfile

@ -52,6 +52,8 @@ RUN npm run database:generate-typings
FROM node:22-slim FROM node:22-slim
LABEL org.opencontainers.image.source="https://github.com/ghostfolio/ghostfolio" LABEL org.opencontainers.image.source="https://github.com/ghostfolio/ghostfolio"
ENV NODE_ENV=production ENV NODE_ENV=production
# Railway and most PaaS route to 3000; app default is 3333. Set here so healthcheck passes even if PORT isn't in Variables.
ENV PORT=3000
RUN apt-get update && apt-get install -y --no-install-suggests \ RUN apt-get update && apt-get install -y --no-install-suggests \
curl \ curl \
@ -61,6 +63,6 @@ RUN apt-get update && apt-get install -y --no-install-suggests \
COPY --chown=node:node --from=builder /ghostfolio/dist/apps /ghostfolio/apps/ COPY --chown=node:node --from=builder /ghostfolio/dist/apps /ghostfolio/apps/
COPY --chown=node:node ./docker/entrypoint.sh /ghostfolio/ COPY --chown=node:node ./docker/entrypoint.sh /ghostfolio/
WORKDIR /ghostfolio/apps/api WORKDIR /ghostfolio/apps/api
EXPOSE ${PORT:-3333} EXPOSE 3000
USER node USER node
CMD [ "/ghostfolio/entrypoint.sh" ] CMD [ "/ghostfolio/entrypoint.sh" ]

2
ENV_KEYS.md

@ -39,7 +39,7 @@ Here, **Postgres and Redis are provided by Railway**; you only generate the two
| **OPENROUTER_API_KEY** | Your key from [openrouter.ai](https://openrouter.ai). | | **OPENROUTER_API_KEY** | Your key from [openrouter.ai](https://openrouter.ai). |
| **OPENROUTER_MODEL** | Your choice; e.g. `openai/gpt-4o-mini`. | | **OPENROUTER_MODEL** | Your choice; e.g. `openai/gpt-4o-mini`. |
| **NODE_ENV** | Set to `production`. | | **NODE_ENV** | Set to `production`. |
| **PORT** | Railway usually sets this (e.g. `3333`); only set if your app expects a specific port. | | **PORT** | **Required on Railway.** Set to `3000` so the app listens on the same port Railway routes to (target port 3000). The app default is 3333, so without this you get "Application failed to respond". |
**Setup:** In your Railway project, open the **Ghostfolio** service (the one from GitHub) → **Variables** → add each variable. For Postgres and Redis, copy from the addon services. For `ACCESS_TOKEN_SALT` and `JWT_SECRET_KEY`, generate once and paste. **Setup:** In your Railway project, open the **Ghostfolio** service (the one from GitHub) → **Variables** → add each variable. For Postgres and Redis, copy from the addon services. For `ACCESS_TOKEN_SALT` and `JWT_SECRET_KEY`, generate once and paste.

6
apps/api/src/main.ts

@ -86,7 +86,11 @@ async function bootstrap() {
} }
const HOST = configService.get<string>('HOST') || DEFAULT_HOST; const HOST = configService.get<string>('HOST') || DEFAULT_HOST;
const PORT = configService.get<number>('PORT') || DEFAULT_PORT; // Prefer process.env.PORT so Railway/Heroku etc. work (they inject PORT; app default is 3333)
const PORT =
Number(process.env.PORT) ||
configService.get<number>('PORT') ||
DEFAULT_PORT;
await app.listen(PORT, HOST, () => { await app.listen(PORT, HOST, () => {
logLogo(); logLogo();

3
railway.toml

@ -3,6 +3,7 @@ dockerfilePath = "Dockerfile"
[deploy] [deploy]
healthcheckPath = "/api/v1/health" healthcheckPath = "/api/v1/health"
healthcheckTimeout = 120 # Migrate + seed run before server start; allow 3 min for first deploy or slow DB
healthcheckTimeout = 180
restartPolicyType = "ON_FAILURE" restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 3 restartPolicyMaxRetries = 3

Loading…
Cancel
Save