-
Notifications
You must be signed in to change notification settings - Fork 2
Add SMTP configuration and environment support #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
c0582a0
fb735d1
d16c662
6205660
dd690cf
0915f2b
2f522a3
4def4d5
7b31f6c
232c0b2
8d5e840
109370d
442a9c4
43dfbd9
93914a1
a16d9dc
6232e3a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -346,6 +346,42 @@ Warning: using user "cluster" credentials from the environment | |
| "http2https": true | ||
| } | ||
| ``` | ||
| ## Smarthost setting discovery | ||
|
|
||
| Some configuration settings, like the smarthost setup, are not part of the | ||
| `configure-module` action input: they are discovered by looking at some | ||
| Redis keys. To ensure the module is always up-to-date with the | ||
| centralized [smarthost | ||
| setup](https://nethserver.github.io/ns8-core/core/smarthost/) every time | ||
| `phpfpm@.service` starts, the command `bin/discover-smarthost` runs and refreshes | ||
| the `state/smarthost.env` file with fresh values from Redis. | ||
|
|
||
| Furthermore if smarthost setup is changed when webserver is already | ||
| running, the event handler `events/smarthost-changed/10reload_services` | ||
| restarts `phpfpm@.service`. | ||
|
|
||
| See also the `systemd/user/phpfpm@.service` file. | ||
|
|
||
| ### Environment files for PHP versions | ||
|
|
||
| The systemd service is templated using `phpfpm@.service` to support multiple PHP versions. | ||
| Environment files are present and loaded inside the container for each PHP version instance. | ||
| For example, when the systemd service `phpfpm@8.5.service` runs, it loads the following environment files: | ||
|
|
||
| - `state/smarthost.env` - SMTP and smarthost configuration (optional, prefixed with `SMTP_`) | ||
|
|
||
| These environment variables are automatically passed to the corresponding PHP-FPM container instance, allowing configuration to be centrally managed through environment files that apply to all PHP versions (8.5, 8.4, 8.3, etc.). | ||
| This setting discovery is just an example to understand how the module is expected to work: | ||
| ``` | ||
| cat smarthost.env | ||
|
Comment on lines
+371
to
+376
|
||
| SMTP_ENABLED=1 | ||
| SMTP_HOST=10.5.4.1 | ||
| SMTP_PORT=25 | ||
| SMTP_USERNAME= | ||
| SMTP_PASSWORD= | ||
| SMTP_ENCRYPTION=none | ||
| SMTP_TLSVERIFY= | ||
| ``` | ||
|
|
||
| ## Uninstall | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| # | ||
| # Copyright (C) 2026 Nethesis S.r.l. | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # | ||
|
|
||
| import agent | ||
| import os | ||
|
|
||
| # Connect the local Redis replica. This is necessary to consistently start | ||
| # the service if the leader node is not reachable: | ||
| rdb = agent.redis_connect(use_replica=True) | ||
| smtp_settings = agent.get_smarthost_settings(rdb) | ||
|
|
||
| # create the smarthost folder | ||
| envfile = 'smarthosts/smarthost.env' | ||
|
|
||
| # Ensure the target directory exists: | ||
| os.makedirs(os.path.dirname(envfile), exist_ok=True) | ||
|
|
||
| # Create a unique temporary file using process PID to avoid concurrent writes: | ||
| tmp_path = f"{envfile}.tmp.{os.getpid()}" | ||
|
|
||
| with open(tmp_path, "w") as efp: | ||
| # HINT for lamp: adjust variable names as needed | ||
| print(f"SMTP_ENABLED={'1' if smtp_settings['enabled'] else ''}", file=efp) | ||
| print(f"SMTP_HOST={smtp_settings['host']}", file=efp) | ||
| print(f"SMTP_PORT={smtp_settings['port']}", file=efp) | ||
| print(f"SMTP_USERNAME={smtp_settings['username']}", file=efp) | ||
| print(f"SMTP_PASSWORD={smtp_settings['password']}", file=efp) | ||
| print(f"SMTP_ENCRYPTION={smtp_settings['encrypt_smtp']}", file=efp) | ||
| print(f"SMTP_TLSVERIFY={'1' if smtp_settings['tls_verify'] else ''}", file=efp) | ||
|
|
||
| # Commit changes by atomically replacing the existing envfile: | ||
| os.replace(tmp_path, envfile) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,19 @@ | ||||||||||||||||||||||||||||||||||||||
| #!/usr/bin/env python3 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||
| # Copyright (C) 2026 Nethesis S.r.l. | ||||||||||||||||||||||||||||||||||||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import subprocess | ||||||||||||||||||||||||||||||||||||||
| import glob | ||||||||||||||||||||||||||||||||||||||
| import re | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| # detect if a service has configurations and restart it | ||||||||||||||||||||||||||||||||||||||
| PhpServiceArray = glob.glob('php*-fpm-custom.d') | ||||||||||||||||||||||||||||||||||||||
| for folder in PhpServiceArray: | ||||||||||||||||||||||||||||||||||||||
| ConfiguredServices = re.findall('php[0-9\.]+', folder) | ||||||||||||||||||||||||||||||||||||||
| ListConfigurations = glob.glob(folder+'/dyn-*.conf') | ||||||||||||||||||||||||||||||||||||||
| if ListConfigurations : | ||||||||||||||||||||||||||||||||||||||
| subprocess.run(["download-php-fpm",ConfiguredServices[0].replace('php','')]) | ||||||||||||||||||||||||||||||||||||||
| subprocess.run(["systemctl", "--user", "restart", "phpfpm@"+ConfiguredServices[0].replace('php','')+".service"]) | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+16
to
+19
|
||||||||||||||||||||||||||||||||||||||
| ListConfigurations = glob.glob(folder+'/dyn-*.conf') | |
| if ListConfigurations : | |
| subprocess.run(["download-php-fpm",ConfiguredServices[0].replace('php','')]) | |
| subprocess.run(["systemctl", "--user", "restart", "phpfpm@"+ConfiguredServices[0].replace('php','')+".service"]) | |
| if not ConfiguredServices: | |
| # Skip folders that do not match the expected php version pattern | |
| continue | |
| php_version = ConfiguredServices[0].replace('php', '') | |
| ListConfigurations = glob.glob(folder + '/dyn-*.conf') | |
| if ListConfigurations: | |
| try: | |
| subprocess.run(["download-php-fpm", php_version], check=True) | |
| subprocess.run( | |
| ["systemctl", "--user", "restart", f"phpfpm@{php_version}.service"], | |
| check=True, | |
| ) | |
| except subprocess.CalledProcessError as e: | |
| print(f"Error handling php-fpm service for {php_version}: {e}", flush=True) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -9,15 +9,18 @@ Environment=PODMAN_SYSTEMD_UNIT=%n | |||||
| EnvironmentFile=%S/state/environment | ||||||
| EnvironmentFile=%S/state/image_url_tag.env | ||||||
| WorkingDirectory=%S/state | ||||||
| EnvironmentFile=-%S/state/smarthosts/smarthost.env | ||||||
|
||||||
| Restart=always | ||||||
| TimeoutStopSec=70 | ||||||
| ExecStartPre=/bin/rm -f %t/php%i-fpm.pid %t/php%i-fpm.ctr-id | ||||||
| ExecStartPre=/usr/bin/mkdir -p %S/state/php%i-fpm-custom.d | ||||||
| ExecStartPre=-runagent discover-smarthost | ||||||
|
||||||
| ExecStartPre=-runagent discover-smarthost | |
| ExecStartPre=-/usr/local/bin/runagent discover-smarthost |
Copilot
AI
Feb 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
podman run --env SMTP_* will pass a literal variable name SMTP_* (systemd does not do shell glob expansion for ExecStart arguments, and * is not a valid env var name). As a result, SMTP variables won’t be propagated into the container. Prefer --env-file pointing to the generated env file, or explicitly list each SMTP_... variable to forward.
| --env SMTP_* \ | |
| --env-file %S/state/smarthosts/smarthost.env \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation doesn’t match the implementation: the unit references
state/smarthosts/smarthost.env(anddiscover-smarthostwrites undersmarthosts/), but the README mentionsstate/smarthost.env. Also, the documented handler nameevents/smarthost-changed/10reload_servicesdoesn’t exist in this PR (added file is10restart_phpfpm). Update the paths/names to reflect the actual files.