mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge branch 'stretch-stable' into stretch-testing
This commit is contained in:
commit
4e8642f675
12 changed files with 101 additions and 38 deletions
|
@ -170,7 +170,7 @@ smtpd_milters = inet:localhost:11332
|
|||
milter_default_action = accept
|
||||
|
||||
# Avoid to send simultaneously too many emails
|
||||
smtp_destination_concurrency_limit = 1
|
||||
smtp_destination_concurrency_limit = 2
|
||||
default_destination_rate_delay = 5s
|
||||
|
||||
# Avoid email adress scanning
|
||||
|
|
16
debian/changelog
vendored
16
debian/changelog
vendored
|
@ -11,6 +11,22 @@ yunohost (3.8.5) testing; urgency=low
|
|||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 06 Jun 2020 02:11:51 +0200
|
||||
|
||||
yunohost (3.8.4.9) stable; urgency=low
|
||||
|
||||
- [fix] Force lowercase on domain names (804f4b3e)
|
||||
- [fix] Add dirmngr to Depends:, needed for apt-key / gpg (cd115ed8)
|
||||
- [fix] Improve debugging when diagnosis ain't happy when renewing certs (0f0194be)
|
||||
- [enh] Add yunohost version to logs metadata (d615546b)
|
||||
- [enh] Alway filter irrelevant log lines when sharing it (38704cba, 51d53be5)
|
||||
- [fix] Regen-conf outputing many 'forget-about-it' because of files flagged as to be removed (f4525488)
|
||||
- [fix] postfix per-domain destination concurrency (#988)
|
||||
- [fix] Call regenconf for ssh before the general regenconf during the postinstall to avoid an irrelevant warning (7805837b)
|
||||
- [i18n] Translations updated for Catalan, French, German
|
||||
|
||||
Thanks to all contributors <3 ! (taziden, ljf, ppr, xaloc33, Yasss Gurl)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 18 Jun 2020 15:13:01 +0200
|
||||
|
||||
yunohost (3.8.4.8) stable; urgency=low
|
||||
|
||||
- [fix] Don't add unprotected_urls if it's already in skipped_urls (#1005)
|
||||
|
|
2
debian/control
vendored
2
debian/control
vendored
|
@ -15,7 +15,7 @@ Depends: ${python:Depends}, ${misc:Depends}
|
|||
, python-psutil, python-requests, python-dnspython, python-openssl
|
||||
, python-miniupnpc, python-dbus, python-jinja2
|
||||
, python-toml, python-packaging
|
||||
, apt, apt-transport-https
|
||||
, apt, apt-transport-https, dirmngr
|
||||
, nginx, nginx-extras (>=1.6.2)
|
||||
, php-fpm, php-ldap, php-intl
|
||||
, mariadb-server, php-mysql | php-mysqlnd
|
||||
|
|
|
@ -651,5 +651,20 @@
|
|||
"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}",
|
||||
"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>."
|
||||
"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>.",
|
||||
"migration_0015_cleaning_up": "Netejant la memòria cau i els paquets que ja no són necessaris…",
|
||||
"migration_0015_specific_upgrade": "Començant l'actualització dels paquets del sistema que s'han d'actualitzar de forma independent…",
|
||||
"migration_0015_modified_files": "Tingueu en compte que s'han trobat els següents fitxers que es van modificar manualment i podria ser que es sobreescriguin durant l'actualització: {manually_modified_files}",
|
||||
"migration_0015_problematic_apps_warning": "Tingueu en compte que s'han trobat les següents aplicacions que podrien ser problemàtiques. Sembla que aquestes aplicacions no s'han instal·lat des del catàleg d'aplicacions de YunoHost, o no estan marcades com «funcionant». En conseqüència, no es pot garantir que segueixin funcionant després de l'actualització: {problematic_apps}",
|
||||
"migration_0015_general_warning": "Tingueu en compte que aquesta migració és una operació delicada. L'equip de YunoHost ha fet tots els possibles per revisar i testejar, però tot i això podria ser que la migració trenqui alguna part del sistema o algunes aplicacions.\n\nPer tant, està recomana:\n - Fer una còpia de seguretat de totes les dades o aplicacions crítiques. Més informació a https://yunohost.org/backup;\n - Ser pacient un cop comenci la migració: en funció de la connexió Internet i del maquinari, podria estar unes hores per actualitzar-ho tot.",
|
||||
"migration_0015_system_not_fully_up_to_date": "El sistema no està completament al dia. Heu de fer una actualització normal abans de fer la migració a Buster.",
|
||||
"migration_0015_not_enough_free_space": "Hi ha poc espai lliure a /var/! HI hauria d'haver un mínim de 1GB lliure per poder fer aquesta migració.",
|
||||
"migration_0015_not_stretch": "La distribució actual de Debian no és Stretch!",
|
||||
"migration_0015_yunohost_upgrade": "Començant l'actualització del nucli de YunoHost…",
|
||||
"migration_0015_still_on_stretch_after_main_upgrade": "Alguna cosa ha anat malament durant la actualització principal, sembla que el sistema encara està en Debian Stretch",
|
||||
"migration_0015_main_upgrade": "Començant l'actualització principal…",
|
||||
"migration_0015_patching_sources_list": "Apedaçament de source.lists…",
|
||||
"migration_0015_start": "Començant la migració a Buster",
|
||||
"migration_description_0015_migrate_to_buster": "Actualitza els sistema a Debian Buster i YunoHost 4.x",
|
||||
"regenconf_need_to_explicitly_specify_ssh": "La configuració ssh ha estat modificada manualment, però heu d'especificar explícitament la categoria «ssh» amb --force per fer realment els canvis."
|
||||
}
|
||||
|
|
|
@ -340,5 +340,6 @@
|
|||
"diagnosis_ip_weird_resolvconf": "DNS Auflösung scheint zu funktionieren, aber sei vorsichtig wenn du eine eigene <code>/etc/resolv.conf</code> verwendest.",
|
||||
"diagnosis_display_tip": "Um die gefundenen Probleme zu sehen, kannst Du zum Diagnose-Bereich des webadmin gehen, oder 'yunohost diagnosis show --issues' in der Kommandozeile ausführen.",
|
||||
"backup_archive_corrupted": "Das Backup-Archiv '{archive}' scheint beschädigt: {error}",
|
||||
"backup_archive_cant_retrieve_info_json": "Die Informationen für das Archiv '{archive}' konnten nicht geladen werden... Die Datei info.json wurde nicht gefunden (oder ist kein gültiges json)."
|
||||
"backup_archive_cant_retrieve_info_json": "Die Informationen für das Archiv '{archive}' konnten nicht geladen werden... Die Datei info.json wurde nicht gefunden (oder ist kein gültiges json).",
|
||||
"app_packaging_format_not_supported": "Diese App kann nicht installiert werden da das Paketformat nicht von der Yunohost-Version unterstützt wird. Denken Sie darüber nach das System zu aktualisieren."
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@
|
|||
"certmanager_attempt_to_renew_valid_cert": "Le certificat pour le domaine {domain:s} n’est pas sur le point d’expirer ! (Vous pouvez utiliser --force si vous savez ce que vous faites)",
|
||||
"certmanager_domain_http_not_working": "Le domaine {domain:s} ne semble pas être accessible via HTTP. Merci de vérifier la catégorie 'Web' dans le diagnostic pour plus d'informations. (Ou si vous savez ce que vous faites, utilisez '--no-checks' pour désactiver la vérification.)",
|
||||
"certmanager_error_no_A_record": "Aucun enregistrement DNS 'A' n’a été trouvé pour {domain:s}. Vous devez faire pointer votre nom de domaine vers votre machine pour être en mesure d’installer un certificat Let’s Encrypt ! (Si vous savez ce que vous faites, utilisez --no-checks pour désactiver ces contrôles)",
|
||||
"certmanager_domain_dns_ip_differs_from_public_ip": "L’enregistrement DNS 'A' du domaine {domain:s} est différent de l’adresse IP de ce serveur. Si vous avez récemment modifié votre enregistrement 'A', veuillez attendre sa propagation (des vérificateurs de propagation DNS sont disponibles en ligne). (Si vous savez ce que vous faites, utilisez --no-checks pour désactiver ces contrôles)",
|
||||
"certmanager_domain_dns_ip_differs_from_public_ip": "L'enregistrement DNS du domaine {domain:s} est différent de l’adresse IP de ce serveur. Pour plus d'informations, veuillez consulter la catégorie \"Enregistrements DNS\" dans le diagnostic. Si vous avez récemment modifié votre enregistrement 'A', veuillez attendre sa propagation (des vérificateurs de propagation DNS sont disponibles en ligne). (Si vous savez ce que vous faites, utilisez --no-checks pour désactiver ces contrôles)",
|
||||
"certmanager_cannot_read_cert": "Quelque chose s’est mal passé lors de la tentative d’ouverture du certificat actuel pour le domaine {domain:s} (fichier : {file:s}), la cause est : {reason:s}",
|
||||
"certmanager_cert_install_success_selfsigned": "Le certificat auto-signé est maintenant installé pour le domaine « {domain:s} »",
|
||||
"certmanager_cert_install_success": "Le certificat Let’s Encrypt est maintenant installé pour le domaine « {domain:s} »",
|
||||
|
@ -535,7 +535,7 @@
|
|||
"diagnosis_ip_broken_resolvconf": "La résolution du nom de domaine semble être cassée sur votre serveur, ce qui semble lié au fait que <code>/etc/resolv.conf</code> ne pointe pas vers <code>127.0.0.1</code>.",
|
||||
"diagnosis_dns_good_conf": "Les enregistrements DNS sont correctement configurés pour le domaine {domain} (catégorie {category})",
|
||||
"diagnosis_dns_bad_conf": "Certains enregistrements DNS sont manquants ou incorrects pour le domaine {domain} (catégorie {category})",
|
||||
"diagnosis_dns_discrepancy": "Cet enregistrement DNS ne semble pas correspondre à la configuration recommandée :<br>Type : <code>{type}</code><br>Nom : <code>{name}</code><br>Valeur actuelle : <code>{current}</code><br>Valeur attendue : <code>{value}</code>",
|
||||
"diagnosis_dns_discrepancy": "Cet enregistrement DNS ne semble pas correspondre à la configuration recommandée : <br>Type : <code>{type}</code><br>Nom : <code>{name}</code><br> La valeur actuelle est : <code>{current}</code><br> La valeur attendue est : <code>{value}</code>",
|
||||
"diagnosis_services_bad_status": "Le service {service} est {status} :-(",
|
||||
"diagnosis_diskusage_verylow": "L'espace de stockage <code>{mountpoint}</code> (sur l’appareil <code>{device}</code>) ne dispose que de {free} ({free_percent}%) espace restant (sur {total}). Vous devriez vraiment envisager de nettoyer de l’espace !",
|
||||
"diagnosis_diskusage_low": "L'espace de stockage <code>{mountpoint}</code> (sur l'appareil <code>{device}</code>) ne dispose que de {free} ({free_percent}%) espace restant (sur {total}). Faites attention.",
|
||||
|
@ -649,5 +649,23 @@
|
|||
"diagnosis_domain_expiration_error": "Certains domaines vont expirer TRÈS PROCHAINEMENT !",
|
||||
"diagnosis_domain_expires_in": "{domain} expire dans {days} jours.",
|
||||
"certmanager_domain_not_diagnosed_yet": "Il n'y a pas encore de résultat de diagnostic pour le domaine %s. Merci de relancer un diagnostic pour les catégories 'Enregistrements DNS' et 'Web' dans la section Diagnostique pour vérifier si le domaine est prêt pour Let's Encrypt. (Ou si vous savez ce que vous faites, utilisez '--no-checks' pour désactiver la vérification.)",
|
||||
"diagnosis_swap_tip": "Merci d'être prudent et conscient que si vous hébergez une partition SWAP sur une carte SD ou un disque SSD, cela risque de réduire drastiquement l’espérance de vie du périphérique."
|
||||
"diagnosis_swap_tip": "Merci d'être prudent et conscient que si vous hébergez une partition SWAP sur une carte SD ou un disque SSD, cela risque de réduire drastiquement l’espérance de vie du périphérique.",
|
||||
"restore_already_installed_apps": "Les applications suivantes ne peuvent pas être restaurées car elles sont déjà installées : {apps}",
|
||||
"regenconf_need_to_explicitly_specify_ssh": "La configuration de ssh a été modifiée manuellement. Vous devez explicitement indiquer la mention --force à \"ssh\" pour appliquer les changements.",
|
||||
"migration_0015_cleaning_up": "Nettoyage du cache et des paquets qui ne sont plus utiles …",
|
||||
"migration_0015_specific_upgrade": "Commencement de la mise à jour des paquets du système qui doivent être mis à jour séparément …",
|
||||
"migration_0015_modified_files": "Veuillez noter que les fichiers suivants ont été modifiés manuellement et pourraient être écrasés à la suite de la mise à niveau : {manually_modified_files}",
|
||||
"migration_0015_problematic_apps_warning": "Veuillez noter que des applications qui peuvent poser problèmes ont été détectées. Il semble qu'elles n'aient pas été installées à partir du catalogue d'applications YunoHost, ou bien qu'elles ne soient pas signalées comme \"fonctionnelles\". Par conséquent, il n'est pas possible de garantir que les applications suivantes fonctionneront encore après la mise à niveau : {problematic_apps}",
|
||||
"migration_0015_general_warning": "Veuillez noter que cette migration est une opération délicate. L'équipe YunoHost a fait de son mieux pour la revérifier et la tester, mais la migration pourrait quand même casser des éléments du système ou de ses applications.\n\nIl est donc recommandé :\n…- de faire une sauvegarde de toute donnée ou application critique. Plus d'informations ici https://yunohost.org/backup ;\n…- d'être patient après le lancement de la migration. Selon votre connexion internet et votre matériel, la mise à niveau peut prendre jusqu'à quelques heures.",
|
||||
"migration_0015_system_not_fully_up_to_date": "Votre système n'est pas entièrement à jour. Veuillez effectuer une mise à jour normale avant de lancer la migration vers Buster.",
|
||||
"migration_0015_not_enough_free_space": "L'espace libre est très faible dans /var/ ! Vous devriez avoir au moins 1 Go de libre pour effectuer cette migration.",
|
||||
"migration_0015_not_stretch": "La distribution Debian actuelle n'est pas Stretch !",
|
||||
"migration_0015_yunohost_upgrade": "Lancement de la mise à jour de YunoHost …",
|
||||
"migration_0015_still_on_stretch_after_main_upgrade": "Quelque chose s'est mal passé lors de la mise à niveau, le système semble toujours être sous Debian Stretch",
|
||||
"migration_0015_main_upgrade": "Début de la mise à niveau générale …",
|
||||
"migration_0015_patching_sources_list": "Mise à jour du fichier sources.lists …",
|
||||
"migration_0015_start": "Démarrage de la migration vers Buster",
|
||||
"migration_description_0015_migrate_to_buster": "Mise à niveau du système vers Debian Buster et YunoHost 4.x",
|
||||
"diagnosis_dns_try_dyndns_update_force": "La configuration DNS de ce domaine devrait être automatiquement gérée par Yunohost. Si ce n'est pas le cas, vous pouvez essayer de forcer une mise à jour en utilisant <cmd>yunohost dyndns update --force</cmd>.",
|
||||
"app_packaging_format_not_supported": "Cette application ne peut pas être installée car son format n'est pas pris en charge par votre version de Yunohost. Vous devriez probablement envisager de mettre à jour votre système."
|
||||
}
|
||||
|
|
|
@ -369,12 +369,11 @@ def certificate_renew(domain_list, force=False, no_checks=False, email=False, st
|
|||
if not no_checks:
|
||||
try:
|
||||
_check_domain_is_ready_for_ACME(domain)
|
||||
except:
|
||||
msg = "Certificate renewing for %s failed !" % (domain)
|
||||
logger.error(msg)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
if email:
|
||||
logger.error("Sending email with details to root ...")
|
||||
_email_renewing_failed(domain, msg)
|
||||
_email_renewing_failed(domain, e)
|
||||
continue
|
||||
|
||||
logger.info(
|
||||
|
|
|
@ -89,6 +89,10 @@ def domain_add(operation_logger, domain, dyndns=False):
|
|||
raise YunohostError('domain_exists')
|
||||
|
||||
operation_logger.start()
|
||||
|
||||
# Lower domain to avoid some edge cases issues
|
||||
# See: https://forum.yunohost.org/t/invalid-domain-causes-diagnosis-web-to-fail-fr-on-demand/11765
|
||||
domain = domain.lower()
|
||||
|
||||
# DynDNS domain
|
||||
if dyndns:
|
||||
|
|
|
@ -35,6 +35,7 @@ from logging import FileHandler, getLogger, Formatter
|
|||
from moulinette import m18n, msettings
|
||||
from moulinette.core import MoulinetteError
|
||||
from yunohost.utils.error import YunohostError
|
||||
from yunohost.utils.packages import get_ynh_package_version
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_file, read_yaml
|
||||
|
||||
|
@ -135,6 +136,29 @@ def log_display(path, number=None, share=False, filter_irrelevant=False):
|
|||
share
|
||||
"""
|
||||
|
||||
if share:
|
||||
filter_irrelevant = True
|
||||
|
||||
if filter_irrelevant:
|
||||
filters = [
|
||||
r"set [+-]x$",
|
||||
r"set [+-]o xtrace$",
|
||||
r"local \w+$",
|
||||
r"local legacy_args=.*$",
|
||||
r".*Helper used in legacy mode.*",
|
||||
r"args_array=.*$",
|
||||
r"local -A args_array$",
|
||||
r"ynh_handle_getopts_args",
|
||||
r"ynh_script_progression"
|
||||
]
|
||||
else:
|
||||
filters = []
|
||||
|
||||
def _filter_lines(lines, filters=[]):
|
||||
|
||||
filters = [re.compile(f) for f in filters]
|
||||
return [l for l in lines if not any(f.search(l.strip()) for f in filters)]
|
||||
|
||||
# Normalize log/metadata paths and filenames
|
||||
abs_path = path
|
||||
log_path = None
|
||||
|
@ -173,7 +197,8 @@ def log_display(path, number=None, share=False, filter_irrelevant=False):
|
|||
content += read_file(md_path)
|
||||
content += "\n============\n\n"
|
||||
if os.path.exists(log_path):
|
||||
content += read_file(log_path)
|
||||
actual_log = read_file(log_path)
|
||||
content += "\n".join(_filter_lines(actual_log.split("\n"), filters))
|
||||
|
||||
url = yunopaste(content)
|
||||
|
||||
|
@ -202,27 +227,12 @@ def log_display(path, number=None, share=False, filter_irrelevant=False):
|
|||
|
||||
# Display logs if exist
|
||||
if os.path.exists(log_path):
|
||||
|
||||
if filter_irrelevant:
|
||||
filters = [
|
||||
r"set [+-]x$",
|
||||
r"set [+-]o xtrace$",
|
||||
r"local \w+$",
|
||||
r"local legacy_args=.*$",
|
||||
r".*Helper used in legacy mode.*",
|
||||
r"args_array=.*$",
|
||||
r"local -A args_array$",
|
||||
r"ynh_handle_getopts_args",
|
||||
r"ynh_script_progression"
|
||||
]
|
||||
else:
|
||||
filters = []
|
||||
|
||||
from yunohost.service import _tail
|
||||
if number:
|
||||
logs = _tail(log_path, int(number), filters=filters)
|
||||
logs = _tail(log_path, int(number))
|
||||
else:
|
||||
logs = read_file(log_path)
|
||||
logs = _filter_lines(logs, filters)
|
||||
infos['log_path'] = log_path
|
||||
infos['logs'] = logs
|
||||
|
||||
|
@ -456,6 +466,7 @@ class OperationLogger(object):
|
|||
data = {
|
||||
'started_at': self.started_at,
|
||||
'operation': self.operation,
|
||||
'yunohost_version': get_ynh_package_version("yunohost")["version"],
|
||||
}
|
||||
if self.related_to is not None:
|
||||
data['related_to'] = self.related_to
|
||||
|
|
|
@ -236,6 +236,8 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run
|
|||
conf_files[f] = None
|
||||
# </> End discussion about stale file hashes
|
||||
|
||||
force_update_hashes_for_this_category = False
|
||||
|
||||
for system_path, pending_path in conf_files.items():
|
||||
logger.debug("processing pending conf '%s' to system conf '%s'",
|
||||
pending_path, system_path)
|
||||
|
@ -284,7 +286,8 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run
|
|||
os.remove(pending_path)
|
||||
conf_hashes[system_path] = None
|
||||
conf_status = 'forget-about-it'
|
||||
regenerated = True
|
||||
force_update_hashes_for_this_category = True
|
||||
continue
|
||||
elif not saved_hash or force:
|
||||
if force:
|
||||
logger.debug("> system conf has been manually removed")
|
||||
|
@ -377,7 +380,7 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run
|
|||
else:
|
||||
logger.success(m18n.n('regenconf_would_be_updated', category=category))
|
||||
|
||||
if succeed_regen and not dry_run:
|
||||
if (succeed_regen or force_update_hashes_for_this_category) and not dry_run:
|
||||
_update_conf_hashes(category, conf_hashes)
|
||||
|
||||
# Append the category results
|
||||
|
|
|
@ -639,7 +639,7 @@ def _save_services(services):
|
|||
raise
|
||||
|
||||
|
||||
def _tail(file, n, filters=[]):
|
||||
def _tail(file, n):
|
||||
"""
|
||||
Reads a n lines from f with an offset of offset lines. The return
|
||||
value is a tuple in the form ``(lines, has_more)`` where `has_more` is
|
||||
|
@ -650,8 +650,6 @@ def _tail(file, n, filters=[]):
|
|||
avg_line_length = 74
|
||||
to_read = n
|
||||
|
||||
if filters:
|
||||
filters = [re.compile(f) for f in filters]
|
||||
|
||||
try:
|
||||
if file.endswith(".gz"):
|
||||
|
@ -673,9 +671,6 @@ def _tail(file, n, filters=[]):
|
|||
pos = f.tell()
|
||||
lines = f.read().splitlines()
|
||||
|
||||
for filter_ in filters:
|
||||
lines = [l for l in lines if not filter_.search(l)]
|
||||
|
||||
if len(lines) >= to_read:
|
||||
return lines[-to_read:]
|
||||
|
||||
|
|
|
@ -368,7 +368,6 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False,
|
|||
service_enable("yunohost-firewall")
|
||||
service_start("yunohost-firewall")
|
||||
|
||||
regen_conf(force=True)
|
||||
regen_conf(names=["ssh"], force=True)
|
||||
|
||||
# Restore original ssh conf, as chosen by the
|
||||
|
@ -384,6 +383,8 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False,
|
|||
if os.path.exists(original_sshd_conf):
|
||||
os.rename(original_sshd_conf, '/etc/ssh/sshd_config')
|
||||
|
||||
regen_conf(force=True)
|
||||
|
||||
logger.success(m18n.n('yunohost_configured'))
|
||||
|
||||
logger.warning(m18n.n('yunohost_postinstall_end_tip'))
|
||||
|
|
Loading…
Add table
Reference in a new issue