We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
mailu front fails with KeyError: 'LD_PRELOAD'
<!--

Thank you for opening an issue with Mailu. Please understand that issues are meant for bugs and enhancement-requests.
For **user-support questions**, reach out to us  on [matrix](https://matrix.to/#/#mailu:tedomum.net).

To be able to help you best, we need some more information.

Before you open your issue
- Check if no issue or pull-request for this already exists.
- Check [documentation](https://mailu.io/master/) and [FAQ](https://mailu.io/master/faq.html). (Tip, use the search function on the documentation page)
- You understand `Mailu` is made by volunteers in their **free time** — be concise, civil and accept that delays can occur.
- The title of the issue should be short and simple. It should contain specific terms related to the actual issue. Be specific while writing the title.

Please put your text outside of the comment blocks to be visible. You can use the button "Preview" above to check.

-->

## Environment & Version

### Environment

- [X] docker compose
- [ ] kubernetes
- [ ] docker swarm

### Version

- Version: `2.0`

<!--
To find your version, get the image name of a mailu container and read  the version from the tag (example for version 1.7).

$> docker ps -a | grep mailu
140b09d4b09c    mailu/roundcube:1.7    "docker-php-entrypoi…"    2 weeks ago    Up 2 days (healthy)    80/tcp
$> grep MAILU_VERSION docker-compose.yml mailu.env
-->

## Description
<!--
Further explain the bug in a few words. It should be clear what the unexpected behaviour is.  Share it in an easy-to-understand language.
-->
Pulled the image today to create a new server. The nginx fails with the following error.

## Replication Steps
<!--
Steps for replicating your issue
-->
* docker-compose up -d
* docker shows unhealthy front container
* docker logs mailu_front_1

## Observed behaviour
<!--
Explain or paste the result you received.
-->

## Expected behaviour
<!--
Explain what results you expected - be as specific as possible.
Just saying "it doesn’t work as expected" is not useful. It's also helpful to describe what you actually experienced.
-->

## Logs
<!--
Often it is very useful to include log fragments of the involved component.
You can get the logs via `docker logs <container name> --tail 1000`.
For example for the admin container: `docker logs mailu_admin_1 --tail 1000`
or using docker compose `docker compose -f /mailu/docker-compose.yml logs --tail 1000 admin`

If you can find the relevant section, please share only the parts that seem relevant. If you have any logs, please enclose them in code tags, like so:

-->


```
# docker logs mailu_front_1
Traceback (most recent call last):
  File "/config.py", line 8, in <module>
    args = system.set_env()
  File "/app/venv/lib/python3.10/site-packages/socrate/system.py", line 80, in set_env
    del os.environ['LD_PRELOAD']
  File "/usr/lib/python3.10/os.py", line 696, in __delitem__
    raise KeyError(key) from None
KeyError: 'LD_PRELOAD'
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `core/base/libs/socrate/socrate/system.py`
Content:
```
1 import hmac
2 import logging as log
3 import os
4 import sys
5 import re
6 from pwd import getpwnam
7 import socket
8 import tenacity
9 
10 @tenacity.retry(stop=tenacity.stop_after_attempt(100),
11                 wait=tenacity.wait_random(min=2, max=5))
12 def resolve_hostname(hostname):
13     """ This function uses system DNS to resolve a hostname.
14     It is capable of retrying in case the host is not immediately available
15     """
16     try:
17         return sorted(socket.getaddrinfo(hostname, None, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE), key=lambda s:s[0])[0][4][0]
18     except Exception as e:
19         log.warn("Unable to lookup '%s': %s",hostname,e)
20         raise e
21 
22 def _coerce_value(value):
23     if isinstance(value, str) and value.lower() in ('true','yes'):
24         return True
25     elif isinstance(value, str) and value.lower() in ('false', 'no'):
26         return False
27     return value
28 
29 class LogFilter(object):
30     def __init__(self, stream, re_patterns, log_file):
31         self.stream = stream
32         if isinstance(re_patterns, list):
33             self.pattern = re.compile('|'.join([f'(?:{pattern})' for pattern in re_patterns]))
34         elif isinstance(re_patterns, str):
35             self.pattern = re.compile(re_patterns)
36         else:
37             self.pattern = re_patterns
38         self.found = False
39         self.log_file = log_file
40 
41     def __getattr__(self, attr_name):
42         return getattr(self.stream, attr_name)
43 
44     def write(self, data):
45         if data == '\n' and self.found:
46             self.found = False
47         else:
48             if not self.pattern.search(data):
49                 self.stream.write(data)
50                 self.stream.flush()
51                 if self.log_file:
52                     try:
53                         with open(self.log_file, 'a', encoding='utf-8') as l:
54                             l.write(data)
55                     except:
56                         pass
57             else:
58                 # caught bad pattern
59                 self.found = True
60 
61     def flush(self):
62         self.stream.flush()
63 
64 def _is_compatible_with_hardened_malloc():
65     with open('/proc/cpuinfo', 'r') as f:
66         lines = f.readlines()
67         for line in lines:
68             # See #2764, we need vmovdqu
69             if line.startswith('flags') and ' avx ' not in line:
70                 return False
71     return True
72 
73 def set_env(required_secrets=[], log_filters=[], log_file=None):
74     if log_filters:
75         sys.stdout = LogFilter(sys.stdout, log_filters, log_file)
76         sys.stderr = LogFilter(sys.stderr, log_filters, log_file)
77     log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", 'WARNING'))
78 
79     if not _is_compatible_with_hardened_malloc():
80         del os.environ['LD_PRELOAD']
81 
82     """ This will set all the environment variables and retains only the secrets we need """
83     if 'SECRET_KEY_FILE' in os.environ:
84         try:
85             secret_key = open(os.environ.get("SECRET_KEY_FILE"), "r").read().strip()
86         except Exception as exc:
87             log.error(f"Can't read SECRET_KEY from file: {exc}")
88             raise exc
89     else:
90         secret_key = os.environ.get('SECRET_KEY')
91     clean_env()
92     # derive the keys we need
93     for secret in required_secrets:
94         os.environ[f'{secret}_KEY'] = hmac.new(bytearray(secret_key, 'utf-8'), bytearray(secret, 'utf-8'), 'sha256').hexdigest()
95 
96     return {
97             key: _coerce_value(os.environ.get(key, value))
98             for key, value in os.environ.items()
99            }
100 
101 def clean_env():
102     """ remove all secret keys """
103     [os.environ.pop(key, None) for key in os.environ.keys() if key.endswith("_KEY")]
104 
105 def drop_privs_to(username='mailu'):
106     pwnam = getpwnam(username)
107     os.setgroups([])
108     os.setgid(pwnam.pw_gid)
109     os.setuid(pwnam.pw_uid)
110     os.environ['HOME'] = pwnam.pw_dir
111
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/core/base/libs/socrate/socrate/system.py b/core/base/libs/socrate/socrate/system.py
--- a/core/base/libs/socrate/socrate/system.py
+++ b/core/base/libs/socrate/socrate/system.py
@@ -68,6 +68,9 @@
             # See #2764, we need vmovdqu
             if line.startswith('flags') and ' avx ' not in line:
                 return False
+            # See #2541
+            if line.startswith('Features') and ' lrcpc ' not in line:
+                return False
     return True
 
 def set_env(required_secrets=[], log_filters=[], log_file=None):
@@ -76,7 +79,8 @@
         sys.stderr = LogFilter(sys.stderr, log_filters, log_file)
     log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", 'WARNING'))
 
-    if not _is_compatible_with_hardened_malloc():
+    if 'LD_PRELOAD' in os.environ and not _is_compatible_with_hardened_malloc():
+        log.warning('Disabling hardened-malloc on this CPU')
         del os.environ['LD_PRELOAD']
 
     """ This will set all the environment variables and retains only the secrets we need """

{"golden_diff": "diff --git a/core/base/libs/socrate/socrate/system.py b/core/base/libs/socrate/socrate/system.py\n--- a/core/base/libs/socrate/socrate/system.py\n+++ b/core/base/libs/socrate/socrate/system.py\n@@ -68,6 +68,9 @@\n             # See #2764, we need vmovdqu\n             if line.startswith('flags') and ' avx ' not in line:\n                 return False\n+            # See #2541\n+            if line.startswith('Features') and ' lrcpc ' not in line:\n+                return False\n     return True\n \n def set_env(required_secrets=[], log_filters=[], log_file=None):\n@@ -76,7 +79,8 @@\n         sys.stderr = LogFilter(sys.stderr, log_filters, log_file)\n     log.basicConfig(stream=sys.stderr, level=os.environ.get(\"LOG_LEVEL\", 'WARNING'))\n \n-    if not _is_compatible_with_hardened_malloc():\n+    if 'LD_PRELOAD' in os.environ and not _is_compatible_with_hardened_malloc():\n+        log.warning('Disabling hardened-malloc on this CPU')\n         del os.environ['LD_PRELOAD']\n \n     \"\"\" This will set all the environment variables and retains only the secrets we need \"\"\"\n", "issue": "mailu front fails with KeyError: 'LD_PRELOAD'\n<!--\r\n\r\nThank you for opening an issue with Mailu. Please understand that issues are meant for bugs and enhancement-requests.\r\nFor **user-support questions**, reach out to us  on [matrix](https://matrix.to/#/#mailu:tedomum.net).\r\n\r\nTo be able to help you best, we need some more information.\r\n\r\nBefore you open your issue\r\n- Check if no issue or pull-request for this already exists.\r\n- Check [documentation](https://mailu.io/master/) and [FAQ](https://mailu.io/master/faq.html). (Tip, use the search function on the documentation page)\r\n- You understand `Mailu` is made by volunteers in their **free time** \u2014 be concise, civil and accept that delays can occur.\r\n- The title of the issue should be short and simple. It should contain specific terms related to the actual issue. Be specific while writing the title.\r\n\r\nPlease put your text outside of the comment blocks to be visible. You can use the button \"Preview\" above to check.\r\n\r\n-->\r\n\r\n## Environment & Version\r\n\r\n### Environment\r\n\r\n- [X] docker compose\r\n- [ ] kubernetes\r\n- [ ] docker swarm\r\n\r\n### Version\r\n\r\n- Version: `2.0`\r\n\r\n<!--\r\nTo find your version, get the image name of a mailu container and read  the version from the tag (example for version 1.7).\r\n\r\n$> docker ps -a | grep mailu\r\n140b09d4b09c    mailu/roundcube:1.7    \"docker-php-entrypoi\u2026\"    2 weeks ago    Up 2 days (healthy)    80/tcp\r\n$> grep MAILU_VERSION docker-compose.yml mailu.env\r\n-->\r\n\r\n## Description\r\n<!--\r\nFurther explain the bug in a few words. It should be clear what the unexpected behaviour is.  Share it in an easy-to-understand language.\r\n-->\r\nPulled the image today to create a new server. The nginx fails with the following error.\r\n\r\n## Replication Steps\r\n<!--\r\nSteps for replicating your issue\r\n-->\r\n* docker-compose up -d\r\n* docker shows unhealthy front container\r\n* docker logs mailu_front_1\r\n\r\n## Observed behaviour\r\n<!--\r\nExplain or paste the result you received.\r\n-->\r\n\r\n## Expected behaviour\r\n<!--\r\nExplain what results you expected - be as specific as possible.\r\nJust saying \"it doesn\u2019t work as expected\" is not useful. It's also helpful to describe what you actually experienced.\r\n-->\r\n\r\n## Logs\r\n<!--\r\nOften it is very useful to include log fragments of the involved component.\r\nYou can get the logs via `docker logs <container name> --tail 1000`.\r\nFor example for the admin container: `docker logs mailu_admin_1 --tail 1000`\r\nor using docker compose `docker compose -f /mailu/docker-compose.yml logs --tail 1000 admin`\r\n\r\nIf you can find the relevant section, please share only the parts that seem relevant. If you have any logs, please enclose them in code tags, like so:\r\n\r\n-->\r\n\r\n\r\n```\r\n# docker logs mailu_front_1\r\nTraceback (most recent call last):\r\n  File \"/config.py\", line 8, in <module>\r\n    args = system.set_env()\r\n  File \"/app/venv/lib/python3.10/site-packages/socrate/system.py\", line 80, in set_env\r\n    del os.environ['LD_PRELOAD']\r\n  File \"/usr/lib/python3.10/os.py\", line 696, in __delitem__\r\n    raise KeyError(key) from None\r\nKeyError: 'LD_PRELOAD'\r\n```\r\n\n", "before_files": [{"content": "import hmac\nimport logging as log\nimport os\nimport sys\nimport re\nfrom pwd import getpwnam\nimport socket\nimport tenacity\n\n@tenacity.retry(stop=tenacity.stop_after_attempt(100),\n                wait=tenacity.wait_random(min=2, max=5))\ndef resolve_hostname(hostname):\n    \"\"\" This function uses system DNS to resolve a hostname.\n    It is capable of retrying in case the host is not immediately available\n    \"\"\"\n    try:\n        return sorted(socket.getaddrinfo(hostname, None, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE), key=lambda s:s[0])[0][4][0]\n    except Exception as e:\n        log.warn(\"Unable to lookup '%s': %s\",hostname,e)\n        raise e\n\ndef _coerce_value(value):\n    if isinstance(value, str) and value.lower() in ('true','yes'):\n        return True\n    elif isinstance(value, str) and value.lower() in ('false', 'no'):\n        return False\n    return value\n\nclass LogFilter(object):\n    def __init__(self, stream, re_patterns, log_file):\n        self.stream = stream\n        if isinstance(re_patterns, list):\n            self.pattern = re.compile('|'.join([f'(?:{pattern})' for pattern in re_patterns]))\n        elif isinstance(re_patterns, str):\n            self.pattern = re.compile(re_patterns)\n        else:\n            self.pattern = re_patterns\n        self.found = False\n        self.log_file = log_file\n\n    def __getattr__(self, attr_name):\n        return getattr(self.stream, attr_name)\n\n    def write(self, data):\n        if data == '\\n' and self.found:\n            self.found = False\n        else:\n            if not self.pattern.search(data):\n                self.stream.write(data)\n                self.stream.flush()\n                if self.log_file:\n                    try:\n                        with open(self.log_file, 'a', encoding='utf-8') as l:\n                            l.write(data)\n                    except:\n                        pass\n            else:\n                # caught bad pattern\n                self.found = True\n\n    def flush(self):\n        self.stream.flush()\n\ndef _is_compatible_with_hardened_malloc():\n    with open('/proc/cpuinfo', 'r') as f:\n        lines = f.readlines()\n        for line in lines:\n            # See #2764, we need vmovdqu\n            if line.startswith('flags') and ' avx ' not in line:\n                return False\n    return True\n\ndef set_env(required_secrets=[], log_filters=[], log_file=None):\n    if log_filters:\n        sys.stdout = LogFilter(sys.stdout, log_filters, log_file)\n        sys.stderr = LogFilter(sys.stderr, log_filters, log_file)\n    log.basicConfig(stream=sys.stderr, level=os.environ.get(\"LOG_LEVEL\", 'WARNING'))\n\n    if not _is_compatible_with_hardened_malloc():\n        del os.environ['LD_PRELOAD']\n\n    \"\"\" This will set all the environment variables and retains only the secrets we need \"\"\"\n    if 'SECRET_KEY_FILE' in os.environ:\n        try:\n            secret_key = open(os.environ.get(\"SECRET_KEY_FILE\"), \"r\").read().strip()\n        except Exception as exc:\n            log.error(f\"Can't read SECRET_KEY from file: {exc}\")\n            raise exc\n    else:\n        secret_key = os.environ.get('SECRET_KEY')\n    clean_env()\n    # derive the keys we need\n    for secret in required_secrets:\n        os.environ[f'{secret}_KEY'] = hmac.new(bytearray(secret_key, 'utf-8'), bytearray(secret, 'utf-8'), 'sha256').hexdigest()\n\n    return {\n            key: _coerce_value(os.environ.get(key, value))\n            for key, value in os.environ.items()\n           }\n\ndef clean_env():\n    \"\"\" remove all secret keys \"\"\"\n    [os.environ.pop(key, None) for key in os.environ.keys() if key.endswith(\"_KEY\")]\n\ndef drop_privs_to(username='mailu'):\n    pwnam = getpwnam(username)\n    os.setgroups([])\n    os.setgid(pwnam.pw_gid)\n    os.setuid(pwnam.pw_uid)\n    os.environ['HOME'] = pwnam.pw_dir\n", "path": "core/base/libs/socrate/socrate/system.py"}], "after_files": [{"content": "import hmac\nimport logging as log\nimport os\nimport sys\nimport re\nfrom pwd import getpwnam\nimport socket\nimport tenacity\n\n@tenacity.retry(stop=tenacity.stop_after_attempt(100),\n                wait=tenacity.wait_random(min=2, max=5))\ndef resolve_hostname(hostname):\n    \"\"\" This function uses system DNS to resolve a hostname.\n    It is capable of retrying in case the host is not immediately available\n    \"\"\"\n    try:\n        return sorted(socket.getaddrinfo(hostname, None, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE), key=lambda s:s[0])[0][4][0]\n    except Exception as e:\n        log.warn(\"Unable to lookup '%s': %s\",hostname,e)\n        raise e\n\ndef _coerce_value(value):\n    if isinstance(value, str) and value.lower() in ('true','yes'):\n        return True\n    elif isinstance(value, str) and value.lower() in ('false', 'no'):\n        return False\n    return value\n\nclass LogFilter(object):\n    def __init__(self, stream, re_patterns, log_file):\n        self.stream = stream\n        if isinstance(re_patterns, list):\n            self.pattern = re.compile('|'.join([f'(?:{pattern})' for pattern in re_patterns]))\n        elif isinstance(re_patterns, str):\n            self.pattern = re.compile(re_patterns)\n        else:\n            self.pattern = re_patterns\n        self.found = False\n        self.log_file = log_file\n\n    def __getattr__(self, attr_name):\n        return getattr(self.stream, attr_name)\n\n    def write(self, data):\n        if data == '\\n' and self.found:\n            self.found = False\n        else:\n            if not self.pattern.search(data):\n                self.stream.write(data)\n                self.stream.flush()\n                if self.log_file:\n                    try:\n                        with open(self.log_file, 'a', encoding='utf-8') as l:\n                            l.write(data)\n                    except:\n                        pass\n            else:\n                # caught bad pattern\n                self.found = True\n\n    def flush(self):\n        self.stream.flush()\n\ndef _is_compatible_with_hardened_malloc():\n    with open('/proc/cpuinfo', 'r') as f:\n        lines = f.readlines()\n        for line in lines:\n            # See #2764, we need vmovdqu\n            if line.startswith('flags') and ' avx ' not in line:\n                return False\n            # See #2541\n            if line.startswith('Features') and ' lrcpc ' not in line:\n                return False\n    return True\n\ndef set_env(required_secrets=[], log_filters=[], log_file=None):\n    if log_filters:\n        sys.stdout = LogFilter(sys.stdout, log_filters, log_file)\n        sys.stderr = LogFilter(sys.stderr, log_filters, log_file)\n    log.basicConfig(stream=sys.stderr, level=os.environ.get(\"LOG_LEVEL\", 'WARNING'))\n\n    if 'LD_PRELOAD' in os.environ and not _is_compatible_with_hardened_malloc():\n        log.warning('Disabling hardened-malloc on this CPU')\n        del os.environ['LD_PRELOAD']\n\n    \"\"\" This will set all the environment variables and retains only the secrets we need \"\"\"\n    if 'SECRET_KEY_FILE' in os.environ:\n        try:\n            secret_key = open(os.environ.get(\"SECRET_KEY_FILE\"), \"r\").read().strip()\n        except Exception as exc:\n            log.error(f\"Can't read SECRET_KEY from file: {exc}\")\n            raise exc\n    else:\n        secret_key = os.environ.get('SECRET_KEY')\n    clean_env()\n    # derive the keys we need\n    for secret in required_secrets:\n        os.environ[f'{secret}_KEY'] = hmac.new(bytearray(secret_key, 'utf-8'), bytearray(secret, 'utf-8'), 'sha256').hexdigest()\n\n    return {\n            key: _coerce_value(os.environ.get(key, value))\n            for key, value in os.environ.items()\n           }\n\ndef clean_env():\n    \"\"\" remove all secret keys \"\"\"\n    [os.environ.pop(key, None) for key in os.environ.keys() if key.endswith(\"_KEY\")]\n\ndef drop_privs_to(username='mailu'):\n    pwnam = getpwnam(username)\n    os.setgroups([])\n    os.setgid(pwnam.pw_gid)\n    os.setuid(pwnam.pw_uid)\n    os.environ['HOME'] = pwnam.pw_dir\n", "path": "core/base/libs/socrate/socrate/system.py"}]}