diff --git a/.env.production.example b/.env.production.example index 691fbf4c2..1968bfdaa 100644 --- a/.env.production.example +++ b/.env.production.example @@ -21,5 +21,5 @@ NODE_ENV=production PORT=3000 # AGENT (OpenRouter) -OPENROUTER_API_KEY=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 +OPENROUTER_API_KEY= OPENROUTER_MODEL=openai/gpt-4o-mini diff --git a/Dockerfile b/Dockerfile index e73cd73e6..c9c15c957 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,6 +52,8 @@ RUN npm run database:generate-typings FROM node:22-slim LABEL org.opencontainers.image.source="https://github.com/ghostfolio/ghostfolio" 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 \ 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 ./docker/entrypoint.sh /ghostfolio/ WORKDIR /ghostfolio/apps/api -EXPOSE ${PORT:-3333} +EXPOSE 3000 USER node CMD [ "/ghostfolio/entrypoint.sh" ] diff --git a/ENV_KEYS.md b/ENV_KEYS.md index 3744edf1b..fbc0d1cef 100644 --- a/ENV_KEYS.md +++ b/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_MODEL** | Your choice; e.g. `openai/gpt-4o-mini`. | | **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. diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index a8de3dc5e..01e82f58c 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -86,7 +86,11 @@ async function bootstrap() { } const HOST = configService.get('HOST') || DEFAULT_HOST; - const PORT = configService.get('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('PORT') || + DEFAULT_PORT; await app.listen(PORT, HOST, () => { logLogo(); diff --git a/railway.toml b/railway.toml index 8473d43d6..df3178eb7 100644 --- a/railway.toml +++ b/railway.toml @@ -3,6 +3,7 @@ dockerfilePath = "Dockerfile" [deploy] 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" restartPolicyMaxRetries = 3