Quick Start — Elixir¶
Deploy an Elixir app (Phoenix, Plug, plain OTP) from git push to a live HTTPS URL in 5 minutes.
Prerequisites¶
- An Elixir project with
mix.exs - Elixir 1.16+ + Erlang/OTP 26+ on your machine (
elixir --version) - The
paasCLI:
Scaffold (if you don't have a project yet — Phoenix)¶
mix archive.install hex phx_new --force
mix phx.new hello_paas --no-ecto --no-live --no-mailer --no-tailwind
cd hello_paas
mix deps.get
git init && git add -A && git commit -m "init"
For a minimal Plug-only project:
mix new hello_paas --sup && cd hello_paas
cat >> mix.exs <<'EOF'
defp deps do
[{:plug_cowboy, "~> 2.7"}]
end
EOF
# Edit lib/hello_paas/application.ex to start a Cowboy listener on PORT
mix deps.get
git init && git add -A && git commit -m "init"
Step 1 — Authenticate¶
Verify:
Step 2 — Create the app¶
Output:
✓ Created app hello-paas
URL: https://hello-paas.runtime.di2amp.com
Region: eu-fr-1
Plan: free
Git: https://git.di2amp.com/octave/hello-paas.git
Step 3 — Configure for production + add a Procfile¶
In config/runtime.exs (Phoenix), bind on PORT:
import Config
if config_env() == :prod do
port = String.to_integer(System.get_env("PORT") || "4000")
config :hello_paas, HelloPaasWeb.Endpoint,
http: [ip: {0, 0, 0, 0}, port: port],
server: true,
secret_key_base: System.fetch_env!("SECRET_KEY_BASE")
end
Procfile:
The Paketo Erlang buildpack auto-detects mix.exs. For better cold start, generate a release with mix release and run the binary:
# Procfile (release-mode, faster boot)
web: _build/prod/rel/hello_paas/bin/hello_paas start
release: _build/prod/rel/hello_paas/bin/hello_paas eval "HelloPaas.Release.migrate"
Commit:
Step 4 — Push to deploy¶
Live build logs:
remote: ─────── PaaS Build ───────
remote: → Detected: erlang/elixir (paketo-buildpacks/elixir)
remote: → Installing Erlang/OTP 26.2.5
remote: → Installing Elixir 1.16.3
remote: → Running: mix deps.get --only prod
remote: → Running: MIX_ENV=prod mix release
remote: → Image: registry.di2amp.com/octave/hello-paas:abc1234
remote: → Image size: 67 MB (BEAM + release tree, ERTS embedded)
remote: → SBOM: ✓ generated, 24 packages
remote: → CVE scan: ✓ 0 critical, 0 high
remote:
remote: ─────── PaaS Deploy ───────
remote: → Process types: web
remote: → Replicas: 1/1 ready
remote: → Rollout: v1 → v2 (canary 10% → 100%)
remote: → Health: / returns 200 OK
remote: → URL: https://hello-paas.runtime.di2amp.com
remote:
remote: ✓ Deployed in 84s
PaaS automatically generates a SECRET_KEY_BASE env var for new Phoenix apps.
Step 5 — Verify the app is live¶
$ curl https://hello-paas.runtime.di2amp.com/
<!DOCTYPE html><html>... Phoenix welcome page ...</html>
Dashboard runtime status:
https://ma30.di2amp.com/runtime/dashboard/apps/hello-paas
Next steps¶
Add a managed PostgreSQL¶
DATABASE_URL is injected. Phoenix config/runtime.exs:
Run migrations on every deploy¶
# Procfile
web: _build/prod/rel/hello_paas/bin/hello_paas start
release: _build/prod/rel/hello_paas/bin/hello_paas eval "HelloPaas.Release.migrate"
Tail logs¶
Cluster nodes (libcluster)¶
PaaS injects POD_IP + POD_NAMESPACE. Use libcluster's Kubernetes strategy:
config :libcluster,
topologies: [
paas: [
strategy: Cluster.Strategy.Kubernetes,
config: [
mode: :hostname,
kubernetes_node_basename: "hello_paas",
kubernetes_selector: "paas-app=hello-paas"
]
]
]