odoobot

Security

What our agent can do on your server,
and how you stay in control.

You are installing software that manages your machine. You should know exactly what it can do, how it talks to us, and how to limit or remove it. No marketing claims — each point below says how to verify it.

01 · connection

It only dials out. Nothing can connect to it.

The agent opens no listening ports. It makes one outbound connection to odoobot over TLS, with the certificate verified, and receives work over that connection. There is no port to open in your firewall and nothing on the internet can reach the agent.

Check it yourself — this prints nothing:

sudo ss -tlnp | grep odoobot-agent
02 · enrollment

A join token works once, for one hour, for your organisation only.

The token in the install command is single-use and expires after an hour. Enrolling consumes it and gives this machine its own credential; a credential issued to one machine is useless on another. You can revoke a machine from the console at any time, and a machine you mark as stolen is wiped of odoobot-managed data the next time it connects.

03 · privileges

It runs as root. Here is why, and how you limit it.

Managing Odoo means managing Docker, nginx, systemd and files under /etc. Every attempt to run the agent unprivileged ended with a carve-out per feature, so it runs as root — and we would rather say so than hide it behind a sandbox that isn't one.

What you get instead is a veto that lives on your machine. The agent reads /etc/odoobot-agent/policy.json before every command and refuses anything listed. The file is never written by the agent, so nothing odoobot sends can change it. To turn off free-form commands and the web shell:

sudo mkdir -p /etc/odoobot-agent
echo '{"deny": ["system.exec", "shell"]}' | sudo tee /etc/odoobot-agent/policy.json

Managed operations — deploying, updating modules, backups — keep working. A policy file that can't be parsed makes the agent refuse every command, so a typo never silently leaves you unrestricted.

04 · accountability

Every command is recorded, and only the right people can send one.

  • Every command sent to your machine is recorded with who sent it, and listed under Command history on the machine's page. Opening a web shell is recorded the same way.
  • Running commands on the machine itself takes an Owner or Admin of your organisation. Developers deploy, view logs and can open a shell inside their Odoo containers — not on the host. Viewers only read; Billing users see no technical data at all.
  • Organisations are isolated: nobody outside yours can see or act on your machines.
05 · updates

Every release is signed with a key our servers never hold.

Agent releases are built and signed on a release machine, with a key that lives in its Secure Enclave and signs only with a fingerprint touch. It cannot be copied off that machine, and no odoobot server has it. An offline backup key, kept behind a passphrase, exists for the day that machine is lost.

The agent (0.4.80 and later) installs an update only if its release manifest carries a valid signature from one of those two keys, and only if the binary matches the checksum inside that signed manifest. It never moves to an older version, and an update never interrupts a command in progress. So even if odoobot's own servers were compromised, they could not push an update we did not sign to a machine already running the agent.

The installer checks the same signature before it installs anything. A first install necessarily trusts the installer it downloads, so if you want to be certain, read it first (see below) and check that the keys it embeds have these fingerprints:

SHA256:m5FaX8h9NyK0dgTed+t8MOhG5HHmJ6ujcP8ZACENT1k  release key (Secure Enclave, Touch ID)
SHA256:D4IWf9TplpuKPPEagRisk0sOWZSVzx2AdKaOuzm6O5o  offline backup key
06 · install

Read the installer before you run it.

The one-line install is convenient, but you don't have to pipe anything into a shell. Download it, read it, then run it:

curl -fsSL https://app.odoobot.net/api/agent/install.sh -o odoobot-install.sh
less odoobot-install.sh          # read it: ~200 lines of plain bash
sudo bash odoobot-install.sh --token=<your join token>
07 · leaving

Removing it takes four commands.

Your Odoo instances keep running; only odoobot's management stops.

sudo systemctl disable --now odoobot-agent
sudo rm -f /etc/systemd/system/odoobot-agent.service /usr/local/bin/odoobot-agent
sudo rm -rf /var/lib/odoobot-agent
sudo systemctl daemon-reload

See it for yourself

A security assessment of every machine.

From a machine's page in the console, run an assessment. The agent reports what listens where, your firewall's state, SSH settings, Docker's published ports and pending security updates — read-only, nothing is changed. odoobot then tries to connect to those ports from the internet, so you see what is actually reachable, not what should be.

It catches the classic surprise: a database container published by Docker, which bypasses ufw, sitting open to the world while the firewall says it's closed. Each finding says why it matters and exactly how to fix it.

The outside scan only ever targets the public address your machine itself connects to us from — never an address anyone types in, and never a private network. You can switch the outside scan off.

Report a problem

Found a security problem? Email security@devhost.io. We read every report.