diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 8fe181ad..05f2ac6a 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -916,6 +916,16 @@ export ENCRYPTION_KEY="your-64-character-hex-key" **Key rotation:** To rotate the encryption key, use the built-in rekey utility: ```bash +# Docker (no source code required): +docker exec -e ENCRYPTION_KEY="old-key" -e NEW_ENCRYPTION_KEY="new-key" plexus ./plexus rekey + +# Docker Compose: +docker compose exec -e ENCRYPTION_KEY="old-key" -e NEW_ENCRYPTION_KEY="new-key" plexus ./plexus rekey + +# Binary install: +ENCRYPTION_KEY="old-key" NEW_ENCRYPTION_KEY="new-key" ./plexus rekey + +# From source: ENCRYPTION_KEY="old-key" NEW_ENCRYPTION_KEY="new-key" bun run rekey ``` diff --git a/packages/backend/src/cli/rekey.ts b/packages/backend/src/cli/rekey.ts index de6b8a42..ca716673 100644 --- a/packages/backend/src/cli/rekey.ts +++ b/packages/backend/src/cli/rekey.ts @@ -196,7 +196,12 @@ async function main() { ); } -main().catch((err) => { - logger.error('Re-key failed:', err); - process.exit(1); -}); +export { main as rekeyMain }; + +// Allow direct execution: bun run src/cli/rekey.ts +if (import.meta.main) { + main().catch((err) => { + logger.error('Re-key failed:', err); + process.exit(1); + }); +} diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index f29e9864..76bf952b 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -1,3 +1,19 @@ +// --- CLI Subcommand Routing --- +// Check for subcommands (e.g. `./plexus rekey`) before starting the server. +// This allows Docker users to run CLI tools without needing the source code. +const subcommand = process.argv[2]; +if (subcommand === 'rekey') { + const { rekeyMain } = await import('./cli/rekey'); + rekeyMain() + .then(() => process.exit(0)) + .catch((err) => { + console.error('Re-key failed:', err); + process.exit(1); + }); + // Prevent the rest of the server from initializing + await new Promise(() => {}); // Block forever; process.exit above will terminate +} + import Fastify, { FastifyReply, FastifyRequest } from 'fastify'; import cors from '@fastify/cors'; import multipart from '@fastify/multipart';