Yuki Deploy Dashboard

Yuki Deploy docs

Yuki Deploy builds your code into a container and runs it at name.deploy.yukichat.lol with its own HTTPS certificate. You sign in with YukiChat.

Quick start

# 1. install the CLI (macOS, Linux, WSL)
curl -fsSL deploy.yukichat.lol/install | sh

# 2. log in: approve the code in your browser
yd login

# 3. deploy from your project folder
cd my-app
yd

The first yd asks for a name and saves it in .yukideploy, so the next deploys go to the same app. You can also upload a .zip or import a Git repo from the dashboard.

The one rule: your app must listen on 0.0.0.0 at the port in $PORT (8080 unless you change it). localhost won't be reachable.

CLI

CommandWhat it does
yd [folder]Pack the folder (skipping node_modules, .git, .env, virtualenvs) and deploy it. Follows the build log.
yd lsYour apps and their state.
yd logs [-f] [--tail N]App output; -f keeps following.
yd env · set K=V · rm KEnvironment variables. REVEAL=1 yd env prints values.
yd restart | stop | startControl the running container.
yd rollbackPut the previous build back live (no rebuild).
yd git <url> [branch]Build from a public Git repo instead of local files.
yd open · yd rmOpen the app, or delete it with its data.

Every command takes --name <app>. Add a .ydignore (tar exclude patterns, one per line) to skip more files. In CI, set YD_TOKEN to an API token from the dashboard menu.

Runtimes

If there's no Dockerfile, the stack is detected from the files at the root:

FoundBuildStart
DockerfileYour DockerfileIts CMD. Port from EXPOSE, else 8080.
package.jsonNode 20: npm ci / pnpm / yarn by lockfile, then the build scriptstart script, else main/server.js/index.js. No server at all? The build output (dist, build, out) is served as a static SPA.
requirements.txt / pyproject.tomlPython 3.12, pip installFastAPI → uvicorn main:app, Flask → gunicorn app:app, Django → gunicorn project.wsgi, else python main.py. A Procfile web: line wins.
index.htmlnoneStatic files. For static-only sites, Yuki Pages is lighter.

yuki.json

Optional, at the project root. Every field is optional:

{
  "runtime": "node",            // node | python | static | docker
  "build": "npm run build:prod",
  "start": "node dist/server.js",
  "port": 3000
}

The start command and port can also be set in the dashboard under Settings → Advanced.

Env vars and /data

Set variables in the dashboard or with yd env set. They apply on the next deploy or restart. These are always set: PORT, YUKI_APP (the app name) and YUKI_URL (its public URL).

/data is a disk that survives deploys and restarts (512 MB). Put SQLite files and uploads there; everything else in the container resets on each deploy.

Sleep and wake

When an app gets no requests for its sleep time (15 minutes by default), its container stops. The next request starts it again and waits until it answers, usually one or two seconds. Background jobs and bots that only poll stop while asleep. If an app crashes on start, visitors see a "crashed" page and the logs show why.

Deploys swap with no downtime: the new container must answer HTTP within 60 seconds before traffic moves to it. If it doesn't, the old one stays live and the deploy is marked failed.

Git and webhooks

Connect a public https repo (GitHub, GitLab, Codeberg…) when you create the app or in Settings. The dashboard then shows a webhook URL. In GitHub: Settings → Webhooks → Add webhook, paste it as the Payload URL, pick application/json and "Just the push event". Pushes to other branches are ignored.

HTTP API

Base URL https://deploy.yukichat.lol. Send Authorization: Bearer yd_… (a token from the dashboard menu or yd login). Errors come back as {"detail": "…"}.

RequestWhat it does
GET /api/meYou, your apps and your limits
POST /api/apps{"name", "git_url"?, "git_branch"?}, creates the app (and builds when there's a repo)
GET /api/apps/{name}One app: state, URL, settings
PATCH /api/apps/{name}memory, sleep_min, start_cmd, app_port, git_url, git_branch, new_hook
DELETE /api/apps/{name}Delete the app, its images and /data
POST /api/apps/{name}/deployBody: a .tar.gz or .zip (any content type), or JSON {"git_url"?, "git_branch"?}. ?create=1 makes the app if needed, ?message= labels it. Returns {"id"}.
GET /api/apps/{name}/deploymentsLast 30 deployments
GET /api/deployments/{id}?offset=NStatus and build log from byte N. Poll with the returned offset. &fmt=text gives plain text with X-Status/X-Offset headers.
POST /api/apps/{name}/rollback{"deployment": id}, reuses that build's image
POST /api/apps/{name}/restart|stop|startContainer control
GET /api/apps/{name}/logs?tail=300App output (plain text)
GET /api/apps/{name}/statsCPU, memory, network of the running container
GET|PUT /api/apps/{name}/envPUT {"set": {K: V}, "unset": [K]} or {"env": {…}} to replace all
POST /api/hooks/{name}/{key}Push webhook (no token; the key is the secret)
# deploy a folder from CI
tar -czf app.tar.gz --exclude=node_modules --exclude=.git .
curl -fsS -X POST -H "Authorization: Bearer $YD_TOKEN" \
  --data-binary @app.tar.gz \
  "https://deploy.yukichat.lol/api/apps/my-app/deploy?message=ci"

Limits

WhatLimit
Apps per account3
Memory128 or 256 MB, 0.5 CPU
Sleep after idle5–60 minutes
Build10 minutes, 1 GB memory, one build at a time on the server (others queue)
Upload50 MB packed, 250 MB / 20,000 files unpacked
Image1.5 GB
/data512 MB (the app is paused when it's over)
NetworkOutbound internet only: no host, private ranges, other apps or port 25

Phishing, crypto miners, spam, proxies for abuse and anything illegal get disabled without notice.