Merge branch 'stretch-unstable' into fix-regen-conf-for-ssh

This commit is contained in:
Alexandre Aubin 2020-06-06 01:57:03 +02:00 committed by GitHub
commit 5a003291bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 468 additions and 50 deletions

View file

@ -260,11 +260,11 @@ ynh_install_app_dependencies () {
# And we have packages from sury installed (7.0.33-10+weirdshiftafter instead of 7.0.33-0 on debian)
if dpkg --list | grep "php7.0" | grep --quiet --invert-match "7.0.33-0+deb9"
then
# And sury ain't already installed
if ! grep --line-number --recursive --quiet "sury" /etc/apt/sources.list*
# And sury ain't already in sources.lists
if ! grep --recursive --quiet "^ *deb.*sury" /etc/apt/sources.list*
then
# Re-add sury
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version --priority=600
# Pin this sury repository to prevent sury of doing shit
for package_to_not_upgrade in "php" "php-fpm" "php-mysql" "php-xml" "php-zip" "php-mbstring" "php-ldap" "php-gd" "php-curl" "php-bz2" "php-json" "php-sqlite3" "php-intl" "openssl" "libssl1.1" "libssl-dev"

View file

@ -1,5 +1,6 @@
#!/bin/bash
n_version=6.5.1
n_install_dir="/opt/node_n"
node_version_path="$n_install_dir/n/versions/node"
# N_PREFIX is the directory of n, it needs to be loaded as a environment variable.
@ -16,8 +17,8 @@ ynh_install_n () {
ynh_print_info --message="Installation of N - Node.js version management"
# Build an app.src for n
mkdir --parents "../conf"
echo "SOURCE_URL=https://github.com/tj/n/archive/v4.1.0.tar.gz
SOURCE_SUM=3983fa3f00d4bf85ba8e21f1a590f6e28938093abe0bb950aeea52b1717471fc" > "../conf/n.src"
echo "SOURCE_URL=https://github.com/tj/n/archive/v${n_version}.tar.gz
SOURCE_SUM=5833f15893b9951a9ed59487e87b6c181d96b83a525846255872c4f92f0d25dd" > "../conf/n.src"
# Download and extract n
ynh_setup_source --dest_dir="$n_install_dir/git" --source_id=n
# Install n
@ -125,7 +126,10 @@ ynh_install_nodejs () {
test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n
# If n is not previously setup, install it
if ! test $(n --version > /dev/null 2>&1)
if ! $n_install_dir/bin/n --version > /dev/null 2>&1
then
ynh_install_n
elif dpkg --compare-versions "$($n_install_dir/bin/n --version)" lt $n_version
then
ynh_install_n
fi

View file

@ -354,7 +354,7 @@ ynh_install_php () {
fi
# Add an extra repository for those packages
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version --priority=600
# Install requested dependencies from this extra repository.
# Install php-fpm first, otherwise php will install apache as a dependency.

View file

@ -213,7 +213,7 @@ ynh_psql_drop_user() {
# usage: ynh_psql_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
# | arg: -p, --db_pwd= - Password of the database. If not given, a password will be generated
# | arg: -p, --db_pwd= - Password of the database. If not provided, a password will be generated
#
# After executing this helper, the password of the created database will be available in $db_pwd
# It will also be stored as "psqlpwd" into the app settings.
@ -231,7 +231,7 @@ ynh_psql_setup_db() {
if ! ynh_psql_user_exists --user=$db_user; then
local new_db_pwd=$(ynh_string_random) # Generate a random password
# If $db_pwd is not given, use new_db_pwd instead for db_pwd
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
ynh_psql_create_user "$db_user" "$db_pwd"

View file

@ -144,8 +144,13 @@ ynh_setup_source () {
then # Use the local source file if it is present
cp $local_src $src_filename
else # If not, download the source
# NB. we have to declare the var as local first,
# otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
# because local always return 0 ...
local out
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
local out=`wget --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1` || ynh_print_err --message="$out"
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
|| ynh_die --message="$out"
fi
# Check the control sum

View file

@ -67,6 +67,15 @@ EOF
# (this make sure that the hash is null / file is flagged as to-delete)
mkdir -p $pending_dir/etc/etckeeper
touch $pending_dir/etc/etckeeper/etckeeper.conf
# Skip ntp if inside a container (inspired from the conf of systemd-timesyncd)
mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/
echo "
[Unit]
ConditionCapability=CAP_SYS_TIME
ConditionVirtualization=!container
" > ${pending_dir}/etc/systemd/system/ntp.service.d/ynh-override.conf
}
do_post_regen() {
@ -91,6 +100,7 @@ do_post_regen() {
[[ ! -e /etc/yunohost/hooks.d ]] || (chown root /etc/yunohost/hooks.d && chmod 700 /etc/yunohost/hooks.d)
[[ ! -e /etc/yunohost/apps ]] || (chown root /etc/yunohost/apps && chmod 700 /etc/yunohost/apps)
[[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || { systemctl daemon-reload; systemctl restart ntp; }
}
_update_services() {

View file

@ -12,6 +12,8 @@ do_init_regen() {
do_pre_regen ""
systemctl daemon-reload
# fix some permissions
chown root:openldap /etc/ldap/slapd.conf
chown -R openldap:openldap /etc/ldap/schema/

View file

@ -20,9 +20,11 @@ do_post_regen() {
# 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
systemctl is-active mariadb -q || systemctl start mariadb
fi
if [ ! -f /etc/yunohost/mysql ]; then

8
data/other/ffdhe2048.pem Normal file
View file

@ -0,0 +1,8 @@
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
-----END DH PARAMETERS-----

View file

@ -14,9 +14,10 @@ ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Uncomment the following directive after DH generation
# > openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048
#ssl_dhparam /etc/ssl/private/dh2048.pem;
# Pre-defined FFDHE group (RFC 7919)
# From https://ssl-config.mozilla.org/ffdhe2048.txt
# https://security.stackexchange.com/a/149818
ssl_dhparam /usr/share/yunohost/other/ffdhe2048.pem;
# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
# https://wiki.mozilla.org/Security/Guidelines/Web_Security

15
debian/changelog vendored
View file

@ -1,3 +1,18 @@
yunohost (3.8.4.7) stable; urgency=low
- [fix] Remove some remains of glances (17eec25e)
- [fix] Force external resolution for reverse DNS dig (852cd14c)
- [fix] Make sure mysql is an alias to mariadb (e24191ce, ca89607d)
- [fix] Path for ynh_add_fpm_config template in restore (#1001)
- [fix] Add -o Acquire::Retries=3 to fix some stupid network issues happening sometimes with apt (03432349)
- [fix] ynh_setup_source: Retry wget on non-critical failures to try to avoid tmp dns issues (3d66eaec)
- [fix] ynh_setup_source: Calling ynh_print_err in case of error didn't work, and we probably want a ynh_die here (55036fad)
- [i18n] Translations updated for Catalan, French, Italian, Occitan
Thanks to all contributors <3 ! (JimboJoe, Leandro N., ppr, Quentí, xaloc33, yalh76)
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 04 Jun 2020 02:28:33 +0200
yunohost (3.8.4.6) stable; urgency=low
- [fix] Bump server_names_hash_bucket_size to 128 to avoid nginx exploding for stupid reasons (b3db4d92)

1
debian/install vendored
View file

@ -8,6 +8,7 @@ data/other/yunoprompt.service /etc/systemd/system/
data/other/password/* /usr/share/yunohost/other/password/
data/other/dpkg-origins/yunohost /etc/dpkg/origins
data/other/dnsbl_list.yml /usr/share/yunohost/other/
data/other/ffdhe2048.pem /usr/share/yunohost/other/
data/other/* /usr/share/yunohost/yunohost-config/moulinette/
data/templates/* /usr/share/yunohost/templates/
data/helpers /usr/share/yunohost/

View file

@ -537,7 +537,7 @@
"diagnosis_dns_good_conf": "Els registres DNS han estat correctament configurats pel domini {domain} (categoria {category})",
"diagnosis_dns_bad_conf": "Alguns registres DNS són incorrectes o no existeixen pel domini {domain} (categoria {category})",
"diagnosis_dns_missing_record": "Segons la configuració DNS recomanada, hauríeu d'afegir un registre DNS amb la següent informació.<br>Tipus: <code>{type}</code><br>Nom: <code>{name}</code><br>Valor: <code>{value}</code>",
"diagnosis_dns_discrepancy": "El registre DNS de tipus {type} i nom {name} no concorda amb la configuració recomanada.\nValor actual: {current}\nValor esperat: {value}",
"diagnosis_dns_discrepancy": "La configuració DNS següent sembla que no segueix la configuració recomanada: <br>Tipus: <code>{type}</code><br>Nom: <code>{name}</code><br>Valor actual: <code>{current}</code><br>Valor esperat: <code>{value}</code>",
"diagnosis_services_bad_status": "El servei {service} està {status} :(",
"diagnosis_diskusage_verylow": "El lloc d'emmagatzematge <code>{mountpoint}</code> (en l'aparell <code>{device}</code>) només té disponibles {free} ({free_percent}%). Hauríeu de considerar alliberar una mica d'espai!",
"diagnosis_diskusage_low": "El lloc d'emmagatzematge <code>{mountpoint}</code> (en l'aparell <code>{device}</code>) només té disponibles {free} ({free_percent}%). Aneu amb compte.",
@ -649,5 +649,7 @@
"diagnosis_domain_expiration_error": "Alguns dominis expiraran EN BREUS!",
"diagnosis_domain_expires_in": "{domain} expirarà en {days} dies.",
"diagnosis_swap_tip": "Vigileu i tingueu en compte que els servidor està allotjant memòria d'intercanvi en una targeta SD o en l'emmagatzematge SSD, això pot reduir dràsticament l'esperança de vida del dispositiu.",
"restore_already_installed_apps": "No s'han pogut restaurar les següents aplicacions perquè ja estan instal·lades: {apps}"
"restore_already_installed_apps": "No s'han pogut restaurar les següents aplicacions perquè ja estan instal·lades: {apps}",
"app_packaging_format_not_supported": "No es pot instal·lar aquesta aplicació ja que el format del paquet no és compatible amb la versió de YunoHost del sistema. Hauríeu de considerar actualitzar el sistema.",
"diagnosis_dns_try_dyndns_update_force": "La configuració DNS d'aquest domini hauria de ser gestionada automàticament per YunoHost. Si aquest no és el cas, podeu intentar forçar-ne l'actualització utilitzant <cmd>yunohost dyndns update --force</cmd>."
}

View file

@ -428,6 +428,7 @@
"migration_description_0012_postgresql_password_to_md5_authentication": "Force PostgreSQL authentication to use MD5 for local connections",
"migration_description_0013_futureproof_apps_catalog_system": "Migrate to the new future-proof apps catalog system",
"migration_description_0014_remove_app_status_json": "Remove legacy status.json app files",
"migration_description_0015_migrate_to_buster": "Upgrade the system to Debian Buster and YunoHost 4.x",
"migration_0003_start": "Starting migration to Stretch. The logs will be available in {logfile}.",
"migration_0003_patching_sources_list": "Patching the sources.lists…",
"migration_0003_main_upgrade": "Starting main upgrade…",
@ -465,6 +466,19 @@
"migration_0011_update_LDAP_database": "Updating LDAP database…",
"migration_0011_update_LDAP_schema": "Updating LDAP schema…",
"migration_0011_failed_to_remove_stale_object": "Could not remove stale object {dn}: {error}",
"migration_0015_start" : "Starting migration to Buster",
"migration_0015_patching_sources_list": "Patching the sources.lists…",
"migration_0015_main_upgrade": "Starting main upgrade…",
"migration_0015_still_on_stretch_after_main_upgrade": "Something went wrong during the main upgrade, the system appears to still be on Debian Stretch",
"migration_0015_yunohost_upgrade" : "Starting YunoHost core upgrade…",
"migration_0015_not_stretch" : "The current Debian distribution is not Stretch!",
"migration_0015_not_enough_free_space" : "Free space is pretty low in /var/! You should have at least 1GB free to run this migration.",
"migration_0015_system_not_fully_up_to_date": "Your system is not fully up-to-date. Please perform a regular upgrade before running the migration to Buster.",
"migration_0015_general_warning": "Please note that this migration is a delicate operation. The YunoHost team did its best to review and test it, but the migration might still break parts of the system or its apps.\n\nTherefore, it is recommended to:\n - Perform a backup of any critical data or app. More info on https://yunohost.org/backup;\n - Be patient after launching the migration: Depending on your Internet connection and hardware, it might take up to a few hours for everything to upgrade.",
"migration_0015_problematic_apps_warning": "Please note that the following possibly problematic installed apps were detected. It looks like those were not installed from the YunoHost app catalog, or are not flagged as 'working'. Consequently, it cannot be guaranteed that they will still work after the upgrade: {problematic_apps}",
"migration_0015_modified_files": "Please note that the following files were found to be manually modified and might be overwritten following the upgrade: {manually_modified_files}",
"migration_0015_specific_upgrade": "Starting upgrade of system packages that needs to be upgrade independently…",
"migration_0015_cleaning_up": "Cleaning up cache and packages not useful anymore…",
"migrations_already_ran": "Those migrations are already done: {ids}",
"migrations_cant_reach_migration_file": "Could not access migrations files at the path '%s'",
"migrations_dependencies_not_satisfied": "Run these migrations: '{dependencies_id}', before migration {id}.",

View file

@ -426,7 +426,7 @@
"tools_upgrade_special_packages_completed": "La mise à jour des paquets de YunoHost est finie !\nPressez [Entrée] pour revenir à la ligne de commande",
"dpkg_lock_not_available": "Cette commande ne peut pas être exécutée pour le moment car un autre programme semble utiliser le verrou de dpkg (le gestionnaire de package système)",
"tools_upgrade_cant_unhold_critical_packages": "Impossible de conserver les paquets critiques…",
"tools_upgrade_special_packages_explanation": "La mise à niveau spéciale se poursuivra en arrière-plan. Veuillez ne pas lancer d'autres actions sur votre serveur pendant les 10 prochaines minutes (selon la vitesse du matériel). Après cela, vous devrez peut-être vous reconnecter à l'administrateur Web. Le journal de mise à niveau sera disponible dans Outils → Journal (dans le webadmin) ou en utilisant la « liste des journaux yunohost » (à partir de la ligne de commande).",
"tools_upgrade_special_packages_explanation": "La mise à niveau spécifique à YunoHost se poursuivra en arrière-plan. Veuillez ne pas lancer d'autres actions sur votre serveur pendant les 10 prochaines minutes (selon la vitesse du matériel). Après cela, vous devrez peut-être vous reconnecter à l'administrateur Web. Le journal de mise à niveau sera disponible dans Outils → Journal (dans le webadmin) ou en utilisant la « liste des journaux yunohost » (à partir de la ligne de commande).",
"update_apt_cache_failed": "Impossible de mettre à jour le cache APT (gestionnaire de paquets Debian). Voici un extrait du fichier sources.list qui pourrait vous aider à identifier les lignes problématiques :\n{sourceslist}",
"update_apt_cache_warning": "Des erreurs se sont produites lors de la mise à jour du cache APT (gestionnaire de paquets Debian). Voici un extrait des lignes du fichier sources.list qui pourrait vous aider à identifier les lignes problématiques :\n{sourceslist}",
"backup_permission": "Permission de sauvegarde pour lapplication {app:s}",

View file

@ -1,7 +1,7 @@
{
"app_already_installed": "{app:s} è già installata",
"app_extraction_failed": "Impossibile estrarre i file di installazione",
"app_not_installed": "{app:s} non è installata",
"app_not_installed": "Impossibile trovare l'applicazione '{app:s}' nell'elenco delle applicazioni installate: {all_apps}",
"app_unknown": "Applicazione sconosciuta",
"ask_email": "Indirizzo email",
"ask_password": "Password",
@ -28,13 +28,13 @@
"admin_password": "Password dell'amministrazione",
"admin_password_change_failed": "Impossibile cambiare la password",
"admin_password_changed": "La password dell'amministrazione è stata cambiata",
"app_install_files_invalid": "Non sono validi i file di installazione",
"app_install_files_invalid": "Questi file non possono essere installati",
"app_manifest_invalid": "Manifesto dell'applicazione non valido: {error}",
"app_not_correctly_installed": "{app:s} sembra di non essere installata correttamente",
"app_not_properly_removed": "{app:s} non è stata correttamente rimossa",
"action_invalid": "L'azione '{action:s}' non è valida",
"app_removed": "{app:s} è stata rimossa",
"app_sources_fetch_failed": "Impossibile riportare i file sorgenti",
"app_sources_fetch_failed": "Impossibile riportare i file sorgenti, l'URL è corretto?",
"app_upgrade_failed": "Impossibile aggiornare {app:s}",
"app_upgraded": "{app:s} è stata aggiornata",
"app_requirements_checking": "Controllo i pacchetti richiesti per {app}…",
@ -176,9 +176,9 @@
"app_change_url_failed_nginx_reload": "Non riesco a riavviare NGINX. Questo è il risultato di 'nginx -t':\n{nginx_errors:s}",
"app_change_url_identical_domains": "Il vecchio ed il nuovo dominio/percorso_url sono identici ('{domain:s}{path:s}'), nessuna operazione necessaria.",
"app_change_url_no_script": "L'applicazione '{app_name:s}' non supporta ancora la modifica dell'URL. Forse dovresti aggiornare l'applicazione.",
"app_change_url_success": "URL dell'applicazione {app:s} cambiato con successo in {domain:s}{path:s}",
"app_make_default_location_already_used": "Impostazione dell'applicazione '{app}' come predefinita del dominio {domain} non riuscita perchè è già stata impostata per l'altra applicazione '{other_app}'",
"app_location_unavailable": "Questo URL non è disponibile o va in conflitto con la/le applicazione/i già installata/e:\n{apps:s}",
"app_change_url_success": "L'URL dell'applicazione {app:s} è stato cambiato in {domain:s}{path:s}",
"app_make_default_location_already_used": "Impostazione dell'applicazione '{app}' come predefinita del dominio non riuscita perché il dominio {domain} è già in uso per l'altra applicazione '{other_app}'",
"app_location_unavailable": "Questo URL non è più disponibile o va in conflitto con la/le applicazione/i già installata/e:\n{apps:s}",
"app_upgrade_app_name": "Aggiornando l'applicazione {app}…",
"app_upgrade_some_app_failed": "Impossibile aggiornare alcune applicazioni",
"backup_abstract_method": "Questo metodo di backup non è ancora stato implementato",
@ -212,8 +212,8 @@
"certmanager_cert_install_success": "Certificato Let's Encrypt per il dominio {domain:s} installato con successo!",
"aborting": "Annullamento.",
"admin_password_too_long": "Per favore scegli una password più corta di 127 caratteri",
"app_not_upgraded": "Le seguenti app non sono state aggiornate: {apps}",
"app_start_install": "Installando l'applicazione {app}…",
"app_not_upgraded": "Impossibile aggiornare le applicazioni '{failed_app}' e di conseguenza l'aggiornamento delle seguenti applicazione è stato cancellato: {apps}",
"app_start_install": "Installando l'applicazione '{app}'…",
"app_start_remove": "Rimuovendo l'applicazione {app}…",
"app_start_backup": "Raccogliendo file da salvare nel backup per {app}…",
"app_start_restore": "Ripristinando l'applicazione {app}…",
@ -335,5 +335,9 @@
"migration_0003_not_jessie": "La distribuzione attuale non è Jessie!",
"migration_0003_system_not_fully_up_to_date": "Il tuo sistema non è completamente aggiornato. Per favore prima esegui un aggiornamento normale prima di migrare a stretch.",
"this_action_broke_dpkg": "Questa azione ha danneggiato dpkg/apt (i gestori di pacchetti del sistema)… Puoi provare a risolvere questo problema connettendoti via SSH ed eseguendo `sudo dpkg --configure -a`.",
"app_action_broke_system": "Questa azione sembra avere rotto questi servizi importanti: {services}"
"app_action_broke_system": "Questa azione sembra avere rotto questi servizi importanti: {services}",
"app_remove_after_failed_install": "Rimozione dell'applicazione a causa del fallimento dell'installazione…",
"app_install_script_failed": "Si è verificato un errore nello script di installazione dell'applicazione",
"app_install_failed": "Impossibile installare {app}:{error}",
"app_full_domain_unavailable": "Spiacente, questa app deve essere installata su un proprio dominio, ma altre applicazioni sono state installate sul dominio '{domain}'. Dovresti invece usare un sotto-dominio dedicato per questa app."
}

View file

@ -472,7 +472,7 @@
"migrations_not_pending_cant_skip": "Aquestas migracions son pas en espèra, las podètz pas doncas ignorar : {ids}",
"app_action_broke_system": "Aquesta accion sembla aver copat de servicis importants : {services}",
"diagnosis_display_tip_web": "Podètz anar a la seccion Diagnostic (dins lecran dacuèlh) per veire los problèmas trobats.",
"diagnosis_ip_no_ipv6": "Lo servidor a pas dadreça IPv5 activa.",
"diagnosis_ip_no_ipv6": "Lo servidor a pas dadreça IPv6 activa.",
"diagnosis_ip_not_connected_at_all": "Lo servidor sembla pas connectat a Internet ?!",
"diagnosis_security_all_good": "Cap de vulnerabilitat de seguretat critica pas trobada.",
"diagnosis_description_regenconf": "Configuracion sistèma",
@ -537,7 +537,7 @@
"group_cannot_be_deleted": "Lo grop « {group} » pòt pas èsser suprimit manualament.",
"diagnosis_found_warnings": "Trobat {warnings} element(s) que se poirián melhorar per {category}.",
"diagnosis_dns_missing_record": "Segon la configuracion DNS recomandada, vos calriá ajustar un enregistrament DNS\ntipe: {type}\nnom: {name}\nvalor: {value}",
"diagnosis_dns_discrepancy": "Segon la configuracion DNS recomandada, la valor per lenregistrament DNS\ntipe: {type}\nnom: {name}\ndeuriá èsser: {current}\nallòc de: {value}",
"diagnosis_dns_discrepancy": "La configuracion DNS seguenta sembla pas la configuracion recomandada: <br>Tipe: <code>{type}</code><br>Nom: <code>{name}</code><br>Valors actualas:<code> {current]</code><br>Valor esperada: <code>{value}</code>",
"diagnosis_regenconf_manually_modified_debian_details": "Es pas problematic, mas car téner dagacher...",
"diagnosis_ports_could_not_diagnose": "Impossible de diagnosticar se los pòrts son accessibles de lexterior.",
"diagnosis_ports_could_not_diagnose_details": "Error : {error}",

View file

@ -1358,7 +1358,7 @@ def app_ssowatconf():
url = _sanitized_absolute_url(perm_info["url"])
perm_info["url"] = url
if "visitors" in perm_info["allowed"]:
if url not in unprotected_urls:
if url not in unprotected_urls and url not in skipped_urls:
unprotected_urls.append(url)
# Legacy stuff : we remove now protected-urls that might have been declared as unprotected earlier...

View file

@ -0,0 +1,197 @@
import glob
import os
from moulinette import m18n
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger
from moulinette.utils.process import check_output, call_async_output
from moulinette.utils.filesystem import read_file
from yunohost.tools import Migration, tools_update, tools_upgrade
from yunohost.app import unstable_apps
from yunohost.regenconf import manually_modified_files
from yunohost.utils.filesystem import free_space_in_directory
from yunohost.utils.packages import get_ynh_package_version, _list_upgradable_apt_packages
logger = getActionLogger('yunohost.migration')
class MyMigration(Migration):
"Upgrade the system to Debian Buster and Yunohost 4.x"
mode = "manual"
def run(self):
self.check_assertions()
logger.info(m18n.n("migration_0015_start"))
#
# Patch sources.list
#
logger.info(m18n.n("migration_0015_patching_sources_list"))
self.patch_apt_sources_list()
tools_update(system=True)
# Tell libc6 it's okay to restart system stuff during the upgrade
os.system("echo 'libc6 libraries/restart-without-asking boolean true' | debconf-set-selections")
# Don't send an email to root about the postgresql migration. It should be handled automatically after.
os.system("echo 'postgresql-common postgresql-common/obsolete-major seen true' | debconf-set-selections")
#
# Specific packages upgrades
#
logger.info(m18n.n("migration_0015_specific_upgrade"))
# Update unscd independently, was 0.53-1+yunohost on stretch (custom build of ours) but now it's 0.53-1+b1 on vanilla buster,
# which for apt appears as a lower version (hence the --allow-downgrades and the hardcoded version number)
unscd_version = check_output('dpkg -s unscd | grep "^Version: " | cut -d " " -f 2')
if "yunohost" in unscd_version:
self.apt_install('unscd=0.53-1+b1 --allow-downgrades')
# Upgrade libpam-modules independently, small issue related to willing to overwrite a file previously provided by Yunohost
libpammodules_version = check_output('dpkg -s libpam-modules | grep "^Version: " | cut -d " " -f 2')
if not libpammodules_version.startswith("1.3"):
self.apt_install('libpam-modules -o Dpkg::Options::="--force-overwrite"')
#
# Main upgrade
#
logger.info(m18n.n("migration_0015_main_upgrade"))
apps_packages = self.get_apps_equivs_packages()
self.hold(apps_packages)
tools_upgrade(system=True, allow_yunohost_upgrade=False)
if self.debian_major_version() == 9:
raise YunohostError("migration_0015_still_on_stretch_after_main_upgrade")
# Clean the mess
logger.info(m18n.n("migration_0015_cleaning_up"))
os.system("apt autoremove --assume-yes")
os.system("apt clean --assume-yes")
#
# Yunohost upgrade
#
logger.info(m18n.n("migration_0015_yunohost_upgrade"))
self.unhold(apps_packages)
tools_upgrade(system=True)
def debian_major_version(self):
# The python module "platform" and lsb_release are not reliable because
# on some setup, they may still return Release=9 even after upgrading to
# buster ... (Apparently this is related to OVH overriding some stuff
# with /etc/lsb-release for instance -_-)
# Instead, we rely on /etc/os-release which should be the raw info from
# the distribution...
return int(check_output("grep VERSION_ID /etc/os-release | head -n 1 | tr '\"' ' ' | cut -d ' ' -f2"))
def yunohost_major_version(self):
return int(get_ynh_package_version("yunohost")["version"].split('.')[0])
def check_assertions(self):
# Be on stretch (9.x) and yunohost 3.x
# NB : we do both check to cover situations where the upgrade crashed
# in the middle and debian version could be > 9.x but yunohost package
# would still be in 3.x...
if not self.debian_major_version() == 9 \
and not self.yunohost_major_version() == 3:
raise YunohostError("migration_0015_not_stretch")
# Have > 1 Go free space on /var/ ?
if free_space_in_directory("/var/") / (1024**3) < 1.0:
raise YunohostError("migration_0015_not_enough_free_space")
# Check system is up to date
# (but we don't if 'stretch' is already in the sources.list ...
# which means maybe a previous upgrade crashed and we're re-running it)
if " buster " not in read_file("/etc/apt/sources.list"):
tools_update(system=True)
upgradable_system_packages = list(_list_upgradable_apt_packages())
if upgradable_system_packages:
raise YunohostError("migration_0015_system_not_fully_up_to_date")
@property
def disclaimer(self):
# Avoid having a super long disclaimer + uncessary check if we ain't
# on stretch / yunohost 3.x anymore
# NB : we do both check to cover situations where the upgrade crashed
# in the middle and debian version could be >= 10.x but yunohost package
# would still be in 3.x...
if not self.debian_major_version() == 9 \
and not self.yunohost_major_version() == 3:
return None
# Get list of problematic apps ? I.e. not official or community+working
problematic_apps = unstable_apps()
problematic_apps = "".join(["\n - " + app for app in problematic_apps])
# Manually modified files ? (c.f. yunohost service regen-conf)
modified_files = manually_modified_files()
modified_files = "".join(["\n - " + f for f in modified_files])
message = m18n.n("migration_0015_general_warning")
if problematic_apps:
message += "\n\n" + m18n.n("migration_0015_problematic_apps_warning", problematic_apps=problematic_apps)
if modified_files:
message += "\n\n" + m18n.n("migration_0015_modified_files", manually_modified_files=modified_files)
return message
def patch_apt_sources_list(self):
sources_list = glob.glob("/etc/apt/sources.list.d/*.list")
sources_list.append("/etc/apt/sources.list")
# This :
# - replace single 'stretch' occurence by 'buster'
# - comments lines containing "backports"
# - replace 'stretch/updates' by 'strech/updates' (or same with -)
for f in sources_list:
command = "sed -i -e 's@ stretch @ buster @g' " \
"-e '/backports/ s@^#*@#@' " \
"-e 's@ stretch/updates @ buster/updates @g' " \
"-e 's@ stretch-updates @ buster-updates @g' " \
"{}".format(f)
os.system(command)
def get_apps_equivs_packages(self):
command = "dpkg --get-selections" \
" | grep -v deinstall" \
" | awk '{print $1}'" \
" | { grep 'ynh-deps$' || true; }"
output = check_output(command).strip()
return output.split('\n') if output else []
def hold(self, packages):
for package in packages:
os.system("apt-mark hold {}".format(package))
def unhold(self, packages):
for package in packages:
os.system("apt-mark unhold {}".format(package))
def apt_install(self, cmd):
def is_relevant(l):
return "Reading database ..." not in l.rstrip()
callbacks = (
lambda l: logger.info("+ " + l.rstrip() + "\r") if is_relevant(l) else logger.debug(l.rstrip() + "\r"),
lambda l: logger.warning(l.rstrip()),
)
cmd = "LC_ALL=C DEBIAN_FRONTEND=noninteractive APT_LISTCHANGES_FRONTEND=none apt install --quiet -o=Dpkg::Use-Pty=0 --fix-broken --assume-yes " + cmd
call_async_output(cmd, callbacks, shell=True)

View file

@ -200,6 +200,42 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run
conf_hashes[sshd_config] = _calculate_hash(conf_files[sshd_config])
_update_conf_hashes(category, conf_hashes)
# Consider the following scenario:
# - you add a domain foo.bar
# - the regen-conf creates file /etc/dnsmasq.d/foo.bar
# - the admin manually *deletes* /etc/dnsmasq.d/foo.bar
# - the file is now understood as manually deleted because there's the old file hash in regenconf.yml
#
# ... so far so good, that's the expected behavior.
#
# But then:
# - the admin remove domain foo.bar entirely
# - but now the hash for /etc/dnsmasq.d/foo.bar is *still* in
# regenconf.yml and and the file is still flagged as manually
# modified/deleted... And the user cannot even do anything about it
# except removing the hash in regenconf.yml...
#
# Expected behavior: it should forget about that
# hash because dnsmasq's regen-conf doesn't say anything about what's
# the state of that file so it should assume that it should be deleted.
#
# - then the admin tries to *re-add* foo.bar !
# - ... but because the file is still flagged as manually modified
# the regen-conf refuses to re-create the file.
#
# Excepted behavior : the regen-conf should have forgot about the hash
# from earlier and this wouldnt happen.
# ------
# conf_files contain files explicitly set by the current regen conf run
# conf_hashes contain all files known from the past runs
# we compare these to get the list of stale hashes and flag the file as
# "should be removed"
stale_files = set(conf_hashes.keys()) - set(conf_files.keys())
stale_files_with_non_empty_hash = [f for f in stale_files if conf_hashes.get(f)]
for f in stale_files_with_non_empty_hash:
conf_files[f] = None
# </> End discussion about stale file hashes
for system_path, pending_path in conf_files.items():
logger.debug("processing pending conf '%s' to system conf '%s'",
pending_path, system_path)
@ -211,20 +247,45 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run
system_path, pending_path, True) if with_diff else None
# Check if the conf must be removed
to_remove = True if os.path.getsize(pending_path) == 0 else False
to_remove = True if pending_path and os.path.getsize(pending_path) == 0 else False
# Retrieve and calculate hashes
system_hash = _calculate_hash(system_path)
saved_hash = conf_hashes.get(system_path, None)
new_hash = None if to_remove else _calculate_hash(pending_path)
# -> configuration was previously managed by yunohost but should now
# be removed / unmanaged
if system_path in stale_files_with_non_empty_hash:
# File is already deleted, so let's just silently forget about this hash entirely
if not system_hash:
logger.debug("> forgetting about stale file/hash")
conf_hashes[system_path] = None
conf_status = 'forget-about-it'
regenerated = True
# Otherwise there's still a file on the system but it's not managed by
# Yunohost anymore... But if user requested --force we shall
# force-erase it
elif force:
logger.debug("> force-remove stale file")
regenerated = _regen(system_path)
conf_status = 'force-removed'
# Otherwise, flag the file as manually modified
else:
logger.warning(m18n.n(
'regenconf_file_manually_modified',
conf=system_path))
conf_status = 'modified'
# -> system conf does not exists
if not system_hash:
elif not system_hash:
if to_remove:
logger.debug("> system conf is already removed")
os.remove(pending_path)
continue
if not saved_hash or force:
conf_hashes[system_path] = None
conf_status = 'forget-about-it'
regenerated = True
elif not saved_hash or force:
if force:
logger.debug("> system conf has been manually removed")
conf_status = 'force-created'
@ -301,7 +362,7 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run
if regenerated:
succeed_regen[system_path] = conf_result
conf_hashes[system_path] = new_hash
if os.path.isfile(pending_path):
if pending_path and os.path.isfile(pending_path):
os.remove(pending_path)
else:
failed_regen[system_path] = conf_result
@ -417,7 +478,7 @@ def _get_files_diff(orig_file, new_file, as_string=False, skip_header=True):
def _calculate_hash(path):
"""Calculate the MD5 hash of a file"""
if not os.path.exists(path):
if not path or not os.path.exists(path):
return None
hasher = hashlib.md5()
@ -503,6 +564,12 @@ def _update_conf_hashes(category, hashes):
if category_conf is None:
category_conf = {}
# If a file shall be removed and is indeed removed, forget entirely about
# that path.
# It avoid keeping weird old entries like
# /etc/nginx/conf.d/some.domain.that.got.removed.conf
hashes = {path: hash_ for path, hash_ in hashes.items() if hash_ is not None or os.path.exists(path)}
category_conf['conffiles'] = hashes
categories[category] = category_conf
_save_regenconf_infos(categories)

View file

@ -1,20 +1,13 @@
import glob
import os
import pytest
import shutil
import requests
from conftest import message, raiseYunohostError
from moulinette import m18n
from moulinette.utils.filesystem import mkdir
from yunohost.domain import _get_maindomain, domain_add, domain_remove, domain_list
from yunohost.utils.error import YunohostError
from yunohost.regenconf import manually_modified_files, regen_conf, _get_conf_hashes, _force_clear_hashes
from conftest import message
from yunohost.domain import domain_add, domain_remove, domain_list
from yunohost.regenconf import regen_conf, manually_modified_files, _get_conf_hashes, _force_clear_hashes
TEST_DOMAIN = "secondarydomain.test"
TEST_DOMAIN_NGINX_CONFIG = "/etc/nginx/conf.d/secondarydomain.test.conf"
TEST_DOMAIN_NGINX_CONFIG = "/etc/nginx/conf.d/%s.conf" % TEST_DOMAIN
TEST_DOMAIN_DNSMASQ_CONFIG = "/etc/dnsmasq.d/%s" % TEST_DOMAIN
SSHD_CONFIG = "/etc/ssh/sshd_config"
def setup_function(function):
@ -22,11 +15,13 @@ def setup_function(function):
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
clean()
def teardown_function(function):
clean()
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
def clean():
assert os.system("pgrep slapd >/dev/null") == 0
@ -116,3 +111,94 @@ def test_ssh_conf_unmanaged_and_manually_modified(mocker):
assert SSHD_CONFIG in _get_conf_hashes("ssh")
assert SSHD_CONFIG not in manually_modified_files()
def test_stale_hashes_get_removed_if_empty():
"""
This is intended to test that if a file gets removed and is indeed removed,
we don't keep a useless empty hash corresponding to an old file.
In this case, we test this using the dnsmasq conf file (we don't do this
using the nginx conf file because it's already force-removed during
domain_remove())
"""
domain_add(TEST_DOMAIN)
assert os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
assert TEST_DOMAIN_DNSMASQ_CONFIG in _get_conf_hashes("dnsmasq")
domain_remove(TEST_DOMAIN)
assert not os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
assert TEST_DOMAIN_DNSMASQ_CONFIG not in _get_conf_hashes("dnsmasq")
def test_stale_hashes_if_file_manually_deleted():
"""
Same as other test, but manually delete the file in between and check
behavior
"""
domain_add(TEST_DOMAIN)
assert os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
assert TEST_DOMAIN_DNSMASQ_CONFIG in _get_conf_hashes("dnsmasq")
os.remove(TEST_DOMAIN_DNSMASQ_CONFIG)
assert not os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
regen_conf(names=["dnsmasq"])
assert not os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
assert TEST_DOMAIN_DNSMASQ_CONFIG in _get_conf_hashes("dnsmasq")
domain_remove(TEST_DOMAIN)
assert not os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
assert TEST_DOMAIN_DNSMASQ_CONFIG not in _get_conf_hashes("dnsmasq")
# This test only works if you comment the part at the end of the regen-conf in
# dnsmasq that auto-flag /etc/dnsmasq.d/foo.bar as "to be removed" (using touch)
# ... But we want to keep it because they also possibly flag files that were
# never known by the regen-conf (e.g. if somebody adds a
# /etc/dnsmasq.d/my.custom.extension)
# Ideally we could use a system that's able to properly state 'no file in this
# folder should exist except the ones excplicitly defined by regen-conf' but
# that's too much work for the scope of this commit.
#
# ... Anyway, the proper way to write these tests would be to use a dummy
# regen-conf hook just for tests but meh I'm lazy
#
#def test_stale_hashes_if_file_manually_modified():
# """
# Same as other test, but manually delete the file in between and check
# behavior
# """
#
# domain_add(TEST_DOMAIN)
#
# assert os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
# assert TEST_DOMAIN_DNSMASQ_CONFIG in _get_conf_hashes("dnsmasq")
#
# os.system("echo '#pwet' > %s" % TEST_DOMAIN_DNSMASQ_CONFIG)
#
# assert os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
# assert open(TEST_DOMAIN_DNSMASQ_CONFIG).read().strip() == "#pwet"
#
# regen_conf(names=["dnsmasq"])
#
# assert os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
# assert open(TEST_DOMAIN_DNSMASQ_CONFIG).read().strip() == "#pwet"
# assert TEST_DOMAIN_DNSMASQ_CONFIG in _get_conf_hashes("dnsmasq")
#
# domain_remove(TEST_DOMAIN)
#
# assert os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
# assert open(TEST_DOMAIN_DNSMASQ_CONFIG).read().strip() == "#pwet"
# assert TEST_DOMAIN_DNSMASQ_CONFIG in _get_conf_hashes("dnsmasq")
#
# regen_conf(names=["dnsmasq"], force=True)
#
# assert not os.path.exists(TEST_DOMAIN_DNSMASQ_CONFIG)
# assert TEST_DOMAIN_DNSMASQ_CONFIG not in _get_conf_hashes("dnsmasq")

View file

@ -489,7 +489,7 @@ def _list_upgradable_apps():
@is_unit_operation()
def tools_upgrade(operation_logger, apps=None, system=False):
def tools_upgrade(operation_logger, apps=None, system=False, allow_yunohost_upgrade=True):
"""
Update apps & package cache, then display changelog
@ -552,7 +552,7 @@ def tools_upgrade(operation_logger, apps=None, system=False):
# Critical packages are packages that we can't just upgrade
# randomly from yunohost itself... upgrading them is likely to
critical_packages = ("moulinette", "yunohost", "yunohost-admin", "ssowat", "python")
critical_packages = ["moulinette", "yunohost", "yunohost-admin", "ssowat"]
critical_packages_upgradable = [p["name"] for p in upgradables if p["name"] in critical_packages]
noncritical_packages_upgradable = [p["name"] for p in upgradables if p["name"] not in critical_packages]
@ -605,7 +605,7 @@ def tools_upgrade(operation_logger, apps=None, system=False):
#
# Critical packages upgrade
#
if critical_packages_upgradable:
if critical_packages_upgradable and allow_yunohost_upgrade:
logger.info(m18n.n("tools_upgrade_special_packages"))