Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test-module.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ on:
jobs:
module:
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event.workflow_run.conclusion == '' }}
uses: NethServer/ns8-github-actions/.github/workflows/module-info.yml@main
uses: NethServer/ns8-github-actions/.github/workflows/module-info.yml@v1
run_tests:
needs: module
uses: NethServer/ns8-github-actions/.github/workflows/test-on-digitalocean-infra.yml@main
uses: NethServer/ns8-github-actions/.github/workflows/test-on-digitalocean-infra.yml@v1
with:
args: "ghcr.io/${{needs.module.outputs.owner}}/${{needs.module.outputs.name}}:${{needs.module.outputs.tag}}"
repo_ref: ${{needs.module.outputs.sha}}
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Then launch `configure-module`, by setting the following parameters:
- fully qualified domain name for Nextcloud
- let's encrypt option
- LDAP domain (optional)
- use internal Nextcloud mail sending settings or the cluster smarthost

Example:
```
Expand All @@ -35,7 +36,8 @@ api-cli run module/nextcloud1/configure-module --data - <<EOF
"host": "nextcloud.nethserver.org",
"lets_encrypt": true,
"domain": "ad.nethserver.org",
"password": "Nethesis,1234"
"password": "Nethesis,1234",
"internal_smarthost": false
}
EOF
```
Expand Down
4 changes: 2 additions & 2 deletions build-images.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ buildah config --entrypoint=/ \
--label="org.nethserver.rootfull=0" \
--label="org.nethserver.volumes=nextcloud-app-data" \
--label="org.nethserver.min-from=1.5.0" \
--label="org.nethserver.min-core=3.12.4-0" \
--label="org.nethserver.images=docker.io/redis:7.4.5-alpine docker.io/mariadb:10.6.24 docker.io/nginx:1.29.2-alpine ghcr.io/nethserver/nextcloud-app:${IMAGETAG} ghcr.io/nethserver/nextcloud-notify_push:${IMAGETAG}" \
--label="org.nethserver.min-core=3.18.0-0" \
--label="org.nethserver.images=docker.io/redis:7.4.5-alpine docker.io/mariadb:10.6.25 docker.io/nginx:1.29.2-alpine ghcr.io/nethserver/nextcloud-app:${IMAGETAG} ghcr.io/nethserver/nextcloud-notify_push:${IMAGETAG}" \
"${container}"
# Commit the image
buildah commit "${container}" "${repobase}/${reponame}"
Expand Down
3 changes: 3 additions & 0 deletions imageroot/actions/get-configuration/20read
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,8 @@ config["is_collabora"] = True if array_collabora else False
if "tls_verify_collabora" not in config:
config["tls_verify_collabora"] = False

if "internal_smarthost" not in config:
config["internal_smarthost"] = False
Comment thread
mrmarkuz marked this conversation as resolved.

# Dump the configuration to stdout
json.dump(config, fp=sys.stdout)
15 changes: 5 additions & 10 deletions imageroot/bin/discover-smarthost
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@ smtp_settings = agent.get_smarthost_settings(rdb)

envfile = "smarthost.env"

# Using .tmp suffix: do not overwrite the target file until the new one is
# saved to disk:
if not smtp_settings['host']:
with open('config.json', 'r') as cf:
config = json.loads(cf.read())

if not smtp_settings['host'] or config['internal_smarthost'] == True:
f = open(envfile, "w")
f.write("")
f.close
sys.exit(0)

with open('config.json', 'r') as cf:
config = json.loads(cf.read())

domain = config['host'].split('.',1)[1]

with open(envfile + ".tmp", "w") as efp:
with agent.safe_open(envfile) as efp:
print(f"SMTP_HOST={smtp_settings['host']}", file=efp)
print(f"SMTP_PORT={smtp_settings['port']}", file=efp)
print(f"MAIL_DOMAIN={domain}", file=efp)
Expand All @@ -44,6 +42,3 @@ with open(envfile + ".tmp", "w") as efp:
print("SMTP_AUTHTYPE=LOGIN", file=efp)
else:
print("SMTP_AUTHTYPE=PLAIN", file=efp)

# Commit changes by replacing the existing envfile:
os.replace(envfile + ".tmp", envfile)
30 changes: 27 additions & 3 deletions imageroot/bin/setup-smtp
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,44 @@
#

import agent
import json
import subprocess

def occ(args):
cmd = ['podman', 'exec', '--user', 'www-data', 'nextcloud-app', 'php', './occ']
p = subprocess.run(cmd + args, capture_output=True)
return (p.returncode, p.stdout)

def occget(args):
cmd = ['podman', 'exec', '--user', 'www-data', 'nextcloud-app', 'php', './occ']
p = subprocess.run(cmd + args, capture_output=True)
return (p.stdout.decode().rstrip())

smarthost= agent.read_envfile("smarthost.env")
smtphost= occget(["config:system:get","mail_smtphost"])
Comment thread
DavidePrincipi marked this conversation as resolved.

with open('config.json', 'r') as cf:
config = json.loads(cf.read())

# Remove mail configuration when smarthost is disabled
if 'SMTP_HOST' not in smarthost and config['internal_smarthost'] == False and smtphost:
occ(["config:system:delete","mail_from_address"])
occ(["config:system:delete","mail_smtpmode"])
occ(["config:system:delete","mail_sendmailmode"])
occ(["config:system:delete","mail_domain"])
occ(["config:system:delete","mail_smtphost"])
occ(["config:system:delete","mail_smtpauth"])
occ(["config:system:delete","mail_smtpport"])
occ(["config:system:delete","mail_smtpname"])
occ(["config:system:delete","mail_smtppassword"])
occ(["config:system:delete","mail_smtpsecure"])
occ(["config:system:delete","mail_smtpauthtype"])
occ(["config:system:delete","mail_smtpstreamoptions"])

# smarthost is configured
if 'SMTP_HOST' in smarthost:
if 'SMTP_HOST' in smarthost and config['internal_smarthost'] == False:
# verify if smarthost verify tls certificate
if smarthost.get('SMTP_SECURE') == 'none' or smarthost.get('SMTP_TLS_VERIFY') == 'False':
occ(["config:system:set","mail_smtpstreamoptions","ssl","allow_self_signed","--value=true", "--type=boolean"])
occ(["config:system:set","mail_smtpstreamoptions","ssl","verify_peer","--value=false","--type=boolean"])
occ(["config:system:set","mail_smtpstreamoptions","ssl","verify_peer_name","--value=false","--type=boolean"])
else:
occ(["config:system:delete","mail_smtpstreamoptions","ssl"])
44 changes: 44 additions & 0 deletions imageroot/update-module.d/17smarthost_switch
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env python3

#
# Copyright (C) 2026 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

import agent
import json
import subprocess
import sys

def occget(args):
cmd = ['podman', 'exec', '--user', 'www-data', 'nextcloud-app', 'php', './occ']
p = subprocess.run(cmd + args, capture_output=True)
return (p.stdout.decode().rstrip())

with open('config.json', 'r') as cf:
config = json.loads(cf.read())

# Exit if internal smarthost is already set
if "internal_smarthost" in config:
sys.exit(0)

smarthost = agent.read_envfile("smarthost.env")

# Get the smtphost via occ
smtphost = occget(["config:system:get","mail_smtphost"])

# Get the smarthost
if 'SMTP_HOST' in smarthost:
smtpsmarthost=smarthost['SMTP_HOST']
else:
smtpsmarthost=""

# Compare occ with smarthost settings and set the internal_smarthost variable accordingly
if smtphost == smtpsmarthost:
config["internal_smarthost"] = False
else:
config["internal_smarthost"] = True

# Write config.json
with open('config.json', 'w') as cfp:
cfp.write(json.dumps(config))
2 changes: 1 addition & 1 deletion nextcloud/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM docker.io/library/nextcloud:32.0.1-fpm-alpine
FROM docker.io/library/nextcloud:32.0.6-fpm-alpine

RUN set -ex; \
\
Expand Down
2 changes: 1 addition & 1 deletion notify_push/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: AGPL-3.0-or-later

FROM clux/muslrust:stable AS build
ARG NOTIFY_PUSH_VERSION="1.2.1"
ARG NOTIFY_PUSH_VERSION="1.2.2"

# Download and extract the source code
RUN apt-get update && apt-get install -y wget && \
Expand Down
2 changes: 1 addition & 1 deletion tests/nextcloud.robot
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Check if nextcloud is installed correctly
Set Suite Variable ${module_id} ${output.module_id}

Check if nextcloud can be configured
${out} ${err} ${rc} = Execute Command api-cli run module/${module_id}/configure-module --data '{"host": "nextcloud.dom.test", "lets_encrypt": false, "domain": "", "password": "Nethesis,1234"}'
${out} ${err} ${rc} = Execute Command api-cli run module/${module_id}/configure-module --data '{"host": "nextcloud.dom.test", "lets_encrypt": false, "domain": "", "password": "Nethesis,1234", "internal_smarthost": false}'
... return_rc=True return_stdout=True return_stderr=True
Should Be Equal As Integers ${rc} 0

Expand Down
3 changes: 2 additions & 1 deletion ui/public/i18n/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
"host_placeholder": "E.g. mynextcloud.example.org",
"admin_password_tooltip": "The user 'admin' is the internal administrator of Nextcloud. This password is used to authenticate the 'admin' user in the Nextcloud web interface.",
"host_pattern": "Must be a valid fully qualified domain name",
"host_format": "Must be a valid fully qualified domain name"
"host_format": "Must be a valid fully qualified domain name",
"internal_smarthost": "Manage email sending from Nextcloud admin panel"
Comment thread
DavidePrincipi marked this conversation as resolved.
},
"about": {
"title": "About"
Expand Down
17 changes: 17 additions & 0 deletions ui/src/views/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@
ref="domain"
>
</NsComboBox>
<NsToggle
value="internalSmarthost"
:label="$t('settings.internal_smarthost')"
v-model="internalSmarthost"
:disabled="loadingUi"
class="mg-bottom"
>
<template slot="text-left">{{
$t("settings.disabled")
}}</template>
<template slot="text-right">{{
$t("settings.enabled")
}}</template>
</NsToggle>
<template v-if="is_collabora && installed">
<NsComboBox
v-model.trim="collabora_host"
Expand Down Expand Up @@ -241,6 +255,7 @@ export default {
host: "",
isLetsEncryptEnabled: false,
isLetsEncryptCurrentlyEnabled: false,
internalSmarthost: false,
collabora_host: "",
domain: "",
password: "Nethesis,1234",
Expand Down Expand Up @@ -490,6 +505,7 @@ export default {
host: this.host,
lets_encrypt: this.isLetsEncryptEnabled,
domain: this.domain === "-" ? "" : this.domain,
internal_smarthost: this.internalSmarthost,
is_collabora: this.is_collabora,
collabora_host: this.collabora_host,
tls_verify_collabora: this.tls_verify_collabora,
Expand Down Expand Up @@ -521,6 +537,7 @@ export default {
this.host = config.host;
this.isLetsEncryptEnabled = config.lets_encrypt;
this.isLetsEncryptCurrentlyEnabled = config.lets_encrypt;
this.internalSmarthost = config.internal_smarthost;
this.running = config.running;
this.installed = config.installed;
this.is_collabora = config.is_collabora;
Expand Down
Loading