Workspaces Docs

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
  1. Run eutonomous domains. It shows the address your environment is served from.
  2. At your DNS provider, create an A record for the name with that address.
  3. 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 503 with Retry-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

CommandWhat it does
eutonomous loginsign in through the browser and store a key
eutonomous logoutrevoke the key and forget it
eutonomous whoamiwho the key belongs to, what it may do, when it expires
eutonomous initwrite a pixi.toml for a project that has none
eutonomous deployupload the project and make it the live release
eutonomous releaseslist releases; * is live
eutonomous rollbackgo back to the previous release
eutonomous logsthe app’s output; -f follows, -n sets the number of lines, -p picks a process, --grep searches
eutonomous psthe app’s processes and whether each is running
eutonomous exec -- <command>run a command in the environment
eutonomous openopen the app in the browser
eutonomous env set, unset, listvariables and secrets
eutonomous accessshow or set public or private
eutonomous domainslist, add or remove your own domains
eutonomous always-on on, offkeep a workspace awake, or let it sleep
eutonomous sleepput the workspace to sleep now
eutonomous envsyour 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 gitconnect <repo>, status, deploy, disconnect, see Deploy from Git
eutonomous imagewrite a Dockerfile for the project; --build -t <tag> builds it
eutonomous snapshotcreate, list, restore, delete, see Snapshots
eutonomous mcpyour 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.