fix(backend): harden endpoint and startup config
This commit is contained in:
@@ -9,6 +9,16 @@
|
||||
- Post management UI should use `/posts` (`@indiekit/endpoint-posts.mountPath`).
|
||||
- Do not set post-management `mountPath` to frontend routes like `/blog`, otherwise backend publishing can be shadowed by the public site.
|
||||
|
||||
## Backend endpoints
|
||||
|
||||
- Configured endpoint mount paths:
|
||||
- Posts management: `/posts`
|
||||
- Files: `/files`
|
||||
- Webmentions moderation + API: `/webmentions`
|
||||
- Conversations + API: `/conversations`
|
||||
- GitHub activity + API: `/github`
|
||||
- If IndieKit is reverse-proxied behind `/admin`, these become `/admin/posts`, `/admin/files`, etc.
|
||||
|
||||
## MongoDB
|
||||
|
||||
- Preferred: set a full `MONGO_URL` (example: `mongodb://user:pass@host:27017/indiekit?authSource=admin`).
|
||||
@@ -46,4 +56,9 @@
|
||||
- `GH_CONTENT_TOKEN`: token for content repo (`blog`), used by `@indiekit/store-github`.
|
||||
- `GH_ACTIVITY_TOKEN`: token for GitHub dashboard/activity endpoint, used by `@rmdes/indiekit-endpoint-github`.
|
||||
- `GITHUB_USERNAME`: GitHub user/owner name.
|
||||
- Backward compatibility: if `GH_CONTENT_TOKEN` or `GH_ACTIVITY_TOKEN` are not set, config falls back to `GITHUB_TOKEN`.
|
||||
- Backward compatibility: if `GH_CONTENT_TOKEN` or `GH_ACTIVITY_TOKEN` are not set, config falls back to `GITHUB_TOKEN`.
|
||||
|
||||
## Startup script
|
||||
|
||||
- `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).
|
||||
+15
-2
@@ -1,2 +1,15 @@
|
||||
require('dotenv').config();
|
||||
require('indiekit').serve();
|
||||
require("dotenv/config");
|
||||
const { spawn } = require("child_process");
|
||||
|
||||
const args = [
|
||||
require.resolve("@indiekit/indiekit/bin/cli.js"),
|
||||
"serve",
|
||||
"--config",
|
||||
"indiekit.config.mjs",
|
||||
];
|
||||
|
||||
const child = spawn(process.execPath, args, { stdio: "inherit" });
|
||||
|
||||
child.on("exit", (code) => {
|
||||
process.exit(code ?? 1);
|
||||
});
|
||||
|
||||
+21
-8
@@ -27,6 +27,18 @@ const githubContentToken =
|
||||
process.env.GH_CONTENT_TOKEN || process.env.GITHUB_TOKEN;
|
||||
const githubActivityToken =
|
||||
process.env.GH_ACTIVITY_TOKEN || process.env.GITHUB_TOKEN;
|
||||
const publicationBaseUrl = (
|
||||
process.env.PUBLICATION_URL || "https://blog.giersig.eu"
|
||||
).replace(/\/+$/, "");
|
||||
|
||||
let webmentionDomain = process.env.WEBMENTION_IO_DOMAIN;
|
||||
if (!webmentionDomain) {
|
||||
try {
|
||||
webmentionDomain = new URL(publicationBaseUrl).hostname;
|
||||
} catch {
|
||||
webmentionDomain = "blog.giersig.eu";
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
debug: "indiekit:*",
|
||||
@@ -35,55 +47,55 @@ export default {
|
||||
mongodbUrl: mongoUrl,
|
||||
},
|
||||
publication: {
|
||||
me: "https://blog.giersig.eu",
|
||||
me: publicationBaseUrl,
|
||||
postTypes: {
|
||||
article: {
|
||||
name: "Artikel",
|
||||
post: {
|
||||
path: "content/articles/{slug}.md",
|
||||
url: "https://blog.giersig.eu/articles/{slug}/",
|
||||
url: `${publicationBaseUrl}/articles/{slug}/`,
|
||||
},
|
||||
},
|
||||
note: {
|
||||
name: "Notiz",
|
||||
post: {
|
||||
path: "content/notes/{slug}.md",
|
||||
url: "https://blog.giersig.eu/notes/{slug}/",
|
||||
url: `${publicationBaseUrl}/notes/{slug}/`,
|
||||
},
|
||||
},
|
||||
bookmark: {
|
||||
name: "Lesezeichen",
|
||||
post: {
|
||||
path: "content/bookmarks/{slug}.md",
|
||||
url: "https://blog.giersig.eu/bookmarks/{slug}/",
|
||||
url: `${publicationBaseUrl}/bookmarks/{slug}/`,
|
||||
},
|
||||
},
|
||||
like: {
|
||||
name: "Like",
|
||||
post: {
|
||||
path: "content/likes/{slug}.md",
|
||||
url: "https://blog.giersig.eu/likes/{slug}/",
|
||||
url: `${publicationBaseUrl}/likes/{slug}/`,
|
||||
},
|
||||
},
|
||||
photo: {
|
||||
name: "Foto",
|
||||
post: {
|
||||
path: "content/photos/{slug}.md",
|
||||
url: "https://blog.giersig.eu/photos/{slug}/",
|
||||
url: `${publicationBaseUrl}/photos/{slug}/`,
|
||||
},
|
||||
},
|
||||
reply: {
|
||||
name: "Antwort",
|
||||
post: {
|
||||
path: "content/replies/{slug}.md",
|
||||
url: "https://blog.giersig.eu/replies/{slug}/",
|
||||
url: `${publicationBaseUrl}/replies/{slug}/`,
|
||||
},
|
||||
},
|
||||
page: {
|
||||
name: "Seite",
|
||||
post: {
|
||||
path: "content/pages/{slug}.md",
|
||||
url: "https://blog.giersig.eu/{slug}/",
|
||||
url: `${publicationBaseUrl}/{slug}/`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -113,6 +125,7 @@ export default {
|
||||
},
|
||||
"@rmdes/indiekit-endpoint-webmention-io": {
|
||||
token: process.env.WEBMENTION_IO_TOKEN,
|
||||
domain: webmentionDomain,
|
||||
},
|
||||
"@rmdes/indiekit-endpoint-conversations": {
|
||||
mountPath: "/conversations",
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
cd /usr/local/indiekit
|
||||
|
||||
# Optional: load environment from local .env file.
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
. ./.env
|
||||
set +a
|
||||
fi
|
||||
|
||||
: "${SECRET:?SECRET is required}"
|
||||
: "${PASSWORD_SECRET:?PASSWORD_SECRET is required}"
|
||||
|
||||
# Allow either full Mongo URL or decomposed credentials.
|
||||
if [ -z "${MONGO_URL:-}" ]; then
|
||||
: "${MONGO_PASSWORD:?MONGO_PASSWORD is required when MONGO_URL is not set}"
|
||||
export MONGO_USERNAME="${MONGO_USERNAME:-indiekit}"
|
||||
export MONGO_AUTH_SOURCE="${MONGO_AUTH_SOURCE:-admin}"
|
||||
fi
|
||||
|
||||
if [ -z "${GH_CONTENT_TOKEN:-}" ] && [ -z "${GITHUB_TOKEN:-}" ]; then
|
||||
echo "GH_CONTENT_TOKEN or GITHUB_TOKEN is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export NODE_ENV="${NODE_ENV:-production}"
|
||||
|
||||
exec /usr/local/bin/node node_modules/@indiekit/indiekit/bin/cli.js serve --config indiekit.config.mjs
|
||||
Reference in New Issue
Block a user