How Apps run
What an App is on Basemodo: one machine with its own disk, the port it must answer on, how it sleeps and wakes, and what it may reach.
One App, one machine
Every App runs on its own machine (a small virtual machine), with its own disk at /data. Its Processes share the machine: web, which answers HTTP, and any workers and cron entries you declare. No other App runs on it, and Apps cannot reach each other.
Basemodo gives every Process these environment variables, besides your Secrets:
| Variable | What it holds |
|---|---|
PORT | The port the web Process must listen on. |
BASEMODO_DATA | /data, the App's disk: what is written there survives every Deploy. |
BASEMODO_DB | /data/app.db, the App's SQLite database. |
BASEMODO_JWT_PUBLIC_KEY | The key to verify the identity token with. |
Processes, and commands run with basemodo run and basemodo db, never run as root: they run as your image's own USER, or, when the image runs as root (every image Basemodo builds), as an unprivileged user of Basemodo's (uid 10000). That user owns /data (and, in images Basemodo builds, the App's folder) and may write in /tmp; it may listen on any port, 80 too. If your own Dockerfile writes elsewhere while it runs, give what it writes to its USER (COPY --chown, RUN chown), or set USER to the user that owns it: a Process denied permission gets a line in the Logs that says so.
The Port Contract
The web Process must listen on the port in $PORT, on every interface (0.0.0.0, not localhost), and answer HTTP. Its first answer, whatever it is, within 60 seconds of starting means the App is ready, and only then does a Deploy go live. There is nothing else to configure: no health check, no exposed port.
Apps Basemodo detects keep this contract by themselves. If you start your App yourself (with web.command or your own Dockerfile), read the port from the environment, as in app.listen(process.env.PORT ?? 3000, "0.0.0.0"). EXPOSE in a Dockerfile does not change the port. An App that never answers fails its Deploy with not_ready.
Sleep and wake
An App nobody uses for 10 minutes falls asleep: its machine stops, its disk stays, and it costs nothing. The next visit wakes it: Basemodo holds that request for the few seconds the App takes to start, then passes it on. Nobody sees an error. Only requests that get in count as use, so strangers hitting the sign-in page of a Private App never keep it awake, but a webhook on a Public Path does wake it.
basemodo status says whether an App is awake, asleep or starting, or paused: stopped by Basemodo because a worker kept crashing (or by its Plan), with the reason, until it is deployed again or restarted. A worker keeps an App awake.
basemodo restart starts an App's machine again on its live Deploy, without building: use it to apply Secrets you just set (every start reads them, waking from sleep included), or to resume an App paused because a worker kept crashing or ran out of memory or disk once you fixed the cause. An App paused until its Owner chooses a Plan, or for review, stays paused.
Logs
What your Processes print (stdout and stderr) and what each build prints are kept as the App's Logs for 7 days, 30 on Pro and Workspace (Plans). Follow them live with basemodo logs, or see the latest on the App's page.
The network
- In: only through Basemodo. Every request reaches the App through Basemodo's gate, which signs visitors in, applies the App's Visibility, adds the identity headers and limits floods. The machine has no public address of its own.
- Out: open by default, so your App can call any API. Basemodo blocks itself (basemodo.com and its internal networks), the provider's metadata service, private network ranges, other Apps' machines (call another App at its URL instead) and outgoing email over SMTP ports 25, 465 and 587 (send email through an email API instead). Apps a Workspace owns can be limited to a list of hosts with
network.allow; the blocks still apply to the hosts listed. A personal App's Deploy withnetwork.allowis refused, since the allowlist comes with the Workspace plan. The App's names are resolved by Basemodo inside its machine: names it may not reach are refused there, and other DNS servers are not reachable.
Addresses and search engines
Apps answer at https://<name>.basemodo.app, a domain apart from basemodo.com. Paths under /.basemodo/ belong to Basemodo (the sign-in) and never reach your App. Apps are never indexed by search engines unless a Public App asks to be (see Sharing).