<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Mail: failed Solr/Tika readiness check on boot silently disables all inbound mail, while healthcheck reports green]]></title><description><![CDATA[<hr />
<p dir="auto"><strong>Category:</strong> Support / Mail</p>
<hr />
<p dir="auto"><a class="plugin-mentions-group plugin-mentions-a" href="/groups/staff" aria-label="Profile: staff">@<bdi>staff</bdi></a> could you please take a look at this as mail is not working?</p>
<p dir="auto">Cloudron 9.0.0, mail image <code>cloudron/mail:4.3.5</code>.</p>
<p dir="auto">After a reboot of a reasonably busy server, inbound mail was dead for nearly three hours. The dashboard showed the mail service healthy for all of it. There are four separate issues tangled together here, and the last two are what turned a bad morning into a long one.</p>
<h3>1. A slow Solr start takes Haraka and Spamd down with it</h3>
<p dir="auto"><code>services.js</code> starts things in this order:</p>
<pre><code class="language-js">async function start() {
    await dovecot.start(); // start this before solr in case the fts has to be re-indexed
    await fts.start();
    await haraka.start();
    await spamd.start();
    ...
}
</code></pre>
<p dir="auto">On our boot, Solr exceeded the readiness timeout:</p>
<pre><code>08:55:47  Error: Could not verify fts readiness: Timed out waiting for solr/tika readiness
            at Object.start (/app/code/fts.js:286:27)
            at async Object.start (/app/code/services.js:32:5)
08:57:26  solr core "dovecot" comes up normally (14,093 docs)
</code></pre>
<p dir="auto">Solr was fine, just about a hundred seconds slower than the check allowed, because the whole box was contending after a reboot. But the throw propagated out of <code>start()</code>, so <code>haraka.start()</code> and <code>spamd.start()</code> never ran:</p>
<pre><code>dovecot        RUNNING
haraka         STOPPED   Not started
spamd          STOPPED   Not started
mail-service   RUNNING
solr           RUNNING
tika           RUNNING
</code></pre>
<p dir="auto">Full-text search is a search index. It seems wrong for it to be a hard prerequisite of SMTP. Could <code>fts.start()</code> be made non-fatal, logging and continuing with a background retry, or simply moved after <code>haraka.start()</code>? Either would have turned a three-hour mail outage into a temporarily degraded search box.</p>
<h3>2. The healthcheck reports green while all mail is being rejected</h3>
<p dir="auto">Throughout the outage, and afterwards in the broken state described below:</p>
<pre><code class="language-json">{"status":true,"haraka":{"status":true},"dovecot":{"status":true},"spamd":{"status":true},
 "redis":{"status":true},"solr":{"status":true},"tika":{"status":true}}
</code></pre>
<p dir="auto">This is because <code>getHealth()</code> is process liveness only:</p>
<pre><code class="language-js">const out = safe.child_process.execSync(`supervisorctl status ${program} | grep RUNNING`, ...);
health[program].status = out &amp;&amp; out.includes('RUNNING');
</code></pre>
<p dir="auto">A running Haraka that rejects every recipient is reported exactly like a working one. Would it be reasonable for the healthcheck to assert that <code>/run/haraka/config/host_list</code> is non-empty whenever at least one domain has <code>inbound</code> set? That single check would have caught both this and issue 3.</p>
<h3>3. Starting Haraka by hand skips config generation, and makes things worse</h3>
<p dir="auto">Seeing <code>haraka STOPPED</code>, the obvious operator move is:</p>
<pre><code>docker exec mail supervisorctl start haraka spamd
</code></pre>
<p dir="auto">Both come up RUNNING, the healthcheck goes green, and SMTP answers on 25 and 587. It looks fixed. It is not. <code>haraka.start()</code> is not just <code>supervisorctl start haraka</code>:</p>
<pre><code class="language-js">async function start() {
    const [syncConfigError] = await safe(syncConfig());
    if (syncConfigError) throw new Error(...);
    safe.child_process.execSync('supervisorctl start haraka', ...);
}
</code></pre>
<p dir="auto"><code>syncConfig()</code> is what writes <code>/run/haraka/config/host_list</code> and populates the DKIM runtime directory. Starting the daemon directly skips it, so Haraka runs with an empty host list and no DKIM keys. The result:</p>
<pre><code>RCPT TO:&lt;valid-mailbox@example.com&gt;     550 I cannot deliver mail for &lt;valid-mailbox@example.com&gt;
RCPT TO:&lt;nosuchuser@example.com&gt;        550 No such address
</code></pre>
<p dir="auto">Note the asymmetry, which is what misled us for a while: the <em>invalid</em> address gets the correct "No such address" from the <code>cloudron</code> plugin, proving the plugin is loaded and knows the domain. The <em>valid</em> address falls through to Haraka's core rejection in <code>connection.js</code>, because the <code>cloudron</code> plugin calls plain <code>next()</code> for a good mailbox and relies on <code>rcpt_to.in_host_list</code> to accept it, and <code>host_list</code> is empty.</p>
<p dir="auto"><strong>This state is worse than the service simply being down.</strong> With Haraka stopped, port 25 refuses connections and sending servers queue and retry for days, so nothing is lost. With Haraka running against an empty host list, every sender gets a permanent 550 and gives up. Mail is destroyed rather than delayed.</p>
<p dir="auto">Two suggestions:</p>
<ul>
<li>Have Haraka refuse to serve, or exit, when <code>host_list</code> is empty while inbound domains are configured. Failing closed at connect level is far safer than 550-ing real mail.</li>
<li>Consider a comment or a guard around the <code>supervisorctl</code> entries, since <code>supervisorctl start haraka</code> is the natural thing for an operator to type and it is silently wrong.</li>
</ul>
<h3>4. <code>POST /mail/&lt;domain&gt;/inbound</code> returns 202 without applying anything</h3>
<p dir="auto">Having worked out that the runtime config needed regenerating, the natural way to trigger it looks like a no-op write of a domain's existing inbound setting. It answers a confident <code>202</code> and does nothing relevant:</p>
<pre><code class="language-js">async function setDomainInbound(domain, enabled, auditSource) {
    const result = await database.query('UPDATE mail SET inbound = ? WHERE domain = ?', );
    if (result.affectedRows === 0) throw new MailError(...);
    await boxEventlog.add(...);
}
</code></pre>
<p dir="auto">There is no call to <code>restartHarakaService()</code>. It is defined at <code>domains.js:11</code> but called only from lines 92, 128 and 143, and the route returns <code>202</code> unconditionally. <code>host_list</code> stayed empty and Haraka's uptime never reset. Would it be worth having domain setters that change delivery-relevant state trigger a reconfigure, or at least not report success when nothing was applied?</p>
<h3>The recovery, for anyone who lands here</h3>
<p dir="auto">The underlying config is untouched in the database; only Haraka's runtime copy is missing. A no-op write of the existing max email size triggers <code>haraka.reconfigure()</code>, which regenerates <code>host_list</code> and the DKIM keys and restarts Haraka, without touching Dovecot and without re-running the fts check. It also returns <code>503</code> with a real error if the reconfigure fails, rather than an unconditional success:</p>
<pre><code>GET  /max_email_size?access_token=$CLOUDRON_MAIL_TOKEN     -&gt; {"size":25000000}
POST /max_email_size?access_token=$CLOUDRON_MAIL_TOKEN
Body: {"size": 25000000}                                    (write back the same value)
</code></pre>
<p dir="auto">Verify all three of these, because the first two can look right while mail is still broken:</p>
<pre><code>cat /run/haraka/config/host_list      # your inbound domains
ls  /run/haraka/config/dkim           # one directory per domain
supervisorctl status haraka           # uptime MUST reset to seconds
</code></pre>
<p dir="auto">A Haraka uptime that has not reset means the reconfigure did not run, whatever the HTTP code said. Then test a real recipient over SMTP. A valid mailbox must return 250 where it previously returned <code>550 I cannot deliver mail for</code>, while a genuinely unknown address should still return <code>550 No such address</code>.</p>
<p dir="auto">One last note for anyone probing SMTP by hand: Haraka applies a greeting delay to unknown clients, so a short-timeout probe reports failure against a perfectly healthy server. Allow at least 20 seconds before concluding the port is dead.</p>
]]></description><link>https://forum.cloudron.io/topic/15926/mail-failed-solr-tika-readiness-check-on-boot-silently-disables-all-inbound-mail-while-healthcheck-reports-green</link><generator>RSS for Node</generator><lastBuildDate>Mon, 14 Sep 2026 19:39:24 GMT</lastBuildDate><atom:link href="https://forum.cloudron.io/topic/15926.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 07 Sep 2026 11:24:30 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Mail: failed Solr/Tika readiness check on boot silently disables all inbound mail, while healthcheck reports green on Tue, 08 Sep 2026 05:14:38 GMT]]></title><description><![CDATA[<blockquote>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/loudlemur" aria-label="Profile: LoudLemur">@<bdi>LoudLemur</bdi></a> <a href="/post/129148">said</a>:</p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/necrevistonnezr" aria-label="Profile: necrevistonnezr">@<bdi>necrevistonnezr</bdi></a> has a valid point, too. What else can we do, though? "Understand it better?" This problem meant people were not receiving emails. Not sending a bug report, particularly when the ai had found a fix, didn't seem public spirited. It also is a bit like self-censorship.</p>
</blockquote>
<p dir="auto">It’s pretty simple: Read the output, work with it it, make it your own. Don‘t just forward it unfiltered. If that’s too much, leave it.</p>
<p dir="auto">In case of a bug report, if you don’t want to put in the work, what’s the point? How does the team know your report was verified by you and has merits? It would probably more helpful to leave the team your result in 3-4 sentences and provide the prompt - then they can see for themselves.</p>
]]></description><link>https://forum.cloudron.io/post/129156</link><guid isPermaLink="true">https://forum.cloudron.io/post/129156</guid><dc:creator><![CDATA[necrevistonnezr]]></dc:creator><pubDate>Tue, 08 Sep 2026 05:14:38 GMT</pubDate></item><item><title><![CDATA[Reply to Mail: failed Solr/Tika readiness check on boot silently disables all inbound mail, while healthcheck reports green on Mon, 07 Sep 2026 20:44:44 GMT]]></title><description><![CDATA[<blockquote>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/marcusquinn" aria-label="Profile: marcusquinn">@<bdi>marcusquinn</bdi></a> <a href="/post/129142">said</a>:</p>
<p dir="auto">We're pretty-much now in the age of: "I'll have my AI speak to your AI, and TLDR me the results."</p>
<p dir="auto">Wild times.</p>
</blockquote>
<p dir="auto">It is like Hollywood: "I'll have my people talk to your people and we can figure out a time to have lunch."</p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/necrevistonnezr" aria-label="Profile: necrevistonnezr">@<bdi>necrevistonnezr</bdi></a> has a valid point, too. What else can we do, though? "Understand it better?" This problem meant people were not receiving emails. Not sending a bug report, particularly when the ai had found a fix, didn't seem public spirited. It also is a bit like self-censorship.</p>
<p dir="auto">On the other hand, Cloudron has a policy about no AI generated text in the forum. This is just one case where there is an AI bug report. <a class="plugin-mentions-user plugin-mentions-a" href="/user/girish" aria-label="Profile: girish">@<bdi>girish</bdi></a> kindly found the time to investigate it. In the future, there may be many AI bug reports and human intervention might not be able to handle them all.</p>
<p dir="auto">There are arguments for and against both sides. It does seem rude though to paste a load of AI and expect a human to look at it. I know what you mean.</p>
]]></description><link>https://forum.cloudron.io/post/129148</link><guid isPermaLink="true">https://forum.cloudron.io/post/129148</guid><dc:creator><![CDATA[LoudLemur]]></dc:creator><pubDate>Mon, 07 Sep 2026 20:44:44 GMT</pubDate></item><item><title><![CDATA[Reply to Mail: failed Solr/Tika readiness check on boot silently disables all inbound mail, while healthcheck reports green on Mon, 07 Sep 2026 18:35:15 GMT]]></title><description><![CDATA[<p dir="auto">We're pretty-much now in the age of: "I'll have my AI speak to your AI, and TLDR me the results."</p>
<p dir="auto">Wild times.</p>
]]></description><link>https://forum.cloudron.io/post/129142</link><guid isPermaLink="true">https://forum.cloudron.io/post/129142</guid><dc:creator><![CDATA[marcusquinn]]></dc:creator><pubDate>Mon, 07 Sep 2026 18:35:15 GMT</pubDate></item><item><title><![CDATA[Reply to Mail: failed Solr/Tika readiness check on boot silently disables all inbound mail, while healthcheck reports green on Mon, 07 Sep 2026 17:21:35 GMT]]></title><description><![CDATA[<p dir="auto">Right, I don't read AI stuff myself <img src="https://forum.cloudron.io/assets/plugins/nodebb-plugin-emoji/emoji/android/1f642.png?v=ef90891ebe9" class="not-responsive emoji emoji-android emoji--slightly_smiling_face" style="height:23px;width:auto;vertical-align:middle" title=":-)" alt="🙂" /> But since this was a bug report I fed it into another AI and got something meaningful out of it.</p>
<p dir="auto">I think the issue is that solr (fts) start up failure blocks all mail from starting. On top, there is a bug that gives incorrect notification that mail is running. Both these are fixed . The points 3,4 are not correct since the mail server API is not public and meant to be used via the box code . I guess the enthusiastic AI went straight into the mail container and started having some fun.</p>
]]></description><link>https://forum.cloudron.io/post/129141</link><guid isPermaLink="true">https://forum.cloudron.io/post/129141</guid><dc:creator><![CDATA[girish]]></dc:creator><pubDate>Mon, 07 Sep 2026 17:21:35 GMT</pubDate></item><item><title><![CDATA[Reply to Mail: failed Solr/Tika readiness check on boot silently disables all inbound mail, while healthcheck reports green on Mon, 07 Sep 2026 16:27:27 GMT]]></title><description><![CDATA[<p dir="auto">Sorry, but pushing a wall of unread and unrefined AI-output is just super-rude.</p>
]]></description><link>https://forum.cloudron.io/post/129138</link><guid isPermaLink="true">https://forum.cloudron.io/post/129138</guid><dc:creator><![CDATA[necrevistonnezr]]></dc:creator><pubDate>Mon, 07 Sep 2026 16:27:27 GMT</pubDate></item><item><title><![CDATA[Reply to Mail: failed Solr/Tika readiness check on boot silently disables all inbound mail, while healthcheck reports green on Mon, 07 Sep 2026 15:30:37 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/loudlemur" aria-label="Profile: loudlemur">@<bdi>loudlemur</bdi></a> I think some of the issues are valid, fixing.</p>
]]></description><link>https://forum.cloudron.io/post/129136</link><guid isPermaLink="true">https://forum.cloudron.io/post/129136</guid><dc:creator><![CDATA[girish]]></dc:creator><pubDate>Mon, 07 Sep 2026 15:30:37 GMT</pubDate></item></channel></rss>