How Kaneo Handles Configuration: Environment Variables and Type-Safe Settings

Kaneo centralizes all runtime configuration in a type-safe getSettings() helper that loads environment variables via dotenv-mono, validates critical security settings, and supplies sensible defaults for local development.

Kaneo keeps sensitive credentials out of source control by relying entirely on environment-based configuration. At startup, the application loads a root .env file and exposes typed settings through a centralized utility, ensuring every service—from the PostgreSQL database to S3-compatible storage—accesses validated configuration through a single source of truth.

Centralized Configuration Architecture

Loading Environment Variables with dotenv-mono

Instead of scattering process.env access throughout the codebase, Kaneo uses the dotenv-mono package to parse a single .env file located at the repository root. This executes before application logic, making all environment variables available through process.env to every module in the monorepo.

The getSettings() Type-Safe Helper

The configuration system's core resides in apps/api/src/utils/get-settings.ts. This module exports a getSettings() function that extracts required variables, casts them to appropriate TypeScript types, and provides fallback values—such as defaulting KANEO_API_URL to http://localhost:1337 when undefined.

import { getSettings } from "@/utils/get-settings";

const { DATABASE_URL, AUTH_SECRET } = getSettings();

export const db = drizzle(DATABASE_URL, { schema });
export const jwt = new JwtService(AUTH_SECRET);

Source: apps/api/src/database/index.ts and apps/api/src/auth.ts

Database and Infrastructure Configuration

PostgreSQL and Drizzle ORM Setup

In apps/api/src/database/index.ts, the application reads DATABASE_URL, POSTGRES_DB, POSTGRES_USER, and POSTGRES_PASSWORD to initialize the Drizzle ORM connection. The settings helper ensures these values are present before attempting to connect, preventing runtime undefined errors.

Authentication and Session Storage

The authentication layer in apps/api/src/auth.ts retrieves AUTH_SECRET for JWT signing and REDIS_URL for session storage. The system enforces security by validating that AUTH_SECRET contains at least 32 characters, throwing a clear error and exiting if this requirement is not met.

import { getSettings } from "@/utils/get-settings";

const {
  S3_ENDPOINT,
  S3_BUCKET,
  S3_ACCESS_KEY_ID,
  S3_SECRET_ACCESS_KEY,
  S3_REGION,
  S3_FORCE_PATH_STYLE,
} = getSettings();

export const s3 = new S3Client({
  endpoint: S3_ENDPOINT,
  region: S3_REGION,
  credentials: {
    accessKeyId: S3_ACCESS_KEY_ID,
    secretAccessKey: S3_SECRET_ACCESS_KEY,
  },
  forcePathStyle: S3_FORCE_PATH_STYLE === "true",
});

Source: apps/api/src/storage/s3.ts

Third-Party Service Integration

S3-Compatible Object Storage

File attachments are handled by an S3-compatible client configured in apps/api/src/storage/s3.ts. This module consumes six environment variables: S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_REGION, and the optional boolean string S3_FORCE_PATH_STYLE.

GitHub OAuth and App Integration

For GitHub Single Sign-On, apps/api/src/plugins/github/utils/github-app.ts reads GITHUB_OAUTH_CLIENT_ID, GITHUB_OAUTH_CLIENT_SECRET, GITHUB_CLIENT_ID, and GITHUB_CLIENT_SECRET. These credentials remain isolated within the plugin utility and are never hard-coded into the source.

Frontend API Configuration

The web client in apps/web/src/lib/utils.ts consumes VITE_API_URL (derived from KANEO_API_URL) to construct API request URLs. During development, this defaults to http://localhost:1337, allowing the frontend to proxy requests to the local API server without manual configuration.

import { getSettings } from "@/utils/get-settings";

export const API_URL = getSettings().KANEO_API_URL;

// Usage in a fetcher
export async function getTask(id: string) {
  const res = await fetch(`${API_URL}/tasks/${id}`);
  return res.json();
}

Source: apps/web/src/lib/utils.ts

Validation and Security Defaults

Kaneo's configuration system enforces security at startup. Required variables like AUTH_SECRET trigger immediate application shutdown if missing or insufficiently long, while optional variables receive sensible defaults. This design prevents the server from starting in a misconfigured state where secrets might be vulnerable or database connections would fail silently.

Summary

  • dotenv-mono loads a root .env file into process.env before application startup
  • The getSettings() helper in apps/api/src/utils/get-settings.ts provides type-safe access with automatic defaults for local development
  • Database connections in apps/api/src/database/index.ts and authentication in apps/api/src/auth.ts import configuration through the centralized helper
  • S3 storage credentials and GitHub OAuth secrets are isolated in their respective plugin utilities
  • The frontend reads VITE_API_URL via apps/web/src/lib/utils.ts to communicate with the backend API
  • Critical security variables undergo length and presence validation to prevent misconfigured deployments

Frequently Asked Questions

What environment variables are required to run Kaneo?

At minimum, you must provide DATABASE_URL (or individual PostgreSQL credentials POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD), AUTH_SECRET (minimum 32 characters), and REDIS_URL. For file upload functionality, S3 configuration including S3_ENDPOINT, S3_BUCKET, and access keys is required.

How does Kaneo validate configuration at startup?

The getSettings() function validates that AUTH_SECRET meets minimum length requirements and checks for the presence of mandatory database credentials. If validation fails, the application throws a descriptive error and exits immediately before initializing external connections.

Can I use a different storage provider than AWS S3?

The current implementation in apps/api/src/storage/s3.ts targets S3-compatible APIs. While the configuration system itself is provider-agnostic, switching to a different storage architecture (such as local filesystem or Azure Blob) would require implementing a custom adapter that follows the same pattern of consuming settings via getSettings().

How do I configure Kaneo for production deployment?

Create a .env file at the repository root with production values for DATABASE_URL, AUTH_SECRET, REDIS_URL, and your S3 credentials. Set KANEO_API_URL to your public API endpoint (e.g., https://api.kaneo.example.com), and ensure VITE_API_URL is set accordingly before building the frontend.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →