fix(startup): add strict mongo preflight in production
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
- Preferred: set a full `MONGO_URL` (example: `mongodb://user:pass@host:27017/indiekit?authSource=admin`).
|
- Preferred: set a full `MONGO_URL` (example: `mongodb://user:pass@host:27017/indiekit?authSource=admin`).
|
||||||
- If `MONGO_URL` is not set, set `MONGO_USERNAME` and `MONGO_PASSWORD` explicitly; config builds the URL from `MONGO_USERNAME`, `MONGO_PASSWORD`, `MONGO_HOST`, `MONGO_PORT`, `MONGO_DATABASE`, `MONGO_AUTH_SOURCE`.
|
- If `MONGO_URL` is not set, set `MONGO_USERNAME` and `MONGO_PASSWORD` explicitly; config builds the URL from `MONGO_USERNAME`, `MONGO_PASSWORD`, `MONGO_HOST`, `MONGO_PORT`, `MONGO_DATABASE`, `MONGO_AUTH_SOURCE`.
|
||||||
- Startup scripts now fail fast when `MONGO_URL` is absent and `MONGO_USERNAME` is missing, to avoid silent auth mismatches.
|
- Startup scripts now fail fast when `MONGO_URL` is absent and `MONGO_USERNAME` is missing, to avoid silent auth mismatches.
|
||||||
|
- Startup now runs `scripts/preflight-mongo-connection.mjs` before boot. In `NODE_ENV=production` this is strict and aborts start on Mongo auth/connect failures.
|
||||||
- For `MongoServerError: Authentication failed`, first verify `MONGO_PASSWORD`, then try `MONGO_AUTH_SOURCE=admin`.
|
- For `MongoServerError: Authentication failed`, first verify `MONGO_PASSWORD`, then try `MONGO_AUTH_SOURCE=admin`.
|
||||||
|
|
||||||
## Content paths
|
## Content paths
|
||||||
@@ -65,7 +66,7 @@
|
|||||||
- `start.sh` is intentionally ignored by Git (`.gitignore`) so server secrets are not committed.
|
- `start.sh` is intentionally ignored by Git (`.gitignore`) so server secrets are not committed.
|
||||||
- Use `start.example.sh` as the tracked template and keep real credentials in environment variables (or `.env` on the server).
|
- Use `start.example.sh` as the tracked template and keep real credentials in environment variables (or `.env` on the server).
|
||||||
- Startup scripts parse `.env` with the `dotenv` parser (not shell `source`), so values containing spaces are handled safely.
|
- Startup scripts parse `.env` with the `dotenv` parser (not shell `source`), so values containing spaces are handled safely.
|
||||||
- Startup scripts run patch helpers before boot (`scripts/patch-lightningcss.mjs`, `scripts/patch-endpoint-media-scope.mjs`, `scripts/patch-endpoint-files-upload-route.mjs`, `scripts/patch-frontend-serviceworker-file.mjs`, `scripts/patch-conversations-collection-guards.mjs`).
|
- Startup scripts run preflight + patch helpers before boot (`scripts/preflight-mongo-connection.mjs`, `scripts/patch-lightningcss.mjs`, `scripts/patch-endpoint-media-scope.mjs`, `scripts/patch-endpoint-files-upload-route.mjs`, `scripts/patch-frontend-serviceworker-file.mjs`, `scripts/patch-conversations-collection-guards.mjs`).
|
||||||
- The media scope patch fixes a known upstream issue where file uploads can fail if the token scope is `create update delete` without explicit `media`.
|
- The media scope patch fixes a known upstream issue where file uploads can fail if the token scope is `create update delete` without explicit `media`.
|
||||||
- The files upload route patch fixes browser multi-upload by posting to `/files/upload` (session-authenticated) instead of direct `/media` calls without bearer token.
|
- The files upload route patch fixes browser multi-upload by posting to `/files/upload` (session-authenticated) instead of direct `/media` calls without bearer token.
|
||||||
- The frontend serviceworker patch ensures `@indiekit/frontend/lib/serviceworker.js` exists at runtime to avoid ENOENT in the offline/service worker route.
|
- The frontend serviceworker patch ensures `@indiekit/frontend/lib/serviceworker.js` exists at runtime to avoid ENOENT in the offline/service worker route.
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-conversations-collection-guards.mjs",
|
"postinstall": "node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-conversations-collection-guards.mjs",
|
||||||
"serve": "node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-conversations-collection-guards.mjs && node node_modules/@indiekit/indiekit/bin/cli.js serve --config indiekit.config.mjs",
|
"serve": "node scripts/preflight-mongo-connection.mjs && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-conversations-collection-guards.mjs && node node_modules/@indiekit/indiekit/bin/cli.js serve --config indiekit.config.mjs",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import { MongoClient } from "mongodb";
|
||||||
|
|
||||||
|
import config from "../indiekit.config.mjs";
|
||||||
|
|
||||||
|
const strictMode =
|
||||||
|
process.env.REQUIRE_MONGO === "1" ||
|
||||||
|
(process.env.REQUIRE_MONGO !== "0" && process.env.NODE_ENV === "production");
|
||||||
|
|
||||||
|
const hasMongoUrl = Boolean(process.env.MONGO_URL);
|
||||||
|
const mongoUser = process.env.MONGO_USERNAME || process.env.MONGO_USER || "";
|
||||||
|
const hasMongoPassword = Boolean(process.env.MONGO_PASSWORD);
|
||||||
|
|
||||||
|
if (!hasMongoUrl && (!mongoUser || !hasMongoPassword)) {
|
||||||
|
const message =
|
||||||
|
"[preflight] Missing Mongo credentials: set MONGO_URL or MONGO_USERNAME + MONGO_PASSWORD.";
|
||||||
|
|
||||||
|
if (strictMode) {
|
||||||
|
console.error(message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(`${message} Continuing because strict mode is disabled.`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mongodbUrl = config.application?.mongodbUrl;
|
||||||
|
|
||||||
|
if (!mongodbUrl) {
|
||||||
|
const message = "[preflight] MongoDB URL could not be resolved from configuration.";
|
||||||
|
|
||||||
|
if (strictMode) {
|
||||||
|
console.error(message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(`${message} Continuing because strict mode is disabled.`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new MongoClient(mongodbUrl, { connectTimeoutMS: 5000 });
|
||||||
|
|
||||||
|
try {
|
||||||
|
await client.connect();
|
||||||
|
await client.db().command({ ping: 1 });
|
||||||
|
console.log("[preflight] MongoDB connection OK");
|
||||||
|
} catch (error) {
|
||||||
|
const message = `[preflight] MongoDB connection failed: ${error.message}`;
|
||||||
|
|
||||||
|
if (strictMode) {
|
||||||
|
console.error(message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(`${message} Continuing because strict mode is disabled.`);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
await client.close();
|
||||||
|
} catch {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,9 @@ fi
|
|||||||
|
|
||||||
export NODE_ENV="${NODE_ENV:-production}"
|
export NODE_ENV="${NODE_ENV:-production}"
|
||||||
|
|
||||||
|
# Verify MongoDB credentials/connectivity before launching server.
|
||||||
|
/usr/local/bin/node scripts/preflight-mongo-connection.mjs
|
||||||
|
|
||||||
# Ensure runtime dependency patches are applied even if node_modules already exists.
|
# Ensure runtime dependency patches are applied even if node_modules already exists.
|
||||||
/usr/local/bin/node scripts/patch-lightningcss.mjs
|
/usr/local/bin/node scripts/patch-lightningcss.mjs
|
||||||
/usr/local/bin/node scripts/patch-endpoint-media-scope.mjs
|
/usr/local/bin/node scripts/patch-endpoint-media-scope.mjs
|
||||||
|
|||||||
Reference in New Issue
Block a user