Openship Configuration File Locations: Complete Guide to Deployment Settings

Openship discovers deployment settings by scanning the repository root for well-known files like package.json, vercel.json, and docker-compose.yml, then overlays explicit values from a single openship.json file that overrides auto-detected defaults.

The oblien/openship deployment engine uses a two-stage pipeline to determine how to build and run your application. First, it performs auto-detection by analyzing root-level configuration files to infer the framework, package manager, and build commands. Second, it applies explicit overrides from an optional openship.json file in the repository root, which serves as the authoritative source for custom deployment parameters.

Primary Configuration File Locations

Openship expects specific files to reside in the repository root (/) to drive the deployment process. These files are categorized by their authority level and function.

The openship.json File

The openship.json file is the primary declarative configuration that overrides all auto-detected values. According to [schema.ts](https://github.com/oblien/openship/blob/main/packages/core/src/openship-config/schema.ts), this file supports fields for build, runtime, env, domains, routes, resources, services, and monorepo layout. Only fields present in the file replace detected values; omitted fields retain their defaults.

Placement requirements:

  • Must reside at the repository root (/)
  • Only one file per repository (service-level openship.json files are not supported)

Platform-Specific Metadata Files

Openship recognizes configuration files from other platforms and treats them as authoritative metadata:

Both files must reside at the repository root to be detected.

Docker and Compose Files

Docker-related configurations trigger specialized deployment paths:

Auto-Detection and Language Manifests

Before applying openship.json overrides, Openship scans for standard language and package manager files to infer the stack:

  • package.json: Detects JavaScript/Node.js stacks. As a root-config file, changes force a full rebuild.
  • Language manifests: Cargo.toml (Rust), pyproject.toml (Python), go.mod (Go), and others identified by workspace detectors in packages/core/src/workspaces/*.
  • Lockfiles: Used to identify the package manager and dependency tree.

These files can exist at the repository root or within a service's rootDirectory in monorepo setups.

Configuration Overlay System

The merging of auto-detected values and explicit configuration follows a strict pipeline:

  1. Parsing: The parseOpenshipConfig function in [parse.ts](https://github.com/oblien/openship/blob/main/packages/core/src/openship-config/parse.ts) reads the raw JSON, validates it against TOP_LEVEL_KEYS, and builds a typed OpenshipConfig object.

  2. Metadata Merge: In [prepare.service.ts](https://github.com/oblien/openship/blob/main/apps/api/src/modules/deployments/prepare.service.ts), the repo-root openship.json is merged onto the detection result (ProjectInfo). Only present fields replace detected values.

  3. Runtime Application: The merged configuration feeds the build pipeline, routing compiler, and cloud-resource allocator.

{
  "$schema": "https://github.com/oblien/openship/schema/openship.json",
  "framework": "nextjs",
  "buildCommand": "npm run build",
  "outputDirectory": ".next"
}

Monorepo Configuration Patterns

For monorepos, Openship uses a single root-level openship.json with a monorepo block. Individual applications are declared inside the monorepo.apps[] array, as defined by the OpenshipMonorepoApp type in [schema.ts](https://github.com/oblien/openship/blob/main/packages/core/src/openship-config/schema.ts).

Each app entry specifies its own rootDirectory, allowing per-app framework detection and build configuration:

{
  "$schema": "https://github.com/oblien/openship/schema/openship.json",
  "monorepo": {
    "apps": [
      {
        "name": "frontend",
        "rootDirectory": "apps/frontend",
        "framework": "nextjs",
        "buildCommand": "npm run build",
        "outputDirectory": ".next"
      },
      {
        "name": "api",
        "rootDirectory": "apps/api",
        "framework": "node",
        "buildCommand": "npm run build"
      }
    ]
  }
}

The rootDirectory values align with the detector's workspace logic in packages/core/src/workspaces/*.

Force-Rebuild Triggers

Changes to root-configuration files automatically set forceAll = true, bypassing smart per-service routing. The classifyChangedFiles function in [webhook-changed-files.ts](https://github.com/oblien/openship/blob/main/apps/api/src/modules/github/webhook-changed-files.ts) monitors the ROOT_CONFIG_FILES array, which includes:

Any modification to these files causes Openship to rebuild all services in the repository rather than detecting which specific services changed.

CLI Tools for Configuration Management

The Openship CLI provides commands to scaffold and validate configuration files, implemented in [apps/cli/src/commands/config.ts](https://github.com/oblien/openship/blob/main/apps/cli/src/commands/config.ts).

Initialize a New Configuration

openship config init

This generates a starter openship.json with detected framework defaults and the $schema reference.

Validate Existing Configuration

openship config validate

# Or specify a path

openship config validate path/to/openship.json

The CLI uses parseOpenshipConfig to validate against the schema and print errors or warnings.

Summary

  • Primary location: All configuration files must reside in the repository root (/), with openship.json serving as the single authoritative override source.
  • Auto-detection: Openship scans for package.json, language manifests (Cargo.toml, pyproject.toml, etc.), and platform configs (vercel.json, railway.toml) before applying explicit settings.
  • No service-level configs: Monorepos must use a single root openship.json with a monorepo.apps[] array; individual service directories cannot contain their own openship.json files.
  • Force-rebuild files: Modifications to Dockerfile, docker-compose.yml, .dockerignore, or package.json trigger full repository rebuilds.
  • CLI support: Use openship config init and openship config validate to manage configuration files.

Frequently Asked Questions

Can I place openship.json in a subdirectory instead of the repository root?

No. Openship strictly requires openship.json to reside at the repository root (/). The parseOpenshipConfig function in packages/core/src/openship-config/parse.ts only reads from this location, and service-level configuration files are not supported.

How does Openship handle conflicts between vercel.json and openship.json?

When both files exist, values in openship.json override those in vercel.json. The metadata merge logic in prepare.service.ts applies platform-specific configs first, then overlays explicit openship.json fields. Only fields present in openship.json replace the detected defaults.

What happens if I modify the docker-compose.yml file after the initial deployment?

Changes to docker-compose.yml trigger forceAll = true in the classifyChangedFiles function, causing Openship to rebuild all services in the repository rather than incrementally updating individual services. This ensures that changes affecting the entire container orchestration are applied consistently.

Can I use a custom path for my Docker Compose file?

Yes. While Openship looks for compose files in the repository root by default, you can specify an alternative path using the composePath field in openship.json. The prepare.service.ts module reads this field to locate your compose configuration in subdirectories.

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 →