GuideOctober 13, 20266 min read

Building a Monorepo Developer Setup with ConfigSync

Monorepos need complex tooling: root configs, per-package settings, shared linting rules, and per-service environment variables. Here is how to manage it all.

Monorepo Config Complexity

A monorepo is not just one project — it is an ecosystem. There is a root-level ESLint config, per-package TypeScript configurations, a shared Prettier setup, Turborepo or Nx pipeline definitions, and .env files for each service. Docker Compose files wire up local databases and message queues.

When a new developer clones the repo, they get the code but not the environment. The gitignored files — environment variables, local overrides, credential files — are missing. ConfigSync fills this gap by tracking and syncing the files that git cannot.

Tracking Monorepo Config Files

Start by adding the configuration files that every developer needs but that are not (or should not be) in version control:

Adding monorepo configs
# Local development overrides (gitignored) configsync add config ~/git/monorepo/docker-compose.override.yml configsync add config ~/git/monorepo/.env # Per-service environment files configsync add config ~/git/monorepo/apps/web/.env.local configsync add config ~/git/monorepo/apps/api/.env.local configsync add config ~/git/monorepo/apps/worker/.env.local # Database configuration configsync add config ~/git/monorepo/packages/database/.env
Git vs ConfigSync: Files checked into the repo belong in git. ConfigSync is for the gitignored layer — environment variables, local overrides, credentials, and developer-specific settings that should not be committed.

Per-Service Environment Variables

Monorepos with multiple services need different environment variables for each one. These .env files are typically gitignored for good reason — they contain database passwords, API keys, and service tokens. But they still need to be shared with the team.

Environment files for a typical monorepo
# apps/web/.env.local NEXT_PUBLIC_API_URL=http://localhost:3001 NEXT_PUBLIC_STRIPE_KEY=pk_test_xxx # apps/api/.env.local DATABASE_URL=postgres://localhost:5432/myapp_dev REDIS_URL=redis://localhost:6379 STRIPE_SECRET_KEY=sk_test_xxx JWT_SECRET=local-dev-secret # apps/worker/.env.local DATABASE_URL=postgres://localhost:5432/myapp_dev REDIS_URL=redis://localhost:6379 AWS_ACCESS_KEY_ID=AKIA... AWS_SECRET_ACCESS_KEY=xxx

ConfigSync detects that these files contain secrets and encrypts them before syncing. When a new developer pulls, they get all the environment variables needed to run every service locally — no asking teammates on Slack for database passwords.

Using Groups for Organization

When your monorepo has many config files, groups keep things organized:

Grouping monorepo configs
# Create a group for all monorepo configs configsync add group ~/git/monorepo --name "monorepo" # Pull just the monorepo group on a new machine configsync pull --filter group:monorepo # Push only monorepo changes configsync push --filter group:monorepo

Groups let you treat a set of related files as a unit. A developer setting up the monorepo can pull just that group without affecting their shell or git configuration. And when you push, you can scope the operation to just the files that belong to the monorepo.

Environment-Scoped Configs

Different environments need different values. Your local development database URL is not your staging URL. ConfigSync profiles handle this:

Environment-scoped .env files
profiles: local: vars: database_url: "postgres://localhost:5432/myapp_dev" redis_url: "redis://localhost:6379" staging: vars: database_url: "postgres://staging-db.internal:5432/myapp" redis_url: "redis://staging-redis.internal:6379" # In apps/api/.env.local: DATABASE_URL={{vars.database_url}} REDIS_URL={{vars.redis_url}}

Post-Pull Hooks for Monorepo Bootstrap

After pulling config files, most monorepos need a dependency installation step. Automate this with a post-pull hook:

Monorepo post-pull hooks
hooks: post_pull: - "cd ~/git/monorepo && pnpm install" - "cd ~/git/monorepo/packages/database && pnpm prisma generate" - "cd ~/git/monorepo && docker compose up -d postgres redis" - "cd ~/git/monorepo/packages/database && pnpm prisma db push"

Every pull automatically reinstalls dependencies, regenerates the Prisma client, starts infrastructure services, and syncs the database schema. If someone updates the Prisma schema on one machine, every other machine applies the change automatically after pulling.

Team Onboarding in One Command

With ConfigSync managing your monorepo's gitignored configuration, onboarding becomes trivial. A new developer clones the repo, pulls from ConfigSync, and the post-pull hooks handle the rest. No setup wiki. No Slack messages asking for credentials. No half-day spent getting the development environment running. Just clone, pull, code.

Ready to try ConfigSync?

Sync your entire dev environment across machines in minutes. Free forever for up to 3 devices.