-
Notifications
You must be signed in to change notification settings - Fork 68
Deployment
Milady runs locally by default, but can also be deployed as a container (Railway, Docker, VPS) or connected to Eliza Cloud.
On first run, onboarding asks where the backend should live:
- Local — run the backend on the current machine (the default local flow)
- Cloud — use Eliza Cloud or attach to a Remote Milady backend
If you choose Eliza Cloud, the app provisions and connects to a managed backend at elizacloud.ai. If you choose Remote Milady, the frontend rebinds to the backend you specify.
Use this when you want the Milady frontend to connect to a backend running on a VPS, homelab, or another machine.
- Install Milady on the target machine
- Bind the API to a reachable address
- Generate a strong API token
- Allow the frontend origin explicitly
- Expose the backend over HTTPS or a private Tailscale URL
Recommended server environment:
export MILADY_API_BIND=0.0.0.0
export MILADY_API_TOKEN="$(openssl rand -hex 32)"
export MILADY_ALLOWED_ORIGINS="https://app.milady.ai,https://milady.ai,https://elizacloud.ai,https://www.elizacloud.ai"
milady start
The access key entered in onboarding is the value of MILADY_API_TOKEN.
For private remote access without opening the backend publicly:
tailscale serve --https=443 http://127.0.0.1:2138
If you intentionally want a public Tailscale URL:
tailscale funnel --https=443 http://127.0.0.1:2138
Use the Tailscale HTTPS URL as the backend address in onboarding and keep using the same MILADY_API_TOKEN as the access key.
A Dockerfile is included at the repo root. It uses node:22-bookworm as the base, installs Bun, builds the project, and starts Milady in headless mode.
docker build -t milady .
docker run -d \
-p 2138:2138 \
-v /data/.milady:/data/.milady \
-e MILADY_API_TOKEN=your-secure-token \
milady
The container CMD is:
MILADY_PORT=2138 node milady.mjs start
Railway sets PORT dynamically; the CMD maps it to MILADY_PORT.
The Dockerfile sets these defaults for container deployments:
| Variable | Container default | Description |
|---|---|---|
NODE_ENV |
production |
Node environment |
MILADY_API_BIND |
0.0.0.0 |
Bind to all interfaces (required in containers) |
MILADY_STATE_DIR |
/data/.milady |
State directory (config, db, logs) |
MILADY_CONFIG_PATH |
/data/.milady/milady.json |
Config file path |
PGLITE_DATA_DIR |
/data/.milady/workspace/.eliza/.elizadb |
PGLite database directory |
Important: Always set MILADY_API_TOKEN when MILADY_API_BIND=0.0.0.0. Without it, anyone who can reach the server has full access.
Mount /data as a persistent volume so config, the database, and agent state survive redeploys:
docker run -v /host/path:/data milady
On Railway, attach a persistent volume at /data.
Deploy directly from the GitHub repo. Recommended env vars:
MILADY_API_TOKEN=<generated>
ANTHROPIC_API_KEY=<your-key>
TELEGRAM_BOT_TOKEN=<your-token>
Attach a persistent volume at /data.
In container/server deployments, always run headless:
milady start
This suppresses the TUI and browser popup. The Dockerfile CMD already does this.
In headless/daemon mode, logs go to ~/.milady/logs/ (or MILADY_STATE_DIR/logs/ in containers). Use --verbose for log level info or --debug for debug.
Milady does not ship a built-in daemon manager. Use your preferred process manager.
systemd:
[Unit]
Description=Milady AI Agent
After=network.target
[Service]
ExecStart=/usr/local/bin/milady start
Restart=on-failure
Environment=MILADY_API_TOKEN=your-token
[Install]
WantedBy=multi-user.targetpm2:
pm2 start "milady start" --name milady
pm2 save
The Dockerfile handles Git LFS assets (VRM avatars, animations) with a multi-step fallback:
- Runs
git lfs pullif.gitis present in the build context - Falls back to cloning from the origin repo if LFS pointers remain unresolved
- Falls back to
media.githubusercontent.comfor VRM files as a last resort
VRM pointer files that are still unresolved after all fallbacks will fail the build. Animation pointer files will produce a warning but not fail.
Pass GITHUB_TOKEN as a build arg for private repo access:
docker build --build-arg GITHUB_TOKEN=ghp_... -t milady .
Pass MILADY_DOCKER_APT_PACKAGES to install additional system packages:
docker build --build-arg MILADY_DOCKER_APT_PACKAGES=ffmpeg -t milady .