gromox(7)

πŸ“¦
version 3.6 Β· 2 versions
, in alpine 3.24

okay so welcome to gromox(7), bestie β€” this is the Gromox admin reference manual section, and it's basically your group-chat pinned message for the entire Gromox groupware server universe ✨

πŸŽ€ NAME πŸŽ€

gromox β€” the big-picture overview of the Gromox groupware server, periodt.

πŸ’… DESCRIPTION πŸ’…

Gromox is a groupware server that can absolutely serve as a replacement for Microsoft Exchange β€” like, it's giving "we have Exchange at home" but the Exchange at home is actually iconic. Its connectivity options include RPC/HTTP (Outlook Anywhere), IMAP, POP3, an SMTP-speaking LDA, and a PHP module with a Z-MAPI function subset. Slay.

Gromox does rely on other components to make a sensibly complete mail system, tho β€” for example Postfix as a mail transfer agent, and grommunio-admin for user management. A web interface is available with grommunio-web. The grommunio distribution ships these essentials and has a ready-to-run installation of Gromox. system.


πŸ“š MANUAL PAGE LISTING πŸ“š

Gromox documentation consists of at least a dozen manual pages ("manpages") on its individual components. We have grouped these according to their principal function, so you can find your fave without scrolling forever 🫢

🌸 Overview and definitions 🌸

  • gromox(7) β€” this very page, an overview of the Gromox groupware server.
  • mapi(7gx) β€” the definition for "Messaging Application Programming Interface" β€” yes, the whole acronym gets its own page, and honestly? deserved.
  • gromox-selinux(5) β€” the SELinux policy for Gromox. Security girlie behavior πŸ”₯

🧚 Information Store subsystem 🧚

  • autoconfig(7) β€” all about the AutoConfig protocols.
  • autodiscover(4gx) β€” the AutoDiscover HTTP Service Protocol handler (responder).
  • autodiscover(7) β€” the AutoDiscover protocols themselves, explained.
  • exmdb_provider(4gx) β€” the Gromox Information Store. Main character energy, no cap.
  • http(8gx) β€” protocol handler for HTTP and RPCH.
  • istore(8gx) β€” the Information Store launcher.
  • mod_cache(4gx) β€” handler for serving objects from a local filesystem.
  • mod_fastcgi(4gx) β€” handler for proxying requests to FastCGI servers.
  • mod_rewrite(4gx) β€” handler for altering HTTP request URIs before processing.
  • timer(8gx) β€” the deferred command executor. It's giving "I'll do it later" but responsibly πŸ’…

πŸ¦‹ Exchange subsystem and its components πŸ¦‹

  • exchange_emsmdb(4gx) β€” handler for the Wire Format Protocol (Outlook/Exchange RPCs) and Remote Operations Protocol.
  • exchange_nsp(4gx) β€” handler for the Name Service Provider Interface Protocol.
  • exchange_rfr(4gx) β€” handler for the Address Book Name Service Provider Interface Referral Protocol. Say that five times fast, I dare you 😭
  • ews(4gx) β€” handler for Exchange Web Services requests.
  • mh_emsmdb(4gx) β€” handler for MAPIHTTP-wrapped EMSMDB requests.
  • mh_nsp(4gx) β€” handler for MAPIHTTP-wrapped NSPI requests.

πŸ’œ PHP-MAPI subsystem πŸ’œ

  • zcore(8gx) β€” the bridge for PHP-MAPI requests.

πŸ“ Mail retrieval agent subsystem (MRA) πŸ“

πŸŽ€ Local delivery agent (LDA) πŸŽ€

⭐ Auxiliary services ⭐

πŸ‘‘ System administration πŸ‘‘

🌈 Mail import, export and conversion 🌈

πŸ”₯ Components πŸ”₯

πŸ’€ Historic commands that have been removed πŸ’€

The following is a list of programs that no longer exist. It is intended solely to capture keyword searches within the documentation for said obsolete/removed commands. So like, these are ghosts β€” but the search keywords still need a home, iykyk.

  • gromox-mt2exm: renamed to gromox-import

🫢 Language bindings 🫢

  • mapi(4gx) β€” PHP module providing MAPI functions.

πŸ’Ύ Configuration files

okay so this is where all your config lives β€” bestie, it's /etc/gromox, that's the spot. Program configuration files reside within /etc/gromox. ✨

The format for .cfg files is literally just: one key=value pair per line. That's it. Empty lines are ignored, and so are lines beginning with a # character. Lines can have a maximum length of 1024 β€” yes, a hard cap, don't be extra. Each key=value line is logically split at the equals sign, and whitespace is trimmed around key and value. And listen: comments at the end of a value are not supported, and escape sequences are not supported. So put the comment on its own line like a good little gremlin. πŸ’…

The format for .ini files is: one key=value pair per line. Empty lines are ignored, as are lines beginning with a ; character. (Different comment char, same energy. iykyk.)

Many programs have a config_file_path directive with which the search path for further config files can be specified. For example, http(8gx) defaults to config_file_path=/etc/gromox/http:/etc/gromox, so the mysql_adaptor(4gx) component as loaded by http will first try /etc/gromox/http/mysql_adaptor.cfg, then /etc/gromox/mysql_adaptor.cfg. The way that works is genuinely iconic β€” it allows having one file that is shared between multiple programs as well as being able to override on a per program-basis. 🫢


πŸ—‚οΈ Listing of config files per component

A list of components and the config files they potentially use. Screenshot this, you'll want it later. πŸŽ€


πŸ”„ Listing of components per config file

Same info, flipped sideways. We love a bidirectional relationship. πŸ’–


πŸ—„οΈ Databases

  • User information is held in a MariaDB/MySQL database. This database can be accessed by multiple Gromox servers, and so enables distributed Gromox operation. The MariaDB system itself provides the necessary utilities for distributing or replicating this database. distributed slay ✨
  • Per-user e-mail messages are stored in a SQLite database (e.g. /var/lib/gromox/user/m1/1/1/exchange.sqlite3), as is a message index (e.g. /var/lib/gromox/user/m1/1/1/midb.sqlite3). These are normally only used by one system, but can be shared through network filesystems provided that file locking is properly implemented in the filesystem driver β€” that part is not a vibe, that's a requirement. πŸ‘€ Normal file mechanisms can be used to backup or transfer the database to another Gromox host.

🌐 Host addresses

Gromox exclusively uses the AF_INET6 socket family with the Berkeley/BSD/POSIX socket API. No cap, that's just how it is. What this means is that, whenever an IP address is logged, it will have the form specified in RFC 4291 Β§2.2/Β§2.5.5. Furthermore, whenever some configuration file directive (field) requires an IP address (i.e. you cannot or do not want to use a hostname), the RFC 4291 form must be used for both IPv6 and IPv4. Yes, even your little IPv4 addresses. Especially those. πŸ’€


πŸ”Œ Listening sockets

look at all those ports, absolutely booked and busy 🫢

πŸ“ FILES πŸ“

okay bestie, here's where all the stuff actually lives on disk ✨

  • /usr/share/gromox/cpid.txt β€” the mapping between character set IDs and names πŸ’…
  • /usr/share/gromox/folder_names.txt β€” translations for the essential folders in a message store πŸŽ€
  • /usr/share/gromox/lang_charset.txt β€” mapping from language code to character set 🌸
  • /usr/share/gromox/lcid.txt β€” mapping between locale IDs and names 🌈
  • /usr/share/gromox/mime_extension.txt β€” mapping between file extensions and MIME types πŸ¦‹
  • /var/lib/gromox β€” the basic root directory of all variadic data for Gromox πŸ‘‘
  • /var/lib/gromox/queue β€” directory for delivery-queue(8) temporary files πŸ“¬
  • /var/lib/gromox/user/account@domain β€” the individual mailbox container. lowkey the directory name/path has only a few requirements: the users.maildir column in the gromox MariaDB/MySQL database needs to reflect that location. Some user management tools generate extra directory levels, e.g. /user/m1/1/0 πŸ™ˆ

and inside that mailbox container, it's giving little ecosystem 🫢:

  • .../a@d/exmdb/exchange.sqlite3 β€” the mail store with almost everything in it (but no mail bodies, mind you) πŸ’€
  • .../a@d/cid/ β€” attachments and message bodies (PR_BODY, PR_HTML, PR_RTF_COMPRESSED) πŸ“
  • .../a@d/eml/mid_string β€” the RFC5322 representation for a message. mid_string has no required form. Typically there's timestamp.seqid.hostname, which represents EMLs captured by delivery(8gx) on ingestion, and timestamp.seqid.midb for EMLs generated by midb(8gx) out of MAPI messages πŸ“
  • .../a@d/ext/mid_string β€” the digest for the RFC5322 file. This JSON-encoded file contains, like, indexing information for individual MIME parts of the RFC5322 representation. Generated by midb(8gx) 🧚

🚨 FAIL2BAN INTEGRATION 🚨

so the daemons emit mostly consistent log messages when authentication fails, and you can match them with this PCRE, iconic:

/rhost=\[(\S+)?\]\S* user=(\S+) .*(auth|login.*|logon) rejected:/

the operation texts can be any of these hun πŸ‘‡

  • HTTP auth rejected (http)
  • zs_logon rejected (zcore)
  • zs_logon_token rejected (zcore)
  • LOGIN phase0 rejected (imap)
  • LOGIN phase1 rejected (imap)
  • LOGIN phase2 rejeceted (imap)
  • login rejected (pop3)
and yes bestie, that rejeceted is literally spelled that way β€” it's a real literal string, don't come for me 😭

⏱️ DURATION SPECIFICATIONS ⏱️

duration strings gotta be of this exact form, no cap:

duration := quantum [ quantum ]*

quantum := number unit

# "number" can be whatever strtol(3) accepts. If a period is detected,
# parsing switches to strtod(3).

unit := "ns" | "nsec" | "Β΅s" | "Β΅sec" | "ms" | "msec" | "s" | "sec" |
"second" | "seconds" | "min" | "minute" | "minutes" | "h" | "hour" |
"hours" | "d" | "day" | "days" | "week" | "weeks" | "month" | "months" |
"y" | "year" | "years"

whitespace is ignored wherever it appears β€” so use as much as you need, go off πŸŽ€. quanta with the same unit may be used, they're simply added together. per this syntax, numbers can be positive or negative, integral or fractional (just be mindful of the precision limits of computers' floating-point math, ngl πŸ’…).

examples, so you get the vibe:

  • 1d1h1m1s
  • 3.5 hours
  • 1 hour 1 hour (that's 2 hours)
  • 1 hour 60 minutes (also 2 hours) ✨
heads up: Gromox may impose additional restrictions on specific configuration directives after the basic parse, to enforce certain minimum and maximum values. so like, the parser ate but the directive might still vibe-check you πŸ”₯

aaaand that's a wrap bestie πŸ’– this was gromox(7) from the Gromox project, dated whenever the page was built β€” source, version and date all live in that footer, mwah πŸ«ΆπŸ’…βœ¨

πŸ“¦ where this page comes from