Dokumentasjon
Alt du trenger for å publisere.
Ny her? Start med den enkle guiden. Skriver du kode selv, finner du alle detaljene i den tekniske referansen.
Teknisk referanse
Dette trenger Hosait fra repoet ditt
Koble til et GitHub-repo, så finner Hosait ut hvordan det skal kjøres, bygger det isolert og serverer det på din egen adresse. Denne siden er alt plattformen forutsetter — så verken du eller Claude i repoet ditt trenger å gjette.
Getting started
- 1
Connect GitHub under Account → Connections. Hosait asks for repository access so it can read private repos and register a push webhook.
- 2
Start a new project, pick the repository and the branch. Hosait inspects it before anything is built and tells you what it found.
- 3
Fill in the required variables. They are read from your repo; for secret-shaped ones there is a Generate button so you never have to make one by hand.
- 4
Publish. From then on, every push to that branch deploys automatically, and the project page shows each deploy with its commit, its log and its outcome.
What Hosait detects
Without any configuration, Hosait looks at the repository and picks one of three ways to run it. A hosait.json file overrides the guess.
static
An index.html at the root or in a common output folder. If there is a build script, it is run first in an isolated container and the output is served.
node
A package.json with a start script and no static output. Built, then run as a container; the package manager is read from the lockfile.
compose
A docker-compose file. The whole stack is started — database, workers, one-shot jobs and all — and one service is chosen as the web front.
hosait.json
Optional. Put it at the root of the repository when detection guesses wrong or you want to be explicit. When present it wins over every heuristic; when present but invalid, the deploy fails loudly rather than guessing.
{
"runtime": "compose",
"compose": { "file": "docker-compose.yml", "web": "frontend" }
}
{
"runtime": "node",
"build": "npm run build",
"start": "node dist/server.js",
"port": 3000,
"migrate": "npx prisma migrate deploy"
}
| Field | Meaning |
|---|---|
| runtime | static, node or compose. The only required field. |
| build | Build command for static and node. Defaults to the package manager's build script. |
| output | Folder the build writes static files to (static only). |
| start | Start command (node only). Defaults to the package manager's start script. |
| port | The port the app listens on (node only). Hosait proxies to it. |
| migrate | A command run once before start, every deploy — migrations, seeds (node only). |
| compose.file | Which compose file to use, if not docker-compose.yml. |
| compose.web | The service that answers HTTP. Set it when the automatic choice is wrong. |
Docker Compose
A compose stack runs as-is. These are the conventions Hosait applies around it.
- Which service is the web front
- In order:
compose.webfrom hosait.json; then a service named web, frontend, proxy, nginx, caddy, www, app or gateway; then the first service that publishes a port; then the first service. Setcompose.webif that lands on the wrong one. - One-shot services are fine
- A migrate or seed service that runs and exits with 0 is not treated as a failure. Hosait only health-checks the web service. What does fail the stack is Compose itself, when a service declares depends_on with service_completed_successfully and that dependency exits non-zero.
- Published host ports are removed
- Hosait proxies straight to the container, so ports: entries are stripped before the stack starts. They would collide with the host, with other tenants, and a published database port would be exposed. You do not need to change your file.
- Volumes survive deploys
- Deploys are in place: named volumes and the compose project keep their identity, so your database is still there after a redeploy. Volumes are removed only when you delete the project.
- Until the first success, a failed deploy starts over
- A stack that has never been live has no data to protect, so a failed deploy removes its volumes too. The next attempt creates the database with the variables you have now. Once a deploy has succeeded, volumes are kept. The live database starts empty: users and data from your own machine do not come along.
- Required variables come from the file
- Every
${VAR}reference without a default is required, and publishing is blocked until it has a value. - Isolation
privileged,cap_add,network_mode: host,pid: host,devices,security_opt,sysctls,volumes_from, bind mounts outside the repository (including the docker socket), external volumes and networks, and secrets from host files are refused withcompose_unsafebefore anything is built. Every service runs withno-new-privilegesand a resource ceiling (1 GB RAM, 1 CPU, 512 processes by default).- Every path is yours
- On your address, every path — including /api — reaches your app. Hosait reserves nothing on a customer's domain.
Environment variables
- Values are masked everywhere in the interface; click the eye to reveal one.
- Secret-shaped names (PASSWORD, SECRET, KEY, TOKEN …) get a Generate button that produces a value of the right length.
- Saving variables does not restart anything by itself. Save and redeploy applies them.
- Do not change a database password after the first deploy. Postgres keeps the password its volume was created with; changing the variable alone locks the app out of its own database.
Deploys, logs and rollback
- Build locally with Docker before you push (docker compose build, or docker build for a Dockerfile). A deploy is a production build on a clean machine: it catches type errors, a lockfile out of sync and files that were never committed — and each of those is otherwise a failed deploy.
- Every deploy is a row in the project's history: who triggered it, which commit, how long it took, what happened.
- Logs are captured for successful runs too — build output, then what the app printed once it was up. A failure that happens before there is any output stores its reason instead.
- Hosait resolves the branch tip before fetching and deploys that exact commit, so the SHA it shows is the code that ran.
- A failed deploy never takes a working site down. The previous version keeps serving, and the failure is shown to you on the project page — not to your visitors.
- Roll back restores the previous version with one click. The button is shown only when one exists.
Operations reference
The facts an operator or an allow-list needs. Kept in English on purpose — these are values, not prose.
- Outbound IP address
- Every request your stack makes to the outside world leaves from one static address:
213.184.208.76(Norway). Put it in the allow-list of your database provider, payment API or on-prem service. It does not change between deploys. - Prebuilt images, no repository build
- A compose file whose services use
image:(from Docker Hub, GHCR or any public registry) deploys without building anything. Mix freely:build:for your own services,image:for the rest. Private images (on ghcr.io, Docker Hub, registry.gitlab.com or quay.io) work too, forimage:and for a Dockerfile'sFROM: add a username and an access token under the project's Settings → Private registries. The token is stored encrypted, used only for that project's deploys, and never shown again. Every deploy pulls the images again, so a re-pushed tag is picked up; a rollback uses the images already on the host. Pin to the commit: Hosait passesHOSAIT_COMMIT_SHA(andHOSAIT_COMMIT_SHORT) to the compose file, soimage: ghcr.io/acme/api:${HOSAIT_COMMIT_SHA}runs exactly what CI built for the deployed commit — also on restart and rollback. - Memory and CPU per service
- A service runs with what its compose file declares —
deploy.resources.limits.memoryand.cpus, or the oldermem_limitandcpus— and with 1 GB and 1 CPU when it declares nothing. Your plan caps each service and the whole project: Starter 2 GB / 2 CPUs per project (2 GB / 1 CPU per service), Pro 4 GB / 4 CPUs (4 GB / 2), Scale 16 GB / 8 CPUs (8 GB / 4). Above a cap nothing starts and the deploy fails withcompose_limits_exceeded, naming the service. Every undeclared service counts as 1 GB towards the total, so give small services small limits (nginx128m, redis256m). The new-project wizard checks the file against your plan before the first deploy and offers the plan that fits. - Prebuilt images from CI
- The request itself is described under Deploy API (CI). Two settings make it fit a pipeline that builds images: turn off Deploy automatically on push (Settings → Advanced), so a push does not deploy before CI has pushed the images; and tag the images with the commit,
image: ghcr.io/acme/api:${HOSAIT_COMMIT_SHA}, so the deploy runs exactly what CI built. A pinned deploy that only starts after a newer commit went live is recorded as skipped instead of putting the older commit back. - Build cache
- Builds run with BuildKit and share a layer cache per host. A layer whose inputs did not change is reused (
CACHEDin the deploy log); cache older than seven days and images nothing references are pruned daily. An unchanged stack redeploys in 12–50 s; a full rebuild takes as long as your Dockerfile does. - Private by default
- Exactly one service in a stack is reachable from the Internet: the web service (see Docker Compose above). Every other service — databases, workers, caches — is reachable only from inside the stack's own network.
ports:entries are removed before start, so nothing you publish by accident becomes public. The project page lists which service is public. - Health checks and restarts
- Compose honours your
healthcheck:andrestart:as written. Hosait health-checks the web service over HTTP at deploy time and proxies to it once it answers; a container that dies later is restarted by Docker according to its ownrestart:policy. - Data services: copy-paste snippets
- Any image runs, on a named volume. Redis:
image: redis:7-alpinewithcommand: ["redis-server", "--save", "60", "1"]andredis_data:/data. Meilisearch:image: getmeili/meilisearch:v1.10,MEILI_MASTER_KEY: ${MEILI_MASTER_KEY},meili_data:/meili_data. Object storage: use the built-in S3 endpoint (Settings → Storage) rather than running MinIO in your stack. Postgres: see the compose example above. - Custom domains
- Project page → Settings → Domains. Add any name, apex or subdomain; you keep the hosait.com address for ever. Ownership is proven by one TXT record (
_hosait.<name>); pointing is an A record to213.184.208.76for an apex or a CNAME tocustom.hosait.comfor a subdomain. Add these records and change nothing else in your zone — your MX, SPF and other verification records must stay. One name is primary; the others 308-redirect to it. The certificate can be issued before DNS moves: via a Domeneshop API token (issued and renewed automatically, DNS-01), by DNS delegation — one CNAME from_acme-challenge.<name>to a target underacme.hosait.com, after which Hosait issues and renews by itself — or by adding the_acme-challengeTXT records we show you; either way https works from the first request after the move. - Wildcard domains
- Add
*.example.comto serve every name one level under it — one subdomain per customer of a SaaS — with theHostheader intact, so your app picks the tenant from it. Three records: TXT_hosait.example.com(ownership), CNAME*.example.com→custom.hosait.com, and the_acme-challenge.example.comdelegation CNAME. A wildcard certificate can only be proven over DNS, so it comes through delegation (or a Domeneshop token) and renews automatically. An exact name always wins over a wildcard, anda.b.example.comis not covered by*.example.com. - Backups
- Every Postgres, MySQL, MariaDB and MongoDB service in a compose stack is dumped every night with its own tool, inside its container, then compressed and encrypted per project. Kept: 7 daily and 4 weekly copies (Scale: 14 daily, 8 weekly, 6 monthly). Settings → Backups lists them and offers Back up now, Download (the decrypted dump, yours to keep) and Restore, which takes a fresh safety copy first, stops the rest of the stack, loads the dump and starts the stack again. The dump runs with the official images' own credential variables (
POSTGRES_USER,MYSQL_ROOT_PASSWORD,MARIADB_ROOT_PASSWORD,MONGO_INITDB_ROOT_USERNAME). Copies are stored on Hosait's own servers in Norway; an off-site copy is planned. Deleting a project deletes its backups. - For agents
- This page in machine-readable form: llms.txt and the Hosait skill (Markdown, versioned, fetched live by the MCP server's
get_hosait_guide).
Connect your Claude Code
The Hosait MCP server lets the Claude Code in your repository inspect and operate the project it belongs to: status, deploys, logs, variables, redeploy, rollback, restart. It runs on your machine and talks to Hosait over HTTPS with a token scoped to one project.
- On the project page, open Settings → API tokens and create one. It is shown once.
- Register the server with Claude Code:
claude mcp add hosait --env HOSAIT_TOKEN=hosait_pat_… -- npx -y hosait-mcp-server
Teach your Claude the conventions on this page: install the Hosait skill, and Claude Code writes hosait.json, compose files and Dockerfiles the way Hosait expects — and knows what every error code means.
mkdir -p ~/.claude/skills/hosait && curl -fsSL -o ~/.claude/skills/hosait/SKILL.md https://hosait.com/skills/hosait/SKILL.md
Codex
codex mcp add hosait --env HOSAIT_TOKEN=hosait_pat_… -- npx -y hosait-mcp-server
codex mcp list
mkdir -p ~/.agents/skills/hosait && curl -fsSL -o ~/.agents/skills/hosait/SKILL.md https://hosait.com/skills/hosait/SKILL.md
ChatGPT
Add https://hosait.com/mcp as a custom MCP server in ChatGPT developer mode. When you use a project tool, sign in to Hosait, choose one project, and approve the permissions shown. The connection is listed under that project's Settings → API tokens, where you can revoke it at any time. Commands and other sensitive changes still ask for a separate approval in Hosait.
Deploy-API (CI)
Publiser fra din egen pipeline, for eksempel GitHub Actions når testene har gått gjennom. Lag et token med tillatelsen deploy under prosjektets Innstillinger → API-tokens, og lagre det som en hemmelighet i CI-en din (aldri i repoet).
POST /api/mcp/v1/redeploy publiserer siste commit på grenen prosjektet følger. Send {"ref": "<commit-SHA>"} for å sikre at akkurat den commiten – for eksempel den CI nettopp testet – er den som går live. Hosait sjekker først hos GitHub at commiten finnes, ligger på grenen prosjektet følger og fortsatt er den siste der; ellers startes ingenting (ref_not_found, ref_not_on_branch, ref_not_latest hvis en nyere commit er pushet – den publiseres av sin egen push). Vil du publisere en eldre commit med vilje, legger du til "allowOlder": true.
Svaret inneholder en deployId. Spør GET /api/mcp/v1/deploys/<deployId> med noen sekunders mellomrom til deploy.status er succeeded, failed eller rolled_back; hvis den feiler, forteller GET /api/mcp/v1/deploys/latest/diagnostics hvorfor.
# .github/workflows/publish.yml — after your tests
- name: Publish on Hosait
env:
HOSAIT_TOKEN: ${{ secrets.HOSAIT_TOKEN }}
run: |
id=$(curl -fsS -X POST https://hosait.com/api/mcp/v1/redeploy \
-H "Authorization: Bearer $HOSAIT_TOKEN" -H "Content-Type: application/json" \
-d "{\"ref\": \"${{ github.sha }}\"}" | jq -r .deployId)
[ -n "$id" ] && [ "$id" != null ] || exit 1
for i in $(seq 1 60); do
s=$(curl -fsS -H "Authorization: Bearer $HOSAIT_TOKEN" \
https://hosait.com/api/mcp/v1/deploys/$id | jq -r .deploy.status)
[ "$s" = succeeded ] && exit 0
case "$s" in failed|rolled_back) exit 1;; esac
sleep 10
done; exit 1
Ferdigbygde images: la compose-filen hente taggen fra en variabel, f.eks. image: ghcr.io/deg/app:${IMAGE_TAG}. Sett den med PATCH /api/mcp/v1/env (tillatelsen env:write) og kall deretter redeploy. Offentlige images på GHCR, Docker Hub og andre registre virker uten videre. Private images virker også: legg inn brukernavn og tilgangsnøkkel under prosjektets Innstillinger → Private registre.
Tools
| get_project_status | Status, address, deploy kind, source. |
| list_deploys | Recent deploys, newest first. |
| get_deploy | One deploy by id — poll it to wait for a run you started. |
| get_deploy_log | The captured log, secrets redacted. |
| get_env | Variable names; secret-looking values come back masked. |
| set_env | Set or update variables by key. Unmentioned keys are untouched; a masked value means keep what is stored. |
| delete_env | Remove one variable. |
| redeploy | Deploy the branch tip again. Returns the deploy id. |
| rollback | Restore the previous version. |
| restart | Restart the running app or stack without rebuilding. |
| get_runtime_logs | What the running app prints now — one service or all, last N lines, since a point in time, filtered by text or level. |
| run_task | Run one command in a compose service (migration, seed, script), time-limited; the output lands in the history. |
| get_task | One task by id — status, exit code and output. |
| list_services | The compose services and their state — the names run_task and the log filter take. |
| get_deploy_diagnostics | Why a deploy failed, in one answer: error code, missing variables, service states, rollback availability, log tail. |
| check_live_site | Request the public address now: status, latency, and whether a holding page answers. |
| get_domain_diagnostics | Per domain: records to add, a fresh DNS check and the certificate state. Read-only. |
| get_usage | Disk, memory and CPU now, and the ceiling each service runs under. |
| analyze_repository | What Hosait would run for a GitHub repository: runtime, start command, required variables, findings. Read-only. |
| connect_repository | Point a blank project at a repository, set its variables and deploy. The owner approves first. |
| set_maintenance | Maintenance mode on or off: the address shows a holding page while the app keeps running. |
Revoke the token from the same tab at any time; it stops working immediately.
Error codes
Every failed deploy carries a stable code alongside its explanation. The code is what to search for or paste into an AI tool; the text follows your language.
| github_connection_expired | |
| github_rate_limited | |
| github_forbidden | |
| github_unreachable | |
| repo_not_found | |
| branch_not_found | |
| no_repo | |
| builder_disabled | |
| build_failed | |
| no_build_output | |
| nothing_to_deploy | |
| compose_file_missing | |
| compose_unsafe | |
| compose_start_failed | |
| compose_limits_exceeded | |
| image_pull_failed | |
| app_start_failed | |
| manifest_invalid | |
| bad_domain | |
| domain_unverified | |
| domain_unsupported | |
| nothing_to_roll_back | |
| rollback_failed |
Holding pages
When there is nothing to serve yet — a first deploy in progress, a project that has never run, an unclaimed address — Hosait answers with a holding page in the visitor's language. It is distinguishable from your app by machine:
X-Hosait-Placeholder: queued | provisioning | failed | maintenance | available | unknown_address | upstream_down
Cache-Control: no-store
# with Accept: application/json
{ "ok": false, "code": "not_live", "placeholder": "queued" }
A running app is proxied untouched — none of this is added to your responses.