diff --git a/README.md b/README.md index 0d6649c3..ab5638ec 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ - `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). +- 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`). - 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. \ No newline at end of file diff --git a/start.example.sh b/start.example.sh index 16743f42..ad713a81 100644 --- a/start.example.sh +++ b/start.example.sh @@ -3,11 +3,18 @@ set -eu cd /usr/local/indiekit -# Optional: load environment from local .env file. +# Optional: load environment from local .env file +# (dotenv syntax, supports spaces in values). if [ -f .env ]; then - set -a - . ./.env - set +a + eval "$(${NODE_BIN:-/usr/local/bin/node} -e ' + const fs = require("node:fs"); + const dotenv = require("dotenv"); + const parsed = dotenv.parse(fs.readFileSync(".env")); + for (const [key, value] of Object.entries(parsed)) { + const safe = String(value).split("\x27").join("\x27\"\x27\"\x27"); + process.stdout.write(`export ${key}=\x27${safe}\x27\\n`); + } + ')" fi : "${SECRET:?SECRET is required}"