Documentation Index
Fetch the complete documentation index at: https://docs.capy.sc/llms.txt
Use this file to discover all available pages before exploring further.
Fly Machines are long-running containers. Same pattern as Docker: capy run wraps your process, and flyctl secrets set puts SECRETS_BLOB and PROJECT_KEY into the Machine’s env.
Dockerfile
FROM node:22-slim
WORKDIR /app
RUN npm install -g @capy/cli
COPY package.json bun.lock ./
RUN bun install --production
COPY . .
EXPOSE 3000
ENTRYPOINT ["capy", "run", "--"]
CMD ["node", "server.js"]
fly.toml
app = "my-app"
primary_region = "sjc"
[build]
[http_service]
internal_port = 3000
force_https = true
[[vm]]
memory = "512mb"
cpu_kind = "shared"
No special Fly config needed - standard http_service on the port your app listens on.
Setting secrets
capy deploy # pick Fly.io; copy the printed values
flyctl secrets set \
SECRETS_BLOB="<value-from-capy-deploy>" \
PROJECT_KEY="<value-from-capy-deploy>"
Fly restarts the Machines automatically after flyctl secrets set. The first boot under the new deploy code calls Capy’s service once, caches the decrypted env for the Machine’s lifetime, and serves traffic.
Deploying
That’s it. The image has capy run as its entrypoint; Fly has the deploy-code secrets; every new Machine decrypts at boot.
Verifying
Shell into a running Machine and inspect its env:
flyctl ssh console
# Inside the Machine:
env | grep -E "DATABASE_URL|STRIPE" # should show plaintext
SECRETS_BLOB and PROJECT_KEY are still set too - capy run passes the parent env through to the child.
Revocation
Revoke the deploy token → next Machine boot fails to decrypt, Fly’s health checks flag the bad rollout, traffic stays on the previous Machines. Rotate the project key instead if you need to kill all running Machines’ ability to decrypt.