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: 8080health: endpoints: - name: default path: /health interval: 10s retries: 3 mode: autodeploy: strategy: classicA full example using every supported field:
name: apiport: 3000 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-greenThe 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. |
| 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, or rolling. |
| deploy.replicas | no | Replica count for rolling (requires deploy.strategy: rolling). |
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: 3Explicit flags still override the config (--blue-green, --replicas, --port). 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, 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, rollingValidated: 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).
phelix init
Detects the project type (Go/Rust) and creates phelix.yaml with the application name, port, 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.22 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.