1 (edited by Neovana 2025-08-18 05:57:00)

Topic: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Thank you for your great work, iRedMail is a swell product.

I updated to iRedMail 1.7.4 while still on OpenBSD 7.6 without issue.

I updated to OpenBSD 7.7, patched the system, updated the packages, and upgraded from PGSQL 16 to 17.

# doas syspatch
# doas pkg_add -u
# doas reboot

Upon boot, I was seeing the following error:

php81_fpm(absent)

The web server and email servers are working, but I was not able to use roundcube, nor iRedAdmin. Here is how I fixed the roundcube issue:

% doas rcctl disable php81_fpm
% doas ln -s /etc/php-8.2.sample/bz2.ini /etc/php-8.2/bz2.ini
% doas ln -s /etc/php-8.2.sample/gd.ini /etc/php-8.2/gd.ini
% doas ln -s /etc/php-8.2.sample/imap.ini /etc/php-8.2/imap.ini
% doas ln -s /etc/php-8.2.sample/intl.ini /etc/php-8.2/intl.ini
% doas ln -s /etc/php-8.2.sample/opcache.ini /etc/php-8.2/opcache.ini
% doas ln -s /etc/php-8.2.sample/pdo_pgsql.ini /etc/php-8.2/pdo_pgsql.ini
% doas ln -s /etc/php-8.2.sample/pspell.ini /etc/php-8.2/pspell.ini
% doas ln -s /etc/php-8.2.sample/zip.ini /etc/php-8.2/zip.ini
% doas rcctl enable php82_fpm
% doas rcctl start php82_fpm
php82_fpm(ok)

Now roundcube is working, but not iRedAdmin.

I tried:

# bash /root/iRedAdmin-2.6/tools/upgrade_iredadmin.sh

and that did not solve the issue.

----

Spider Email Archiver: On-Premises, lightweight email archiving software developed by iRedMail team. Supports Amazon S3 compatible storage and custom branding.

2

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Any error while running commands below?

pkg_add py3-cheroot
cd /opt/www/iredadmin/
python3 iredadmin.py

3

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

# pkg_add py3-cheroot
quirks-7.103 signed on 2025-08-08T08:45:16Z
py3-cheroot-10.0.1:py3-jaraco-functools-4.1.0p0: ok
Collision in py3-cheroot-10.0.1: the following files already exist
    /usr/local/bin/cheroot from py3-cheroot-10.0.1 (different checksum)
It seems to be a missing package registration
Repair ? [y/N/a] y
py3-cheroot-10.0.1: ok

# cd /opt/www/iredadmin/
# python3 iredadmin.py
http://0.0.0.0:8080/

% doas rcctl restart iredadmin
iredadmin(ok)

Still not working.

4

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Any error in /var/log/messages and Nginx log file?

5

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Nginx error:

[13/Aug/2025:00:45:07 -0400] "GET /iredadmin/login HTTP/2.0" 502 552 "-" "…"

Which shows up as "502 Bad Gateway" in the browser.

---------------

Lots of errors in /var/log/messages:

iredapd <!> Error while applying plugin 'wblist_rdns': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/wblist_rdns.py", line 85, in restriction\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT rdns\\n               …

iredapd <!> Error while querying domain: ObjectNotExecutableError('Not an executable object: "SELECT domain\\n                   FROM domain\\n                  WHERE domain=…

iredapd <!> Error while querying alias domain: ObjectNotExecutableError('Not an executable object: "SELECT alias_domain.alias_domain\\n                       FROM alias_domain, domain\\n                      WHERE domain.active=1\\n                            AND domain.domain=alias_domain.target_domain\\n                            AND alias_domain.alias_domain=…

iredapd <!> Error while logging smtp action: AttributeError("'Engine' object has no attribute 'execute'")

And it keeps on going "Error while applying plugin"

---------------

Also cron:

Cron <root@mail> /usr/local/bin/php-8.1 /opt/www/roundcubemail/bin/cleandb.sh >/dev/null

/bin/sh: /usr/local/bin/php-8.1: not found

Cron <root@mail> /usr/local/bin/php-8.1 /opt/www/roundcubemail/bin/gc.sh >/dev/null

/bin/sh: /usr/local/bin/php-8.1: not found

Cron <root@mail> /usr/local/bin/python3 /opt/iredapd/tools/spf_to_greylist_whitelists.py >/dev/null

Traceback (most recent call last):
  File "/opt/iredapd/tools/spf_to_greylist_whitelists.py", line 92, in <module>
    qr = conn.select('greylisting_whitelist_domains', what='domain')
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/iredapd/tools/../web/db.py", line 870, in select
    return self.query(qout, processed=True)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/iredapd/tools/../web/db.py", line 816, in query
    db_cursor = self._db_cursor()
                ^^^^^^^^^^^^^^^^^
  File "/opt/iredapd/tools/../web/db.py", line 723, in _db_cursor
    return self.ctx.db.cursor()
           ^^^^^^^^
  File "/opt/iredapd/tools/../web/db.py", line 661, in _getctx
    self._load_context(self._ctx)
  File "/opt/iredapd/tools/../web/db.py", line 673, in _load_context
    ctx.db = self._connect(self.keywords)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/iredapd/tools/../web/db.py", line 1212, in _connect
    conn = DB._connect(self, keywords)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/iredapd/tools/../web/db.py", line 701, in _connect
    return self.db_module.connect(**keywords)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/psycopg2/__init__.py", line 122, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
psycopg2.OperationalError: connection to server at "127.0.0.1", port 5432 failed: Connection refused
    Is the server running on that host and accepting TCP/IP connections?

6

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Neovana wrote:

/bin/sh: /usr/local/bin/php-8.1: not found

OpenBSD 7.7 offers php 8.3, not 8.1.

Neovana wrote:

psycopg2.OperationalError: connection to server at "127.0.0.1", port 5432 failed: Connection refused
    Is the server running on that host and accepting TCP/IP connections?

Is postgresql service running?

7 (edited by Neovana 2025-08-14 02:12:53)

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

% ls -al /usr/local/bin/ | grep php
lrwxr-xr-x    1 root   wheel         7 Aug 11 02:59 php -> php-8.2
-rwxr-xr-x    1 root   bin    16334928 Jul  5 15:08 php-8.2
lrwxr-xr-x    1 root   wheel        14 Aug 11 02:59 php-config -> php-config-8.2
-rwxr-xr-x    1 root   bin        4547 Jul  5 15:08 php-config-8.2
lrwxr-xr-x    1 root   wheel        26 Mar 30  2024 php-fpm -> /usr/local/bin/php-fpm-8.1
lrwxr-xr-x    1 root   wheel        10 Aug 11 02:59 phpize -> phpize-8.2
-rwxr-xr-x    1 root   bin        4504 Jul  5 15:08 phpize-8.2

I don't see 8.3.

It looks like the generic php-fpm alias needs to be updated to use php-fpm-8.2…

% ls -al /usr/local/sbin/ | grep php
-rwxr-xr-x   1 root  bin        16334528 Jul  5 15:08 php-fpm-8.2

which is in /sbin?

% doas rm /usr/local/bin/php-fpm
doas ln -s /usr/local/sbin/php-fpm-8.2 /usr/local/bin/php-fpm

PGSQL is running fine, all email services are using it without issue.

Looks like the crontab needs to be updated:

# iRedMail: Backup PostgreSQL databases on 03:01 AM
1   3   *   *   *   /usr/local/bin/bash /var/vmail/backup/backup_pgsql.sh

# iRedAPD: Clean up expired tracking records hourly.
1   *   *   *   *   /usr/local/bin/python3 /opt/iredapd/tools/cleanup_db.py >/dev/null

# iRedAPD: Convert SPF DNS record of specified domain names to IP
#          addresses/networks hourly.
2   *   *   *   *   /usr/local/bin/python3 /opt/iredapd/tools/spf_to_greylist_whitelists.py >/dev/null

# iRedMail: Cleanup Amavisd database
1   2   *   *   *   /usr/local/bin/python3 /opt/www/iredadmin/tools/cleanup_amavisd_db.py >/dev/null

# iRedAdmin: Clean up sql database.
1   *   *   *   *   /usr/local/bin/python3 /opt/www/iredadmin/tools/cleanup_db.py >/dev/null 2>&1

# iRedAdmin: Delete mailboxes on file system which belong to removed accounts.
1   *   *   *   *   /usr/local/bin/python3 /opt/www/iredadmin/tools/delete_mailboxes.py
# iRedMail: Cleanup Roundcube SQL database
2   2   *   *   *   /usr/local/bin/php-8.1 /opt/www/roundcubemail/bin/cleandb.sh >/dev/null

# iRedMail: Cleanup Roundcube temporary files under 'temp/' directory
2   2   *   *   *   /usr/local/bin/php-8.1 /opt/www/roundcubemail/bin/gc.sh >/dev/null

I've changed the references of php-8.1 to php.

After reboot, the iredadp python "Error while applying plugin" errors persist.

Aug 13 12:26:30 mail iredapd <!> Error while applying plugin 'wblist_rdns': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/wblist_rdns.py", line 85, in restriction\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT rdns\\n               FROM wblist_rdns\\n              WHERE rdns IN (\'example.com\', \'.example.com\', \'.example.com\', \'.example.com\', \'.example.com\') AND wb=\'W\'\\n              LIMIT 1"\n']
Aug 13 12:26:30 mail iredapd <!> Error while querying domain: ObjectNotExecutableError('Not an executable object: "SELECT domain\\n                   FROM domain\\n                  WHERE domain=\'example.com\' AND active=1 AND backupmx=0\\n                  LIMIT 1"')
Aug 13 12:26:30 mail iredapd <!> Error while querying alias domain: ObjectNotExecutableError('Not an executable object: "SELECT alias_domain.alias_domain\\n                       FROM alias_domain, domain\\n                      WHERE domain.active=1\\n                            AND domain.domain=alias_domain.target_domain\\n                            AND alias_domain.alias_domain=\'example.com\'\\n                      LIMIT 1"')
Aug 13 12:26:30 mail iredapd <!> Error while applying plugin 'greylisting': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/greylisting.py", line 350, in restriction\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 87, in get_alias_target_domain\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT alias_domain.target_domain\\n               FROM alias_domain, domain\\n              WHERE domain.active=1\\n                    AND domain.domain=alias_domain.target_domain\\n                    AND alias_domain.alias_domain=\'example.com\'\\n              LIMIT 1"\n']
Aug 13 12:26:30 mail iredapd <!> Error while applying plugin 'sql_ml_access_policy': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/sql_ml_access_policy.py", line 36, in restriction\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 118, in get_access_policy\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT accesspolicy\\n               FROM maillists\\n              WHERE address=\'user@example.com\'\\n              LIMIT 1"\n']
Aug 13 12:26:30 mail iredapd <!> Error while applying plugin 'sql_alias_access_policy': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/sql_alias_access_policy.py", line 99, in restriction\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 118, in get_access_policy\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT accesspolicy\\n               FROM alias\\n              WHERE address=\'user@example.com\'\\n              LIMIT 1"\n']
Aug 13 12:26:30 mail iredapd <!> Error while applying plugin 'amavisd_wblist': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/amavisd_wblist.py", line 310, in restriction\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 87, in get_alias_target_domain\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT alias_domain.target_domain\\n               FROM alias_domain, domain\\n              WHERE domain.active=1\\n                    AND domain.domain=alias_domain.target_domain\\n                    AND alias_domain.alias_domain=\'example.com\'\\n              LIMIT 1"\n']
Aug 13 12:26:31 mail iredapd <!> Error while applying plugin 'throttle': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/throttle.py", line 761, in restriction\n', '  File "/opt/iredapd/plugins/throttle.py", line 255, in apply_throttle\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 87, in get_alias_target_domain\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT alias_domain.target_domain\\n               FROM alias_domain, domain\\n              WHERE domain.active=1\\n                    AND domain.domain=alias_domain.target_domain\\n                    AND alias_domain.alias_domain=\'example.com\'\\n              LIMIT 1"\n']
Aug 13 12:26:31 mail iredapd <!> Error while logging smtp action: AttributeError("'Engine' object has no attribute 'execute'")

iRedAdmin still not working.

8

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

# ls -al /opt/iRedAPD-5.9.1/libs/        
total 268
dr-x------   5 root  wheel    512 Aug 13 00:26 .
dr-x------  13 root  wheel    512 Aug 13 00:26 ..
-r-x------   1 root  wheel   5394 Aug 13 00:26 __init__.py
dr-x------   2 root  wheel    512 Aug 13 00:26 __pycache__
-r-x------   1 root  wheel  13245 Aug 13 00:26 channel.py
-r-x------   1 root  wheel   7156 Aug 13 00:26 daemon.py
-r-x------   1 root  wheel  10729 Aug 13 00:26 default_settings.py
-r-x------   1 root  wheel  13127 Aug 13 00:26 dnsspf.py
-r-x------   1 root  wheel   4367 Aug 13 00:26 greylisting.py
dr-x------   2 root  wheel    512 Aug 13 00:26 ldaplib
-r-x------   1 root  wheel    884 Aug 13 00:26 logger.py
-r-x------   1 root  wheel   3759 Aug 13 00:26 regxes.py
dr-x------   3 root  wheel    512 Aug 13 00:26 sql
-r-x------   1 root  wheel  15147 Aug 13 00:26 srslib.py
-r-x------   1 root  wheel  25138 Aug 13 00:26 utils.py
-r-x------   1 root  wheel  15524 Aug 13 00:26 wblist.py

# ls -al /opt/iredapd/plugins/
total 284
dr-x------   3 root  wheel   1024 Aug 13 00:26 .
dr-x------  13 root  wheel    512 Aug 13 00:26 ..
-r-x------   1 root  wheel      0 Aug 13 00:26 __init__.py
dr-x------   2 root  wheel    512 Aug 13 00:26 __pycache__
-r-x------   1 root  wheel  13634 Aug 13 00:26 amavisd_wblist.py
-r-x------   1 root  wheel  17364 Aug 13 00:26 greylisting.py
-r-x------   1 root  wheel   2843 Aug 13 00:26 ldap_force_change_password.py
-r-x------   1 root  wheel  12082 Aug 13 00:26 ldap_maillist_access_policy.py
-r-x------   1 root  wheel    986 Aug 13 00:26 reject_null_sender.py
-r-x------   1 root  wheel  16400 Aug 13 00:26 reject_sender_login_mismatch.py
-r-x------   1 root  wheel    788 Aug 13 00:26 reject_to_hostname.py
-r-x------   1 root  wheel   4254 Aug 13 00:26 senderscore.py
-r-x------   1 root  wheel   8665 Aug 13 00:26 sql_alias_access_policy.py
-r-x------   1 root  wheel   2824 Aug 13 00:26 sql_force_change_password.py
-r-x------   1 root  wheel   6044 Aug 13 00:26 sql_ml_access_policy.py
-r-x------   1 root  wheel  31770 Aug 13 00:26 throttle.py
-r-x------   1 root  wheel   3324 Aug 13 00:26 wblist_rdns.py
-r-x------   1 root  wheel   3849 Aug 13 00:26 whitelist_outbound_recipient.py

# ls -al /usr/local/lib/python3.12/site-packages/sqlalchemy/engine/       
total 1412
drwxr-xr-x   3 root  wheel     512 Aug 11 02:39 .
drwxr-xr-x  15 root  wheel     512 Aug 11 02:39 ..
-rw-r--r--   1 root  bin      2818 Apr  9 19:36 __init__.py
drwxr-xr-x   2 root  wheel    1536 Aug 11 02:38 __pycache__
-rw-r--r--   1 root  bin      3744 Apr  9 19:36 _py_processors.py
-rw-r--r--   1 root  bin      3787 Apr  9 19:36 _py_row.py
-rw-r--r--   1 root  bin      2484 Apr  9 19:36 _py_util.py
-rw-r--r--   1 root  bin    122901 Apr  9 19:36 base.py
-rw-r--r--   1 root  bin      4765 Apr  9 19:36 characteristics.py
-rw-r--r--   1 root  bin     33217 Apr  9 19:36 create.py
-rw-r--r--   1 root  bin     76489 Apr  9 19:36 cursor.py
-rw-r--r--   1 root  bin     85334 Apr  9 19:36 default.py
-rw-r--r--   1 root  bin     37400 Apr  9 19:36 events.py
-rw-r--r--   1 root  bin    113456 Apr  9 19:36 interfaces.py
-rw-r--r--   1 root  bin      4181 Apr  9 19:36 mock.py
-rw-r--r--   1 root  bin      2379 Apr  9 19:36 processors.py
-rw-r--r--   1 root  bin     75383 Apr  9 19:36 reflection.py
-rw-r--r--   1 root  bin     77636 Apr  9 19:36 result.py
-rw-r--r--   1 root  bin     12031 Apr  9 19:36 row.py
-rw-r--r--   1 root  bin       442 Apr  9 19:36 strategies.py
-rw-r--r--   1 root  bin     31069 Apr  9 19:36 url.py
-rw-r--r--   1 root  bin      5682 Apr  9 19:36 util.py

Are the files in /usr/local/lib/python3.12/site-packages/sqlalchemy/engine/ supposed to be executable like in /opt/iredapd/plugins/ and /opt/iRedAPD-5.9.1/libs/ ?

9

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Download latest iRedAPD and upgrade, it will re-install required python modules.
https://docs.iredmail.org/upgrade.iredapd.html

Same to mlmmjadmin, iRedAdmin(-Pro).

10

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

ZhangHuangbin wrote:

Download latest iRedAPD and upgrade, it will re-install required python modules.
https://docs.iredmail.org/upgrade.iredapd.html

Same to mlmmjadmin, iRedAdmin(-Pro).

I've reinstalled them all since updating to OpenBSD 7.7. I'll do it again for thoroughness.

11 (edited by Neovana 2025-08-15 13:20:13)

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

mail# bash upgrade_iredapd.sh
* Detected Linux/BSD distribution: OPENBSD
* Checking dependent Python modules:
  + [required] wheel
  + [required] sqlalchemy
  + [required] dnspython
  + [required] requests
* Found iRedAPD directory: /opt/iredapd, symbol link of iRedAPD-5.9.1
* Found iRedAPD config file: /opt/iredapd/settings.py
* Copying new version to /opt/iRedAPD-5.9.1
* Copy old config file: settings.py (/opt/iredapd/settings.py -> /opt/iRedAPD-5.9.1/settings.py)
cp: /opt/iRedAPD-5.9.1/settings.py and /opt/iredapd/settings.py are identical (not copied).
* Copy custom plugins: iRedAPD-5.9.1/plugins/custom_*.py.
* Set correct owner and permission for /opt/iRedAPD-5.9.1: root:wheel, 0500.
* Set permission for iRedAPD config file: /opt/iRedAPD-5.9.1/settings.py -> 0400.
* Re-create symbol link: /opt/iredapd -> /opt/iRedAPD-5.9.1
* Copy new SysV init script.
* Replace py2 by py3 in cron jobs.
* Restarting iRedAPD service.
iredapd(ok)
iredapd(ok)
* Upgrade completed.

< NOTE > If iRedAPD doesn't work as expected, please post your issue in our
< NOTE > online support forum: http://www.iredmail.org/forum/
< NOTE >
< NOTE > * Turn on debug mode: http://www.iredmail.org/docs/debug.iredapd.html
< NOTE > * iRedAPD log file is /var/log/iredapd/iredapd.log.

mail# bash upgrade_mlmmjadmin.sh
* Detected Linux/BSD distribution: OPENBSD
* Checking Python 3.
* Checking required Python(-3) modules:
  + [required] psycopg2
* Found mlmmjadmin: /opt/mlmmjadmin, symbol link of /opt/mlmmjadmin-3.4.0
* Found old config file: /opt/mlmmjadmin/settings.py
* Copying new version to /opt/mlmmjadmin-3.4.0
* Copy /opt/mlmmjadmin/settings.py.
cp: /opt/mlmmjadmin-3.4.0/settings.py and /opt/mlmmjadmin/settings.py are identical (not copied).
* Removing old symbol link /opt/mlmmjadmin
* Creating symbol link: /opt/mlmmjadmin-3.4.0 -> /opt/mlmmjadmin
* Copy SysV init script.
* mlmmjadmin has been successfully upgraded.
* Restarting service: mlmmjadmin.
mlmmjadmin(ok)
* Sync mailing list profiles to SQL/LDAP.
No mailing list found. Abort.
* Upgrading completed.
<<< NOTE >>> If mlmmjadmin doesn't work as expected, please post your issue in
<<< NOTE >>> our online support forum: http://www.iredmail.org/forum/

mail# bash upgrade_iredadmin.sh
* Detected Linux/BSD distribution: OPENBSD
* HTTP server root: /opt/www
* Found iRedAdmin directory: /opt/www/iredadmin, symbol link of iRedAdmin-2.6
* Found iRedAdmin config file: /opt/www/iredadmin/settings.py
* Copying new version to /opt/www/iRedAdmin-2.6
* Copy /opt/www/iredadmin/settings.py.
cp: /opt/www/iRedAdmin-2.6/settings.py and /opt/www/iredadmin/settings.py are identical (not copied).
* Removing old symbol link /opt/www/iredadmin
* Creating symbol link /opt/www/iredadmin to /opt/www/iRedAdmin-2.6
* Enable mlmmj integration.
* Restarting service: mlmmjadmin.
mlmmjadmin(ok)
* Check and install required packages.
ALTER TABLE
* Replace py2 by py3 in cron jobs.
* Clean up.
* Delete all existing sessions to force all admins to re-login.
* iRedAdmin has been successfully upgraded.
* Restarting iredadmin service.
iredadmin(ok)
* Enable service: iredadmin
iredadmin(ok)
* Upgrading completed.
<<< NOTE >>> If iRedAdmin doesn't work as expected, please post your issue in
<<< NOTE >>> our online support forum: http://www.iredmail.org/forum/

% cat /vat/log/messages
Aug 15 01:11:29 mail iredapd <!> Error while applying plugin 'wblist_rdns': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/wblist_rdns.py", line 85, in restriction\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT rdns\\n               FROM wblist_rdns\\n              WHERE rdns IN (\'example.com\', \'.example.com\', \'.example.com\', \'.com\') AND wb=\'W\'\\n              LIMIT 1"\n']
Aug 15 01:11:29 mail iredapd <!> Error while querying domain: ObjectNotExecutableError('Not an executable object: "SELECT domain\\n                   FROM domain\\n                  WHERE domain=\'example.com\' AND active=1 AND backupmx=0\\n                  LIMIT 1"')
Aug 15 01:11:29 mail iredapd <!> Error while querying alias domain: ObjectNotExecutableError('Not an executable object: "SELECT alias_domain.alias_domain\\n                       FROM alias_domain, domain\\n                      WHERE domain.active=1\\n                            AND domain.domain=alias_domain.target_domain\\n                            AND alias_domain.alias_domain=\'example.com\'\\n                      LIMIT 1"')
Aug 15 01:11:29 mail iredapd <!> Error while applying plugin 'greylisting': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/greylisting.py", line 350, in restriction\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 87, in get_alias_target_domain\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT alias_domain.target_domain\\n               FROM alias_domain, domain\\n              WHERE domain.active=1\\n                    AND domain.domain=alias_domain.target_domain\\n                    AND alias_domain.alias_domain=\'example.com\'\\n              LIMIT 1"\n']
Aug 15 01:11:29 mail iredapd <!> Error while applying plugin 'sql_ml_access_policy': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/sql_ml_access_policy.py", line 36, in restriction\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 118, in get_access_policy\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT accesspolicy\\n               FROM maillists\\n              WHERE address=\'user@example.com\'\\n              LIMIT 1"\n']
Aug 15 01:11:29 mail iredapd <!> Error while applying plugin 'sql_alias_access_policy': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/sql_alias_access_policy.py", line 99, in restriction\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 118, in get_access_policy\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT accesspolicy\\n               FROM alias\\n              WHERE address=\'user@example.com\'\\n              LIMIT 1"\n']
Aug 15 01:11:29 mail iredapd <!> Error while applying plugin 'amavisd_wblist': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/amavisd_wblist.py", line 310, in restriction\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 87, in get_alias_target_domain\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT alias_domain.target_domain\\n               FROM alias_domain, domain\\n              WHERE domain.active=1\\n                    AND domain.domain=alias_domain.target_domain\\n                    AND alias_domain.alias_domain=\'example.com\'\\n              LIMIT 1"\n']
Aug 15 01:11:29 mail iredapd <!> Error while applying plugin 'throttle': ['Traceback (most recent call last):\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1412, in execute\n    meth = statement._execute_on_connection\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', "AttributeError: 'str' object has no attribute '_execute_on_connection'\n", '\nThe above exception was the direct cause of the following exception:\n\n', 'Traceback (most recent call last):\n', '  File "/opt/iRedAPD-5.9.1/libs/utils.py", line 91, in apply_plugin\n', '  File "/opt/iredapd/plugins/throttle.py", line 761, in restriction\n', '  File "/opt/iredapd/plugins/throttle.py", line 255, in apply_throttle\n', '  File "/opt/iRedAPD-5.9.1/libs/sql/__init__.py", line 87, in get_alias_target_domain\n', '  File "/usr/local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1414, in execute\n    raise exc.ObjectNotExecutableError(statement) from err\n', 'sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: "SELECT alias_domain.target_domain\\n               FROM alias_domain, domain\\n              WHERE domain.active=1\\n                    AND domain.domain=alias_domain.target_domain\\n                    AND alias_domain.alias_domain=\'example.com\'\\n              LIMIT 1"\n']
Aug 15 01:11:29 mail iredapd <!> Error while logging smtp action: AttributeError("'Engine' object has no attribute 'execute'")

After re-installing and rebooting, same problem. See above iredapd errors while applying plugins.

12

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

% python3 -c "import sqlalchemy; print('SQLAlchemy version:', sqlalchemy.__version__)"
SQLAlchemy version: 2.0.40

% ls -la /usr/local/bin/python*
lrwxr-xr-x  1 root  wheel    10 Aug 11 02:45 /usr/local/bin/python3 -> python3.12
lrwxr-xr-x  1 root  wheel    17 Aug 11 02:45 /usr/local/bin/python3-config -> python3.12-config
-rwxr-xr-x  1 root  bin    6872 Jun 24 09:02 /usr/local/bin/python3.12
-rwxr-xr-x  1 root  bin    3060 Jun 24 09:02 /usr/local/bin/python3.12-config

% pip3 --version
pip 25.0.1 from /usr/local/lib/python3.12/site-packages/pip (python 3.12)

% pip3.12 --version
pip 25.0.1 from /usr/local/lib/python3.12/site-packages/pip (python 3.12)

Looking at these iRedAPD errors, it seems that the core issue is that SQLAlchemy's API has changed, and the code is trying to use the old .execute() method directly on string SQL queries, which is no longer supported in newer SQLAlchemy versions.

The errors show that iRedAPD is trying to execute raw SQL strings directly, but SQLAlchemy now requires these to be wrapped in text() objects. This is a breaking change that happened in SQLAlchemy 1.4/2.0.

You'll need to modify the iRedAPD source files to use SQLAlchemy's text() wrapper. Here's what needs to be changed:

In files like /opt/iRedAPD-5.9.1/libs/sql/__init__.py and the plugin files, find lines that look like:

result = conn.execute("SELECT ...")

Change them to:

from sqlalchemy import text
result = conn.execute(text("SELECT ..."))

The error at the end about 'Engine' object has no attribute 'execute' suggests there might be additional compatibility issues beyond just the text() wrapper.

13 (edited by Neovana 2025-08-15 15:29:31)

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

# find /opt/iRedAPD-5.9.1 -name "*.py" -exec grep -n "\.execute(" {} + | grep -v "text("
/opt/iRedAPD-5.9.1/libs/channel.py:246:                    qr = conn_iredapd.execute(sql)
/opt/iRedAPD-5.9.1/libs/greylisting.py:31:        conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/greylisting.py:50:        conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/greylisting.py:69:        conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/greylisting.py:88:        conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/greylisting.py:106:        conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/greylisting.py:124:        conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/greylisting.py:127:        conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/sql/__init__.py:38:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/sql/__init__.py:59:            qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/sql/__init__.py:87:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/sql/__init__.py:118:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/utils.py:765:        conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:15:                conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:28:        conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:32:            qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:47:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:150:        conn.execute('DELETE FROM wblist WHERE rid=%s' % sqlquote(user_id))
/opt/iRedAPD-5.9.1/libs/wblist.py:153:        conn.execute('DELETE FROM outbound_wblist WHERE sid=%s' % sqlquote(user_id))
/opt/iRedAPD-5.9.1/libs/wblist.py:165:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:176:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:188:            conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:192:            conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:223:                    conn.execute("INSERT INTO wblist (sid, rid, wb) VALUES ({}, {}, {})".format(sqlquote(v['sid']),
/opt/iRedAPD-5.9.1/libs/wblist.py:232:                    conn.execute("INSERT INTO outbound_wblist (sid, rid, wb) VALUES ({}, {}, {})".format(sqlquote(v['sid']),
/opt/iRedAPD-5.9.1/libs/wblist.py:296:            qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:305:                conn.execute("DELETE FROM wblist WHERE rid={} AND sid IN {} AND wb='W'".format(sqlquote(user_id), sqlquote(sids)))
/opt/iRedAPD-5.9.1/libs/wblist.py:311:            qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:320:                conn.execute("DELETE FROM wblist WHERE rid={} AND sid IN {} AND wb='B'".format(sqlquote(user_id), sqlquote(sids)))
/opt/iRedAPD-5.9.1/libs/wblist.py:326:            qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:335:                conn.execute("DELETE FROM outbound_wblist WHERE sid={} AND rid IN {} AND wb='W'".format(sqlquote(user_id), sqlquote(rids)))
/opt/iRedAPD-5.9.1/libs/wblist.py:341:            qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:350:                conn.execute("DELETE FROM outbound_wblist WHERE sid={} AND rid IN {} AND wb='B'".format(sqlquote(user_id), sqlquote(rids)))
/opt/iRedAPD-5.9.1/libs/wblist.py:384:            conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:388:            conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:392:            conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:396:            conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:423:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/libs/wblist.py:457:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/amavisd_wblist.py:93:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/amavisd_wblist.py:138:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/amavisd_wblist.py:168:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/amavisd_wblist.py:196:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/amavisd_wblist.py:239:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:57:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:114:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:144:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:226:        qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:249:            conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:272:        conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:287:            conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:290:            conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:310:                conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:321:                conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/greylisting.py:398:        conn_iredapd.execute(_sql)
/opt/iRedAPD-5.9.1/plugins/reject_sender_login_mismatch.py:290:                qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/reject_sender_login_mismatch.py:308:                    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/reject_sender_login_mismatch.py:335:                qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/reject_sender_login_mismatch.py:349:                qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/senderscore.py:57:    qr = conn_iredapd.execute(sql)
/opt/iRedAPD-5.9.1/plugins/senderscore.py:99:                conn_iredapd.execute(sql)
/opt/iRedAPD-5.9.1/plugins/sql_alias_access_policy.py:54:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/sql_alias_access_policy.py:76:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/sql_alias_access_policy.py:139:    _qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/sql_force_change_password.py:53:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/sql_ml_access_policy.py:81:    _qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/sql_ml_access_policy.py:103:    _qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/sql_ml_access_policy.py:119:    _qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/throttle.py:229:                conn.execute(_sql)
/opt/iRedAPD-5.9.1/plugins/throttle.py:283:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/throttle.py:473:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/throttle.py:688:            conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/throttle.py:709:            conn.execute(_sql)
/opt/iRedAPD-5.9.1/plugins/wblist_rdns.py:85:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/plugins/wblist_rdns.py:100:    qr = conn.execute(sql)
/opt/iRedAPD-5.9.1/samples/plugins/custom_relay.py:173:            qr = conn_relay.execute(sql)
/opt/iRedAPD-5.9.1/web/db.py:744:            out = cur.execute(query, params)

After patching the above files and adding

from sqlalchemy import text

That seems to have resolved most of the errors.

The following error remains:

iredapd <!> Error while logging smtp action: AttributeError("'Engine' object has no attribute 'execute'")

The code expects SQLAlchemy 1.x's Engine.execute() method, which no longer exists in 2.0.

You'd need to modify the iRedAPD code to use SQLAlchemy 2.0's new execution style. This involves changing calls from:

engine.execute(query)

to:

from sqlalchemy import text

with engine.connect() as conn:
    conn.execute(text(query))
    conn.commit()
sed -i '766c\
        with conn.connect() as connection:\
            connection.execute(text(sql))\
            connection.commit()' /opt/iredapd/libs/utils.py

Wow, python is picky about indentation. This seems to have resolved the issue.

14

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

More incompatibilities found.

patch in /opt/iredapd/web/db.py

# Change:
return self.query(qout, processed=True)

# To:
return self.query(str(qout), processed=True)

15 (edited by Neovana 2025-08-16 06:16:50)

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

In /opt/iredapd/web/db.py (def _process_query)

#    def _process_query(self, sql_query):
#        """Takes the SQLQuery object and returns query string and parameters."""
#        # MSSQLDB expects params to be a tuple.
#        # Overwriting the default implementation to convert params to tuple.
#        paramstyle = getattr(self, "paramstyle", "pyformat")
#        query = sql_query.query(paramstyle)
#        params = sql_query.values()
#        return query, tuple(params)

    def _process_query(self, sql_query):
        """Takes the SQLQuery object or string and returns query string and parameters."""
        # MSSQLDB expects params to be a tuple.
        # Overwriting the default implementation to convert params to tuple.
        paramstyle = getattr(self, "paramstyle", "pyformat")

        if isinstance(sql_query, str):
            # Already a string query, no parameters
            return sql_query, tuple()
        elif hasattr(sql_query, 'query'):
            # SQLQuery object from web.py
            query = sql_query.query(paramstyle)
            params = sql_query.values()
            return query, tuple(params)
        else:
            # Fallback - convert to string
            return str(sql_query), tuple()

#    def _process_query(self, sql_query):
#        """Takes the SQLQuery object and returns query string and parameters."""
#        paramstyle = getattr(self, "paramstyle", "pyformat")
#        query = sql_query.query(paramstyle)
#        params = sql_query.values()
#        return query, params

    def _process_query(self, sql_query):
        """Takes the SQLQuery object or string and returns query string and parameters."""
        paramstyle = getattr(self, "paramstyle", "pyformat")

        if isinstance(sql_query, str):
            # Already a string query, no parameters
            return sql_query, []
        elif hasattr(sql_query, 'query'):
            # SQLQuery object from web.py
            query = sql_query.query(paramstyle)
            params = sql_query.values()
            return query, params
        else:
            # Fallback - convert to string
            return str(sql_query), []

16 (edited by Neovana 2025-08-16 06:17:05)

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

In /opt/iredapd/web/db.py (def _db_execute)

#    def _db_execute(self, cur, sql_query):
#        """executes an sql query"""
#        self.ctx.dbq_count += 1
#
#        try:
#            a = time.time()
#            query, params = self._process_query(sql_query)
#            out = cur.execute(text(query), params)
#            cur.execute(text(query), params)
#            print(f"DEBUG: query='{query}'")
#           if params:
#               # Convert %s placeholders to :paramN for SQLAlchemy text()
#                if '%s' in query:
#                    import re
#                    placeholders = re.findall(r'%s', query)
#
#                    # Replace %s with :param0, :param1, etc.
#                    for i in range(len(placeholders)):
#                        query = query.replace('%s', f':param{i}', 1)
#
#                    # Convert params list to dict with matching names
#                    params_dict = {f'param{i}': params[i] for i in range(len(params))}
#                    cur.execute(text(query), params_dict)
#                else:
#                    cur.execute(text(query), params)
#            else:
#                # Don't use text() when there are no parameters
#                cur.execute(query)
#            b = time.time()
#        except:
#            if self.printing:
#                print("ERR:", str(sql_query), file=debug)
#            if self.ctx.transactions:
#                self.ctx.transactions[-1].rollback()
#            else:
#                self.ctx.rollback()
#            raise
#
#        if self.printing:
#            print(
#                f"{round(b - a, 2)} ({self.ctx.dbq_count}): {str(sql_query)}",
#                file=debug,
#            )
#        return out
#        return None

    def _db_execute(self, cur, sql_query):
        """executes an sql query"""
        self.ctx.dbq_count += 1

        try:
            a = time.time()
            query, params = self._process_query(sql_query)

            if params:
                # For %s placeholder queries, don't use text() as it causes issues
                if '%s' in query:
                    # Use the query directly with params - this should be safe
                    # since params are passed separately
                    cur.execute(query, params)
                else:
                    # For other parameter styles, use text()
                    cur.execute(text(query), params)
            else:
                # For queries without parameters, check if we need text()
                # Only use text() if the query might have special characters
                if any(char in query for char in [';', '--', '/*']):
                    cur.execute(text(query))
                else:
                    cur.execute(query)

            b = time.time()
        except:
            if self.printing:
                print("ERR:", str(sql_query), file=debug)
            if self.ctx.transactions:
                self.ctx.transactions[-1].rollback()
            else:
                self.ctx.rollback()
            raise

        if self.printing:
            print(
                f"{round(b - a, 2)} ({self.ctx.dbq_count}): {str(sql_query)}",
                file=debug,
            )
        return None

These changes helped to resolve more errors.

17 (edited by Neovana 2025-08-16 17:45:17)

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

I'm having a reoccurring issue where this warning is appearing in maillog:

postfix/smtpd[xxxxx]: warning: problem talking to server 127.0.0.1:7777: Operation timed out

% netstat -an | grep 7777
tcp        635      0  127.0.0.1.7777         127.0.0.1.30917        CLOSE_WAIT
tcp        708      0  127.0.0.1.7777         127.0.0.1.30129        CLOSE_WAIT
tcp        680      0  127.0.0.1.7777         127.0.0.1.11690        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.39534        CLOSE_WAIT
tcp        635      0  127.0.0.1.7777         127.0.0.1.15469        CLOSE_WAIT
tcp        708      0  127.0.0.1.7777         127.0.0.1.26980        CLOSE_WAIT
tcp          0      0  127.0.0.1.26980        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.30129        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.15469        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.30917        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.12837        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.11690        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.39534        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.37405        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.7777         127.0.0.1.12837        CLOSE_WAIT
tcp        635      0  127.0.0.1.7777         127.0.0.1.37405        CLOSE_WAIT
tcp          0      0  127.0.0.1.7777         *.*                    LISTEN

% nc -zv 127.0.0.1 7777
Connection to 127.0.0.1 7777 port [tcp/*] succeeded!

% fstat | grep 7777
_postfix smtpd      50949   18* internet stream tcp 0x0 127.0.0.1:21501 --> 127.0.0.1:7777
iredapd  python3.12 71213    4* internet stream tcp 0x0 127.0.0.1:7777
iredapd  python3.12 71213    7* internet stream tcp 0x0 127.0.0.1:7777 <-- 127.0.0.1:12837
root     resolvd    81345 text /           77772  -r-xr-xr-x     r    20296

% doas rcctl check iredapd
iredapd(ok)

I'm concerned that it could be a memory leak in iRedAPD requiring periodic restarts, a database connection pool exhaustion, or a specific email pattern triggering a bug.

Restarting iRedAPD clears the issue, but it seems to to come back after an hour or two.

Edit: This may have been resolved by my other fixes.

Edit: Edit: Nope. See below.

18

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Ok, problem not solved.

% netstat -an | grep 7777
tcp        710      0  127.0.0.1.7777         127.0.0.1.8958         CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.25853        CLOSE_WAIT
tcp        708      0  127.0.0.1.7777         127.0.0.1.14836        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.40178        CLOSE_WAIT
tcp        648      0  127.0.0.1.7777         127.0.0.1.42988        CLOSE_WAIT
tcp        708      0  127.0.0.1.7777         127.0.0.1.29164        CLOSE_WAIT
tcp        714      0  127.0.0.1.7777         127.0.0.1.13288        CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.44773        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.32485        CLOSE_WAIT
tcp        619      0  127.0.0.1.7777         127.0.0.1.48356        CLOSE_WAIT
tcp        707      0  127.0.0.1.7777         127.0.0.1.10720        CLOSE_WAIT
tcp        620      0  127.0.0.1.7777         127.0.0.1.10714        CLOSE_WAIT
tcp        709      0  127.0.0.1.7777         127.0.0.1.5077         CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.3285         CLOSE_WAIT
tcp        710      0  127.0.0.1.7777         127.0.0.1.16851        CLOSE_WAIT
tcp        620      0  127.0.0.1.7777         127.0.0.1.42191        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.42446        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.30411        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.35524        CLOSE_WAIT
tcp        710      0  127.0.0.1.7777         127.0.0.1.31681        CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.6079         CLOSE_WAIT
tcp        714      0  127.0.0.1.7777         127.0.0.1.6075         CLOSE_WAIT
tcp        716      0  127.0.0.1.7777         127.0.0.1.16821        CLOSE_WAIT
tcp        712      0  127.0.0.1.7777         127.0.0.1.34996        CLOSE_WAIT
tcp        707      0  127.0.0.1.7777         127.0.0.1.49075        CLOSE_WAIT
tcp        622      0  127.0.0.1.7777         127.0.0.1.21938        CLOSE_WAIT
tcp        679      0  127.0.0.1.7777         127.0.0.1.2223         CLOSE_WAIT
tcp        622      0  127.0.0.1.7777         127.0.0.1.9898         CLOSE_WAIT
tcp        710      0  127.0.0.1.7777         127.0.0.1.1448         CLOSE_WAIT
tcp        710      0  127.0.0.1.7777         127.0.0.1.40614        CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.35750        CLOSE_WAIT
tcp        620      0  127.0.0.1.7777         127.0.0.1.19878        CLOSE_WAIT
tcp        620      0  127.0.0.1.7777         127.0.0.1.23455        CLOSE_WAIT
tcp        712      0  127.0.0.1.7777         127.0.0.1.11677        CLOSE_WAIT
tcp        709      0  127.0.0.1.7777         127.0.0.1.42396        CLOSE_WAIT
tcp        714      0  127.0.0.1.7777         127.0.0.1.24476        CLOSE_WAIT
tcp        710      0  127.0.0.1.7777         127.0.0.1.34202        CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.3225         CLOSE_WAIT
tcp        706      0  127.0.0.1.7777         127.0.0.1.36245        CLOSE_WAIT
tcp        707      0  127.0.0.1.7777         127.0.0.1.29332        CLOSE_WAIT
tcp        706      0  127.0.0.1.7777         127.0.0.1.5774         CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.18052        CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.9345         CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.25211        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.43641        CLOSE_WAIT
tcp        709      0  127.0.0.1.7777         127.0.0.1.13173        CLOSE_WAIT
tcp        622      0  127.0.0.1.7777         127.0.0.1.28268        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.15724        CLOSE_WAIT
tcp        706      0  127.0.0.1.7777         127.0.0.1.7016         CLOSE_WAIT
tcp        622      0  127.0.0.1.7777         127.0.0.1.47716        CLOSE_WAIT
tcp        709      0  127.0.0.1.7777         127.0.0.1.16737        CLOSE_WAIT
tcp          0      0  127.0.0.1.24476        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.16900        127.0.0.1.7777         SYN_SENT
tcp          0      0  127.0.0.1.29164        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.5077         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.14836        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.40614        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.8958         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.16821        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.44084        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.3225         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.18052        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.25921        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.7016         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.44773        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.47716        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.44346        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.9898         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.21938        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.22108        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.28268        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.34996        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.11677        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.22570        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.2223         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.10306        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.6989         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.6075         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.19018        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.25853        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.30511        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.40792        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.7738         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.13173        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.26458        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.16737        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.31681        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.3285         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.6079         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.15910        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.32485        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.5774         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.36245        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.42988        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.9345         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.43600        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.16851        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.35750        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.15724        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.28176        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.35524        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.25211        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.42446        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.30411        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.40178        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.27680        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.6998         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.42396        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.1448         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.40220        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.14355        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.23455        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.43641        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.13288        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.42191        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.10714        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.48356        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.19878        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.29332        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.34202        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.24923        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.28457        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.19008        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.38417        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.49075        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.3361         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.32776        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.34644        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.25949        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.10720        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.23378        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.44874        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.11793        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.38431        127.0.0.1.7777         FIN_WAIT_2
tcp        707      0  127.0.0.1.7777         127.0.0.1.25949        CLOSE_WAIT
tcp        622      0  127.0.0.1.7777         127.0.0.1.22108        CLOSE_WAIT
tcp        709      0  127.0.0.1.7777         127.0.0.1.24923        CLOSE_WAIT
tcp        709      0  127.0.0.1.7777         127.0.0.1.26458        CLOSE_WAIT
tcp        646      0  127.0.0.1.7777         127.0.0.1.40792        CLOSE_WAIT
tcp        708      0  127.0.0.1.7777         127.0.0.1.6998         CLOSE_WAIT
tcp        648      0  127.0.0.1.7777         127.0.0.1.34644        CLOSE_WAIT
tcp        705      0  127.0.0.1.7777         127.0.0.1.23378        CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.43600        CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.6989         CLOSE_WAIT
tcp        705      0  127.0.0.1.7777         127.0.0.1.44874        CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.19018        CLOSE_WAIT
tcp        714      0  127.0.0.1.7777         127.0.0.1.10306        CLOSE_WAIT
tcp        710      0  127.0.0.1.7777         127.0.0.1.25921        CLOSE_WAIT
tcp        709      0  127.0.0.1.7777         127.0.0.1.19008        CLOSE_WAIT
tcp        622      0  127.0.0.1.7777         127.0.0.1.44346        CLOSE_WAIT
tcp        646      0  127.0.0.1.7777         127.0.0.1.7738         CLOSE_WAIT
tcp        716      0  127.0.0.1.7777         127.0.0.1.44084        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.30511        CLOSE_WAIT
tcp        679      0  127.0.0.1.7777         127.0.0.1.22570        CLOSE_WAIT
tcp        710      0  127.0.0.1.7777         127.0.0.1.28457        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.15910        CLOSE_WAIT
tcp        707      0  127.0.0.1.7777         127.0.0.1.3361         CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.27680        CLOSE_WAIT
tcp          0      0  127.0.0.1.7777         127.0.0.1.38431        CLOSE_WAIT
tcp        709      0  127.0.0.1.7777         127.0.0.1.40220        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.14355        CLOSE_WAIT
tcp        710      0  127.0.0.1.7777         127.0.0.1.38417        CLOSE_WAIT
tcp        647      0  127.0.0.1.7777         127.0.0.1.11793        CLOSE_WAIT
tcp        713      0  127.0.0.1.7777         127.0.0.1.28176        CLOSE_WAIT
tcp        711      0  127.0.0.1.7777         127.0.0.1.32776        CLOSE_WAIT
tcp          0      0  127.0.0.1.7777         *.*                    LISTEN
% doas rcctl restart iredapd                
iredapd(ok)
iredapd(ok)
mail:~:% netstat -an | grep 7777   
tcp          0      0  127.0.0.1.38431        127.0.0.1.7777         TIME_WAIT
tcp          0      0  127.0.0.1.34329        127.0.0.1.7777         SYN_SENT
tcp          0      0  127.0.0.1.7777         *.*                    LISTEN

19

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Apparently, iredadmin and mlmmjadmin are failing quietly, and I don't know why.

% doas rcctl check iredadmin
iredadmin(failed)
% doas rcctl check mlmmjadmin
mlmmjadmin(failed)
% doas rcctl restart iredadmin
iredadmin(ok)
% doas rcctl restart mlmmjadmin
mlmmjadmin(ok)

20

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

It seems like uwsgi is the problem now.

Aug 17 15:31:14 mail uwsgi: *** Starting uWSGI 2.0.28 (64bit) on [Sun Aug 17 15:31:14 2025] ***
Aug 17 15:31:14 mail uwsgi: compiled with version: OpenBSD Clang 16.0.6 on 24 February 2025 17:33:12
Aug 17 15:31:14 mail uwsgi: compiled with version: OpenBSD Clang 16.0.6 on 24 February 2025 17:33:12
Aug 17 15:31:14 mail uwsgi: os: OpenBSD-7.7 GENERIC.MP#2
Aug 17 15:31:14 mail uwsgi: os: OpenBSD-7.7 GENERIC.MP#2
Aug 17 15:31:14 mail uwsgi: nodename: mail.example.com
Aug 17 15:31:14 mail uwsgi: nodename: mail.example.com
Aug 17 15:31:14 mail uwsgi: machine: amd64
Aug 17 15:31:14 mail uwsgi: machine: amd64
Aug 17 15:31:14 mail uwsgi: clock source: unix
Aug 17 15:31:14 mail uwsgi: clock source: unix
Aug 17 15:31:14 mail uwsgi: pcre jit disabled
Aug 17 15:31:14 mail uwsgi: pcre jit disabled
Aug 17 15:31:14 mail uwsgi: detected number of CPU cores: 4
Aug 17 15:31:14 mail uwsgi: detected number of CPU cores: 4
Aug 17 15:31:14 mail uwsgi: current working directory: /
Aug 17 15:31:14 mail uwsgi: current working directory: /
Aug 17 15:31:14 mail uwsgi: writing pidfile to /var/run/iredadmin/iredadmin.pid
Aug 17 15:31:14 mail uwsgi: writing pidfile to /var/run/iredadmin/iredadmin.pid
Aug 17 15:31:14 mail uwsgi: detected binary path: /usr/local/bin/uwsgi
Aug 17 15:31:14 mail uwsgi: detected binary path: /usr/local/bin/uwsgi
Aug 17 15:31:14 mail uwsgi: chdir() to /opt/www/iredadmin
Aug 17 15:31:14 mail uwsgi: chdir() to /opt/www/iredadmin
Aug 17 15:31:14 mail uwsgi: your processes number limit is 1310
Aug 17 15:31:14 mail uwsgi: your processes number limit is 1310
Aug 17 15:31:14 mail uwsgi: your memory page size is 4096 bytes
Aug 17 15:31:14 mail uwsgi: your memory page size is 4096 bytes
Aug 17 15:31:14 mail uwsgi: detected max file descriptor number: 128
Aug 17 15:31:14 mail uwsgi: detected max file descriptor number: 128
Aug 17 15:31:14 mail uwsgi: VirtualHosting mode enabled.
Aug 17 15:31:14 mail uwsgi: VirtualHosting mode enabled.
Aug 17 15:31:14 mail uwsgi: lock engine: ipcsem
Aug 17 15:31:14 mail uwsgi: lock engine: ipcsem
Aug 17 15:31:14 mail uwsgi: thunder lock: disabled (you can enable it with --thunder-lock)
Aug 17 15:31:14 mail uwsgi: thunder lock: disabled (you can enable it with --thunder-lock)
Aug 17 15:31:14 mail uwsgi: uwsgi socket 0 bound to TCP address 127.0.0.1:7791 fd 6
Aug 17 15:31:14 mail uwsgi: uwsgi socket 0 bound to TCP address 127.0.0.1:7791 fd 6
Aug 17 15:31:14 mail uwsgi: Python version: 3.11.10 (main, Oct  9 2024, 08:18:14) [Clang 16.0.6 ]
Aug 17 15:31:14 mail uwsgi: Python version: 3.11.10 (main, Oct  9 2024, 08:18:14) [Clang 16.0.6 ]
Aug 17 15:31:14 mail uwsgi: Could not find platform independent libraries <prefix>
Aug 17 15:31:14 mail uwsgi: Could not find platform independent libraries <prefix>
Aug 17 15:31:14 mail uwsgi: Could not find platform dependent libraries <exec_prefix>
Aug 17 15:31:14 mail uwsgi: Could not find platform dependent libraries <exec_prefix>
Aug 17 15:31:14 mail uwsgi: Python path configuration:
Aug 17 15:31:14 mail uwsgi: Python path configuration:
Aug 17 15:31:14 mail uwsgi:   PYTHONHOME = 
Aug 17 15:31:14 mail uwsgi:   PYTHONHOME = 
Aug 17 15:31:14 mail uwsgi: (not set)
Aug 17 15:31:14 mail uwsgi: (not set)
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   PYTHONPATH = 
Aug 17 15:31:14 mail uwsgi:   PYTHONPATH = 
Aug 17 15:31:14 mail uwsgi: (not set)
Aug 17 15:31:14 mail uwsgi: (not set)
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   program name = 
Aug 17 15:31:14 mail uwsgi:   program name = 
Aug 17 15:31:14 mail uwsgi: '
Aug 17 15:31:14 mail uwsgi: '
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: u
Aug 17 15:31:14 mail uwsgi: u
Aug 17 15:31:14 mail uwsgi: s
Aug 17 15:31:14 mail uwsgi: s
Aug 17 15:31:14 mail uwsgi: r
Aug 17 15:31:14 mail uwsgi: r
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: o
Aug 17 15:31:14 mail uwsgi: o
Aug 17 15:31:14 mail uwsgi: c
Aug 17 15:31:14 mail uwsgi: c
Aug 17 15:31:14 mail uwsgi: a
Aug 17 15:31:14 mail uwsgi: a
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: b
Aug 17 15:31:14 mail uwsgi: b
Aug 17 15:31:14 mail uwsgi: i
Aug 17 15:31:14 mail uwsgi: i
Aug 17 15:31:14 mail uwsgi: n
Aug 17 15:31:14 mail uwsgi: n
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: u
Aug 17 15:31:14 mail uwsgi: u
Aug 17 15:31:14 mail uwsgi: w
Aug 17 15:31:14 mail uwsgi: w
Aug 17 15:31:14 mail uwsgi: s
Aug 17 15:31:14 mail uwsgi: s
Aug 17 15:31:14 mail uwsgi: g
Aug 17 15:31:14 mail uwsgi: g
Aug 17 15:31:14 mail uwsgi: i
Aug 17 15:31:14 mail uwsgi: i
Aug 17 15:31:14 mail uwsgi: '
Aug 17 15:31:14 mail uwsgi: '
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   isolated = 0
Aug 17 15:31:14 mail uwsgi:   isolated = 0
Aug 17 15:31:14 mail uwsgi:   environment = 1
Aug 17 15:31:14 mail uwsgi:   environment = 1
Aug 17 15:31:14 mail uwsgi:   user site = 1
Aug 17 15:31:14 mail uwsgi:   user site = 1
Aug 17 15:31:14 mail uwsgi:   safe_path = 0
Aug 17 15:31:14 mail uwsgi:   safe_path = 0
Aug 17 15:31:14 mail uwsgi:   import site = 1
Aug 17 15:31:14 mail uwsgi:   import site = 1
Aug 17 15:31:14 mail uwsgi:   is in build tree = 0
Aug 17 15:31:14 mail uwsgi:   is in build tree = 0
Aug 17 15:31:14 mail uwsgi:   stdlib dir = 
Aug 17 15:31:14 mail uwsgi:   stdlib dir = 
Aug 17 15:31:14 mail uwsgi: '
Aug 17 15:31:14 mail uwsgi: '
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: u
Aug 17 15:31:14 mail uwsgi: u
Aug 17 15:31:14 mail uwsgi: s
Aug 17 15:31:14 mail uwsgi: s
Aug 17 15:31:14 mail uwsgi: r
Aug 17 15:31:14 mail uwsgi: r
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: o
Aug 17 15:31:14 mail uwsgi: o
Aug 17 15:31:14 mail uwsgi: c
Aug 17 15:31:14 mail uwsgi: c
Aug 17 15:31:14 mail uwsgi: a
Aug 17 15:31:14 mail uwsgi: a
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: l
Aug 17 15:31:14 mail uwsgi: i
Aug 17 15:31:14 mail uwsgi: i
Aug 17 15:31:14 mail uwsgi: b
Aug 17 15:31:14 mail uwsgi: b
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: /
Aug 17 15:31:14 mail uwsgi: p
Aug 17 15:31:14 mail uwsgi: p
Aug 17 15:31:14 mail uwsgi: y
Aug 17 15:31:14 mail uwsgi: y
Aug 17 15:31:14 mail uwsgi: t
Aug 17 15:31:14 mail uwsgi: t
Aug 17 15:31:14 mail uwsgi: h
Aug 17 15:31:14 mail uwsgi: h
Aug 17 15:31:14 mail uwsgi: o
Aug 17 15:31:14 mail uwsgi: o
Aug 17 15:31:14 mail uwsgi: n
Aug 17 15:31:14 mail uwsgi: n
Aug 17 15:31:14 mail uwsgi: 3
Aug 17 15:31:14 mail uwsgi: 3
Aug 17 15:31:14 mail uwsgi: .
Aug 17 15:31:14 mail uwsgi: .
Aug 17 15:31:14 mail uwsgi: 1
Aug 17 15:31:14 mail last message repeated 3 times
Aug 17 15:31:14 mail uwsgi: '
Aug 17 15:31:14 mail uwsgi: '
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   sys._base_executable = 
Aug 17 15:31:14 mail uwsgi:   sys._base_executable = 
Aug 17 15:31:14 mail uwsgi: '/usr/local/bin/uwsgi'
Aug 17 15:31:14 mail uwsgi: '/usr/local/bin/uwsgi'
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   sys.base_prefix = 
Aug 17 15:31:14 mail uwsgi:   sys.base_prefix = 
Aug 17 15:31:14 mail uwsgi: '/usr/local'
Aug 17 15:31:14 mail uwsgi: '/usr/local'
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   sys.base_exec_prefix = 
Aug 17 15:31:14 mail uwsgi:   sys.base_exec_prefix = 
Aug 17 15:31:14 mail uwsgi: '/usr/local'
Aug 17 15:31:14 mail uwsgi: '/usr/local'
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   sys.platlibdir = 
Aug 17 15:31:14 mail uwsgi:   sys.platlibdir = 
Aug 17 15:31:14 mail uwsgi: 'lib'
Aug 17 15:31:14 mail uwsgi: 'lib'
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   sys.executable = 
Aug 17 15:31:14 mail uwsgi:   sys.executable = 
Aug 17 15:31:14 mail uwsgi: '/usr/local/bin/uwsgi'
Aug 17 15:31:14 mail uwsgi: '/usr/local/bin/uwsgi'
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   sys.prefix = 
Aug 17 15:31:14 mail uwsgi:   sys.prefix = 
Aug 17 15:31:14 mail uwsgi: '/usr/local'
Aug 17 15:31:14 mail uwsgi: '/usr/local'
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   sys.exec_prefix = 
Aug 17 15:31:14 mail uwsgi:   sys.exec_prefix = 
Aug 17 15:31:14 mail uwsgi: '/usr/local'
Aug 17 15:31:14 mail uwsgi: '/usr/local'
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi:   sys.path = [
Aug 17 15:31:14 mail uwsgi:   sys.path = [
Aug 17 15:31:14 mail uwsgi:     '/usr/local/lib/python311.zip',
Aug 17 15:31:14 mail uwsgi:     '/usr/local/lib/python311.zip',
Aug 17 15:31:14 mail uwsgi:     '/usr/local/lib/python3.11',
Aug 17 15:31:14 mail uwsgi:     '/usr/local/lib/python3.11',
Aug 17 15:31:14 mail uwsgi:     '/usr/local/lib/python3.11/lib-dynload',
Aug 17 15:31:14 mail uwsgi:     '/usr/local/lib/python3.11/lib-dynload',
Aug 17 15:31:14 mail uwsgi:   ]
Aug 17 15:31:14 mail uwsgi:   ]
Aug 17 15:31:14 mail uwsgi: Fatal Python error: 
Aug 17 15:31:14 mail uwsgi: Fatal Python error: 
Aug 17 15:31:14 mail uwsgi: init_fs_encoding
Aug 17 15:31:14 mail uwsgi: init_fs_encoding
Aug 17 15:31:14 mail uwsgi: : 
Aug 17 15:31:14 mail uwsgi: : 
Aug 17 15:31:14 mail uwsgi: failed to get the Python codec of the filesystem encoding
Aug 17 15:31:14 mail uwsgi: failed to get the Python codec of the filesystem encoding
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: Python runtime state: 
Aug 17 15:31:14 mail uwsgi: Python runtime state: 
Aug 17 15:31:14 mail uwsgi: core initialized
Aug 17 15:31:14 mail uwsgi: core initialized
Aug 17 15:31:14 mail uwsgi: 
Aug 17 15:31:14 mail uwsgi: 

21

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Fix for uWSGI Python Version Mismatch on OpenBSD 7.7

Problem: uWSGI compiled for Python 3.11 but Python 3.11 standard library is missing/incomplete.

Solution: Rebuild uWSGI for Python 3.12 (the default Python on OpenBSD 7.7).

# Rebuild uWSGI from source
cd /root/uwsgi
python3.12 uwsgiconfig.py --clean
python3.12 uwsgiconfig.py --build

# Replace the binary
cp /usr/local/bin/uwsgi /usr/local/bin/uwsgi.bak
cp uwsgi /usr/local/bin/uwsgi

# Restart services
rcctl restart iredadmin
rcctl restart mlmmjadmin

Root cause: OpenBSD 7.7 ships with Python 3.12, but the existing uWSGI binary was compiled against Python 3.11 which lacked its standard library files.

22

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Fix fail2ban jails not loading at boot in OpenBSD 7.7
Problem: fail2ban service starts but jails don't activate because it starts before its dependencies (logs/services) are ready.
Solution: Reload fail2ban after boot completes using rc.local.

Add reload command to rc.local:

echo '(
    sleep 10
    /usr/local/bin/fail2ban-client -x reload
) &' >> /etc/rc.local

Make rc.local executable:

chmod +x /etc/rc.local

Reboot and verify:

reboot
# After reboot:
fail2ban-client status  # Should show active jails

Note: The 10-second delay ensures all monitored services/logs are ready. The & backgrounds the command so boot doesn't hang.

23 (edited by Neovana 2025-08-18 05:08:48)

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Fix nginx log rotation on OpenBSD 7.7

Problem: nginx logs stop recording after weekly rotation because newsyslog signals httpd instead of nginx.
Solution:

Edit /etc/newsyslog.conf

doas nano /etc/newsyslog.conf

Find these lines:

/var/www/logs/access.log 644  4     *    $W6D19  Z  "pkill -USR1 -u root -U root -x httpd"
/var/www/logs/error.log 644  7     250  *     Z  "pkill -USR1 -u root -U root -x httpd"

Change httpd to nginx in both lines:

/var/www/logs/access.log 644  4     *    $W6D19  Z  "pkill -USR1 -u root -U root -x nginx"
/var/www/logs/error.log 644  7     250  *     Z  "pkill -USR1 -u root -U root -x nginx"

Test (optional):

doas newsyslog -F

The issue occurs because newsyslog rotates the files but signals the wrong daemon. nginx needs the USR1 signal to reopen its log files after rotation.

24 (edited by Neovana 2025-08-19 15:13:51)

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Now getting "Server configuration problem" error messages in /var/log/maillog again.

% netstat -an | grep 7777
tcp        717      0  127.0.0.1.7777         127.0.0.1.42748        CLOSE_WAIT
tcp        661      0  127.0.0.1.7777         127.0.0.1.41457        CLOSE_WAIT
tcp        631      0  127.0.0.1.7777         127.0.0.1.18929        CLOSE_WAIT
tcp        718      0  127.0.0.1.7777         127.0.0.1.47086        CLOSE_WAIT
tcp        723      0  127.0.0.1.7777         127.0.0.1.34541        CLOSE_WAIT
tcp        700      0  127.0.0.1.7777         127.0.0.1.5090         CLOSE_WAIT
tcp        612      0  127.0.0.1.7777         127.0.0.1.41441        CLOSE_WAIT
tcp        688      0  127.0.0.1.7777         127.0.0.1.31962        CLOSE_WAIT
tcp        700      0  127.0.0.1.7777         127.0.0.1.31444        CLOSE_WAIT
tcp        670      0  127.0.0.1.7777         127.0.0.1.10964        CLOSE_WAIT
tcp        687      0  127.0.0.1.7777         127.0.0.1.7888         CLOSE_WAIT
tcp        654      0  127.0.0.1.7777         127.0.0.1.38351        CLOSE_WAIT
tcp        718      0  127.0.0.1.7777         127.0.0.1.28879        CLOSE_WAIT
tcp        669      0  127.0.0.1.7777         127.0.0.1.47310        CLOSE_WAIT
tcp        669      0  127.0.0.1.7777         127.0.0.1.40653        CLOSE_WAIT
tcp        705      0  127.0.0.1.7777         127.0.0.1.21197        CLOSE_WAIT
tcp        613      0  127.0.0.1.7777         127.0.0.1.39879        CLOSE_WAIT
tcp        662      0  127.0.0.1.7777         127.0.0.1.19398        CLOSE_WAIT
tcp        672      0  127.0.0.1.7777         127.0.0.1.27845        CLOSE_WAIT
tcp        661      0  127.0.0.1.7777         127.0.0.1.17085        CLOSE_WAIT
tcp        688      0  127.0.0.1.7777         127.0.0.1.2748         CLOSE_WAIT
tcp        706      0  127.0.0.1.7777         127.0.0.1.48054        CLOSE_WAIT
tcp        752      0  127.0.0.1.7777         127.0.0.1.25781        CLOSE_WAIT
tcp        717      0  127.0.0.1.7777         127.0.0.1.21939        CLOSE_WAIT
tcp        662      0  127.0.0.1.7777         127.0.0.1.32178        CLOSE_WAIT
tcp        628      0  127.0.0.1.7777         127.0.0.1.46001        CLOSE_WAIT
tcp        655      0  127.0.0.1.7777         127.0.0.1.28327        CLOSE_WAIT
tcp        670      0  127.0.0.1.7777         127.0.0.1.3238         CLOSE_WAIT
tcp        671      0  127.0.0.1.7777         127.0.0.1.48036        CLOSE_WAIT
tcp          0      0  127.0.0.1.7777         127.0.0.1.44708        CLOSE_WAIT
tcp        661      0  127.0.0.1.7777         127.0.0.1.2722         CLOSE_WAIT
tcp        655      0  127.0.0.1.7777         127.0.0.1.35999        CLOSE_WAIT
tcp        756      0  127.0.0.1.7777         127.0.0.1.24735        CLOSE_WAIT
tcp        661      0  127.0.0.1.7777         127.0.0.1.23686        CLOSE_WAIT
tcp        655      0  127.0.0.1.7777         127.0.0.1.14722        CLOSE_WAIT
tcp        752      0  127.0.0.1.7777         127.0.0.1.23168        CLOSE_WAIT
tcp        701      0  127.0.0.1.7777         127.0.0.1.30591        CLOSE_WAIT
tcp        660      0  127.0.0.1.7777         127.0.0.1.43899        CLOSE_WAIT
tcp        672      0  127.0.0.1.7777         127.0.0.1.21626        CLOSE_WAIT
tcp        717      0  127.0.0.1.7777         127.0.0.1.22901        CLOSE_WAIT
tcp        655      0  127.0.0.1.7777         127.0.0.1.42097        CLOSE_WAIT
tcp        700      0  127.0.0.1.7777         127.0.0.1.9329         CLOSE_WAIT
tcp        717      0  127.0.0.1.7777         127.0.0.1.22894        CLOSE_WAIT
tcp        686      0  127.0.0.1.7777         127.0.0.1.24682        CLOSE_WAIT
tcp        628      0  127.0.0.1.7777         127.0.0.1.10858        CLOSE_WAIT
tcp        700      0  127.0.0.1.7777         127.0.0.1.11879        CLOSE_WAIT
tcp          0      0  127.0.0.1.22857        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.30742        127.0.0.1.7777         SYN_SENT
tcp          0      0  127.0.0.1.39297        127.0.0.1.7777         SYN_SENT
tcp          0      0  127.0.0.1.22517        127.0.0.1.7777         SYN_SENT
tcp          0      0  127.0.0.1.34541        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.44573        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.2748         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.24682        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.11851        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.7888         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.42748        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.35999        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.2722         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.21939        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.28327        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.31962        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.28879        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.5407         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.6433         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.3238         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.12350        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.36147        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.40253        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.10964        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.25781        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.48036        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.8710         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.5706         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.47086        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.44544        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.8515         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.5953         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.21197        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.22901        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.8019         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.34328        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.24735        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.27845        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.21626        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.10858        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.46001        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.7174         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.46668        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.4896         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.41441        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.27651        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.23168        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.47310        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.40653        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.42097        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.43899        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.22894        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.14722        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.36630        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.17197        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.47706        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.27156        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.36958        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.30591        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.15108        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.39258        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.48054        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.3624         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.41007        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.32178        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.39453        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.43087        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.32518        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.18929        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.23686        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.5090         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.17085        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.9329         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.38351        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.11804        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.11879        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.31444        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.2875         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.29233        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.5707         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.39879        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.5464         127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.41457        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.19398        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.44708        127.0.0.1.7777         FIN_WAIT_2
tcp          0      0  127.0.0.1.36290        127.0.0.1.7777         SYN_SENT
tcp          0      0  127.0.0.1.22528        127.0.0.1.7777         SYN_SENT
tcp        715      0  127.0.0.1.7777         127.0.0.1.36958        CLOSE_WAIT
tcp        706      0  127.0.0.1.7777         127.0.0.1.47706        CLOSE_WAIT
tcp        715      0  127.0.0.1.7777         127.0.0.1.39258        CLOSE_WAIT
tcp        661      0  127.0.0.1.7777         127.0.0.1.5464         CLOSE_WAIT
tcp        756      0  127.0.0.1.7777         127.0.0.1.8019         CLOSE_WAIT
tcp        701      0  127.0.0.1.7777         127.0.0.1.43087        CLOSE_WAIT
tcp        718      0  127.0.0.1.7777         127.0.0.1.46668        CLOSE_WAIT
tcp        670      0  127.0.0.1.7777         127.0.0.1.11851        CLOSE_WAIT
tcp        630      0  127.0.0.1.7777         127.0.0.1.5707         CLOSE_WAIT
tcp        701      0  127.0.0.1.7777         127.0.0.1.5706         CLOSE_WAIT
tcp        671      0  127.0.0.1.7777         127.0.0.1.22857        CLOSE_WAIT
tcp        671      0  127.0.0.1.7777         127.0.0.1.8515         CLOSE_WAIT
tcp        717      0  127.0.0.1.7777         127.0.0.1.5953         CLOSE_WAIT
tcp        688      0  127.0.0.1.7777         127.0.0.1.12350        CLOSE_WAIT
tcp        752      0  127.0.0.1.7777         127.0.0.1.40253        CLOSE_WAIT
tcp        630      0  127.0.0.1.7777         127.0.0.1.2875         CLOSE_WAIT
tcp        613      0  127.0.0.1.7777         127.0.0.1.36147        CLOSE_WAIT
tcp        613      0  127.0.0.1.7777         127.0.0.1.29233        CLOSE_WAIT
tcp        654      0  127.0.0.1.7777         127.0.0.1.41007        CLOSE_WAIT
tcp        631      0  127.0.0.1.7777         127.0.0.1.17197        CLOSE_WAIT
tcp        706      0  127.0.0.1.7777         127.0.0.1.3624         CLOSE_WAIT
tcp        661      0  127.0.0.1.7777         127.0.0.1.6433         CLOSE_WAIT
tcp        627      0  127.0.0.1.7777         127.0.0.1.4896         CLOSE_WAIT
tcp        613      0  127.0.0.1.7777         127.0.0.1.5407         CLOSE_WAIT
tcp        723      0  127.0.0.1.7777         127.0.0.1.44573        CLOSE_WAIT
tcp        701      0  127.0.0.1.7777         127.0.0.1.39453        CLOSE_WAIT
tcp        661      0  127.0.0.1.7777         127.0.0.1.11804        CLOSE_WAIT
tcp        705      0  127.0.0.1.7777         127.0.0.1.34328        CLOSE_WAIT
tcp        660      0  127.0.0.1.7777         127.0.0.1.36630        CLOSE_WAIT
tcp        701      0  127.0.0.1.7777         127.0.0.1.27156        CLOSE_WAIT
tcp        631      0  127.0.0.1.7777         127.0.0.1.32518        CLOSE_WAIT
tcp        701      0  127.0.0.1.7777         127.0.0.1.8710         CLOSE_WAIT
tcp        627      0  127.0.0.1.7777         127.0.0.1.7174         CLOSE_WAIT
tcp        715      0  127.0.0.1.7777         127.0.0.1.15108        CLOSE_WAIT
tcp        752      0  127.0.0.1.7777         127.0.0.1.27651        CLOSE_WAIT
tcp        718      0  127.0.0.1.7777         127.0.0.1.44544        CLOSE_WAIT
tcp          0      0  127.0.0.1.7777         *.*                    LISTEN

Looks like iredapd is borked again, but it isn't reporting that it's borked…

% doas rcctl check iredadmin
iredadmin(ok)
% doas rcctl check iredapd 
iredapd(ok)
% doas rcctl check mlmmjadmin
mlmmjadmin(ok)

Restarting iredapd temporarily solves the issue:

:% doas rcctl restart iredapd
iredapd(ok)
iredapd(ok)
% netstat -an | grep 7777      
tcp          0      0  127.0.0.1.7777         127.0.0.1.35820        ESTABLISHED
tcp          0      0  127.0.0.1.7777         127.0.0.1.33395        ESTABLISHED
tcp          0      0  127.0.0.1.35820        127.0.0.1.7777         ESTABLISHED
tcp          0      0  127.0.0.1.33395        127.0.0.1.7777         ESTABLISHED
tcp          0      0  127.0.0.1.7777         *.*                    LISTEN

Potential reasons why this is happening:

• iredapd accepts connections but something (network issues, slow database queries, or client disconnects) causes connections to pile up
• Once it hits 128 open files, it can't accept new connections
• Postfix gets connection errors and returns 451 errors

Potential solutions:
• Increasing limits: Allows more connections but uses more resources
• Adding timeouts: Prevents stuck connections but might drop slow legitimate requests
• Auto-restart: Ensures availability but briefly interrupts service

Increasing file descriptor limits:

# Add a specific login class for iredapd
doas nano /etc/login.conf

# Add this section (note the indentation with tabs):
iredapd:\
    :openfiles-cur=512:\
    :openfiles-max=2048:\
    :tc=daemon:

# Rebuild the login.conf database
doas cap_mkdb /etc/login.conf

# Update the iredapd user to use this class
doas usermod -L iredapd iredapd

# Restart iredapd
doas rcctl restart iredapd

Add connection timeout settings to iredapd:

# Edit iredapd settings
doas nano /opt/iredapd/settings.py

# Add these lines:
# Close idle connections after 60 seconds
SOCKET_TIMEOUT = 60

Monitor and auto-recover (belt and suspenders):

# Enhanced monitoring script
cat << 'EOF' | doas tee /usr/local/bin/check_iredapd.sh
#!/bin/sh
STUCK_CONNS=$(netstat -an | grep 7777 | grep CLOSE_WAIT | wc -l)
TOTAL_CONNS=$(netstat -an | grep 7777 | wc -l)

if [ $STUCK_CONNS -gt 50 ] || [ $TOTAL_CONNS -gt 100 ]; then
    logger -t iredapd-monitor "Warning: $STUCK_CONNS stuck, $TOTAL_CONNS total connections"
    doas rcctl restart iredapd
    logger -t iredapd-monitor "iredapd restarted due to connection buildup"
fi
EOF

doas chmod +x /usr/local/bin/check_iredapd.sh

I've implemented all three options.

I still don't know what's causing the iredapd port 7777 instances to stall and pile-up. This is frustrating because mail is being rejected with "Server configuration problem" errors. There are 146 instances in the last 34 hours.

25

Re: OpenBSD 7.7 and iRedMail 1.7.4 PGSQL Nginx: many issues and fixes

Disable iredapd in /etc/postfix/main.cf temporarily by removing / commenting the "check_policy_service inet:127.0.0.1:7777" line.