Build

Deploy a Next.js app on Aria

A complete aria.yaml for a Next.js app with Postgres: build-time variables, migrations, health check, domain, and the commands to deploy and check it.

Updated Markdown

In this page
  1. What does the stack file look like?
  2. What does each part do?
  3. Can I use a Dockerfile instead?
  4. What if my app is in a monorepo?
  5. Are there more examples?
  6. How do I deploy it?
  7. Which plan do I need?

To deploy a Next.js app on Aria, describe it as one web service in aria.yaml, add a Postgres database, wire DATABASE_URL with from: main.url, and mark any NEXT_PUBLIC_ variable your build reads. Aria then builds the app, runs your migration command, starts it and checks that it answers. Next.js runs as an ordinary long-running Node server on your own VPS.

What does the stack file look like?

YAML
version: 1
name: my-next-app
services:
  web:
    type: web
    framework: nextjs
    install: npm ci
    build: npm run build
    start: npm start
    port: 3000
    healthcheck: /api/health
    migrate: npx prisma migrate deploy
    domain: "@"
databases:
  main:
    type: postgres
env:
  DATABASE_URL:
    services: [web]
    from: main.url
  AUTH_SECRET:
    services: [web]
    generate: secret
  NEXT_PUBLIC_SITE_NAME:
    services: [web]
    value: My app
    build: true
  STRIPE_SECRET_KEY:
    services: [web]
    required: true
    secret: true
    description: Stripe secret key, from the Stripe dashboard
resources:
  users: 200

Swap npx prisma migrate deploy for your own migration command, or remove migrate if your app creates tables another way. Every field is explained in the aria.yaml reference.

What does each part do?

  • framework: nextjs is a hint for sizing. A Next.js build needs more memory than a small API, and Aria counts that when it suggests a plan.
  • install, build and start run when there is no Dockerfile. Each is one line.
  • port: 3000 is the port Aria routes to. Aria sets PORT to it, and next start reads it and listens on all interfaces by default.
  • healthcheck is a path your app answers quickly with a 2xx and no login. Create a route at /api/health that returns “ok”, or use / if your home page is public.
  • migrate runs once per deploy, in the newly built image, before the new version takes traffic. If it fails, the old version keeps serving.
  • domain: "@" asks for your main domain when you connect one. See Domains.
  • NEXT_PUBLIC_SITE_NAME is read while the app builds, so it needs build: true. Names that start with NEXT_PUBLIC_ are passed at build time automatically, and anyone who visits the site can read them. Never wire a secret into one.
  • STRIPE_SECRET_KEY is required and secret. The service waits until you enter it with aria env add STRIPE_SECRET_KEY. See Environment variables.

Can I use a Dockerfile instead?

Yes. Set dockerfile and Aria ignores install, build and start. Declare every variable the build reads with ARG:

Dockerfile
FROM node:22-alpine
WORKDIR /app
ARG NEXT_PUBLIC_SITE_NAME
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
ENV NODE_ENV=production
CMD ["npm", "start"]
YAML
services:
  web:
    type: web
    dockerfile: Dockerfile
    port: 3000
    healthcheck: /api/health

What if my app is in a monorepo?

Set path to the app’s folder and context to the root of the workspace, so the build can see shared packages. The commands then run from that root:

YAML
services:
  web:
    type: web
    path: apps/web
    context: .
    build: pnpm install --frozen-lockfile && pnpm --filter web... build
    start: pnpm --filter web start
    port: 3000

A push rebuilds a service only when files under its path change, plus the root files such as the lockfile when context is .. Code in a shared package outside every service’s path rebuilds nothing, so run aria deploy after changing it. A monorepo build needs more memory, and Aria counts that too.

Are there more examples?

Two whole stacks are written out in the aria.yaml reference: a three-service stack with Postgres and Redis, and a web app on self-hosted Supabase, which passes NEXT_PUBLIC_ variables into a Dockerfile build.

How do I deploy it?

Aria AI can write the file for you during setup. Otherwise commit aria.yaml and push. Once the app is live, a push redeploys the services that the commit touched. For the first launch, or to apply a changed aria.yaml that you did not push:

Terminal
aria deploy --wait
aria check
aria open

aria deploy web deploys one service. If something fails, aria logs web --lines 200 shows its recent output.

Which plan do I need?

Aria estimates your stack’s memory from aria.yaml and recommends the smallest plan that fits, with room for builds. For the file above, with Postgres, the estimate is about 4.0 GB, which just fits the Starter plan. Add Redis and it is about 4.2 GB, which needs Developer. The plan table is on the billing page, and prices are on pricing.

For the reasoning behind running Next.js on your own server, read Deploy Next.js on your own server. If your app came from an AI builder, read Deploy a vibe-coded app.

Account · Terms

We’ve updated our terms.

Please read and accept the current terms of service and privacy policy to keep using Aria.