🍽 Fork YunoHost — snapshot mangé par la machine à tsoins
Some checks failed
Check for new n releases / updater (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

Upstream: https://github.com/YunoHost/yunohost @ 3a5f8bac8301c450897b96cbd43a4c7d3ba750fb
But (José) : transformer tout le code en bions + ploxions du xerboxion.
La carte de digestion vit au labo : /yunohost-digest.json
This commit is contained in:
machine-a-tsoins
2026-07-03 17:20:06 +00:00
commit edb4c397df
395 changed files with 105504 additions and 0 deletions

400
hooks/conf_regen/01-yunohost Executable file
View File

@@ -0,0 +1,400 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
base_folder_and_perm_init() {
#############################
# Base yunohost conf folder #
#############################
mkdir -p /etc/yunohost
# NB: x permission for 'others' is important for ssl-cert (and maybe mdns), otherwise slapd will fail to start because can't access the certs
chmod 755 /etc/yunohost
################
# Logs folders #
################
mkdir -p /var/log/yunohost
chown root:root /var/log/yunohost
chmod 750 /var/log/yunohost
##################
# Portal folders #
##################
getent passwd ynh-portal &> /dev/null || useradd --no-create-home --shell /usr/sbin/nologin --system --user-group ynh-portal
mkdir -p /etc/yunohost/portal
chmod 500 /etc/yunohost/portal
chown ynh-portal:ynh-portal /etc/yunohost/portal
mkdir -p /usr/share/yunohost/portal/customassets
chmod 775 /usr/share/yunohost/portal/customassets
chown root:root /usr/share/yunohost/portal/customassets
touch /var/log/yunohost-portalapi.log
chown ynh-portal:root /var/log/yunohost-portalapi.log
chmod 600 /var/log/yunohost-portalapi.log
###############################
# Sessions folder and secrets #
###############################
# Portal
mkdir -p /var/cache/yunohost-portal/sessions
chown ynh-portal:www-data /var/cache/yunohost-portal
chmod 510 /var/cache/yunohost-portal
chown ynh-portal:www-data /var/cache/yunohost-portal/sessions
chmod 710 /var/cache/yunohost-portal/sessions
# Webadmin
mkdir -p /var/cache/yunohost/sessions
chown root:root /var/cache/yunohost/sessions
chmod 700 /var/cache/yunohost/sessions
if test -e /etc/yunohost/installed; then
# Initialize session secrets
# Obviously we only do this in the post_regen, ie during the postinstall, because we don't want every pre-installed instance to have the same secret
if [ ! -e /etc/yunohost/.admin_cookie_secret ]; then
dd if=/dev/urandom bs=1 count=1000 2> /dev/null | tr --complement --delete 'A-Za-z0-9' | head -c 64 > /etc/yunohost/.admin_cookie_secret
fi
chown root:root /etc/yunohost/.admin_cookie_secret
chmod 400 /etc/yunohost/.admin_cookie_secret
if [ ! -e /etc/yunohost/.ssowat_cookie_secret ]; then
# NB: we need this to be exactly 32 char long, because it is later used as a key for AES256
dd if=/dev/urandom bs=1 count=1000 2> /dev/null | tr --complement --delete 'A-Za-z0-9' | head -c 32 > /etc/yunohost/.ssowat_cookie_secret
fi
chown ynh-portal:root /etc/yunohost/.ssowat_cookie_secret
chmod 400 /etc/yunohost/.ssowat_cookie_secret
fi
##################
# Domain folders #
##################
mkdir -p /etc/yunohost/domains
chown root /etc/yunohost/domains
chmod 700 /etc/yunohost/domains
###############
# App folders #
###############
mkdir -p /etc/yunohost/apps
chown root /etc/yunohost/apps
chmod 700 /etc/yunohost/apps
#####################
# Apps data folders #
#####################
mkdir -p /home/yunohost.app
chmod 755 /home/yunohost.app
################
# Certs folder #
################
mkdir -p /etc/yunohost/certs
chown -R root:ssl-cert /etc/yunohost/certs
chmod 750 /etc/yunohost/certs
# We do this with find because there could be a lot of them...
find /etc/yunohost/certs/ -type f -exec chmod 640 {} \;
find /etc/yunohost/certs/ -type d -exec chmod 750 {} \;
##################
# Backup folders #
##################
mkdir -p /home/yunohost.backup/archives
chmod 770 /home/yunohost.backup
chmod 770 /home/yunohost.backup/archives
if test -e /etc/yunohost/installed; then
# The admins group only exist after the postinstall
chown root:admins /home/yunohost.backup
chown root:admins /home/yunohost.backup/archives
else
chown root:root /home/yunohost.backup
chown root:root /home/yunohost.backup/archives
fi
########
# Misc #
########
mkdir -p /etc/yunohost/hooks.d
chown root /etc/yunohost/hooks.d
chmod 700 /etc/yunohost/hooks.d
mkdir -p /var/cache/yunohost/repo
chown root:root /var/cache/yunohost
chmod 700 /var/cache/yunohost
[ ! -e /var/www/.well-known/ynh-diagnosis/ ] || chmod 775 /var/www/.well-known/ynh-diagnosis/
if test -e /etc/yunohost/installed; then
# We use "|| true" because some filesystem do not support ACL (such as NTFS ... for example when incus storage is on an NTFS drive in dir storage)
setfacl -m g:all_users:--- /var/www || true
setfacl -m g:all_users:--- /var/log/nginx || true
setfacl -m g:all_users:--- /etc/yunohost || true
setfacl -m g:all_users:--- /etc/ssowat || true
fi
}
do_init_regen() {
cd /usr/share/yunohost/conf/yunohost
base_folder_and_perm_init
# Empty ssowat json persistent conf
echo "{}" > '/etc/ssowat/conf.json.persistent'
chmod 644 /etc/ssowat/conf.json.persistent
chown root:root /etc/ssowat/conf.json.persistent
echo "{}" > '/etc/ssowat/conf.json'
chmod 644 /etc/ssowat/conf.json
chown root:root /etc/ssowat/conf.json
# Empty service conf
touch /etc/yunohost/services.yml
# set default current_host
[[ -f /etc/yunohost/current_host ]] \
|| echo "yunohost.org" > /etc/yunohost/current_host
# copy default services and firewall
[[ -f /etc/yunohost/firewall.yml ]] \
|| cp firewall.yml /etc/yunohost/firewall.yml
# allow users to access /media directory
[[ -d /etc/skel/media ]] \
|| (mkdir -p /media && ln -s /media /etc/skel/media)
# YunoHost services
cp yunohost-api.service /etc/systemd/system/yunohost-api.service
cp yunohost-portal-api.service /etc/systemd/system/yunohost-portal-api.service
cp yunoprompt.service /etc/systemd/system/yunoprompt.service
systemctl daemon-reload
systemctl enable yunohost-api.service --quiet
systemctl start yunohost-api.service
systemctl enable yunohost-portal-api.service --quiet
systemctl start yunohost-portal-api.service
# Enable yunoprompt (in particular for installs from ISO where we want this to show on first boot instead of asking for a login/password)
systemctl enable yunoprompt --quiet
# Yunohost-firewall is enabled only during postinstall, not init, not 100% sure why
cp dpkg-origins /etc/dpkg/origins/yunohost
# Change dpkg vendor
# see https://wiki.debian.org/Derivatives/Guidelines#Vendor
if readlink -f /etc/dpkg/origins/default | grep -q debian; then
rm -f /etc/dpkg/origins/default
ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default
fi
}
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/yunohost
mkdir -p "$pending_dir/etc/systemd/system"
mkdir -p "$pending_dir/etc/cron.d/"
mkdir -p "$pending_dir/etc/cron.daily/"
# add cron job for diagnosis to be ran at 7h and 19h + a random delay between
# 0 and 20min, meant to avoid every instances running their diagnosis at
# exactly the same time, which may overload the diagnosis server.
cat > "$pending_dir/etc/cron.d/yunohost-diagnosis" << EOF
SHELL=/bin/bash
0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably"
EOF
# Cron job that upgrade the app list everyday
cat > "$pending_dir/etc/cron.daily/yunohost-fetch-apps-catalog" << EOF
#!/bin/bash
sleep \$((RANDOM%3600)); yunohost tools update apps > /dev/null
EOF
# Cron job that renew lets encrypt certificates if there's any that needs renewal
cat > "$pending_dir/etc/cron.daily/yunohost-certificate-renew" << EOF
#!/bin/bash
yunohost domain cert renew --email
EOF
# If we subscribed to a dyndns domain, add the corresponding cron
# - delay between 0 and 60 secs to spread the check over a 1 min window
# - do not run the command if some process already has the lock, to avoid queuing hundreds of commands...
if ls -l /etc/yunohost/dyndns/K*.key 2> /dev/null; then
cat > "$pending_dir/etc/cron.d/yunohost-dyndns" << EOF
SHELL=/bin/bash
# Every 10 minutes,
# - (sleep random 60 is here to spread requests over a 1-min window)
# - if ipv4/6.yunohost.org answers ping (basic check to validate that we're connected to the internet and yunohost infra aint down)
# - and if lock ain't already taken by another command
# - trigger yunohost dyndns update
*/10 * * * * root : YunoHost DynDNS update; sleep \$((RANDOM\\%60)); ! ping -q -W5 -c1 ipv4.yunohost.org >/dev/null 2>&1 || test -e /var/run/moulinette_yunohost.lock || yunohost dyndns update >> /dev/null
EOF
else
# (Delete cron if no dyndns domain found)
touch "$pending_dir/etc/cron.d/yunohost-dyndns"
fi
# Skip ntp if inside a container (inspired from the conf of systemd-timesyncd)
if systemctl | grep -q 'ntp.service'; then
mkdir -p "$pending_dir/etc/systemd/system/ntp.service.d/"
cat > "$pending_dir/etc/systemd/system/ntp.service.d/ynh-override.conf" << EOF
[Unit]
ConditionCapability=CAP_SYS_TIME
ConditionVirtualization=!container
EOF
fi
mkdir -p "$pending_dir/etc/systemd/system/nftables.service.d/"
cp yunohost-nftables-hooks-override.conf "$pending_dir/etc/systemd/system/nftables.service.d/yunohost-nftables-hooks.conf"
# Delete legacy conflict between yunohost and nftables
touch "$pending_dir/etc/systemd/system/nftables.service.d/ynh-override.conf"
# Don't suspend computer on LidSwitch
mkdir -p "$pending_dir/etc/systemd/logind.conf.d/"
cat > "$pending_dir/etc/systemd/logind.conf.d/ynh-override.conf" << EOF
[Login]
HandleLidSwitch=ignore
HandleLidSwitchDocked=ignore
HandleLidSwitchExternalPower=ignore
EOF
cp yunohost-api.service "$pending_dir/etc/systemd/system/yunohost-api.service"
cp yunohost-portal-api.service "$pending_dir/etc/systemd/system/yunohost-portal-api.service"
cp yunoprompt.service "$pending_dir/etc/systemd/system/yunoprompt.service"
cp proc-hidepid.service "$pending_dir/etc/systemd/system/proc-hidepid.service"
# Delete legacy yunohost-firewall service
touch "$pending_dir/etc/systemd/system/yunohost-firewall.service"
mkdir -p "$pending_dir/etc/dpkg/origins/"
cp dpkg-origins "$pending_dir/etc/dpkg/origins/yunohost"
# Remove legacy hackish/clumsy nodejs autoupdate which ends up filling up space with ambiguous upgrades >_>
touch "$pending_dir/etc/cron.daily/node_update"
}
do_post_regen() {
regen_conf_files=$1
# Re-mkdir / apply permission to all basic folders etc
base_folder_and_perm_init
# Legacy log tree structure
if [ ! -e /var/log/yunohost/operations ]; then
mkdir -p /var/log/yunohost/operations
fi
if [ -d /var/log/yunohost/categories/operation ] && [ ! -L /var/log/yunohost/categories/operation ]; then
# (we use find -type f instead of mv /folder/* to make sure to also move hidden files which are not included in globs by default)
find /var/log/yunohost/categories/operation/ -type f -print0 | xargs -0 -I {} mv {} /var/log/yunohost/operations/
# Attempt to delete the old dir (because we want it to be a symlink) or just rename it if it can't be removed (not empty) for some reason
rmdir /var/log/yunohost/categories/operation || mv /var/log/yunohost/categories/operation /var/log/yunohost/categories/operation.old
ln -s /var/log/yunohost/operations /var/log/yunohost/categories/operation
fi
# Make sure conf files why may be created by apps are owned and writable only by root
find /etc/systemd/system/*.service -type f | xargs -r chown root:root
find /etc/systemd/system/*.service -type f | xargs -r chmod 0644
if ls -l /etc/php/*/fpm/pool.d/*.conf 2> /dev/null; then
chown root:root /etc/php/*/fpm/pool.d/*.conf
chmod 644 /etc/php/*/fpm/pool.d/*.conf
fi
find /etc/cron.*/yunohost-* -type f -exec chmod 755 {} \;
find /etc/cron.d/yunohost-* -type f -exec chmod 644 {} \;
find /etc/cron.*/yunohost-* -type f -exec chown root:root {} \;
for USER in $(yunohost user list --quiet --output-as json | jq -r '.users | .[] | .username'); do
[ ! -e "/home/$USER" ] || setfacl -m g:all_users:--- "/home/$USER"
done
# Misc configuration / state files
for file in /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql}; do
if [ -f "$file" ]; then
if [ "$file" != "mdns.yml" ]; then
chown root:root "$file"
fi
chmod 600 "$file"
fi
done
# Create ssh.app and sftp.app groups if they don't exist yet
grep -q '^ssh.app:' /etc/group || groupadd ssh.app
grep -q '^sftp.app:' /etc/group || groupadd sftp.app
# Propagates changes in systemd service config overrides
if systemctl | grep -q 'ntp.service'; then
[[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || {
systemctl daemon-reload
systemctl restart ntp
}
fi
[[ ! "$regen_conf_files" =~ "login.conf.d/ynh-override.conf" ]] || {
systemctl daemon-reload
systemctl restart systemd-logind
}
[[ ! "$regen_conf_files" =~ "yunohost-api.service" ]] || systemctl daemon-reload
[[ ! "$regen_conf_files" =~ "yunohost-portal-api.service" ]] || systemctl daemon-reload
[[ ! "$regen_conf_files" =~ "nftables.service.d/yunohost-nftables-hooks.conf" ]] || systemctl daemon-reload
if [[ "$regen_conf_files" =~ "yunoprompt.service" ]]; then
systemctl daemon-reload
action=$([[ -e /etc/systemd/system/yunoprompt.service ]] && echo 'enable' || echo 'disable')
systemctl "$action" yunoprompt --quiet --now
fi
if [[ "$regen_conf_files" =~ "proc-hidepid.service" ]]; then
systemctl daemon-reload
action=$([[ -e /etc/systemd/system/proc-hidepid.service ]] && echo 'enable' || echo 'disable')
systemctl "$action" proc-hidepid --quiet --now
fi
systemctl enable yunohost-portal-api.service --quiet
systemctl is-active yunohost-portal-api --quiet || systemctl start yunohost-portal-api.service
# Change dpkg vendor
# see https://wiki.debian.org/Derivatives/Guidelines#Vendor
if readlink -f /etc/dpkg/origins/default | grep -q debian; then
rm -f /etc/dpkg/origins/default
ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default
fi
if test -e /etc/yunohost/installed && test -e /etc/profile.d/check_yunohost_is_installed.sh; then
rm /etc/profile.d/check_yunohost_is_installed.sh
fi
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

149
hooks/conf_regen/02-ssl Executable file
View File

@@ -0,0 +1,149 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
ssl_dir="/usr/share/yunohost/ssl"
template_dir="/usr/share/yunohost/conf/ssl"
ynh_ca="/etc/yunohost/certs/yunohost.org/ca.pem"
ynh_crt="/etc/yunohost/certs/yunohost.org/crt.pem"
ynh_key="/etc/yunohost/certs/yunohost.org/key.pem"
regen_local_ca() {
domain="$1"
echo -e "\n# Creating local certification authority with domain=$domain\n"
# create certs and SSL directories
mkdir -p "/etc/yunohost/certs/yunohost.org"
mkdir -p "${ssl_dir}/"{ca,certs,crl,newcerts}
pushd ${ssl_dir}
# (Update the serial so that it's specific to this very instance)
# N.B. : the weird RANDFILE thing comes from:
# https://stackoverflow.com/questions/94445/using-openssl-what-does-unable-to-write-random-state-mean
RANDFILE=.rnd openssl rand -hex 19 > serial
rm -f index.txt
touch index.txt
cp ${template_dir}/openssl.cnf openssl.ca.cnf
sed -i "s/yunohost.org/${domain}/g" openssl.ca.cnf
openssl req -x509 \
-new \
-config openssl.ca.cnf \
-days 3650 \
-out ca/cacert.pem \
-keyout ca/cakey.pem \
-nodes \
-batch \
-subj "/CN=${domain}/O=${domain%.*}" 2>&1
chmod 640 ca/cacert.pem
chmod 640 ca/cakey.pem
cp ca/cacert.pem $ynh_ca
ln -sf "$ynh_ca" /etc/ssl/certs/ca-yunohost_crt.pem
update-ca-certificates
popd
}
do_init_regen() {
LOGFILE=/tmp/yunohost-ssl-init
touch "$LOGFILE"
chown root:root "$LOGFILE"
chmod 640 "$LOGFILE"
# Make sure this conf exists
mkdir -p ${ssl_dir}/{ca,certs,crl,newcerts}
install -D -m 644 ${template_dir}/openssl.cnf "${ssl_dir}/openssl.cnf"
# create default certificates
if [[ ! -f "$ynh_ca" ]]; then
regen_local_ca yunohost.org >> "$LOGFILE"
fi
if [[ ! -f "$ynh_crt" ]]; then
echo -e "\n# Creating initial key and certificate \n" >> "$LOGFILE"
openssl req -new \
-config "${ssl_dir}/openssl.cnf" \
-out "${ssl_dir}/certs/yunohost_csr.pem" \
-keyout "${ssl_dir}/certs/yunohost_key.pem" \
-nodes -batch &>> $LOGFILE
openssl ca \
-config "${ssl_dir}/openssl.cnf" \
-days 730 \
-in "${ssl_dir}/certs/yunohost_csr.pem" \
-out "${ssl_dir}/certs/yunohost_crt.pem" \
-batch &>> $LOGFILE
chmod 640 "${ssl_dir}/certs/yunohost_key.pem"
chmod 640 "${ssl_dir}/certs/yunohost_crt.pem"
cp "${ssl_dir}/certs/yunohost_key.pem" "$ynh_key"
cp "${ssl_dir}/certs/yunohost_crt.pem" "$ynh_crt"
ln -sf "$ynh_crt" /etc/ssl/certs/yunohost_crt.pem
ln -sf "$ynh_key" /etc/ssl/private/yunohost_key.pem
fi
chown -R root:ssl-cert /etc/yunohost/certs/yunohost.org/
chmod o-rwx /etc/yunohost/certs/yunohost.org/
}
do_pre_regen() {
pending_dir=$1
install -D -m 644 $template_dir/openssl.cnf "${pending_dir}/${ssl_dir}/openssl.cnf"
}
do_post_regen() {
current_local_ca_domain=$(openssl x509 -in $ynh_ca -text | tr ',' '\n' | grep Issuer | awk '{print $4}')
main_domain=$(cat /etc/yunohost/current_host)
# Automigrate legacy folder
if [ -e /usr/share/yunohost/yunohost-config/ssl/yunoCA ]; then
mv /usr/share/yunohost/yunohost-config/ssl/yunoCA/* ${ssl_dir}
rm -rf /usr/share/yunohost/yunohost-config
# Overwrite openssl.cnf because it may still contain references to the old yunoCA dir
install -D -m 644 ${template_dir}/openssl.cnf "${ssl_dir}/openssl.cnf"
install -D -m 644 ${template_dir}/openssl.cnf "${ssl_dir}/openssl.ca.cnf"
sed -i "s/yunohost.org/${main_domain}/g" openssl.ca.cnf
fi
mkdir -p ${ssl_dir}/{ca,certs,crl,newcerts}
chown root:root ${ssl_dir}
chmod 750 ${ssl_dir}
chmod -R o-rwx ${ssl_dir}
chmod o+x ${ssl_dir}/certs
chmod o+r ${ssl_dir}/certs/yunohost_crt.pem
if [[ "$current_local_ca_domain" != "$main_domain" ]]; then
regen_local_ca "$main_domain"
# Idk how useful this is, but this was in the previous python code (domain.main_domain())
ln -sf "/etc/yunohost/certs/$main_domain/crt.pem" /etc/ssl/certs/yunohost_crt.pem
ln -sf "/etc/yunohost/certs/$main_domain/key.pem" /etc/ssl/private/yunohost_key.pem
fi
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

59
hooks/conf_regen/03-ssh Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
set -e
# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/ssh
# Support different strategy for security configurations
export compatibility="$(jq -r '.ssh_compatibility' <<< "$YNH_SETTINGS")"
export port="$(jq -r '.ssh_port' <<< "$YNH_SETTINGS")"
export password_authentication="$(jq -r '.ssh_password_authentication' <<< "$YNH_SETTINGS" | int_to_bool)"
export ssh_keys=$(ls /etc/ssh/ssh_host_{ed25519,rsa,ecdsa}_key 2> /dev/null || true)
# do not listen to IPv6 if unavailable
[[ -f /proc/net/if_inet6 ]] && ipv6_enabled=true || ipv6_enabled=false
export ipv6_enabled
ynh_render_template "sshd_config" "${pending_dir}/etc/ssh/sshd_config"
}
do_post_regen() {
regen_conf_files=$1
# If no file changed, there's nothing to do
[[ -n "$regen_conf_files" ]] || return 0
# Enforce permissions for /etc/ssh/sshd_config
chown root:root "/etc/ssh/sshd_config"
chmod 644 "/etc/ssh/sshd_config"
systemctl restart ssh
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

199
hooks/conf_regen/06-slapd Executable file
View File

@@ -0,0 +1,199 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
tmp_backup_dir_file="/root/slapd-backup-dir.txt"
config="/usr/share/yunohost/conf/slapd/config.ldif"
db_init="/usr/share/yunohost/conf/slapd/db_init.ldif"
do_init_regen() {
do_pre_regen ""
# Drop current existing slapd data
rm -rf /var/backups/*.ldapdb
rm -rf /var/backups/slapd-*
debconf-set-selections << EOF
slapd slapd/password1 password yunohost
slapd slapd/password2 password yunohost
slapd slapd/domain string yunohost.org
slapd shared/organization string yunohost.org
slapd slapd/allow_ldap_v2 boolean false
slapd slapd/invalid_config boolean true
slapd slapd/backend select MDB
slapd slapd/move_old_database boolean true
slapd slapd/no_configuration boolean false
slapd slapd/purge_database boolean false
EOF
DEBIAN_FRONTEND=noninteractive dpkg-reconfigure slapd -u
# Enforce permissions
chown -R openldap:openldap /etc/ldap/schema/
usermod -aG ssl-cert openldap
# (Re-)init data according to default ldap entries
echo ' Initializing LDAP with YunoHost DB structure'
rm -rf /etc/ldap/slapd.d
mkdir -p /etc/ldap/slapd.d
slapadd -F /etc/ldap/slapd.d -b cn=config -l "$config" 2>&1 \
| grep -v "none elapsed\|Closing DB" || true
chown -R openldap: /etc/ldap/slapd.d
rm -rf /var/lib/ldap
mkdir -p /var/lib/ldap
slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org -l "$db_init" 2>&1 \
| grep -v "none elapsed\|Closing DB" || true
chown -R openldap: /var/lib/ldap
nscd -i group || true
nscd -i passwd || true
systemctl restart slapd
}
_regenerate_slapd_conf() {
# Validate the new slapd config
# To do so, we have to use the .ldif to generate the config directory
# so we use a temporary directory slapd_new.d
rm -Rf /etc/ldap/slapd_new.d
mkdir /etc/ldap/slapd_new.d
slapadd -b cn=config -l "$config" -F /etc/ldap/slapd_new.d/ 2>&1 \
| grep -v "none elapsed\|Closing DB" || true
# Actual validation (-Q is for quiet, -u is for dry-run)
slaptest -Q -u -F /etc/ldap/slapd_new.d
# "Commit" / apply the new config (meaning we delete the old one and replace
# it with the new one)
rm -Rf /etc/ldap/slapd.d
mv /etc/ldap/slapd_new.d /etc/ldap/slapd.d
chown -R openldap:openldap /etc/ldap/slapd.d/
}
do_pre_regen() {
pending_dir=$1
# remove temporary backup file
rm -f "$tmp_backup_dir_file"
# Define if we need to migrate from hdb to mdb
if [ -e /etc/ldap/slapd.conf ]; then
curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2> /dev/null | awk '{print $2}')
if [ "$curr_backend" != 'mdb' ] && [ -n "$curr_backend" ]; then
backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)"
mkdir -p "$backup_dir"
slapcat -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif"
echo "$backup_dir" > "$tmp_backup_dir_file"
fi
fi
# create needed directories
ldap_dir="${pending_dir}/etc/ldap"
schema_dir="${ldap_dir}/schema"
mkdir -p "$ldap_dir" "$schema_dir"
cd /usr/share/yunohost/conf/slapd
# copy configuration files
cp -a ldap.conf "$ldap_dir"
cp -a sudo.ldif mailserver.ldif permission.ldif "$schema_dir"
mkdir -p "$pending_dir/etc/systemd/system/slapd.service.d/"
cp systemd-override.conf "$pending_dir/etc/systemd/system/slapd.service.d/ynh-override.conf"
install -D -m 644 slapd.default "${pending_dir}/etc/default/slapd"
}
do_post_regen() {
regen_conf_files=$1
# fix some permissions
echo "Enforce permissions on ldap/slapd directories and certs ..."
# penldap user should be in the ssl-cert group to let it access the certificate for TLS
usermod -aG ssl-cert openldap
chown -R openldap:openldap /etc/ldap/schema/
chown -R openldap:openldap /etc/ldap/slapd.d/
# Fix weird scenarios where /etc/sudo-ldap.conf doesn't exists (yet is supposed to be
# created by the sudo-ldap package) : https://github.com/YunoHost/issues/issues/2091
if [ ! -e /etc/sudo-ldap.conf ]; then
ln -s /etc/ldap/ldap.conf /etc/sudo-ldap.conf
fi
# If we changed the systemd ynh-override conf
if echo "$regen_conf_files" | sed 's/,/\n/g' | grep -q "^/etc/systemd/system/slapd.service.d/ynh-override.conf$"; then
systemctl daemon-reload
systemctl restart slapd
sleep 3
fi
# For some reason, old setups don't have the admins group defined...
if ! slapcat -H "ldap:///cn=admins,ou=groups,dc=yunohost,dc=org" | grep -q 'cn=admins,ou=groups,dc=yunohost,dc=org'; then
slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org <<< \
"dn: cn=admins,ou=groups,dc=yunohost,dc=org
cn: admins
gidNumber: 4001
memberUid: admin
objectClass: posixGroup
objectClass: top"
chown -R openldap: /var/lib/ldap
systemctl restart slapd
nscd -i group
fi
if [ -z "$regen_conf_files" ] && [ "$FORCE" == "false" ]; then
exit 0
fi
# regenerate LDAP config directory from slapd.conf
echo "Regenerate LDAP config directory from config.ldif"
_regenerate_slapd_conf
# If there's a backup, re-import its data
if [ -f "$tmp_backup_dir_file" ]; then
backup_dir=$(cat "$tmp_backup_dir_file")
if [[ -n "$backup_dir" && -f "${backup_dir}/dc=yunohost-dc=org.ldif" ]]; then
# regenerate LDAP config directory and import database as root
echo "Import the database using slapadd"
slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif"
chown -R openldap:openldap /var/lib/ldap 2>&1
fi
fi
echo "Running slapdindex"
su openldap -s "/bin/bash" -c "/usr/sbin/slapindex"
echo "Reloading slapd"
systemctl force-reload slapd
}
if [[ "$1" == _regenerate_slapd_conf ]]; then
_regenerate_slapd_conf
else
"do_$1_regen" "$(echo "${*:2}" | xargs)"
fi

44
hooks/conf_regen/09-nslcd Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
do_init_regen() {
do_pre_regen ""
systemctl restart nslcd
}
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/nslcd
install -D -m 644 nslcd.conf "${pending_dir}/etc/nslcd.conf"
}
do_post_regen() {
regen_conf_files=$1
[[ -z "$regen_conf_files" ]] \
|| systemctl restart nslcd
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

116
hooks/conf_regen/10-apt Executable file
View File

@@ -0,0 +1,116 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
readonly YNH_DEFAULT_PHP_VERSION=8.2
do_pre_regen() {
pending_dir=$1
mkdir --parents "${pending_dir}/etc/apt/preferences.d"
# Add sury
mkdir -p "$pending_dir/etc/apt/sources.list.d/"
echo "deb [signed-by=/etc/apt/trusted.gpg.d/extra_php_version.gpg] https://packages.sury.org/php/ $(lsb_release --codename --short) main" > "${pending_dir}/etc/apt/sources.list.d/extra_php_version.list"
# Ban some packages from sury
echo "
Package: php-common
Pin: origin \"packages.sury.org\"
Pin-Priority: 500" >> "${pending_dir}/etc/apt/preferences.d/extra_php_version"
packages_to_refuse_from_sury="php php-* openssl libssl1.1 libssl-dev"
for package in $packages_to_refuse_from_sury; do
echo "
Package: $package
Pin: origin \"packages.sury.org\"
Pin-Priority: -1" >> "${pending_dir}/etc/apt/preferences.d/extra_php_version"
done
# Add yarn
echo "deb [signed-by=/etc/apt/trusted.gpg.d/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > "${pending_dir}/etc/apt/sources.list.d/yarn.list"
# Ban everything from Yarn except Yarn
echo "
Package: *
Pin: origin \"dl.yarnpkg.com\"
Pin-Priority: -1
Package: yarn
Pin: origin \"dl.yarnpkg.com\"
Pin-Priority: 500" >> "${pending_dir}/etc/apt/preferences.d/yarn"
# Ban apache2, bind9
echo "
# PLEASE READ THIS WARNING AND DON'T EDIT THIS FILE
# You are probably reading this file because you tried to install apache2 or
# bind9. These 2 packages conflict with YunoHost.
# Installing apache2 will break nginx and break the entire YunoHost ecosystem
# on your server, therefore don't remove those lines!
# You have been warned.
Package: apache2
Pin: release *
Pin-Priority: -1
Package: apache2-bin
Pin: release *
Pin-Priority: -1
# Also bind9 will conflict with dnsmasq.
# Same story as for apache2.
# Don't install it, don't remove those lines.
Package: bind9
Pin: release *
Pin-Priority: -1
" >> "${pending_dir}/etc/apt/preferences.d/ban_packages"
}
do_post_regen() {
# Purge expired keys (such as sury 95BD4743)
EXPIRED_KEYS="$(LC_ALL='en_US.UTF-8' apt-key list 2> /dev/null | grep -A1 'expired:' | grep -v 'expired\|^-' | sed 's/\s//g' || true)"
for KEY in $EXPIRED_KEYS; do apt-key del "$KEY" 2> /dev/null; done
# Add sury key
# We do this only at the post regen and if the key doesn't already exists, because we don't want the regenconf to fuck everything up if the regenconf runs while the network is down
if [[ ! -s /etc/apt/trusted.gpg.d/extra_php_version.gpg ]]; then
wget --timeout 900 --quiet "https://packages.sury.org/php/apt.gpg" --output-document=- | gpg --dearmor > "/etc/apt/trusted.gpg.d/extra_php_version.gpg"
fi
# Similar to Sury
if [[ ! -s /etc/apt/trusted.gpg.d/yarn.gpg ]]; then
wget --timeout 900 --quiet "https://dl.yarnpkg.com/debian/pubkey.gpg" --output-document=- | gpg --dearmor > "/etc/apt/trusted.gpg.d/yarn.gpg"
fi
# Make sure php7.4 is the default version when using php in cli
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
fi
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

209
hooks/conf_regen/15-nginx Executable file
View File

@@ -0,0 +1,209 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -e
# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers
do_base_regen() {
pending_dir=$1
nginx_dir="${pending_dir}/etc/nginx"
nginx_conf_dir="${nginx_dir}/conf.d"
mkdir -p "$nginx_conf_dir"
# install plain conf files
cp acme-challenge.conf.inc "$nginx_conf_dir"
cp global.conf "$nginx_conf_dir"
cp ssowat.conf "$nginx_conf_dir"
cp yunohost_http_errors.conf.inc "$nginx_conf_dir"
cp yunohost_sso.conf.inc "$nginx_conf_dir"
cp proxy_params_with_auth "$nginx_dir"
cp proxy_params_no_auth "$nginx_dir"
cp fastcgi_params_with_auth "$nginx_dir"
cp fastcgi_params_no_auth "$nginx_dir"
ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc"
ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf"
ynh_render_template "yunohost_admin.conf.inc" "${nginx_conf_dir}/yunohost_admin.conf.inc"
ynh_render_template "yunohost_api.conf.inc" "${nginx_conf_dir}/yunohost_api.conf.inc"
mkdir -p "$nginx_conf_dir/default.d/"
cp "redirect_to_admin.conf" "$nginx_conf_dir/default.d/"
}
do_init_regen() {
cd /usr/share/yunohost/conf/nginx
export compatibility="intermediate"
do_base_regen ""
# probably run with init: just disable default site, restart NGINX and exit
rm -f "${nginx_dir}/sites-enabled/default"
# Restart nginx if conf looks good, otherwise display error and exit unhappy
nginx -t 2> /dev/null || {
nginx -t
exit 1
}
systemctl restart nginx || {
journalctl --no-pager --lines=10 -u nginx >&2
exit 1
}
exit 0
}
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/nginx
nginx_dir="${pending_dir}/etc/nginx"
nginx_conf_dir="${nginx_dir}/conf.d"
mkdir -p "$nginx_conf_dir"
export webadmin_allowlist_enabled="$(jq -r '.webadmin_allowlist_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
if [ "$webadmin_allowlist_enabled" == "True" ]; then
export webadmin_allowlist="$(jq -r '.webadmin_allowlist' <<< "$YNH_SETTINGS" | sed 's/^null$//g')"
fi
# Support different strategy for security configurations
export redirect_to_https="$(jq -r '.nginx_redirect_to_https' <<< "$YNH_SETTINGS" | int_to_bool)"
export compatibility="$(jq -r '.nginx_compatibility' <<< "$YNH_SETTINGS" | int_to_bool)"
export experimental="$(jq -r '.security_experimental_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
export tls_passthrough_enabled="$(jq -r '.tls_passthrough_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
export tls_passthrough_list="$(jq -r '.tls_passthrough_list' <<< "$YNH_SETTINGS" | int_to_bool)"
do_base_regen "${pending_dir}"
local tls_passthrough_module="${pending_dir}/etc/nginx/modules-enabled/tls_passthrough.conf"
mkdir -p "${pending_dir}/etc/nginx/modules-enabled/"
if [[ "$tls_passthrough_enabled" == "True" ]]; then
ynh_render_template "tls_passthrough.conf" "${tls_passthrough_module}"
for tls_passthrough_domain_and_ip in ${tls_passthrough_list//,/ }; do
export tls_passthrough_domain=$(echo "$tls_passthrough_domain_and_ip" | awk -F';' '{print $1}')
export tls_passthrough_ip=$(echo "$tls_passthrough_domain_and_ip" | awk -F';' '{print $2}')
export tls_passthrough_port=$(echo "$tls_passthrough_domain_and_ip" | awk -F';' '{print $3}')
ynh_render_template "tls_passthrough_server.conf" "${nginx_conf_dir}/${tls_passthrough_domain}.forward80.conf"
done
else
touch "${tls_passthrough_module}"
fi
# "Touch" every known .conf file for every domain,
# meaning it should be removed by the regen conf
# - For real 'existing' domains, this file will be overwritten with an actual conf right after using ynh_render_template
# - For old domains, this will tell the regen conf that it is "to be deleted"
ls -1 /etc/nginx/conf.d \
| awk '/^[^\.]+\.[^\.]+.*\.conf$/ { print $1 }' \
| xargs --replace={} touch "${nginx_conf_dir}/{}"
# add domain conf files
cert_status=$(yunohost domain cert status --json)
for domain in $YNH_DOMAINS; do
domain_conf_dir="${nginx_conf_dir}/${domain}.d"
mkdir -p "$domain_conf_dir"
mail_autoconfig_dir="${pending_dir}/var/www/.well-known/${domain}/autoconfig/mail/"
mkdir -p "$mail_autoconfig_dir"
# NGINX server configuration
export domain
export domain_cert_ca=$(echo "$cert_status" \
| jq ".certificates.\"$domain\".CA_type" \
| tr -d '"')
if tr ' ' '\n' <<< "$YNH_DOMAINS_WITH_MAIL_IN_AND_OUT" | grep -q "^$domain$"; then
export mail_enabled="True"
else
export mail_enabled="False"
fi
ynh_render_template "server.tpl.conf" "${nginx_conf_dir}/${domain}.conf"
if [ $mail_enabled == "True" ]; then
ynh_render_template "autoconfig.tpl.xml" "${mail_autoconfig_dir}/config-v1.1.xml"
fi
touch "${domain_conf_dir}/yunohost_local.conf" # Clean legacy conf files
done
# Legacy file to remove, but we can't really remove it because it may be included by app confs...
echo "# The old yunohost panel/tile/button doesn't exists anymore" > "$nginx_conf_dir"/yunohost_panel.conf.inc
# remove old mail-autoconfig files
autoconfig_files=$(ls -1 /var/www/.well-known/*/autoconfig/mail/config-v1.1.xml 2> /dev/null || true)
for file in $autoconfig_files; do
domain=$(basename "$(readlink -f "$(dirname "$file")/../..")")
[[ $YNH_DOMAINS =~ $domain ]] \
|| (mkdir -p "$(dirname "${pending_dir}/${file}")" && touch "${pending_dir}/${file}")
done
# disable default site
mkdir -p "${nginx_dir}/sites-enabled"
touch "${nginx_dir}/sites-enabled/default"
}
do_post_regen() {
regen_conf_files=$1
# Make sure fastcgi / PHP uses the YNH_USER auth header instead of $remote_user from the Authorization header
# shellcheck disable=SC2016
sed -i 's/$remote_user;/$http_ynh_user if_not_empty;/g' /etc/nginx/fastcgi_params
# Hotfix CVE-2026-42945
# shellcheck disable=SC2016
if ! grep -qE 'fastcgi_param\s+HTTP_HOST\s+\$host;' /etc/nginx/fastcgi_params 2> /dev/null; then
# shellcheck disable=SC2016
echo 'fastcgi_param HTTP_HOST $host;' >> /etc/nginx/fastcgi_params
fi
if ls -l /etc/nginx/conf.d/*.d/*.conf; then
chown root:root /etc/nginx/conf.d/*.d/*.conf
chmod 644 /etc/nginx/conf.d/*.d/*.conf
fi
[ -z "$regen_conf_files" ] && exit 0
# create NGINX conf directories for domains
for domain in $YNH_DOMAINS; do
mkdir -p "/etc/nginx/conf.d/${domain}.d"
done
if ! nginx -t 2> /dev/null; then
# Print issues to console and exit
nginx -t
exit 1
fi
# Only reload nginx if it's already running
if pgrep nginx; then
if ! systemctl reload nginx; then
journalctl --no-pager --lines=10 -u nginx >&2
exit 1
fi
fi
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

140
hooks/conf_regen/19-postfix Executable file
View File

@@ -0,0 +1,140 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -e
# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/postfix
postfix_dir="${pending_dir}/etc/postfix"
mkdir -p "$postfix_dir"
default_dir="${pending_dir}/etc/default/"
mkdir -p "$default_dir"
# install plain conf files
cp plain/* "$postfix_dir"
# prepare main.cf conf file
main_domain=$(cat /etc/yunohost/current_host)
# Support different strategy for security configurations
export compatibility="$(jq -r '.postfix_compatibility' <<< "$YNH_SETTINGS")"
# Add possibility to specify a relay
# Could be useful with some isp with no 25 port open or more complex setup
export relay_port=""
export relay_user=""
export relay_host=""
export relay_enabled="$(jq -r '.smtp_relay_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
if [ "${relay_enabled}" == "True" ]; then
relay_host="$(jq -r '.smtp_relay_host' <<< "$YNH_SETTINGS")"
relay_port="$(jq -r '.smtp_relay_port' <<< "$YNH_SETTINGS")"
relay_user="$(jq -r '.smtp_relay_user' <<< "$YNH_SETTINGS")"
relay_password="$(jq -r '.smtp_relay_password' <<< "$YNH_SETTINGS")"
# Avoid to display "Relay account paswword" to other users
touch "${postfix_dir}/sasl_passwd"
chmod 750 "${postfix_dir}/sasl_passwd"
# Avoid "postmap: warning: removing zero-length database file"
chown postfix "${pending_dir}/etc/postfix"
chown postfix "${pending_dir}/etc/postfix/sasl_passwd"
cat <<< "[${relay_host}]:${relay_port} ${relay_user}:${relay_password}" > "${postfix_dir}/sasl_passwd"
fi
export enable_blocklists="$(jq -r '.enable_blocklists' <<< "$YNH_SETTINGS" | int_to_bool)"
# Use this postfix server as a backup MX
export backup_mx_domains="$(jq -r '.smtp_backup_mx_domains' <<< "$YNH_SETTINGS" | sed 's/^null$//g' | sed "s/,/ /g")"
export backup_mx_emails="$(jq -r '.smtp_backup_mx_emails_whitelisted' <<< "$YNH_SETTINGS" | sed "s/,/ /g")"
rm -f "${postfix_dir}/relay_recipients"
touch "${postfix_dir}/relay_recipients"
rm -f "${postfix_dir}/relay_recipients.db"
touch "${postfix_dir}/relay_recipients.db"
if [ -n "${backup_mx_domains}" ] && [ -n "${backup_mx_emails}" ]; then
for mail in ${backup_mx_emails}; do
echo "$mail OK" >> "${postfix_dir}/relay_recipients"
done
postmap "${postfix_dir}/relay_recipients"
fi
export main_domain
export domain_list="$YNH_DOMAINS_WITH_MAIL_IN_AND_OUT"
ynh_render_template "main.cf" "${postfix_dir}/main.cf"
ynh_render_template "sni" "${postfix_dir}/sni"
# Activate mailbox only on domains with mail_in features
# If mail_in is disabled for a domain, this allows to send
# mails on external mailbox using this domain
# See: https://forum.yunohost.org/t/how-to-keep-your-mailbox-outside-yunohost/4860
echo "# This file is regenerated automatically" > "${postfix_dir}/virtual-mailbox-domains"
echo "# Please DO NOT edit manually ... changes will be overwritten!" >> "${postfix_dir}/virtual-mailbox-domains"
tr ' ' '\n' <<< "$YNH_DOMAINS_WITH_MAIL_IN" >> "${postfix_dir}/virtual-mailbox-domains"
cat postsrsd \
| sed "s/{{ main_domain }}/${main_domain}/g" \
| sed "s/{{ domain_list }}/${domain_list}/g" \
> "${default_dir}/postsrsd"
# adapt it for IPv4-only hosts
ipv6="$(jq -r '.smtp_allow_ipv6' <<< "$YNH_SETTINGS" | int_to_bool)"
if [ "$ipv6" == "False" ] || [ ! -f /proc/net/if_inet6 ]; then
sed -i \
's/ \[::ffff:127.0.0.0\]\/104 \[::1\]\/128//g' \
"${postfix_dir}/main.cf"
sed -i \
's/inet_interfaces = all/&\ninet_protocols = ipv4/' \
"${postfix_dir}/main.cf"
fi
}
do_post_regen() {
regen_conf_files=$1
chown postfix /etc/postfix
if [ -e /etc/postfix/sasl_passwd ]; then
chmod 750 /etc/postfix/sasl_passwd*
chown postfix:root /etc/postfix/sasl_passwd*
postmap /etc/postfix/sasl_passwd
fi
if [ -e /etc/postfix/relay_recipients ]; then
chmod 750 /etc/postfix/relay_recipients*
chown postfix:root /etc/postfix/relay_recipients*
fi
postmap -F hash:/etc/postfix/sni
python3 -c 'from yunohost.app import regen_mail_app_user_config_for_dovecot_and_postfix as r; r(only="postfix")'
[[ -z "$regen_conf_files" ]] \
|| { systemctl restart postfix && systemctl restart postsrsd; }
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

93
hooks/conf_regen/25-dovecot Executable file
View File

@@ -0,0 +1,93 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/dovecot
dovecot_dir="${pending_dir}/etc/dovecot"
mkdir -p "${dovecot_dir}/global_script"
# copy simple conf files
cp dovecot-ldap.conf "${dovecot_dir}/dovecot-ldap.conf"
cp dovecot.sieve "${dovecot_dir}/global_script/dovecot.sieve"
export pop3_enabled="$(jq -r '.pop3_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
export main_domain=$(cat /etc/yunohost/current_host)
export domain_list="$YNH_DOMAINS_WITH_MAIL_IN_AND_OUT"
ynh_render_template "dovecot.conf" "${dovecot_dir}/dovecot.conf"
# adapt it for IPv4-only hosts
if [ ! -f /proc/net/if_inet6 ]; then
sed -i \
's/^\(listen =\).*/\1 */' \
"${dovecot_dir}/dovecot.conf"
fi
mkdir -p "${dovecot_dir}/yunohost.d"
cp pre-ext.conf "${dovecot_dir}/yunohost.d"
cp post-ext.conf "${dovecot_dir}/yunohost.d"
}
do_post_regen() {
regen_conf_files=$1
mkdir -p "/etc/dovecot/yunohost.d/pre-ext.d"
mkdir -p "/etc/dovecot/yunohost.d/post-ext.d"
# create vmail user
id vmail > /dev/null 2>&1 \
|| {
mkdir -p /var/vmail
adduser --system --ingroup mail --uid 500 vmail --home /var/vmail --no-create-home
}
# Delete legacy home for vmail that existed in the past but was empty, poluting /home/
[ ! -e /home/vmail ] || rmdir --ignore-fail-on-non-empty /home/vmail
# fix permissions
chown -R vmail:mail /etc/dovecot/global_script
chmod 770 /etc/dovecot/global_script
chown root:mail /var/mail
chmod 1775 /var/mail
python3 -c 'from yunohost.app import regen_mail_app_user_config_for_dovecot_and_postfix as r; r(only="dovecot")'
[ -z "$regen_conf_files" ] && exit 0
# compile sieve script
[[ "$regen_conf_files" =~ dovecot\.sieve ]] && {
sievec /etc/dovecot/global_script/dovecot.sieve
chown -R vmail:mail /etc/dovecot/global_script
}
systemctl restart dovecot
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

59
hooks/conf_regen/30-opendkim Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/opendkim
install -D -m 644 opendkim.conf "$pending_dir/etc/opendkim.conf"
}
do_post_regen() {
mkdir -p /etc/dkim
# Create / empty those files because we're force-regenerating them
echo "" > /etc/dkim/keytable
echo "" > /etc/dkim/signingtable
# create DKIM key for domains
for domain in $YNH_DOMAINS_WITH_MAIL_IN_AND_OUT; do
domain_key="/etc/dkim/${domain}.mail.key"
if [ ! -f "$domain_key" ]; then
opendkim-genkey --domain="$domain" \
--selector=mail --directory=/etc/dkim -b 2048
mv /etc/dkim/mail.private "$domain_key"
mv /etc/dkim/mail.txt "/etc/dkim/${domain}.mail.txt"
fi
echo "mail._domainkey.${domain} ${domain}:mail:${domain_key}" >> /etc/dkim/keytable
echo "*@$domain mail._domainkey.${domain}" >> /etc/dkim/signingtable
done
chown -R opendkim /etc/dkim/
chmod 700 /etc/dkim/
systemctl restart opendkim
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

76
hooks/conf_regen/34-mysql Executable file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers
if ! dpkg --list | grep -q '^ii\s*mariadb-server\s'; then
echo 'mysql/mariadb is not installed, skipping'
exit 0
fi
do_pre_regen() {
# Nothing to do
:
}
do_post_regen() {
regen_conf_files=$1
if [[ ! -d /var/lib/mysql/mysql ]]; then
# dpkg-reconfigure will initialize mysql (if it ain't already)
# It enabled auth_socket for root, so no need to define any root password...
# c.f. : cat /var/lib/dpkg/info/mariadb-server-10.3.postinst | grep install_db -C3
MYSQL_PKG="$(dpkg --list | sed -ne 's/^ii \(mariadb-server-[[:digit:].]\+\) .*$/\1/p')"
dpkg-reconfigure -freadline -u "$MYSQL_PKG" 2>&1
if ! systemctl -q is-active mariadb.service; then
systemctl start mariadb
fi
sleep 5
if ! echo "" | mysql; then
echo "Can't connect to mysql using unix_socket auth ... something went wrong during initial configuration of mysql !?" >&2
fi
fi
# mysql is supposed to be an alias to mariadb... but in some weird case is not
# c.f. https://forum.yunohost.org/t/mysql-ne-fonctionne-pas/11661
# Playing with enable/disable allows to recreate the proper symlinks.
if [ ! -e /etc/systemd/system/mysql.service ]; then
systemctl stop mysql -q
systemctl disable mysql -q
systemctl disable mariadb -q
systemctl enable mariadb -q
if ! systemctl is-active mariadb -q; then
systemctl start mariadb
fi
fi
if [[ -n "$regen_conf_files" ]]; then
systemctl restart mysql
fi
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

76
hooks/conf_regen/35-postgresql Executable file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers
if ! dpkg --list | grep -q "^ii\s*postgresql-$PSQL_VERSION\s"; then
echo 'postgresql is not installed, skipping'
exit 0
fi
if [ ! -e "/etc/postgresql/$PSQL_VERSION" ]; then
ynh_die --message="It looks like postgresql was not properly configured ? /etc/postgresql/$PSQL_VERSION is missing ... Could be due to a locale issue, c.f.https://serverfault.com/questions/426989/postgresql-etc-postgresql-doesnt-exist"
fi
do_pre_regen() {
# Nothing to do
:
}
do_post_regen() {
#regen_conf_files=$1
# Make sure postgresql is started and enabled
# (N.B. : to check the active state, we check the cluster state because
# postgresql could be flagged as active even though the cluster is in
# failed state because of how the service is configured..)
if ! systemctl is-active "postgresql@$PSQL_VERSION-main" -q; then
ynh_systemd_action --service_name=postgresql --action=restart
fi
if ! systemctl is-enabled postgresql -q; then
systemctl enable postgresql --quiet
fi
# If this is the very first time, we define the root password
# and configure a few things
if [ ! -f "$PSQL_ROOT_PWD_FILE" ] || [ ! -s "$PSQL_ROOT_PWD_FILE" ]; then
ynh_string_random > "$PSQL_ROOT_PWD_FILE"
fi
chown root:postgres "$PSQL_ROOT_PWD_FILE"
chmod 440 "$PSQL_ROOT_PWD_FILE"
sudo --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$(cat "$PSQL_ROOT_PWD_FILE")'" postgres
# force all user to connect to local databases using hashed passwords
# https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF
# Note: we can't use peer since YunoHost create users with nologin
# See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user
local pg_hba=/etc/postgresql/$PSQL_VERSION/main/pg_hba.conf
ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba"
ynh_systemd_action --service_name=postgresql --action=reload
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

85
hooks/conf_regen/37-mdns Executable file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
_generate_config() {
echo "domains:"
# Add yunohost.local (only if yunohost.local ain't already in ynh_domains)
if ! echo "${YNH_DOMAINS:-}" | tr ' ' '\n' | grep -q --line-regexp 'yunohost.local'; then
echo " - yunohost.local"
fi
for domain in ${YNH_DOMAINS:-}; do
# Only keep .local domains (don't keep
[[ "$domain" =~ [^.]+\.[^.]+\.local$ ]] && echo "Subdomain $domain cannot be handled by Bonjour/Zeroconf/mDNS" >&2
[[ "$domain" =~ ^[^.]+\.local$ ]] || continue
echo " - $domain"
done
if [[ -e /etc/yunohost/mdns.aliases ]]; then
for localalias in $(cat /etc/yunohost/mdns.aliases | grep -v "^ *$"); do
echo " - $localalias.local"
done
fi
}
do_init_regen() {
do_pre_regen ""
do_post_regen /etc/systemd/system/yunomdns.service
systemctl enable yunomdns --quiet
}
do_pre_regen() {
pending_dir="$1"
cd /usr/share/yunohost/conf/mdns
mkdir -p "$pending_dir/etc/systemd/system/"
cp yunomdns.service "$pending_dir/etc/systemd/system/"
if ! getent passwd mdns &> /dev/null; then
useradd --no-create-home --shell /usr/sbin/nologin --system --user-group mdns
fi
mkdir -p "$pending_dir/etc/yunohost"
_generate_config > "$pending_dir/etc/yunohost/mdns.yml"
}
do_post_regen() {
regen_conf_files="$1"
chown mdns:mdns /etc/yunohost/mdns.yml
# If we changed the systemd ynh-override conf
if echo "$regen_conf_files" | sed 's/,/\n/g' | grep -q "^/etc/systemd/system/yunomdns.service$"; then
systemctl daemon-reload
fi
# Legacy stuff to enable the new yunomdns service on legacy systems
if [[ -e /etc/avahi/avahi-daemon.conf ]] && grep -q 'yunohost' /etc/avahi/avahi-daemon.conf; then
systemctl enable yunomdns --now --quiet
sleep 2
fi
if [[ -n "$regen_conf_files" ]]; then
systemctl restart yunomdns
fi
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -e
# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers
PY_LIST_PORTS_OF="
import os
import yaml
file = os.environ['FILE']
proto = os.environ['PROTO']
data = yaml.safe_load(open(file, 'r'))
ports = [str(port) for port, info in data.get(proto, {}).items() if info['open']]
# Sane fallback in case for reason we cant find any TCP port opened which probably indicates there's an issue with the file, we don't want the server to just drop all the traffic
if not ports and proto == 'TCP':
ports = [22, 80, 443]
print(' '.join(ports))
"
do_pre_regen() {
pending_dir=$1
firewall_file="/etc/yunohost/firewall.yml"
tcp_ports=$(FILE=$firewall_file PROTO=tcp python3 -c "$PY_LIST_PORTS_OF")
udp_ports=$(FILE=$firewall_file PROTO=udp python3 -c "$PY_LIST_PORTS_OF")
export tcp_ports udp_ports
cd /usr/share/yunohost/conf/nftables
mkdir -p "${pending_dir}/etc/nftables.d"
cp nftables.conf "${pending_dir}/etc/nftables.conf"
ynh_render_template nftables.d/yunohost-firewall.tpl.conf "${pending_dir}/etc/nftables.d/yunohost-firewall.conf"
}
do_post_regen() {
regen_conf_files=$1
if ls -l /etc/nftables.d/*.conf > /dev/null; then
chown root:root /etc/nftables.d/*.conf
chmod 644 /etc/nftables.d/*.conf
fi
[[ -z "$regen_conf_files" ]] \
|| systemctl restart nftables
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

203
hooks/conf_regen/43-dnsmasq Executable file
View File

@@ -0,0 +1,203 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -e
# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers
do_init_regen() {
cd /usr/share/yunohost/conf/dnsmasq
if jq -re '.dns_custom_resolvers_enabled' <<< "$YNH_SETTINGS"; then
read -ra nameservers <<< "$(jq -r '.dns_custom_resolvers_list' <<< "$YNH_SETTINGS")"
for nameserver in "${nameservers[@]}"; do
echo "nameserver $nameserver" >> /etc/resolv.dnsmasq.conf
done
else
# Use a seed derived from the machine id and current month
# This way, the shuffle is random but should be stable accross the same month
# and make sure the regenconf is idempotent (at least during the same month)
# i.e. that it doesn't re-shuffle the file everytime we run the regenconf
SEED=$( (
cat /etc/machine-id || true
date +%m%Y
) | md5sum)
cat plain/resolv.dnsmasq.conf | grep "^nameserver" | shuf --random-source=<(echo "$SEED") > /etc/resolv.dnsmasq.conf
fi
chown root /etc/resolv.dnsmasq.conf
chmod 644 /etc/resolv.dnsmasq.conf
cp plain/etcdefault /etc/default/dnsmasq
export wireless_interfaces=""
ynh_render_template "dnsmasq.conf.tpl" "${pending_dir}/etc/dnsmasq.conf"
# Remove / disable services likely to conflict with dnsmasq
for SERVICE in systemd-resolved bind9; do
systemctl is-enabled $SERVICE &> /dev/null && systemctl disable $SERVICE 2> /dev/null
systemctl is-active $SERVICE &> /dev/null && systemctl stop $SERVICE
done
systemctl restart dnsmasq
}
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/dnsmasq
# create directory for pending conf
dnsmasq_dir="${pending_dir}/etc/dnsmasq.d"
mkdir -p "$dnsmasq_dir"
etcdefault_dir="${pending_dir}/etc/default"
mkdir -p "$etcdefault_dir"
# add default conf files
cp plain/etcdefault "${pending_dir}/etc/default/dnsmasq"
# add resolver pool
if jq -re '.dns_custom_resolvers_enabled' <<< "$YNH_SETTINGS"; then
read -ra nameservers <<< "$(jq -r '.dns_custom_resolvers_list' <<< "$YNH_SETTINGS" | sed 's/,/ /g')"
for nameserver in "${nameservers[@]}"; do
echo "nameserver $nameserver" >> "${pending_dir}/etc/resolv.dnsmasq.conf"
done
else
# Use a seed derived from the machine id and current month
# This way, the shuffle is random but should be stable accross the same month
# and make sure the regenconf is idempotent (at least during the same month)
# i.e. that it doesn't re-shuffle the file everytime we run the regenconf
SEED=$( (
cat /etc/machine-id || true
date +%m%Y
) | md5sum)
cat plain/resolv.dnsmasq.conf | grep "^nameserver" | shuf --random-source=<(echo "$SEED") > "${pending_dir}/etc/resolv.dnsmasq.conf"
fi
# retrieve variables
ipv4=$(curl --max-time 10 -s -4 https://ipv4.yunohost.org 2> /dev/null || true)
ynh_validate_ip4 "$ipv4" || ipv4='127.0.0.1'
ipv6=$(curl --max-time 10 -s -6 https://ipv6.yunohost.org 2> /dev/null || true)
ynh_validate_ip6 "$ipv6" || ipv6=''
interfaces="$(ip -j addr show | jq -r '[.[].ifname]|join(" ")')"
wireless_interfaces="lo"
for dev in /sys/class/net/*; do
if [ -d "$dev/wireless" ] && grep -q "up" "$dev/operstate"; then
wireless_interfaces+=" $(basename "$dev")"
fi
done
# General configuration
export wireless_interfaces
ynh_render_template "dnsmasq.conf.tpl" "${pending_dir}/etc/dnsmasq.conf"
# add domain conf files
export interfaces
export ipv4
export ipv6
for domain in $YNH_DOMAINS; do
[[ ! $domain =~ \.local$ ]] || continue
export domain
if tr ' ' '\n' <<< "$YNH_DOMAINS_WITH_MAIL_IN" | grep -q "^$domain$"; then
export mail_in="True"
else
export mail_in="False"
fi
ynh_render_template "domain.tpl" "${dnsmasq_dir}/${domain}"
done
# We arbitrarily pick 'c' for spamhaus NS but there's a/b/c/e
SPAMHAUS_NS=c.gns.spamhaus.org
# We need to perform a dig request ... but dnsmasq may not be up yet, and we'll get an empty result
# It's not too dramatic because next time the regenconf is ran, dnsmasq should be up
# Nevertheless it's good to try to make sure that this doesn't happen to avoid weird stuff where
# the regenconf is not idempotent ...
# So if dnsmasq is not up, try to pick the first IPv4 resolver from the shuffled list
if systemctl --quiet is-active dnsmasq; then
RESOLVER_FOR_DIG="127.0.0.1"
else
RESOLVER_FOR_DIG=$(grep '^nameserver.*\.' /etc/resolv.dnsmasq.conf | head -n1 | awk '{print $2}')
fi
cat << EOF > "${dnsmasq_dir}/spamhaus"
# Gotta force the usage of resolvers for spamhaus,
# Which will otherwise complain that we may be using an open resolver...
# cf https://www.spamhaus.com/resource-center/successfully-accessing-spamhauss-free-block-lists-using-a-public-dns/#yes-but-why-block-queries-from-public-recursive-name-servers
# We pick one of spamhaus' a/b/c/d/e nameservers, cf https://multirbl.valli.org/detail/zen.spamhaus.org.html
# And kind of hard-code the corresponding IPs because in practice dnsmasq doesn't allow to have a domain name for the resolver part of server= :| ...
# Fun-fact : did you know that AAAA is the name of IPv6 DNS records, but also the sound you make when debugging network and DNS??? #TheMoreYouKnow
EOF
for IP in $( (
dig +short A $SPAMHAUS_NS "@$RESOLVER_FOR_DIG" 2> /dev/null || true
dig +short AAAA $SPAMHAUS_NS "@$RESOLVER_FOR_DIG" 2> /dev/null || true
) | grep -v '^;' | sort); do
echo "server=/*.zen.spamhaus.org/$IP" >> "${dnsmasq_dir}/spamhaus"
done
# remove old domain conf files
for conf_file in /etc/dnsmasq.d/*.*; do
domain=$(basename "$conf_file")
if [[ ! $YNH_DOMAINS =~ $domain ]] && [[ ! $domain =~ \.local$ ]] && [[ $domain != spamhaus ]]; then
touch "${dnsmasq_dir}/${domain}"
fi
done
}
do_post_regen() {
regen_conf_files=$1
# Force permission (to cover some edge cases where root's umask is like 027 and then dnsmasq cant read this file)
chown root /etc/resolv.dnsmasq.conf
chmod 644 /etc/resolv.dnsmasq.conf
# Fuck it, those domain/search entries from dhclient are usually annoying
# lying shit from the ISP trying to MiTM
if grep -q -E "^ *(domain|search)" /run/resolvconf/resolv.conf; then
if grep -q -E "^ *(domain|search)" /run/resolvconf/interface/*.dhclient 2> /dev/null; then
sed -E "s/^(domain|search)/#\1/g" -i /run/resolvconf/interface/*.dhclient
fi
grep -q '^supersede domain-name "";' /etc/dhcp/dhclient.conf 2> /dev/null || echo 'supersede domain-name "";' >> /etc/dhcp/dhclient.conf
grep -q '^supersede domain-search "";' /etc/dhcp/dhclient.conf 2> /dev/null || echo 'supersede domain-search "";' >> /etc/dhcp/dhclient.conf
grep -q '^supersede search "";' /etc/dhcp/dhclient.conf 2> /dev/null || echo 'supersede search "";' >> /etc/dhcp/dhclient.conf
systemctl restart resolvconf
fi
# Some stupid things like rabbitmq-server used by onlyoffice won't work if
# the *short* hostname doesn't exists in /etc/hosts -_-
short_hostname=$(hostname -s)
grep -q "127.0.0.1.*$short_hostname" /etc/hosts || echo -e "\n127.0.0.1\t$short_hostname" >> /etc/hosts
[[ -n "$regen_conf_files" ]] || return 0
# Remove / disable services likely to conflict with dnsmasq
for SERVICE in systemd-resolved bind9; do
systemctl is-enabled $SERVICE &> /dev/null && systemctl disable $SERVICE 2> /dev/null
systemctl is-active $SERVICE &> /dev/null && systemctl stop $SERVICE
done
systemctl restart dnsmasq
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

45
hooks/conf_regen/46-nsswitch Executable file
View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
do_init_regen() {
do_pre_regen ""
systemctl restart unscd
}
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/nsswitch
install -D -m 644 nsswitch.conf "$pending_dir/etc/nsswitch.conf"
}
do_post_regen() {
regen_conf_files=$1
if [[ -n "$regen_conf_files" ]]; then
systemctl restart unscd
fi
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"

61
hooks/conf_regen/52-fail2ban Executable file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Exit hook on subcommand error or unset variable
set -eu
# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/conf/fail2ban
fail2ban_dir="${pending_dir}/etc/fail2ban"
mkdir -p "${fail2ban_dir}/filter.d"
mkdir -p "${fail2ban_dir}/jail.d"
mkdir -p "${pending_dir}/etc/systemd/system/fail2ban.service.d/"
cp yunohost.conf "${fail2ban_dir}/filter.d/yunohost.conf"
cp yunohost-portal.conf "${fail2ban_dir}/filter.d/yunohost-portal.conf"
cp postfix-sasl.conf "${fail2ban_dir}/filter.d/postfix-sasl.conf"
cp jail.conf "${fail2ban_dir}/jail.conf"
cp systemd-override-bind-nftables.conf "${pending_dir}/etc/systemd/system/fail2ban.service.d/systemd-override-bind-nftables.conf"
export ssh_port="$(jq -r '.ssh_port' <<< "$YNH_SETTINGS")"
ynh_render_template "yunohost-jails.conf" "${fail2ban_dir}/jail.d/yunohost-jails.conf"
}
do_post_regen() {
regen_conf_files=$1
if ls -l /etc/fail2ban/jail.d/*.conf; then
chown root:root /etc/fail2ban/jail.d/*.conf
chmod 644 /etc/fail2ban/jail.d/*.conf
fi
if [[ -n "$regen_conf_files" ]]; then
systemctl reload fail2ban
fi
}
"do_$1_regen" "$(echo "${*:2}" | xargs)"