Multi-Environment Setup
cloudflared-project treats environments as first-class citizens. Each project can have isolated tunnel configurations for dev, staging, and prod — different tunnels, different ingress rules, different service URLs.
Project Structure
Section titled “Project Structure”After initializing a project, the directory layout is:
~/.cloudflared/projects/myapp/├── project.yaml # Project metadata└── environments/ ├── dev.yaml # Dev environment tunnel config ├── staging.yaml # Staging environment tunnel config └── prod.yaml # Production environment tunnel configEach environments/<env>.yaml file is a standard cloudflared configuration that can be passed directly to cloudflared tunnel run --config.
Setting the Active Environment
Section titled “Setting the Active Environment”Use the --env / -e flag on any command to target a specific environment. The default is dev.
# Target stagingcloudflared-project -p myapp -e staging config show
# Target productioncloudflared-project -p myapp -e prod deploy --route-dnsYou can also set the environment via an environment variable:
export CLOUDFLARED_PROJECT_ENV=stagingcloudflared-project -p myapp deployCreating Environment Configurations
Section titled “Creating Environment Configurations”Step 1 — Create the tunnel for each environment
Section titled “Step 1 — Create the tunnel for each environment”cloudflared-project -p myapp tunnel create myapp-devcloudflared-project -p myapp -e staging tunnel create myapp-stagingcloudflared-project -p myapp -e prod tunnel create myapp-prodStep 2 — Configure ingress rules per environment
Section titled “Step 2 — Configure ingress rules per environment”Dev:
cloudflared-project -p myapp -e dev \ config add-ingress --hostname dev.myapp.example.com --service http://localhost:3000Staging:
cloudflared-project -p myapp -e staging \ config add-ingress --hostname staging.myapp.example.com --service http://localhost:3001Prod:
cloudflared-project -p myapp -e prod \ config add-ingress --hostname myapp.example.com --service http://localhost:8080Step 3 — Validate all configurations
Section titled “Step 3 — Validate all configurations”cloudflared-project -p myapp -e dev config validatecloudflared-project -p myapp -e staging config validatecloudflared-project -p myapp -e prod config validateStep 4 — Deploy per environment
Section titled “Step 4 — Deploy per environment”# Deploy dev (foreground, interactive)cloudflared-project -p myapp -e dev deploy
# Deploy staging (background)cloudflared-project -p myapp -e staging deploy --detach
# Deploy production (background, with DNS routing)cloudflared-project -p myapp -e prod deploy --detach --route-dnsExample Environment Files
Section titled “Example Environment Files”environments/dev.yaml
Section titled “environments/dev.yaml”tunnel: a1b2c3d4-dev-tunnel-uuidcredentials-file: /home/user/.cloudflared/a1b2c3d4-dev-tunnel-uuid.jsoningress: - hostname: dev.myapp.example.com service: http://localhost:3000 originRequest: connectTimeout: 10s - service: http_status:404environments/prod.yaml
Section titled “environments/prod.yaml”tunnel: e5f6a7b8-prod-tunnel-uuidcredentials-file: /home/user/.cloudflared/e5f6a7b8-prod-tunnel-uuid.jsoningress: - hostname: myapp.example.com service: http://localhost:8080 originRequest: connectTimeout: 30s tlsTimeout: 30s - hostname: api.myapp.example.com service: http://localhost:8081 - service: http_status:404warp-routing: enabled: falseSetting a Default Environment
Section titled “Setting a Default Environment”By default, cloudflared-project uses dev. To change the default for a project, edit project.yaml:
version: "1"name: myappdefault_env: stagingBest Practices
Section titled “Best Practices”- One tunnel per environment — avoids credential conflicts and makes rollbacks straightforward.
- Separate domains per environment —
dev.app.com,staging.app.com,app.comfor clear separation. - Use
--detachfor staging and prod — foreground mode is for development only. - Always validate before deploying to prod — run
config validateas part of your CI pipeline. - Store projects in version control — the
environments/*.yamlfiles contain no secrets (credentials are separate.jsonfiles) and should be committed.
Caution: The
environments/*.jsoncredentials files do contain sensitive secrets. Never commit them to version control. Add*.jsonto your.gitignorewithin the project directory.
Monitoring Multiple Environments
Section titled “Monitoring Multiple Environments”# Check dev statuscloudflared-project -p myapp -e dev status
# Check prod status with live refreshcloudflared-project -p myapp -e prod status --watch
# Tail prod logscloudflared-project -p myapp -e prod logs --follow