Deploy a static site
A static app is files. The CLI packs a directory, uploads the archive, and waits until https://<slug>.tori.cloud serves those files. Nothing runs in a container, so environment variables do not apply. The CLI refuses tori env set on a static site; see Environment variables.
An app is static or a service for its whole life. A static site cannot later become a service. Create a new app with --service or --image in a directory that has no tori.json if you need a container — see Deploy a container service.
Directory deploys
Section titled “Directory deploys”From the project root:
npx tori.hostor, with an explicit directory:
npx tori.host deploy ./distDetection, when you omit the directory, is documented in the quickstart. Flags live on tori deploy.
The first deploy writes tori.json with the app slug. Later deploys from that directory update the same app. Put tori.json in git; do not hand-edit the slug to a name you do not own.
Sign-in on the deploy path
Section titled “Sign-in on the deploy path”If the machine has no saved token, deploy opens a browser (or prints a device code). In CI set TORI_TOKEN. Revoke a token in the console under Settings → API tokens. See Sign in.
Uploads
Section titled “Uploads”The upload can take minutes on a slow link. The progress line on stderr is how you tell a wait from a hang; when stderr is a pipe (CI), progress is periodic lines instead.
Archives over the CLI’s local size cap are refused before the request starts. The server also enforces the plan’s artefact limit, a per-file size cap, and a limit on how many members the archive may contain. A single file that is too large fails after upload with a reason such as artifact contains a file larger than 64 MB. Unsafe paths (.., absolute names) are refused the same way.
A very slow upload can be closed by the API with HTTP 408 before the last byte arrives. That is a server request deadline, not a broken connection. Retry from a faster link; nothing was deployed.
When it is live
Section titled “When it is live”live means the files of this deploy are the ones the URL serves. Ctrl+C stops watching; it does not cancel an upload that already finished. There is no separate “promote” step.
If another deploy of the same app is already in progress, the server refuses the new upload with HTTP 409 and nothing is sent. Wait, or inspect it with npx tori.host deploy status.
In the console, open the app → deploys for the same history. Rollback is offered there for a previous static deploy whose files have not been reclaimed yet.
Custom hostnames
Section titled “Custom hostnames”An app can use a hostname you already own if the plan includes custom hostnames. The console hides Add domain when the plan has none; the API refuses with a message that names the plan. tori whoami and Settings show the plan.
When the plan allows it:
- In the console, open the app → domains, or run
npx tori.host domains add www.example.comfrom the directory that holdstori.json. - Create the DNS record the command prints — a CNAME to the app’s
*.tori.cloudname for a subdomain, or an A record to the zone’s addresses for a two-label name. npx tori.host domains check www.example.comre-runs the check (at most once per 30 seconds). A certificate is issued only after the record points here.
See tori domains for flags. Do not point a hostname at Tori until the add command has reserved it — the printed record is the one to create.
export TORI_TOKEN=tori_… # Settings → API tokensnpx tori.host deploy ./distProgress becomes periodic lines because stderr is not a terminal. The deploy still waits until the URL is live.
See tori deploy for flags and the API for the HTTP side of the same flow.
Download this page as Markdown.