convex env set fails to handle multi-line environment variable values
The convex env set command fails when trying to set environment variables that contain multi-line values, such as PEM-formatted private keys. This is particularly problematic for JWT authentication setups where JWT_PRIVATE_KEY needs to be a multi-line PEM-formatted RSA private key.
Steps to Reproduce
- Generate a standard PEM-formatted private key:
openssl genrsa -out private.key 2048
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private.key -out private.pem
- Try to set it as an environment variable:
convex env set JWT_PRIVATE_KEY "$(cat private.pem)" --admin-key <admin-key> --url <convex-url>
Expected Behavior
The multi-line PEM key should be stored correctly as an environment variable.
Actual Behavior
The command fails with various errors depending on the attempt:
- Direct attempt: Command hangs or fails
- With escaped newlines (
\n): May appear to succeed but the value is stored incorrectly - Via stdin redirect: Also fails
Environment
- Convex CLI version: [latest]
- OS: Linux/macOS
- Context: Self-hosted Convex backend
Impact
This blocks automated setup of JWT authentication in CI/CD pipelines for self-hosted Convex deployments (which i use for spinning up test envs). Manual intervention through the dashboard is required, which breaks automation workflows.
Workarounds Attempted
- Replacing newlines with
\n- stores literal\ninstead of actual newlines - Single line with spaces - breaks PEM format
- Base64 encoding - requires application code changes to decode
- Using stdin - still fails
- Using heredoc - still fails
Suggested Fix
The CLI should properly handle multi-line values, perhaps by:
- Supporting a
--from-fileflag:convex env set JWT_PRIVATE_KEY --from-file private.pem - Properly parsing multi-line strings from command arguments
- Supporting stdin input:
cat private.pem | convex env set JWT_PRIVATE_KEY --from-stdin
Related
This issue is mentioned in the Convex auth setup documentation: https://labs.convex.dev/auth/setup/manual
--from-file sounds great. Would take a PR that supports it.
Otherwise, we'll keep it on our list of feature ideas and get to it when we get a chance.
Sounds good. I'll try and take a stab at this at some point
I also encountered this.
my current automation uses sed to clean things up for this situation. something along these lines:
generateKeys.mjs:
import { exportJWK, exportPKCS8, generateKeyPair } from "jose";
const keys = await generateKeyPair("RS256");
const privateKey = await exportPKCS8(keys.privateKey);
const publicKey = await exportJWK(keys.publicKey);
const jwks = JSON.stringify({ keys: [{ use: "sig", ...publicKey }] });
process.stdout.write(
`JWT_PRIVATE_KEY="${privateKey.trimEnd().replace(/\n/g, " ")}"`,
);
process.stdout.write("\n");
process.stdout.write(`JWKS=${jwks}`);
process.stdout.write("\n");
#!/bin/bash
output=$(node generateKeys.mjs)
JWT_PRIVATE_KEY=$(echo "$output" | sed -n 's/^JWT_PRIVATE_KEY="\([^"]*\)"/\1/p')
JWKS=$(echo "$output" | sed -n 's/^JWKS=\(.*\)/\1/p')
ENV_CMD="npx convex env set"
# configure other env vars here as such
# $ENV_CMD -- MAX_USERS 1 >/dev/null
# auth will fail if these are not set
if ! $ENV_CMD -- JWT_PRIVATE_KEY "$JWT_PRIVATE_KEY" >/dev/null; then
echo "Failed to set JWT_PRIVATE_KEY"
fi
if ! $ENV_CMD -- JWKS "$JWKS" >/dev/null; then
echo "Failed to set JWKS"
fi
--from-filesounds great. Would take a PR that supports it.Otherwise, we'll keep it on our list of feature ideas and get to it when we get a chance.
any updates here? @nipunn1313
it's not currently prioritized. @alvin-r - would you like to take a shot at it?