Configuration and state
A server's configuration has two halves with two owners, and neither is a file you edit. Nothing here is hand-edited in normal operation: the host
half is written by ohm install, and the policy half is edited in the console.
The two halves
| Half | Holds | Lives in | Written by |
|---|---|---|---|
| The host's | Hostname; the instance, backup, archive and temp directories; the management URLs; the registry and its credentials; the PostgreSQL major version; the console key; the Fail2Ban and GeoIP service pairs | /etc/antelao/agent.env and /var/lib/ohm-agent/host-state.json | ohm install, and the jobs that change the host - a PostgreSQL major-version migration, a console key rotation |
| The policy | Description; mail; intrusion prevention; the access rules; the GeoIP account; the certificate mode; job concurrency; image retention; the license warning window; trusted proxies; the outbound proxy; the provisioning domain; the cloud metadata block | The ServerSettings row of the master database, its secrets encrypted under the API's key ring | The console's server pages, and ohm server config import |
The agent serves the host's half to the management plane as GET /api/v1/host. The API composes
the two at startup and, while the composition fails, every ten seconds until it succeeds. That is
what a serverConfigLoaded: false health response means, and why fixing the cause is enough - there
is nothing to restart.
The bootstrap agent's dashboard on port 5202 shows the host's half - the server id, the hostname and the registry - because that is where those are decided.
To change anything in the host's half, run the installer again on the host.
The server's name is the one exception with a page of its own: the Configuration page of the
bootstrap agent renames the server, and so does ohm server rename on the host. Both run the same
repair the installer runs for a new name, and request a certificate for the new name in the
configured mode. See Renaming the server.
$ sudo ohm server rename new.example.comsudo ANTELAO_INSTALL_HOSTNAME=new.example.com ohm install
Every change to the policy half is recorded. Configuration > Revisions is what it was before, who changed it and when.
The policy half travels as a file:
pelmo$ ohm server config export -o settings.jsonpelmo$ ohm server config import -j settings.jsonThe export redacts credentials. The import replaces the row; the host's half is not in the file, so a configuration exported from one server cannot carry another server's identity onto it.
A whole server - the settings, the license, the PostgreSQL profiles, the instances and the maintenance calendar, plus the host's half - moves as one manifest instead:
pelmo$ ohm server manifest export -j manifest.jsonpelmo$ ohm server manifest apply -j manifest.jsonThe server says what it would do before it does it, then queues the apply as a job. Applying the
same manifest twice changes nothing the second time. --with-secrets keeps the credentials in the
file, and then the file is a key to the server: treat it as one.
Where the state lives
/root/.local/share/ohm/ the application root
├── conf/ appsettings.json - the master-database connection, and nothing else
├── data/ container data trees, generated secrets, certificates, GeoIP databases
├── logs/ ohm-cli-*.log, ohm-audit-*.log, action logs
└── license/ *.lic license files, install-id, checkin.receipt, checkin-state.json
/etc/antelao/agent.env the agent's credentials and the host's half (mode 0600)
/etc/antelao/bootstrap.json OPTIONAL one-shot install input; consumed and DELETED by a
successful fresh install, and ignored by every repair (mode 0600)
/etc/antelao/license-agreement.json the acceptance recorded on the host, before a database exists
/var/lib/ohm-agent/ the agent's task list, host-state.json, and its upgrade request
/var/lib/odoo/instances the instance trees
/var/lib/odoo/backup the backups
/var/lib/odoo/archive the archive
The master database holds everything else: users, instances, jobs, schedules, statistics, the
license register and the ServerSettings row.
The stored credentials in the master database are encrypted under the API's key ring, which lives in
the Docker volume ohm-api-keys; the console's own ring, for its sign-in cookies, is in
ohm-web-keys.
Back up the master database, the application root and the ohm-api-keys volume together. None
of them is much use without the others: the database's credentials open only with that key ring. See
Credentials on the backup targets page.
appsettings.json
The one file under conf/. The CLI and the API both read it: it says which master-database provider
to use and how to reach it, and it is where the API's own process settings below are set.
{
"Connection": {
"Default": "PostgreSQL"
},
"ConnectionStrings": {
"PostgreSQL": "Host=localhost;Port=5432;Database=master;SSL Mode=Prefer;Timeout=30;Cancellation Timeout=-1",
"SqlServer": ""
}
}
Default is PostgreSQL or SqlServer. Those are the two providers the product supports,
and only the connection string Default names is used; leave any other entry in
ConnectionStrings as it is.
PostgreSQL in the bundled ohm-postgres container is the default, and ohm install creates the
database and its schema. Moving to an external SQL Server is a job, not a file edit:
pelmo$ ohm system database migrate --to SqlServerIt runs inside the API rather than on the host, because the stored credentials are re-encrypted on
the way and the API is what holds the key ring. It switches the configured provider in
appsettings.json and takes effect when ohm-api and ohm-web restart.
The SQL Server connection string must be complete and must name a dedicated database. Never the
engine's own master: the application database merely happens to share that name on the PostgreSQL
container.
Master data exports the whole master database as a SQL script for its engine, and
imports one. The import asks for the confirmation word IMPORT and writes a safety export first.
Alerting and uptime settings
Two sections of the API's own configuration, read once, when the API starts. Neither has a console page. The ones worth knowing are the retentions and the two switches.
To change one, add it to conf/appsettings.json under Api, beside what the file already holds,
then restart ohm-api on Core services. For example, to switch the uptime probe off and keep
alert events for 30 days:
{
"Connection": { "Default": "PostgreSQL" },
"ConnectionStrings": { "PostgreSQL": "...", "SqlServer": "" },
"Api": {
"Uptime": { "Enabled": false },
"Alerting": { "EventRetentionDays": 30 }
}
}
Api:Alerting
| Setting | Default | What it does |
|---|---|---|
Enabled | true | Whether the hub publishes at all |
MaxDeliveriesPerMinute | 30 | The per-channel budget |
PauseAfterFailures | 10 | Consecutive failures that pause a channel |
EventRetentionDays | 90 | How long an event is kept |
DeliveryRetentionDays | 30 | How long a delivery row is kept |
ExecutorGraceSeconds | 120 | How long the container event relay may be silent before the executor is called unreachable |
DeliveryTimeoutSeconds | 15 | How long one attempt may take |
ResponseBodyCapBytes | 65536 | How much of a response is read before it is abandoned |
AllowPrivateTargets offAllowPrivateTargets lets a channel target a loopback or private address, which the
webhook policy otherwise refuses. Switching it on removes the guard that
stops a webhook being used to reach inside your network. No page or job ever sets it; do not set it
on a server.
Api:Uptime
| Setting | Default | What it does |
|---|---|---|
Enabled | true | Whether the probe runs. Turn it off if you monitor from elsewhere |
IntervalSeconds | 60 | How often a tick runs, floored at 30 - a tighter value probes faster than nginx answers |
HttpTimeoutSeconds | 10 | How long one check may take |
Concurrency | 8 | How many instances are checked at once |
FailuresBeforeDown | 3 | Consecutive failures that open an outage |
SuccessesBeforeUp | 2 | Consecutive successes that close one |
CertificateWarnDays | 14 | Days left before the certificate warning |
CertificateCriticalDays | 3 | Days left before it becomes critical |
FineRetentionDays | 14 | How long the five-minute rows are kept before compaction |
RetentionDays | 400 | How long the daily rows are kept |
A filesystem's disk alert has no boundaries of its own here: it is raised by Usage warning (%) and Usage critical (%) under Configuration, 80 and 90 by default, the same pair the Statistics and Storage pages colour a reading by.
See Alerting and Uptime for what these govern.
Api:Audit
| Key | Default | What it decides |
|---|---|---|
RetentionDays | 365 | How long the audit trail is kept before the retention job prunes it |
It is set in the same file, under Api, and the next prune reads it. The prune deletes; it does
not archive. Export before the window closes if you need longer.
Ports
Every port the server listens on, with its defaults. Bound to is the address the service listens
on: the loopback answers the server itself and nothing else; every interface answers whatever can
route to the server, unless a firewall stops it. Firewall script is what the firewall script
antelao-ohm-ufw.sh does with the port: open to everyone, open to your own addresses only, or
nothing (the script's default refuses it). Service is the container, or for SSH the host's own
program, that answers; ohm-<id> is an instance's container.
| Port | Protocol | Bound to | Firewall script | Service | What it is |
|---|---|---|---|---|---|
| 22 | SSH | Every interface | Your addresses | sshd | The host's own SSH server, not part of the product |
| 80 | HTTP | Every interface | Everyone | ohm-nginx | The web server in front of the instances: Let's Encrypt's HTTP check and the redirect to HTTPS |
| 443 | HTTPS | Every interface | Everyone | ohm-nginx | The instances, and the consoles a Published (443) rule publishes under /admin, /pgadmin, /portainer and /metabase |
| 5201 | HTTP | Loopback | Nothing | ohm-agent | The host agent, for the command line and the server's own parts |
| 5202 | HTTPS | Every interface | Your addresses | ohm-agent | The host agent's page and API. Protected by its key and by who may reach the agent |
| 5311 | HTTP | Loopback | Nothing | ohm-api | The management API, for the command line and the console on the server itself |
| 5312 | HTTPS | Every interface | Your addresses | ohm-api | The management API |
| 5321 | HTTP | Loopback | Nothing | ohm-web | The console, for the server itself and an SSH tunnel |
| 5322 | HTTPS | Every interface | Your addresses | ohm-web | The console |
| 5323 | HTTPS | Every interface | Your addresses | ohm-web | The browser editor an instance's Code tab opens, with the console's certificate. Allow it wherever you allow 5322 |
| 5411 | HTTP | Loopback | Nothing | ohm-geoip | The GeoIP service, for the management API |
| 5421 | HTTP | Loopback | Nothing | ohm-fail2ban | The Fail2Ban service, for the management API |
| 5431 | HTTP | Loopback | Nothing | ohm-crowdsec | CrowdSec's local API, while CrowdSec is switched on |
| 2500 | SMTP | Loopback | Nothing | ohm-postfix | The mail relay the server's own mail leaves through |
| 5432 | PostgreSQL | Loopback | Nothing | ohm-postgres | The PostgreSQL cluster |
| 5433 | PostgreSQL | Loopback | Nothing | ohm-postgres-replica | The read replica, once installed |
| 6432 | PostgreSQL | Loopback | Nothing | ohm-pgbouncer | The connection pooler, once installed |
| 8000 | TCP | Every interface | Nothing | ohm-portainer | Portainer's tunnel for its Edge agents, while installed. The product does not use it: keep it closed |
| 8081 | HTTP | Loopback | Your addresses | ohm-pgadmin | pgAdmin. It answers the server itself only, whatever the script allows: reach it through an SSH tunnel |
| 5511 | HTTP | Every interface | Your addresses | ohm-metabase | Analytics, once installed |
| 5512 | HTTPS | Every interface | Your addresses | ohm-metabase | Analytics, with the management certificate |
| 9000 | HTTP | Every interface | Your addresses | ohm-portainer | Portainer, while installed |
| 9443 | HTTPS | Every interface | Your addresses | ohm-portainer | Portainer, while installed |
| 2222 | SSH | Every interface | Your addresses | ohm-ssh | The SSH gateway for developers, while it is switched on. The port can be moved; the script names 2222 |
| 5680-5779 | TCP | Every interface | Your addresses | ohm-<id> | An instance's debugger, while remote debugging is on for it |
| 6680-6779 | HTTP | Every interface | Your addresses | ohm-<id> | An instance's own HTTP port, while remote debugging is on for it |
Only the web server on 80 and 443 is in front of the instances. Every other port is answered by its service directly, without the web server's protection, so keep each one closed to everyone but your administrators: with the firewall script, a provider firewall that admits the same list from the same addresses, or a VPN.
The script opens 80 and 443 to everyone and every port marked "Your addresses" to the addresses you
give it, and refuses everything else. pgAdmin, analytics, the SSH gateway and the debugger ranges are
published by a container, which Docker lets past UFW's own rules; the script therefore writes the
same allow-list into Docker's DOCKER-USER chain as well. Get it and run it as
Restricting the management ports
shows.
The server's own containers, the Odoo instances and the code editors among them, cannot open a
connection to the agent, the management API, the console or Portainer at all: the server keeps a firewall rule
of its own for that, puts it back whenever the agent starts, and takes it away when the product is
removed. A firewall tool that reloads the server's rules, such as ufw reload, removes it until
sudo systemctl restart ohm-agent.
The consoles on port 443
The console, pgAdmin, Portainer and Metabase can also be served on port 443, at
https://<the server's host name>/admin, /pgadmin, /portainer and /metabase. That is no
longer a switch on Configuration > General: a console is served there while a rule on
Security > Firewall > Rules > Published (443) governs it, and those rules decide who reaches it.
The web server that serves your instances passes every request on with the visitor's own address,
so the sign-in limits and the audit trail keep seeing the person rather than the web server. See
Publishing consoles on port 443.
With no enabled rule on Published (443) the site is removed; the consoles stay on their own ports.
Trusted proxies
Configuration > Network > Trusted proxies lists the proxies, load balancers or tunnels that forward visitors to this server: addresses or CIDR ranges, comma separated. A listed proxy is believed when it names the visitor it forwards for, so the access rules, the sign-in limits and the audit trail see the visitor rather than the proxy. The list applies to the web server on ports 80 and 443 (the instances and the consoles published on port 443) and to the console and the management API on their own ports. A range may be no wider than /8 for IPv4 or /32 for IPv6. An instance's own Trusted proxies, on its Configuration page, can be changed by an Administrator only; an Operator sees them read-only.
A program on the server itself that forwards to port 443, such as a tunnel agent reaching
localhost:443, arrives at the web server from an address of the server's own container network
rather than from loopback. List that address to trust it; the untrusted proxy notice names it.
Fail2Ban and CrowdSec never ban a listed proxy. CrowdSec also never bans this server itself, the addresses in its own whitelist or the proxies an instance lists for itself, and judges every other address, private networks included. A load balancer or proxy on your own network that is not listed can therefore be banned, and everyone behind it with it. After changing an instance's own Trusted proxies, use Install on the CrowdSec tab to bring CrowdSec's whitelist up to date.
A proxy that forwards without being listed is not trusted: everybody behind it looks like the proxy. Administrators then see a notice on every console page and the server raises the Untrusted proxy alert. List the proxy if it is yours.
Behind a listed proxy, a Fail2Ban ban cannot block the visitor at the host firewall, which only sees the proxy's address. The web server refuses the banned address the proxy forwards instead, with a 403, within half a minute of the ban and until it is lifted. See Intrusion prevention.
The instances are watched the same way: a proxy in front of an instance's site that is not listed is named in the notice, on the instance's Configuration tab and on the Fail2Ban and CrowdSec tabs. Trust this proxy on the notice adds it to this list and applies it. An instance's own Trusted proxies field, when filled, replaces this list for that instance, so a proxy in front of such an instance belongs there.
The provisioning domain
An instance created, cloned or restored without a host name of its own is named after its id.
Configuration > Network > Provisioning domain decides the rest of the name: with a domain such
as customers.example.com set, the instance is named <id>.customers.example.com; with none, which
is the default, it is named <id>.localhost, which only this server can reach.
The names have to point at this server, so the Domain field needs a wildcard DNS record,
*.customers.example.com, of type A (and AAAA when the server has an IPv6 address) with the
server's public address. Check the wildcard record resolves a random name under the domain and
says whether it reaches this server; a record that is not in place yet is a warning, never a
refusal, because the record is often created after the setting.
Only new instances use the domain: setting, changing or clearing it renames no instance. A
development copy always keeps its localhost name, and so does every instance on a
workstation or on the Developer edition. The domain is saved with the
page's Save; nothing on the host is applied for it.
From the command line, on the server or with --server:
pelmo$ ohm server config domain showpelmo$ ohm server config domain set customers.example.compelmo$ ohm server config domain clearshow also prints the name an instance created now without one would get. set accepts
*.customers.example.com too. The installer takes the domain from the bootstrap document's
provisioningDomain, --provisioning-domain or ANTELAO_INSTALL_PROVISIONING_DOMAIN. See
Install the server.
Cloud metadata
On a cloud server, the address 169.254.169.254 answers with facts about the machine and, when the
machine has a cloud identity (an AWS instance role, an Azure managed identity, a Google Cloud
service account), with credentials for that cloud account. On Azure, 168.63.129.16 serves the
machine's agent as well.
Configuration > Network > Cloud metadata carries Block the cloud metadata addresses, which is
on by default. With it on, the Odoo instances and the other containers on the server's networks
cannot reach either address, so an Odoo module cannot pick up those credentials. Name lookups
through 168.63.129.16 keep working, and the server itself and its management services are not
affected. Switch it off only for a module that needs the cloud's metadata.
It takes effect when the server configuration is applied, and again after every restart of the server or of Docker. A reload of the server's firewall does not lift it for long either: the server checks the block every minute and puts back what a reload took away, and the UFW ruleset carries the block itself from 0.24.0 on.
The outbound proxy
For a network that lets nothing out except through a proxy, Configuration > Network > Outbound
proxy names the proxy the server sends its Internet traffic through: its address
(http://host:port, or https://host:port for a proxy that speaks TLS itself), an optional user
name and password, and a list of names that go out directly. Empty, which is the default, sends
everything out directly. The password is stored encrypted and is never shown again; leave the field
empty to keep it.
Test the proxy sends one request through the proxy as it is entered on the card, saved or not, and says "The outbound proxy works (answered in 53 ms)." or "The outbound proxy did not work:" and the reason - a proxy that wants a password it does not get answers 407.
Saving applies it at once. With a proxy set:
- The management service and the host agent send their own requests through it: the license
check-in, the update checks (Docker Hub,
nightly.odoo.com, GitHub), the GeoIP account check, GitHub and GitLab sign-in and lookups, the payment providers' address lists, backup storage at your provider, the management plane link, the speed test and the Internet card. - Image pulls go through it: Docker is given the proxy. Docker reads it when it starts, so a
Docker that keeps its containers running across a restart (
"live-restore": true) is restarted for you a few seconds after the save; any other Docker uses the proxy for pulls after its next restart, which is yours to choose, because it stops every instance with it. - Image builds pass it to the build, so the package and Python downloads inside them use it.
- Module downloads from git use it.
- The GeoIP service and CrowdSec are recreated with it, and certificate requests use it.
- A Python package install inside an instance gets it for that one command.
- The host's own package updates get it: the server writes a package manager setting for it.
Always direct, whatever the list says: this machine itself (localhost, 127.0.0.1, ::1), the
server's host name, and every instance's name and host names; ohm server config proxy show
lists them. The Odoo instances themselves are never given the proxy: an instance on a server without a
way out stays without one.
Some traffic cannot go through an HTTP proxy:
| Traffic | What happens |
|---|---|
| Outgoing mail (SMTP) | Not through the proxy. The mail relay needs its own way out to your mail server |
| FTP backup targets | Not through the proxy. They need their own way out |
| Odoo's upgrade service | Cannot go through a proxy, so an Enterprise database upgrade is refused on a server with a proxy set |
| The DNS record checks | Asked over HTTPS (cloudflare-dns.com, dns.google) through the proxy instead of DNS on port 53 |
| The Internet card | Times a connection opened through the proxy, and says so. The public address it shows is the proxy's, not the server's |
| Alert webhooks | Sent through the proxy. The proxy resolves the name, so the check of the address a webhook resolves to is the proxy's to make |
Clearing the address takes everything back out again: Docker's and the package manager's settings, and the proxy in the GeoIP and CrowdSec containers.
From the command line, on the server or with --server:
pelmo$ ohm server config proxy set --url http://proxy.example.com:3128 --username ohm --passwordpelmo$ ohm server config proxy testpelmo$ ohm server config proxy showpelmo$ ohm server config proxy clear--password asks for the password at a masked prompt; --password-file and --password-stdin read
it from a file or standard input. --no-proxy takes the list of names that go out directly.
What the server reaches
For your proxy's allow-list. Which of these you need depends on what you use; everything else in the list can stay closed.
| Address | What for |
|---|---|
packages.antelao.io | The package, the installer and its scripts, and the proxy test |
ghcr.io, pkg-containers.githubusercontent.com | The product's images |
license.antelao.io, license.antelao.app | The license check-in and activation |
antelao.io | Bug reports and feature requests sent from the Support page to Antelao's helpdesk |
registry-1.docker.io, auth.docker.io, production.cloudflare.docker.com, hub.docker.com | The Odoo and service images, and the update check's look at their tags |
nightly.odoo.com | Odoo's nightly builds, for images built from Odoo's own recipe and the update check |
upgrade.odoo.com, and Odoo's upgrade servers on ports 32768 to 60999 | Upgrading Enterprise databases. Direct only, never through the proxy |
github.com, api.github.com, codeload.github.com, objects.githubusercontent.com | Odoo's and your modules' code, commit lookups, GitHub sign-in for developers, support tickets |
gitlab.com, or your own git server | Modules hosted there |
deb.debian.org, security.debian.org, archive.ubuntu.com, pypi.org, files.pythonhosted.org, registry.npmjs.org, apt.postgresql.org, www.postgresql.org | The packages image builds install |
download.maxmind.com | The GeoLite2 databases, with a MaxMind account |
hub-cdn.crowdsec.net, api.crowdsec.net | CrowdSec's collections and community blocklist, when CrowdSec is on |
acme-v02.api.letsencrypt.org, and your DNS provider's API | Let's Encrypt certificates |
stripe.com, api.paddle.com, ip-ranges.mollie.com | The payment providers' webhook addresses, for the Payments firewall rules |
open-vsx.org | Extensions for the browser editor |
Your backup storage: *.blob.core.windows.net, management.azure.com, login.microsoftonline.com, *.backblazeb2.com, *.r2.cloudflarestorage.com, api.cloudflare.com, your S3 endpoint | Backups at your provider |
| Your management plane and your alert webhooks | When you use them |
api.anthropic.com, api.openai.com, your Azure OpenAI resource's endpoint | Diagnose, for the AI providers that are switched on |
challenges.cloudflare.com | Cloudflare Turnstile on the console's sign-in, when it is on |
cloudflare-dns.com, dns.google | The DNS record checks |
www.microsoft.com, www.cloudflare.com, www.google.com, speed.cloudflare.com, ipv4.icanhazip.com, ipv6.icanhazip.com, ifconfig.co | The Internet card, the speed test and the public address readouts |
Your distribution's package mirrors, download.docker.com | The host's own package updates |
Installing behind a proxy
The installer downloads the package and the first images before the server exists to apply its own setting, so on a host that has no direct way out, give the package manager and Docker the proxy first:
# The package manager
echo 'Acquire::http::Proxy "http://proxy.example.com:3128/";
Acquire::https::Proxy "http://proxy.example.com:3128/";' | sudo tee /etc/apt/apt.conf.d/80proxy
# Docker (merge into an existing /etc/docker/daemon.json rather than replacing it)
echo '{ "proxies": { "http-proxy": "http://proxy.example.com:3128",
"https-proxy": "http://proxy.example.com:3128", "no-proxy": "localhost,127.0.0.1,::1" } }' \
| sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
Then run the installer with HTTPS_PROXY exported for its own download, and put the same proxy in the
bootstrap document's outboundProxy, so the server takes it over. Once the server has applied its own
setting, remove your 80proxy file: the server writes its own.
The master database schema
The schema is owned by the application and upgraded forward. The upgrade is forward-only: an older binary refuses to start against a newer schema, so rolling a release back means restoring the database from before the upgrade too.
Updating the containers does not by itself upgrade the schema, and neither does Apply Update in the console. When a build expects a newer one than the database carries, the API refuses to start and says so, and this is the way past it:
$ sudo ohm database upgradeohm install does the same as part of a repair, before it rolls any container.
Global options
Five options are on the root command and therefore on every command. They are omitted from the tables in the command reference.
| Option | Meaning |
|---|---|
-v, --verbosity <level> | Debug, Error, Fatal, Info, None, Trace or Warn for this invocation |
--error-action <action> | Continue, SilentlyContinue or Stop. Default Stop |
--server <name|url> | Run against a stored connection or a management API URL |
--token <key> | The API key for remote mode |
--local | Force local execution even when a connection is configured |
Three more appear on the commands that can use them rather than on all of them: -y, --yes to
answer confirmations for unattended use, -f, --force to recreate or overwrite instead of reusing
what exists, and --show-secrets to print credentials unmasked instead of ****.
Environment variables
| Variable | Used by | Purpose |
|---|---|---|
OHM_API_URL | ohm | Default management API endpoint for remote mode |
OHM_API_KEY | ohm | The API key for remote mode |
ANTELAO_INSTALL_* | ohm install | The installer's answers, when they are not being prompted for. See Install the server |
ANTELAO_BOOT_* | ohm-agent | The agent's entire configuration, in /etc/antelao/agent.env. Written by ohm install; the line below and ANTELAO_BOOT_ALLOW are the ones you may change by hand |
ANTELAO_INSTALL_OUTBOUND_PROXY_URL, _USERNAME, _PASSWORD, _NO_PROXY | ohm install | The outbound proxy, over the bootstrap document's outboundProxy; the password is stored encrypted |
ANTELAO_INSTALL_PROVISIONING_DOMAIN | ohm install | The provisioning domain, over the bootstrap document's provisioningDomain |
ANTELAO_INSTALL_TURNSTILE_SITE_KEY, ANTELAO_INSTALL_TURNSTILE_SECRET_KEY | ohm install | The keys of Cloudflare Turnstile, stored by the install (the secret encrypted). Both or neither |
ANTELAO_BOOT_TURNSTILE_BYPASS | ohm-agent | true turns Turnstile on the console sign-in off once ohm install has recreated the management containers, and wins over the setting. The emergency line you may add by hand; a repair keeps it. The faster way is ohm server turnstile disable |
Who may reach the agent
The agent answers HTTPS on 5202 on every interface, like the other management ports, and plain HTTP
on 5201 on the server itself only. Its key is the protection, and ANTELAO_BOOT_ALLOW in
/etc/antelao/agent.env says from which addresses the key may be presented. Loopback is always
admitted.
ANTELAO_BOOT_ALLOW | Who reaches the agent |
|---|---|
| Empty | Every address, and the key alone protects the page |
| Addresses or CIDR ranges | Those and the server itself. Any other address gets a bare "403 Forbidden" with no explanation; the agent's log records the refusal |
ohm install writes it, and its default depends on whether you gave management addresses at
install (--api-allow, or ANTELAO_INSTALL_API_ALLOW):
- Without management addresses the list is empty: every address may reach the agent's page, behind its key. This is what lets you reach the page from a browser elsewhere when the console is down.
- With management addresses the list is this server's own addresses and those, and every other address is refused.
ANTELAO_INSTALL_AGENT_ALLOW writes any list you choose instead, for example
sudo ANTELAO_INSTALL_AGENT_ALLOW=203.0.113.7,10.8.0.0/24 ohm install, and so does editing
ANTELAO_BOOT_ALLOW by hand followed by sudo systemctl restart ohm-agent. ohm install prints who
may reach the agent under its address.
An existing server keeps a list you wrote, on every install and update. Two lists an earlier release
wrote without anyone choosing them are replaced by the default above on the next install: every
address (0.0.0.0/0,::/0), and the server's own addresses alone. On a server installed without a
management address that default is the empty list, so the agent's page stays open to every address
behind its key. To keep 0.0.0.0/0,::/0 as it is, run the install with
ANTELAO_INSTALL_AGENT_ALLOW=0.0.0.0/0,::/0. Plain HTTP that answered on every interface is moved to
the loopback.
While the list names 0.0.0.0/0 or ::/0, the agent's Dashboard and ohm install warn that its key
is the only protection.