Security & Keys
Security in this boilerplate is treated as a first-class citizen. Rather than relying heavily on external services for basic security needs, we provide a robust set of built-in cryptographic functions (crypto.ts) and an automated key generation process (bun gen:keys).
This ensures you have complete control over your identity management, token signing, and data encryption.
The Key Generation Process
Before running the application in a production-like environment (especially if you are using the Identity or SSO domains), you need a secure set of cryptographic keys.
We use the command bun gen:keys to automate this setup.
bun gen:keysWhat happens when you run this command?
- RSA Pair Generation: It generates a 2048-bit RSA Public/Private key pair (
private.pem,public.pem), essential for signing and validating JWTs asymmetrically. - Self-Signed SSL: It automatically calls
opensslto generate a self-signedcert.pemfor local HTTPS/HTTP2 development. - JWKS Generation: It converts the new public key into a JSON Web Key (JWK) and exports a
jwks.jsonfile. This format is the industry standard for distributing public keys so clients (or other microservices) can verify your tokens. - OIDC Metadata: It generates the
openid-configuration.jsonnecessary to make your server act as an OpenID Connect identity provider.
The Security Flow
Here is how the keys are utilized across the architecture:
Cryptographic Utilities (crypto.ts)
The src/infrastructure/pipes/crypto.ts file abstracts Node's native node:crypto module to provide easy-to-use, secure functions.
Password Hashing
For user passwords, we leverage Bun's native Bun.password API (usually implemented inside the Identity domain actions, rather than the crypto.ts pipe directly). It automatically handles salt generation and secure hashing (e.g., bcrypt or argon2) without needing external npm packages.
Available Crypto Functions
The crypto.ts pipe provides the following utilities:
uuid(): Generates a standard random UUID.sha256(data): Quickly hashes data. Useful for creating identifiers or data integrity checks.base64url(input): Encodes data securely for use in URLs (removes+,/, and=).generateRSAKeyPair(): The core function used by the CLI to create the PEM files.pemToJWK(pem): Converts a public PEM file into a standard JWK object.rsa(data, privateKey): Signs a string of data using RSA-SHA256. Used internally to sign custom tokens.rsaVerify(data, signature, publicKey): Verifies that a specific piece of data was signed by the matching private key.
Managing Keys in Production
WARNING
The keys generated by bun gen:keys are placed in the ./keys folder by default and are ignored by Git (.gitignore). Do NOT commit your private.pem to version control!
In a production environment (e.g., Docker/Kubernetes):
- You should generate the keys securely offline or via a secure pipeline.
- Inject the keys into your container via Secrets (e.g., Docker Secrets, AWS Secrets Manager, or Kubernetes Secrets).
- The application will read the folder specified by the
APP_FOLDER_KEYenvironment variable (defined in.env) to load the keys at startup.