Deploy to Pinecall
pinecall deploy: Pinecall installs and runs your project. Secrets, limits, logs, rollbacks.
pinecall deploy uploads your project, and Pinecall installs it and keeps pinecall start running
for you in an isolated container. There is no server to rent, no process manager and no token to
paste.
How it works#
Each upload is a release of an app: numbered from 1 and never edited. The release before keeps answering until the new one's agents have registered, so a deploy cuts no call.
.gitignore files leave it, installed from your lockfile.
SecretsThe environment variables your code reads, set apart from the code.
LimitsWhat a hosted app may use and reach.
Every dayLogs, rollbacks, stop and start.
~/acme-support $ pinecall deploy --prod
acme-support: release 1 sent · 38 KB · 3b507661b052
acme-support: release 1 is live
Without --prod, everything on this page acts on the sandbox. The sandbox and production have
separate apps, releases and secrets.
Before the first deploy#
- A TypeScript project in the layout
pinecall newwrites:agents/<name>/at the root, apackage.jsonand atsconfig.json. A Ruby or Python agent runs on your own server. @pinecall/agentsunderdependencies. Pinecall installs production dependencies only, and starts the project with its ownpinecall start: the CLI is never a dependency of the project.pinecall deployrefuses a project that does not list the framework there, before it sends anything.- A committed lockfile.
pnpm-lock.yamlis installed withpnpm install --frozen-lockfile --prod,package-lock.jsonwithnpm ci --omit=dev. With neither,npm install --omit=devresolvespackage.jsonagain on every release. - No build step.
pinecall startreads your.tsxfiles directly. Apps run on the officialnode:24-slimimage, which has no compiler: use packages with prebuilt linux-x64 binaries. - A key that may deploy: one that opens
app(the developer and admin roles), and for--prod, your production switch on.
The app's name is the folder's, or --name: lower-case words and dashes, 40 characters at most.
The first upload makes the app, within the org's number of hosted apps there.
What happens when you deploy#
Packed#
The folder is packed as its .gitignore files leave it, each read where it sits; git is not asked,
so a folder that is no checkout packs the same.
node_modules/, .git/, dist/, .pinecall/, .DS_Store and every .env stay on your machine.
A release is at most 10 MiB packed, 100 MiB unpacked and 5,000 files; a symbolic link or a path
outside the folder is refused.
Kept#
The gateway keeps the release. The first one also mints a server token for the app, listed in the
console's Tokens as hosted app <name>. Nobody ever sees its value.
Installed#
The dependencies are installed inside the same sandbox the app runs in, with 1 GiB of memory and 300 seconds at most.
Live#
pinecall start (--prod in production) starts with your secrets, the app's token and the
gateway's address. Once its agents register, the release is live, and the one before drains: its
calls move to the new process and its running tools finish, within 45 seconds.
The verb follows all of it for up to eight minutes and prints release N is live (exit 0) or why
it failed (exit 1). --no-follow returns as soon as the release is kept.
A release fails when its install fails, when its process exits before its agents register, or when 120 seconds pass without a register. The release before keeps answering. A failed release is not tried again: fix it and deploy again.
Secrets#
.env never travels. Whatever your tools read from the environment is set as the org's secrets,
the sandbox's and production's apart:
$ printf %s "$CRM_TOKEN" | pinecall secrets set CRM_TOKEN --prod
CRM_TOKEN kept · the org's hosted apps here start again with it
Your code reads process.env.CRM_TOKEN as before. Every hosted app of the org there starts
with every secret. A name is capitals, digits and underscores and never starts with PINECALL_; a
value is 16 KB at most. Type the value or pipe it in, never on the command line. Nothing reads a
value back: pinecall secrets lists names, who set each and when. Setting or removing one restarts
every app of the org there, the old process answering until the new one registers.
| variable | set by |
|---|---|
| each of the org's secrets, the sandbox's or production's | pinecall secrets set, or the console's Agents ▸ Secrets |
PINECALL_KEY |
Pinecall: the app's own server token |
PINECALL_URL |
Pinecall: the gateway's address, the same for the sandbox and production |
HOME, TMPDIR |
/scratch |
NO_COLOR |
1 |
What an app may do#
| memory | 256 MiB for the process |
| CPU | half a core; a tool waiting on your API uses none of it |
| disk | the root filesystem and the project's folder are read-only. /scratch is 64 MiB in memory, emptied whenever the process starts again |
| network out | the internet, through public resolvers (1.1.1.1, 8.8.8.8). Never private ranges (10/8, 172.16/12, 192.168/16, 100.64/10) or link-local addresses, so a database reachable only inside your network is out of reach |
| network in | none. The agent's calls reach it over the socket it opens to the gateway |
Every app runs under gVisor, a kernel of its own between your code and the machine, on a cluster apart from the gateway's.
A deploy never pushes the knowledge base. Production's documents are written in the agent's Knowledge ▸ Docs on production's console, or pushed once with
pinecall docs push --prod, a separate step that replaces the base whole. See From sandbox to production.
Every day#
| command | what it does |
|---|---|
pinecall deploy list --prod |
every app of the org: live, on its way, failed and why, or stopped |
pinecall deploy releases --prod |
one app's releases, newest first: when, size, who, the note (--note on a deploy) |
pinecall deploy logs --prod [--follow] |
the last 300 lines the process printed, fetched fresh |
pinecall deploy rollback 3 --prod |
release 3's sources kept again as the next release, and started like any |
pinecall deploy stop --prod · start |
the process drains and nothing runs; start runs the newest release again |
pinecall deploy rm --prod |
the app removed: its releases deleted, its token revoked |
Each takes --name <app> outside the app's folder. The console shows the same under
Agents ▸ Apps. An app keeps its newest ten releases, and the one serving.
If a live process exits, Pinecall starts it again at once. After five exits in ten minutes it stops: the release is reported failed with its last lines, and the app answers nothing until the next release, a changed secret or a rollback.
From CI#
A pipeline deploys on a production server token from Settings ▸ Tokens, after the goldens:
# two steps of a GitHub Actions job, after checkout, setup-node 24 and npm ci
- run: npx pinecall test
env: { PINECALL_KEY: "${{ secrets.PINECALL_SANDBOX_TOKEN }}" }
- run: npx pinecall deploy --prod --name support-line --note "${{ github.sha }}"
env: { PINECALL_KEY: "${{ secrets.PINECALL_TOKEN }}" }