Deploy Elixir on Your Own Server
Deploy Elixir and Phoenix applications as compiled releases with automatic HTTPS and managed PostgreSQL. A custom Dockerfile is recommended for Phoenix to produce a small, self-contained release.
Quickstart
From your project root, deploy with your preferred package manager:
npx @temps-sdk/cli up
Temps supports Elixir via Nixpacks (select the nixpacks-elixir preset in project settings). For Phoenix, add the Dockerfile below for full control over the release build.
What Temps Handles Automatically
| Feature | How Temps handles it |
|---|---|
| Detection | mix.exs (Nixpacks nixpacks-elixir preset) |
| Build | mix release for Phoenix via Dockerfile |
| HTTPS | Let's Encrypt certificate, auto-renewed |
| Port | PORT env var injected |
| Health checks | HTTP health check on / |
| Zero-downtime deploys | New container starts before old one stops |
Phoenix Dockerfile
A multi-stage Dockerfile that compiles a Phoenix release and runs it on a minimal Alpine base:
Dockerfile (Phoenix)
FROM elixir:1.17-alpine AS build
RUN apk add --no-cache build-base git
WORKDIR /app
ENV MIX_ENV=prod
COPY mix.exs mix.lock ./
RUN mix deps.get --only prod && mix deps.compile
COPY lib ./lib
COPY priv ./priv
COPY config ./config
RUN mix compile && mix release
FROM alpine:3.20
RUN apk add --no-cache libstdc++ openssl ncurses-libs
WORKDIR /app
COPY --from=build /app/_build/prod/rel/my_app ./
ENV PORT=4000
EXPOSE 4000
CMD ["bin/my_app", "start"]
Make sure your Phoenix endpoint reads the port from the environment:
config/runtime.exs
config :my_app, MyAppWeb.Endpoint,
url: [host: System.get_env("APP_HOST") || "localhost"],
http: [ip: {0, 0, 0, 0}, port: String.to_integer(System.get_env("PORT") || "4000")]
A Dockerfile in your repository root always takes priority over auto-detection. See the Custom Dockerfile guide for build caching and more.
Platform behavior
These rules apply to every app deployed on Temps, regardless of framework.
The one requirement: your app must listen on the port in the PORT environment variable and bind to 0.0.0.0 — not localhost or 127.0.0.1. Temps runs your app in a container and routes traffic from the host, so an app bound to localhost only accepts connections from inside the container and will fail its health check.
Health checks
After your container starts, Temps sends HTTP GET requests to verify it is healthy before routing traffic to it.
- Path:
/(the root of your application) - Success: 2 consecutive responses with a 2xx or 3xx status code
- Timeout: 300 seconds (5 minutes) for the app to become healthy
- Retry interval: every 5 seconds
Connection errors while the app is still starting are retried without penalty. If the app returns 4xx or 5xx errors for 60 consecutive seconds, the deployment fails. Customize the check by adding a .temps.yaml to your repository root:
health:
path: /health
status: 200
interval: 30
timeout: 5
retries: 3/health endpoint that returns a simple 200. This avoids issues where / requires authentication or returns a redirect.Auto-injected environment variables
Temps injects these variables into every deployment automatically:
| Variable | Value | Description |
|---|---|---|
PORT | Resolved port | The port your app must listen on |
HOST | 0.0.0.0 | Bind address |
SENTRY_DSN | Auto-generated | Error tracking endpoint |
TEMPS_API_URL | Your Temps URL | Platform API endpoint |
TEMPS_API_TOKEN | Deployment token | Authentication for Temps SDKs |
OTEL_EXPORTER_OTLP_ENDPOINT | Your Temps OTLP URL | OpenTelemetry trace collection |
OTEL_SERVICE_NAME | Project name | Service identifier for traces |
You do not need to configure these manually. They are available in process.env (Node.js), os.environ (Python), os.Getenv (Go), and the equivalent in other languages.