Deploy from your computer
eutonomous login # opens the browser; approve the code, the key is stored for you
eutonomous deploy # uploads this project, installs it, serves it at your environment's /
That is the whole loop. The first deploy asks which environment to use (or takes the only
one), remembers it in .eutonomous/project.toml, and sets the environment up for deploys,
which takes under a minute, once. After that a deploy is an upload, an install and a switch
to the new release.
Install
Python 3.11 or newer, nothing else:
uv tool install eutonomous # or: pipx install eutonomous
What your project needs
A pixi.toml with a serve task that starts the app on $HOST and $PORT:
[tasks]
serve = "fastapi run main.py --host $HOST --port $PORT"
No pixi.toml yet? eutonomous init writes one. A FastAPI app (main.py or app.py with
FastAPI() is detected, and requirements.txt becomes the PyPI dependencies. You can also
pass the command once with eutonomous deploy --cmd "…"; it is remembered for the next
deploy.
The app must listen on $PORT, not on a fixed port. During a deploy the new release runs
next to the old one for a moment, each on its own port.
Version control, local environments, caches, node_modules and .env files are never
uploaded. List more in a .eutonomousignore (data/, *.log, …). An upload can be up to
256 MB.
Every deploy is a release
A new release starts next to the one that is live and takes over only once it answers HTTP
(within 90 seconds; --wait changes that), so visitors never see a gap. If it does not
start, the live release was never touched, and the new one’s log lines are printed. A
rollback and a change of variables work the same way.
eutonomous logs -f # the app's output, as it happens
eutonomous releases # what was deployed; * is live
eutonomous rollback # back to the previous release
eutonomous open # the app in your browser
eutonomous exec -- ls apps # any command in the environment
The platform’s Apps page shows the same in the browser: each app’s releases with a roll-back button, and its variables.
More than one process
A Procfile in the project names processes that run next to the web process: a worker, a
scheduler, a queue consumer.
worker: pixi run worker
clock: pixi run python jobs.py
Each line is name: command, run in the project’s environment with the app’s variables.
The processes belong to the live release. A deploy, a rollback or a change of variables
restarts them on the new release, after the web process has switched, so a release that does
not start never touches them. They are restarted if they exit, and come back with the
workspace after it sleeps. A web: line, if you write one, replaces the serve task.
eutonomous ps # web and each process, and whether it is running
eutonomous logs -p worker # one process's output; add -f to follow it
eutonomous logs --grep "timeout" # search the output that is kept
Output is kept per process, up to about 60 MB each, oldest dropped first. A sleeping workspace runs nothing, so a job that must run at a set time needs the workspace always on.
Requests and response times
eutonomous metrics # the last hour
eutonomous metrics -m 15 # the last 15 minutes
How many requests the app answered, how many failed with a server error, the response times (median, 95th and 99th percentile) and the busiest and slowest paths. The timings are taken inside the workspace, directly in front of your app. They are recorded from the first request after a deploy.
A new account
There is no free trial. An account creates its first workspace after buying credits, and nothing is charged while a workspace sleeps.
How big a workspace is
A workspace has 2 CPUs and 4 GB of memory. A process that needs more memory than that is stopped by the workspace, not by its neighbours: every workspace has its own ceiling.
Variables and secrets
eutonomous env set DATABASE_URL=postgres://… DEBUG=0
eutonomous env set API_TOKEN # asks for the value, so it stays out of your shell history
eutonomous env set -f .env # everything in a .env file
eutonomous env list # names only; values are never shown again
eutonomous env unset DEBUG
The app sees them as ordinary environment variables. Setting or removing one restarts the app without a gap; if the app does not start with the new values, it keeps running with the old ones and the command reports the failure.
Values are stored inside your environment and nowhere else, not on the platform. They survive deploys, rollbacks and sleep.
Who can open it
eutonomous deploy # an environment's first deploy is private
eutonomous deploy --public # anyone with the link
eutonomous deploy --private # only you and the environment's members, after signing in
eutonomous access # which one it is now
eutonomous access public # or: private
Private means behind the eutonomous login: only you and the people you invited to the environment get in. After the first deploy, a deploy without either flag leaves access as it is. It is the same switch as the platform’s Access page, and a change applies within 15 seconds.
Your own domain
eutonomous domains # your domains, and the address to point them at
eutonomous domains add app.example.com # after its A record points there
eutonomous domains remove app.example.com
- Run
eutonomous domains. It shows the address your environment is served from. - At your DNS provider, create an A record for the name with that address.
- Run
eutonomous domains add app.example.com.
The platform gets a certificate for the name, which takes about a minute, and serves your app there over HTTPS. Public or private, sleeping and waking work the same as on the environment’s own address. If the certificate cannot be issued, the domain is not added and the command says why; the usual cause is an A record that does not point to the address yet.
Sleeping and always on
A workspace sleeps when nobody has used it for a while and is not billed for awake time while it sleeps. The next request wakes it:
- a browser sees a “Waking up” page that turns into your app by itself a few seconds later;
- an API client gets
503withRetry-After: 5, which most HTTP clients retry on.
Only a request that is allowed in wakes it. For a private app, that means a signed-in member.
eutonomous always-on on # keep it awake around the clock (billed while awake)
eutonomous always-on off # back to sleeping when idle (the default)
A classic environment is always on. It never sleeps, so there is nothing to switch.
As a container image
The same project can run outside a workspace, on any container platform:
eutonomous image # writes a Dockerfile and a .dockerignore
eutonomous image --build -t my-api # ...and builds it with docker or podman
docker run --rm -p 8000:8000 my-api
The image holds the same pixi environment (from pixi.lock, if the project has one) and
starts the same serve task. It runs as an unprivileged user and listens on port 8000.
Variables you set with eutonomous env set are not in the image; pass them to the
container where you run it. The image starts the web process only; run a Procfile
process as a second container with its command.
The serve task must use $HOST for the address, as eutonomous init writes it. A workspace
sets it to 127.0.0.1, because the app sits behind the workspace’s proxy; the image sets
it to 0.0.0.0.
Commands
| Command | What it does |
|---|---|
eutonomous login | sign in through the browser and store a key |
eutonomous logout | revoke the key and forget it |
eutonomous whoami | who the key belongs to, what it may do, when it expires |
eutonomous init | write a pixi.toml for a project that has none |
eutonomous deploy | upload the project and make it the live release |
eutonomous releases | list releases; * is live |
eutonomous rollback | go back to the previous release |
eutonomous logs | the app’s output; -f follows, -n sets the number of lines, -p picks a process, --grep searches |
eutonomous ps | the app’s processes and whether each is running |
eutonomous exec -- <command> | run a command in the environment |
eutonomous open | open the app in the browser |
eutonomous env set, unset, list | variables and secrets |
eutonomous access | show or set public or private |
eutonomous domains | list, add or remove your own domains |
eutonomous always-on on, off | keep a workspace awake, or let it sleep |
eutonomous sleep | put the workspace to sleep now |
eutonomous envs | your environments |
eutonomous link [env] | choose the environment this project deploys to |
eutonomous create [name] | a new workspace; --link makes it this project’s |
eutonomous delete <env> | delete a workspace and every file in it (asks first; --yes skips the question) |
eutonomous git | connect <repo>, status, deploy, disconnect, see Deploy from Git |
eutonomous image | write a Dockerfile for the project; --build -t <tag> builds it |
eutonomous snapshot | create, list, restore, delete, see Snapshots |
eutonomous mcp | your workspaces as tools for an AI agent, see For AI agents |
Every command that works on an environment takes --env <id or name>; without it, the
environment linked in .eutonomous/project.toml is used.