Core workflow
Ports & configuration
The PORT contract and the complete phelix.yaml field reference.
The PORT contract
Phelix sets the PORT environment variable. Applications managed by Phelix should listen on the port provided by PORT rather than hardcoding a port.
phelix build api --port 4000This starts your application with PORT=4000, so it should listen on :4000. If the process runs but nothing listens on the requested port, Phelix reports a port-validation failure and suggests phelix doctor.
port := os.Getenv("PORT")if port == "" { port = "3000"} log.Fatal(http.ListenAndServe(":"+port, router))Three port concepts
| Concept | Example | Who owns it |
|---|---|---|
| Public proxy port | :8080 | The Phelix proxy (clients connect here) |
| Internal application port | :49152 / :49153 | Phelix assigns per instance (blue/green get different ports) |
| PORT environment variable | PORT=49152 | How Phelix tells each instance which internal port to use |
With blue-green deployment, each instance receives its own PORT; the proxy owns the single public port. A failed new deployment never touches the currently active instance.
Project configuration
phelix.yaml is the project-level Phelix configuration file, stored in the current project directory. It removes the need to repeat the application name, port, health checks, and deployment strategy on every command. phelix init detects the project type (Go/Rust) and generates it:
# Phelix project configuration.# CLI flags override these values (e.g. --port).name: my-appport: 8080watching: disablehealth: endpoints: - name: default path: /health interval: 10s retries: 3 mode: autodeploy: strategy: classicAn example combining health checks, blue-green deployment, and Git webhooks:
name: apiport: 3000watching: enable health: endpoints: - name: readiness path: /ready interval: 5s retries: 3 mode: http - name: liveness path: /health interval: 10s retries: 3 mode: auto deploy: strategy: blue-green webhook: enabled: true branch: main secret_env: PHELIX_WEBHOOK_SECRETThe configuration file is fully optional. Projects without phelix.yaml keep working exactly as before - every existing flag and prompt is unchanged.
Field reference
| Field | Required | Description |
|---|---|---|
| name | no* | Application name used by build, rebuild, health, rollback, etc. *Optional: when missing, build prompts for it (TTY) or fails with a clear error (scripts). |
| port | no | Public application port. Default 8080 when missing. |
| watching | no | Backend monitoring opt-in: enable or disable (phelix init writes disable). Applied to the app on every build/rebuild; absent leaves the app's current state (see Multi-server monitoring). |
| health.endpoints[].name | yes (per endpoint) | Endpoint name, e.g. default, readiness. Must be unique. |
| health.endpoints[].path | yes (per endpoint) | HTTP path on localhost, e.g. /health. Must start with /. |
| health.endpoints[].interval | no | Monitoring check interval (e.g. 10s, 1m). Default 10s. |
| health.endpoints[].retries | no | Consecutive failures before marking DOWN. Default 3. |
| health.endpoints[].mode | no | Deploy health tier: auto (default), http, tcp-only, none. |
| deploy.strategy | no | classic (default), blue-green, rolling, canary, or progressive. |
| deploy.replicas | no | Replica count for rolling (requires deploy.strategy: rolling). |
| deploy.runtime | no | native (default) or docker - run instances as containers. docker requires a zero-downtime strategy (see Docker runtime). |
| deploy.rollout.canary | no | Traffic share (percent) for canary before promotion. Default 10. |
| deploy.rollout.duration | no | Verification window for canary (e.g. 2m). Default 30s. |
| deploy.rollout.steps[] | no | Progressive steps: traffic (percent) and optional duration per step; must strictly increase and end at 100. |
| deploy.rollout.verification | no | Regression thresholds: interval, max_error_rate, max_error_delta, max_p95_factor (see Canary & progressive rollouts). |
| webhook.enabled | no | Enable Git push triggers for this app. Default false. |
| webhook.branch | yes (when enabled) | Bare branch name whose pushes trigger rebuilds, such as main or release/2.x. |
| webhook.secret_env | yes (when enabled) | Environment variable name holding the HMAC-SHA256 shared secret. Never put the secret itself in phelix.yaml. |
| resources.cpu | no | Per-instance CPU ceiling: millicores (500m) or cores (0.5), Linux only (see Resource limits). |
| resources.memory | no | Per-instance memory limit with binary units (512Mi, 1Gi), Linux only. |
Resolution order
phelix build (and the other project-aware commands) resolve values in this order:
CLI argument/flag → phelix.yaml → Phelix default → interactive promptWith the full example above, running phelix build resolves automatically - no prompts:
Application: apiPort: 3000Partial configurations work: a file with only name: prompts for the port (in a TTY) or uses the default 8080; a file with only port: prompts for the name. No file at all means today's behavior (prompt or explicit args).
Explicit flags always win:
phelix build --port 8080 # uses port 8080 even though the config says 3000phelix build my-custom-name # uses my-custom-name even though the config has a nameHealth endpoints
Endpoints declared in phelix.yaml are applied to the app's persisted health configuration on every phelix build / phelix rebuild, so:
phelix health list <app>andphelix health status <app>show them.- Zero-downtime deploys use the first endpoint's
path/modeas the deploy health tier (same asphelix health set). - The
phelix health set/add/removecommands keep working: ahealth:block in the config replaces the persisted endpoints at the next build/rebuild, while apps without ahealth:block keep whatever was set via the commands.
Deployment strategies
deploy.strategy selects which existing deployment path phelix rebuild uses - it does not introduce a new deployment system.
deploy: strategy: classic # normal stop → rebuild → startdeploy: strategy: blue-green # zero-downtime blue-green (same as --blue-green)deploy: strategy: rolling # zero-downtime rolling (same as --replicas N) replicas: 3deploy: strategy: canary # one-shot canary share, then promotion rollout: canary: 5% # traffic share for the canary (default 10%) duration: 2m # verification window before promotion (default 30s)deploy: strategy: progressive # step-by-step traffic increase rollout: steps: - traffic: 5% duration: 2m - traffic: 25% duration: 5m - traffic: 50% duration: 5m - traffic: 100% # the final promotion step (required) verification: interval: 5s # health/metrics poll cadence (default 5s) max_error_rate: 5 # absolute canary error-rate cap, percent (default 5) max_error_delta: 2 # canary minus baseline, percentage points (default 2) max_p95_factor: 3 # canary p95 at most N × baseline p95 (default 3)The rollout behavior behind canary and progressive is documented in Canary & progressive rollouts.
Explicit flags still override the config (--blue-green, --replicas, --canary, --port), and --strategy overrides it for a single rebuild without editing the file - the same one-off override the dashboard sends for a remote rebuild.
When nothing names a strategy, a rebuild keeps the one the app is already deployed with (from deploy.json) instead of falling back to classic: demoting a live blue-green/rolling app tears its instances down and drops its deployment state, so it has to be asked for - strategy: classic here, or --strategy classic for one rebuild. A rollout runs on the blue-green topology, so an app whose last deploy was canary/progressive inherits blue-green when nothing names a strategy; put strategy: canary or progressive in phelix.yaml to make rollouts the app's default.
phelix rollback needs no configuration: it inspects the recorded deploy state and automatically uses classic or zero-downtime rollback to match how the app was actually deployed. phelix proxy is required for blue-green/rolling/canary, exactly as with the flags.
Validation
The configuration is validated before it can affect a build or deploy - an invalid file fails the command with a CONFIGURATION_ERROR instead of being ignored:
Configuration error: invalid deploy.strategy "foobar"Hint: expected one of: classic, blue-green, rolling, canary, progressiveValidated: YAML syntax, port range, strategy name, replicas (≥ 1, rolling only), endpoint names (required, unique), paths (must start with /), durations (10s, 1m, ...), modes (auto, http, tcp-only, none), and the rollout plan: traffic percentages (whole numbers, 25 or "25%"), each step within 1-100, strictly increasing shares ending at the 100% promotion, non-negative durations, canary within 1-99, and verification thresholds (positive interval, error rates within 0-100, p95 factor ≥ 1).
phelix init
Detects the project type (Go/Rust) and creates phelix.yaml with the application name, port, watching: disable, a default health endpoint, and the classic deploy strategy. Prompts interactively in a TTY; fully scriptable with flags. Never modifies application source code. If a hardcoded listen port is detected, prints a warning and points to phelix doctor.
phelix init --name api --port 3000 --yesphelix doctor
Diagnoses whether the current project is Phelix-compatible: project detection, toolchain, build tools, phelix.yaml, and - most importantly - whether the application listens on PORT instead of a hardcoded port.
$ phelix doctor Phelix Doctor ✓ Project detected go (/home/me/api)✓ go toolchain go1.27 linux/amd64✓ Build tools ready✓ phelix.yaml found✓ Application name api✓ Configured port 4000✗ PORT configuration hardcoded :3000 Summary: 6 passed 1 failedExits non-zero when a critical check fails. Inconclusive detection (no listener found, no PORT usage) is reported as a warning, not a false failure. Diagnostic only - never rewrites source code.