How Openship Handles Configuration for Its Packages: The openship.json Architecture
Openship centralizes package-level configuration in a declarative, strongly-typed openship.json file that merges auto-detected defaults, explicit overrides, and environment variables into a unified runtime configuration.
The oblien/openship repository implements a layered configuration system designed to support both simple applications and complex monorepos. By combining static schema validation with intelligent runtime detection, the system provides type-safe settings while remaining flexible enough to handle encrypted secrets and per-service customizations.
The Declarative openship.json File
All configuration originates from an openship.json file located at the repository root. This file follows a strict schema defined in packages/core/src/openship-config/schema.ts, which enforces type safety and validates structure before the runtime consumes any values. The schema supports framework detection, service definitions, domain mappings, and monorepo-specific overrides.
Validation and Parsing
When the CLI or web UI initializes, packages/core/src/openship-config/parse.ts processes the raw JSON. This module validates the file against the schema and coerces values into a fully-typed OpenshipConfig object, preventing malformed configurations from reaching production.
Runtime Configuration Layer
The packages/core/src/runtime-config.ts module exposes the getConfig() helper that packages import to access settings. As implemented in oblien/openship, this utility merges three distinct configuration sources in strict order of precedence:
-
Auto-detected defaults – The system inspects the codebase via
packages/core/src/stacks.tsto identify frameworks (such as Next.js), Dockerfiles, and build commands, generating baseline settings automatically. -
openship.jsonoverrides – Any field defined in the root configuration file replaces the auto-detected value, while omitted fields retain their intelligent defaults. -
Environment variables – Values supplied via
process.envor encrypted secret objects temporarily override the merged configuration for specific deployment runs.
Packages access the final merged configuration through the @openship/core import:
import { getConfig } from "@openship/core/runtime-config";
const cfg = getConfig();
console.log(cfg.port); // 3000 or auto-detected fallback
console.log(cfg.services?.[0]); // Service-specific configuration
Persistent Settings and Secret Management
Configuration requiring persistence across restarts—including SSH server details, SMTP credentials, and resource limits—stores in the internal database. The schema defined in packages/db/src/schema/settings.ts manages these values, with sensitive fields stored as encrypted JSON blobs. This approach ensures secrets remain secure at rest while remaining accessible to the runtime configuration layer.
await db
.updateTable("settings")
.set({ smtpPassword: { value: "s3cr3t", secret: true } })
.where("id", "=", 1)
.run();
Monorepo Support with Per-App Overrides
For monorepo structures, the schema includes an openshipMonorepoApp definition allowing each sub-application to specify independent build commands, ports, and frameworks. These per-app overrides apply after the global detection step, enabling independent build and deployment workflows while maintaining a common configuration surface across the repository.
A minimal openship.json configuration for a Next.js application appears as:
{
"framework": "next",
"port": 3000,
"services": [
{ "name": "web", "build": "npm run build", "env": { "NODE_ENV": "production" } }
],
"domains": [{ "domain": "app.example.com" }]
}
Summary
- Openship uses a root-level
openship.jsonfile as the primary configuration source, validated against a TypeScript schema inpackages/core/src/openship-config/schema.ts. - The parsing layer in
packages/core/src/openship-config/parse.tsconverts raw JSON into typedOpenshipConfigobjects. - Runtime configuration merges auto-detected defaults, file-based overrides, and environment variables via the
getConfig()helper inpackages/core/src/runtime-config.ts. - Persistent settings and encrypted secrets store in database tables defined by
packages/db/src/schema/settings.ts. - Monorepo support allows sub-applications to define independent configurations through the
openshipMonorepoAppschema property.
Frequently Asked Questions
What file format does Openship use for package configuration?
Openship uses a JSON file named openship.json located at the repository root. This file follows a strictly typed schema defined in packages/core/src/openship-config/schema.ts, supporting values for frameworks, ports, services, domains, and monorepo-specific settings.
How does Openship handle sensitive configuration values like passwords?
Sensitive values persist in the internal database using the schema defined in packages/db/src/schema/settings.ts. These fields store as encrypted JSON blobs marked with "secret": true, ensuring credentials like SMTP passwords or SSH keys remain encrypted at rest while remaining accessible to the runtime configuration system.
Can environment variables override openship.json settings?
Yes. The runtime configuration layer applies environment variables as the highest precedence layer after auto-detected defaults and openship.json values. You can temporarily override any configuration field for a specific run by setting the corresponding environment variable before starting the CLI or web UI.
How does Openship support configuration in monorepos?
The openship.json schema includes an openshipMonorepoApp definition that allows each sub-application to provide its own build commands, ports, and framework settings. These per-app configurations apply after global auto-detection, enabling independent deployment pipelines while sharing the centralized configuration system.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →