Skip to content
Development
Skill

/deploy

Elixir/Phoenix deployment patterns — Dockerfile, fly.toml, runtime.exs, mix release, rel/ overlays. Use when configuring Fly.io, Docker, CI/CD, health checks, or production migrations.

From plugin
claude-elixir-phoenix
574106 skills37 agents2 commands

Claude Code

$ npx -y skills add oliver-kriska/claude-elixir-phoenix --skill deploy --agent claude-code

SKILL.md

deploy.SKILL.md
name: deploy
description: "Elixir/Phoenix deployment patterns — Dockerfile, fly.toml, runtime.exs, mix release, rel/ overlays. Use when configuring Fly.io, Docker, CI/CD, health checks, or production migrations."
effort: medium
paths:
  - "config/runtime.exs"
  - "Dockerfile"
  - "fly.toml"
  - "rel/**/*"

Elixir/Phoenix Deployment Reference

Quick reference for deploying Elixir/Phoenix applications.

Iron Laws — Never Violate These

1. **Config at runtime, not compile time** — Secrets in `config.exs` get baked into the release binary. Use `runtime.exs` with env vars so secrets are resolved at boot 2. **Graceful shutdown ≥ 60 seconds** — Shorter timeouts kill in-flight requests and WebSocket connections mid-operation, causing data loss for users 3. **Health checks required** — Without startup/liveness/readiness endpoints, orchestrators can't distinguish a booting node from a dead one, leading to cascading restarts 4. **SSL verification for database** — Skipping `verify: :verify_peer` allows MITM attacks between your app and database; production data traverses the connection 5. **No CPU limits** — The BEAM scheduler assumes it owns all cores; cgroups CPU limits cause scheduler collapse where the VM thinks it has more cores than it can use, leading to latency spikes 6. **Guard optional service credentials** — `runtime.exs` runs whenever a release boots, including `eval`-based migration commands. Only require S3, Redis, and similar credentials when that integration is enabled

Quick Configuration

runtime.exs (Essential)

if config_env() == :prod do
  database_url = System.get_env("DATABASE_URL") || raise "DATABASE_URL is required"
  secret_key_base = System.get_env("SECRET_KEY_BASE") || raise "SECRET_KEY_BASE is required"
  host = System.get_env("PHX_HOST") || raise "PHX_HOST is required"

  config :my_app, MyApp.Repo,
    url: database_url,
    pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
    ssl: true,
    ssl_opts: [verify: :verify_peer]

  config :my_app, MyAppWeb.Endpoint,
    url: [host: host, port: 443, scheme: "https"],
    http: [ip: {0, 0, 0, 0}, port: String.to_integer(System.get_env("PORT") || "4000")],
    secret_key_base: secret_key_base,
    server: true
end

Guard Optional Services

Keep core boot secrets such as `DATABASE_URL` and `SECRET_KEY_BASE` required. Gate credentials for optional integrations behind the same feature switch that enables the integration:

s3_config =
  if System.get_env("STORAGE_BACKEND") == "s3" do
    [
      access_key_id:
        System.get_env("S3_ACCESS_KEY") ||
          raise("S3_ACCESS_KEY is required when STORAGE_BACKEND=s3"),
      secret_access_key:
        System.get_env("S3_SECRET_KEY") ||
          raise("S3_SECRET_KEY is required when STORAGE_BACKEND=s3")
    ]
  else
    []
  end

config :my_app, :s3_config, s3_config

This lets release tasks that do not use S3 start without S3 credentials while still failing fast when S3 is selected.

Health Check Plug

def call(%{path_info: ["health", "readiness"]} = conn, _opts) do
  case Ecto.Adapters.SQL.query(MyApp.Repo, "SELECT 1", []) do
    {:ok, _} -> send_resp(conn, 200, ~s({"status":"ok"})) |> halt()
    {:error, _} -> send_resp(conn, 503, ~s({"status":"error"})) |> halt()
  end
end

Quick Decisions

Platform Choice

| Need | Use | |------|-----| | Simple, managed | Fly.io | | Enterprise, existing K8s | Kubernetes | | Custom infrastructure | Docker + your orchestrator |

Resource Limits

| Resource | Recommendation | |----------|----------------| | CPU | **NO LIMITS** (BEAM scheduler issues) | | Memory | Set limits (256Mi-512Mi typical) | | Graceful shutdown | ≥ 60 seconds |

Deployment Checklist

  • [ ] All secrets from environment variables in runtime.exs
  • [ ] Optional service credentials required only when their integration is enabled
  • [ ] `server: true` in endpoint config
  • [ ] SSL verification for database connections
  • [ ] Health endpoints: /health/startup, /health/liveness, /health/readiness
  • [ ] Graceful shutdown period ≥ 60 seconds
  • [ ] No CPU limits (memory limits only)
  • [ ] Migrations in deploy process

Asset Pipeline Notes

Phoenix 1.8 uses esbuild + tailwind (no Node.js required):

  • Config in `config/config.exs` under `:esbuild` and `:tailwind`
  • `mix assets.deploy` builds for production
  • `mix assets.setup` installs binaries on first run
  • Custom JS bundlers: configure in `config/config.exs`

References

For detailed patterns, see:

  • `${CLAUDE_SKILL_DIR}/references/docker-config.md` - Multi-stage Dockerfile, best practices
  • `${CLAUDE_SKILL_DIR}/references/flyio-config.md` - fly.toml, clustering, commands
Read more
@oliver-kriska
Ships withclaude-elixir-phoenix

Docs: phxagents.dev -- install guides per runtime, the runtime compatibility matrix, all 26 Iron Laws, and a browsable skill and agent catalog. Claude Code is great.

574106 skills37 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
574
Star history of oliver-kriska/claude-elixir-phoenix on GitHub, a chart by star-history.com

Other skills on claude-elixir-phoenix.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills12d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc13d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react2d252k
@facebook@facebookInstall Skill

Questions about deploy.

Which coding agents can use deploy?
deploy installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.