Cloudron makes it easy to run web apps like WordPress, Nextcloud, GitLab on your server. Find out more or install now.


Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

Cloudron Forum

Apps - Status | Demo | Docs | Install
imc67I

Marcel C

@imc67
translator
Unfollow Follow
About
Posts
984
Topics
183
Shares
0
Groups
1
Followers
3
Following
0

Posts

Recent Best Controversial

  • Mail app: optional SpamAssassin plugins can't be enabled with their stock rules, and `sa-update` never runs
    imc67I imc67

    haha (sorry) now you experience the same as I do, every hour the newly to be blocked IP's are pushed via API and it takes 4-6 minutes to be processed. That's why I suggested previously in a post to maken it "insert/update/delete" per IP or CIDR.

    Good luck!

    Support spamassassin

  • Mail app: optional SpamAssassin plugins can't be enabled with their stock rules, and `sa-update` never runs
    imc67I imc67

    @girish indeed I noticed git.cloudron.io gave a 403.

    As you might remember I created my own "security monitor" for centrally monitoring and managing 3 Cloudron servers, it's growing with hundreds a day, the list below are lines, the unique IP's are 641.451.742 separate IPv4-adressess:
    Scherm­afbeelding 2026-07-29 om 10.02.05.png

    Support spamassassin

  • Mail app: optional SpamAssassin plugins can't be enabled with their stock rules, and `sa-update` never runs
    imc67I imc67

    sorry @girish it was indeed written by Claude Code Opus 5. But realise that in this AI world I noticed on my 3 Cloudron-servers a huge increase of attacks, spam and phishing (and the last one was once "successful" for one user with nasty results).

    As far as I can see the default "anti-spam / anti-phishing" in Cloudron is absolutely not sufficient, @d19dotca was "the pioneer" here on the forum with custom SA rules and I fight "attackers with AI" with my own "AI" 😃.

    The only thing I ask you devs is to increase attention for "attacks, spam and phishing" and tell me what I can do if you don't/can't.

    Support spamassassin

  • Mail app: optional SpamAssassin plugins can't be enabled with their stock rules, and `sa-update` never runs
    imc67I imc67

    Running three Cloudron servers (9.2.x, mail app 3.18.2, SpamAssassin 4.0.0) with
    about 35 mailboxes between them. While hardening against a run of phishing that
    was getting through, I went looking at how SpamAssassin is set up inside the mail
    container and found a few things that I think are worth sharing — plus some
    questions I couldn't answer from the docs.

    Everything below is reproducible with docker exec mail … on the host.

    1. The optional plugins are off — but that's upstream, not Cloudron

    My first assumption was that Cloudron had disabled them. It hasn't:

    docker exec mail dpkg -V spamassassin
    ??5??????  c /etc/spamassassin/local.cf
    ??5??????  c /etc/spamassassin/v310.pre
    

    Only local.cf and v310.pre differ from the Debian package. v342.pre is
    byte-identical
    , and that is the file holding Phishing, FromNameSpoof,
    DecodeShortURLs, URILocalBL and PhishTag — all commented out exactly as
    upstream ships them. So this is stock SpamAssassin behaviour, and I want to be
    clear I'm not reporting a Cloudron bug here. It only becomes a Cloudron question
    because of point 2.

    For completeness, Cloudron's entire spamd setup is this, from /app/code/start.sh:

    setup_spamd() {
        mkdir -p /run/spamd /app/data/spamd /run/spamd/tmp
        touch /app/data/spamd/custom.cf /app/data/spamd/acl.cf
        chown -R cloudron:cloudron /app/data/spamd /run/spamd
    }
    

    2. loadplugin works from custom.cf, but the stock rules don't come with it

    The only persistent config surface is the Custom SpamAssassin rules field in
    the Email view, which is /app/data/spamd/custom.cf, included at the end of
    local.cf. Anything in /etc/spamassassin/ is reset on app update.

    loadplugin is accepted there and lints clean:

    docker exec mail spamassassin --lint --cf="loadplugin Mail::SpamAssassin::Plugin::FromNameSpoof"
    # exit 0
    

    But it has no effect on the plugin's own rules. Those live in
    /usr/share/spamassassin/72_active.cf behind an ifplugin guard, and that file
    is parsed before local.cf pulls in custom.cf — so by the time the plugin
    loads, the guard has already been evaluated and the rules skipped for good.

    Verified with a message whose From: display name is the recipient's address
    (should trip T_FROMNAME_EQUALS_TO😞

    # without the plugin
    tests=FROM_2_EMAILS_SHORT,…            score=3.0
    
    # with --cf="loadplugin …FromNameSpoof"
    tests=FROM_2_EMAILS_SHORT,…            score=3.0     ← identical
    

    Workaround that does work: load the plugin and redefine the rules yourself
    in custom.cf under your own names. That gives 3.0 → 4.9 on the same message:

    loadplugin Mail::SpamAssassin::Plugin::FromNameSpoof
    
    header   __MY_FROMNAME_SPOOF       eval:check_fromname_spoof()
    header   __MY_FROMNAME_EQUALS_TO   eval:check_fromname_equals_to()
    meta     MY_FROMNAME_SPOOFED_EMAIL (__MY_FROMNAME_SPOOF && !__VIA_ML && !__VIA_RESIGNER && !__RP_MATCHES_RCVD)
    meta     MY_FROMNAME_EQUALS_TO     __MY_FROMNAME_EQUALS_TO
    score    MY_FROMNAME_SPOOFED_EMAIL 0.01
    score    MY_FROMNAME_EQUALS_TO     0.01
    

    It works, but you're maintaining a copy of upstream's rule definitions, which
    will silently drift when SpamAssassin changes them.

    3. sa-update never runs

    This one surprised me more than the plugins:

    docker exec mail ls /var/lib/spamassassin/
    sa-update-keys                                  ← only the keys, no rules dir
    
    docker exec mail ls /etc/cron.d/                ← e2scrub_all, php
    docker exec mail grep -rn sa-update /app/code/start.sh /etc/supervisor/   ← nothing
    

    No versioned rules directory means sa-update has never completed. The static
    rule set is therefore whatever the Debian package ships —
    /usr/share/spamassassin/50_scores.cf is dated 2022-07-01 on my servers.

    In practice this matters less than it sounds, because the adaptive parts are all
    still live: DNSBL/URIBL lookups are DNS queries and always current, Bayes trains
    itself, and custom.cf is mine. But rule updates also carry rescored weights
    from current corpora, and those never arrive.

    I can see why it isn't run: /var/lib/spamassassin isn't persistent, so any
    sa-update result is discarded on the next app update.

    4. Two smaller things

    • The Phishing plugin reads its feed file only in finish_parsing_end, i.e.
      once at spamd startup. Refreshing the feed on disk does nothing until
      supervisorctl restart spamd. I'm doing that from a host cron job; it works,
      but it feels like reaching around the platform.
    • Unrelated to Cloudron, but a time-saver for anyone else wiring up that plugin:
      https://openphish.com/feed.txt is now a 302 to a GitHub raw URL, so curl
      without -L silently writes an HTML error page over your feed. And the
      phishstats.info/phish_score.csv URL in the plugin's own documentation
      currently returns 404.

    Questions

    1. Is there a supported way to load a SpamAssassin plugin early enough that its
      stock ifplugin-guarded rules activate? A persistent .pre — or a second
      textarea next to the custom-rules field that gets written to a .pre — would
      solve it without anyone having to copy upstream rule definitions.
    2. Is not running sa-update a deliberate choice? If so, what's the reasoning,
      and is there a recommended way to keep the static rule set reasonably current
      given that /var/lib/spamassassin doesn't survive an app update?
    3. Would you consider enabling FromNameSpoof by default? It needs no external
      service, no feed, and no configuration, and display-name spoofing ("Rabobank"
      from a random domain) is one of the most common phishing shapes we see.
    4. For external data files that a plugin reads at startup (like the phishing
      feed): is a host cron doing docker exec mail supervisorctl restart spamd the
      intended approach, or is there a cleaner hook?

    Happy to test anything on my side — I have three servers and a corpus of real
    phishing that got through, so I can measure rather than guess.

    Support spamassassin

  • def_whitelist_from_rcvd / welcomelist_from_rcvd does not fire on Cloudron mail app (SpamAssassin 4.0.0) — also no GUI option for sender whitelisting
    imc67I imc67

    any update?

    Support spamassassin

  • def_whitelist_from_rcvd / welcomelist_from_rcvd does not fire on Cloudron mail app (SpamAssassin 4.0.0) — also no GUI option for sender whitelisting
    imc67I imc67

    Cloudron mail app version: cloudron/mail 3.18.2 (SpamAssassin 4.0.0, 2022-12-13)

    Summary

    There is no GUI (or API) way to whitelist a trusted sender domain in the Cloudron mail app — the only exposed mechanism is the free-text "Custom SpamAssassin rules" field, which maps directly to /app/data/spamd/custom.cf (included from local.cf). While investigating recurring false positives on legitimate Microsoft 365 senders, I found that the relay-verified whitelist directive (whitelist_from_rcvd / its current alias welcomelist_from_rcvd, including the def_ variants) does not fire at all in this setup — confirmed on both long-standing entries and newly added ones. The unauthenticated variant (welcomelist_from, From-header only, no relay check) works correctly.

    Environment

    • Cloudron mail app 3.18.2, SpamAssassin 4.0.0
    • spamd invocation (from ps) : /usr/sbin/spamd --max-children 2 --port 7833 --nouser-config --virtual-config /app/data/spamd/%u --syslog stderr -u cloudron --allow-tell
    • /etc/spamassassin/local.cf (shipped, resets on update) includes two persistent files under /app/data/spamd/: acl.cf (GUI-managed sender allow/blocklist) and custom.cf (GUI "Custom SpamAssassin rules" free-text field — this is the only place available for score/whitelist tuning).
    • No trusted_networks / internal_networks directive is present anywhere in the shipped config (local.cf, *.pre files) or in custom.cf.

    Steps to reproduce

    1. In the mail app's "Custom SpamAssassin rules" field, add:
      def_whitelist_from_rcvd *@outlook.com *.protection.outlook.com
      
    2. Save (this restarts spamd — confirmed via ps -o etime on the spamd process).
    3. Take a real inbound message from an *@outlook.com sender that passed through *.protection.outlook.com relays (verified via the Received headers).
    4. Re-score it: docker exec mail spamassassin -t < message.eml
    5. Observe X-Spam-Status — no USER_IN_WELCOMELIST / USER_IN_DEF_WHITELIST (deprecated alias) test appears, and the score is identical to a run with the whitelist line removed.

    Repeated with:

    • A newly added entry for a specific business partner domain (def_whitelist_from_rcvd *@example.nl *.protection.outlook.com) on a real message from that domain — same result, rule does not fire.
    • The current directive name instead of the deprecated alias (def_welcomelist_from_rcvd *@example.nl *.protection.outlook.com) — same result.
    • A synthetic minimal .eml with a single clean Received header (from HOST.outbound.protection.outlook.com (mail-....outbound.protection.outlook.com [IP]) by my.<domain> (Haraka) ...) and a matching From address — same result. SpamAssassin's own debug log correctly identifies this Received header as __LAST_UNTRUSTED_RELAY_NO_AUTH (i.e. it does parse the relay boundary correctly), yet the whitelist rule still does not fire.

    Control test (confirms the mechanism itself, isolates the bug)

    spamassassin -t --cf="welcomelist_from *@example.nl" < message.eml
    

    → X-Spam-Status: No, score=-100.0 ... tests=...,USER_IN_WELCOMELIST — fires immediately and correctly, at the rule's hardcoded default score of -100.

    So: the address-only, non-relay-verified directive works reliably; the relay-verified directive (which is presumably intended to be the "safe" option, since it additionally confirms the mail actually arrived via the claimed infrastructure, not just a forged From: header) never fires, in this container/config, regardless of naming (whitelist_from_rcvd vs welcomelist_from_rcvd) or entry age (default-shipped vs newly added).

    Suspected cause

    _check_welcomelist_rcvd (in Mail::SpamAssassin::Plugin::WLBLEval, called from check_from_in_default_welcomelist) presumably relies on SpamAssassin's own trusted/internal relay boundary detection to know which Received header to compare against the second (origin) parameter. Since this Cloudron config declares no trusted_networks / internal_networks, that auto-detection may be picking the wrong boundary or failing silently for this reason — even though the same debug run shows SpamAssassin does correctly tag the relevant Received header as the last untrusted relay via a different, unrelated eval (__LAST_UNTRUSTED_RELAY_NO_AUTH). I have not been able to fully confirm this from the plugin source in the time available; posting here in case someone has already solved this or knows the missing config.

    Workaround in use

    Switched the partner-domain entries to the non-relay-verified directive with a tuned-down score (rather than the default -100, which would let a spoofed From: header fully bypass filtering):

    score USER_IN_WELCOMELIST -4.0
    welcomelist_from *@example.nl
    

    This is good enough to counter a BAYES/HELO false-positive but does not fully bypass SPF/DKIM/DNSBL-driven detection the way the (non-working) relay-verified version was intended to. It's a knowingly weaker mechanism (spoofable From header) — would much prefer the relay-verified variant to actually work.

    Ask

    1. Is whitelist_from_rcvd / welcomelist_from_rcvd known to be broken in this SpamAssassin/Cloudron combination, and if so is there a missing config directive (e.g. trusted_networks) that should be shipped by default or that we should add ourselves in custom.cf?
    2. Separately: is there any plan for a proper GUI/API-level "trusted sender domain" feature in the mail app, so this doesn't require hand-editing SpamAssassin rule syntax in a free-text field?

    Happy to provide more debug output / test further if useful.

    Support spamassassin

  • client_max_body_size 2m in /api/ location blocks the large blocklists
    imc67I imc67

    A follow-up, because raising nginx client_max_body_size alone turns out not to be enough — there is a second, hard-coded ceiling that hits right after.

    Even with the /api/ location bumped to 10m, a blocklist POST now fails with HTTP 500 and this JSON body:

    {"status":"Internal Server Error","message":"request entity too large"}
    

    Note it is a 500, not an nginx 413 — the body passes nginx and is then rejected
    inside box. The cause is the JSON body-parser limit in:

    box/src/server.js  (9.0.0, ~line 41)
    const QUERY_LIMIT = '2mb', // max size for json queries (see also client_max_body_size in nginx)
    ...
    const json = middleware.json({ strict: true, limit: QUERY_LIMIT }, true);
    

    That QUERY_LIMIT applies to every JSON POST route, including
    POST /api/v1/network/blocklist. So there are two coupled limits — the nginx one
    and this one — and the box default (2mb = 2,097,152 bytes) is the real wall for
    large blocklists.

    Concrete numbers from a live install: the combined blocklist is ~90,600 entries and
    the JSON request body is 2,096,109 bytes — about 1 KB under the 2 MiB limit. One of my
    servers already fails as soon as a few hundred new IPs are added, while others with a
    slightly shorter list still squeak through. (JSON encoding inflates it further: each
    newline becomes \n → \n, ~90 KB on top of the raw list. JSON_UNESCAPED_SLASHES is
    already applied.)

    Request: please raise both limits, ideally toward the ipset capacity (262,144
    entries). At minimum, give the blocklist route a QUERY_LIMIT that matches a raised
    client_max_body_size (e.g. 8–10 MB) — otherwise raising the nginx value has no effect
    for this endpoint. The in-code comment already acknowledges the two are meant to track
    each other.

    Happy to provide a sample 90k-entry blocklist for testing if useful.

    Support api nginx

  • Cloudron v9.2.0 makes app-menu items disappear
    imc67I imc67

    O now I see it, I would appreciate it when the "admin page/url" won't be obsolete because its not always obvious where the admin-page is (like Surfer) 😊

    Support gui cloudron

  • Cloudron v9.2.0 makes app-menu items disappear
    imc67I imc67

    I noticed that since 9.2.0 the menu below is not complete anymore:

    Scherm­afbeelding 2026-05-26 om 09.13.06.png

    Cloudron 9.1.7:
    Scherm­afbeelding 2026-05-26 om 09.14.13.png

    Support gui cloudron

  • client_max_body_size 2m in /api/ location blocks the large blocklists
    imc67I imc67

    @robi I'm not a developer but a security concerned Cloudron user. The reason I started this application (LAMP-app, php and py) was that one of the users was lured into a phishing mail, his password was used for almost 2 months to send spam (via a direct SMTP connection, so no traces in IMAP). I was not able to discover this in Cloudron, that made me angry and extremely concerned: "what is happening more in the 3 Cloudrons I don't know because I can't see".

    So I took a Claude AI subscription and in about 10 weeks daily coding, step-by-step I created this application but never with the thought of distributing it. So there is functionality (GUI) to add one or more Cloudrons, but ie. there is no user management (only 1 user) and the access is IP restricted to my 2 WAN IP's via DDNS reversed IP lookup, but on the other hand API keys (Cloudrons, AbuseIPDB, Pushover, ClaudeAI for daily email summary) etc. are managed via GUI.

    To make it even a community app is totally out of my knowledge and comfort zone, moreover updating the app and being (feeling) responsible for others is too much. Maybe @staff can have a look with me to get inspired?

    Support api nginx

  • client_max_body_size 2m in /api/ location blocks the large blocklists
    imc67I imc67

    @nebulon I created CRMON — Cloudron Security Monitor, CRMON is a self-built security monitoring platform I run to monitor three Cloudron servers. It combines several threat intelligence sources and pushes a consolidated blocklist nightly to each Cloudron's network firewall via the /api/v1/network/blocklist API.

    Beyond the blocklist, CRMON also uses the Cloudron API to continuously monitor event logs: mail delivery events, IMAP/SMTP authentication failures, user login anomalies and nginx failed login attempts are fetched every few minutes and cross-referenced against AbuseIPDB. IPs exceeding configurable abuse score thresholds are auto-blocked and immediately (hourly alas because the API is not per IP) synced to the firewall.

    The blocklist has 5 layers, each with a different purpose:

    Layer Count Source
    Individual auto-blocks ~6,200 IMAP brute-force, login anomalies, mail abuse — auto-blocked based on AbuseIPDB score thresholds
    Wordfence (WordPress) ~4,200 A MU-plugin on ~25 WordPress sites reports attacker IPs in real time to CRMON, which syncs them to the firewall
    AbuseIPDB blacklist ~9,600 Daily import of the top-scoring IPs from the AbuseIPDB API
    FireHOL level1 ~4,500 Known malicious network CIDR ranges (botnets, scanners, exploits)
    Geo/country blocking ~63,000 IP ranges (IPv4 + IPv6) for ~23 high-risk countries (CN, RU, IR, KP, etc.)

    Why it grows: The Wordfence layer is the fastest-growing (+150–280 IPs/day) as WordPress sites under management continuously see new attackers. The geo layer is the largest by far — country-level CIDR ranges, especially for China and Russia, account for the bulk of entries.

    The geo ranges alone explain why we're pushing well over 80,000 entries. Without geo blocking, the list would be ~20,000 entries and the 2 MB limit would never be an issue.

    Support api nginx

  • client_max_body_size 2m in /api/ location blocks the large blocklists
    imc67I imc67

    @james the current blocklist payload (~2.03 MB) link I've sent you via PM

    Note: this is the GET response (Python-encoded by our nightly geo sync, which doesn't escape /). The actual PHP POST payload was ~68 KB larger because PHP's json_encode() escapes all forward slashes as / by default — one extra byte per CIDR entry, ~68,000 CIDR entries total. This pushed the payload to ~2.10 MB, triggering the 413.

    Workaround applied: json_encode($body, JSON_UNESCAPED_SLASHES) in our PHP code reduces it back to ~2.03 MB. We also manually patched the nginx config to client_max_body_size 10m as a structural fix.

    Both are a temporary workaround as the list is increasing with 300-500 IP's a day.

    Support api nginx

  • client_max_body_size 2m in /api/ location blocks the large blocklists
    imc67I imc67

    Following the fix in #10547 that raised the ipset limit to 262,144 elements, we ran into the next bottleneck: the nginx client_max_body_size 2m on the /api/ location in the dashboard config prevents actually reaching anywhere near that element count via the API.

    In /home/yellowtent/platformdata/nginx/applications/dashboard/<hostname>.conf:

    location /api/ {
        proxy_pass   http://127.0.0.1:3000;
        client_max_body_size 2m;   ← limits POST body to ~86k entries
    }
    

    At ~23 bytes per entry (JSON-encoded), 2MB caps the blocklist at roughly 86,000 entries — well below the 262k ipset capacity. Anything larger returns HTTP 413.

    Workaround: changing 2m to 10m in that location block fixes it immediately.

    Request: could this limit be raised (or set to 0) in a future Cloudron release? Given the server-level client_max_body_size 0 already applies to all app traffic, the 2m restriction on /api/ seems overly conservative for the network blocklist endpoint.

    Support api nginx

  • Reverse geocoding (addition to Dawarich)
    imc67I imc67

    Dawarich can be setup with "reverse geocoding", this is the process of converting geographic coordinates into a human-readable address.

    The result is that Dawarich can create "visits and places", this feature tracks your visits to locations to build a comprehensive picture of your daily activities and travel history.

    For this Dawarich recommends:

    Currently, Dawarich supports 4 options for reverse geocoding services:

    • Geoapify (free, limited usage, see Geoapify pricing)
    • Photon (free, limited usage, 1 request per second)
    • Self-hosted Photon (free, unlimited usage)
    • Nominatim (free, limited usage, see Nominatim usage policy) or self-hosted Nominatim instance (free, unlimited usage)

    So an new Cloudron-app either Photon or Nomanitim is very welcome to get the most out of Dawarich.

    Feature Requests dawarich geocoding

  • Dovecot > Sieve > central management
    imc67I imc67

    @James does the moving from 'support' to 'feature requests' means it's currently not possible 😉?

    Feature Requests

  • Dawarich signup env doesn't prevent from signing up
    imc67I imc67

    o, wait, obviously there was somewhere an update and the setting is now in the app GUI! Be sure everyone to check this as the env didn't work anymore!

    @staff please correct this in the docs

    Dawarich

  • Dawarich signup env doesn't prevent from signing up
    imc67I imc67

    Hi guys,

    this is a serious issue: setting this https://docs.cloudron.io/packages/dawarich#disable-registration doesn't work, I still can signup ... 😡

    Dawarich

  • Dovecot > Sieve > central management
    imc67I imc67

    I was wondering if it is possible in Cloudron to manage sieve centrally (via for example API or else) with server-wide rules?

    Currently the only way to "push" server-wide "marks" on incoming email is via "Email Address Blocklist" but the result of that is: the mail is still delivered to the user's spam-folder.

    I'm looking for a way to reject emails (discard) based on sender (I know it's possible at senders' IP address via blocklist)

    Feature Requests

  • What's coming in Cloudron 10
    imc67I imc67

    @girish said:

    @imc67 yes, that's part of the plan

    @girish Would it be feasible to change the current methodology from text lists to database records for all block/allow-lists (mail, IP)? I manage the IP blocklist, via API, with around 90k rows and update it every hour with new and it takes about 2-3 minutes for each Cloudron-server to "handle" this. Better would be to have an API functionality with "list, add, remove"-commands.

    Announcements
  • Login

  • Don't have an account? Register

  • Login or register to search.
  • First post
    Last post
0
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search