Skip to main content

The bootstrap document

The install asks nothing it does not have to. Everything it is not told it installs with a sensible default, and all of it can be finished in the console afterwards. To decide something in advance instead - the server's name, the mail profile, the addresses that may reach the API - write a bootstrap document before you run the installer.

The document is optional, and so is every key in it: no hostname means the machine's own name, no registry means anonymous pulls, no smtp or geoip means unconfigured until you reach the console.

Write it​

The file is /etc/antelao/bootstrap.json, and it has to be there before the installer runs:

# On a brand-new server /etc/antelao does not exist yet. The installer creates it later, but this
# file has to be there before the installer runs.
sudo install -d -m 0755 /etc/antelao

sudo tee /etc/antelao/bootstrap.json > /dev/null <<'EOF'
{
"hostname": "pelmo.example.com",
"acceptLicense": true,
// null installs at the unregistered tier; upload the license later under License.
// To have the host born licensed, copy your .lic to the server and name it here. A repair
// never touches a license already on the host.
"licensePath": null,
"geoip": { "maxMindAccountId": "123456", "maxMindLicenseKey": "AbCdEf..." },
"smtp": {
"host": "mail.example.com",
"port": 587,
"username": "notifier@example.com",
"password": "s3cret",
"sender": "odoo@example.com",
"senderName": "Odoo Host Manager",
"to": ["ops@example.com", "admin@example.com"]
},
// null trusts no proxy: every connection's own address is the visitor.
"trustedProxies": null,
// The addresses that may reach the host agent (HTTPS on 5202); its key is the protection. null
// admits this server and the apiAllow addresses below; ["0.0.0.0/0", "::/0"] admits every address.
"agentAllow": null,

// Addresses the management API on 5312 admits beside this server's own network. A fresh
// install closes the API to the outside: name the console that manages this server here.
"apiAllow": null,

// The proxy this server reaches the Internet through, when it has no direct way out.
// null is none. See "The outbound proxy" in the configuration reference.
"outboundProxy": null,

// Instances created without a host name are named <id>.pelmo.example.com. Point the
// wildcard *.pelmo.example.com at this server. Leave the key out for <id>.localhost.
"provisioningDomain": "pelmo.example.com",

// The built-in admin account's password (at least 12 characters) and its two-factor seed
// (base32). Either may be given alone. Leave the section out for a generated password.
"administrator": {
"password": "a-long-passphrase-of-your-own",
"totpSeed": "JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP"
}
}
EOF
sudo chmod 0600 /etc/antelao/bootstrap.json

Comments are allowed in the file.

Every key​

KeyWhat it decidesLeft out
hostnameThe name the server answers to: the console, the API and the agent, and the name on the management certificateThe machine's own name
acceptLicensetrue accepts the license agreement for this installation on behalf of whoever wrote the file, as --accept-license does. See The license agreementNo acceptance for the installation. Run from a terminal, the installer then shows the agreement and asks
licensePathA *.lic file already on this server, placed during the installThe unregistered tier, until you install a license under License
registryurl, username and password of a self-hosted registry that needs a credential. Give both the user name and the password, or neitherAnonymous pulls: the product's own images need no credential
geoipmaxMindAccountId and maxMindLicenseKey: the MaxMind account the GeoIP service downloads the GeoLite2 databases with, which location rules match againstNo GeoIP account until you add one under Security > GeoIP
smtpThe mail profile: host, port, username, password, sender, senderName, the recipient lists to, cc and bcc, and fromFilter, the sender addresses allowed. Saved enabled, and the Postfix relay comes up with itNo mail profile
outboundProxyurl, and optionally username, password and a noProxy list. See The outbound proxyNo proxy
trustedProxiesThe exact addresses of a reverse proxy or load balancer in front of nginxNo proxy is trusted
agentAllowThe addresses or ranges that may reach the host agent on 5202. The loopback address is always admittedWith no apiAllow either, every address, the agent's key being the protection. With apiAllow, this server and those addresses
apiAllowThe addresses or ranges the management API admits beside this server's own network: the console that manages this server, and your own address if you administer it remotely. See First, let your address inThe API answers this server and the private ranges only
provisioningDomainThe domain instances created without a host name of their own are named under. See The provisioning domainSuch instances are named under localhost
administratorpassword and totpSeed of the built-in admin account. See The administrator's credentialsA generated password, and two-factor left to the person
workstationtrue makes this machine a developer workstation, as ohm install --workstation doesAn ordinary server
workstationUserOn a workstation, the developer's own accountThe account that ran sudo
allowUnencryptedDiskOn a workstation, true goes ahead on a disk the installer cannot prove is encryptedAn unencrypted disk is a refusal
ideOn a workstation, the editor new profiles default to: vscode, pycharm or bothvscode

A provisioning console or an Odoo Management Plane that writes the document for a server it sets up adds keys of its own (provisionedBy, acceptedBy, managedBy). Leave those to the tool that writes them.

Never put a whole private range in trustedProxies

Set it only when a reverse proxy or load balancer stands in front of nginx, and list exactly its addresses - ["10.0.0.8"], never ["10.0.0.0/8"]. A whole range lets anything inside it, the instance containers included, forge visitor addresses to the firewall, the bans and the logs.

null is right for a server that is its own edge. Editable later under Configuration > Network edge.

It is checked before anything is installed​

The file is validated before anything is installed. An unknown key, a bad value or malformed JSON stops the installer with every problem named at once, and nothing on the host is touched. A misspelt key is therefore a refusal you see straight away, not a setting that is quietly ignored.

It is input, not a record

Its secrets are stored encrypted during the install, and the whole file is overwritten and then deleted once the install succeeds. A later repair ignores it entirely - by then the server's own settings are authoritative, and a stale file must never reshape or block anything.

Environment variables (ANTELAO_INSTALL_*) override the file for one run.

The license agreement​

The installer asks one question at most, and it is this one. Run from a terminal, it shows the license agreement and asks you to accept it before it changes anything on the host; a no stops it and leaves the host as it was. "acceptLicense": true answers the question in advance, as do --accept-license and ANTELAO_INSTALL_ACCEPT_LICENSE=yes, and the acceptance is recorded for the installation.

With no terminal and no answer - a cloud-init run, a machine image's first boot - the installer asks nothing and goes ahead without an acceptance for the installation, and says so.

Either way, the console still asks every person to accept the agreement the first time they sign in, and again whenever a release carries a new version. acceptLicense does not answer that for anyone. See Sign in and finish the setup.

The outbound proxy​

An outboundProxy section (url, and optionally username, password and a noProxy list) is saved and applied with the rest, so the server sends its Internet traffic through that proxy from its first minute:

"outboundProxy": {
"url": "http://proxy.example.com:3128",
"username": "ohm",
"password": "s3cret",
"noProxy": ["intranet.example.com", "10.0.0.0/8"]
}

The package and the first images are downloaded before the server can apply it. On a host with no direct way out, give the package manager and Docker the proxy before you run the installer - see Installing behind a proxy.

The provisioning domain​

provisioningDomain is the server's provisioning domain: an instance created without a host name of its own is named <id>.pelmo.example.com instead of <id>.localhost. The installer's --provisioning-domain option and ANTELAO_INSTALL_PROVISIONING_DOMAIN set it too.

Cloudflare Turnstile​

ANTELAO_INSTALL_TURNSTILE_SITE_KEY and ANTELAO_INSTALL_TURNSTILE_SECRET_KEY, both together, switch on the console's Cloudflare Turnstile at install. They are read from the environment only; the document has no key for them.

The administrator's credentials​

By default the install creates the built-in admin account with a generated password, printed once in the hand-off. To have the server start with credentials you already hold - a provisioned server above all - give them in the bootstrap document's administrator section:

  • password, at least 12 characters, is set as the account's password.
  • totpSeed, a base32 two-factor seed of at least 16 bytes (26 characters), switches two-factor on and makes it required, so the account cannot go on without a second factor. Load the same seed into your authenticator app.

Either may be given alone: a seed alone keeps the generated password, and a password alone leaves two-factor to the person. A document with an administrator section must be readable by root only - the chmod 0600 above - or the installer refuses it before anything is installed.

ohm install can read them from files instead, which keeps them out of the document altogether:

sudo ohm install --admin-password-file /root/admin-password --admin-totp-file /root/admin-totp

Each file holds the value on its first line and must be readable by its owner only (chmod 600); a file that is missing, empty, readable by others or holding an unusable value stops the installer with the file named, and nothing is installed. The files win over the document. The one-line installer passes no options, so give these to ohm install itself, on a host where the antelao-ohm package is installed. Unlike the document, they work on a repair too: --admin-password-file sets a new password on the existing account, and --admin-totp-file sets a new seed and requires two-factor.

Neither value is ever printed, logged or written into the audit trail; the audit entry says only where each came from. The hand-off then shows where the password came from instead of the password, and says two-factor is on and required when a seed was given.

Provisioning many servers​

The bootstrap document is the same file a remote provisioner writes before running the one-line installer, so setting up a fleet is the ordinary install, repeated. Write the document, run the installer, and the host comes up configured - narrowed agent included, if you set agentAllow, its API open to the console that manages it, if you set apiAllow, its instances named under provisioningDomain, and with an administrator section, signed in with credentials you already hold and two-factor required from the first minute.