Agent Zero
Overview
Agent Zero is an open source, general-purpose AI agent framework. You give it a task in a chat and it works on it step by step. It plans, writes and runs code in a terminal, reads and edits files, searches and browses the web, remembers what worked, and can hand parts of a task to subordinate agents. You watch every step live in the web interface.
This SecureAnyCloud image runs Agent Zero on Ubuntu 24.04 on Azure. Upstream ships Agent Zero as a Docker image, and this VM runs that official image, pinned by its digest, as a systemd-managed container.
What you get:
- Agent Zero in its own Linux container, which is the agent's workspace. The upstream image is based on Kali Linux and carries Python, Node.js, a browser runtime, LibreOffice and a desktop for the agent to use
- Ollama running on the VM itself and serving a small open-weight model on the CPU, so the agent works before you add any API key
- nginx as the only public listener: HTTPS on
443with a certificate generated for this VM, and80only redirects - Agent Zero v2.14 from the official image, pinned by digest and already pulled, so first boot fetches no code
- A private Docker network (
a0net,172.30.254.0/24) for the container. Only the web port is published, and only to127.0.0.1:50080. The container's SSH server, tunnel API and9000to9009ports are not published - Ollama 0.40.5 (CPU backends only) running as a dedicated
ollamaaccount, bound to the Docker network's gateway172.30.254.1:11434, withgranite4:tiny-halready pulled - An nftables egress guard that stops the agent's container, and the Ollama account, from reaching the Azure Instance Metadata Service and the Azure WireServer
- nginx terminating HTTPS on
443with a per-VM certificate, redirecting80to HTTPS, and rate limiting the login - Unattended security upgrades left on for the operating system
- 24/7 SecureAnyCloud support
Component Version Licence
Agent Zero (image agent0ai/agent-zero, linux/amd64) v2.14, commit ff2a5b9c, digest sha256:307a2cef... MIT
Ollama (CPU only) 0.40.5 MIT
Model granite4:tiny-h (IBM Granite 4.0 Tiny) registry manifest sha256:1da8cadb... Apache 2.0
Docker engine Ubuntu docker.io 29.1.3 Apache 2.0
Set your expectations for the bundled model. granite4:tiny-h is a small model running on the CPU. It can complete simple, well-specified tasks, such as running a command, writing and running a short script, or reading a file. A task like that takes two to five minutes on a 4 vCPU VM.
The bundled model is much weaker than a large hosted model. It sometimes misreads a task, repeats itself or gives up, and multi-step work is slow and unreliable. For real work, add a key for a hosted model provider (Step 10). The bundled model is there so the appliance works privately the moment it boots.
No password, key or certificate is baked into the image. Upstream Agent Zero runs with no login unless you configure one. On this image, first boot generates a login, a runtime identity, the API key derived from them, and a TLS certificate, all unique to the VM. Nothing serves until that is done.
Before it marks the VM ready, first boot proves four things: an anonymous visitor is sent to the login page, a wrong password is refused, a missing or wrong API key is refused, and the agent's container cannot reach the Azure metadata service.
Agent Zero is developed by Agent Zero, s.r.o. and contributors and is licensed under the MIT licence. Ollama is developed by Ollama, Inc. under the MIT licence, and Granite is a model family from IBM. Kali Linux is a trademark of OffSec Services Limited. This image is produced by SecureAnyCloud and is not affiliated with, endorsed by, or sponsored by Agent Zero, s.r.o., Ollama, IBM or OffSec. The names are used here solely to identify the software and model this image contains.
Prerequisites
- An Azure subscription with permission to create VMs
- A
Standard_D4s_v3(4 vCPU, 16 GiB) or larger non-burstable size is recommended for the bundled model. The model uses about 5 GiB of memory and all four CPUs while it works, and the Agent Zero container uses another 1 to 2 GiB. B-series sizes such asStandard_B4msrun it at full speed only while they have CPU credits. Measured on this image, aB4msexhausted its credits after about an hour of agent work, and a single step then took more than twenty minutes. With a hosted model (Step 10), the VM only runs the container, andStandard_B2ms(2 vCPU, 8 GiB) is enough - Inbound TCP
443(and80for the redirect) open only to the networks you connect from, plus22for SSH administration - An SSH key pair for administrative access
Deploy from the Azure Portal
- In the Azure Portal, search the Marketplace for Agent Zero by SecureAnyCloud and select Create.
- Choose your subscription, resource group and region.
- Set the VM size to Standard_D4s_v3 or larger.
- Under Administrator account, select SSH public key and supply your own key.
- Under Inbound port rules, allow HTTPS (443), HTTP (80) and SSH (22), then restrict all three to your own address ranges on the networking blade.
- Review your settings, then create the VM.
Deploy from the Azure CLI
az vm image terms accept --urn sac1647283583153:agent-zero-ubuntu-24-04:default:latest
az vm create \
--resource-group my-resource-group \
--name my-agent-zero \
--image sac1647283583153:agent-zero-ubuntu-24-04:default:latest \
--size Standard_D4s_v3 \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_rsa.pub \
--public-ip-sku Standard
# Open HTTPS (and the HTTP redirect) to YOUR network only. MY_CIDR="203.0.113.0/24"
# replace with your own range
az network nsg rule create \
--resource-group my-resource-group \
--nsg-name my-agent-zeroNSG \
--name allow-https-from-office --priority 1010 \
--source-address-prefixes "${MY_CIDR}" \
--destination-port-ranges 80 443 --protocol Tcp --access AllowConnect to your VM
ssh azureuser@<vm-ip>Confirm the services are running
First boot takes about a minute. It generates this VM's login, API key and certificate, starts the container and proves the gates before it finishes. Run these commands to check the services:
systemctl is-active agent-zero-egress-guard docker ollama agent-zero nginx
systemctl show -p Result --value agent-zero-firstboot
# SSH and nginx are the only routable listeners. Ollama is bound to the private Docker bridge.
sudo ss -lntH | awk '{print $4}' | grep -v -E '^(127\.|\[::1\])' | sort
# The container publishes only its web port, and only to loopback.
sudo docker port agent-zeroExpected output:
active active active active active success 0.0.0.0:22 0.0.0.0:443 0.0.0.0:80 172.30.254.1:11434 [::]:22 [::]:443 [::]:80 80/tcp -> 127.0.0.1:50080Read this VM's credentials
Read the credentials file below. Everything in it was generated on this VM at first boot.
sudo cat /root/agent-zero-credentials.txt# Agent Zero - per-VM credentials generated on first boot (...). Keep this file private.
# The web login and the API key below are this VM's own; change the password in Settings > Authentication # (the API key changes with it - see Settings > External services). AGENT_ZERO_URL=https://<vm-ip>/ AGENT_ZERO_USERNAME=a0admin AGENT_ZERO_PASSWORD=<A0_PASSWORD> AGENT_ZERO_API_KEY=<A0_API_KEY>The login name is a0admin rather than admin on purpose: Agent Zero hides its login name wherever it appears in the agent's output, so a common word would be masked in ordinary text.
Sign in and give the agent a task
- Open
AGENT_ZERO_URLin your browser. The certificate is self-signed and generated for this VM, so your browser warns you the first time. Accept it for this address, or follow Step 13 to use your own domain and a trusted certificate. - Sign in as
a0adminwithAGENT_ZERO_PASSWORD. - Type a task into the box under How can I help you today? and press Enter. Give the bundled model short, concrete instructions. Asking it to run a specific command works best, for example:
Run this shell command in the terminal and tell me exactly what it printed: python3 -c "print([n for n in range(2, 30) if all(n % d for d in range(2, n))])" | tee primes.txtA large hosted model (Step 10) can take open ended tasks such as write a script that ..., test it and fix any errors; the bundled model often answers those without running anything.
The chat shows each step as the agent takes it: the code it writes, the command it runs, the output, and its final answer. With the bundled model expect a few minutes for a task like this.
Files the agent creates are in its work directory, /a0/usr/workdir inside the container, which is /var/lib/agent-zero/usr/workdir on the VM. Open Files on the home screen to browse them.
Understand the code execution model
Agent Zero runs code. That is what it is for, and you should treat it accordingly:
- Every command and script the agent runs executes as root inside the Agent Zero container. The container is not privileged, has no access to the Docker socket and runs with
no-new-privileges, but within it the agent can install packages, write files and run any program. - The agent can read and change everything under
/a0, including its own settings and/a0/usr/.env, which holds this VM's login password and any provider API keys you add. Anyone who can give the agent instructions, including text on a web page or in a file it reads (prompt injection), can try to make it reveal or misuse them. Only give it tasks and data you trust, and use provider keys with spending limits. - The container has full outbound internet access, which the agent needs to browse, download and install. It cannot reach the Azure Instance Metadata Service (
169.254.169.254, which hands out managed identity tokens) or the Azure WireServer (168.63.129.16): an nftables guard drops that traffic for every Docker network and for the Ollama account, and Docker will not start without the guard loaded. - The container can reach the VM itself through the Docker network gateway (
172.30.254.1): Ollama there, and the VM's own SSH and nginx ports. - Your chats, the agent's memory, uploaded files and the work directory persist in
/var/lib/agent-zero/usron the VM. Packages the agent installs live in the container and survive restarts, but not a re-creation of the container (Step 14).
You can check the egress guard and the gates from the VM:
M='http://169.254.169.254/metadata/instance?api-version=2021-02-01' printf 'VM itself -> IMDS %s\n' "$(curl -s -o /dev/null -w '%{http_code}' -m 5 -H Metadata:true "$M")" printf 'agent-zero container -> IMDS %s\n' "$(sudo docker exec agent-zero curl -s -o /dev/null -w '%{http_code}' -m 5 -H Metadata:true "$M")" printf 'agent-zero container -> WireServer %s\n' "$(sudo docker exec agent-zero curl -s -o /dev/null -w '%{http_code}' -m 5 'http://168.63.129.16/?comp=versions')" printf 'agent-zero container -> pypi.org %s\n' "$(sudo docker exec agent-zero curl -s -o /dev/null -w '%{http_code}' -m 20 https://pypi.org/simple/pip/)" printf 'anonymous / -> %s\n' "$(curl -sk -o /dev/null -w '%{http_code} %{redirect_url}' https://127.0.0.1/)" printf 'API without a key -> %s\n' "$(curl -sk -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -d '{"message":"hi"}' https://127.0.0.1/api/api_message)"Expected output (000 means the connection was dropped):
VM itself -> IMDS 200 agent-zero container -> IMDS 000 agent-zero container -> WireServer 000 agent-zero container -> pypi.org 200 anonymous / -> 302 https://127.0.0.1/login?next=/ API without a key -> 401Understand the access model
- Web interface. Every page and API route needs this VM's login, except the login page and a health check. Agent Zero reads the login from
AUTH_LOGINandAUTH_PASSWORDin/var/lib/agent-zero/usr/.env(mounted at/a0/usr/.env); the container will not start if either is empty, so it never runs without a login. The session cookie leaves nginx markedSecure,HttpOnlyandSameSite=Lax, and nginx allows ten login attempts a minute per client. - External API, MCP and A2A. Agent Zero's external API (
/api/api_messageand related routes), its MCP server (/mcp) and its A2A server (/a2a) authenticate with one API key, which Agent Zero derives from its runtime identity, login and password. That key isAGENT_ZERO_API_KEY. The MCP and A2A servers are off until you enable them in Settings. - Network. nginx is the only public listener. The container's port is published to
127.0.0.1only, and Ollama listens only on the Docker network gateway. Development only routes are closed: nginx refuses/api/rfc(remote function calls from a development copy of Agent Zero).
The bundled model
Agent Zero's Default model preset on this VM uses Ollama on the VM for both its main and utility model, and a local sentence transformer (all-MiniLM-L6-v2, baked into the image) for memory embeddings, so nothing leaves the VM unless the agent itself browses. The default agent profile is upstream's Tiny Local profile, which gives small local models a simpler tool calling contract. Each reply from the bundled model is capped at 2,048 tokens (max_tokens in the preset), because a small model can fall into a repetition loop that would otherwise occupy the CPU for many minutes; raise or remove the cap if you switch to a larger model.
ollama --version ollama list ollama show granite4:tiny-h --license | grep -m1 'Apache'ollama version is 0.40.5 NAME ID SIZE MODIFIED granite4:tiny-h 566b725534ea 4.2 GB ... Apache LicenseThis image adds one small configuration plugin, sac_ollama_chat in /a0/usr/plugins. Upstream's built in Ollama provider sends requests to Ollama's /api/generate endpoint with a generic prompt format; with that, the bundled model ignored tasks and replied with a greeting. The plugin points the same Ollama provider at Ollama's /api/chat endpoint, where each model's own chat template is applied. It contains no code and needs no key.
You can also call the agent through its external API. With the bundled model each call takes a few minutes, so run it from your own shell:
KEY=$(sudo sed -n 's/^AGENT_ZERO_API_KEY=//p' /root/agent-zero-credentials.txt)
# The key is read from standard input (-H @-), so it never appears on a command line. printf 'X-API-KEY: %s\n' "$KEY" | curl -sk -m 1500 -X POST -H @- -H 'Content-Type: application/json' \
-d '{"message":"Run this shell command in the terminal and reply with only its output: date -u"}' \
https://127.0.0.1/api/api_messageA real reply from the bundled model on this image (shortened):
{"context_id": "ZCrk0mco", "response": "`Fri Oct 16 02:07:13 UTC 2026`\n\n(venv) root@agent-zero:/a0/usr/workdir#\n\n# Current system date and time of user\n ..."}The agent really ran date -u in its terminal (the chat in the web interface shows the command and its output), but the small model then pasted part of its own context after the answer. In another run it ran the command and then quoted a different time zone, and for uname -m it once answered aarch64 on this x86_64 VM without running anything. Always check the tool output in the chat rather than trusting the bundled model's summary; a hosted model (Step 10) answers these cleanly.
Use a hosted model with your API key
For real work, use a large hosted model:
- Open Settings (the gear in the top left) and go to Agent Settings > Models to edit the presets, or choose a preset from the menu in a chat's status bar.
- Pick a provider, for example OpenAI, Anthropic, Google, OpenRouter or Azure OpenAI, enter your API key for it, and choose the main and utility models. Keep HuggingFace
all-MiniLM-L6-v2as the embedding model unless you have a reason to change it. - For a capable model, switch the agent profile from Tiny Local back to upstream's default Agent 0 profile under Agent Settings > Agent Config.
With a hosted model, your prompts, the agent's working context and anything it reads go to that provider under the provider's terms. You can then stop Ollama to free its memory: sudo systemctl disable --now ollama.
Add a larger local model
Ollama can run any model from its library that fits in the VM's memory. Pull it and select it in the preset editor (the list is read from Ollama):
ollama pull qwen3:8b
# about 5 GB; needs 16 GiB of memory or more, and is slower on CPU ollama listCheck each model's licence before using it commercially (ollama show <model> --license), prefer models that support tool calling, and expect larger models to be slower on the CPU. This image ships Ollama's CPU backends only; for GPU inference use a GPU VM size with a GPU build of Ollama.
MCP and A2A
Agent Zero can act as an MCP server (so tools such as Claude Desktop or Cursor can delegate tasks to it) and as an A2A agent. Both are off by default. Enable them under Settings > MCP/A2A (A0 MCP Server and A0 A2A Server), which also shows the connection URLs. Every URL contains or requires AGENT_ZERO_API_KEY; without it the endpoints refuse the connection. Use your domain name (Step 13) in the URLs you give to other tools, and only enable these if those tools can reach the VM over HTTPS.
Use your own domain and certificate
The self-signed certificate is fine for a trial. For regular use, point a DNS name at the VM's public IP and install a trusted certificate. nginx already serves the Let's Encrypt HTTP-01 challenge path on port 80.
sudo apt-get update && sudo apt-get install -y certbot
sudo certbot certonly --webroot -w /var/www/html -d agent.example.com
sudo sed -i \
-e 's#/etc/agent-zero/tls/server.crt#/etc/letsencrypt/live/agent.example.com/fullchain.pem#' \
-e 's#/etc/agent-zero/tls/server.key#/etc/letsencrypt/live/agent.example.com/privkey.pem#' \
/etc/nginx/sites-available/agent-zero
sudo nginx -t && sudo systemctl reload nginxAdd --deploy-hook "systemctl reload nginx" to the certonly command so nginx picks up each renewal.
Day-2 operations
# Restart Agent Zero or Ollama.
sudo systemctl restart agent-zero
sudo systemctl restart ollama
# Recent logs.
sudo journalctl -u agent-zero -n 20 --no-pager
# What is installed.
cat /usr/share/agent-zero/VERSIONS- Data. Everything Agent Zero stores is in
/var/lib/agent-zero/usr(mounted at/a0/usr): settings and keys (.env), chats, memory, knowledge, uploads, projects and the work directory. Back it up, together with/var/lib/ollama/modelsif you pulled extra models, or take Azure disk snapshots. - Changing the password. Change it in Settings > External Services > Authentication. The API key is derived from the password, so it changes too; read the new one under Settings > External Services > External API and update the credentials file if you keep it.
- Remote Control (tunnels). Settings > External Services > Remote Control can publish Agent Zero through a public tunnel service. The login still applies, but the tunnel bypasses your network security group, so leave it off unless you need it.
- Upgrading Agent Zero. The image is pinned in
/etc/agent-zero/agent-zero.envasA0_IMAGE. To upgrade, take a snapshot, pull a newer official image by digest, setA0_IMAGEto it and runsudo systemctl restart agent-zero; the container is re-created and your data in/var/lib/agent-zero/usris kept. Packages the agent installed inside the old container are not carried over. Agent Zero's own in app updater works too, but changes the code inside the running container only. - Operating system updates. Unattended security upgrades are on, including the Docker engine from the Ubuntu archive. Reboot when
/var/run/reboot-requiredexists; everything starts again on boot. - Docker network. The container network uses 172.30.254.0/24. If that overlaps an address range your VM must reach, contact SecureAnyCloud support before changing it, because Ollama and the egress guard are bound to it.
Troubleshooting
- The browser shows a certificate warning. Expected with the per-VM self-signed certificate; see Step 13.
- The page does not load at all. Check that the VM's network security group allows
443from your address, and thatsystemctl is-active agent-zero nginxreportsactive. - "Too many requests" when signing in. nginx allows ten login attempts a minute per client. Wait a minute and sign in with the password from the credentials file.
- The agent is very slow. Expected with the bundled model on the CPU. On a B series size, check the VM's CPU Credits Remaining metric in the Azure Portal; once credits run out the CPU is throttled and each step can take many minutes. Use a D series size, or a hosted model (Step 10).
- The agent stops with "consecutive unusable model responses", repeats itself or answers something else. The small bundled model lost track of the task. Start a new chat and phrase the task more simply, or use a hosted model.
- The agent cannot reach a site. Outbound internet is open except for the Azure platform addresses in Step 7. Check name resolution from inside the container:
sudo docker exec agent-zero curl -sI https://example.com.
Support
SecureAnyCloud provides 24/7 support for this image by email at sales@secureanycloud.com, covering deployment, VM sizing, model and provider choice, the code execution and network model, MCP and A2A, TLS and upgrades.
Deploy on Azure
Launch Agent Zero on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com