Troubleshooting Blocklist
Organised by what you see. Start with the API's own log, which names most causes in a sentence. From the folder that holds docker-compose.yml:
sudo docker compose logs blocklist --tail 200
sudo docker compose logs blocklist-ui --tail 200
The console's Jobs page shows how every change and every refresh ended, with the reason for each
failure; GET /api/v1/jobs (with your X-Api-Key) returns the same.
Checks
| Symptom | Cause | Fix |
|---|---|---|
Every answer says "unlicensed": true | The service is not licensed, or its license lapsed | Open the License page, which says why. See Licensing and the license rows below |
| A check answers 400 with a sentence | The address, the domain or the IP cannot be read, or nothing was named | The sentence says which; see Asking. In a batch, the sentence names the check (Check 3: ...) and nothing in the batch is answered |
| A domain you know is a throwaway domain is not listed | The list that holds it is switched off, not covered by the license, or has not been downloaded yet; or you made an exception for it | Look at the list's card on the Blocklists page: Checked, Entries and Refreshed, and the exceptions in the entries. See The public lists |
| A domain your customers use is listed | A public list holds it | Add an Exception of that list for the domain on the Blocklists page. See Exceptions |
mail is always null | The check did not ask for it ("mailDomain": true), the client IP was already listed, or the license does not carry the mail-domain check | Ask for it, or see the License page's Checking that a domain receives mail row |
mail is often unknown | DNS did not answer in time, or answered with a failure, from inside the container | Check the container's resolvers (sudo docker compose exec blocklist cat /etc/resolv.conf). unknown never lists anything, so no visitor is refused for it |
| An entry just added is not matched | Its job has not finished, or failed | Read its job on the Jobs page. An entry is checked against from the moment its job succeeds |
| Checks answer 429 | The rate limit is on and the key went over it | Wait the Retry-After seconds, or raise the limit on the Options page. See Rate limits |
| Checks answer an empty 404 from one place only | The firewall's Checks door does not admit that address | Add the address on Security > Firewall, Checks tab. The Log tab names the rule that refused it. See Firewall |
Public lists and refreshes
| Symptom | Cause | Fix |
|---|---|---|
| A list is missing from the Blocklists and Maintenance pages | The license does not carry its feature | See the License page, and Licensing |
A refresh fails with could not be downloaded | A firewall or a proxy between this host and the list's publisher | Let the API container reach the hosts on the list's Source line over HTTPS. See Outbound access. The entries in force were kept |
A refresh fails as a broken download, not a refresh | The file that arrived holds far fewer entries than a sound copy of the list | Usually passing: try Run now later. The entries in force were kept |
Refresh now or Run now is refused with may be downloaded at most once every 24 hours | The list allows one download a day, and it was downloaded less than 24 hours ago | Wait until the time the message names. The scheduled refresh picks it up on its own. See A list with a daily limit |
Saving a list's schedule is refused with choose daily, weekly or every 24 hours or more | The schedule would download a list with a daily limit more often | Choose daily, weekly, or every 24 hours or more |
| Refresh now answers that a refresh is already queued or running (409) | One is on its way | Follow it on the Jobs page |
| No list is ever refreshed on its own | Blocklist__ScheduledRefresh=false in the environment, or the task is off on the Maintenance page | Remove the variable and restart, or switch the task on |
A list's card says never: nothing is checked until the first refresh | It has not been downloaded yet: a new list is refreshed a minute after the service starts | Wait a minute, or Run now. If it stays, read its last run on the Maintenance page |
| A job is Interrupted | The service stopped while it ran | Check what it changed, and ask again |
Licensing
| Symptom | Cause | Fix |
|---|---|---|
| The License page says the license is bound to another machine | The license was activated on another host, or /etc/machine-id is not mounted and the recreated container looks like a new machine | Mount /etc/machine-id read-only as in the compose file. Moving a license to another host: see Moving a license |
| The hardware challenge on the License page changes after every recreate | /etc/machine-id is not mounted | Mount it, recreate the container, and activate again if the license was activated for the old challenge |
| The license worked for two weeks, then stopped | It was never activated, or no check-in has got through for 14 days | Activate online on the License page. Let the container reach the internet for its daily check-in |
| A license restored from a backup is not in force | A license that arrives with a restore is read at the next start | Restart the container: sudo docker compose restart blocklist |
The start-up log says running unlicensed | The reason follows in brackets: no license of its own, a sponsorship that no longer holds, or a refused offer | Install or activate a license, or, when another product sponsors this service, look at that product's license |
The license's lists and sponsorships:
| Symptom | Cause | Fix |
|---|---|---|
| A list the license should carry shows Disabled on the License page | The license does not carry that list's feature, or it carries it without the base feature | Compare the Features table with what was bought. See Licensing |
| The License page shows a refused sponsorship | An offer came from a product that may not sponsor this service, or its license did not verify | The page names the product and the reason. Only an Odoo Host Manager license sponsors this service |
API keys and sign-in
| Symptom | Cause | Fix |
|---|---|---|
| Every call answers 401 | The X-Api-Key header is missing, or the key is wrong, revoked or expired | Send a configured key (Api__Keys__<name>) or a live issued one. A configured key always works: it cannot be revoked through the API |
| Every call from one address answers an empty 404, while checks still answer | The address is banned by threat protection, after too many wrong keys or passwords | Lift the ban on Security > Threat protection, and put the address on the whitelist if it is your own. See Threat protection |
A POST, PUT or DELETE answers 403 This API key is read-only, so it may only issue GET requests and checks. | The key was issued read-only | Use a key that is not read-only |
| A call with a session answers 401 | The person's session has ended | Sign in again |
| A call or a console action answers 403 | The signed-in account's role does not allow it | An administrator changes the role on the Users page. See Roles |
| Nobody can sign in to the console as admin | The password is forgotten, or the account is locked | Change BLOCKLIST_SEED_ADMIN_PASS and restart the API. On a first start with no value set, read the generated one with sudo docker compose exec blocklist cat /data/first-admin-password |
The console says Too many wrong passwords: this account is locked for fifteen minutes. | Five wrong passwords in a row | Wait fifteen minutes, or have an administrator lift the lock on the Users page |
| Signing in works over an SSH tunnel but not on the server's own name | The console keeps a sign-in only over HTTPS or on localhost | Put a reverse proxy with HTTPS in front of the console. Ui__AllowPlainHttp=true is the alternative for a trusted network only. See the reference |
Every sign-in says The sign-in could not be confirmed. Try again. | Cloudflare Turnstile is refusing: a wrong key, a hostname the widget does not list, or the console cannot reach challenges.cloudflare.com | Start the console with the bypass, fix the cause, and remove the bypass. See Locked out by the check |
| The console answers an empty 404 from everywhere but the server itself | The firewall's Console door does not admit your address | Add it with AccessControl__Surfaces__admin__AllowedIps__0 on the console container and restart it; that entry cannot be removed on the page. See Entries from the deployment |
| The API or the console does not start | An invalid value: an authenticator secret in BLOCKLIST_SEED_ADMIN_TOTP that is not base32 of at least 26 characters, or a trusted proxy entry that is not an address or network | The log's last line, beginning The service did not start, names the setting. Correct it and start again |
Mail and proxies
| Symptom | Cause | Fix |
|---|---|---|
| No ban mail arrives | Send mail is off (Smtp__Enabled is false by default), the settings are incomplete, or nobody is set to receive it | Switch it on, fill in the server, the from address and a recipient, and press the test button. See Mail |
| The test message fails | The mail server refused it, or cannot be reached | The page shows the server's own words. Check the port and the security setting: StartTls on 587, SslOnConnect on 465 |
| Settings in the compose file have no effect on mail | Settings saved on the SMTP page replace the environment's entirely | Change them on the SMTP page, or remove the saved set (DELETE /smtp) to hand control back to the environment |
| The audit log and the session list show one address for everyone | A reverse proxy in front of the console or the API is not named as trusted | Set Ui__TrustedProxies__0 or Api__TrustedProxies__0 to its address and restart that container. The notice on every page names the address. See A proxy that is not trusted |
| Everybody behind the proxy is throttled or banned together | The same cause: every visitor is judged as the proxy | The same fix |
Recording what you did
A bug report describes a problem from memory. A session trace records it.
Start one on the Support page, reproduce the problem, and stop it with the recording button that appears beside your name. What you did is stored by the service and can be attached to a bug report.
A trace lists the pages you opened, the controls you used, and anything that went wrong. It can also save a copy of each page as it looked, which is the only thing that answers it rendered wrong.
A trace records which field you filled, never what you put in it, and the places that show a secret are blanked before anything is written down. A copy of a page still shows whatever that page showed - names, host names, addresses - so read a trace before you send it, as you would a log or a support bundle.
A trace belongs to the tab it was started in, and it names the user it belongs to, so a file can be read back to a person.
What an administrator decides
The Support page carries a Configuration card, and what is set there is what every user gets: whether the recording button sits beside your name at all, how much a trace writes down, and how many session traces the service keeps. Lowering a keep count deletes the files above it as soon as the card is saved.
Attaching it
Download the trace from the Support page and send it to whoever asked for it, privately. Never attach it to a public post: see Getting help.
Getting help
Without a license, ask on the community forum on antelao.io, like any free product: say what you did, what you saw, and quote the error. With a license, write to support@antelao.io.
Never post a backup, a log export or your configuration on the forum or in a public issue. They hold your accounts, your settings and visitors' addresses. When Antelao asks for one, send it privately to support@antelao.io.