Quickstart — your first deploy

Five minutes from "I have an installed Paas" to "my app is live at a URL." This walks through the dashboard + CLI hybrid; everything done here can also be done purely via the REST API.

0. Prerequisites

  • Paas is installed and you can sign in to the dashboard.
  • Your local SSH public key is registered (Account → SSH keys).
  • You have a small app with a Dockerfile that listens on a port via $PORT (default 8080).

A minimal sample app:

# Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY . .
RUN echo 'console.log("hello")' > index.js && \
    cat > server.js <<'EOF'
const http = require('http');
http.createServer((req, res) => {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(`hello from ${process.env.PAAS_RELEASE}\n`);
}).listen(process.env.PORT || 8080);
EOF
CMD ["node", "server.js"]
git init
git add Dockerfile
git commit -m "first commit"

1. Create an organization

Dashboard → Orgs → fill in slug acme and display name Acme.

2. Create a project

acmeprojects → fill in slug storefront. A production environment (deploys from the main branch) is auto-created. See Projects & environments for adding staging / preview / etc.

3. Create an app

acmestorefrontCreate app. Slug web, port 8080. The page returns the clone URL:

git@git.example.com:acme/storefront/web.git

(Substitute your PAAS_GIT_PUBLIC_HOST and the SSH port if you changed PAAS_GIT_SSH_PORT from 2222.)

4. Push

git remote add paas ssh://git@git.example.com:2222/acme/storefront/web.git
git push paas main

The push prints something like:

[paas] sending push: branch=main sha=a1b2c3d
[paas] queued: env=production deployment=1f8a3b21-…

If you push a branch that doesn't match any environment's BranchPattern, you'll instead see [paas] skipped: no environment matches branch '…' — that's normal. Add a matching environment if you want that branch to deploy.

5. Watch it deploy

Dashboard → acmestorefrontweb → click the production env tab. You'll see the deployment go from QueuedBuildingBuiltReleasingLive. The Live logs panel streams as soon as a healthy container is running.

6. Visit it

The auto-assigned URL is http://acme.storefront-web-production.apps.example.com. The first request after a deploy may show a brief 502 while nginx finishes its reload — the Orchestrator only swaps the upstream after the new container is healthy.

What happens under the hood

git push ──▶ git-server hook ──▶ POST /internal/git/post-receive
                                   │
                                   ▼
                            Deployment(Queued)
                                   │
                                   ▼ (Builder polls)
                       git clone + docker build + docker push
                                   │
                                   ▼
                             Deployment(Built) → Release(N)
                                   │
                                   ▼ (Orchestrator reconciles)
                  start container; HTTP probe on / ; mark Healthy
                                   │
                                   ▼ (ProxyController reacts)
                  rewrite /etc/nginx/conf.d/web-acme.apps.example.com.conf
                  nginx -t && nginx -s reload
                                   │
                                   ▼
                           https://web-acme.apps.example.com  →  ✨

What's next