Deploy spec & headers
How AxHub builds your app and how it gives you the logged-in user — the two things a developer needs to know.
If you're editing the app's code, two things matter — how AxHub builds your code (the deploy spec) and how it gives you the logged-in user (SSO headers). Template apps already have both set up; this is what to know when you bring your own code.
Deploy spec — how AxHub picks the build
AxHub looks at your repo files and picks a build method in this order. It stops at the first match.
axhub.yaml— if present, this manifest winsDockerfile— at the root, builds a single image- Compose file —
docker-compose.yml·docker-compose.yaml·compose.yaml·compose.yml - Railpack auto-detection — otherwise, infers the framework from marker files (
package.json→node,go.mod→go,requirements.txt/pyproject.toml→python,Cargo.toml→rust, etc.)
If none of the four exist, there's nothing to build and it fails.
Add an axhub.yaml when the build/start command is ambiguous or you want to pin it.
version: axhub/v1
runtime:
port: 3000
health_path: /
build:
deploy_method: docker
dockerfile: Dockerfile
env:
required:
- name: DATABASE_URL
scope: runtimeaxhub.yaml is the current name that replaces the old apphub.yaml. If both exist, axhub.yaml wins. The full schema is in the axhub.yaml reference.
SSO headers — read the logged-in user
An app behind AxHub doesn't need its own login. The gate handles auth and adds six user-info headers to requests that pass.
| Header | Value |
|---|---|
X-AxHub-User-ID | User UUID |
X-AxHub-User-Email | Base64-encoded email |
X-AxHub-User-Name | Base64-encoded name |
X-AxHub-App-Role | owner · platform_admin · tenant_admin · app_member · tenant_member |
X-AxHub-Is-Admin | true · false |
X-AxHub-Tenant-Slug | Tenant slug |
Read them on the server:
export function currentAxHubUser(req: Request) {
const h = req.headers;
return {
id: h.get('x-axhub-user-id'),
email: Buffer.from(h.get('x-axhub-user-email') ?? '', 'base64').toString('utf8'),
name: Buffer.from(h.get('x-axhub-user-name') ?? '', 'base64').toString('utf8'),
role: h.get('x-axhub-app-role'),
isAdmin: h.get('x-axhub-is-admin') === 'true',
tenant: h.get('x-axhub-tenant-slug'),
};
}Always read these on the server. The gate overwrites any X-AxHub-* the client sends — and when access is denied, all six headers arrive empty. So if X-AxHub-User-ID is empty, treat the request as unauthenticated.
Redeploy on change
Push a new commit to the connected repo and a deploy starts again. You can also create a deployment manually from the Deploy tab in the web console.