Merge branch 'stretch-unstable' into enh-postgresql-locale-misconfigured

This commit is contained in:
Alexandre Aubin 2020-04-28 17:20:19 +02:00 committed by GitHub
commit d6e7295dfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
153 changed files with 11697 additions and 8376 deletions

4
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,4 @@
# These are supported funding model platforms
custom: https://donate.yunohost.org
liberapay: YunoHost

101
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,101 @@
stages:
- postinstall
- tests
.tests:
image: after-postinstall
before_script:
- apt-get install python-pip -y
- mkdir -p .pip
- pip install -U pip
- hash -d pip
- pip --cache-dir=.pip install pytest pytest-sugar pytest-mock requests-mock mock
- pushd src/yunohost/tests
- >
if [ ! -d "./apps" ]; then
git clone https://github.com/YunoHost/test_apps ./apps
fi
- cd apps
- git pull > /dev/null 2>&1
- popd
- export PYTEST_ADDOPTS="--color=yes"
cache:
paths:
- .pip
- src/yunohost/tests/apps
key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"
postinstall:
image: before-postinstall
stage: postinstall
script:
- yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns
root-tests:
extends: .tests
stage: tests
script:
- py.test tests
test-apps:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_apps.py
test-appscatalog:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_appscatalog.py
test-appurl:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_appurl.py
test-backuprestore:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_backuprestore.py
test-changeurl:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_changeurl.py
test-permission:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_permission.py
test-settings:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_settings.py
test-user-group:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_user-group.py
test-regenconf:
extends: .tests
stage: tests
script:
- cd src/yunohost
- py.test tests/test_regenconf.py

View file

@ -1,48 +1,43 @@
<p align="center">
<img alt="YunoHost" src="https://raw.githubusercontent.com/YunoHost/doc/master/images/logo_roundcorner.png" width="100px" />
</p>
<h1 align="center">YunoHost</h1>
<div align="center">
[![Build status](https://travis-ci.org/YunoHost/yunohost.svg?branch=stretch-unstable)](https://travis-ci.org/YunoHost/yunohost)
[![GitHub license](https://img.shields.io/github/license/YunoHost/yunohost)](https://github.com/YunoHost/yunohost/blob/stretch-unstable/LICENSE)
[![Mastodon Follow](https://img.shields.io/mastodon/follow/28084)](https://mastodon.social/@yunohost)
# YunoHost core
</div>
This repository is the core of YunoHost code.
YunoHost is an operating system aiming to simplify as much as possible the administration of a server.
This repository corresponds to the core code of YunoHost, mainly written in Python and Bash.
- [Project features](https://yunohost.org/#/whatsyunohost)
- [Project website](https://yunohost.org)
- [Bugtracker](https://github.com/YunoHost/issues).
- [Install documentation](https://yunohost.org/install)
- [Issue tracker](https://github.com/YunoHost/issues)
# Screenshots
Webadmin ([Yunohost-Admin](https://github.com/YunoHost/yunohost-admin)) | Single sign-on user portal ([SSOwat](https://github.com/YunoHost/ssowat))
--- | ---
![](https://raw.githubusercontent.com/YunoHost/doc/master/images/webadmin.png) | ![](https://raw.githubusercontent.com/YunoHost/doc/master/images/user_panel.png)
## Contributing
- You can develop on this repository using [ynh-dev](https://github.com/YunoHost/ynh-dev) with `use-git` sub-command.
- On this repository we are [following this workflow](https://yunohost.org/#/build_system_en): `stable ← testing ← unstable ← your_branch`.
- Note: If you modify Python scripts, you will have to modifiy the actions map.
- You can learn how to get started with developing on YunoHost by reading [this piece of documentation](https://yunohost.org/dev).
- Come chat with us on the [dev chatroom](https://yunohost.org/#/chat_rooms) !
- You can help translate YunoHost on our [translation platform](https://translate.yunohost.org/engage/yunohost/?utm_source=widget)
<p align="center">
<img src="https://translate.yunohost.org/widgets/yunohost/-/multi-auto.svg" alt="Translation status" />
## Repository content
- [YunoHost core Python 2.7 scripts](./src/yunohost).
- [An actionsmap](./data/actionsmap/yunohost.yml) used by moulinette.
- [Services configuration templates](./data/templates).
- [Hooks](./data/hooks).
- [Locales](./locales) for translations of `yunohost` command.
- [Shell helpers](./helpers.d) for [application packaging](https://yunohost.org/#/packaging_apps_helpers_en).
- [Modules for the XMPP server Metronome](./lib/metronome/modules).
- [Debian files](./debian) for package creation.
## How does it work?
- Python core scripts are accessible through two interfaces thanks to the [moulinette framework](https://github.com/YunoHost/moulinette):
- [CLI](https://en.wikipedia.org/wiki/Command-line_interface) for `yunohost` command.
- [API](https://en.wikipedia.org/wiki/Application_programming_interface) for [web administration module](https://github.com/YunoHost/yunohost-admin) (other modules could be implemented).
- You can find more details about how YunoHost works on this [documentation (in French)](https://yunohost.org/#/package_list_fr).
## Dependencies
- [Python 2.7](https://www.python.org/download/releases/2.7)
- [Moulinette](https://github.com/YunoHost/moulinette)
- [Bash](https://www.gnu.org/software/bash/bash.html)
- [Debian Stretch](https://www.debian.org/releases/stretch)
</p>
## License
As [other components of YunoHost core code](https://yunohost.org/#/faq_en), this repository is licensed GNU AGPL v3.
As [other components of YunoHost](https://yunohost.org/#/faq_en), this repository is licensed under GNU AGPL v3.

View file

@ -179,6 +179,10 @@ def _retrieve_namespaces():
ret.append(n)
return ret
# Stupid PATH management because sometimes (e.g. some cron job) PATH is only /usr/bin:/bin ...
default_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
if os.environ["PATH"] != default_path:
os.environ["PATH"] = default_path + ":" + os.environ["PATH"]
# Main action ----------------------------------------------------------

View file

@ -201,24 +201,34 @@ user:
subcategories:
group:
subcategory_help: Manage group
subcategory_help: Manage user groups
actions:
### user_group_list()
list:
action_help: List group
action_help: List existing groups
api: GET /users/groups
arguments:
--fields:
help: fields to fetch
nargs: "+"
-s:
full: --short
help: List only the names of groups
action: store_true
-f:
full: --full
help: Display all informations known about each groups
action: store_true
-p:
full: --include-primary-groups
help: Also display primary groups (each user has an eponym group that only contains itself)
action: store_true
default: false
### user_group_add()
add:
### user_group_create()
create:
action_help: Create group
api: POST /users/groups
arguments:
groupname:
help: The unique group name to add
help: Name of the group to be created
extra:
pattern: &pattern_groupname
- !!str ^[a-z0-9_]+$
@ -230,7 +240,7 @@ user:
api: DELETE /users/groups/<groupname>
arguments:
groupname:
help: Username to delete
help: Name of the group to be deleted
extra:
pattern: *pattern_groupname
@ -240,19 +250,19 @@ user:
api: PUT /users/groups/<groupname>
arguments:
groupname:
help: Username to update
help: Name of the group to be updated
extra:
pattern: *pattern_groupname
-a:
full: --add-user
help: User to add in group
full: --add
help: User(s) to add in the group
nargs: "*"
metavar: USERNAME
extra:
pattern: *pattern_username
-r:
full: --remove-user
help: User to remove in group
full: --remove
help: User(s) to remove in the group
nargs: "*"
metavar: USERNAME
extra:
@ -260,112 +270,69 @@ user:
### user_group_info()
info:
action_help: Get group information
action_help: Get information about a specific group
api: GET /users/groups/<groupname>
arguments:
groupname:
help: Groupname to get information
help: Name of the group to fetch info about
extra:
pattern: *pattern_username
permission:
subcategory_help: Manage user permission
subcategory_help: Manage permissions
actions:
### user_permission_list()
list:
action_help: List access to user and group
api: GET /users/permissions/<app>
action_help: List permissions and corresponding accesses
api: GET /users/permissions
arguments:
-s:
full: --short
help: Only list permission names
action: store_true
-f:
full: --full
help: Display all info known about each permission, including the full user list of each group it is granted to.
action: store_true
### user_permission_info()
info:
action_help: Get information about a specific permission
api: GET /users/permissions/<permission>
arguments:
permission:
help: Name of the permission to fetch info about
### user_permission_update()
update:
action_help: Manage group or user permissions
api: PUT /users/permissions/<permission>
arguments:
permission:
help: Permission to manage (e.g. mail or nextcloud or wordpress.editors)
-a:
full: --app
help: Application to manage the permission
full: --add
help: Group or usernames to grant this permission to
nargs: "*"
metavar: APP
-p:
full: --permission
help: Name of permission (main by default)
nargs: "*"
metavar: PERMISSION
-u:
full: --username
help: Username
nargs: "*"
metavar: USER
-g:
full: --group
help: Group name
nargs: "*"
metavar: GROUP
### user_permission_add()
add:
action_help: Grant access right to users and group
api: POST /users/permissions/<app>
arguments:
app:
help: Application to manage the permission
nargs: "+"
-p:
full: --permission
help: Name of permission (main by default)
nargs: "*"
metavar: PERMISSION
-u:
full: --username
help: Username
nargs: "*"
metavar: USER
metavar: GROUP_OR_USER
extra:
pattern: *pattern_username
-g:
full: --group
help: Group name
-r:
full: --remove
help: Group or usernames revoke this permission from
nargs: "*"
metavar: GROUP
metavar: GROUP_OR_USER
extra:
pattern: *pattern_username
### user_permission_remove()
remove:
action_help: Revoke access right to users and group
api: PUT /users/permissions/<app>
arguments:
app:
help: Application to manage the permission
nargs: "+"
-p:
full: --permission
help: Name of permission (main by default)
nargs: "*"
metavar: PERMISSION
-u:
full: --username
help: Username
nargs: "*"
metavar: USER
extra:
pattern: *pattern_username
-g:
full: --group
help: Group name
nargs: "*"
metavar: GROUP
extra:
pattern: *pattern_username
## user_permission_clear()
clear:
action_help: Reset access rights for the app
## user_permission_reset()
reset:
action_help: Reset allowed groups to the default (all_users) for a given permission
api: DELETE /users/permissions/<app>
arguments:
app:
help: Application to manage the permission
nargs: "+"
-p:
full: --permission
help: Name of permission (main by default)
nargs: "*"
metavar: PERMISSION
permission:
help: Permission to manage (e.g. mail or nextcloud or wordpress.editors)
ssh:
subcategory_help: Manage ssh access
@ -439,6 +406,10 @@ domain:
list:
action_help: List domains
api: GET /domains
arguments:
--exclude-subdomains:
help: Filter out domains that are obviously subdomains of other declared domains
action: store_true
### domain_add()
add:
@ -481,6 +452,21 @@ domain:
- !!str ^[0-9]+$
- "pattern_positive_number"
### domain_maindomain()
main-domain:
action_help: Check the current main domain, or change it
deprecated_alias:
- maindomain
api:
- GET /domains/main
- PUT /domains/main
arguments:
-n:
full: --new-main-domain
help: Change the current main domain
extra:
pattern: *pattern_domain
### certificate_status()
cert-status:
action_help: List status of current certificates (all by default).
@ -568,78 +554,53 @@ app:
category_help: Manage apps
actions:
### app_fetchlist()
catalog:
action_help: Show the catalog of installable application
api: GET /appscatalog
arguments:
-f:
full: --full
help: Display all details, including the app manifest and various other infos
action: store_true
-c:
full: --with-categories
help: Also return a list of app categories
action: store_true
fetchlist:
action_help: Fetch application lists from app servers, or register a new one.
api: PUT /appslists
arguments:
-n:
full: --name
help: Name of the list to fetch (fetches all registered lists if empty)
extra:
pattern: &pattern_listname
- !!str ^[a-z0-9_]+$
- "pattern_listname"
-u:
full: --url
help: URL of a new application list to register. To be specified with -n.
### app_listlists()
listlists:
action_help: List registered application lists
api: GET /appslists
### app_removelist()
removelist:
action_help: Remove and forget about a given application list
api: DELETE /appslists
arguments:
name:
help: Name of the list to remove
extra:
ask: ask_list_to_remove
pattern: *pattern_listname
deprecated: true
### app_list()
list:
action_help: List apps
action_help: List installed apps
api: GET /apps
arguments:
-f:
full: --filter
help: Name filter of app_id or app_name
-r:
full: --raw
help: Return the full app_dict
full: --full
help: Display all details, including the app manifest and various other infos
action: store_true
-i:
full: --installed
help: Return only installed apps
action: store_true
-b:
full: --with-backup
help: Return only apps with backup feature (force --installed filter)
help: Dummy argument, does nothing anymore (still there only for backward compatibility)
action: store_true
filter:
nargs: '?'
### app_info()
info:
action_help: Get information about an installed app
action_help: Show infos about a specific installed app
api: GET /apps/<app>
arguments:
app:
help: Specific app ID
-s:
full: --show-status
help: Show app installation status
action: store_true
-r:
full: --raw
help: Return the full app_dict
-f:
full: --full
help: Display all details, including the app manifest and various other infos
action: store_true
### app_map()
map:
action_help: List apps by domain
action_help: Show the mapping between urls and apps
api: GET /appsmap
arguments:
-a:
@ -738,30 +699,6 @@ app:
help: Delete the key
action: store_true
### app_checkport()
checkport:
action_help: Check availability of a local port
api: GET /tools/checkport
deprecated: true
arguments:
port:
help: Port to check
extra:
pattern: &pattern_port
- !!str ^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$
- "pattern_port"
### app_checkurl()
checkurl:
action_help: Check availability of a web path
api: GET /tools/checkurl
deprecated: True
arguments:
url:
help: Url to check
-a:
full: --app
help: Write domain & path to app settings for further checks
### app_register_url()
register-url:
@ -776,32 +713,6 @@ app:
help: The path to be registered (e.g. /coffee)
### app_initdb()
initdb:
action_help: Create database and initialize it with optionnal attached script
api: POST /tools/initdb
deprecated: true
arguments:
user:
help: Name of the DB user
-p:
full: --password
help: Password of the DB (generated unless set)
-d:
full: --db
help: DB name (user unless set)
-s:
full: --sql
help: Initial SQL file
### app_debug()
debug:
action_help: Display all debug informations for an application
api: GET /apps/<app>/debug
arguments:
app:
help: App name
### app_makedefault()
makedefault:
action_help: Redirect domain root to an app
@ -832,6 +743,7 @@ app:
addaccess:
action_help: Grant access right to users (everyone by default)
api: PUT /access
deprecated: true
arguments:
apps:
nargs: "+"
@ -843,6 +755,7 @@ app:
removeaccess:
action_help: Revoke access right to users (everyone by default)
api: DELETE /access
deprecated: true
arguments:
apps:
nargs: "+"
@ -854,6 +767,7 @@ app:
clearaccess:
action_help: Reset access rights for the app
api: POST /access
deprecated: true
arguments:
apps:
nargs: "+"
@ -1005,147 +919,6 @@ backup:
pattern: *pattern_backup_archive_name
#############################
# Monitor #
#############################
monitor:
category_help: Monitor the server
actions:
### monitor_disk()
disk:
action_help: Monitor disk space and usage
api: GET /monitor/disk
arguments:
-f:
full: --filesystem
help: Show filesystem disk space
action: append_const
const: filesystem
dest: units
-t:
full: --io
help: Show I/O throughput
action: append_const
const: io
dest: units
-m:
full: --mountpoint
help: Monitor only the device mounted on MOUNTPOINT
action: store
-H:
full: --human-readable
help: Print sizes in human readable format
action: store_true
### monitor_network()
network:
action_help: Monitor network interfaces
api: GET /monitor/network
arguments:
-u:
full: --usage
help: Show interfaces bit rates
action: append_const
const: usage
dest: units
-i:
full: --infos
help: Show network informations
action: append_const
const: infos
dest: units
-c:
full: --check
help: Check network configuration
action: append_const
const: check
dest: units
-H:
full: --human-readable
help: Print sizes in human readable format
action: store_true
### monitor_system()
system:
action_help: Monitor system informations and usage
api: GET /monitor/system
arguments:
-m:
full: --memory
help: Show memory usage
action: append_const
const: memory
dest: units
-c:
full: --cpu
help: Show CPU usage and load
action: append_const
const: cpu
dest: units
-p:
full: --process
help: Show processes summary
action: append_const
const: process
dest: units
-u:
full: --uptime
help: Show the system uptime
action: append_const
const: uptime
dest: units
-i:
full: --infos
help: Show system informations
action: append_const
const: infos
dest: units
-H:
full: --human-readable
help: Print sizes in human readable format
action: store_true
### monitor_updatestats()
update-stats:
action_help: Update monitoring statistics
api: POST /monitor/stats
arguments:
period:
help: Time period to update
choices:
- day
- week
- month
### monitor_showstats()
show-stats:
action_help: Show monitoring statistics
api: GET /monitor/stats
arguments:
period:
help: Time period to show
choices:
- day
- week
- month
### monitor_enable()
enable:
action_help: Enable server monitoring
api: PUT /monitor
arguments:
-s:
full: --with-stats
help: Enable monitoring statistics
action: store_true
### monitor_disable()
disable:
api: DELETE /monitor
action_help: Disable server monitoring
#############################
# Settings #
#############################
@ -1209,24 +982,13 @@ service:
arguments:
name:
help: Service name to add
-s:
full: --status
help: Custom status command
-d:
full: --description
help: Description of the service
-l:
full: --log
help: Absolute path to log file to display
nargs: "+"
-r:
full: --runlevel
help: Runlevel priority of the service
type: int
-n:
full: --need_lock
help: Use this option to prevent deadlocks if the service does invoke yunohost commands.
action: store_true
-d:
full: --description
help: Description of the service
-t:
full: --log_type
help: Type of the log (file or systemd)
@ -1235,6 +997,22 @@ service:
- file
- systemd
default: file
--test_status:
help: Specify a custom bash command to check the status of the service. Note that it only makes sense to specify this if the corresponding systemd service does not return the proper information already.
--test_conf:
help: Specify a custom bash command to check if the configuration of the service is valid or broken, similar to nginx -t.
--needs_exposed_ports:
help: A list of ports that needs to be publicly exposed for the service to work as intended.
nargs: "+"
type: int
metavar: PORT
-n:
full: --need_lock
help: Use this option to prevent deadlocks if the service does invoke yunohost commands.
action: store_true
-s:
full: --status
help: Deprecated, old option. Does nothing anymore. Possibly check the --test_status option.
### service_remove()
remove:
@ -1276,6 +1054,7 @@ service:
### service_restart()
restart:
action_help: Restart one or more services. If the services are not running yet, they will be started.
api: PUT /services/<names>/restart
arguments:
names:
help: Service name to restart
@ -1579,12 +1358,9 @@ tools:
### tools_maindomain()
maindomain:
action_help: Check the current main domain, or change it
api:
- GET /domains/main
- PUT /domains/main
arguments:
-n:
full: --new-domain
full: --new-main-domain
help: Change the current main domain
extra:
pattern: *pattern_domain
@ -1643,26 +1419,6 @@ tools:
help: Upgrade only the system packages
action: store_true
### tools_diagnosis()
diagnosis:
action_help: YunoHost diagnosis
api: GET /diagnosis
arguments:
-p:
full: --private
help: Show private data (domain, IP)
action: store_true
### tools_port_available()
port-available:
action_help: Check availability of a local port
api: GET /tools/portavailable
arguments:
port:
help: Port to check
extra:
pattern: *pattern_port
### tools_shell()
shell:
action_help: Launch a development shell
@ -1717,6 +1473,11 @@ tools:
help: List pending configuration files and exit
action: store_true
### tools_versions()
versions:
action_help: Display YunoHost's packages versions
api: GET /versions
subcategories:
migrations:
@ -1898,3 +1659,73 @@ log:
--share:
help: Share the full log using yunopaste
action: store_true
#############################
# Diagnosis #
#############################
diagnosis:
category_help: Look for possible issues on the server
actions:
list:
action_help: List diagnosis categories
api: GET /diagnosis/list
show:
action_help: Show most recents diagnosis results
api: GET /diagnosis/show
arguments:
categories:
help: Diagnosis categories to display (all by default)
nargs: "*"
--full:
help: Display additional information
action: store_true
--issues:
help: Only display issues
action: store_true
--share:
help: Share the logs using yunopaste
action: store_true
run:
action_help: Run diagnosis
api: POST /diagnosis/run
arguments:
categories:
help: Diagnosis categories to run (all by default)
nargs: "*"
--force:
help: Ignore the cached report even if it is still 'fresh'
action: store_true
--except-if-never-ran-yet:
help: Don't run anything if diagnosis never ran yet ... (this is meant to be used by the webadmin)
action: store_true
ignore:
action_help: Configure some diagnosis results to be ignored and therefore not considered as actual issues
api: POST /diagnosis/ignore
arguments:
--add-filter:
help: "Add a filter. The first element should be a diagnosis category, and other criterias can be provided using the infos from the 'meta' sections in 'yunohost diagnosis show'. For example: 'dnsrecords domain=yolo.test category=xmpp'"
nargs: "*"
metavar: CRITERIA
--remove-filter:
help: Remove a filter (it should be an existing filter as listed with --list)
nargs: "*"
metavar: CRITERIA
--list:
help: List active ignore filters
action: store_true
get:
action_help: Low-level command to fetch raw data and status about a specific diagnosis test
api: GET /diagnosis/item/<category>
arguments:
category:
help: Diagnosis category to fetch results from
item:
help: "List of criteria describing the test. Must correspond exactly to the 'meta' infos in 'yunohost diagnosis show'"
metavar: CRITERIA
nargs: "*"

View file

@ -3,7 +3,7 @@ Simple automated generation of a bash_completion file
for yunohost command from the actionsmap.
Generates a bash completion file assuming the structure
`yunohost domain action`
`yunohost category action`
adds `--help` at the end if one presses [tab] again.
author: Christophe Vuillot
@ -15,18 +15,39 @@ THIS_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
ACTIONSMAP_FILE = THIS_SCRIPT_DIR + '/yunohost.yml'
BASH_COMPLETION_FILE = THIS_SCRIPT_DIR + '/../bash-completion.d/yunohost'
def get_dict_actions(OPTION_SUBTREE, category):
ACTIONS = [action for action in OPTION_SUBTREE[category]["actions"].keys()
if not action.startswith('_')]
ACTIONS_STR = '{}'.format(' '.join(ACTIONS))
DICT = { "actions_str": ACTIONS_STR }
return DICT
with open(ACTIONSMAP_FILE, 'r') as stream:
# Getting the dictionary containning what actions are possible per domain
# Getting the dictionary containning what actions are possible per category
OPTION_TREE = yaml.load(stream)
DOMAINS = [str for str in OPTION_TREE.keys() if not str.startswith('_')]
DOMAINS_STR = '"{}"'.format(' '.join(DOMAINS))
CATEGORY = [category for category in OPTION_TREE.keys() if not category.startswith('_')]
CATEGORY_STR = '{}'.format(' '.join(CATEGORY))
ACTIONS_DICT = {}
for domain in DOMAINS:
ACTIONS = [str for str in OPTION_TREE[domain]['actions'].keys()
if not str.startswith('_')]
ACTIONS_STR = '"{}"'.format(' '.join(ACTIONS))
ACTIONS_DICT[domain] = ACTIONS_STR
for category in CATEGORY:
ACTIONS_DICT[category] = get_dict_actions(OPTION_TREE, category)
ACTIONS_DICT[category]["subcategories"] = {}
ACTIONS_DICT[category]["subcategories_str"] = ""
if "subcategories" in OPTION_TREE[category].keys():
SUBCATEGORIES = [ subcategory for subcategory in OPTION_TREE[category]["subcategories"].keys() ]
SUBCATEGORIES_STR = '{}'.format(' '.join(SUBCATEGORIES))
ACTIONS_DICT[category]["subcategories_str"] = SUBCATEGORIES_STR
for subcategory in SUBCATEGORIES:
ACTIONS_DICT[category]["subcategories"][subcategory] = get_dict_actions(OPTION_TREE[category]["subcategories"], subcategory)
with open(BASH_COMPLETION_FILE, 'w') as generated_file:
@ -47,31 +68,49 @@ with open(ACTIONSMAP_FILE, 'r') as stream:
generated_file.write('\tnarg=${#COMP_WORDS[@]}\n\n')
generated_file.write('\t# the current word being typed\n')
generated_file.write('\tcur="${COMP_WORDS[COMP_CWORD]}"\n\n')
generated_file.write('\t# the last typed word\n')
generated_file.write('\tprev="${COMP_WORDS[COMP_CWORD-1]}"\n\n')
# If one is currently typing a domain then match with the domain list
generated_file.write('\t# If one is currently typing a domain,\n')
generated_file.write('\t# match with domains\n')
# If one is currently typing a category then match with the category list
generated_file.write('\t# If one is currently typing a category,\n')
generated_file.write('\t# match with categorys\n')
generated_file.write('\tif [[ $narg == 2 ]]; then\n')
generated_file.write('\t\topts={}\n'.format(DOMAINS_STR))
generated_file.write('\t\topts="{}"\n'.format(CATEGORY_STR))
generated_file.write('\tfi\n\n')
# If one is currently typing an action then match with the action list
# of the previously typed domain
generated_file.write('\t# If one already typed a domain,\n')
generated_file.write('\t# match the actions of that domain\n')
# of the previously typed category
generated_file.write('\t# If one already typed a category,\n')
generated_file.write('\t# match the actions or the subcategories of that category\n')
generated_file.write('\tif [[ $narg == 3 ]]; then\n')
for domain in DOMAINS:
generated_file.write('\t\tif [[ $prev == "{}" ]]; then\n'.format(domain))
generated_file.write('\t\t\topts={}\n'.format(ACTIONS_DICT[domain]))
generated_file.write('\t\t# the category typed\n')
generated_file.write('\t\tcategory="${COMP_WORDS[1]}"\n\n')
for category in CATEGORY:
generated_file.write('\t\tif [[ $category == "{}" ]]; then\n'.format(category))
generated_file.write('\t\t\topts="{} {}"\n'.format(ACTIONS_DICT[category]["actions_str"], ACTIONS_DICT[category]["subcategories_str"]))
generated_file.write('\t\tfi\n')
generated_file.write('\tfi\n\n')
# If both domain and action have been typed or the domain
generated_file.write('\t# If one already typed an action or a subcategory,\n')
generated_file.write('\t# match the actions of that subcategory\n')
generated_file.write('\tif [[ $narg == 4 ]]; then\n')
generated_file.write('\t\t# the category typed\n')
generated_file.write('\t\tcategory="${COMP_WORDS[1]}"\n\n')
generated_file.write('\t\t# the action or the subcategory typed\n')
generated_file.write('\t\taction_or_subcategory="${COMP_WORDS[2]}"\n\n')
for category in CATEGORY:
if len(ACTIONS_DICT[category]["subcategories"]):
generated_file.write('\t\tif [[ $category == "{}" ]]; then\n'.format(category))
for subcategory in ACTIONS_DICT[category]["subcategories"]:
generated_file.write('\t\t\tif [[ $action_or_subcategory == "{}" ]]; then\n'.format(subcategory))
generated_file.write('\t\t\t\topts="{}"\n'.format(ACTIONS_DICT[category]["subcategories"][subcategory]["actions_str"]))
generated_file.write('\t\t\tfi\n')
generated_file.write('\t\tfi\n')
generated_file.write('\tfi\n\n')
# If both category and action have been typed or the category
# was not recognized propose --help (only once)
generated_file.write('\t# If no options were found propose --help\n')
generated_file.write('\tif [ -z "$opts" ]; then\n')
generated_file.write('\t\tprev="${COMP_WORDS[COMP_CWORD-1]}"\n\n')
generated_file.write('\t\tif [[ $prev != "--help" ]]; then\n')
generated_file.write('\t\t\topts=( --help )\n')
generated_file.write('\t\tfi\n')

View file

@ -5,6 +5,7 @@
# [internal]
#
# usage: ynh_wait_dpkg_free
# | exit: Return 1 if dpkg is broken
#
# Requires YunoHost version 3.3.1 or higher.
ynh_wait_dpkg_free() {
@ -13,7 +14,7 @@ ynh_wait_dpkg_free() {
for try in `seq 1 17`
do
# Check if /var/lib/dpkg/lock is used by another process
if sudo lsof /var/lib/dpkg/lock > /dev/null
if lsof /var/lib/dpkg/lock > /dev/null
then
echo "apt is already in use..."
# Sleep an exponential time at each round
@ -27,7 +28,7 @@ ynh_wait_dpkg_free() {
while read dpkg_file <&9
do
# Check if the name of this file contains only numbers.
if echo "$dpkg_file" | grep -Pq "^[[:digit:]]+$"
if echo "$dpkg_file" | grep --perl-regexp --quiet "^[[:digit:]]+$"
then
# If so, that a remaining of dpkg.
ynh_print_err "E: dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem."
@ -45,20 +46,20 @@ ynh_wait_dpkg_free() {
# example: ynh_package_is_installed --package=yunohost && echo "ok"
#
# usage: ynh_package_is_installed --package=name
# | arg: -p, --package - the package name to check
# | arg: -p, --package= - the package name to check
#
# Requires YunoHost version 2.2.4 or higher.
ynh_package_is_installed() {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=package= )
local -A args_array=( [p]=package= )
local package
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_wait_dpkg_free
dpkg-query -W -f '${Status}' "$package" 2>/dev/null \
| grep -c "ok installed" &>/dev/null
dpkg-query --show --showformat='${Status}' "$package" 2>/dev/null \
| grep --count "ok installed" &>/dev/null
}
# Get the version of an installed package
@ -66,20 +67,21 @@ ynh_package_is_installed() {
# example: version=$(ynh_package_version --package=yunohost)
#
# usage: ynh_package_version --package=name
# | arg: -p, --package - the package name to get version
# | arg: -p, --package= - the package name to get version
# | ret: the version or an empty string
#
# Requires YunoHost version 2.2.4 or higher.
ynh_package_version() {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=package= )
local -A args_array=( [p]=package= )
local package
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ynh_package_is_installed "$package"; then
dpkg-query -W -f '${Version}' "$package" 2>/dev/null
if ynh_package_is_installed "$package"
then
dpkg-query --show --showformat='${Version}' "$package" 2>/dev/null
else
echo ''
fi
@ -94,7 +96,7 @@ ynh_package_version() {
# Requires YunoHost version 2.4.0.3 or higher.
ynh_apt() {
ynh_wait_dpkg_free
DEBIAN_FRONTEND=noninteractive apt-get -y $@
LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get --assume-yes $@
}
# Update package index files
@ -113,8 +115,8 @@ ynh_package_update() {
#
# Requires YunoHost version 2.2.4 or higher.
ynh_package_install() {
ynh_apt --no-remove -o Dpkg::Options::=--force-confdef \
-o Dpkg::Options::=--force-confold install $@
ynh_apt --no-remove --option Dpkg::Options::=--force-confdef \
--option Dpkg::Options::=--force-confold install $@
}
# Remove package(s)
@ -163,8 +165,8 @@ ynh_package_install_from_equivs () {
local controlfile=$1
# retrieve package information
local pkgname=$(grep '^Package: ' $controlfile | cut -d' ' -f 2) # Retrieve the name of the debian package
local pkgversion=$(grep '^Version: ' $controlfile | cut -d' ' -f 2) # And its version number
local pkgname=$(grep '^Package: ' $controlfile | cut --delimiter=' ' --fields=2) # Retrieve the name of the debian package
local pkgversion=$(grep '^Version: ' $controlfile | cut --delimiter=' ' --fields=2) # And its version number
[[ -z "$pkgname" || -z "$pkgversion" ]] \
&& ynh_die --message="Invalid control file" # Check if this 2 variables aren't empty.
@ -172,7 +174,7 @@ ynh_package_install_from_equivs () {
ynh_package_update
# Build and install the package
local TMPDIR=$(mktemp -d)
local TMPDIR=$(mktemp --directory)
# Force the compatibility level at 10, levels below are deprecated
echo 10 > /usr/share/equivs/template/debian/compat
@ -184,10 +186,22 @@ ynh_package_install_from_equivs () {
ynh_wait_dpkg_free
cp "$controlfile" "${TMPDIR}/control"
(cd "$TMPDIR"
equivs-build ./control 1> /dev/null
dpkg --force-depends -i "./${pkgname}_${pkgversion}_all.deb" 2>&1)
ynh_package_install -f || ynh_die --message="Unable to install dependencies"
[[ -n "$TMPDIR" ]] && rm -rf $TMPDIR # Remove the temp dir.
LC_ALL=C equivs-build ./control 1> /dev/null
dpkg --force-depends --install "./${pkgname}_${pkgversion}_all.deb" 2>&1)
# If install fails we use "apt-get check" to try to debug and diagnose possible unmet dependencies
# Note the use of { } which allows to group commands without starting a subshell (otherwise the ynh_die wouldn't exit the current shell).
# Be careful with the syntax : the semicolon + space at the end is important!
ynh_package_install --fix-broken || \
{ # If the installation failed
# Get the list of dependencies from the deb
local dependencies="$(dpkg --info "$TMPDIR/${pkgname}_${pkgversion}_all.deb" | grep Depends | \
sed 's/^ Depends: //' | sed 's/,//g')"
# Fake an install of those dependencies to see the errors
# The sed command here is, Print only from '--fix-broken' to the end.
ynh_package_install $dependencies --dry-run | sed --quiet '/--fix-broken/,$p' >&2
ynh_die --message="Unable to install dependencies"; }
[[ -n "$TMPDIR" ]] && rm --recursive --force $TMPDIR # Remove the temp dir.
# check if the package is actually installed
ynh_package_is_installed "$pkgname"
@ -205,19 +219,58 @@ ynh_package_install_from_equivs () {
# Requires YunoHost version 2.6.4 or higher.
ynh_install_app_dependencies () {
local dependencies=$@
local dependencies=${dependencies// /, }
# Add a comma for each space between packages. But not add a comma if the space separate a version specification. (See below)
dependencies="$(echo "$dependencies" | sed 's/\([^\<=\>]\)\ \([^(]\)/\1, \2/g')"
local dependencies=${dependencies//|/ | }
local manifest_path="../manifest.json"
if [ ! -e "$manifest_path" ]; then
manifest_path="../settings/manifest.json" # Into the restore script, the manifest is not at the same place
manifest_path="../settings/manifest.json" # Into the restore script, the manifest is not at the same place
fi
local version=$(grep '\"version\": ' "$manifest_path" | cut -d '"' -f 4) # Retrieve the version number in the manifest file.
local version=$(grep '\"version\": ' "$manifest_path" | cut --delimiter='"' --fields=4) # Retrieve the version number in the manifest file.
if [ ${#version} -eq 0 ]; then
version="1.0"
fi
local dep_app=${app//_/-} # Replace all '_' by '-'
# Handle specific versions
if [[ "$dependencies" =~ [\<=\>] ]]
then
# Replace version specifications by relationships syntax
# https://www.debian.org/doc/debian-policy/ch-relationships.html
# Sed clarification
# [^(\<=\>] ignore if it begins by ( or < = >. To not apply twice.
# [\<=\>] matches < = or >
# \+ matches one or more occurence of the previous characters, for >= or >>.
# [^,]\+ matches all characters except ','
# Ex: 'package>=1.0' will be replaced by 'package (>= 1.0)'
dependencies="$(echo "$dependencies" | sed 's/\([^(\<=\>]\)\([\<=\>]\+\)\([^,]\+\)/\1 (\2 \3)/g')"
fi
#
# Epic ugly hack to fix the goddamn dependency nightmare of sury
# Sponsored by the "Djeezusse Fokin Kraiste Why Do Adminsys Has To Be So Fucking Complicated I Should Go Grow Potatoes Instead Of This Shit" collective
# https://github.com/YunoHost/issues/issues/1407
#
# If we require to install php dependency
if echo $dependencies | grep --quiet 'php'
then
# 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*
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
# Pin this sury repository to prevent sury of doing shit
ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version
ynh_pin_repo --package="php${$YNH_DEFAULT_PHP_VERSION}*" --pin="origin \"packages.sury.org\"" --priority=600 --name=extra_php_version --append
fi
fi
fi
cat > /tmp/${dep_app}-ynh-deps.control << EOF # Make a control file for equivs-build
Section: misc
Priority: optional
@ -234,6 +287,38 @@ EOF
ynh_app_setting_set --app=$app --key=apt_dependencies --value="$dependencies"
}
# Add dependencies to install with ynh_install_app_dependencies
#
# usage: ynh_add_app_dependencies --package=phpversion [--replace]
# | arg: -p, --package= - Packages to add as dependencies for the app.
# | arg: -r, --replace - Replace dependencies instead of adding to existing ones.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_add_app_dependencies () {
# Declare an array to define the options of this helper.
local legacy_args=pr
local -A args_array=( [p]=package= [r]=replace)
local package
local replace
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
replace=${replace:-0}
local current_dependencies=""
if [ $replace -eq 0 ]
then
local dep_app=${app//_/-} # Replace all '_' by '-'
if ynh_package_is_installed --package="${dep_app}-ynh-deps"
then
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${dep_app}-ynh-deps) "
fi
current_dependencies=${current_dependencies// | /|}
fi
ynh_install_app_dependencies "${current_dependencies}${package}"
}
# Remove fake package and its dependencies
#
# Dependencies will removed only if no other package need them.
@ -245,3 +330,231 @@ ynh_remove_app_dependencies () {
local dep_app=${app//_/-} # Replace all '_' by '-'
ynh_package_autopurge ${dep_app}-ynh-deps # Remove the fake package and its dependencies if they not still used.
}
#=================================================
# Install packages from an extra repository properly.
#
# usage: ynh_install_extra_app_dependencies --repo="repo" --package="dep1 dep2" [--key=key_url] [--name=name]
# | arg: -r, --repo= - Complete url of the extra repository.
# | arg: -p, --package= - The packages to install from this extra repository
# | arg: -k, --key= - url to get the public key.
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_install_extra_app_dependencies () {
# Declare an array to define the options of this helper.
local legacy_args=rpkn
local -A args_array=( [r]=repo= [p]=package= [k]=key= [n]=name= )
local repo
local package
local key
local name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
key=${key:-}
# Set a key only if asked
if [ -n "$key" ]
then
key="--key=$key"
fi
# Add an extra repository for those packages
ynh_install_extra_repo --repo="$repo" $key --priority=995 --name=$name
# Install requested dependencies from this extra repository.
ynh_add_app_dependencies --package="$package"
# Remove this extra repository after packages are installed
ynh_remove_extra_repo --name=$app
}
# Add an extra repository correctly, pin it and get the key.
#
# [internal]
#
# usage: ynh_install_extra_repo --repo="repo" [--key=key_url] [--priority=priority_value] [--name=name] [--append]
# | arg: -r, --repo= - Complete url of the extra repository.
# | arg: -k, --key= - url to get the public key.
# | arg: -p, --priority= - Priority for the pin
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_install_extra_repo () {
# Declare an array to define the options of this helper.
local legacy_args=rkpna
local -A args_array=( [r]=repo= [k]=key= [p]=priority= [n]=name= [a]=append )
local repo
local key
local priority
local name
local append
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
append=${append:-0}
key=${key:-}
priority=${priority:-}
if [ $append -eq 1 ]
then
append="--append"
wget_append="tee --append"
else
append=""
wget_append="tee"
fi
# Split the repository into uri, suite and components.
# Remove "deb " at the beginning of the repo.
repo="${repo#deb }"
# Get the uri
local uri="$(echo "$repo" | awk '{ print $1 }')"
# Get the suite
local suite="$(echo "$repo" | awk '{ print $2 }')"
# Get the components
local component="${repo##$uri $suite }"
# Add the repository into sources.list.d
ynh_add_repo --uri="$uri" --suite="$suite" --component="$component" --name="$name" $append
# Pin the new repo with the default priority, so it won't be used for upgrades.
# Build $pin from the uri without http and any sub path
local pin="${uri#*://}"
pin="${pin%%/*}"
# Set a priority only if asked
if [ -n "$priority" ]
then
priority="--priority=$priority"
fi
ynh_pin_repo --package="*" --pin="origin \"$pin\"" $priority --name="$name" $append
# Get the public key for the repo
if [ -n "$key" ]
then
mkdir --parents "/etc/apt/trusted.gpg.d"
wget --quiet "$key" --output-document=- | gpg --dearmor | $wget_append /etc/apt/trusted.gpg.d/$name.gpg > /dev/null
fi
# Update the list of package with the new repo
ynh_package_update
}
# Remove an extra repository and the assiociated configuration.
#
# [internal]
#
# usage: ynh_remove_extra_repo [--name=name]
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_remove_extra_repo () {
# Declare an array to define the options of this helper.
local legacy_args=n
local -A args_array=( [n]=name= )
local name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
ynh_secure_remove "/etc/apt/sources.list.d/$name.list"
ynh_secure_remove "/etc/apt/preferences.d/$name"
ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.gpg"
ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.asc"
# Update the list of package to exclude the old repo
ynh_package_update
}
# Add a repository.
#
# [internal]
#
# usage: ynh_add_repo --uri=uri --suite=suite --component=component [--name=name] [--append]
# | arg: -u, --uri= - Uri of the repository.
# | arg: -s, --suite= - Suite of the repository.
# | arg: -c, --component= - Component of the repository.
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files.
#
# Example for a repo like deb http://forge.yunohost.org/debian/ stretch stable
# uri suite component
# ynh_add_repo --uri=http://forge.yunohost.org/debian/ --suite=stretch --component=stable
#
# Requires YunoHost version 3.8.1 or higher.
ynh_add_repo () {
# Declare an array to define the options of this helper.
local legacy_args=uscna
local -A args_array=( [u]=uri= [s]=suite= [c]=component= [n]=name= [a]=append )
local uri
local suite
local component
local name
local append
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
name="${name:-$app}"
append=${append:-0}
if [ $append -eq 1 ]
then
append="tee --append"
else
append="tee"
fi
mkdir --parents "/etc/apt/sources.list.d"
# Add the new repo in sources.list.d
echo "deb $uri $suite $component" \
| $append "/etc/apt/sources.list.d/$name.list"
}
# Pin a repository.
#
# [internal]
#
# usage: ynh_pin_repo --package=packages --pin=pin_filter [--priority=priority_value] [--name=name] [--append]
# | arg: -p, --package= - Packages concerned by the pin. Or all, *.
# | arg: -i, --pin= - Filter for the pin.
# | arg: -p, --priority= - Priority for the pin
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files.
#
# See https://manpages.debian.org/stretch/apt/apt_preferences.5.en.html#How_APT_Interprets_Priorities for information about pinning.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_pin_repo () {
# Declare an array to define the options of this helper.
local legacy_args=pirna
local -A args_array=( [p]=package= [i]=pin= [r]=priority= [n]=name= [a]=append )
local package
local pin
local priority
local name
local append
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
package="${package:-*}"
priority=${priority:-50}
name="${name:-$app}"
append=${append:-0}
if [ $append -eq 1 ]
then
append="tee --append"
else
append="tee"
fi
mkdir --parents "/etc/apt/preferences.d"
echo "Package: $package
Pin: $pin
Pin-Priority: $priority
" \
| $append "/etc/apt/preferences.d/$name"
}

View file

@ -4,6 +4,13 @@ CAN_BIND=${CAN_BIND:-1}
# Add a file or a directory to the list of paths to backup
#
# usage: ynh_backup --src_path=src_path [--dest_path=dest_path] [--is_big] [--not_mandatory]
# | arg: -s, --src_path= - file or directory to bind or symlink or copy. it shouldn't be in the backup dir.
# | arg: -d, --dest_path= - destination file or directory inside the backup dir
# | arg: -b, --is_big - Indicate data are big (mail, video, image ...)
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the backup can ignore it.
# | arg: arg - Deprecated arg
#
# This helper can be used both in a system backup hook, and in an app backup script
#
# Details: ynh_backup writes SRC and the relative DEST into a CSV file. And it
@ -11,13 +18,6 @@ CAN_BIND=${CAN_BIND:-1}
#
# If DEST is ended by a slash it complete this path with the basename of SRC.
#
# usage: ynh_backup --src_path=src_path [--dest_path=dest_path] [--is_big] [--not_mandatory]
# | arg: -s, --src_path - file or directory to bind or symlink or copy. it shouldn't be in the backup dir.
# | arg: -d, --dest_path - destination file or directory inside the backup dir
# | arg: -b, --is_big - Indicate data are big (mail, video, image ...)
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the backup can ignore it.
# | arg: arg - Deprecated arg
#
# Example in the context of a wordpress app
#
# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf"
@ -41,21 +41,22 @@ CAN_BIND=${CAN_BIND:-1}
# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf/$app.conf"
#
# Requires YunoHost version 2.4.0 or higher.
# Requires YunoHost version 3.5.0 or higher for the argument --not_mandatory
ynh_backup() {
# TODO find a way to avoid injection by file strange naming !
# Declare an array to define the options of this helper.
local legacy_args=sdbm
declare -Ar args_array=( [s]=src_path= [d]=dest_path= [b]=is_big [m]=not_mandatory )
local -A args_array=( [s]=src_path= [d]=dest_path= [b]=is_big [m]=not_mandatory )
local src_path
local dest_path
local is_big
local not_mandatory
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local dest_path="${dest_path:-}"
local is_big="${is_big:-0}"
local not_mandatory="${not_mandatory:-0}"
dest_path="${dest_path:-}"
is_big="${is_big:-0}"
not_mandatory="${not_mandatory:-0}"
BACKUP_CORE_ONLY=${BACKUP_CORE_ONLY:-0}
test -n "${app:-}" && do_not_backup_data=$(ynh_app_setting_get --app=$app --key=do_not_backup_data)
@ -64,7 +65,8 @@ ynh_backup() {
# don't backup big data items
if [ $is_big -eq 1 ] && ( [ ${do_not_backup_data:-0} -eq 1 ] || [ $BACKUP_CORE_ONLY -eq 1 ] )
then
if [ $BACKUP_CORE_ONLY -eq 1 ]; then
if [ $BACKUP_CORE_ONLY -eq 1 ]
then
ynh_print_warn --message="$src_path will not be saved, because 'BACKUP_CORE_ONLY' is set."
else
ynh_print_warn --message="$src_path will not be saved, because 'do_not_backup_data' is set."
@ -76,22 +78,23 @@ ynh_backup() {
# Format correctly source and destination paths
# ==============================================================================
# Be sure the source path is not empty
[[ -e "${src_path}" ]] || {
if [ ! -e "$src_path" ]
then
ynh_print_warn --message="Source path '${src_path}' does not exist"
if [ "$not_mandatory" == "0" ]
then
# This is a temporary fix for fail2ban config files missing after the migration to stretch.
if echo "${src_path}" | grep --quiet "/etc/fail2ban"
then
touch "${src_path}"
ynh_print_info --message="The missing file will be replaced by a dummy one for the backup !!!"
else
return 1
fi
# This is a temporary fix for fail2ban config files missing after the migration to stretch.
if echo "${src_path}" | grep --quiet "/etc/fail2ban"
then
touch "${src_path}"
ynh_print_info --message="The missing file will be replaced by a dummy one for the backup !!!"
else
return 1
fi
else
return 0
return 0
fi
}
fi
# Transform the source path as an absolute path
# If it's a dir remove the ending /
@ -100,12 +103,13 @@ ynh_backup() {
# If there is no destination path, initialize it with the source path
# relative to "/".
# eg: src_path=/etc/yunohost -> dest_path=etc/yunohost
if [[ -z "$dest_path" ]]; then
if [[ -z "$dest_path" ]]
then
dest_path="${src_path#/}"
else
if [[ "${dest_path:0:1}" == "/" ]]; then
if [[ "${dest_path:0:1}" == "/" ]]
then
# If the destination path is an absolute path, transform it as a path
# relative to the current working directory ($YNH_CWD)
@ -117,20 +121,23 @@ ynh_backup() {
dest_path="${dest_path#$YNH_CWD/}"
# Case where $2 is an absolute dir but doesn't begin with $YNH_CWD
[[ "${dest_path:0:1}" == "/" ]] \
&& dest_path="${dest_path#/}"
if [[ "${dest_path:0:1}" == "/" ]]; then
dest_path="${dest_path#/}"
fi
fi
# Complete dest_path if ended by a /
[[ "${dest_path: -1}" == "/" ]] \
&& dest_path="${dest_path}/$(basename $src_path)"
if [[ "${dest_path: -1}" == "/" ]]; then
dest_path="${dest_path}/$(basename $src_path)"
fi
fi
# Check if dest_path already exists in tmp archive
[[ ! -e "${dest_path}" ]] || {
if [[ -e "${dest_path}" ]]
then
ynh_print_err --message="Destination path '${dest_path}' already exist"
return 1
}
fi
# Add the relative current working directory to the destination path
local rel_dir="${YNH_CWD#$YNH_BACKUP_DIR}"
@ -142,15 +149,15 @@ ynh_backup() {
# ==============================================================================
# Write file to backup into backup_list
# ==============================================================================
local src=$(echo "${src_path}" | sed -r 's/"/\"\"/g')
local dest=$(echo "${dest_path}" | sed -r 's/"/\"\"/g')
local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g')
local dest=$(echo "${dest_path}" | sed --regexp-extended 's/"/\"\"/g')
echo "\"${src}\",\"${dest}\"" >> "${YNH_BACKUP_CSV}"
# ==============================================================================
# Create the parent dir of the destination path
# It's for retro compatibility, some script consider ynh_backup creates this dir
mkdir -p $(dirname "$YNH_BACKUP_DIR/${dest_path}")
mkdir --parents $(dirname "$YNH_BACKUP_DIR/${dest_path}")
}
# Restore all files that were previously backuped in a core backup script or app backup script
@ -164,10 +171,11 @@ ynh_restore () {
REL_DIR="${REL_DIR%/}/"
# For each destination path begining by $REL_DIR
cat ${YNH_BACKUP_CSV} | tr -d $'\r' | grep -ohP "^\".*\",\"$REL_DIR.*\"$" | \
while read line; do
local ORIGIN_PATH=$(echo "$line" | grep -ohP "^\"\K.*(?=\",\".*\"$)")
local ARCHIVE_PATH=$(echo "$line" | grep -ohP "^\".*\",\"$REL_DIR\K.*(?=\"$)")
cat ${YNH_BACKUP_CSV} | tr --delete $'\r' | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR.*\"$" | \
while read line
do
local ORIGIN_PATH=$(echo "$line" | grep --only-matching --no-filename --perl-regexp "^\"\K.*(?=\",\".*\"$)")
local ARCHIVE_PATH=$(echo "$line" | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR\K.*(?=\"$)")
ynh_restore_file --origin_path="$ARCHIVE_PATH" --dest_path="$ORIGIN_PATH"
done
}
@ -179,7 +187,7 @@ ynh_restore () {
# usage: _get_archive_path ORIGIN_PATH
_get_archive_path () {
# For security reasons we use csv python library to read the CSV
sudo python -c "
python -c "
import sys
import csv
with open(sys.argv[1], 'r') as backup_file:
@ -199,9 +207,9 @@ with open(sys.argv[1], 'r') as backup_file:
# the right place.
#
# usage: ynh_restore_file --origin_path=origin_path [--dest_path=dest_path] [--not_mandatory]
# | arg: -o, --origin_path - Path where was located the file or the directory before to be backuped or relative path to $YNH_CWD where it is located in the backup archive
# | arg: -d, --dest_path - Path where restore the file or the dir, if unspecified, the destination will be ORIGIN_PATH or if the ORIGIN_PATH doesn't exist in the archive, the destination will be searched into backup.csv
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the restore process can ignore it.
# | arg: -o, --origin_path= - Path where was located the file or the directory before to be backuped or relative path to $YNH_CWD where it is located in the backup archive
# | arg: -d, --dest_path= - Path where restore the file or the dir, if unspecified, the destination will be ORIGIN_PATH or if the ORIGIN_PATH doesn't exist in the archive, the destination will be searched into backup.csv
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the restore process can ignore it.
#
# examples:
# ynh_restore_file "/etc/nginx/conf.d/$domain.d/$app.conf"
@ -217,24 +225,25 @@ with open(sys.argv[1], 'r') as backup_file:
# /etc/nginx/conf.d/$domain.d/$app.conf
#
# Requires YunoHost version 2.6.4 or higher.
# Requires YunoHost version 3.5.0 or higher for the argument --not_mandatory
ynh_restore_file () {
# Declare an array to define the options of this helper.
local legacy_args=odm
declare -Ar args_array=( [o]=origin_path= [d]=dest_path= [m]=not_mandatory )
local -A args_array=( [o]=origin_path= [d]=dest_path= [m]=not_mandatory )
local origin_path
local archive_path
local dest_path
local not_mandatory
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local origin_path="/${origin_path#/}"
local archive_path="$YNH_CWD${origin_path}"
origin_path="/${origin_path#/}"
# Default value for dest_path = /$origin_path
local dest_path="${dest_path:-$origin_path}"
local not_mandatory="${not_mandatory:-0}"
dest_path="${dest_path:-$origin_path}"
not_mandatory="${not_mandatory:-0}"
local archive_path="$YNH_CWD${origin_path}"
# If archive_path doesn't exist, search for a corresponding path in CSV
if [ ! -d "$archive_path" ] && [ ! -f "$archive_path" ] && [ ! -L "$archive_path" ]; then
if [ ! -d "$archive_path" ] && [ ! -f "$archive_path" ] && [ ! -L "$archive_path" ]
then
if [ "$not_mandatory" == "0" ]
then
archive_path="$YNH_BACKUP_DIR/$(_get_archive_path \"$origin_path\")"
@ -247,10 +256,10 @@ ynh_restore_file () {
if [[ -e "${dest_path}" ]]
then
# Check if the file/dir size is less than 500 Mo
if [[ $(du -sb ${dest_path} | cut -d"/" -f1) -le "500000000" ]]
if [[ $(du --summarize --bytes ${dest_path} | cut --delimiter="/" --fields=1) -le "500000000" ]]
then
local backup_file="/home/yunohost.conf/backup/${dest_path}.backup.$(date '+%Y%m%d.%H%M%S')"
mkdir -p "$(dirname "$backup_file")"
mkdir --parents "$(dirname "$backup_file")"
mv "${dest_path}" "$backup_file" # Move the current file or directory
else
ynh_secure_remove --file=${dest_path}
@ -258,15 +267,17 @@ ynh_restore_file () {
fi
# Restore origin_path into dest_path
mkdir -p $(dirname "$dest_path")
mkdir --parents $(dirname "$dest_path")
# Do a copy if it's just a mounting point
if mountpoint -q $YNH_BACKUP_DIR; then
if [[ -d "${archive_path}" ]]; then
if mountpoint --quiet $YNH_BACKUP_DIR
then
if [[ -d "${archive_path}" ]]
then
archive_path="${archive_path}/."
mkdir -p "$dest_path"
mkdir --parents "$dest_path"
fi
cp -a "$archive_path" "${dest_path}"
cp --archive "$archive_path" "${dest_path}"
# Do a move if YNH_BACKUP_DIR is already a copy
else
mv "$archive_path" "${dest_path}"
@ -287,22 +298,22 @@ ynh_bind_or_cp() {
# Calculate and store a file checksum into the app settings
#
# $app should be defined when calling this helper
#
# usage: ynh_store_file_checksum --file=file
# | arg: -f, --file - The file on which the checksum will performed, then stored.
# | arg: -f, --file= - The file on which the checksum will performed, then stored.
#
# $app should be defined when calling this helper
#
# Requires YunoHost version 2.6.4 or higher.
ynh_store_file_checksum () {
# Declare an array to define the options of this helper.
local legacy_args=f
declare -Ar args_array=( [f]=file= )
local -A args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
ynh_app_setting_set --app=$app --key=$checksum_setting_name --value=$(sudo md5sum "$file" | cut -d' ' -f1)
ynh_app_setting_set --app=$app --key=$checksum_setting_name --value=$(md5sum "$file" | cut --delimiter=' ' --fields=1)
# If backup_file_checksum isn't empty, ynh_backup_if_checksum_is_different has made a backup
if [ -n "${backup_file_checksum-}" ]
@ -321,14 +332,14 @@ ynh_store_file_checksum () {
# modified config files.
#
# usage: ynh_backup_if_checksum_is_different --file=file
# | arg: -f, --file - The file on which the checksum test will be perfomed.
# | arg: -f, --file= - The file on which the checksum test will be perfomed.
# | ret: the name of a backup file, or nothing
#
# Requires YunoHost version 2.6.4 or higher.
ynh_backup_if_checksum_is_different () {
# Declare an array to define the options of this helper.
local legacy_args=f
declare -Ar args_array=( [f]=file= )
local -A args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -339,11 +350,11 @@ ynh_backup_if_checksum_is_different () {
backup_file_checksum=""
if [ -n "$checksum_value" ]
then # Proceed only if a value was stored into the app settings
if [ -e $file ] && ! echo "$checksum_value $file" | sudo md5sum -c --status
if [ -e $file ] && ! echo "$checksum_value $file" | md5sum --check --status
then # If the checksum is now different
backup_file_checksum="/home/yunohost.conf/backup/$file.backup.$(date '+%Y%m%d.%H%M%S')"
sudo mkdir -p "$(dirname "$backup_file_checksum")"
sudo cp -a "$file" "$backup_file_checksum" # Backup the current file
mkdir --parents "$(dirname "$backup_file_checksum")"
cp --archive "$file" "$backup_file_checksum" # Backup the current file
ynh_print_warn "File $file has been manually modified since the installation or last upgrade. So it has been duplicated in $backup_file_checksum"
echo "$backup_file_checksum" # Return the name of the backup file
fi
@ -352,16 +363,16 @@ ynh_backup_if_checksum_is_different () {
# Delete a file checksum from the app settings
#
# $app should be defined when calling this helper
# usage: ynh_delete_file_checksum --file=file
# | arg: -f, --file= - The file for which the checksum will be deleted
#
# usage: ynh_remove_file_checksum file
# | arg: -f, --file= - The file for which the checksum will be deleted
# $app should be defined when calling this helper
#
# Requires YunoHost version 3.3.1 or higher.
ynh_delete_file_checksum () {
# Declare an array to define the options of this helper.
local legacy_args=f
declare -Ar args_array=( [f]=file= )
local -A args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -373,11 +384,11 @@ ynh_delete_file_checksum () {
# Make a backup in case of failed upgrade
#
# usage:
# ynh_backup_before_upgrade
# ynh_clean_setup () {
# ynh_restore_upgradebackup
# }
# ynh_abort_if_errors
# ynh_backup_before_upgrade
# ynh_clean_setup () {
# ynh_restore_upgradebackup
# }
# ynh_abort_if_errors
#
# Requires YunoHost version 2.7.2 or higher.
ynh_backup_before_upgrade () {
@ -394,7 +405,7 @@ ynh_backup_before_upgrade () {
if [ "$NO_BACKUP_UPGRADE" -eq 0 ]
then
# Check if a backup already exists with the prefix 1
if sudo yunohost backup list | grep -q $app_bck-pre-upgrade1
if yunohost backup list | grep --quiet $app_bck-pre-upgrade1
then
# Prefix becomes 2 to preserve the previous backup
backup_number=2
@ -402,14 +413,14 @@ ynh_backup_before_upgrade () {
fi
# Create backup
sudo BACKUP_CORE_ONLY=1 yunohost backup create --apps $app --name $app_bck-pre-upgrade$backup_number --debug
BACKUP_CORE_ONLY=1 yunohost backup create --apps $app --name $app_bck-pre-upgrade$backup_number --debug
if [ "$?" -eq 0 ]
then
# If the backup succeeded, remove the previous backup
if sudo yunohost backup list | grep -q $app_bck-pre-upgrade$old_backup_number
if yunohost backup list | grep --quiet $app_bck-pre-upgrade$old_backup_number
then
# Remove the previous backup only if it exists
sudo yunohost backup delete $app_bck-pre-upgrade$old_backup_number > /dev/null
yunohost backup delete $app_bck-pre-upgrade$old_backup_number > /dev/null
fi
else
ynh_die --message="Backup failed, the upgrade process was aborted."
@ -422,11 +433,11 @@ ynh_backup_before_upgrade () {
# Restore a previous backup if the upgrade process failed
#
# usage:
# ynh_backup_before_upgrade
# ynh_clean_setup () {
# ynh_restore_upgradebackup
# }
# ynh_abort_if_errors
# ynh_backup_before_upgrade
# ynh_clean_setup () {
# ynh_restore_upgradebackup
# }
# ynh_abort_if_errors
#
# Requires YunoHost version 2.7.2 or higher.
ynh_restore_upgradebackup () {
@ -438,12 +449,12 @@ ynh_restore_upgradebackup () {
if [ "$NO_BACKUP_UPGRADE" -eq 0 ]
then
# Check if an existing backup can be found before removing and restoring the application.
if sudo yunohost backup list | grep -q $app_bck-pre-upgrade$backup_number
if yunohost backup list | grep --quiet $app_bck-pre-upgrade$backup_number
then
# Remove the application then restore it
sudo yunohost app remove $app
yunohost app remove $app
# Restore the backup
sudo yunohost backup restore $app_bck-pre-upgrade$backup_number --apps $app --force --debug
yunohost backup restore $app_bck-pre-upgrade$backup_number --apps $app --force --debug
ynh_die --message="The app was restored to the way it was before the failed upgrade."
fi
else

View file

@ -63,52 +63,54 @@
#
# Requires YunoHost version 3.5.0 or higher.
ynh_add_fail2ban_config () {
# Declare an array to define the options of this helper.
local legacy_args=lrmptv
declare -Ar args_array=( [l]=logpath= [r]=failregex= [m]=max_retry= [p]=ports= [t]=use_template [v]=others_var=)
local logpath
local failregex
local max_retry
local ports
local others_var
local use_template
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
use_template="${use_template:-0}"
max_retry=${max_retry:-3}
ports=${ports:-http,https}
# Declare an array to define the options of this helper.
local legacy_args=lrmptv
local -A args_array=( [l]=logpath= [r]=failregex= [m]=max_retry= [p]=ports= [t]=use_template [v]=others_var=)
local logpath
local failregex
local max_retry
local ports
local others_var
local use_template
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
max_retry=${max_retry:-3}
ports=${ports:-http,https}
others_var=${others_var:-}
use_template="${use_template:-0}"
finalfail2banjailconf="/etc/fail2ban/jail.d/$app.conf"
finalfail2banfilterconf="/etc/fail2ban/filter.d/$app.conf"
ynh_backup_if_checksum_is_different "$finalfail2banjailconf"
ynh_backup_if_checksum_is_different "$finalfail2banfilterconf"
finalfail2banjailconf="/etc/fail2ban/jail.d/$app.conf"
finalfail2banfilterconf="/etc/fail2ban/filter.d/$app.conf"
ynh_backup_if_checksum_is_different "$finalfail2banjailconf"
ynh_backup_if_checksum_is_different "$finalfail2banfilterconf"
if [ $use_template -eq 1 ]
then
# Usage 2, templates
cp ../conf/f2b_jail.conf $finalfail2banjailconf
cp ../conf/f2b_filter.conf $finalfail2banfilterconf
if [ -n "${app:-}" ]
if [ $use_template -eq 1 ]
then
ynh_replace_string "__APP__" "$app" "$finalfail2banjailconf"
ynh_replace_string "__APP__" "$app" "$finalfail2banfilterconf"
fi
# Usage 2, templates
cp ../conf/f2b_jail.conf $finalfail2banjailconf
cp ../conf/f2b_filter.conf $finalfail2banfilterconf
# Replace all other variable given as arguments
for var_to_replace in ${others_var:-}; do
# ${var_to_replace^^} make the content of the variable on upper-cases
# ${!var_to_replace} get the content of the variable named $var_to_replace
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banjailconf"
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banfilterconf"
done
if [ -n "${app:-}" ]
then
ynh_replace_string "__APP__" "$app" "$finalfail2banjailconf"
ynh_replace_string "__APP__" "$app" "$finalfail2banfilterconf"
fi
else
# Usage 1, no template. Build a config file from scratch.
test -n "$logpath" || ynh_die "ynh_add_fail2ban_config expects a logfile path as first argument and received nothing."
test -n "$failregex" || ynh_die "ynh_add_fail2ban_config expects a failure regex as second argument and received nothing."
# Replace all other variable given as arguments
for var_to_replace in $others_var
do
# ${var_to_replace^^} make the content of the variable on upper-cases
# ${!var_to_replace} get the content of the variable named $var_to_replace
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banjailconf"
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banfilterconf"
done
tee $finalfail2banjailconf <<EOF
else
# Usage 1, no template. Build a config file from scratch.
test -n "$logpath" || ynh_die "ynh_add_fail2ban_config expects a logfile path as first argument and received nothing."
test -n "$failregex" || ynh_die "ynh_add_fail2ban_config expects a failure regex as second argument and received nothing."
tee $finalfail2banjailconf <<EOF
[$app]
enabled = true
port = $ports
@ -124,19 +126,20 @@ before = common.conf
failregex = $failregex
ignoreregex =
EOF
fi
fi
# Common to usage 1 and 2.
ynh_store_file_checksum "$finalfail2banjailconf"
ynh_store_file_checksum "$finalfail2banfilterconf"
# Common to usage 1 and 2.
ynh_store_file_checksum "$finalfail2banjailconf"
ynh_store_file_checksum "$finalfail2banfilterconf"
ynh_systemd_action --service_name=fail2ban --action=reload
ynh_systemd_action --service_name=fail2ban --action=reload --line_match="(Started|Reloaded) Fail2Ban Service" --log_path=systemd
local fail2ban_error="$(journalctl -u fail2ban | tail -n50 | grep "WARNING.*$app.*")"
if [[ -n "$fail2ban_error" ]]; then
ynh_print_err --message="Fail2ban failed to load the jail for $app"
ynh_print_warn --message="${fail2ban_error#*WARNING}"
fi
local fail2ban_error="$(journalctl --unit=fail2ban | tail --lines=50 | grep "WARNING.*$app.*")"
if [[ -n "$fail2ban_error" ]]
then
ynh_print_err --message="Fail2ban failed to load the jail for $app"
ynh_print_warn --message="${fail2ban_error#*WARNING}"
fi
}
# Remove the dedicated fail2ban config (jail and filter conf files)
@ -145,7 +148,7 @@ EOF
#
# Requires YunoHost version 3.5.0 or higher.
ynh_remove_fail2ban_config () {
ynh_secure_remove "/etc/fail2ban/jail.d/$app.conf"
ynh_secure_remove "/etc/fail2ban/filter.d/$app.conf"
ynh_systemd_action --service_name=fail2ban --action=reload
ynh_secure_remove "/etc/fail2ban/jail.d/$app.conf"
ynh_secure_remove "/etc/fail2ban/filter.d/$app.conf"
ynh_systemd_action --service_name=fail2ban --action=reload
}

View file

@ -6,7 +6,7 @@
#
# example: function my_helper()
# {
# declare -Ar args_array=( [a]=arg1= [b]=arg2= [c]=arg3 )
# local -A args_array=( [a]=arg1= [b]=arg2= [c]=arg3 )
# local arg1
# local arg2
# local arg3
@ -22,13 +22,13 @@
# This helper need an array, named "args_array" with all the arguments used by the helper
# that want to use ynh_handle_getopts_args
# Be carreful, this array has to be an associative array, as the following example:
# declare -Ar args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
# local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
# Let's explain this array:
# a, b and c are short options, -a, -b and -c
# arg1, arg2 and arg3 are the long options associated to the previous short ones. --arg1, --arg2 and --arg3
# For each option, a short and long version has to be defined.
# Let's see something more significant
# declare -Ar args_array=( [u]=user [f]=finalpath= [d]=database )
# local -A args_array=( [u]=user [f]=finalpath= [d]=database )
#
# NB: Because we're using 'declare' without -g, the array will be declared as a local variable.
#
@ -46,173 +46,179 @@
#
# Requires YunoHost version 3.2.2 or higher.
ynh_handle_getopts_args () {
# Manage arguments only if there's some provided
set +x
if [ $# -ne 0 ]
then
# Store arguments in an array to keep each argument separated
local arguments=("$@")
# Manage arguments only if there's some provided
set +o xtrace # set +x
if [ $# -ne 0 ]
then
# Store arguments in an array to keep each argument separated
local arguments=("$@")
# For each option in the array, reduce to short options for getopts (e.g. for [u]=user, --user will be -u)
# And built parameters string for getopts
# ${!args_array[@]} is the list of all option_flags in the array (An option_flag is 'u' in [u]=user, user is a value)
local getopts_parameters=""
local option_flag=""
for option_flag in "${!args_array[@]}"
do
# Concatenate each option_flags of the array to build the string of arguments for getopts
# Will looks like 'abcd' for -a -b -c -d
# If the value of an option_flag finish by =, it's an option with additionnal values. (e.g. --user bob or -u bob)
# Check the last character of the value associate to the option_flag
if [ "${args_array[$option_flag]: -1}" = "=" ]
then
# For an option with additionnal values, add a ':' after the letter for getopts.
getopts_parameters="${getopts_parameters}${option_flag}:"
else
getopts_parameters="${getopts_parameters}${option_flag}"
fi
# Check each argument given to the function
local arg=""
# ${#arguments[@]} is the size of the array
for arg in `seq 0 $(( ${#arguments[@]} - 1 ))`
do
# Escape options' values starting with -. Otherwise the - will be considered as another option.
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}-/--${args_array[$option_flag]}\\TOBEREMOVED\\-}"
# And replace long option (value of the option_flag) by the short option, the option_flag itself
# (e.g. for [u]=user, --user will be -u)
# Replace long option with =
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}/-${option_flag} }"
# And long option without =
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]%=}/-${option_flag}}"
done
done
# For each option in the array, reduce to short options for getopts (e.g. for [u]=user, --user will be -u)
# And built parameters string for getopts
# ${!args_array[@]} is the list of all option_flags in the array (An option_flag is 'u' in [u]=user, user is a value)
local getopts_parameters=""
local option_flag=""
for option_flag in "${!args_array[@]}"
do
# Concatenate each option_flags of the array to build the string of arguments for getopts
# Will looks like 'abcd' for -a -b -c -d
# If the value of an option_flag finish by =, it's an option with additionnal values. (e.g. --user bob or -u bob)
# Check the last character of the value associate to the option_flag
if [ "${args_array[$option_flag]: -1}" = "=" ]
then
# For an option with additionnal values, add a ':' after the letter for getopts.
getopts_parameters="${getopts_parameters}${option_flag}:"
else
getopts_parameters="${getopts_parameters}${option_flag}"
fi
# Check each argument given to the function
local arg=""
# ${#arguments[@]} is the size of the array
for arg in `seq 0 $(( ${#arguments[@]} - 1 ))`
do
# Escape options' values starting with -. Otherwise the - will be considered as another option.
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}-/--${args_array[$option_flag]}\\TOBEREMOVED\\-}"
# And replace long option (value of the option_flag) by the short option, the option_flag itself
# (e.g. for [u]=user, --user will be -u)
# Replace long option with =
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}/-${option_flag} }"
# And long option without =
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]%=}/-${option_flag}}"
done
done
# Read and parse all the arguments
# Use a function here, to use standart arguments $@ and be able to use shift.
parse_arg () {
# Read all arguments, until no arguments are left
while [ $# -ne 0 ]
do
# Initialize the index of getopts
OPTIND=1
# Parse with getopts only if the argument begin by -, that means the argument is an option
# getopts will fill $parameter with the letter of the option it has read.
local parameter=""
getopts ":$getopts_parameters" parameter || true
# Read and parse all the arguments
# Use a function here, to use standart arguments $@ and be able to use shift.
parse_arg () {
# Read all arguments, until no arguments are left
while [ $# -ne 0 ]
do
# Initialize the index of getopts
OPTIND=1
# Parse with getopts only if the argument begin by -, that means the argument is an option
# getopts will fill $parameter with the letter of the option it has read.
local parameter=""
getopts ":$getopts_parameters" parameter || true
if [ "$parameter" = "?" ]
then
ynh_die --message="Invalid argument: -${OPTARG:-}"
elif [ "$parameter" = ":" ]
then
ynh_die --message="-$OPTARG parameter requires an argument."
else
local shift_value=1
# Use the long option, corresponding to the short option read by getopts, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$parameter]%=}"
# If this option doesn't take values
# if there's a '=' at the end of the long option name, this option takes values
if [ "${args_array[$parameter]: -1}" != "=" ]
then
# 'eval ${option_var}' will use the content of 'option_var'
eval ${option_var}=1
else
# Read all other arguments to find multiple value for this option.
# Load args in a array
local all_args=("$@")
if [ "$parameter" = "?" ]
then
ynh_die --message="Invalid argument: -${OPTARG:-}"
elif [ "$parameter" = ":" ]
then
ynh_die --message="-$OPTARG parameter requires an argument."
else
local shift_value=1
# Use the long option, corresponding to the short option read by getopts, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$parameter]%=}"
# If this option doesn't take values
# if there's a '=' at the end of the long option name, this option takes values
if [ "${args_array[$parameter]: -1}" != "=" ]
then
# 'eval ${option_var}' will use the content of 'option_var'
eval ${option_var}=1
else
# Read all other arguments to find multiple value for this option.
# Load args in a array
local all_args=("$@")
# If the first argument is longer than 2 characters,
# There's a value attached to the option, in the same array cell
if [ ${#all_args[0]} -gt 2 ]; then
# Remove the option and the space, so keep only the value itself.
all_args[0]="${all_args[0]#-${parameter} }"
# Reduce the value of shift, because the option has been removed manually
shift_value=$(( shift_value - 1 ))
fi
# If the first argument is longer than 2 characters,
# There's a value attached to the option, in the same array cell
if [ ${#all_args[0]} -gt 2 ]
then
# Remove the option and the space, so keep only the value itself.
all_args[0]="${all_args[0]#-${parameter} }"
# Reduce the value of shift, because the option has been removed manually
shift_value=$(( shift_value - 1 ))
fi
# Declare the content of option_var as a variable.
eval ${option_var}=""
# Then read the array value per value
local i
for i in `seq 0 $(( ${#all_args[@]} - 1 ))`
do
# If this argument is an option, end here.
if [ "${all_args[$i]:0:1}" == "-" ]
then
# Ignore the first value of the array, which is the option itself
if [ "$i" -ne 0 ]; then
break
fi
else
# Else, add this value to this option
# Each value will be separated by ';'
if [ -n "${!option_var}" ]
then
# If there's already another value for this option, add a ; before adding the new value
eval ${option_var}+="\;"
fi
# Declare the content of option_var as a variable.
eval ${option_var}=""
# Then read the array value per value
local i
for i in `seq 0 $(( ${#all_args[@]} - 1 ))`
do
# If this argument is an option, end here.
if [ "${all_args[$i]:0:1}" == "-" ]
then
# Ignore the first value of the array, which is the option itself
if [ "$i" -ne 0 ]; then
break
fi
else
# Ignore empty parameters
if [ -n "${all_args[$i]}" ]
then
# Else, add this value to this option
# Each value will be separated by ';'
if [ -n "${!option_var}" ]
then
# If there's already another value for this option, add a ; before adding the new value
eval ${option_var}+="\;"
fi
# Remove the \ that escape - at beginning of values.
all_args[i]="${all_args[i]//\\TOBEREMOVED\\/}"
# Remove the \ that escape - at beginning of values.
all_args[i]="${all_args[i]//\\TOBEREMOVED\\/}"
# For the record.
# We're using eval here to get the content of the variable stored itself as simple text in $option_var...
# Other ways to get that content would be to use either ${!option_var} or declare -g ${option_var}
# But... ${!option_var} can't be used as left part of an assignation.
# declare -g ${option_var} will create a local variable (despite -g !) and will not be available for the helper itself.
# So... Stop fucking arguing each time that eval is evil... Go find an other working solution if you can find one!
# For the record.
# We're using eval here to get the content of the variable stored itself as simple text in $option_var...
# Other ways to get that content would be to use either ${!option_var} or declare -g ${option_var}
# But... ${!option_var} can't be used as left part of an assignation.
# declare -g ${option_var} will create a local variable (despite -g !) and will not be available for the helper itself.
# So... Stop fucking arguing each time that eval is evil... Go find an other working solution if you can find one!
eval ${option_var}+='"${all_args[$i]}"'
shift_value=$(( shift_value + 1 ))
fi
done
fi
fi
eval ${option_var}+='"${all_args[$i]}"'
fi
shift_value=$(( shift_value + 1 ))
fi
done
fi
fi
# Shift the parameter and its argument(s)
shift $shift_value
done
}
# Shift the parameter and its argument(s)
shift $shift_value
done
}
# LEGACY MODE
# Check if there's getopts arguments
if [ "${arguments[0]:0:1}" != "-" ]
then
# If not, enter in legacy mode and manage the arguments as positionnal ones..
# Dot not echo, to prevent to go through a helper output. But print only in the log.
set -x; echo "! Helper used in legacy mode !" > /dev/null; set +x
local i
for i in `seq 0 $(( ${#arguments[@]} -1 ))`
do
# Try to use legacy_args as a list of option_flag of the array args_array
# Otherwise, fallback to getopts_parameters to get the option_flag. But an associative arrays isn't always sorted in the correct order...
# Remove all ':' in getopts_parameters
getopts_parameters=${legacy_args:-${getopts_parameters//:}}
# Get the option_flag from getopts_parameters, by using the option_flag according to the position of the argument.
option_flag=${getopts_parameters:$i:1}
if [ -z "$option_flag" ]; then
ynh_print_warn --message="Too many arguments ! \"${arguments[$i]}\" will be ignored."
continue
fi
# Use the long option, corresponding to the option_flag, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$option_flag]%=}"
# LEGACY MODE
# Check if there's getopts arguments
if [ "${arguments[0]:0:1}" != "-" ]
then
# If not, enter in legacy mode and manage the arguments as positionnal ones..
# Dot not echo, to prevent to go through a helper output. But print only in the log.
set -x; echo "! Helper used in legacy mode !" > /dev/null; set +x
local i
for i in `seq 0 $(( ${#arguments[@]} -1 ))`
do
# Try to use legacy_args as a list of option_flag of the array args_array
# Otherwise, fallback to getopts_parameters to get the option_flag. But an associative arrays isn't always sorted in the correct order...
# Remove all ':' in getopts_parameters
getopts_parameters=${legacy_args:-${getopts_parameters//:}}
# Get the option_flag from getopts_parameters, by using the option_flag according to the position of the argument.
option_flag=${getopts_parameters:$i:1}
if [ -z "$option_flag" ]
then
ynh_print_warn --message="Too many arguments ! \"${arguments[$i]}\" will be ignored."
continue
fi
# Use the long option, corresponding to the option_flag, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$option_flag]%=}"
# Store each value given as argument in the corresponding variable
# The values will be stored in the same order than $args_array
eval ${option_var}+='"${arguments[$i]}"'
done
unset legacy_args
else
# END LEGACY MODE
# Call parse_arg and pass the modified list of args as an array of arguments.
parse_arg "${arguments[@]}"
fi
fi
set -x
# Store each value given as argument in the corresponding variable
# The values will be stored in the same order than $args_array
eval ${option_var}+='"${arguments[$i]}"'
done
unset legacy_args
else
# END LEGACY MODE
# Call parse_arg and pass the modified list of args as an array of arguments.
parse_arg "${arguments[@]}"
fi
fi
set -o xtrace # set -x
}

108
data/helpers.d/hardware Normal file
View file

@ -0,0 +1,108 @@
#!/bin/bash
# Get the total or free amount of RAM+swap on the system
#
# usage: ynh_get_ram [--free|--total] [--ignore_swap|--only_swap]
# | arg: -f, --free - Count free RAM+swap
# | arg: -t, --total - Count total RAM+swap
# | arg: -s, --ignore_swap - Ignore swap, consider only real RAM
# | arg: -o, --only_swap - Ignore real RAM, consider only swap
# | ret: the amount of free ram
#
# Requires YunoHost version 3.8.1 or higher.
ynh_get_ram () {
# Declare an array to define the options of this helper.
local legacy_args=ftso
local -A args_array=( [f]=free [t]=total [s]=ignore_swap [o]=only_swap )
local free
local total
local ignore_swap
local only_swap
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ignore_swap=${ignore_swap:-0}
only_swap=${only_swap:-0}
free=${free:-0}
total=${total:-0}
local total_ram=$(vmstat --stats --unit M | grep "total memory" | awk '{print $1}')
local total_swap=$(vmstat --stats --unit M | grep "total swap" | awk '{print $1}')
local total_ram_swap=$(( total_ram + total_swap ))
local free_ram=$(vmstat --stats --unit M | grep "free memory" | awk '{print $1}')
local free_swap=$(vmstat --stats --unit M | grep "free swap" | awk '{print $1}')
local free_ram_swap=$(( free_ram + free_swap ))
# Use the total amount of ram
if [ $free -eq 1 ]
then
# Use the total amount of free ram
local ram=$free_ram_swap
if [ $ignore_swap -eq 1 ]
then
# Use only the amount of free ram
ram=$free_ram
elif [ $only_swap -eq 1 ]
then
# Use only the amount of free swap
ram=$free_swap
fi
elif [ $total -eq 1 ]
then
local ram=$total_ram_swap
if [ $ignore_swap -eq 1 ]
then
# Use only the amount of free ram
ram=$total_ram
elif [ $only_swap -eq 1 ]
then
# Use only the amount of free swap
ram=$total_swap
fi
else
ynh_print_warn --message="You have to choose --free or --total when using ynh_get_ram"
ram=0
fi
echo $ram
}
# Return 0 or 1 depending if the system has a given amount of RAM+swap free or total
#
# usage: ynh_require_ram --required=RAM required in Mb [--free|--total] [--ignore_swap|--only_swap]
# | arg: -r, --required= - The amount to require, in Mb
# | arg: -f, --free - Count free RAM+swap
# | arg: -t, --total - Count total RAM+swap
# | arg: -s, --ignore_swap - Ignore swap, consider only real RAM
# | arg: -o, --only_swap - Ignore real RAM, consider only swap
# | exit: Return 1 if the ram is under the requirement, 0 otherwise.
#
# Requires YunoHost version 3.8.1 or higher.
ynh_require_ram () {
# Declare an array to define the options of this helper.
local legacy_args=rftso
local -A args_array=( [r]=required= [f]=free [t]=total [s]=ignore_swap [o]=only_swap )
local required
local free
local total
local ignore_swap
local only_swap
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Dunno if that's the right way to do, but that's some black magic to be able to
# forward the bool args to ynh_get_ram easily?
# If the variable $free is not empty, set it to '--free'
free=${free:+--free}
total=${total:+--total}
ignore_swap=${ignore_swap:+--ignore_swap}
only_swap=${only_swap:+--only_swap}
local ram=$(ynh_get_ram $free $total $ignore_swap $only_swap)
if [ $ram -lt $required ]
then
return 1
else
return 0
fi
}

View file

@ -3,30 +3,34 @@
# Print a message to stderr and exit
#
# usage: ynh_die --message=MSG [--ret_code=RETCODE]
# | arg: -m, --message= - Message to display
# | arg: -c, --ret_code= - Exit code to exit with
#
# Requires YunoHost version 2.4.0 or higher.
ynh_die() {
# Declare an array to define the options of this helper.
local legacy_args=mc
declare -Ar args_array=( [m]=message= [c]=ret_code= )
local message
local ret_code
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=mc
local -A args_array=( [m]=message= [c]=ret_code= )
local message
local ret_code
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ret_code=${ret_code:-1}
echo "$message" 1>&2
exit "${ret_code:-1}"
echo "$message" 1>&2
exit "$ret_code"
}
# Display a message in the 'INFO' logging category
#
# usage: ynh_print_info --message="Some message"
# | arg: -m, --message= - Message to display
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_info() {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=message= )
local -A args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -45,12 +49,12 @@ ynh_print_info() {
#
# Requires YunoHost version 2.6.4 or higher.
ynh_no_log() {
local ynh_cli_log=/var/log/yunohost/yunohost-cli.log
sudo cp -a ${ynh_cli_log} ${ynh_cli_log}-move
eval $@
local exit_code=$?
sudo mv ${ynh_cli_log}-move ${ynh_cli_log}
return $?
local ynh_cli_log=/var/log/yunohost/yunohost-cli.log
cp --archive ${ynh_cli_log} ${ynh_cli_log}-move
eval $@
local exit_code=$?
mv ${ynh_cli_log}-move ${ynh_cli_log}
return $exit_code
}
# Main printer, just in case in the future we have to change anything about that.
@ -59,121 +63,116 @@ ynh_no_log() {
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_log () {
echo -e "${1}"
echo -e "${1}"
}
# Print a warning on stderr
#
# usage: ynh_print_warn --message="Text to print"
# | arg: -m, --message - The text to print
# | arg: -m, --message= - The text to print
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_warn () {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=m
local -A args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_print_log "\e[93m\e[1m[WARN]\e[0m ${message}" >&2
ynh_print_log "\e[93m\e[1m[WARN]\e[0m ${message}" >&2
}
# Print an error on stderr
#
# usage: ynh_print_err --message="Text to print"
# | arg: -m, --message - The text to print
# | arg: -m, --message= - The text to print
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_err () {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=m
local -A args_array=( [m]=message= )
local message
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_print_log "\e[91m\e[1m[ERR]\e[0m ${message}" >&2
ynh_print_log "\e[91m\e[1m[ERR]\e[0m ${message}" >&2
}
# Execute a command and print the result as an error
#
# usage: ynh_exec_err your_command
# usage: ynh_exec_err "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_err () {
ynh_print_err "$(eval $@)"
ynh_print_err "$(eval $@)"
}
# Execute a command and print the result as a warning
#
# usage: ynh_exec_warn your_command
# usage: ynh_exec_warn "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_warn () {
ynh_print_warn "$(eval $@)"
ynh_print_warn "$(eval $@)"
}
# Execute a command and force the result to be printed on stdout
#
# usage: ynh_exec_warn_less your_command
# usage: ynh_exec_warn_less "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_warn_less () {
eval $@ 2>&1
eval $@ 2>&1
}
# Execute a command and redirect stdout in /dev/null
#
# usage: ynh_exec_quiet your_command
# usage: ynh_exec_quiet "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_quiet () {
eval $@ > /dev/null
eval $@ > /dev/null
}
# Execute a command and redirect stdout and stderr in /dev/null
#
# usage: ynh_exec_fully_quiet your_command
# usage: ynh_exec_fully_quiet "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.2.0 or higher.
ynh_exec_fully_quiet () {
eval $@ > /dev/null 2>&1
eval $@ > /dev/null 2>&1
}
# Remove any logs for all the following commands.
@ -184,7 +183,7 @@ ynh_exec_fully_quiet () {
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_OFF () {
exec {BASH_XTRACEFD}>/dev/null
exec {BASH_XTRACEFD}>/dev/null
}
# Restore the logging after ynh_print_OFF
@ -193,9 +192,9 @@ ynh_print_OFF () {
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_ON () {
exec {BASH_XTRACEFD}>&1
# Print an echo only for the log, to be able to know that ynh_print_ON has been called.
echo ynh_print_ON > /dev/null
exec {BASH_XTRACEFD}>&1
# Print an echo only for the log, to be able to know that ynh_print_ON has been called.
echo ynh_print_ON > /dev/null
}
# Initial definitions for ynh_script_progression
@ -216,86 +215,87 @@ base_time=$(date +%s)
# usage: ynh_script_progression --message=message [--weight=weight] [--time]
# | arg: -m, --message= - The text to print
# | arg: -w, --weight= - The weight for this progression. This value is 1 by default. Use a bigger value for a longer part of the script.
# | arg: -t, --time= - Print the execution time since the last call to this helper. Especially usefull to define weights. The execution time is given for the duration since the previous call. So the weight should be applied to this previous call.
# | arg: -l, --last= - Use for the last call of the helper, to fill te progression bar.
# | arg: -t, --time - Print the execution time since the last call to this helper. Especially usefull to define weights. The execution time is given for the duration since the previous call. So the weight should be applied to this previous call.
# | arg: -l, --last - Use for the last call of the helper, to fill te progression bar.
#
# Requires YunoHost version 3.5.0 or higher.
ynh_script_progression () {
set +x
# Declare an array to define the options of this helper.
local legacy_args=mwtl
declare -Ar args_array=( [m]=message= [w]=weight= [t]=time [l]=last )
local message
local weight
local time
local last
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
set +x
weight=${weight:-1}
time=${time:-0}
last=${last:-0}
set +o xtrace # set +x
# Declare an array to define the options of this helper.
local legacy_args=mwtl
local -A args_array=( [m]=message= [w]=weight= [t]=time [l]=last )
local message
local weight
local time
local last
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Re-disable xtrace, ynh_handle_getopts_args set it back
set +o xtrace # set +x
weight=${weight:-1}
time=${time:-0}
last=${last:-0}
# Get execution time since the last $base_time
local exec_time=$(( $(date +%s) - $base_time ))
base_time=$(date +%s)
# Get execution time since the last $base_time
local exec_time=$(( $(date +%s) - $base_time ))
base_time=$(date +%s)
# Compute $max_progression (if we didn't already)
if [ "$max_progression" = -1 ]
then
# Get the number of occurrences of 'ynh_script_progression' in the script. Except those are commented.
local helper_calls="$(grep --count "^[^#]*ynh_script_progression" $0)"
# Get the number of call with a weight value
local weight_calls=$(grep --perl-regexp --count "^[^#]*ynh_script_progression.*(--weight|-w )" $0)
# Compute $max_progression (if we didn't already)
if [ "$max_progression" = -1 ]
then
# Get the number of occurrences of 'ynh_script_progression' in the script. Except those are commented.
local helper_calls="$(grep --count "^[^#]*ynh_script_progression" $0)"
# Get the number of call with a weight value
local weight_calls=$(grep --perl-regexp --count "^[^#]*ynh_script_progression.*(--weight|-w )" $0)
# Get the weight of each occurrences of 'ynh_script_progression' in the script using --weight
local weight_valuesA="$(grep --perl-regexp "^[^#]*ynh_script_progression.*--weight" $0 | sed 's/.*--weight[= ]\([[:digit:]]*\).*/\1/g')"
# Get the weight of each occurrences of 'ynh_script_progression' in the script using -w
local weight_valuesB="$(grep --perl-regexp "^[^#]*ynh_script_progression.*-w " $0 | sed 's/.*-w[= ]\([[:digit:]]*\).*/\1/g')"
# Each value will be on a different line.
# Remove each 'end of line' and replace it by a '+' to sum the values.
local weight_values=$(( $(echo "$weight_valuesA" | tr '\n' '+') + $(echo "$weight_valuesB" | tr '\n' '+') 0 ))
# Get the weight of each occurrences of 'ynh_script_progression' in the script using --weight
local weight_valuesA="$(grep --perl-regexp "^[^#]*ynh_script_progression.*--weight" $0 | sed 's/.*--weight[= ]\([[:digit:]]*\).*/\1/g')"
# Get the weight of each occurrences of 'ynh_script_progression' in the script using -w
local weight_valuesB="$(grep --perl-regexp "^[^#]*ynh_script_progression.*-w " $0 | sed 's/.*-w[= ]\([[:digit:]]*\).*/\1/g')"
# Each value will be on a different line.
# Remove each 'end of line' and replace it by a '+' to sum the values.
local weight_values=$(( $(echo "$weight_valuesA" | tr '\n' '+') + $(echo "$weight_valuesB" | tr '\n' '+') 0 ))
# max_progression is a total number of calls to this helper.
# Less the number of calls with a weight value.
# Plus the total of weight values
max_progression=$(( $helper_calls - $weight_calls + $weight_values ))
fi
# max_progression is a total number of calls to this helper.
# Less the number of calls with a weight value.
# Plus the total of weight values
max_progression=$(( $helper_calls - $weight_calls + $weight_values ))
fi
# Increment each execution of ynh_script_progression in this script by the weight of the previous call.
increment_progression=$(( $increment_progression + $previous_weight ))
# Store the weight of the current call in $previous_weight for next call
previous_weight=$weight
# Increment each execution of ynh_script_progression in this script by the weight of the previous call.
increment_progression=$(( $increment_progression + $previous_weight ))
# Store the weight of the current call in $previous_weight for next call
previous_weight=$weight
# Reduce $increment_progression to the size of the scale
if [ $last -eq 0 ]
then
local effective_progression=$(( $increment_progression * $progress_scale / $max_progression ))
# If last is specified, fill immediately the progression_bar
else
local effective_progression=$progress_scale
fi
# Reduce $increment_progression to the size of the scale
if [ $last -eq 0 ]
then
local effective_progression=$(( $increment_progression * $progress_scale / $max_progression ))
# If last is specified, fill immediately the progression_bar
else
local effective_progression=$progress_scale
fi
# Build $progression_bar from progress_string(0,1,2) according to $effective_progression and the weight of the current task
# expected_progression is the progression expected after the current task
local expected_progression="$(( ( $increment_progression + $weight ) * $progress_scale / $max_progression - $effective_progression ))"
if [ $last -eq 1 ]
then
expected_progression=0
fi
# left_progression is the progression not yet done
local left_progression="$(( $progress_scale - $effective_progression - $expected_progression ))"
# Build the progression bar with $effective_progression, work done, $expected_progression, current work and $left_progression, work to be done.
local progression_bar="${progress_string2:0:$effective_progression}${progress_string1:0:$expected_progression}${progress_string0:0:$left_progression}"
# Build $progression_bar from progress_string(0,1,2) according to $effective_progression and the weight of the current task
# expected_progression is the progression expected after the current task
local expected_progression="$(( ( $increment_progression + $weight ) * $progress_scale / $max_progression - $effective_progression ))"
if [ $last -eq 1 ]
then
expected_progression=0
fi
# left_progression is the progression not yet done
local left_progression="$(( $progress_scale - $effective_progression - $expected_progression ))"
# Build the progression bar with $effective_progression, work done, $expected_progression, current work and $left_progression, work to be done.
local progression_bar="${progress_string2:0:$effective_progression}${progress_string1:0:$expected_progression}${progress_string0:0:$left_progression}"
local print_exec_time=""
if [ $time -eq 1 ]
then
print_exec_time=" [$(date +%Hh%Mm,%Ss --date="0 + $exec_time sec")]"
fi
local print_exec_time=""
if [ $time -eq 1 ]
then
print_exec_time=" [$(date +%Hh%Mm,%Ss --date="0 + $exec_time sec")]"
fi
ynh_print_info "[$progression_bar] > ${message}${print_exec_time}"
set -x
ynh_print_info "[$progression_bar] > ${message}${print_exec_time}"
set -o xtrace # set -x
}
# Return data to the Yunohost core for later processing
@ -316,63 +316,62 @@ ynh_return () {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_debug () {
# Disable set xtrace for the helper itself, to not pollute the debug log
set +x
# Declare an array to define the options of this helper.
local legacy_args=mt
declare -Ar args_array=( [m]=message= [t]=trace= )
local message
local trace
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Redisable xtrace, ynh_handle_getopts_args set it back
set +x
message=${message:-}
trace=${trace:-}
# Disable set xtrace for the helper itself, to not pollute the debug log
set +o xtrace # set +x
# Declare an array to define the options of this helper.
local legacy_args=mt
local -A args_array=( [m]=message= [t]=trace= )
local message
local trace
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Re-disable xtrace, ynh_handle_getopts_args set it back
set +o xtrace # set +x
message=${message:-}
trace=${trace:-}
if [ -n "$message" ]
then
ynh_print_log "\e[34m\e[1m[DEBUG]\e[0m ${message}" >&2
fi
if [ -n "$message" ]
then
ynh_print_log "\e[34m\e[1m[DEBUG]\e[0m ${message}" >&2
fi
if [ "$trace" == "1" ]
then
ynh_debug --message="Enable debugging"
set +x
# Get the current file descriptor of xtrace
old_bash_xtracefd=$BASH_XTRACEFD
# Add the current file name and the line number of any command currently running while tracing.
PS4='$(basename ${BASH_SOURCE[0]})-L${LINENO}: '
# Force xtrace to stderr
BASH_XTRACEFD=2
# Force stdout to stderr
exec 1>&2
fi
if [ "$trace" == "0" ]
then
ynh_debug --message="Disable debugging"
set +x
# Put xtrace back to its original fild descriptor
BASH_XTRACEFD=$old_bash_xtracefd
# Restore stdout
exec 1>&1
fi
# Renable set xtrace
set -x
if [ "$trace" == "1" ]
then
ynh_debug --message="Enable debugging"
set +o xtrace # set +x
# Get the current file descriptor of xtrace
old_bash_xtracefd=$BASH_XTRACEFD
# Add the current file name and the line number of any command currently running while tracing.
PS4='$(basename ${BASH_SOURCE[0]})-L${LINENO}: '
# Force xtrace to stderr
BASH_XTRACEFD=2
# Force stdout to stderr
exec 1>&2
fi
if [ "$trace" == "0" ]
then
ynh_debug --message="Disable debugging"
set +o xtrace # set +x
# Put xtrace back to its original fild descriptor
BASH_XTRACEFD=$old_bash_xtracefd
# Restore stdout
exec 1>&1
fi
# Renable set xtrace
set -o xtrace # set -x
}
# Execute a command and print the result as debug
#
# usage: ynh_debug_exec your_command
# usage: ynh_debug_exec "your_command | other_command"
# | arg: command - command to execute
#
# When using pipes, double quotes are required - otherwise, this helper will run the first command, and the whole output will be sent through the next pipe.
#
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
#
# Requires YunoHost version 3.5.0 or higher.
ynh_debug_exec () {
ynh_debug --message="$(eval $@)"
ynh_debug --message="$(eval $@)"
}

View file

@ -3,9 +3,9 @@
# Use logrotate to manage the logfile
#
# usage: ynh_use_logrotate [--logfile=/log/file] [--nonappend] [--specific_user=user/group]
# | arg: -l, --logfile - absolute path of logfile
# | arg: -n, --nonappend - (optional) Replace the config file instead of appending this new config.
# | arg: -u, --specific_user : run logrotate as the specified user and group. If not specified logrotate is runned as root.
# | arg: -l, --logfile= - absolute path of logfile
# | arg: -n, --nonappend - (optional) Replace the config file instead of appending this new config.
# | arg: -u, --specific_user= - run logrotate as the specified user and group. If not specified logrotate is runned as root.
#
# If no --logfile is provided, /var/log/${app} will be used as default.
# logfile can be just a directory, or a full path to a logfile :
@ -16,79 +16,88 @@
# the same logrotate config file. Unless you use the option --non-append
#
# Requires YunoHost version 2.6.4 or higher.
# Requires YunoHost version 3.2.0 or higher for the argument --specific_user
ynh_use_logrotate () {
# Declare an array to define the options of this helper.
local legacy_args=lnuya
declare -Ar args_array=( [l]=logfile= [n]=nonappend [u]=specific_user= [y]=non [a]=append )
# [y]=non [a]=append are only for legacy purpose, to not fail on the old option '--non-append'
local logfile
local nonappend
local specific_user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local logfile="${logfile:-}"
local nonappend="${nonappend:-0}"
local specific_user="${specific_user:-}"
# Declare an array to define the options of this helper.
local legacy_args=lnuya
local -A args_array=( [l]=logfile= [n]=nonappend [u]=specific_user= [y]=non [a]=append )
# [y]=non [a]=append are only for legacy purpose, to not fail on the old option '--non-append'
local logfile
local nonappend
local specific_user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
logfile="${logfile:-}"
nonappend="${nonappend:-0}"
specific_user="${specific_user:-}"
# LEGACY CODE - PRE GETOPTS
if [ $# -gt 0 ] && [ "$1" == "--non-append" ]; then
nonappend=1
# Destroy this argument for the next command.
shift
elif [ $# -gt 1 ] && [ "$2" == "--non-append" ]; then
nonappend=1
fi
# LEGACY CODE - PRE GETOPTS
if [ $# -gt 0 ] && [ "$1" == "--non-append" ]
then
nonappend=1
# Destroy this argument for the next command.
shift
elif [ $# -gt 1 ] && [ "$2" == "--non-append" ]
then
nonappend=1
fi
if [ $# -gt 0 ] && [ "$(echo ${1:0:1})" != "-" ]; then
if [ "$(echo ${1##*.})" == "log" ]; then # Keep only the extension to check if it's a logfile
local logfile=$1 # In this case, focus logrotate on the logfile
else
local logfile=$1/*.log # Else, uses the directory and all logfile into it.
fi
fi
# LEGACY CODE
if [ $# -gt 0 ] && [ "$(echo ${1:0:1})" != "-" ]
then
# If the given logfile parameter already exists as a file, or if it ends up with ".log",
# we just want to manage a single file
if [ -f "$1" ] || [ "$(echo ${1##*.})" == "log" ]
then
local logfile=$1
# Otherwise we assume we want to manage a directory and all its .log file inside
else
local logfile=$1/*.log
fi
fi
# LEGACY CODE
local customtee="tee -a"
if [ "$nonappend" -eq 1 ]; then
customtee="tee"
fi
if [ -n "$logfile" ]
then
if [ "$(echo ${logfile##*.})" != "log" ]; then # Keep only the extension to check if it's a logfile
local logfile="$logfile/*.log" # Else, uses the directory and all logfile into it.
fi
else
logfile="/var/log/${app}/*.log" # Without argument, use a defaut directory in /var/log
fi
local su_directive=""
if [[ -n $specific_user ]]; then
su_directive=" # Run logorotate as specific user - group
su ${specific_user%/*} ${specific_user#*/}"
fi
local customtee="tee --append"
if [ "$nonappend" -eq 1 ]; then
customtee="tee"
fi
if [ -n "$logfile" ]
then
if [ ! -f "$1" ] && [ "$(echo ${logfile##*.})" != "log" ]; then # Keep only the extension to check if it's a logfile
local logfile="$logfile/*.log" # Else, uses the directory and all logfile into it.
fi
else
logfile="/var/log/${app}/*.log" # Without argument, use a defaut directory in /var/log
fi
local su_directive=""
if [[ -n $specific_user ]]
then
su_directive=" # Run logorotate as specific user - group
su ${specific_user%/*} ${specific_user#*/}"
fi
cat > ./${app}-logrotate << EOF # Build a config file for logrotate
cat > ./${app}-logrotate << EOF # Build a config file for logrotate
$logfile {
# Rotate if the logfile exceeds 100Mo
size 100M
# Keep 12 old log maximum
rotate 12
# Compress the logs with gzip
compress
# Compress the log at the next cycle. So keep always 2 non compressed logs
delaycompress
# Copy and truncate the log to allow to continue write on it. Instead of move the log.
copytruncate
# Do not do an error if the log is missing
missingok
# Not rotate if the log is empty
notifempty
# Keep old logs in the same dir
noolddir
$su_directive
# Rotate if the logfile exceeds 100Mo
size 100M
# Keep 12 old log maximum
rotate 12
# Compress the logs with gzip
compress
# Compress the log at the next cycle. So keep always 2 non compressed logs
delaycompress
# Copy and truncate the log to allow to continue write on it. Instead of move the log.
copytruncate
# Do not do an error if the log is missing
missingok
# Not rotate if the log is empty
notifempty
# Keep old logs in the same dir
noolddir
$su_directive
}
EOF
sudo mkdir -p $(dirname "$logfile") # Create the log directory, if not exist
cat ${app}-logrotate | sudo $customtee /etc/logrotate.d/$app > /dev/null # Append this config to the existing config file, or replace the whole config file (depending on $customtee)
mkdir --parents $(dirname "$logfile") # Create the log directory, if not exist
cat ${app}-logrotate | $customtee /etc/logrotate.d/$app > /dev/null # Append this config to the existing config file, or replace the whole config file (depending on $customtee)
}
# Remove the app's logrotate config.
@ -97,7 +106,7 @@ EOF
#
# Requires YunoHost version 2.6.4 or higher.
ynh_remove_logrotate () {
if [ -e "/etc/logrotate.d/$app" ]; then
sudo rm "/etc/logrotate.d/$app"
fi
if [ -e "/etc/logrotate.d/$app" ]; then
rm "/etc/logrotate.d/$app"
fi
}

View file

@ -4,19 +4,19 @@ MYSQL_ROOT_PWD_FILE=/etc/yunohost/mysql
# Open a connection as a user
#
# example: ynh_mysql_connect_as 'user' 'pass' <<< "UPDATE ...;"
# example: ynh_mysql_connect_as 'user' 'pass' < /path/to/file.sql
# example: ynh_mysql_connect_as --user="user" --password="pass" <<< "UPDATE ...;"
# example: ynh_mysql_connect_as --user="user" --password="pass" < /path/to/file.sql
#
# usage: ynh_mysql_connect_as --user=user --password=password [--database=database]
# | arg: -u, --user - the user name to connect as
# | arg: -p, --password - the user password
# | arg: -d, --database - the database to connect to
# | arg: -u, --user= - the user name to connect as
# | arg: -p, --password= - the user password
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_connect_as() {
# Declare an array to define the options of this helper.
local legacy_args=upd
declare -Ar args_array=( [u]=user= [p]=password= [d]=database= )
local -A args_array=( [u]=user= [p]=password= [d]=database= )
local user
local password
local database
@ -24,48 +24,48 @@ ynh_mysql_connect_as() {
ynh_handle_getopts_args "$@"
database="${database:-}"
mysql -u "$user" --password="$password" -B "$database"
mysql --user="$user" --password="$password" --batch "$database"
}
# Execute a command as root user
#
# usage: ynh_mysql_execute_as_root --sql=sql [--database=database]
# | arg: -s, --sql - the SQL command to execute
# | arg: -d, --database - the database to connect to
# | arg: -s, --sql= - the SQL command to execute
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_execute_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=sd
declare -Ar args_array=( [s]=sql= [d]=database= )
local -A args_array=( [s]=sql= [d]=database= )
local sql
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
ynh_mysql_connect_as --user="root" --password="$(sudo cat $MYSQL_ROOT_PWD_FILE)" \
ynh_mysql_connect_as --user="root" --password="$(cat $MYSQL_ROOT_PWD_FILE)" \
--database="$database" <<< "$sql"
}
# Execute a command from a file as root user
#
# usage: ynh_mysql_execute_file_as_root --file=file [--database=database]
# | arg: -f, --file - the file containing SQL commands
# | arg: -d, --database - the database to connect to
# | arg: -f, --file= - the file containing SQL commands
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_execute_file_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=fd
declare -Ar args_array=( [f]=file= [d]=database= )
local -A args_array=( [f]=file= [d]=database= )
local file
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
ynh_mysql_connect_as --user="root" --password="$(sudo cat $MYSQL_ROOT_PWD_FILE)" \
ynh_mysql_connect_as --user="root" --password="$(cat $MYSQL_ROOT_PWD_FILE)" \
--database="$database" < "$file"
}
@ -85,9 +85,12 @@ ynh_mysql_create_db() {
local sql="CREATE DATABASE ${db};"
# grant all privilegies to user
if [[ $# -gt 1 ]]; then
if [[ $# -gt 1 ]]
then
sql+=" GRANT ALL PRIVILEGES ON ${db}.* TO '${2}'@'localhost'"
[[ -n ${3:-} ]] && sql+=" IDENTIFIED BY '${3}'"
if [[ -n ${3:-} ]]; then
sql+=" IDENTIFIED BY '${3}'"
fi
sql+=" WITH GRANT OPTION;"
fi
@ -111,22 +114,22 @@ ynh_mysql_drop_db() {
# Dump a database
#
# example: ynh_mysql_dump_db 'roundcube' > ./dump.sql
# example: ynh_mysql_dump_db --database=roundcube > ./dump.sql
#
# usage: ynh_mysql_dump_db --database=database
# | arg: -d, --database - the database name to dump
# | arg: -d, --database= - the database name to dump
# | ret: the mysqldump output
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_dump_db() {
# Declare an array to define the options of this helper.
local legacy_args=d
declare -Ar args_array=( [d]=database= )
local -A args_array=( [d]=database= )
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
mysqldump -u "root" -p"$(sudo cat $MYSQL_ROOT_PWD_FILE)" --single-transaction --skip-dump-date "$database"
mysqldump --user="root" --password="$(cat $MYSQL_ROOT_PWD_FILE)" --single-transaction --skip-dump-date "$database"
}
# Create a user
@ -146,24 +149,25 @@ ynh_mysql_create_user() {
# Check if a mysql user exists
#
# usage: ynh_mysql_user_exists --user=user
# | arg: -u, --user - the user for which to check existence
# | arg: -u, --user= - the user for which to check existence
# | exit: Return 1 if the user doesn't exist, 0 otherwise.
#
# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_user_exists()
{
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=( [u]=user= )
local user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=u
local -A args_array=( [u]=user= )
local user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if [[ -z $(ynh_mysql_execute_as_root --sql="SELECT User from mysql.user WHERE User = '$user';") ]]
then
return 1
else
return 0
fi
if [[ -z $(ynh_mysql_execute_as_root --sql="SELECT User from mysql.user WHERE User = '$user';") ]]
then
return 1
else
return 0
fi
}
# Drop a user
@ -180,59 +184,59 @@ ynh_mysql_drop_user() {
# Create a database, an user and its password. Then store the password in the app's config
#
# usage: ynh_mysql_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 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 "mysqlpwd" into the app settings.
#
# usage: ynh_mysql_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 provided, a password will be generated
#
# Requires YunoHost version 2.6.4 or higher.
ynh_mysql_setup_db () {
# Declare an array to define the options of this helper.
local legacy_args=unp
declare -Ar args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=unp
local -A args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local new_db_pwd=$(ynh_string_random) # Generate a random password
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
local new_db_pwd=$(ynh_string_random) # Generate a random password
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
ynh_mysql_create_db "$db_name" "$db_user" "$db_pwd" # Create the database
ynh_app_setting_set --app=$app --key=mysqlpwd --value=$db_pwd # Store the password in the app's config
ynh_mysql_create_db "$db_name" "$db_user" "$db_pwd" # Create the database
ynh_app_setting_set --app=$app --key=mysqlpwd --value=$db_pwd # Store the password in the app's config
}
# Remove a database if it exists, and the associated user
#
# usage: ynh_mysql_remove_db --db_user=user --db_name=name
# | arg: -u, --db_user - Owner of the database
# | arg: -n, --db_name - Name of the database
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
#
# Requires YunoHost version 2.6.4 or higher.
ynh_mysql_remove_db () {
# Declare an array to define the options of this helper.
local legacy_args=un
declare -Ar args_array=( [u]=db_user= [n]=db_name= )
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=un
local -A args_array=( [u]=db_user= [n]=db_name= )
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local mysql_root_password=$(sudo cat $MYSQL_ROOT_PWD_FILE)
if mysqlshow -u root -p$mysql_root_password | grep -q "^| $db_name"; then # Check if the database exists
ynh_mysql_drop_db $db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
local mysql_root_password=$(cat $MYSQL_ROOT_PWD_FILE)
if mysqlshow --user=root --password=$mysql_root_password | grep --quiet "^| $db_name"
then # Check if the database exists
ynh_mysql_drop_db $db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
# Remove mysql user if it exists
if ynh_mysql_user_exists --user=$db_user; then
ynh_mysql_drop_user $db_user
fi
# Remove mysql user if it exists
if ynh_mysql_user_exists --user=$db_user; then
ynh_mysql_drop_user $db_user
fi
}

View file

@ -5,27 +5,56 @@
# example: port=$(ynh_find_port --port=8080)
#
# usage: ynh_find_port --port=begin_port
# | arg: -p, --port - port to start to search
# | arg: -p, --port= - port to start to search
# | ret: the port number
#
# Requires YunoHost version 2.6.4 or higher.
ynh_find_port () {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=port= )
local port
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=port= )
local port
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
test -n "$port" || ynh_die --message="The argument of ynh_find_port must be a valid port."
while netcat -z 127.0.0.1 $port # Check if the port is free
do
port=$((port+1)) # Else, pass to next port
done
echo $port
test -n "$port" || ynh_die --message="The argument of ynh_find_port must be a valid port."
while ! ynh_port_available --port=$port
do
port=$((port+1)) # Else, pass to next port
done
echo $port
}
# Test if a port is available
#
# example: ynh_port_available --port=1234 || ynh_die "Port 1234 is needs to be available for this app"
#
# usage: ynh_find_port --port=XYZ
# | arg: -p, --port= - port to check
# | exit: Return 1 if the port is already used by another process.
#
# Requires YunoHost version 3.8.0 or higher.
ynh_port_available () {
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=port= )
local port
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ss --numeric --listening --tcp --udp | awk '{print$5}' | grep --quiet --extended-regexp ":$port$" # Check if the port is free
then
return 1
else
return 0
fi
}
# Validate an IP address
#
# [internal]
#
# usage: ynh_validate_ip --family=family --ip_address=ip_address
# | ret: 0 for valid ip addresses, 1 otherwise
#
@ -34,17 +63,17 @@ ynh_find_port () {
# Requires YunoHost version 2.2.4 or higher.
ynh_validate_ip()
{
# http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298
# http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298
# Declare an array to define the options of this helper.
local legacy_args=fi
declare -Ar args_array=( [f]=family= [i]=ip_address= )
local family
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=fi
local -A args_array=( [f]=family= [i]=ip_address= )
local family
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1
python /dev/stdin << EOF
import socket
@ -63,19 +92,20 @@ EOF
# example: ynh_validate_ip4 111.222.333.444
#
# usage: ynh_validate_ip4 --ip_address=ip_address
# | arg: -i, --ip_address= - the ipv4 address to check
# | ret: 0 for valid ipv4 addresses, 1 otherwise
#
# Requires YunoHost version 2.2.4 or higher.
ynh_validate_ip4()
{
# Declare an array to define the options of this helper.
local legacy_args=i
declare -Ar args_array=( [i]=ip_address= )
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=i
local -A args_array=( [i]=ip_address= )
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_validate_ip 4 $ip_address
ynh_validate_ip --family=4 --ip_address=$ip_address
}
@ -84,17 +114,18 @@ ynh_validate_ip4()
# example: ynh_validate_ip6 2000:dead:beef::1
#
# usage: ynh_validate_ip6 --ip_address=ip_address
# | arg: -i, --ip_address= - the ipv6 address to check
# | ret: 0 for valid ipv6 addresses, 1 otherwise
#
# Requires YunoHost version 2.2.4 or higher.
ynh_validate_ip6()
{
# Declare an array to define the options of this helper.
local legacy_args=i
declare -Ar args_array=( [i]=ip_address= )
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=i
local -A args_array=( [i]=ip_address= )
local ip_address
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_validate_ip 6 $ip_address
ynh_validate_ip --family=6 --ip_address=$ip_address
}

View file

@ -12,57 +12,61 @@
# __PORT__ by $port
# __NAME__ by $app
# __FINALPATH__ by $final_path
# __PHPVERSION__ by $YNH_PHP_VERSION ($YNH_PHP_VERSION is either the default php version or the version defined for the app)
#
# And dynamic variables (from the last example) :
# __PATH_2__ by $path_2
# __PORT_2__ by $port_2
#
# Requires YunoHost version 2.7.2 or higher.
# Requires YunoHost version 2.7.13 or higher for dynamic variables
ynh_add_nginx_config () {
finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf"
local others_var=${1:-}
ynh_backup_if_checksum_is_different --file="$finalnginxconf"
sudo cp ../conf/nginx.conf "$finalnginxconf"
finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf"
local others_var=${1:-}
ynh_backup_if_checksum_is_different --file="$finalnginxconf"
cp ../conf/nginx.conf "$finalnginxconf"
# To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable.
# Substitute in a nginx config file only if the variable is not empty
if test -n "${path_url:-}"; then
# path_url_slash_less is path_url, or a blank value if path_url is only '/'
local path_url_slash_less=${path_url%/}
ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$finalnginxconf"
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$finalnginxconf"
fi
if test -n "${domain:-}"; then
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$finalnginxconf"
fi
if test -n "${port:-}"; then
ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$finalnginxconf"
fi
if test -n "${app:-}"; then
ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$finalnginxconf"
fi
if test -n "${final_path:-}"; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalnginxconf"
fi
# To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable.
# Substitute in a nginx config file only if the variable is not empty
if test -n "${path_url:-}"
then
# path_url_slash_less is path_url, or a blank value if path_url is only '/'
local path_url_slash_less=${path_url%/}
ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$finalnginxconf"
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$finalnginxconf"
fi
if test -n "${domain:-}"; then
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$finalnginxconf"
fi
if test -n "${port:-}"; then
ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$finalnginxconf"
fi
if test -n "${app:-}"; then
ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$finalnginxconf"
fi
if test -n "${final_path:-}"; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalnginxconf"
fi
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$YNH_PHP_VERSION" --target_file="$finalnginxconf"
# Replace all other variable given as arguments
for var_to_replace in $others_var
do
# ${var_to_replace^^} make the content of the variable on upper-cases
# ${!var_to_replace} get the content of the variable named $var_to_replace
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalnginxconf"
done
# Replace all other variable given as arguments
for var_to_replace in $others_var
do
# ${var_to_replace^^} make the content of the variable on upper-cases
# ${!var_to_replace} get the content of the variable named $var_to_replace
ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalnginxconf"
done
if [ "${path_url:-}" != "/" ]
then
ynh_replace_string --match_string="^#sub_path_only" --replace_string="" --target_file="$finalnginxconf"
else
ynh_replace_string --match_string="^#root_path_only" --replace_string="" --target_file="$finalnginxconf"
fi
if [ "${path_url:-}" != "/" ]
then
ynh_replace_string --match_string="^#sub_path_only" --replace_string="" --target_file="$finalnginxconf"
else
ynh_replace_string --match_string="^#root_path_only" --replace_string="" --target_file="$finalnginxconf"
fi
ynh_store_file_checksum --file="$finalnginxconf"
ynh_store_file_checksum --file="$finalnginxconf"
ynh_systemd_action --service_name=nginx --action=reload
ynh_systemd_action --service_name=nginx --action=reload
}
# Remove the dedicated nginx config
@ -71,6 +75,6 @@ ynh_add_nginx_config () {
#
# Requires YunoHost version 2.7.2 or higher.
ynh_remove_nginx_config () {
ynh_secure_remove --file="/etc/nginx/conf.d/$domain.d/$app.conf"
ynh_systemd_action --service_name=nginx --action=reload
ynh_secure_remove --file="/etc/nginx/conf.d/$domain.d/$app.conf"
ynh_systemd_action --service_name=nginx --action=reload
}

View file

@ -13,16 +13,16 @@ export N_PREFIX="$n_install_dir"
#
# Requires YunoHost version 2.7.12 or higher.
ynh_install_n () {
ynh_print_info --message="Installation of N - Node.js version management"
# Build an app.src for n
mkdir -p "../conf"
echo "SOURCE_URL=https://github.com/tj/n/archive/v4.1.0.tar.gz
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"
# Download and extract n
ynh_setup_source --dest_dir="$n_install_dir/git" --source_id=n
# Install n
(cd "$n_install_dir/git"
PREFIX=$N_PREFIX make install 2>&1)
# Download and extract n
ynh_setup_source --dest_dir="$n_install_dir/git" --source_id=n
# Install n
(cd "$n_install_dir/git"
PREFIX=$N_PREFIX make install 2>&1)
}
# Load the version of node for an app, and set variables.
@ -41,95 +41,97 @@ SOURCE_SUM=3983fa3f00d4bf85ba8e21f1a590f6e28938093abe0bb950aeea52b1717471fc" > "
#
# Requires YunoHost version 2.7.12 or higher.
ynh_use_nodejs () {
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
nodejs_use_version="echo \"Deprecated command, should be removed\""
nodejs_use_version="echo \"Deprecated command, should be removed\""
# Get the absolute path of this version of node
nodejs_path="$node_version_path/$nodejs_version/bin"
# Get the absolute path of this version of node
nodejs_path="$node_version_path/$nodejs_version/bin"
# Load the path of this version of node in $PATH
[[ :$PATH: == *":$nodejs_path"* ]] || PATH="$nodejs_path:$PATH"
# Load the path of this version of node in $PATH
if [[ :$PATH: != *":$nodejs_path"* ]]; then
PATH="$nodejs_path:$PATH"
fi
}
# Install a specific version of nodejs
#
# n (Node version management) uses the PATH variable to store the path of the version of node it is going to use.
# That's how it changes the version
#
# ynh_install_nodejs will install the version of node provided as argument by using n.
#
# usage: ynh_install_nodejs --nodejs_version=nodejs_version
# | arg: -n, --nodejs_version - Version of node to install. When possible, your should prefer to use major version number (e.g. 8 instead of 8.10.0). The crontab will then handle the update of minor versions when needed.
# | arg: -n, --nodejs_version= - Version of node to install. When possible, your should prefer to use major version number (e.g. 8 instead of 8.10.0). The crontab will then handle the update of minor versions when needed.
#
# n (Node version management) uses the PATH variable to store the path of the version of node it is going to use.
# That's how it changes the version
#
# Requires YunoHost version 2.7.12 or higher.
ynh_install_nodejs () {
# Use n, https://github.com/tj/n to manage the nodejs versions
# Use n, https://github.com/tj/n to manage the nodejs versions
# Declare an array to define the options of this helper.
local legacy_args=n
declare -Ar args_array=( [n]=nodejs_version= )
local nodejs_version
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=n
local -A args_array=( [n]=nodejs_version= )
local nodejs_version
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Create $n_install_dir
mkdir -p "$n_install_dir"
# Create $n_install_dir
mkdir --parents "$n_install_dir"
# Load n path in PATH
CLEAR_PATH="$n_install_dir/bin:$PATH"
# Remove /usr/local/bin in PATH in case of node prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
# Load n path in PATH
CLEAR_PATH="$n_install_dir/bin:$PATH"
# Remove /usr/local/bin in PATH in case of node prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
# Move an existing node binary, to avoid to block n.
test -x /usr/bin/node && mv /usr/bin/node /usr/bin/node_n
test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n
# Move an existing node binary, to avoid to block n.
test -x /usr/bin/node && mv /usr/bin/node /usr/bin/node_n
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)
then
ynh_install_n
fi
# If n is not previously setup, install it
if ! test $(n --version > /dev/null 2>&1)
then
ynh_install_n
fi
# Modify the default N_PREFIX in n script
ynh_replace_string --match_string="^N_PREFIX=\${N_PREFIX-.*}$" --replace_string="N_PREFIX=\${N_PREFIX-$N_PREFIX}" --target_file="$n_install_dir/bin/n"
# Modify the default N_PREFIX in n script
ynh_replace_string --match_string="^N_PREFIX=\${N_PREFIX-.*}$" --replace_string="N_PREFIX=\${N_PREFIX-$N_PREFIX}" --target_file="$n_install_dir/bin/n"
# Restore /usr/local/bin in PATH
PATH=$CLEAR_PATH
# Restore /usr/local/bin in PATH
PATH=$CLEAR_PATH
# And replace the old node binary.
test -x /usr/bin/node_n && mv /usr/bin/node_n /usr/bin/node
test -x /usr/bin/npm_n && mv /usr/bin/npm_n /usr/bin/npm
# And replace the old node binary.
test -x /usr/bin/node_n && mv /usr/bin/node_n /usr/bin/node
test -x /usr/bin/npm_n && mv /usr/bin/npm_n /usr/bin/npm
# Install the requested version of nodejs
uname=$(uname -m)
if [[ $uname =~ aarch64 || $uname =~ arm64 ]]
then
n $nodejs_version --arch=arm64
else
n $nodejs_version
fi
# Install the requested version of nodejs
uname=$(uname --machine)
if [[ $uname =~ aarch64 || $uname =~ arm64 ]]
then
n $nodejs_version --arch=arm64
else
n $nodejs_version
fi
# Find the last "real" version for this major version of node.
real_nodejs_version=$(find $node_version_path/$nodejs_version* -maxdepth 0 | sort --version-sort | tail --lines=1)
real_nodejs_version=$(basename $real_nodejs_version)
# Find the last "real" version for this major version of node.
real_nodejs_version=$(find $node_version_path/$nodejs_version* -maxdepth 0 | sort --version-sort | tail --lines=1)
real_nodejs_version=$(basename $real_nodejs_version)
# Create a symbolic link for this major version if the file doesn't already exist
if [ ! -e "$node_version_path/$nodejs_version" ]
then
ln --symbolic --force --no-target-directory $node_version_path/$real_nodejs_version $node_version_path/$nodejs_version
fi
# Create a symbolic link for this major version if the file doesn't already exist
if [ ! -e "$node_version_path/$nodejs_version" ]
then
ln --symbolic --force --no-target-directory $node_version_path/$real_nodejs_version $node_version_path/$nodejs_version
fi
# Store the ID of this app and the version of node requested for it
echo "$YNH_APP_INSTANCE_NAME:$nodejs_version" | tee --append "$n_install_dir/ynh_app_version"
# Store the ID of this app and the version of node requested for it
echo "$YNH_APP_INSTANCE_NAME:$nodejs_version" | tee --append "$n_install_dir/ynh_app_version"
# Store nodejs_version into the config of this app
ynh_app_setting_set --app=$app --key=nodejs_version --value=$nodejs_version
# Store nodejs_version into the config of this app
ynh_app_setting_set --app=$app --key=nodejs_version --value=$nodejs_version
# Build the update script and set the cronjob
ynh_cron_upgrade_node
# Build the update script and set the cronjob
ynh_cron_upgrade_node
ynh_use_nodejs
ynh_use_nodejs
}
# Remove the version of node used by the app.
@ -142,25 +144,25 @@ ynh_install_nodejs () {
#
# Requires YunoHost version 2.7.12 or higher.
ynh_remove_nodejs () {
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
# Remove the line for this app
sed --in-place "/$YNH_APP_INSTANCE_NAME:$nodejs_version/d" "$n_install_dir/ynh_app_version"
# Remove the line for this app
sed --in-place "/$YNH_APP_INSTANCE_NAME:$nodejs_version/d" "$n_install_dir/ynh_app_version"
# If no other app uses this version of nodejs, remove it.
if ! grep --quiet "$nodejs_version" "$n_install_dir/ynh_app_version"
then
$n_install_dir/bin/n rm $nodejs_version
fi
# If no other app uses this version of nodejs, remove it.
if ! grep --quiet "$nodejs_version" "$n_install_dir/ynh_app_version"
then
$n_install_dir/bin/n rm $nodejs_version
fi
# If no other app uses n, remove n
if [ ! -s "$n_install_dir/ynh_app_version" ]
then
ynh_secure_remove --file="$n_install_dir"
ynh_secure_remove --file="/usr/local/n"
sed --in-place "/N_PREFIX/d" /root/.bashrc
rm -f /etc/cron.daily/node_update
fi
# If no other app uses n, remove n
if [ ! -s "$n_install_dir/ynh_app_version" ]
then
ynh_secure_remove --file="$n_install_dir"
ynh_secure_remove --file="/usr/local/n"
sed --in-place "/N_PREFIX/d" /root/.bashrc
rm --force /etc/cron.daily/node_update
fi
}
# Set a cron design to update your node versions
@ -173,8 +175,8 @@ ynh_remove_nodejs () {
#
# Requires YunoHost version 2.7.12 or higher.
ynh_cron_upgrade_node () {
# Build the update script
cat > "$n_install_dir/node_update.sh" << EOF
# Build the update script
cat > "$n_install_dir/node_update.sh" << EOF
#!/bin/bash
version_path="$node_version_path"
@ -195,26 +197,26 @@ all_real_version=\$(echo "\$all_real_version" | sort --unique)
# Read each major version
while read version
do
echo "Update of the version \$version"
sudo \$n_install_dir/bin/n \$version
echo "Update of the version \$version"
sudo \$n_install_dir/bin/n \$version
# Find the last "real" version for this major version of node.
real_nodejs_version=\$(find \$version_path/\$version* -maxdepth 0 | sort --version-sort | tail --lines=1)
real_nodejs_version=\$(basename \$real_nodejs_version)
# Find the last "real" version for this major version of node.
real_nodejs_version=\$(find \$version_path/\$version* -maxdepth 0 | sort --version-sort | tail --lines=1)
real_nodejs_version=\$(basename \$real_nodejs_version)
# Update the symbolic link for this version
sudo ln --symbolic --force --no-target-directory \$version_path/\$real_nodejs_version \$version_path/\$version
# Update the symbolic link for this version
sudo ln --symbolic --force --no-target-directory \$version_path/\$real_nodejs_version \$version_path/\$version
done <<< "\$(echo "\$all_real_version")"
EOF
chmod +x "$n_install_dir/node_update.sh"
chmod +x "$n_install_dir/node_update.sh"
# Build the cronjob
cat > "/etc/cron.daily/node_update" << EOF
# Build the cronjob
cat > "/etc/cron.daily/node_update" << EOF
#!/bin/bash
$n_install_dir/node_update.sh >> $n_install_dir/node_update.log
EOF
chmod +x "/etc/cron.daily/node_update"
chmod +x "/etc/cron.daily/node_update"
}

View file

@ -1,51 +1,264 @@
#!/bin/bash
readonly YNH_DEFAULT_PHP_VERSION=7.0
# Declare the actual php version to use.
# A packager willing to use another version of php can override the variable into its _common.sh.
YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
# Create a dedicated php-fpm config
#
# usage: ynh_add_fpm_config [--phpversion=7.X]
# | arg: -v, --phpversion - Version of php to use.
# usage 1: ynh_add_fpm_config [--phpversion=7.X] [--use_template] [--package=packages] [--dedicated_service]
# | arg: -v, --phpversion= - Version of php to use.
# | arg: -t, --use_template - Use this helper in template mode.
# | arg: -p, --package= - Additionnal php packages to install
# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one.
#
# -----------------------------------------------------------------------------
#
# usage 2: ynh_add_fpm_config [--phpversion=7.X] --usage=usage --footprint=footprint [--package=packages] [--dedicated_service]
# | arg: -v, --phpversion= - Version of php to use.
# | arg: -f, --footprint= - Memory footprint of the service (low/medium/high).
# low - Less than 20Mb of ram by pool.
# medium - Between 20Mb and 40Mb of ram by pool.
# high - More than 40Mb of ram by pool.
# Or specify exactly the footprint, the load of the service as Mb by pool instead of having a standard value.
# To have this value, use the following command and stress the service.
# watch -n0.5 ps -o user,cmd,%cpu,rss -u APP
#
# | arg: -u, --usage= - Expected usage of the service (low/medium/high).
# low - Personal usage, behind the sso.
# medium - Low usage, few people or/and publicly accessible.
# high - High usage, frequently visited website.
#
# | arg: -p, --package= - Additionnal php packages to install for a specific version of php
# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one.
#
#
# The footprint of the service will be used to defined the maximum footprint we can allow, which is half the maximum RAM.
# So it will be used to defined 'pm.max_children'
# A lower value for the footprint will allow more children for 'pm.max_children'. And so for
# 'pm.start_servers', 'pm.min_spare_servers' and 'pm.max_spare_servers' which are defined from the
# value of 'pm.max_children'
# NOTE: 'pm.max_children' can't exceed 4 times the number of processor's cores.
#
# The usage value will defined the way php will handle the children for the pool.
# A value set as 'low' will set the process manager to 'ondemand'. Children will start only if the
# service is used, otherwise no child will stay alive. This config gives the lower footprint when the
# service is idle. But will use more proc since it has to start a child as soon it's used.
# Set as 'medium', the process manager will be at dynamic. If the service is idle, a number of children
# equal to pm.min_spare_servers will stay alive. So the service can be quick to answer to any request.
# The number of children can grow if needed. The footprint can stay low if the service is idle, but
# not null. The impact on the proc is a little bit less than 'ondemand' as there's always a few
# children already available.
# Set as 'high', the process manager will be set at 'static'. There will be always as many children as
# 'pm.max_children', the footprint is important (but will be set as maximum a quarter of the maximum
# RAM) but the impact on the proc is lower. The service will be quick to answer as there's always many
# children ready to answer.
#
# Requires YunoHost version 2.7.2 or higher.
# Requires YunoHost version 3.5.1 or higher for the argument --phpversion
# Requires YunoHost version 3.8.1 or higher for the arguments --use_template, --usage, --footprint, --package and --dedicated_service
ynh_add_fpm_config () {
# Declare an array to define the options of this helper.
local legacy_args=v
declare -Ar args_array=( [v]=phpversion= )
local phpversion
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=vtufpd
local -A args_array=( [v]=phpversion= [t]=use_template [u]=usage= [f]=footprint= [p]=package= [d]=dedicated_service )
local phpversion
local use_template
local usage
local footprint
local package
local dedicated_service
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
package=${package:-}
# Configure PHP-FPM 7.0 by default
phpversion="${phpversion:-7.0}"
# The default behaviour is to use the template.
use_template="${use_template:-1}"
usage="${usage:-}"
footprint="${footprint:-}"
if [ -n "$usage" ] || [ -n "$footprint" ]; then
use_template=0
fi
# Do not use a dedicated service by default
dedicated_service=${dedicated_service:-0}
local fpm_config_dir="/etc/php/$phpversion/fpm"
local fpm_service="php${phpversion}-fpm"
# Configure PHP-FPM 5 on Debian Jessie
if [ "$(ynh_get_debian_release)" == "jessie" ]; then
fpm_config_dir="/etc/php5/fpm"
fpm_service="php5-fpm"
fi
ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir"
ynh_app_setting_set --app=$app --key=fpm_service --value="$fpm_service"
finalphpconf="$fpm_config_dir/pool.d/$app.conf"
ynh_backup_if_checksum_is_different --file="$finalphpconf"
sudo cp ../conf/php-fpm.conf "$finalphpconf"
ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$finalphpconf"
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalphpconf"
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$finalphpconf"
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="$finalphpconf"
sudo chown root: "$finalphpconf"
ynh_store_file_checksum --file="$finalphpconf"
# Set the default PHP-FPM version by default
phpversion="${phpversion:-$YNH_PHP_VERSION}"
if [ -e "../conf/php-fpm.ini" ]
then
echo "Packagers ! Please do not use a separate php ini file, merge your directives in the pool file instead." >&2
finalphpini="$fpm_config_dir/conf.d/20-$app.ini"
ynh_backup_if_checksum_is_different "$finalphpini"
sudo cp ../conf/php-fpm.ini "$finalphpini"
sudo chown root: "$finalphpini"
ynh_store_file_checksum "$finalphpini"
fi
ynh_systemd_action --service_name=$fpm_service --action=reload
# If the requested php version is not the default version for YunoHost
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ]
then
# If the argument --package is used, add the packages to ynh_install_php to install them from sury
if [ -n "$package" ]
then
local additionnal_packages="--package=$package"
else
local additionnal_packages=""
fi
# Install this specific version of php.
ynh_install_php --phpversion="$phpversion" "$additionnal_packages"
elif [ -n "$package" ]
then
# Install the additionnal packages from the default repository
ynh_add_app_dependencies --package="$package"
fi
if [ $dedicated_service -eq 1 ]
then
local fpm_service="${app}-phpfpm"
local fpm_config_dir="/etc/php/$phpversion/dedicated-fpm"
else
local fpm_service="php${phpversion}-fpm"
local fpm_config_dir="/etc/php/$phpversion/fpm"
fi
# Configure PHP-FPM 5 on Debian Jessie
if [ "$(ynh_get_debian_release)" == "jessie" ]
then
fpm_config_dir="/etc/php5/fpm"
fpm_service="php5-fpm"
fi
# Create the directory for fpm pools
mkdir --parents "$fpm_config_dir/pool.d"
ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir"
ynh_app_setting_set --app=$app --key=fpm_service --value="$fpm_service"
ynh_app_setting_set --app=$app --key=fpm_dedicated_service --value="$dedicated_service"
ynh_app_setting_set --app=$app --key=phpversion --value=$phpversion
finalphpconf="$fpm_config_dir/pool.d/$app.conf"
# Migrate from mutual php service to dedicated one.
if [ $dedicated_service -eq 1 ]
then
local old_fpm_config_dir="/etc/php/$phpversion/fpm"
# If a config file exist in the common pool, move it.
if [ -e "$old_fpm_config_dir/pool.d/$app.conf" ]
then
ynh_print_info --message="Migrate to a dedicated php-fpm service for $app."
# Create a backup of the old file before migration
ynh_backup_if_checksum_is_different --file="$old_fpm_config_dir/pool.d/$app.conf"
# Remove the old php config file
ynh_secure_remove --file="$old_fpm_config_dir/pool.d/$app.conf"
# Reload php to release the socket and allow the dedicated service to use it
ynh_systemd_action --service_name=php${phpversion}-fpm --action=reload
fi
fi
ynh_backup_if_checksum_is_different --file="$finalphpconf"
if [ $use_template -eq 1 ]
then
# Usage 1, use the template in ../conf/php-fpm.conf
cp ../conf/php-fpm.conf "$finalphpconf"
ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$finalphpconf"
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalphpconf"
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$finalphpconf"
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="$finalphpconf"
else
# Usage 2, generate a php-fpm config file with ynh_get_scalable_phpfpm
# Store settings
ynh_app_setting_set --app=$app --key=fpm_footprint --value=$footprint
ynh_app_setting_set --app=$app --key=fpm_usage --value=$usage
# Define the values to use for the configuration of php.
ynh_get_scalable_phpfpm --usage=$usage --footprint=$footprint
# Copy the default file
cp "/etc/php/$phpversion/fpm/pool.d/www.conf" "$finalphpconf"
# Replace standard variables into the default file
ynh_replace_string --match_string="^\[www\]" --replace_string="[$app]" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*listen = .*" --replace_string="listen = /var/run/php/php$phpversion-fpm-$app.sock" --target_file="$finalphpconf"
ynh_replace_string --match_string="^user = .*" --replace_string="user = $app" --target_file="$finalphpconf"
ynh_replace_string --match_string="^group = .*" --replace_string="group = $app" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*chdir = .*" --replace_string="chdir = $final_path" --target_file="$finalphpconf"
# Configure fpm children
ynh_replace_string --match_string=".*pm = .*" --replace_string="pm = $php_pm" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_children = .*" --replace_string="pm.max_children = $php_max_children" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_requests = .*" --replace_string="pm.max_requests = 500" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*request_terminate_timeout = .*" --replace_string="request_terminate_timeout = 1d" --target_file="$finalphpconf"
if [ "$php_pm" = "dynamic" ]
then
ynh_replace_string --match_string=".*pm.start_servers = .*" --replace_string="pm.start_servers = $php_start_servers" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.min_spare_servers = .*" --replace_string="pm.min_spare_servers = $php_min_spare_servers" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_spare_servers = .*" --replace_string="pm.max_spare_servers = $php_max_spare_servers" --target_file="$finalphpconf"
elif [ "$php_pm" = "ondemand" ]
then
ynh_replace_string --match_string=".*pm.process_idle_timeout = .*" --replace_string="pm.process_idle_timeout = 10s" --target_file="$finalphpconf"
fi
# Comment unused parameters
if [ "$php_pm" != "dynamic" ]
then
ynh_replace_string --match_string=".*\(pm.start_servers = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*\(pm.min_spare_servers = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*\(pm.max_spare_servers = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
fi
if [ "$php_pm" != "ondemand" ]
then
ynh_replace_string --match_string=".*\(pm.process_idle_timeout = .*\)" --replace_string=";\1" --target_file="$finalphpconf"
fi
# Concatene the extra config.
if [ -e ../conf/extra_php-fpm.conf ]; then
cat ../conf/extra_php-fpm.conf >> "$finalphpconf"
fi
fi
chown root: "$finalphpconf"
ynh_store_file_checksum --file="$finalphpconf"
if [ -e "../conf/php-fpm.ini" ]
then
ynh_print_warn -message="Packagers ! Please do not use a separate php ini file, merge your directives in the pool file instead."
finalphpini="$fpm_config_dir/conf.d/20-$app.ini"
ynh_backup_if_checksum_is_different "$finalphpini"
cp ../conf/php-fpm.ini "$finalphpini"
chown root: "$finalphpini"
ynh_store_file_checksum "$finalphpini"
fi
if [ $dedicated_service -eq 1 ]
then
# Create a dedicated php-fpm.conf for the service
local globalphpconf=$fpm_config_dir/php-fpm-$app.conf
cp /etc/php/${phpversion}/fpm/php-fpm.conf $globalphpconf
ynh_replace_string --match_string="^[; ]*pid *=.*" --replace_string="pid = /run/php/php${phpversion}-fpm-$app.pid" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*error_log *=.*" --replace_string="error_log = /var/log/php/fpm-php.$app.log" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*syslog.ident *=.*" --replace_string="syslog.ident = php-fpm-$app" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*include *=.*" --replace_string="include = $finalphpconf" --target_file="$globalphpconf"
# Create a config for a dedicated php-fpm service for the app
echo "[Unit]
Description=PHP $phpversion FastCGI Process Manager for $app
After=network.target
[Service]
Type=notify
PIDFile=/run/php/php${phpversion}-fpm-$app.pid
ExecStart=/usr/sbin/php-fpm$phpversion --nodaemonize --fpm-config $globalphpconf
ExecReload=/bin/kill -USR2 \$MAINPID
[Install]
WantedBy=multi-user.target
" > ../conf/$fpm_service
# Create this dedicated php-fpm service
ynh_add_systemd_config --service=$fpm_service --template=$fpm_service
# Integrate the service in YunoHost admin panel
yunohost service add $fpm_service --log /var/log/php/fpm-php.$app.log --log_type file --description "Php-fpm dedicated to $app"
# Configure log rotate
ynh_use_logrotate --logfile=/var/log/php
# Restart the service, as this service is either stopped or only for this app
ynh_systemd_action --service_name=$fpm_service --action=restart
else
# Reload php, to not impact other parts of the system using php
ynh_systemd_action --service_name=$fpm_service --action=reload
fi
}
# Remove the dedicated php-fpm config
@ -54,14 +267,291 @@ ynh_add_fpm_config () {
#
# Requires YunoHost version 2.7.2 or higher.
ynh_remove_fpm_config () {
local fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service)
# Assume php version 7 if not set
if [ -z "$fpm_config_dir" ]; then
fpm_config_dir="/etc/php/7.0/fpm"
fpm_service="php7.0-fpm"
fi
ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf"
ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini" 2>&1
ynh_systemd_action --service_name=$fpm_service --action=reload
local fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service)
local dedicated_service=$(ynh_app_setting_get --app=$app --key=fpm_dedicated_service)
dedicated_service=${dedicated_service:-0}
# Get the version of php used by this app
local phpversion=$(ynh_app_setting_get $app phpversion)
# Assume default PHP-FPM version by default
phpversion="${phpversion:-$YNH_DEFAULT_PHP_VERSION}"
# Assume default php files if not set
if [ -z "$fpm_config_dir" ]
then
fpm_config_dir="/etc/php/$YNH_DEFAULT_PHP_VERSION/fpm"
fpm_service="php$YNH_DEFAULT_PHP_VERSION-fpm"
fi
if [ $dedicated_service -eq 1 ]
then
# Remove the dedicated service php-fpm service for the app
ynh_remove_systemd_config --service=$fpm_service
# Remove the global php-fpm conf
ynh_secure_remove --file="$fpm_config_dir/php-fpm-$app.conf"
# Remove the service from the list of services known by Yunohost
yunohost service remove $fpm_service
elif ynh_package_is_installed --package="php${phpversion}-fpm"; then
ynh_systemd_action --service_name=$fpm_service --action=reload
fi
ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf"
ynh_exec_warn_less ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini"
# If the php version used is not the default version for YunoHost
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ]
then
# Remove this specific version of php
ynh_remove_php
fi
}
# Install another version of php.
#
# [internal]
#
# usage: ynh_install_php --phpversion=phpversion [--package=packages]
# | arg: -v, --phpversion= - Version of php to install.
# | arg: -p, --package= - Additionnal php packages to install
#
# Requires YunoHost version 3.8.1 or higher.
ynh_install_php () {
# Declare an array to define the options of this helper.
local legacy_args=vp
local -A args_array=( [v]=phpversion= [p]=package= )
local phpversion
local package
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
package=${package:-}
# Store phpversion into the config of this app
ynh_app_setting_set $app phpversion $phpversion
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ]
then
ynh_die "Do not use ynh_install_php to install php$YNH_DEFAULT_PHP_VERSION"
fi
# Create the file if doesn't exist already
touch /etc/php/ynh_app_version
# Do not add twice the same line
if ! grep --quiet "$YNH_APP_INSTANCE_NAME:" "/etc/php/ynh_app_version"
then
# Store the ID of this app and the version of php requested for it
echo "$YNH_APP_INSTANCE_NAME:$phpversion" | tee --append "/etc/php/ynh_app_version"
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
# Install requested dependencies from this extra repository.
# Install php-fpm first, otherwise php will install apache as a dependency.
ynh_add_app_dependencies --package="php${phpversion}-fpm"
ynh_add_app_dependencies --package="php$phpversion php${phpversion}-common $package"
# Set the default php version back as the default version for php-cli.
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
# Pin this extra repository after packages are installed to prevent sury of doing shit
ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version
ynh_pin_repo --package="php${YNH_DEFAULT_PHP_VERSION}*" --pin="origin \"packages.sury.org\"" --priority=600 --name=extra_php_version --append
# Advertise service in admin panel
yunohost service add php${phpversion}-fpm --log "/var/log/php${phpversion}-fpm.log"
}
# Remove the specific version of php used by the app.
#
# [internal]
#
# usage: ynh_install_php
#
# Requires YunoHost version 3.8.1 or higher.
ynh_remove_php () {
# Get the version of php used by this app
local phpversion=$(ynh_app_setting_get $app phpversion)
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ] || [ -z "$phpversion" ]
then
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ]
then
ynh_print_err "Do not use ynh_remove_php to remove php$YNH_DEFAULT_PHP_VERSION !"
fi
return 0
fi
# Create the file if doesn't exist already
touch /etc/php/ynh_app_version
# Remove the line for this app
sed --in-place "/$YNH_APP_INSTANCE_NAME:$phpversion/d" "/etc/php/ynh_app_version"
# If no other app uses this version of php, remove it.
if ! grep --quiet "$phpversion" "/etc/php/ynh_app_version"
then
# Remove the service from the admin panel
if ynh_package_is_installed --package="php${phpversion}-fpm"; then
yunohost service remove php${phpversion}-fpm
fi
# Purge php dependencies for this version.
ynh_package_autopurge "php$phpversion php${phpversion}-fpm php${phpversion}-common"
fi
}
# Define the values to configure php-fpm
#
# [internal]
#
# usage: ynh_get_scalable_phpfpm --usage=usage --footprint=footprint [--print]
# | arg: -f, --footprint= - Memory footprint of the service (low/medium/high).
# low - Less than 20Mb of ram by pool.
# medium - Between 20Mb and 40Mb of ram by pool.
# high - More than 40Mb of ram by pool.
# Or specify exactly the footprint, the load of the service as Mb by pool instead of having a standard value.
# To have this value, use the following command and stress the service.
# watch -n0.5 ps -o user,cmd,%cpu,rss -u APP
#
# | arg: -u, --usage= - Expected usage of the service (low/medium/high).
# low - Personal usage, behind the sso.
# medium - Low usage, few people or/and publicly accessible.
# high - High usage, frequently visited website.
#
# | arg: -p, --print - Print the result (intended for debug purpose only when packaging the app)
ynh_get_scalable_phpfpm () {
local legacy_args=ufp
# Declare an array to define the options of this helper.
local -A args_array=( [u]=usage= [f]=footprint= [p]=print )
local usage
local footprint
local print
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Set all characters as lowercase
footprint=${footprint,,}
usage=${usage,,}
print=${print:-0}
if [ "$footprint" = "low" ]
then
footprint=20
elif [ "$footprint" = "medium" ]
then
footprint=35
elif [ "$footprint" = "high" ]
then
footprint=50
fi
# Define the factor to determine min_spare_servers
# to avoid having too few children ready to start for heavy apps
if [ $footprint -le 20 ]
then
min_spare_servers_factor=8
elif [ $footprint -le 35 ]
then
min_spare_servers_factor=5
else
min_spare_servers_factor=3
fi
# Define the way the process manager handle child processes.
if [ "$usage" = "low" ]
then
php_pm=ondemand
elif [ "$usage" = "medium" ]
then
php_pm=dynamic
elif [ "$usage" = "high" ]
then
php_pm=static
else
ynh_die --message="Does not recognize '$usage' as an usage value."
fi
# Get the total of RAM available, except swap.
local max_ram=$(ynh_get_ram --total --ignore_swap)
at_least_one() {
# Do not allow value below 1
if [ $1 -le 0 ]
then
echo 1
else
echo $1
fi
}
# Define pm.max_children
# The value of pm.max_children is the total amount of ram divide by 2 and divide again by the footprint of a pool for this app.
# So if php-fpm start the maximum of children, it won't exceed half of the ram.
php_max_children=$(( $max_ram / 2 / $footprint ))
# If process manager is set as static, use half less children.
# Used as static, there's always as many children as the value of pm.max_children
if [ "$php_pm" = "static" ]
then
php_max_children=$(( $php_max_children / 2 ))
fi
php_max_children=$(at_least_one $php_max_children)
# To not overload the proc, limit the number of children to 4 times the number of cores.
local core_number=$(nproc)
local max_proc=$(( $core_number * 4 ))
if [ $php_max_children -gt $max_proc ]
then
php_max_children=$max_proc
fi
# Get a potential forced value for php_max_children
local php_forced_max_children=$(ynh_app_setting_get --app=$app --key=php_forced_max_children)
if [ -n "$php_forced_max_children" ]; then
php_max_children=$php_forced_max_children
fi
if [ "$php_pm" = "dynamic" ]
then
# Define pm.start_servers, pm.min_spare_servers and pm.max_spare_servers for a dynamic process manager
php_min_spare_servers=$(( $php_max_children / $min_spare_servers_factor ))
php_min_spare_servers=$(at_least_one $php_min_spare_servers)
php_max_spare_servers=$(( $php_max_children / 2 ))
php_max_spare_servers=$(at_least_one $php_max_spare_servers)
php_start_servers=$(( $php_min_spare_servers + ( $php_max_spare_servers - $php_min_spare_servers ) /2 ))
php_start_servers=$(at_least_one $php_start_servers)
else
php_min_spare_servers=0
php_max_spare_servers=0
php_start_servers=0
fi
if [ $print -eq 1 ]
then
ynh_debug --message="Footprint=${footprint}Mb by pool."
ynh_debug --message="Process manager=$php_pm"
ynh_debug --message="Max RAM=${max_ram}Mb"
if [ "$php_pm" != "static" ]
then
ynh_debug --message="\nMax estimated footprint=$(( $php_max_children * $footprint ))"
ynh_debug --message="Min estimated footprint=$(( $php_min_spare_servers * $footprint ))"
fi
if [ "$php_pm" = "dynamic" ]
then
ynh_debug --message="Estimated average footprint=$(( $php_max_spare_servers * $footprint ))"
elif [ "$php_pm" = "static" ]
then
ynh_debug --message="Estimated footprint=$(( $php_max_children * $footprint ))"
fi
ynh_debug --message="\nRaw php-fpm values:"
ynh_debug --message="pm.max_children = $php_max_children"
if [ "$php_pm" = "dynamic" ]
then
ynh_debug --message="pm.start_servers = $php_start_servers"
ynh_debug --message="pm.min_spare_servers = $php_min_spare_servers"
ynh_debug --message="pm.max_spare_servers = $php_max_spare_servers"
fi
fi
}

View file

@ -9,65 +9,65 @@ PSQL_ROOT_PWD_FILE=/etc/yunohost/psql
# ynh_psql_connect_as 'user' 'pass' < /path/to/file.sql
#
# usage: ynh_psql_connect_as --user=user --password=password [--database=database]
# | arg: -u, --user - the user name to connect as
# | arg: -p, --password - the user password
# | arg: -d, --database - the database to connect to
# | arg: -u, --user= - the user name to connect as
# | arg: -p, --password= - the user password
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_connect_as() {
# Declare an array to define the options of this helper.
local legacy_args=upd
declare -Ar args_array=([u]=user= [p]=password= [d]=database=)
local user
local password
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
# Declare an array to define the options of this helper.
local legacy_args=upd
local -A args_array=([u]=user= [p]=password= [d]=database=)
local user
local password
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
sudo --login --user=postgres PGUSER="$user" PGPASSWORD="$password" psql "$database"
sudo --login --user=postgres PGUSER="$user" PGPASSWORD="$password" psql "$database"
}
# Execute a command as root user
#
# usage: ynh_psql_execute_as_root --sql=sql [--database=database]
# | arg: -s, --sql - the SQL command to execute
# | arg: -d, --database - the database to connect to
# | arg: -s, --sql= - the SQL command to execute
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_execute_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=sd
declare -Ar args_array=([s]=sql= [d]=database=)
local sql
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
# Declare an array to define the options of this helper.
local legacy_args=sd
local -A args_array=([s]=sql= [d]=database=)
local sql
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
ynh_psql_connect_as --user="postgres" --password="$(sudo cat $PSQL_ROOT_PWD_FILE)" \
--database="$database" <<<"$sql"
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
--database="$database" <<<"$sql"
}
# Execute a command from a file as root user
#
# usage: ynh_psql_execute_file_as_root --file=file [--database=database]
# | arg: -f, --file - the file containing SQL commands
# | arg: -d, --database - the database to connect to
# | arg: -f, --file= - the file containing SQL commands
# | arg: -d, --database= - the database to connect to
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_execute_file_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=fd
declare -Ar args_array=([f]=file= [d]=database=)
local file
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
# Declare an array to define the options of this helper.
local legacy_args=fd
local -A args_array=([f]=file= [d]=database=)
local file
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
database="${database:-}"
ynh_psql_connect_as --user="postgres" --password="$(sudo cat $PSQL_ROOT_PWD_FILE)" \
--database="$database" <"$file"
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
--database="$database" <"$file"
}
# Create a database and grant optionnaly privilegies to a user
@ -80,17 +80,18 @@ ynh_psql_execute_file_as_root() {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_create_db() {
local db=$1
local user=${2:-}
local db=$1
local user=${2:-}
local sql="CREATE DATABASE ${db};"
local sql="CREATE DATABASE ${db};"
# grant all privilegies to user
if [ -n "$user" ]; then
sql+="GRANT ALL PRIVILEGES ON DATABASE ${db} TO ${user} WITH GRANT OPTION;"
fi
# grant all privilegies to user
if [ -n "$user" ]; then
sql+="ALTER DATABASE ${db} OWNER TO ${user};"
sql+="GRANT ALL PRIVILEGES ON DATABASE ${db} TO ${user} WITH GRANT OPTION;"
fi
ynh_psql_execute_as_root --sql="$sql"
ynh_psql_execute_as_root --sql="$sql"
}
# Drop a database
@ -105,12 +106,12 @@ ynh_psql_create_db() {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_drop_db() {
local db=$1
# First, force disconnection of all clients connected to the database
# https://stackoverflow.com/questions/5408156/how-to-drop-a-postgresql-database-if-there-are-active-connections-to-it
# https://dba.stackexchange.com/questions/16426/how-to-drop-all-connections-to-a-specific-database-without-stopping-the-server
ynh_psql_execute_as_root --sql="SELECT pg_terminate_backend (pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$db';" --database="$db"
sudo --login --user=postgres dropdb $db
local db=$1
# First, force disconnection of all clients connected to the database
# https://stackoverflow.com/questions/17449420/postgresql-unable-to-drop-database-because-of-some-auto-connections-to-db
ynh_psql_execute_as_root --sql="REVOKE CONNECT ON DATABASE $db FROM public;" --database="$db"
ynh_psql_execute_as_root --sql="SELECT pg_terminate_backend (pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$db' AND pid <> pg_backend_pid();" --database="$db"
sudo --login --user=postgres dropdb $db
}
# Dump a database
@ -118,19 +119,19 @@ ynh_psql_drop_db() {
# example: ynh_psql_dump_db 'roundcube' > ./dump.sql
#
# usage: ynh_psql_dump_db --database=database
# | arg: -d, --database - the database name to dump
# | arg: -d, --database= - the database name to dump
# | ret: the psqldump output
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_dump_db() {
# Declare an array to define the options of this helper.
local legacy_args=d
declare -Ar args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
sudo --login --user=postgres pg_dump "$database"
sudo --login --user=postgres pg_dump "$database"
}
# Create a user
@ -143,47 +144,55 @@ ynh_psql_dump_db() {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_create_user() {
local user=$1
local pwd=$2
ynh_psql_execute_as_root --sql="CREATE USER $user WITH ENCRYPTED PASSWORD '$pwd'"
local user=$1
local pwd=$2
ynh_psql_execute_as_root --sql="CREATE USER $user WITH ENCRYPTED PASSWORD '$pwd'"
}
# Check if a psql user exists
#
# usage: ynh_psql_user_exists --user=user
# | arg: -u, --user - the user for which to check existence
# | arg: -u, --user= - the user for which to check existence
# | exit: Return 1 if the user doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=([u]=user=)
local user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=u
local -A args_array=([u]=user=)
local user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(sudo cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT rolname FROM pg_roles WHERE rolname='$user';" | grep --quiet "$user" ; then
return 1
else
return 0
fi
if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT rolname FROM pg_roles WHERE rolname='$user';" | grep --quiet "$user"
then
return 1
else
return 0
fi
}
# Check if a psql database exists
#
# usage: ynh_psql_database_exists --database=database
# | arg: -d, --database - the database for which to check existence
# | arg: -d, --database= - the database for which to check existence
# | exit: Return 1 if the database doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_database_exists() {
# Declare an array to define the options of this helper.
local legacy_args=d
declare -Ar args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(sudo cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT datname FROM pg_database WHERE datname='$database';" | grep --quiet "$database"; then
return 1
else
return 0
fi
if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT datname FROM pg_database WHERE datname='$database';" | grep --quiet "$database"
then
return 1
else
return 0
fi
}
# Drop a user
@ -195,110 +204,121 @@ ynh_psql_database_exists() {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_psql_drop_user() {
ynh_psql_execute_as_root --sql="DROP USER ${1};"
ynh_psql_execute_as_root --sql="DROP USER ${1};"
}
# Create a database, an user and its password. Then store the password in the app's config
#
# 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
#
# 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.
#
# 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
# Requires YunoHost version 2.7.13 or higher.
ynh_psql_setup_db() {
# Declare an array to define the options of this helper.
local legacy_args=unp
declare -Ar args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=unp
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
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
db_pwd="${db_pwd:-$new_db_pwd}"
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
db_pwd="${db_pwd:-$new_db_pwd}"
if ! ynh_psql_user_exists --user=$db_user; then
ynh_psql_create_user "$db_user" "$db_pwd"
fi
if ! ynh_psql_user_exists --user=$db_user; then
ynh_psql_create_user "$db_user" "$db_pwd"
fi
ynh_psql_create_db "$db_name" "$db_user" # Create the database
ynh_app_setting_set --app=$app --key=psqlpwd --value=$db_pwd # Store the password in the app's config
ynh_psql_create_db "$db_name" "$db_user" # Create the database
ynh_app_setting_set --app=$app --key=psqlpwd --value=$db_pwd # Store the password in the app's config
}
# Remove a database if it exists, and the associated user
#
# usage: ynh_psql_remove_db --db_user=user --db_name=name
# | arg: -u, --db_user - Owner of the database
# | arg: -n, --db_name - Name of the database
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
#
# Requires YunoHost version 2.7.13 or higher.
ynh_psql_remove_db() {
# Declare an array to define the options of this helper.
local legacy_args=un
declare -Ar args_array=([u]=db_user= [n]=db_name=)
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=un
local -A args_array=([u]=db_user= [n]=db_name=)
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local psql_root_password=$(sudo cat $PSQL_ROOT_PWD_FILE)
if ynh_psql_database_exists --database=$db_name; then # Check if the database exists
ynh_psql_drop_db $db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
if ynh_psql_database_exists --database=$db_name
then # Check if the database exists
ynh_psql_drop_db $db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
# Remove psql user if it exists
if ynh_psql_user_exists --user=$db_user; then
ynh_psql_drop_user $db_user
else
ynh_print_warn --message="User $db_user not found"
fi
# Remove psql user if it exists
if ynh_psql_user_exists --user=$db_user
then
ynh_psql_drop_user $db_user
else
ynh_print_warn --message="User $db_user not found"
fi
}
# Create a master password and set up global settings
# Please always call this script in install and restore scripts
#
# usage: ynh_psql_test_if_first_run
#
# Requires YunoHost version 2.7.13 or higher.
ynh_psql_test_if_first_run() {
if [ -f "$PSQL_ROOT_PWD_FILE" ]; then
echo "PostgreSQL is already installed, no need to create master password"
else
local psql_root_password="$(ynh_string_random)"
echo "$psql_root_password" >$PSQL_ROOT_PWD_FILE
if [ -e /etc/postgresql/9.4/ ]; then
local pg_hba=/etc/postgresql/9.4/main/pg_hba.conf
local logfile=/var/log/postgresql/postgresql-9.4-main.log
elif [ -e /etc/postgresql/9.6/ ]; then
local pg_hba=/etc/postgresql/9.6/main/pg_hba.conf
local logfile=/var/log/postgresql/postgresql-9.6-main.log
else
if dpkg --list | grep -q "ii postgresql-9."
then
ynh_die "It looks like postgresql was not properly configured ? /etc/postgresql/9.* is missing ... Could be due to a locale issue, c.f.https://serverfault.com/questions/426989/postgresql-etc-postgresql-doesnt-exist"
else
ynh_die "postgresql shoud be 9.4 or 9.6 or "
fi
if [ -f "$PSQL_ROOT_PWD_FILE" ]
then
ynh_print_info --message="PostgreSQL is already installed, no need to create master password"
return
fi
fi
local psql_root_password="$(ynh_string_random)"
echo "$psql_root_password" >$PSQL_ROOT_PWD_FILE
ynh_systemd_action --service_name=postgresql --action=start
if [ -e /etc/postgresql/9.4/ ]
then
local pg_hba=/etc/postgresql/9.4/main/pg_hba.conf
local logfile=/var/log/postgresql/postgresql-9.4-main.log
elif [ -e /etc/postgresql/9.6/ ]
then
local pg_hba=/etc/postgresql/9.6/main/pg_hba.conf
local logfile=/var/log/postgresql/postgresql-9.6-main.log
else
if dpkg --list | grep -q "ii postgresql-9."
then
ynh_die "It looks like postgresql was not properly configured ? /etc/postgresql/9.* is missing ... Could be due to a locale issue, c.f.https://serverfault.com/questions/426989/postgresql-etc-postgresql-doesnt-exist"
else
ynh_die "postgresql shoud be 9.4 or 9.6"
fi
fi
sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$psql_root_password'" postgres
ynh_systemd_action --service_name=postgresql --action=start
# 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
ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba"
sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$psql_root_password'" postgres
# Advertise service in admin panel
yunohost service add postgresql --log "$logfile"
# 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
ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba"
systemctl enable postgresql
ynh_systemd_action --service_name=postgresql --action=reload
fi
# Advertise service in admin panel
yunohost service add postgresql --log "$logfile"
systemctl enable postgresql
ynh_systemd_action --service_name=postgresql --action=reload
}

View file

@ -3,14 +3,14 @@
# Get an application setting
#
# usage: ynh_app_setting_get --app=app --key=key
# | arg: -a, --app - the application id
# | arg: -k, --key - the setting to get
# | arg: -a, --app= - the application id
# | arg: -k, --key= - the setting to get
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_get() {
# Declare an array to define the options of this helper.
local legacy_args=ak
declare -Ar args_array=( [a]=app= [k]=key= )
local -A args_array=( [a]=app= [k]=key= )
local app
local key
# Manage arguments with getopts
@ -22,15 +22,15 @@ ynh_app_setting_get() {
# Set an application setting
#
# usage: ynh_app_setting_set --app=app --key=key --value=value
# | arg: -a, --app - the application id
# | arg: -k, --key - the setting name to set
# | arg: -v, --value - the setting value to set
# | arg: -a, --app= - the application id
# | arg: -k, --key= - the setting name to set
# | arg: -v, --value= - the setting value to set
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_set() {
# Declare an array to define the options of this helper.
local legacy_args=akv
declare -Ar args_array=( [a]=app= [k]=key= [v]=value= )
local -A args_array=( [a]=app= [k]=key= [v]=value= )
local app
local key
local value
@ -43,14 +43,14 @@ ynh_app_setting_set() {
# Delete an application setting
#
# usage: ynh_app_setting_delete --app=app --key=key
# | arg: -a, --app - the application id
# | arg: -k, --key - the setting to delete
# | arg: -a, --app= - the application id
# | arg: -k, --key= - the setting to delete
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_delete() {
# Declare an array to define the options of this helper.
local legacy_args=ak
declare -Ar args_array=( [a]=app= [k]=key= )
local -A args_array=( [a]=app= [k]=key= )
local app
local key
# Manage arguments with getopts
@ -59,98 +59,6 @@ ynh_app_setting_delete() {
ynh_app_setting "delete" "$app" "$key"
}
# Add skipped_uris urls into the config
#
# usage: ynh_add_skipped_uris [--appid=app] --url=url1,url2 [--regex]
# | arg: -a, --appid - the application id
# | arg: -u, --url - the urls to add to the sso for this app
# | arg: -r, --regex - Use the key 'skipped_regex' instead of 'skipped_uris'
#
# An URL set with 'skipped_uris' key will be totally ignored by the SSO,
# which means that the access will be public and the logged-in user information will not be passed to the app.
#
# Requires YunoHost version 3.6.0 or higher.
ynh_add_skipped_uris() {
# Declare an array to define the options of this helper.
local legacy_args=aur
declare -Ar args_array=( [a]=appid= [u]=url= [r]=regex )
local appid
local url
local regex
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
appid={appid:-$app}
regex={regex:-0}
local key=skipped_uris
if [ $regex -eq 1 ]; then
key=skipped_regex
fi
ynh_app_setting_set --app=$appid --key=$key --value="$url"
}
# Add unprotected_uris urls into the config
#
# usage: ynh_add_unprotected_uris [--appid=app] --url=url1,url2 [--regex]
# | arg: -a, --appid - the application id
# | arg: -u, --url - the urls to add to the sso for this app
# | arg: -r, --regex - Use the key 'unprotected_regex' instead of 'unprotected_uris'
#
# An URL set with unprotected_uris key will be accessible publicly, but if an user is logged in,
# his information will be accessible (through HTTP headers) to the app.
#
# Requires YunoHost version 3.6.0 or higher.
ynh_add_unprotected_uris() {
# Declare an array to define the options of this helper.
local legacy_args=aur
declare -Ar args_array=( [a]=appid= [u]=url= [r]=regex )
local appid
local url
local regex
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
appid={appid:-$app}
regex={regex:-0}
local key=unprotected_uris
if [ $regex -eq 1 ]; then
key=unprotected_regex
fi
ynh_app_setting_set --app=$appid --key=$key --value="$url"
}
# Add protected_uris urls into the config
#
# usage: ynh_add_protected_uris [--appid=app] --url=url1,url2 [--regex]
# | arg: -a, --appid - the application id
# | arg: -u, --url - the urls to add to the sso for this app
# | arg: -r, --regex - Use the key 'protected_regex' instead of 'protected_uris'
#
# An URL set with protected_uris will be blocked by the SSO and accessible only to authenticated and authorized users.
#
# Requires YunoHost version 3.6.0 or higher.
ynh_add_protected_uris() {
# Declare an array to define the options of this helper.
local legacy_args=aur
declare -Ar args_array=( [a]=appid= [u]=url= [r]=regex )
local appid
local url
local regex
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
appid={appid:-$app}
regex={regex:-0}
local key=protected_uris
if [ $regex -eq 1 ]; then
key=protected_regex
fi
ynh_app_setting_set --app=$appid --key=$key --value="$url"
}
# Small "hard-coded" interface to avoid calling "yunohost app" directly each
# time dealing with a setting is needed (which may be so slow on ARM boards)
#
@ -158,8 +66,13 @@ ynh_add_protected_uris() {
#
ynh_app_setting()
{
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python - <<EOF
import os, yaml
if [[ "$1" == "delete" ]] && [[ "$3" =~ ^(unprotected|skipped)_ ]]
then
current_value=$(ynh_app_setting_get --app=$app --key=$3)
fi
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python2.7 - <<EOF
import os, yaml, sys
app, action = os.environ['APP'], os.environ['ACTION'].lower()
key, value = os.environ['KEY'], os.environ.get('VALUE', None)
setting_file = "/etc/yunohost/apps/%s/settings.yml" % app
@ -176,12 +89,27 @@ else:
elif action == "set":
if key in ['redirected_urls', 'redirected_regex']:
value = yaml.load(value)
if any(key.startswith(word+"_") for word in ["unprotected", "protected", "skipped"]):
sys.stderr.write("/!\\ Packagers! This app is still using the skipped/protected/unprotected_uris/regex settings which are now obsolete and deprecated... Instead, you should use the new helpers 'ynh_permission_{create,urls,update,delete}' and the 'visitors' group to initialize the public/private access. Check out the documentation at the bottom of yunohost.org/groups_and_permissions to learn how to use the new permission mechanism.\n")
settings[key] = value
else:
raise ValueError("action should either be get, set or delete")
with open(setting_file, "w") as f:
yaml.safe_dump(settings, f, default_flow_style=False)
EOF
# Fucking legacy permission management.
# We need this because app temporarily set the app as unprotected to configure it with curl...
if [[ "$3" =~ ^(unprotected|skipped)_ ]]
then
if [[ "$1" == "set" ]] && [[ "${4:-}" == "/" ]]
then
ynh_permission_update --permission "main" --add "visitors"
elif [[ "$1" == "delete" ]] && [[ "${current_value:-}" == "/" ]] && [[ -n "$(ynh_app_setting_get --app=$2 --key='is_public' )" ]]
then
ynh_permission_update --permission "main" --remove "visitors"
fi
fi
}
# Check availability of a web path
@ -189,20 +117,20 @@ EOF
# example: ynh_webpath_available --domain=some.domain.tld --path_url=/coffee
#
# usage: ynh_webpath_available --domain=domain --path_url=path
# | arg: -d, --domain - the domain/host of the url
# | arg: -p, --path_url - the web path to check the availability of
# | arg: -d, --domain= - the domain/host of the url
# | arg: -p, --path_url= - the web path to check the availability of
#
# Requires YunoHost version 2.6.4 or higher.
ynh_webpath_available () {
# Declare an array to define the options of this helper.
local legacy_args=dp
declare -Ar args_array=( [d]=domain= [p]=path_url= )
local domain
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=dp
local -A args_array=( [d]=domain= [p]=path_url= )
local domain
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
sudo yunohost domain url-available $domain $path_url
yunohost domain url-available $domain $path_url
}
# Register/book a web path for an app
@ -210,90 +138,186 @@ ynh_webpath_available () {
# example: ynh_webpath_register --app=wordpress --domain=some.domain.tld --path_url=/coffee
#
# usage: ynh_webpath_register --app=app --domain=domain --path_url=path
# | arg: -a, --app - the app for which the domain should be registered
# | arg: -d, --domain - the domain/host of the web path
# | arg: -p, --path_url - the web path to be registered
# | arg: -a, --app= - the app for which the domain should be registered
# | arg: -d, --domain= - the domain/host of the web path
# | arg: -p, --path_url= - the web path to be registered
#
# Requires YunoHost version 2.6.4 or higher.
ynh_webpath_register () {
# Declare an array to define the options of this helper.
local legacy_args=adp
declare -Ar args_array=( [a]=app= [d]=domain= [p]=path_url= )
local app
local domain
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=adp
local -A args_array=( [a]=app= [d]=domain= [p]=path_url= )
local app
local domain
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
sudo yunohost app register-url $app $domain $path_url
yunohost app register-url $app $domain $path_url
}
# Create a new permission for the app
#
# usage: ynh_permission_create --app "app" --permission "permission" --defaultdisallow [--urls "url" ["url" ...]]
# | arg: app - the application id
# | arg: permission - the name for the permission (by default a permission named "main" already exist)
# | arg: defaultdisallow - define if all user will be allowed by default
# | arg: urls - the list of urls for the the permission
# example: ynh_permission_create --permission=admin --url=/admin --allowed="alice bob"
#
# usage: ynh_permission_create --permission "permission" [--url=url] [--allowed="group1 group2"]
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" already exist)
# | arg: -u, --url= - (optional) URL for which access will be allowed/forbidden
# | arg: -a, --allowed= - (optional) A list of group/user to allow for the permission
#
# If provided, 'url' is assumed to be relative to the app domain/path if they
# start with '/'. For example:
# / -> domain.tld/app
# /admin -> domain.tld/app/admin
# domain.tld/app/api -> domain.tld/app/api
#
# 'url' can be later treated as a regex if it starts with "re:".
# For example:
# re:/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
# re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_create() {
declare -Ar args_array=( [a]=app= [p]=permission= [d]=defaultdisallow [u]=urls= )
local app
# Declare an array to define the options of this helper.
local legacy_args=pua
local -A args_array=( [p]=permission= [u]=url= [a]=allowed= )
local permission
local defaultdisallow
local urls
local url
local allowed
ynh_handle_getopts_args "$@"
if [[ -n ${defaultdisallow:-} ]]; then
defaultdisallow=",default_allow=False"
url=${url:-}
allowed=${allowed:-}
if [[ -n $url ]]
then
url="'$url'"
else
url="None"
fi
if [[ -n ${urls:-} ]]; then
urls=",urls=['${urls//';'/"','"}']"
if [[ -n $allowed ]]; then
allowed=",allowed=['${allowed//';'/"','"}']"
fi
yunohost tools shell -c "from yunohost.permission import permission_add; permission_add('$app', '$permission' ${defaultdisallow:-} ${urls:-}, sync_perm=False)"
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission', url=$url $allowed , sync_perm=False)"
}
# Remove a permission for the app (note that when the app is removed all permission is automatically removed)
#
# usage: ynh_permission_remove --app "app" --permission "permission"
# | arg: app - the application id
# | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
ynh_permission_remove() {
declare -Ar args_array=( [a]=app= [p]=permission= )
local app
# example: ynh_permission_delete --permission=editors
#
# usage: ynh_permission_delete --permission="permission"
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_delete() {
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=permission= )
local permission
ynh_handle_getopts_args "$@"
yunohost tools shell -c "from yunohost.permission import permission_remove; permission_remove('$app', '$permission', sync_perm=False)"
yunohost tools shell -c "from yunohost.permission import permission_delete; permission_delete('$app.$permission', sync_perm=False)"
}
# Add a path managed by the SSO
# Check if a permission exists
#
# usage: ynh_permission_add_path --app "app" --permission "permission" --url "url" ["url" ...]
# | arg: app - the application id
# | arg: permission - the name for the permission
# | arg: url - the FULL url for the the permission (ex domain.tld/apps/admin)
ynh_permission_add_path() {
declare -Ar args_array=( [a]=app= [p]=permission= [u]=url= )
local app
# usage: ynh_permission_exists --permission=permission
# | arg: -p, --permission= - the permission to check
# | exit: Return 1 if the permission doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_exists() {
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=permission= )
local permission
ynh_handle_getopts_args "$@"
yunohost user permission list --short | grep --word-regexp --quiet "$app.$permission"
}
# Redefine the url associated to a permission
#
# usage: ynh_permission_url --permission="permission" [--url="url"]
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
# | arg: -u, --url= - (optional) URL for which access will be allowed/forbidden
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_url() {
# Declare an array to define the options of this helper.
local legacy_args=pu
local -A args_array=([p]=permission= [u]=url=)
local permission
local url
ynh_handle_getopts_args "$@"
url=${url:-}
yunohost tools shell -c "from yunohost.permission import permission_update; permission_update('$app', '$permission', add_url=['${url//';'/"','"}'], sync_perm=False)"
if [[ -n $url ]]
then
url="'$url'"
else
url="None"
fi
yunohost tools shell -c "from yunohost.permission import permission_url; permission_url('$app.$permission', url=$url)"
}
# Remove a path managed by the SSO
# Update a permission for the app
#
# usage: ynh_permission_del_path --app "app" --permission "permission" --url "url" ["url" ...]
# | arg: app - the application id
# | arg: permission - the name for the permission
# | arg: url - the FULL url for the the permission (ex domain.tld/apps/admin)
ynh_permission_del_path() {
declare -Ar args_array=( [a]=app= [p]=permission= [u]=url= )
local app
# example: ynh_permission_update --permission admin --add=samdoe --remove=all_users
#
# usage: ynh_permission_update --permission="permission" [--add="group1 group2"] [--remove="group1 group2"]
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" already exist)
# | arg: -a, --add= - the list of group or users to enable add to the permission
# | arg: -r, --remove= - the list of group or users to remove from the permission
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_update() {
# Declare an array to define the options of this helper.
local legacy_args=par
local -A args_array=( [p]=permission= [a]=add= [r]=remove= )
local permission
local url
local add
local remove
ynh_handle_getopts_args "$@"
add=${add:-}
remove=${remove:-}
if [[ -n $add ]]; then
add="--add ${add//';'/" "}"
fi
if [[ -n $remove ]]; then
remove="--remove ${remove//';'/" "} "
fi
yunohost user permission update "$app.$permission" $add $remove
}
# Check if a permission has an user
#
# example: ynh_permission_has_user --permission=main --user=visitors
#
# usage: ynh_permission_has_user --permission=permission --user=user
# | arg: -p, --permission= - the permission to check
# | arg: -u, --user= - the user seek in the permission
# | exit: Return 1 if the permission doesn't have that user or doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.7.1 or higher.
ynh_permission_has_user() {
local legacy_args=pu
# Declare an array to define the options of this helper.
local -A args_array=( [p]=permission= [u]=user= )
local permission
local user
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
yunohost tools shell -c "from yunohost.permission import permission_update; permission_update('$app', '$permission', remove_url=['${url//';'/"','"}'], sync_perm=False)"
if ! ynh_permission_exists --permission=$permission
then
return 1
fi
yunohost user permission info "$app.$permission" | grep --word-regexp --quiet "$user"
}

View file

@ -5,29 +5,30 @@
# example: pwd=$(ynh_string_random --length=8)
#
# usage: ynh_string_random [--length=string_length]
# | arg: -l, --length - the string length to generate (default: 24)
# | arg: -l, --length= - the string length to generate (default: 24)
# | ret: the generated string
#
# Requires YunoHost version 2.2.4 or higher.
ynh_string_random() {
# Declare an array to define the options of this helper.
local legacy_args=l
declare -Ar args_array=( [l]=length= )
local -A args_array=( [l]=length= )
local length
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
length=${length:-24}
dd if=/dev/urandom bs=1 count=1000 2> /dev/null \
| tr -c -d 'A-Za-z0-9' \
| sed -n 's/\(.\{'"$length"'\}\).*/\1/p'
| tr --complement --delete 'A-Za-z0-9' \
| sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p'
}
# Substitute/replace a string (or expression) by another in a file
#
# usage: ynh_replace_string --match_string=match_string --replace_string=replace_string --target_file=target_file
# | arg: -m, --match_string - String to be searched and replaced in the file
# | arg: -r, --replace_string - String that will replace matches
# | arg: -f, --target_file - File in which the string will be replaced.
# | arg: -m, --match_string= - String to be searched and replaced in the file
# | arg: -r, --replace_string= - String that will replace matches
# | arg: -f, --target_file= - File in which the string will be replaced.
#
# As this helper is based on sed command, regular expressions and
# references to sub-expressions can be used
@ -35,53 +36,53 @@ ynh_string_random() {
#
# Requires YunoHost version 2.6.4 or higher.
ynh_replace_string () {
# Declare an array to define the options of this helper.
local legacy_args=mrf
declare -Ar args_array=( [m]=match_string= [r]=replace_string= [f]=target_file= )
local match_string
local replace_string
local target_file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=mrf
local -A args_array=( [m]=match_string= [r]=replace_string= [f]=target_file= )
local match_string
local replace_string
local target_file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local delimit=@
# Escape the delimiter if it's in the string.
match_string=${match_string//${delimit}/"\\${delimit}"}
replace_string=${replace_string//${delimit}/"\\${delimit}"}
local delimit=@
# Escape the delimiter if it's in the string.
match_string=${match_string//${delimit}/"\\${delimit}"}
replace_string=${replace_string//${delimit}/"\\${delimit}"}
sudo sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$target_file"
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$target_file"
}
# Substitute/replace a special string by another in a file
#
# usage: ynh_replace_special_string --match_string=match_string --replace_string=replace_string --target_file=target_file
# | arg: -m, --match_string - String to be searched and replaced in the file
# | arg: -r, --replace_string - String that will replace matches
# | arg: -t, --target_file - File in which the string will be replaced.
# | arg: -m, --match_string= - String to be searched and replaced in the file
# | arg: -r, --replace_string= - String that will replace matches
# | arg: -t, --target_file= - File in which the string will be replaced.
#
# This helper will use ynh_replace_string, but as you can use special
# characters, you can't use some regular expressions and sub-expressions.
#
# Requires YunoHost version 2.7.7 or higher.
ynh_replace_special_string () {
# Declare an array to define the options of this helper.
local legacy_args=mrf
declare -Ar args_array=( [m]=match_string= [r]=replace_string= [f]=target_file= )
local match_string
local replace_string
local target_file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=mrf
local -A args_array=( [m]=match_string= [r]=replace_string= [f]=target_file= )
local match_string
local replace_string
local target_file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Escape any backslash to preserve them as simple backslash.
match_string=${match_string//\\/"\\\\"}
replace_string=${replace_string//\\/"\\\\"}
# Escape any backslash to preserve them as simple backslash.
match_string=${match_string//\\/"\\\\"}
replace_string=${replace_string//\\/"\\\\"}
# Escape the & character, who has a special function in sed.
match_string=${match_string//&/"\&"}
replace_string=${replace_string//&/"\&"}
# Escape the & character, who has a special function in sed.
match_string=${match_string//&/"\&"}
replace_string=${replace_string//&/"\&"}
ynh_replace_string --match_string="$match_string" --replace_string="$replace_string" --target_file="$target_file"
ynh_replace_string --match_string="$match_string" --replace_string="$replace_string" --target_file="$target_file"
}
# Sanitize a string intended to be the name of a database
@ -90,24 +91,26 @@ ynh_replace_special_string () {
# example: dbname=$(ynh_sanitize_dbid $app)
#
# usage: ynh_sanitize_dbid --db_name=name
# | arg: -n, --db_name - name to correct/sanitize
# | arg: -n, --db_name= - name to correct/sanitize
# | ret: the corrected name
#
# Requires YunoHost version 2.2.4 or higher.
ynh_sanitize_dbid () {
# Declare an array to define the options of this helper.
local legacy_args=n
declare -Ar args_array=( [n]=db_name= )
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=n
local -A args_array=( [n]=db_name= )
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# We should avoid having - and . in the name of databases. They are replaced by _
echo ${db_name//[-.]/_}
# We should avoid having - and . in the name of databases. They are replaced by _
echo ${db_name//[-.]/_}
}
# Normalize the url path syntax
#
# [internal]
#
# Handle the slash at the beginning of path and its absence at ending
# Return a normalized url path
#
@ -119,23 +122,23 @@ ynh_sanitize_dbid () {
# ynh_normalize_url_path / # -> /
#
# usage: ynh_normalize_url_path --path_url=path_to_normalize
# | arg: -p, --path_url - URL path to normalize before using it
# | arg: -p, --path_url= - URL path to normalize before using it
#
# Requires YunoHost version 2.6.4 or higher.
ynh_normalize_url_path () {
# Declare an array to define the options of this helper.
local legacy_args=p
declare -Ar args_array=( [p]=path_url= )
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=p
local -A args_array=( [p]=path_url= )
local path_url
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
test -n "$path_url" || ynh_die --message="ynh_normalize_url_path expect a URL path as first argument and received nothing."
if [ "${path_url:0:1}" != "/" ]; then # If the first character is not a /
path_url="/$path_url" # Add / at begin of path variable
fi
if [ "${path_url:${#path_url}-1}" == "/" ] && [ ${#path_url} -gt 1 ]; then # If the last character is a / and that not the only character.
path_url="${path_url:0:${#path_url}-1}" # Delete the last character
fi
echo $path_url
test -n "$path_url" || ynh_die --message="ynh_normalize_url_path expect a URL path as first argument and received nothing."
if [ "${path_url:0:1}" != "/" ]; then # If the first character is not a /
path_url="/$path_url" # Add / at begin of path variable
fi
if [ "${path_url:${#path_url}-1}" == "/" ] && [ ${#path_url} -gt 1 ]; then # If the last character is a / and that not the only character.
path_url="${path_url:0:${#path_url}-1}" # Delete the last character
fi
echo $path_url
}

View file

@ -3,8 +3,8 @@
# Create a dedicated systemd config
#
# usage: ynh_add_systemd_config [--service=service] [--template=template]
# | arg: -s, --service - Service name (optionnal, $app by default)
# | arg: -t, --template - Name of template file (optionnal, this is 'systemd' by default, meaning ./conf/systemd.service will be used as template)
# | arg: -s, --service= - Service name (optionnal, $app by default)
# | arg: -t, --template= - Name of template file (optionnal, this is 'systemd' by default, meaning ./conf/systemd.service will be used as template)
#
# This will use the template ../conf/<templatename>.service
# to generate a systemd config, by replacing the following keywords
@ -14,103 +14,106 @@
# __APP__ by $app
# __FINALPATH__ by $final_path
#
# Requires YunoHost version 2.7.2 or higher.
# Requires YunoHost version 2.7.11 or higher.
ynh_add_systemd_config () {
# Declare an array to define the options of this helper.
local legacy_args=st
declare -Ar args_array=( [s]=service= [t]=template= )
local service
local template
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service="${service:-$app}"
local template="${template:-systemd.service}"
# Declare an array to define the options of this helper.
local legacy_args=st
local -A args_array=( [s]=service= [t]=template= )
local service
local template
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service="${service:-$app}"
local template="${template:-systemd.service}"
finalsystemdconf="/etc/systemd/system/$service.service"
ynh_backup_if_checksum_is_different --file="$finalsystemdconf"
sudo cp ../conf/$template "$finalsystemdconf"
finalsystemdconf="/etc/systemd/system/$service.service"
ynh_backup_if_checksum_is_different --file="$finalsystemdconf"
cp ../conf/$template "$finalsystemdconf"
# To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable.
# Substitute in a nginx config file only if the variable is not empty
if test -n "${final_path:-}"; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalsystemdconf"
fi
if test -n "${app:-}"; then
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$finalsystemdconf"
fi
ynh_store_file_checksum --file="$finalsystemdconf"
# To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable.
# Substitute in a nginx config file only if the variable is not empty
if [ -n "${final_path:-}" ]; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalsystemdconf"
fi
if [ -n "${app:-}" ]; then
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$finalsystemdconf"
fi
ynh_store_file_checksum --file="$finalsystemdconf"
sudo chown root: "$finalsystemdconf"
sudo systemctl enable $service
sudo systemctl daemon-reload
chown root: "$finalsystemdconf"
systemctl enable $service
systemctl daemon-reload
}
# Remove the dedicated systemd config
#
# usage: ynh_remove_systemd_config [--service=service]
# | arg: -s, --service - Service name (optionnal, $app by default)
# | arg: -s, --service= - Service name (optionnal, $app by default)
#
# Requires YunoHost version 2.7.2 or higher.
ynh_remove_systemd_config () {
# Declare an array to define the options of this helper.
local legacy_args=s
declare -Ar args_array=( [s]=service= )
local service
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service="${service:-$app}"
# Declare an array to define the options of this helper.
local legacy_args=s
local -A args_array=( [s]=service= )
local service
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service="${service:-$app}"
local finalsystemdconf="/etc/systemd/system/$service.service"
if [ -e "$finalsystemdconf" ]; then
ynh_systemd_action --service_name=$service --action=stop
systemctl disable $service
ynh_secure_remove --file="$finalsystemdconf"
systemctl daemon-reload
fi
local finalsystemdconf="/etc/systemd/system/$service.service"
if [ -e "$finalsystemdconf" ]
then
ynh_systemd_action --service_name=$service --action=stop
systemctl disable $service
ynh_secure_remove --file="$finalsystemdconf"
systemctl daemon-reload
fi
}
# Start (or other actions) a service, print a log in case of failure and optionnaly wait until the service is completely started
#
# usage: ynh_systemd_action [-n service_name] [-a action] [ [-l "line to match"] [-p log_path] [-t timeout] [-e length] ]
# usage: ynh_systemd_action [--service_name=service_name] [--action=action] [ [--line_match="line to match"] [--log_path=log_path] [--timeout=300] [--length=20] ]
# | arg: -n, --service_name= - Name of the service to start. Default : $app
# | arg: -a, --action= - Action to perform with systemctl. Default: start
# | arg: -l, --line_match= - Line to match - The line to find in the log to attest the service have finished to boot. If not defined it don't wait until the service is completely started. WARNING: When using --line_match, you should always add `ynh_clean_check_starting` into your `ynh_clean_setup` at the beginning of the script. Otherwise, tail will not stop in case of failure of the script. The script will then hang forever.
# | arg: -p, --log_path= - Log file - Path to the log file. Default : /var/log/$app/$app.log
# | arg: -t, --timeout= - Timeout - The maximum time to wait before ending the watching. Default : 300 seconds.
# | arg: -e, --length= - Length of the error log : Default : 20
#
# Requires YunoHost version 3.5.0 or higher.
ynh_systemd_action() {
# Declare an array to define the options of this helper.
local legacy_args=nalpte
declare -Ar args_array=( [n]=service_name= [a]=action= [l]=line_match= [p]=log_path= [t]=timeout= [e]=length= )
local -A args_array=( [n]=service_name= [a]=action= [l]=line_match= [p]=log_path= [t]=timeout= [e]=length= )
local service_name
local action
local line_match
local length
local log_path
local timeout
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local service_name="${service_name:-$app}"
local action=${action:-start}
local log_path="${log_path:-/var/log/$service_name/$service_name.log}"
local length=${length:-20}
local timeout=${timeout:-300}
service_name="${service_name:-$app}"
action=${action:-start}
line_match=${line_match:-}
length=${length:-20}
log_path="${log_path:-/var/log/$service_name/$service_name.log}"
timeout=${timeout:-300}
# Start to read the log
if [[ -n "${line_match:-}" ]]
if [[ -n "$line_match" ]]
then
local templog="$(mktemp)"
# Following the starting of the app in its log
if [ "$log_path" == "systemd" ] ; then
if [ "$log_path" == "systemd" ]
then
# Read the systemd journal
journalctl --unit=$service_name --follow --since=-0 --quiet > "$templog" &
# Get the PID of the journalctl command
local pid_tail=$!
else
# Read the specified log file
tail -F -n0 "$log_path" > "$templog" 2>&1 &
tail --follow=name --retry --lines=0 "$log_path" > "$templog" 2>&1 &
# Get the PID of the tail command
local pid_tail=$!
fi
@ -121,10 +124,20 @@ ynh_systemd_action() {
action="reload-or-restart"
fi
systemctl $action $service_name \
|| ( journalctl --no-pager --lines=$length -u $service_name >&2 \
; test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2 \
; false )
# If the service fails to perform the action
if ! systemctl $action $service_name
then
# Show syslog for this service
ynh_exec_err journalctl --no-pager --lines=$length --unit=$service_name
# If a log is specified for this service, show also the content of this log
if [ -e "$log_path" ]
then
ynh_print_err --message="--"
ynh_exec_err tail --lines=$length "$log_path"
fi
# Fail the app script, since the service failed.
ynh_die
fi
# Start the timeout and try to find line_match
if [[ -n "${line_match:-}" ]]
@ -133,9 +146,9 @@ ynh_systemd_action() {
for i in $(seq 1 $timeout)
do
# Read the log until the sentence is found, that means the app finished to start. Or run until the timeout
if grep --quiet "$line_match" "$templog"
if grep --extended-regexp --quiet "$line_match" "$templog"
then
ynh_print_info --message="The service $service_name has correctly started."
ynh_print_info --message="The service $service_name has correctly executed the action ${action}."
break
fi
if [ $i -eq 3 ]; then
@ -151,10 +164,14 @@ ynh_systemd_action() {
fi
if [ $i -eq $timeout ]
then
ynh_print_warn --message="The service $service_name didn't fully started before the timeout."
ynh_print_warn --message="The service $service_name didn't fully executed the action ${action} before the timeout."
ynh_print_warn --message="Please find here an extract of the end of the log of the service $service_name:"
journalctl --no-pager --lines=$length -u $service_name >&2
test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2
ynh_exec_warn journalctl --no-pager --lines=$length --unit=$service_name
if [ -e "$log_path" ]
then
ynh_print_warn --message="\-\-\-"
ynh_exec_warn tail --lines=$length "$log_path"
fi
fi
ynh_clean_check_starting
fi
@ -164,10 +181,17 @@ ynh_systemd_action() {
# (usually used in ynh_clean_setup scripts)
#
# usage: ynh_clean_check_starting
#
# Requires YunoHost version 3.5.0 or higher.
ynh_clean_check_starting () {
# Stop the execution of tail.
kill -s 15 $pid_tail 2>&1
ynh_secure_remove "$templog" 2>&1
if [ -n "$pid_tail" ]
then
# Stop the execution of tail.
kill -SIGTERM $pid_tail 2>&1
fi
if [ -n "$templog" ]
then
ynh_secure_remove "$templog" 2>&1
fi
}

View file

@ -5,18 +5,19 @@
# example: ynh_user_exists 'toto' || exit 1
#
# usage: ynh_user_exists --username=username
# | arg: -u, --username - the username to check
# | arg: -u, --username= - the username to check
# | exit: Return 1 if the user doesn't exist, 0 otherwise
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=( [u]=username= )
local -A args_array=( [u]=username= )
local username
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
sudo yunohost user list --output-as json | grep -q "\"username\": \"${username}\""
yunohost user list --output-as json | grep --quiet "\"username\": \"${username}\""
}
# Retrieve a YunoHost user information
@ -24,21 +25,21 @@ ynh_user_exists() {
# example: mail=$(ynh_user_get_info 'toto' 'mail')
#
# usage: ynh_user_get_info --username=username --key=key
# | arg: -u, --username - the username to retrieve info from
# | arg: -k, --key - the key to retrieve
# | arg: -u, --username= - the username to retrieve info from
# | arg: -k, --key= - the key to retrieve
# | ret: string - the key's value
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_get_info() {
# Declare an array to define the options of this helper.
local legacy_args=uk
declare -Ar args_array=( [u]=username= [k]=key= )
local -A args_array=( [u]=username= [k]=key= )
local username
local key
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
sudo yunohost user info "$username" --output-as plain | ynh_get_plain_key "$key"
yunohost user info "$username" --output-as plain | ynh_get_plain_key "$key"
}
# Get the list of YunoHost users
@ -50,20 +51,21 @@ ynh_user_get_info() {
#
# Requires YunoHost version 2.4.0 or higher.
ynh_user_list() {
sudo yunohost user list --output-as plain --quiet \
| awk '/^##username$/{getline; print}'
yunohost user list --output-as plain --quiet \
| awk '/^##username$/{getline; print}'
}
# Check if a user exists on the system
#
# usage: ynh_system_user_exists --username=username
# | arg: -u, --username - the username to check
# | arg: -u, --username= - the username to check
# | exit: Return 1 if the user doesn't exist, 0 otherwise
#
# Requires YunoHost version 2.2.4 or higher.
ynh_system_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=( [u]=username= )
local -A args_array=( [u]=username= )
local username
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -74,11 +76,14 @@ ynh_system_user_exists() {
# Check if a group exists on the system
#
# usage: ynh_system_group_exists --group=group
# | arg: -g, --group - the group to check
# | arg: -g, --group= - the group to check
# | exit: Return 1 if the group doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.5.0.2 or higher.
ynh_system_group_exists() {
# Declare an array to define the options of this helper.
local legacy_args=g
declare -Ar args_array=( [g]=group= )
local -A args_array=( [g]=group= )
local group
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -95,49 +100,51 @@ ynh_system_group_exists() {
# ynh_system_user_create --username=discourse --home_dir=/var/www/discourse --use_shell
#
# usage: ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell]
# | arg: -u, --username - Name of the system user that will be create
# | arg: -h, --home_dir - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home
# | arg: -s, --use_shell - Create a user using the default login shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell
# | arg: -u, --username= - Name of the system user that will be create
# | arg: -h, --home_dir= - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home
# | arg: -s, --use_shell - Create a user using the default login shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell
#
# Requires YunoHost version 2.6.4 or higher.
ynh_system_user_create () {
# Declare an array to define the options of this helper.
local legacy_args=uhs
declare -Ar args_array=( [u]=username= [h]=home_dir= [s]=use_shell )
local username
local home_dir
local use_shell
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
use_shell="${use_shell:-0}"
home_dir="${home_dir:-}"
# Declare an array to define the options of this helper.
local legacy_args=uhs
local -A args_array=( [u]=username= [h]=home_dir= [s]=use_shell )
local username
local home_dir
local use_shell
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
use_shell="${use_shell:-0}"
home_dir="${home_dir:-}"
if ! ynh_system_user_exists "$username" # Check if the user exists on the system
then # If the user doesn't exist
if [ -n "$home_dir" ]; then # If a home dir is mentioned
local user_home_dir="-d $home_dir"
else
local user_home_dir="--no-create-home"
fi
if [ $use_shell -eq 1 ]; then # If we want a shell for the user
local shell="" # Use default shell
else
local shell="--shell /usr/sbin/nologin"
fi
useradd $user_home_dir --system --user-group $username $shell || ynh_die "Unable to create $username system account"
fi
if ! ynh_system_user_exists "$username" # Check if the user exists on the system
then # If the user doesn't exist
if [ -n "$home_dir" ]
then # If a home dir is mentioned
local user_home_dir="--home-dir $home_dir"
else
local user_home_dir="--no-create-home"
fi
if [ $use_shell -eq 1 ]
then # If we want a shell for the user
local shell="" # Use default shell
else
local shell="--shell /usr/sbin/nologin"
fi
useradd $user_home_dir --system --user-group $username $shell || ynh_die --message="Unable to create $username system account"
fi
}
# Delete a system user
#
# usage: ynh_system_user_delete --username=user_name
# | arg: -u, --username - Name of the system user that will be create
# | arg: -u, --username= - Name of the system user that will be create
#
# Requires YunoHost version 2.6.4 or higher.
ynh_system_user_delete () {
# Declare an array to define the options of this helper.
local legacy_args=u
declare -Ar args_array=( [u]=username= )
local -A args_array=( [u]=username= )
local username
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -145,14 +152,14 @@ ynh_system_user_delete () {
# Check if the user exists on the system
if ynh_system_user_exists "$username"
then
deluser $username
else
ynh_print_warn --message="The user $username was not found"
deluser $username
else
ynh_print_warn --message="The user $username was not found"
fi
# Check if the group exists on the system
if ynh_system_group_exists "$username"
then
delgroup $username
delgroup $username
fi
}

View file

@ -16,60 +16,26 @@
#
# It prints a warning to inform that the script was failed, and execute the ynh_clean_setup function if used in the app script
#
# Requires YunoHost version 2.6.4 or higher.
ynh_exit_properly () {
local exit_code=$?
if [ "$exit_code" -eq 0 ]; then
exit 0 # Exit without error if the script ended correctly
fi
local exit_code=$?
if [ "$exit_code" -eq 0 ]; then
exit 0 # Exit without error if the script ended correctly
fi
trap '' EXIT # Ignore new exit signals
set +eu # Do not exit anymore if a command fail or if a variable is empty
trap '' EXIT # Ignore new exit signals
# Do not exit anymore if a command fail or if a variable is empty
set +o errexit # set +e
set +o nounset # set +u
# Small tempo to avoid the next message being mixed up with other DEBUG messages
sleep 0.5
# Small tempo to avoid the next message being mixed up with other DEBUG messages
sleep 0.5
ynh_print_err --message="!!\n $app's script has encountered an error. Its execution was cancelled.\n!!"
if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script.
ynh_clean_setup # Call the function to do specific cleaning for the app.
fi
# If the script is executed from the CLI, dump the end of the log that precedes the crash.
if [ "$YNH_INTERFACE" == "cli" ]
then
# Unset xtrace to not spoil the log
set +x
local ynh_log="/var/log/yunohost/yunohost-cli.log"
# Wait for the log to be fill with the data until the crash.
local timeout=0
while ! tail --lines=20 "$ynh_log" | grep --quiet "+ ynh_exit_properly"
do
((timeout++))
if [ $timeout -eq 500 ]; then
break
fi
done
echo -e "\e[34m\e[1mPlease find here an extract of the log before the crash:\e[0m" >&2
# Tail the last 30 lines of log of YunoHost
# But remove all lines after "ynh_exit_properly"
# Remove the timestamp at the beginning of the line
# Remove "yunohost.hook..."
# Add DEBUG and color it at the beginning of each log line.
echo -e "$(tail --lines=30 "$ynh_log" \
| sed '1,/+ ynh_exit_properly/!d' \
| sed 's/^[[:digit:]: ,-]*//g' \
| sed 's/ *yunohost.hook.*\]/ -/g' \
| sed 's/^WARNING /&/g' \
| sed 's/^DEBUG /& /g' \
| sed 's/^INFO /& /g' \
| sed 's/^/\\e[34m\\e[1m[DEBUG]\\e[0m: /g')" >&2
set -x
fi
if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script.
ynh_clean_setup # Call the function to do specific cleaning for the app.
fi
ynh_die # Exit with error status
ynh_die # Exit with error status
}
# Exits if an error occurs during the execution of the script.
@ -83,12 +49,17 @@ ynh_exit_properly () {
#
# Requires YunoHost version 2.6.4 or higher.
ynh_abort_if_errors () {
set -eu # Exit if a command fail, and if a variable is used unset.
trap ynh_exit_properly EXIT # Capturing exit signals on shell script
set -o errexit # set -e; Exit if a command fail
set -o nounset # set -u; And if a variable is used unset
trap ynh_exit_properly EXIT # Capturing exit signals on shell script
}
# Download, check integrity, uncompress and patch the source from app.src
#
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id]
# | arg: -d, --dest_dir= - Directory where to setup sources
# | arg: -s, --source_id= - Name of the app, if the package contains more than one app
#
# The file conf/app.src need to contains:
#
# SOURCE_URL=Address to download the app archive
@ -127,16 +98,11 @@ ynh_abort_if_errors () {
# Finally, patches named sources/patches/${src_id}-*.patch and extra files in
# sources/extra_files/$src_id will be applied to dest_dir
#
#
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id]
# | arg: -d, --dest_dir - Directory where to setup sources
# | arg: -s, --source_id - Name of the app, if the package contains more than one app
#
# Requires YunoHost version 2.6.4 or higher.
ynh_setup_source () {
# Declare an array to define the options of this helper.
local legacy_args=ds
declare -Ar args_array=( [d]=dest_dir= [s]=source_id= )
local -A args_array=( [d]=dest_dir= [s]=source_id= )
local dest_dir
local source_id
# Manage arguments with getopts
@ -152,13 +118,13 @@ ynh_setup_source () {
# Load value from configuration file (see above for a small doc about this file
# format)
local src_url=$(grep 'SOURCE_URL=' "$src_file_path" | cut -d= -f2-)
local src_sum=$(grep 'SOURCE_SUM=' "$src_file_path" | cut -d= -f2-)
local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$src_file_path" | cut -d= -f2-)
local src_format=$(grep 'SOURCE_FORMAT=' "$src_file_path" | cut -d= -f2-)
local src_extract=$(grep 'SOURCE_EXTRACT=' "$src_file_path" | cut -d= -f2-)
local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$src_file_path" | cut -d= -f2-)
local src_filename=$(grep 'SOURCE_FILENAME=' "$src_file_path" | cut -d= -f2-)
local src_url=$(grep 'SOURCE_URL=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_sum=$(grep 'SOURCE_SUM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_format=$(grep 'SOURCE_FORMAT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_extract=$(grep 'SOURCE_EXTRACT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_filename=$(grep 'SOURCE_FILENAME=' "$src_file_path" | cut --delimiter='=' --fields=2-)
# Default value
src_sumprg=${src_sumprg:-sha256sum}
@ -166,7 +132,7 @@ ynh_setup_source () {
src_format=${src_format:-tar.gz}
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
src_extract=${src_extract:-true}
if [ "$src_filename" = "" ] ; then
if [ "$src_filename" = "" ]; then
src_filename="${source_id}.${src_format}"
fi
local local_src="/opt/yunohost-apps-src/${YNH_APP_ID}/${src_filename}"
@ -175,15 +141,15 @@ ynh_setup_source () {
then # Use the local source file if it is present
cp $local_src $src_filename
else # If not, download the source
local out=`wget -nv -O $src_filename $src_url 2>&1` || ynh_print_err --message="$out"
local out=`wget --no-verbose --output-document=$src_filename $src_url 2>&1` || ynh_print_err --message="$out"
fi
# Check the control sum
echo "${src_sum} ${src_filename}" | ${src_sumprg} -c --status \
echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status \
|| ynh_die --message="Corrupt source"
# Extract source into the app dir
mkdir -p "$dest_dir"
mkdir --parents "$dest_dir"
if ! "$src_extract"
then
@ -192,10 +158,11 @@ ynh_setup_source () {
then
# Zip format
# Using of a temp directory, because unzip doesn't manage --strip-components
if $src_in_subdir ; then
local tmp_dir=$(mktemp -d)
if $src_in_subdir
then
local tmp_dir=$(mktemp --directory)
unzip -quo $src_filename -d "$tmp_dir"
cp -a $tmp_dir/*/. "$dest_dir"
cp --archive $tmp_dir/*/. "$dest_dir"
ynh_secure_remove --file="$tmp_dir"
else
unzip -quo $src_filename -d "$dest_dir"
@ -204,40 +171,40 @@ ynh_setup_source () {
local strip=""
if [ "$src_in_subdir" != "false" ]
then
if [ "$src_in_subdir" == "true" ]; then
if [ "$src_in_subdir" == "true" ]
then
local sub_dirs=1
else
local sub_dirs="$src_in_subdir"
fi
strip="--strip-components $sub_dirs"
fi
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]] ; then
tar -xf $src_filename -C "$dest_dir" $strip
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]]
then
tar --extract --file=$src_filename --directory="$dest_dir" $strip
else
ynh_die --message="Archive format unrecognized."
fi
fi
# Apply patches
if (( $(find $YNH_CWD/../sources/patches/ -type f -name "${source_id}-*.patch" 2> /dev/null | wc -l) > "0" )); then
local old_dir=$(pwd)
(cd "$dest_dir" \
&& for p in $YNH_CWD/../sources/patches/${source_id}-*.patch; do \
patch -p1 < $p; done) \
|| ynh_die --message="Unable to apply patches"
cd $old_dir
if (( $(find $YNH_CWD/../sources/patches/ -type f -name "${source_id}-*.patch" 2> /dev/null | wc --lines) > "0" ))
then
(cd "$dest_dir"
for p in $YNH_CWD/../sources/patches/${source_id}-*.patch
do
patch --strip=1 < $p
done) || ynh_die --message="Unable to apply patches"
fi
# Add supplementary files
if test -e "$YNH_CWD/../sources/extra_files/${source_id}"; then
cp -a $YNH_CWD/../sources/extra_files/$source_id/. "$dest_dir"
cp --archive $YNH_CWD/../sources/extra_files/$source_id/. "$dest_dir"
fi
}
# Curl abstraction to help with POST requests to local pages (such as installation forms)
#
# $domain and $path_url should be defined externally (and correspond to the domain.tld and the /path (of the app?))
#
# example: ynh_local_curl "/install.php?installButton" "foo=$var1" "bar=$var2"
#
# usage: ynh_local_curl "page_uri" "key1=value1" "key2=value2" ...
@ -246,6 +213,10 @@ ynh_setup_source () {
# | arg: key2=value2 - (Optionnal) Another POST key and corresponding value
# | arg: ... - (Optionnal) More POST keys and values
#
# For multiple calls, cookies are persisted between each call for the same app
#
# $domain and $path_url should be defined externally (and correspond to the domain.tld and the /path (of the app?))
#
# Requires YunoHost version 2.6.4 or higher.
ynh_local_curl () {
# Define url of page to curl
@ -274,12 +245,19 @@ ynh_local_curl () {
# Wait untils nginx has fully reloaded (avoid curl fail with http2)
sleep 2
local cookiefile=/tmp/ynh-$app-cookie.txt
touch $cookiefile
chown root $cookiefile
chmod 700 $cookiefile
# Curl the URL
curl --silent --show-error -kL -H "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url"
curl --silent --show-error --insecure --location --header "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url" --cookie-jar $cookiefile --cookie $cookiefile
}
# Render templates with Jinja2
#
# [internal]
#
# Attention : Variables should be exported before calling this helper to be
# accessible inside templates.
#
@ -287,13 +265,13 @@ ynh_local_curl () {
# | arg: some_template - Template file to be rendered
# | arg: output_path - The path where the output will be redirected to
ynh_render_template() {
local template_path=$1
local output_path=$2
mkdir -p "$(dirname $output_path)"
# Taken from https://stackoverflow.com/a/35009576
python2.7 -c 'import os, sys, jinja2; sys.stdout.write(
local template_path=$1
local output_path=$2
mkdir -p "$(dirname $output_path)"
# Taken from https://stackoverflow.com/a/35009576
python2.7 -c 'import os, sys, jinja2; sys.stdout.write(
jinja2.Template(sys.stdin.read()
).render(os.environ));' < $template_path > $output_path
).render(os.environ));' < $template_path > $output_path
}
# Fetch the Debian release codename
@ -303,7 +281,7 @@ ynh_render_template() {
#
# Requires YunoHost version 2.7.12 or higher.
ynh_get_debian_release () {
echo $(lsb_release --codename --short)
echo $(lsb_release --codename --short)
}
# Create a directory under /tmp
@ -318,7 +296,7 @@ ynh_mkdir_tmp() {
ynh_print_warn --message="The helper ynh_mkdir_tmp is deprecated."
ynh_print_warn --message="You should use 'mktemp -d' instead and manage permissions \
properly with chmod/chown."
local TMP_DIR=$(mktemp -d)
local TMP_DIR=$(mktemp --directory)
# Give rights to other users could be a security risk.
# But for retrocompatibility we need it. (This helpers is deprecated)
@ -329,13 +307,13 @@ properly with chmod/chown."
# Remove a file or a directory securely
#
# usage: ynh_secure_remove --file=path_to_remove
# | arg: -f, --file - File or directory to remove
# | arg: -f, --file= - File or directory to remove
#
# Requires YunoHost version 2.6.4 or higher.
ynh_secure_remove () {
# Declare an array to define the options of this helper.
local legacy_args=f
declare -Ar args_array=( [f]=file= )
local -A args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -349,26 +327,29 @@ ynh_secure_remove () {
ynh_print_warn --message="/!\ Packager ! You provided more than one argument to ynh_secure_remove but it will be ignored... Use this helper with one argument at time."
fi
if [[ "$forbidden_path" =~ "$file" \
if [[ -z "$file" ]]
then
ynh_print_warn --message="ynh_secure_remove called with empty argument, ignoring."
elif [[ "$forbidden_path" =~ "$file" \
# Match all paths or subpaths in $forbidden_path
|| "$file" =~ ^/[[:alnum:]]+$ \
# Match all first level paths from / (Like /var, /root, etc...)
|| "${file:${#file}-1}" = "/" ]]
# Match if the path finishes by /. Because it seems there is an empty variable
then
ynh_print_warn --message="Avoid deleting $file."
ynh_print_warn --message="Not deleting '$file' because it is not an acceptable path to delete."
elif [ -e "$file" ]
then
rm --recursive "$file"
else
if [ -e "$file" ]
then
sudo rm -R "$file"
else
ynh_print_info --message="$file wasn't deleted because it doesn't exist."
fi
ynh_print_info --message="'$file' wasn't deleted because it doesn't exist."
fi
}
# Extract a key from a plain command output
#
# [internal]
#
# example: yunohost user info tata --output-as plain | ynh_get_plain_key mail
#
# usage: ynh_get_plain_key key [subkey [subsubkey ...]]
@ -382,12 +363,16 @@ ynh_get_plain_key() {
# an info to be redacted by the core
local key_=$1
shift
while read line; do
if [[ "$founded" == "1" ]] ; then
while read line
do
if [[ "$founded" == "1" ]]
then
[[ "$line" =~ ^${prefix}[^#] ]] && return
echo $line
elif [[ "$line" =~ ^${prefix}${key_}$ ]]; then
if [[ -n "${1:-}" ]]; then
elif [[ "$line" =~ ^${prefix}${key_}$ ]]
then
if [[ -n "${1:-}" ]]
then
prefix+="#"
key_=$1
shift
@ -400,72 +385,75 @@ ynh_get_plain_key() {
# Read the value of a key in a ynh manifest file
#
# usage: ynh_read_manifest manifest key
# | arg: -m, --manifest= - Path of the manifest to read
# | arg: -k, --key= - Name of the key to find
# usage: ynh_read_manifest --manifest="manifest.json" --key="key"
# | arg: -m, --manifest= - Path of the manifest to read
# | arg: -k, --key= - Name of the key to find
# | ret: the value associate to that key
#
# Requires YunoHost version 3.5.0 or higher.
ynh_read_manifest () {
# Declare an array to define the options of this helper.
local legacy_args=mk
declare -Ar args_array=( [m]=manifest= [k]=manifest_key= )
local manifest
local manifest_key
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=mk
local -A args_array=( [m]=manifest= [k]=manifest_key= )
local manifest
local manifest_key
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if [ ! -e "$manifest" ]; then
# If the manifest isn't found, try the common place for backup and restore script.
manifest="../settings/manifest.json"
fi
if [ ! -e "$manifest" ]; then
# If the manifest isn't found, try the common place for backup and restore script.
manifest="../settings/manifest.json"
fi
jq ".$manifest_key" "$manifest" --raw-output
jq ".$manifest_key" "$manifest" --raw-output
}
# Read the upstream version from the manifest
#
# usage: ynh_app_upstream_version [--manifest="manifest.json"]
# | arg: -m, --manifest= - Path of the manifest to read
# | ret: the version number of the upstream app
#
# The version number in the manifest is defined by <upstreamversion>~ynh<packageversion>
# For example : 4.3-2~ynh3
# This include the number before ~ynh
# In the last example it return 4.3-2
#
# usage: ynh_app_upstream_version [-m manifest]
# | arg: -m, --manifest= - Path of the manifest to read
#
# Requires YunoHost version 3.5.0 or higher.
ynh_app_upstream_version () {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=manifest= )
local -A args_array=( [m]=manifest= )
local manifest
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
manifest="${manifest:-../manifest.json}"
version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
echo "${version_key/~ynh*/}"
}
# Read package version from the manifest
#
# usage: ynh_app_package_version [--manifest="manifest.json"]
# | arg: -m, --manifest= - Path of the manifest to read
# | ret: the version number of the package
#
# The version number in the manifest is defined by <upstreamversion>~ynh<packageversion>
# For example : 4.3-2~ynh3
# This include the number after ~ynh
# In the last example it return 3
#
# usage: ynh_app_package_version [-m manifest]
# | arg: -m, --manifest= - Path of the manifest to read
#
# Requires YunoHost version 3.5.0 or higher.
ynh_app_package_version () {
# Declare an array to define the options of this helper.
local legacy_args=m
declare -Ar args_array=( [m]=manifest= )
local -A args_array=( [m]=manifest= )
local manifest
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
manifest="${manifest:-../manifest.json}"
version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
echo "${version_key/*~ynh/}"
}
@ -488,32 +476,34 @@ ynh_app_package_version () {
#
# Requires YunoHost version 3.5.0 or higher.
ynh_check_app_version_changed () {
local force_upgrade=${YNH_FORCE_UPGRADE:-0}
local package_check=${PACKAGE_CHECK_EXEC:-0}
local force_upgrade=${YNH_FORCE_UPGRADE:-0}
local package_check=${PACKAGE_CHECK_EXEC:-0}
# By default, upstream app version has changed
local return_value="UPGRADE_APP"
# By default, upstream app version has changed
local return_value="UPGRADE_APP"
local current_version=$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)
local current_upstream_version="$(ynh_app_upstream_version --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json")"
local update_version=$(ynh_read_manifest --manifest="../manifest.json" --manifest_key="version" || echo 1.0)
local update_upstream_version="$(ynh_app_upstream_version)"
local current_version=$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)
local current_upstream_version="$(ynh_app_upstream_version --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json")"
local update_version=$(ynh_read_manifest --manifest="../manifest.json" --manifest_key="version" || echo 1.0)
local update_upstream_version="$(ynh_app_upstream_version)"
if [ "$current_version" == "$update_version" ] ; then
# Complete versions are the same
if [ "$force_upgrade" != "0" ]
then
ynh_print_info --message="Upgrade forced by YNH_FORCE_UPGRADE."
unset YNH_FORCE_UPGRADE
elif [ "$package_check" != "0" ]
then
ynh_print_info --message="Upgrade forced for package check."
else
ynh_die "Up-to-date, nothing to do" 0
fi
elif [ "$current_upstream_version" == "$update_upstream_version" ] ; then
# Upstream versions are the same, only YunoHost package versions differ
return_value="UPGRADE_PACKAGE"
fi
echo $return_value
if [ "$current_version" == "$update_version" ]
then
# Complete versions are the same
if [ "$force_upgrade" != "0" ]
then
ynh_print_info --message="Upgrade forced by YNH_FORCE_UPGRADE."
unset YNH_FORCE_UPGRADE
elif [ "$package_check" != "0" ]
then
ynh_print_info --message="Upgrade forced for package check."
else
ynh_die "Up-to-date, nothing to do" 0
fi
elif [ "$current_upstream_version" == "$update_upstream_version" ]
then
# Upstream versions are the same, only YunoHost package versions differ
return_value="UPGRADE_PACKAGE"
fi
echo $return_value
}

View file

@ -11,7 +11,7 @@ backup_dir="${1}/conf/ldap"
# Backup the configuration
ynh_backup "/etc/ldap/slapd.conf" "${backup_dir}/slapd.conf"
sudo slapcat -b cn=config -l "${backup_dir}/cn=config.master.ldif"
slapcat -b cn=config -l "${backup_dir}/cn=config.master.ldif"
# Backup the database
sudo slapcat -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif"
slapcat -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif"

View file

@ -38,28 +38,35 @@ do_pre_regen() {
if [[ -f $services_path ]]; then
tmp_services_path="${services_path}-tmp"
new_services_path="${services_path}-new"
sudo cp "$services_path" "$tmp_services_path"
cp "$services_path" "$tmp_services_path"
_update_services "$new_services_path" || {
sudo mv "$tmp_services_path" "$services_path"
mv "$tmp_services_path" "$services_path"
exit 1
}
if [[ -f $new_services_path ]]; then
# replace services.yml with new one
sudo mv "$new_services_path" "$services_path"
sudo mv "$tmp_services_path" "${services_path}-old"
mv "$new_services_path" "$services_path"
mv "$tmp_services_path" "${services_path}-old"
else
sudo rm -f "$tmp_services_path"
rm -f "$tmp_services_path"
fi
else
sudo cp services.yml /etc/yunohost/services.yml
cp services.yml /etc/yunohost/services.yml
fi
mkdir -p "$pending_dir"/etc/etckeeper/
cp etckeeper.conf "$pending_dir"/etc/etckeeper/
# add cron job for diagnosis to be ran at 7h and 19h + a random delay between
# 0 and 10min, meant to avoid every instances running their diagnosis at
# exactly the same time, which may overload the diagnosis server.
mkdir -p $pending_dir/etc/cron.d/
cat > $pending_dir/etc/cron.d/yunohost-diagnosis << EOF
SHELL=/bin/bash
0 7,19 * * * root : YunoHost Diagnosis; sleep \$((RANDOM\\%600)); yunohost diagnosis run > /dev/null
EOF
}
_update_services() {
sudo python2 - << EOF
python2 - << EOF
import yaml
@ -104,6 +111,12 @@ for service, conf in new_services.items():
if conffiles:
services[service]['conffiles'] = conffiles
# Remove legacy /var/log/daemon.log and /var/log/syslog from log entries
# because they are too general. Instead, now the journalctl log is
# returned by default which is more relevant.
if "log" in services[service]:
if services[service]["log"] in ["/var/log/syslog", "/var/log/daemon.log"]:
del services[service]["log"]
if updated:
with open('/etc/yunohost/services.yml-new', 'w') as f:

View file

@ -99,13 +99,13 @@ do_post_regen() {
[[ -f "${index_txt}" ]] || {
if [[ -f "${index_txt}.saved" ]]; then
# use saved database from 2.2
sudo cp "${index_txt}.saved" "${index_txt}"
cp "${index_txt}.saved" "${index_txt}"
elif [[ -f "${index_txt}.old" ]]; then
# ... or use the state-1 database
sudo cp "${index_txt}.old" "${index_txt}"
cp "${index_txt}.old" "${index_txt}"
else
# ... or create an empty one
sudo touch "${index_txt}"
touch "${index_txt}"
fi
}

View file

@ -63,6 +63,9 @@ do_pre_regen() {
cp -a ldap.conf slapd.conf "$ldap_dir"
cp -a sudo.schema mailserver.schema yunohost.schema "$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"
}
@ -81,6 +84,14 @@ do_post_regen() {
chown -R openldap:openldap /etc/ldap/slapd.d/
chown -R root:ssl-cert /etc/yunohost/certs/yunohost.org/
chmod o-rwx /etc/yunohost/certs/yunohost.org/
chmod -R g+rx /etc/yunohost/certs/yunohost.org/
# 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
fi
[ -z "$regen_conf_files" ] && exit 0
@ -126,7 +137,7 @@ do_post_regen() {
# wait a maximum time of 5 minutes
# yes, force-reload behave like a restart
number_of_wait=0
while ! sudo su admin -c '' && ((number_of_wait < 60))
while ! su admin -c '' && ((number_of_wait < 60))
do
sleep 5
((number_of_wait += 1))

View file

@ -14,7 +14,7 @@ do_post_regen() {
regen_conf_files=$1
[[ -z "$regen_conf_files" ]] \
|| sudo service nslcd restart
|| service nslcd restart
}
FORCE=${2:-0}

View file

@ -14,7 +14,7 @@ do_pre_regen() {
# retrieve variables
main_domain=$(cat /etc/yunohost/current_host)
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
domain_list=$(yunohost domain list --output-as plain --quiet)
# install main conf file
cat metronome.cfg.lua \
@ -41,20 +41,25 @@ do_pre_regen() {
do_post_regen() {
regen_conf_files=$1
# fix some permissions
sudo chown -R metronome: /var/lib/metronome/
sudo chown -R metronome: /etc/metronome/conf.d/
# retrieve variables
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
main_domain=$(cat /etc/yunohost/current_host)
domain_list=$(yunohost domain list --exclude-subdomains --output-as plain --quiet)
# create metronome directories for domains
for domain in $domain_list; do
sudo mkdir -p "/var/lib/metronome/${domain//./%2e}/pep"
mkdir -p "/var/lib/metronome/${domain//./%2e}/pep"
# http_upload directory must be writable by metronome and readable by nginx
mkdir -p "/var/xmpp-upload/${domain}/upload"
chmod g+s "/var/xmpp-upload/${domain}/upload"
chown -R metronome:www-data "/var/xmpp-upload/${domain}"
done
# fix some permissions
chown -R metronome: /var/lib/metronome/
chown -R metronome: /etc/metronome/conf.d/
[[ -z "$regen_conf_files" ]] \
|| sudo service metronome restart
|| service metronome restart
}
FORCE=${2:-0}

View file

@ -23,10 +23,12 @@ do_init_regen() {
rm -f "${nginx_dir}/sites-enabled/default"
export compatibility="intermediate"
ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc"
ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf"
# Restart nginx if conf looks good, otherwise display error and exit unhappy
nginx -t 2>/dev/null && service nginx restart || (nginx -t && exit 1)
nginx -t 2>/dev/null || { nginx -t; exit 1; }
systemctl restart nginx || { journalctl --no-pager --lines=10 -u nginx >&2; exit 1; }
exit 0
}
@ -45,10 +47,11 @@ do_pre_regen() {
# retrieve variables
main_domain=$(cat /etc/yunohost/current_host)
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
domain_list=$(yunohost domain list --output-as plain --quiet)
# Support different strategy for security configurations
export compatibility="$(yunohost settings get 'security.nginx.compatibility')"
ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc"
# add domain conf files
for domain in $domain_list; do
@ -102,15 +105,30 @@ do_post_regen() {
[ -z "$regen_conf_files" ] && exit 0
# retrieve variables
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
domain_list=$(yunohost domain list --output-as plain --quiet)
# create NGINX conf directories for domains
for domain in $domain_list; do
sudo mkdir -p "/etc/nginx/conf.d/${domain}.d"
mkdir -p "/etc/nginx/conf.d/${domain}.d"
done
# Reload nginx configuration
pgrep nginx && sudo service nginx reload
# Get rid of legacy lets encrypt snippets
for domain in $domain_list; do
# If the legacy letsencrypt / acme-challenge domain-specific snippet is still there
if [ -e /etc/nginx/conf.d/${domain}.d/000-acmechallenge.conf ]
then
# And if we're effectively including the new domain-independant snippet now
if grep -q "include /etc/nginx/conf.d/acme-challenge.conf.inc;" /etc/nginx/conf.d/${domain}.conf
then
# Delete the old domain-specific snippet
rm /etc/nginx/conf.d/${domain}.d/000-acmechallenge.conf
fi
fi
done
# Reload nginx if conf looks good, otherwise display error and exit unhappy
nginx -t 2>/dev/null || { nginx -t; exit 1; }
pgrep nginx && systemctl reload nginx || { journalctl --no-pager --lines=10 -u nginx >&2; exit 1; }
}
FORCE=${2:-0}

View file

@ -20,7 +20,7 @@ do_pre_regen() {
# prepare main.cf conf file
main_domain=$(cat /etc/yunohost/current_host)
domain_list=$(sudo yunohost domain list --output-as plain --quiet | tr '\n' ' ')
domain_list=$(yunohost domain list --output-as plain --quiet | tr '\n' ' ')
# Support different strategy for security configurations
export compatibility="$(yunohost settings get 'security.postfix.compatibility')"
@ -35,7 +35,8 @@ do_pre_regen() {
> "${default_dir}/postsrsd"
# adapt it for IPv4-only hosts
if [ ! -f /proc/net/if_inet6 ]; then
ipv6="$(yunohost settings get 'smtp.allow_ipv6')"
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"
@ -49,7 +50,7 @@ do_post_regen() {
regen_conf_files=$1
[[ -z "$regen_conf_files" ]] \
|| { sudo service postfix restart && sudo service postsrsd restart; }
|| { service postfix restart && service postsrsd restart; }
}

View file

@ -2,6 +2,8 @@
set -e
. /usr/share/yunohost/helpers
do_pre_regen() {
pending_dir=$1
@ -14,11 +16,10 @@ do_pre_regen() {
cp dovecot-ldap.conf "${dovecot_dir}/dovecot-ldap.conf"
cp dovecot.sieve "${dovecot_dir}/global_script/dovecot.sieve"
# prepare dovecot.conf conf file
main_domain=$(cat /etc/yunohost/current_host)
cat dovecot.conf \
| sed "s/{{ main_domain }}/${main_domain}/g" \
> "${dovecot_dir}/dovecot.conf"
export pop3_enabled="$(yunohost settings get 'pop3.enabled')"
export main_domain=$(cat /etc/yunohost/current_host)
ynh_render_template "dovecot.conf" "${dovecot_dir}/dovecot.conf"
# adapt it for IPv4-only hosts
if [ ! -f /proc/net/if_inet6 ]; then
@ -35,28 +36,28 @@ do_pre_regen() {
do_post_regen() {
regen_conf_files=$1
sudo mkdir -p "/etc/dovecot/yunohost.d/pre-ext.d"
sudo mkdir -p "/etc/dovecot/yunohost.d/post-ext.d"
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 \
|| sudo adduser --system --ingroup mail --uid 500 vmail
|| adduser --system --ingroup mail --uid 500 vmail
# fix permissions
sudo chown -R vmail:mail /etc/dovecot/global_script
sudo chmod 770 /etc/dovecot/global_script
sudo chown root:mail /var/mail
sudo chmod 1775 /var/mail
chown -R vmail:mail /etc/dovecot/global_script
chmod 770 /etc/dovecot/global_script
chown root:mail /var/mail
chmod 1775 /var/mail
[ -z "$regen_conf_files" ] && exit 0
# compile sieve script
[[ "$regen_conf_files" =~ dovecot\.sieve ]] && {
sudo sievec /etc/dovecot/global_script/dovecot.sieve
sudo chown -R vmail:mail /etc/dovecot/global_script
sievec /etc/dovecot/global_script/dovecot.sieve
chown -R vmail:mail /etc/dovecot/global_script
}
sudo service dovecot restart
service dovecot restart
}
FORCE=${2:-0}

View file

@ -22,11 +22,11 @@ do_post_regen() {
##
# create DKIM directory with proper permission
sudo mkdir -p /etc/dkim
sudo chown _rspamd /etc/dkim
mkdir -p /etc/dkim
chown _rspamd /etc/dkim
# retrieve domain list
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
domain_list=$(yunohost domain list --output-as plain --quiet)
# create DKIM key for domains
for domain in $domain_list; do
@ -34,30 +34,30 @@ do_post_regen() {
[ ! -f "$domain_key" ] && {
# We use a 1024 bit size because nsupdate doesn't seem to be able to
# handle 2048...
sudo opendkim-genkey --domain="$domain" \
opendkim-genkey --domain="$domain" \
--selector=mail --directory=/etc/dkim -b 1024
sudo mv /etc/dkim/mail.private "$domain_key"
sudo mv /etc/dkim/mail.txt "/etc/dkim/${domain}.mail.txt"
mv /etc/dkim/mail.private "$domain_key"
mv /etc/dkim/mail.txt "/etc/dkim/${domain}.mail.txt"
}
done
# fix DKIM keys permissions
sudo chown _rspamd /etc/dkim/*.mail.key
sudo chmod 400 /etc/dkim/*.mail.key
chown _rspamd /etc/dkim/*.mail.key
chmod 400 /etc/dkim/*.mail.key
regen_conf_files=$1
[ -z "$regen_conf_files" ] && exit 0
# compile sieve script
[[ "$regen_conf_files" =~ rspamd\.sieve ]] && {
sudo sievec /etc/dovecot/global_script/rspamd.sieve
sudo chown -R vmail:mail /etc/dovecot/global_script
sudo systemctl restart dovecot
sievec /etc/dovecot/global_script/rspamd.sieve
chown -R vmail:mail /etc/dovecot/global_script
systemctl restart dovecot
}
# Restart rspamd due to the upgrade
# https://rspamd.com/announce/2016/08/01/rspamd-1.3.1.html
sudo systemctl -q restart rspamd.service
systemctl -q restart rspamd.service
}
FORCE=${2:-0}

View file

@ -18,12 +18,12 @@ do_post_regen() {
if [ ! -f /etc/yunohost/mysql ]; then
# ensure that mysql is running
sudo systemctl -q is-active mysql.service \
|| sudo service mysql start
systemctl -q is-active mysql.service \
|| service mysql start
# generate and set new root password
mysql_password=$(ynh_string_random 10)
sudo mysqladmin -s -u root -pyunohost password "$mysql_password" || {
mysqladmin -s -u root -pyunohost password "$mysql_password" || {
if [ $FORCE -eq 1 ]; then
echo "It seems that you have already configured MySQL." \
"YunoHost needs to have a root access to MySQL to runs its" \
@ -31,13 +31,13 @@ do_post_regen() {
"You can find this new password in /etc/yunohost/mysql." >&2
# set new password with debconf
sudo debconf-set-selections << EOF
debconf-set-selections << EOF
$MYSQL_PKG mysql-server/root_password password $mysql_password
$MYSQL_PKG mysql-server/root_password_again password $mysql_password
EOF
# reconfigure Debian package
sudo dpkg-reconfigure -freadline -u "$MYSQL_PKG" 2>&1
dpkg-reconfigure -freadline -u "$MYSQL_PKG" 2>&1
else
echo "It seems that you have already configured MySQL." \
"YunoHost needs to have a root access to MySQL to runs its" \
@ -49,12 +49,12 @@ EOF
}
# store new root password
echo "$mysql_password" | sudo tee /etc/yunohost/mysql
sudo chmod 400 /etc/yunohost/mysql
echo "$mysql_password" | tee /etc/yunohost/mysql
chmod 400 /etc/yunohost/mysql
fi
[[ -z "$regen_conf_files" ]] \
|| sudo service mysql restart
|| service mysql restart
}
FORCE=${2:-0}

View file

@ -15,7 +15,7 @@ do_post_regen() {
regen_conf_files=$1
[[ -z "$regen_conf_files" ]] \
|| sudo service avahi-daemon restart
|| service avahi-daemon restart
}
FORCE=${2:-0}

View file

@ -14,7 +14,7 @@ do_post_regen() {
regen_conf_files=$1
[[ -z "$regen_conf_files" ]] \
|| sudo service glances restart
|| service glances restart
}
FORCE=${2:-0}

View file

@ -26,7 +26,7 @@ do_pre_regen() {
ynh_validate_ip4 "$ipv4" || ipv4='127.0.0.1'
ipv6=$(curl -s -6 https://ip6.yunohost.org 2>/dev/null || true)
ynh_validate_ip6 "$ipv6" || ipv6=''
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
domain_list=$(yunohost domain list --output-as plain --quiet)
# add domain conf files
for domain in $domain_list; do
@ -50,8 +50,23 @@ do_pre_regen() {
do_post_regen() {
regen_conf_files=$1
# 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 name "";' /etc/dhcp/dhclient.conf 2>/dev/null || echo 'supersede name "";' >> /etc/dhcp/dhclient.conf
systemctl restart resolvconf
fi
[[ -z "$regen_conf_files" ]] \
|| sudo service dnsmasq restart
|| service dnsmasq restart
}
FORCE=${2:-0}

View file

@ -14,7 +14,7 @@ do_post_regen() {
regen_conf_files=$1
[[ -z "$regen_conf_files" ]] \
|| sudo service unscd restart
|| service unscd restart
}
FORCE=${2:-0}

View file

@ -20,7 +20,7 @@ do_post_regen() {
regen_conf_files=$1
[[ -z "$regen_conf_files" ]] \
|| sudo service fail2ban restart
|| service fail2ban restart
}
FORCE=${2:-0}

View file

@ -0,0 +1,78 @@
#!/usr/bin/env python
import os
from moulinette.utils.process import check_output
from moulinette.utils.filesystem import read_file
from yunohost.diagnosis import Diagnoser
from yunohost.utils.packages import ynh_packages_version
class BaseSystemDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies = []
def run(self):
# Detect virt technology (if not bare metal) and arch
# Gotta have this "|| true" because it systemd-detect-virt return 'none'
# with an error code on bare metal ~.~
virt = check_output("systemd-detect-virt || true", shell=True).strip()
if virt.lower() == "none":
virt = "bare-metal"
# Detect arch
arch = check_output("dpkg --print-architecture").strip()
hardware = dict(meta={"test": "hardware"},
status="INFO",
data={"virt": virt, "arch": arch},
summary="diagnosis_basesystem_hardware")
# Also possibly the board name
if os.path.exists("/proc/device-tree/model"):
model = read_file('/proc/device-tree/model').strip()
hardware["data"]["model"] = model
hardware["details"] = ["diagnosis_basesystem_hardware_board"]
yield hardware
# Kernel version
kernel_version = read_file('/proc/sys/kernel/osrelease').strip()
yield dict(meta={"test": "kernel"},
data={"kernel_version": kernel_version},
status="INFO",
summary="diagnosis_basesystem_kernel")
# Debian release
debian_version = read_file("/etc/debian_version").strip()
yield dict(meta={"test": "host"},
data={"debian_version": debian_version},
status="INFO",
summary="diagnosis_basesystem_host")
# Yunohost packages versions
# We check if versions are consistent (e.g. all 3.6 and not 3 packages with 3.6 and the other with 3.5)
# This is a classical issue for upgrades that failed in the middle
# (or people upgrading half of the package because they did 'apt upgrade' instead of 'dist-upgrade')
# Here, ynh_core_version is for example "3.5.4.12", so [:3] is "3.5" and we check it's the same for all packages
ynh_packages = ynh_packages_version()
ynh_core_version = ynh_packages["yunohost"]["version"]
consistent_versions = all(infos["version"][:3] == ynh_core_version[:3] for infos in ynh_packages.values())
ynh_version_details = [("diagnosis_basesystem_ynh_single_version",
{"package":package,
"version": infos["version"],
"repo": infos["repo"]}
)
for package, infos in ynh_packages.items()]
yield dict(meta={"test": "ynh_versions"},
data={"main_version": ynh_core_version, "repo": ynh_packages["yunohost"]["repo"]},
status="INFO" if consistent_versions else "ERROR",
summary="diagnosis_basesystem_ynh_main_version" if consistent_versions else "diagnosis_basesystem_ynh_inconsistent_versions",
details=ynh_version_details)
def main(args, env, loggers):
return BaseSystemDiagnoser(args, env, loggers).diagnose()

View file

@ -0,0 +1,159 @@
#!/usr/bin/env python
import os
import random
from moulinette.utils.network import download_text
from moulinette.utils.process import check_output
from moulinette.utils.filesystem import read_file
from yunohost.diagnosis import Diagnoser
from yunohost.utils.network import get_network_interfaces
class IPDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies = []
def run(self):
# ############################################################ #
# PING : Check that we can ping outside at least in ipv4 or v6 #
# ############################################################ #
can_ping_ipv4 = self.can_ping_outside(4)
can_ping_ipv6 = self.can_ping_outside(6)
if not can_ping_ipv4 and not can_ping_ipv6:
yield dict(meta={"test": "ping"},
status="ERROR",
summary="diagnosis_ip_not_connected_at_all")
# Not much else we can do if there's no internet at all
return
# ###################################################### #
# DNS RESOLUTION : Check that we can resolve domain name #
# (later needed to talk to ip. and ip6.yunohost.org) #
# ###################################################### #
can_resolve_dns = self.can_resolve_dns()
# In every case, we can check that resolvconf seems to be okay
# (symlink managed by resolvconf service + pointing to dnsmasq)
good_resolvconf = self.good_resolvconf()
# If we can't resolve domain names at all, that's a pretty big issue ...
# If it turns out that at the same time, resolvconf is bad, that's probably
# the cause of this, so we use a different message in that case
if not can_resolve_dns:
yield dict(meta={"test": "dnsresolv"},
status="ERROR",
summary="diagnosis_ip_broken_dnsresolution" if good_resolvconf else "diagnosis_ip_broken_resolvconf")
return
# Otherwise, if the resolv conf is bad but we were able to resolve domain name,
# still warn that we're using a weird resolv conf ...
elif not good_resolvconf:
yield dict(meta={"test": "dnsresolv"},
status="WARNING",
summary="diagnosis_ip_weird_resolvconf",
details=["diagnosis_ip_weird_resolvconf_details"])
else:
yield dict(meta={"test": "dnsresolv"},
status="SUCCESS",
summary="diagnosis_ip_dnsresolution_working")
# ##################################################### #
# IP DIAGNOSIS : Check that we're actually able to talk #
# to a web server to fetch current IPv4 and v6 #
# ##################################################### #
ipv4 = self.get_public_ip(4) if can_ping_ipv4 else None
ipv6 = self.get_public_ip(6) if can_ping_ipv6 else None
network_interfaces = get_network_interfaces()
def get_local_ip(version):
local_ip = {iface:addr[version].split("/")[0]
for iface, addr in network_interfaces.items() if version in addr}
if not local_ip:
return None
elif len(local_ip):
return next(iter(local_ip.values()))
else:
return local_ip
yield dict(meta={"test": "ipv4"},
data={"global": ipv4, "local": get_local_ip("ipv4")},
status="SUCCESS" if ipv4 else "ERROR",
summary="diagnosis_ip_connected_ipv4" if ipv4 else "diagnosis_ip_no_ipv4",
details=["diagnosis_ip_global", "diagnosis_ip_local"] if ipv4 else None)
yield dict(meta={"test": "ipv6"},
data={"global": ipv6, "local": get_local_ip("ipv6")},
status="SUCCESS" if ipv6 else "WARNING",
summary="diagnosis_ip_connected_ipv6" if ipv6 else "diagnosis_ip_no_ipv6",
details=["diagnosis_ip_global", "diagnosis_ip_local"] if ipv6 else None)
# TODO / FIXME : add some attempt to detect ISP (using whois ?) ?
def can_ping_outside(self, protocol=4):
assert protocol in [4, 6], "Invalid protocol version, it should be either 4 or 6 and was '%s'" % repr(protocol)
# We can know that ipv6 is not available directly if this file does not exists
if protocol == 6 and not os.path.exists("/proc/net/if_inet6"):
return False
# If we are indeed connected in ipv4 or ipv6, we should find a default route
routes = check_output("ip -%s route" % protocol).split("\n")
if not any(r.startswith("default") for r in routes):
return False
# We use the resolver file as a list of well-known, trustable (ie not google ;)) IPs that we can ping
resolver_file = "/usr/share/yunohost/templates/dnsmasq/plain/resolv.dnsmasq.conf"
resolvers = [r.split(" ")[1] for r in read_file(resolver_file).split("\n") if r.startswith("nameserver")]
if protocol == 4:
resolvers = [r for r in resolvers if ":" not in r]
if protocol == 6:
resolvers = [r for r in resolvers if ":" in r]
assert resolvers != [], "Uhoh, need at least one IPv%s DNS resolver in %s ..." % (protocol, resolver_file)
# So let's try to ping the first 4~5 resolvers (shuffled)
# If we succesfully ping any of them, we conclude that we are indeed connected
def ping(protocol, target):
return os.system("ping%s -c1 -W 3 %s >/dev/null 2>/dev/null" % ("" if protocol == 4 else "6", target)) == 0
random.shuffle(resolvers)
return any(ping(protocol, resolver) for resolver in resolvers[:5])
def can_resolve_dns(self):
return os.system("dig +short ip.yunohost.org >/dev/null 2>/dev/null") == 0
def good_resolvconf(self):
content = read_file("/etc/resolv.conf").strip().split("\n")
# Ignore comments and empty lines
content = [l.strip() for l in content if l.strip() and not l.strip().startswith("#") and not l.strip().startswith("search")]
# We should only find a "nameserver 127.0.0.1"
return len(content) == 1 and content[0].split() == ["nameserver", "127.0.0.1"]
def get_public_ip(self, protocol=4):
# FIXME - TODO : here we assume that DNS resolution for ip.yunohost.org is working
# but if we want to be able to diagnose DNS resolution issues independently from
# internet connectivity, we gotta rely on fixed IPs first....
assert protocol in [4, 6], "Invalid protocol version, it should be either 4 or 6 and was '%s'" % repr(protocol)
url = 'https://ip%s.yunohost.org' % ('6' if protocol == 6 else '')
try:
return download_text(url, timeout=30).strip()
except Exception as e:
self.logger_debug("Could not get public IPv%s : %s" % (str(protocol), str(e)))
return None
def main(args, env, loggers):
return IPDiagnoser(args, env, loggers).diagnose()

View file

@ -0,0 +1,141 @@
#!/usr/bin/env python
import os
from moulinette.utils.filesystem import read_file
from yunohost.utils.network import dig
from yunohost.diagnosis import Diagnoser
from yunohost.domain import domain_list, _build_dns_conf, _get_maindomain
class DNSRecordsDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies = ["ip"]
def run(self):
resolvers = read_file("/etc/resolv.dnsmasq.conf").split("\n")
ipv4_resolvers = [r.split(" ")[1] for r in resolvers if r.startswith("nameserver") and ":" not in r]
# FIXME some day ... handle ipv4-only and ipv6-only servers. For now we assume we have at least ipv4
assert ipv4_resolvers != [], "Uhoh, need at least one IPv4 DNS resolver ..."
self.resolver = ipv4_resolvers[0]
main_domain = _get_maindomain()
all_domains = domain_list()["domains"]
for domain in all_domains:
self.logger_debug("Diagnosing DNS conf for %s" % domain)
is_subdomain = domain.split(".",1)[1] in all_domains
for report in self.check_domain(domain, domain == main_domain, is_subdomain=is_subdomain):
yield report
# FIXME : somewhere, should implement a check for reverse DNS ...
# FIXME / TODO : somewhere, could also implement a check for domain expiring soon
def check_domain(self, domain, is_main_domain, is_subdomain):
expected_configuration = _build_dns_conf(domain, include_empty_AAAA_if_no_ipv6=True)
categories = ["basic", "mail", "xmpp", "extra"]
# For subdomains, we only diagnosis A and AAAA records
if is_subdomain:
categories = ["basic"]
for category in categories:
records = expected_configuration[category]
discrepancies = []
results = {}
for r in records:
id_ = r["type"] + ":" + r["name"]
r["current"] = self.get_current_record(domain, r["name"], r["type"])
if r["value"] == "@":
r["value"] = domain + "."
if self.current_record_match_expected(r):
results[id_] = "OK"
else:
if r["current"] is None:
results[id_] = "MISSING"
discrepancies.append(("diagnosis_dns_missing_record", r))
else:
results[id_] = "WRONG"
discrepancies.append(("diagnosis_dns_discrepancy", r))
def its_important():
# Every mail DNS records are important for main domain
# For other domain, we only report it as a warning for now...
if is_main_domain and category == "mail":
return True
elif category == "basic":
# A bad or missing A record is critical ...
# And so is a wrong AAAA record
# (However, a missing AAAA record is acceptable)
if results["A:@"] != "OK" or results["AAAA:@"] == "WRONG":
return True
return False
if discrepancies:
status = "ERROR" if its_important() else "WARNING"
summary = "diagnosis_dns_bad_conf"
else:
status = "SUCCESS"
summary = "diagnosis_dns_good_conf"
output = dict(meta={"domain": domain, "category": category},
data=results,
status=status,
summary=summary)
if discrepancies:
output["details"] = ["diagnosis_dns_point_to_doc"] + discrepancies
yield output
def get_current_record(self, domain, name, type_):
query = "%s.%s" % (name, domain) if name != "@" else domain
success, answers = dig(query, type_, resolvers="force_external")
if success != "ok":
return None
else:
return answers[0] if len(answers) == 1 else answers
def current_record_match_expected(self, r):
if r["value"] is not None and r["current"] is None:
return False
if r["value"] is None and r["current"] is not None:
return False
elif isinstance(r["current"], list):
return False
if r["type"] == "TXT":
# Split expected/current
# from "v=DKIM1; k=rsa; p=hugekey;"
# to a set like {'v=DKIM1', 'k=rsa', 'p=...'}
expected = set(r["value"].strip(';" ').replace(";", " ").split())
current = set(r["current"].strip(';" ').replace(";", " ").split())
# For SPF, ignore parts starting by ip4: or ip6:
if r["name"] == "@":
current = {part for part in current if not part.startswith("ip4:") and not part.startswith("ip6:")}
return expected == current
elif r["type"] == "MX":
# For MX, we want to ignore the priority
expected = r["value"].split()[-1]
current = r["current"].split()[-1]
return expected == current
else:
return r["current"] == r["value"]
def main(args, env, loggers):
return DNSRecordsDiagnoser(args, env, loggers).diagnose()

View file

@ -0,0 +1,116 @@
#!/usr/bin/env python
import os
from yunohost.diagnosis import Diagnoser
from yunohost.utils.error import YunohostError
from yunohost.service import _get_services
class PortsDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies = ["ip"]
def run(self):
# TODO: report a warning if port 53 or 5353 is exposed to the outside world...
# This dict is something like :
# { 80: "nginx",
# 25: "postfix",
# 443: "nginx"
# ... }
ports = {}
services = _get_services()
for service, infos in services.items():
for port in infos.get("needs_exposed_ports", []):
ports[port] = service
ipversions = []
ipv4 = Diagnoser.get_cached_report("ip", item={"test": "ipv4"}) or {}
if ipv4.get("status") == "SUCCESS":
ipversions.append(4)
# To be discussed: we could also make this check dependent on the
# existence of an AAAA record...
ipv6 = Diagnoser.get_cached_report("ip", item={"test": "ipv6"}) or {}
if ipv6.get("status") == "SUCCESS":
ipversions.append(6)
# Fetch test result for each relevant IP version
results = {}
for ipversion in ipversions:
try:
r = Diagnoser.remote_diagnosis('check-ports',
data={'ports': ports.keys()},
ipversion=ipversion)
results[ipversion] = r["ports"]
except Exception as e:
yield dict(meta={"reason": "remote_diagnosis_failed", "ipversion": ipversion},
data={"error": str(e)},
status="WARNING",
summary="diagnosis_ports_could_not_diagnose",
details=["diagnosis_ports_could_not_diagnose_details"])
continue
ipversions = results.keys()
if not ipversions:
return
for port, service in sorted(ports.items()):
port = str(port)
category = services[service].get("category", "[?]")
# If both IPv4 and IPv6 (if applicable) are good
if all(results[ipversion].get(port) is True for ipversion in ipversions):
yield dict(meta={"port": port},
data={"service": service, "category": category},
status="SUCCESS",
summary="diagnosis_ports_ok",
details=["diagnosis_ports_needed_by"])
# If both IPv4 and IPv6 (if applicable) are failed
elif all(results[ipversion].get(port) is not True for ipversion in ipversions):
yield dict(meta={"port": port},
data={"service": service, "category": category},
status="ERROR",
summary="diagnosis_ports_unreachable",
details=["diagnosis_ports_needed_by", "diagnosis_ports_forwarding_tip"])
# If only IPv4 is failed or only IPv6 is failed (if applicable)
else:
passed, failed = (4, 6) if results[4].get(port) is True else (6, 4)
# Failing in ipv4 is critical.
# If we failed in IPv6 but there's in fact no AAAA record
# It's an acceptable situation and we shall not report an
# error
# If any AAAA record is set, IPv6 is important...
def ipv6_is_important():
dnsrecords = Diagnoser.get_cached_report("dnsrecords") or {}
return any(record["data"]["AAAA:@"] in ["OK", "WRONG"] for record in dnsrecords.get("items", []))
if failed == 4 or ipv6_is_important():
yield dict(meta={"port": port},
data={"service": service, "category": category, "passed": passed, "failed": failed},
status="ERROR",
summary="diagnosis_ports_partially_unreachable",
details=["diagnosis_ports_needed_by", "diagnosis_ports_forwarding_tip"])
# So otherwise we report a success
# And in addition we report an info about the failure in IPv6
# *with a different meta* (important to avoid conflicts when
# fetching the other info...)
else:
yield dict(meta={"port": port},
data={"service": service, "category": category},
status="SUCCESS",
summary="diagnosis_ports_ok",
details=["diagnosis_ports_needed_by"])
yield dict(meta={"test": "ipv6", "port": port},
data={"service": service, "category": category, "passed": passed, "failed": failed},
status="INFO",
summary="diagnosis_ports_partially_unreachable",
details=["diagnosis_ports_needed_by", "diagnosis_ports_forwarding_tip"])
def main(args, env, loggers):
return PortsDiagnoser(args, env, loggers).diagnose()

View file

@ -0,0 +1,166 @@
#!/usr/bin/env python
import os
import random
import requests
from moulinette.utils.filesystem import read_file
from yunohost.diagnosis import Diagnoser
from yunohost.domain import domain_list
from yunohost.utils.error import YunohostError
DIAGNOSIS_SERVER = "diagnosis.yunohost.org"
class WebDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies = ["ip"]
def run(self):
all_domains = domain_list()["domains"]
domains_to_check = []
for domain in all_domains:
# If the diagnosis location ain't defined, can't do diagnosis,
# probably because nginx conf manually modified...
nginx_conf = "/etc/nginx/conf.d/%s.conf" % domain
if ".well-known/ynh-diagnosis/" not in read_file(nginx_conf):
yield dict(meta={"domain": domain},
status="WARNING",
summary="diagnosis_http_nginx_conf_not_up_to_date",
details=["diagnosis_http_nginx_conf_not_up_to_date_details"])
else:
domains_to_check.append(domain)
self.nonce = ''.join(random.choice("0123456789abcedf") for i in range(16))
os.system("rm -rf /tmp/.well-known/ynh-diagnosis/")
os.system("mkdir -p /tmp/.well-known/ynh-diagnosis/")
os.system("touch /tmp/.well-known/ynh-diagnosis/%s" % self.nonce)
if not domains_to_check:
return
# To perform hairpinning test, we gotta make sure that port forwarding
# is working and therefore we'll do it only if at least one ipv4 domain
# works.
self.do_hairpinning_test = False
ipversions = []
ipv4 = Diagnoser.get_cached_report("ip", item={"test": "ipv4"}) or {}
if ipv4.get("status") == "SUCCESS":
ipversions.append(4)
# To be discussed: we could also make this check dependent on the
# existence of an AAAA record...
ipv6 = Diagnoser.get_cached_report("ip", item={"test": "ipv6"}) or {}
if ipv6.get("status") == "SUCCESS":
ipversions.append(6)
for item in self.test_http(domains_to_check, ipversions):
yield item
# If at least one domain is correctly exposed to the outside,
# attempt to diagnose hairpinning situations. On network with
# hairpinning issues, the server may be correctly exposed on the
# outside, but from the outside, it will be as if the port forwarding
# was not configured... Hence, calling for example
# "curl --head the.global.ip" will simply timeout...
if self.do_hairpinning_test:
global_ipv4 = ipv4.get("data", {}).get("global", None)
if global_ipv4:
try:
requests.head("http://" + global_ipv4, timeout=5)
except requests.exceptions.Timeout:
yield dict(meta={"test": "hairpinning"},
status="WARNING",
summary="diagnosis_http_hairpinning_issue",
details=["diagnosis_http_hairpinning_issue_details"])
except:
# Well I dunno what to do if that's another exception
# type... That'll most probably *not* be an hairpinning
# issue but something else super weird ...
pass
def test_http(self, domains, ipversions):
results = {}
for ipversion in ipversions:
try:
r = Diagnoser.remote_diagnosis('check-http',
data={'domains': domains,
"nonce": self.nonce},
ipversion=ipversion)
results[ipversion] = r["http"]
except Exception as e:
yield dict(meta={"reason": "remote_diagnosis_failed", "ipversion": ipversion},
data={"error": str(e)},
status="WARNING",
summary="diagnosis_http_could_not_diagnose",
details=["diagnosis_http_could_not_diagnose_details"])
continue
ipversions = results.keys()
if not ipversions:
return
for domain in domains:
# If both IPv4 and IPv6 (if applicable) are good
if all(results[ipversion][domain]["status"] == "ok" for ipversion in ipversions):
if 4 in ipversions:
self.do_hairpinning_test = True
yield dict(meta={"domain": domain},
status="SUCCESS",
summary="diagnosis_http_ok")
# If both IPv4 and IPv6 (if applicable) are failed
elif all(results[ipversion][domain]["status"] != "ok" for ipversion in ipversions):
detail = results[4 if 4 in ipversions else 6][domain]["status"]
yield dict(meta={"domain": domain},
status="ERROR",
summary="diagnosis_http_unreachable",
details=[detail.replace("error_http_check", "diagnosis_http")])
# If only IPv4 is failed or only IPv6 is failed (if applicable)
else:
passed, failed = (4, 6) if results[4][domain]["status"] == "ok" else (6, 4)
detail = results[failed][domain]["status"]
# Failing in ipv4 is critical.
# If we failed in IPv6 but there's in fact no AAAA record
# It's an acceptable situation and we shall not report an
# error
def ipv6_is_important_for_this_domain():
dnsrecords = Diagnoser.get_cached_report("dnsrecords", item={"domain": domain, "category": "basic"}) or {}
AAAA_status = dnsrecords.get("data", {}).get("AAAA:@")
return AAAA_status in ["OK", "WRONG"]
if failed == 4 or ipv6_is_important_for_this_domain():
yield dict(meta={"domain": domain},
data={"passed": passed, "failed": failed},
status="ERROR",
summary="diagnosis_http_partially_unreachable",
details=[detail.replace("error_http_check", "diagnosis_http")])
# So otherwise we report a success (note that this info is
# later used to know that ACME challenge is doable)
#
# And in addition we report an info about the failure in IPv6
# *with a different meta* (important to avoid conflicts when
# fetching the other info...)
else:
self.do_hairpinning_test = True
yield dict(meta={"domain": domain},
status="SUCCESS",
summary="diagnosis_http_ok")
yield dict(meta={"test": "ipv6", "domain": domain},
data={"passed": passed, "failed": failed},
status="INFO",
summary="diagnosis_http_partially_unreachable",
details=[detail.replace("error_http_check", "diagnosis_http")])
def main(args, env, loggers):
return WebDiagnoser(args, env, loggers).diagnose()

View file

@ -0,0 +1,238 @@
#!/usr/bin/env python
import os
import dns.resolver
import socket
import re
from subprocess import CalledProcessError
from moulinette.utils.process import check_output
from moulinette.utils.filesystem import read_yaml
from yunohost.diagnosis import Diagnoser
from yunohost.domain import _get_maindomain, domain_list
from yunohost.settings import settings_get
from yunohost.utils.network import dig
DEFAULT_DNS_BLACKLIST = "/usr/share/yunohost/other/dnsbl_list.yml"
class MailDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies = ["ip"]
def run(self):
self.ehlo_domain = _get_maindomain()
self.mail_domains = domain_list()["domains"]
self.ipversions, self.ips = self.get_ips_checked()
# TODO Is a A/AAAA and MX Record ?
# TODO Are outgoing public IPs authorized to send mail by SPF ?
# TODO Validate DKIM and dmarc ?
# TODO check that the recent mail logs are not filled with thousand of email sending (unusual number of mail sent)
# TODO check for unusual failed sending attempt being refused in the logs ?
checks = ["check_outgoing_port_25", "check_ehlo", "check_fcrdns",
"check_blacklist", "check_queue"]
for check in checks:
self.logger_debug("Running " + check)
reports = list(getattr(self, check)())
for report in reports:
yield report
if not reports:
name = check[6:]
yield dict(meta={"test": "mail_" + name},
status="SUCCESS",
summary="diagnosis_mail_" + name + "_ok")
def check_outgoing_port_25(self):
"""
Check outgoing port 25 is open and not blocked by router
This check is ran on IPs we could used to send mail.
"""
for ipversion in self.ipversions:
cmd = '/bin/nc -{ipversion} -z -w2 yunohost.org 25'.format(ipversion=ipversion)
if os.system(cmd) != 0:
yield dict(meta={"test": "outgoing_port_25", "ipversion": ipversion},
data={},
status="ERROR",
summary="diagnosis_mail_outgoing_port_25_blocked",
details=["diagnosis_mail_outgoing_port_25_blocked_details",
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn"])
def check_ehlo(self):
"""
Check the server is reachable from outside and it's the good one
This check is ran on IPs we could used to send mail.
"""
for ipversion in self.ipversions:
try:
r = Diagnoser.remote_diagnosis('check-smtp',
data={},
ipversion=ipversion)
except Exception as e:
yield dict(meta={"test": "mail_ehlo", "reason": "remote_server_failed",
"ipversion": ipversion},
data={"error": str(e)},
status="WARNING",
summary="diagnosis_mail_ehlo_could_not_diagnose",
details=["diagnosis_mail_ehlo_could_not_diagnose_details"])
continue
if r["status"] != "ok":
summary = r["status"].replace("error_smtp_", "diagnosis_mail_ehlo_")
yield dict(meta={"test": "mail_ehlo", "ipversion": ipversion},
data={},
status="ERROR",
summary=summary,
details=[summary + "_details"])
elif r["helo"] != self.ehlo_domain:
yield dict(meta={"test": "mail_ehlo", "ipversion": ipversion},
data={"wrong_ehlo": r["helo"], "right_ehlo": self.ehlo_domain},
status="ERROR",
summary="diagnosis_mail_ehlo_wrong",
details=["diagnosis_mail_ehlo_wrong_details"])
def check_fcrdns(self):
"""
Check the reverse DNS is well defined by doing a Forward-confirmed
reverse DNS check
This check is ran on IPs we could used to send mail.
"""
for ip in self.ips:
if ":" in ip:
ipversion = 6
details = ["diagnosis_mail_fcrdns_nok_details",
"diagnosis_mail_fcrdns_nok_alternatives_6"]
else:
ipversion = 4
details = ["diagnosis_mail_fcrdns_nok_details",
"diagnosis_mail_fcrdns_nok_alternatives_4"]
try:
rdns_domain, _, _ = socket.gethostbyaddr(ip)
except socket.herror:
yield dict(meta={"test": "mail_fcrdns", "ipversion": ipversion},
data={"ip": ip, "ehlo_domain": self.ehlo_domain},
status="ERROR",
summary="diagnosis_mail_fcrdns_dns_missing",
details=details)
continue
if rdns_domain != self.ehlo_domain:
details = ["diagnosis_mail_fcrdns_different_from_ehlo_domain_details"] + details
yield dict(meta={"test": "mail_fcrdns", "ipversion": ipversion},
data={"ip": ip,
"ehlo_domain": self.ehlo_domain,
"rdns_domain": rdns_domain},
status="ERROR",
summary="diagnosis_mail_fcrdns_different_from_ehlo_domain",
details=details)
def check_blacklist(self):
"""
Check with dig onto blacklist DNS server
This check is ran on IPs and domains we could used to send mail.
"""
dns_blacklists = read_yaml(DEFAULT_DNS_BLACKLIST)
for item in self.ips + self.mail_domains:
for blacklist in dns_blacklists:
item_type = "domain"
if ":" in item:
item_type = 'ipv6'
elif re.match(r'^\d+\.\d+\.\d+\.\d+$', item):
item_type = 'ipv4'
if not blacklist[item_type]:
continue
# Build the query for DNSBL
subdomain = item
if item_type != "domain":
rev = dns.reversename.from_address(item)
subdomain = str(rev.split(3)[0])
query = subdomain + '.' + blacklist['dns_server']
# Do the DNS Query
status, _ = dig(query, 'A')
if status != 'ok':
continue
# Try to get the reason
details = []
status, answers = dig(query, 'TXT')
reason = "-"
if status == 'ok':
reason = ', '.join(answers)
details.append("diagnosis_mail_blacklist_reason")
details.append("diagnosis_mail_blacklist_website")
yield dict(meta={"test": "mail_blacklist", "item": item,
"blacklist": blacklist["dns_server"]},
data={'blacklist_name': blacklist['name'],
'blacklist_website': blacklist['website'],
'reason': reason},
status="ERROR",
summary='diagnosis_mail_blacklist_listed_by',
details=details)
def check_queue(self):
"""
Check mail queue is not filled with hundreds of email pending
"""
command = 'postqueue -p | grep -v "Mail queue is empty" | grep -c "^[A-Z0-9]" || true'
try:
output = check_output(command).strip()
pending_emails = int(output)
except (ValueError, CalledProcessError) as e:
yield dict(meta={"test": "mail_queue"},
data={"error": str(e)},
status="ERROR",
summary="diagnosis_mail_queue_unavailable",
details="diagnosis_mail_queue_unavailable_details")
else:
if pending_emails > 100:
yield dict(meta={"test": "mail_queue"},
data={'nb_pending': pending_emails},
status="WARNING",
summary="diagnosis_mail_queue_too_big")
else:
yield dict(meta={"test": "mail_queue"},
data={'nb_pending': pending_emails},
status="SUCCESS",
summary="diagnosis_mail_queue_ok")
def get_ips_checked(self):
outgoing_ipversions = []
outgoing_ips = []
ipv4 = Diagnoser.get_cached_report("ip", {"test": "ipv4"}) or {}
if ipv4.get("status") == "SUCCESS":
outgoing_ipversions.append(4)
global_ipv4 = ipv4.get("data", {}).get("global", {})
if global_ipv4:
outgoing_ips.append(global_ipv4)
if settings_get("smtp.allow_ipv6"):
ipv6 = Diagnoser.get_cached_report("ip", {"test": "ipv6"}) or {}
if ipv6.get("status") == "SUCCESS":
outgoing_ipversions.append(6)
global_ipv6 = ipv6.get("data", {}).get("global", {})
if global_ipv6:
outgoing_ips.append(global_ipv6)
return (outgoing_ipversions, outgoing_ips)
def main(args, env, loggers):
return MailDiagnoser(args, env, loggers).diagnose()

View file

@ -0,0 +1,40 @@
#!/usr/bin/env python
import os
from yunohost.diagnosis import Diagnoser
from yunohost.service import service_status
class ServicesDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 300
dependencies = []
def run(self):
all_result = service_status()
for service, result in sorted(all_result.items()):
item = dict(meta={"service": service},
data={"status": result["status"], "configuration": result["configuration"]})
if result["status"] != "running":
item["status"] = "ERROR"
item["summary"] = "diagnosis_services_bad_status"
item["details"] = ["diagnosis_services_bad_status_tip"]
elif result["configuration"] == "broken":
item["status"] = "WARNING"
item["summary"] = "diagnosis_services_conf_broken"
item["details"] = result["configuration-details"]
else:
item["status"] = "SUCCESS"
item["summary"] = "diagnosis_services_running"
yield item
def main(args, env, loggers):
return ServicesDiagnoser(args, env, loggers).diagnose()

View file

@ -0,0 +1,121 @@
#!/usr/bin/env python
import os
import psutil
from yunohost.diagnosis import Diagnoser
class SystemResourcesDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 300
dependencies = []
def run(self):
MB = 1024**2
GB = MB*1024
#
# RAM
#
ram = psutil.virtual_memory()
ram_available_percent = 100 * ram.available / ram.total
item = dict(meta={"test": "ram"},
data={"total": human_size(ram.total),
"available": human_size(ram.available),
"available_percent": round_(ram_available_percent)})
if ram.available < 100 * MB or ram_available_percent < 5:
item["status"] = "ERROR"
item["summary"] = "diagnosis_ram_verylow"
elif ram.available < 200 * MB or ram_available_percent < 10:
item["status"] = "WARNING"
item["summary"] = "diagnosis_ram_low"
else:
item["status"] = "SUCCESS"
item["summary"] = "diagnosis_ram_ok"
yield item
#
# Swap
#
swap = psutil.swap_memory()
item = dict(meta={"test": "swap"},
data={"total": human_size(swap.total), "recommended": "512 MiB"})
if swap.total <= 1 * MB:
item["status"] = "ERROR"
item["summary"] = "diagnosis_swap_none"
elif swap.total <= 512 * MB:
item["status"] = "WARNING"
item["summary"] = "diagnosis_swap_notsomuch"
else:
item["status"] = "SUCCESS"
item["summary"] = "diagnosis_swap_ok"
yield item
# FIXME : add a check that swapiness is low if swap is on a sdcard...
#
# Disks usage
#
disk_partitions = psutil.disk_partitions()
for disk_partition in disk_partitions:
device = disk_partition.device
mountpoint = disk_partition.mountpoint
usage = psutil.disk_usage(mountpoint)
free_percent = round_(100 - usage.percent)
item = dict(meta={"test": "diskusage", "mountpoint": mountpoint},
data={"device": device, "total": human_size(usage.total), "free": human_size(usage.free), "free_percent": free_percent})
# Special checks for /boot partition because they sometimes are
# pretty small and that's kind of okay... (for example on RPi)
if mountpoint.startswith("/boot"):
if usage.free < 10 * MB or free_percent < 10:
item["status"] = "ERROR"
item["summary"] = "diagnosis_diskusage_verylow"
elif usage.free < 20 * MB or free_percent < 20:
item["status"] = "WARNING"
item["summary"] = "diagnosis_diskusage_low"
else:
item["status"] = "SUCCESS"
item["summary"] = "diagnosis_diskusage_ok"
else:
if usage.free < 1 * GB or free_percent < 5:
item["status"] = "ERROR"
item["summary"] = "diagnosis_diskusage_verylow"
elif usage.free < 2 * GB or free_percent < 10:
item["status"] = "WARNING"
item["summary"] = "diagnosis_diskusage_low"
else:
item["status"] = "SUCCESS"
item["summary"] = "diagnosis_diskusage_ok"
yield item
def human_size(bytes_):
# Adapted from https://stackoverflow.com/a/1094933
for unit in ['','ki','Mi','Gi','Ti','Pi','Ei','Zi']:
if abs(bytes_) < 1024.0:
return "%s %sB" % (round_(bytes_), unit)
bytes_ /= 1024.0
return "%s %sB" % (round_(bytes_), 'Yi')
def round_(n):
# round_(22.124) -> 22
# round_(9.45) -> 9.4
n = round(n, 1)
if n > 10:
n = int(round(n))
return n
def main(args, env, loggers):
return SystemResourcesDiagnoser(args, env, loggers).diagnose()

View file

@ -0,0 +1,42 @@
#!/usr/bin/env python
import os
import subprocess
from yunohost.diagnosis import Diagnoser
from yunohost.regenconf import _get_regenconf_infos, _calculate_hash
class RegenconfDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 300
dependencies = []
def run(self):
regenconf_modified_files = list(self.manually_modified_files())
if not regenconf_modified_files:
yield dict(meta={"test": "regenconf"},
status="SUCCESS",
summary="diagnosis_regenconf_allgood"
)
else:
for f in regenconf_modified_files:
yield dict(meta={"test": "regenconf", "category": f['category'], "file": f['path']},
status="WARNING",
summary="diagnosis_regenconf_manually_modified",
details=["diagnosis_regenconf_manually_modified_details"]
)
def manually_modified_files(self):
for category, infos in _get_regenconf_infos().items():
for path, hash_ in infos["conffiles"].items():
if hash_ != _calculate_hash(path):
yield {"path": path, "category": category}
def main(args, env, loggers):
return RegenconfDiagnoser(args, env, loggers).diagnose()

View file

@ -0,0 +1,98 @@
#!/usr/bin/env python
import os
import json
import subprocess
from yunohost.diagnosis import Diagnoser
from moulinette.utils.filesystem import read_json, write_to_json
class SecurityDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 3600
dependencies = []
def run(self):
"CVE-2017-5754"
if self.is_vulnerable_to_meltdown():
yield dict(meta={"test": "meltdown"},
status="ERROR",
summary="diagnosis_security_vulnerable_to_meltdown",
details=["diagnosis_security_vulnerable_to_meltdown_details"]
)
else:
yield dict(meta={},
status="SUCCESS",
summary="diagnosis_security_all_good"
)
def is_vulnerable_to_meltdown(self):
# meltdown CVE: https://security-tracker.debian.org/tracker/CVE-2017-5754
# We use a cache file to avoid re-running the script so many times,
# which can be expensive (up to around 5 seconds on ARM)
# and make the admin appear to be slow (c.f. the calls to diagnosis
# from the webadmin)
#
# The cache is in /tmp and shall disappear upon reboot
# *or* we compare it to dpkg.log modification time
# such that it's re-ran if there was package upgrades
# (e.g. from yunohost)
cache_file = "/tmp/yunohost-meltdown-diagnosis"
dpkg_log = "/var/log/dpkg.log"
if os.path.exists(cache_file):
if not os.path.exists(dpkg_log) or os.path.getmtime(cache_file) > os.path.getmtime(dpkg_log):
self.logger_debug("Using cached results for meltdown checker, from %s" % cache_file)
return read_json(cache_file)[0]["VULNERABLE"]
# script taken from https://github.com/speed47/spectre-meltdown-checker
# script commit id is store directly in the script
SCRIPT_PATH = "/usr/lib/moulinette/yunohost/vendor/spectre-meltdown-checker/spectre-meltdown-checker.sh"
# '--variant 3' corresponds to Meltdown
# example output from the script:
# [{"NAME":"MELTDOWN","CVE":"CVE-2017-5754","VULNERABLE":false,"INFOS":"PTI mitigates the vulnerability"}]
try:
self.logger_debug("Running meltdown vulnerability checker")
call = subprocess.Popen("bash %s --batch json --variant 3" %
SCRIPT_PATH, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# TODO / FIXME : here we are ignoring error messages ...
# in particular on RPi2 and other hardware, the script complains about
# "missing some kernel info (see -v), accuracy might be reduced"
# Dunno what to do about that but we probably don't want to harass
# users with this warning ...
output, err = call.communicate()
assert call.returncode in (0, 2, 3), "Return code: %s" % call.returncode
# If there are multiple lines, sounds like there was some messages
# in stdout that are not json >.> ... Try to get the actual json
# stuff which should be the last line
output = output.strip()
if "\n" in output:
self.logger_debug("Original meltdown checker output : %s" % output)
output = output.split("\n")[-1]
CVEs = json.loads(output)
assert len(CVEs) == 1
assert CVEs[0]["NAME"] == "MELTDOWN"
except Exception as e:
import traceback
traceback.print_exc()
self.logger_warning("Something wrong happened when trying to diagnose Meltdown vunerability, exception: %s" % e)
raise Exception("Command output for failed meltdown check: '%s'" % output)
self.logger_debug("Writing results from meltdown checker to cache file, %s" % cache_file)
write_to_json(cache_file, CVEs)
return CVEs[0]["VULNERABLE"]
def main(args, env, loggers):
return SecurityDiagnoser(args, env, loggers).diagnose()

View file

@ -5,7 +5,7 @@ if [[ $EUID -ne 0 ]]; then
# We need to execute this script as root, since the ldap
# service will be shut down during the operation (and sudo
# won't be available)
sudo /bin/bash $(readlink -f $0) $1
/bin/bash $(readlink -f $0) $1
else

View file

@ -1,8 +1,8 @@
backup_dir="$1/conf/ssh"
if [ -d /etc/ssh/ ]; then
sudo cp -a $backup_dir/. /etc/ssh
sudo service ssh restart
cp -a $backup_dir/. /etc/ssh
service ssh restart
else
echo "SSH is not installed"
fi

View file

@ -9,15 +9,15 @@ service mysql status >/dev/null 2>&1 \
# retrieve current and new password
[ -f /etc/yunohost/mysql ] \
&& curr_pwd=$(sudo cat /etc/yunohost/mysql)
new_pwd=$(sudo cat "${backup_dir}/root_pwd" || sudo cat "${backup_dir}/mysql")
&& curr_pwd=$(cat /etc/yunohost/mysql)
new_pwd=$(cat "${backup_dir}/root_pwd" || cat "${backup_dir}/mysql")
[ -z "$curr_pwd" ] && curr_pwd="yunohost"
[ -z "$new_pwd" ] && {
new_pwd=$(ynh_string_random 10)
}
# attempt to change it
sudo mysqladmin -s -u root -p"$curr_pwd" password "$new_pwd" || {
mysqladmin -s -u root -p"$curr_pwd" password "$new_pwd" || {
echo "It seems that you have already configured MySQL." \
"YunoHost needs to have a root access to MySQL to runs its" \
@ -25,18 +25,18 @@ sudo mysqladmin -s -u root -p"$curr_pwd" password "$new_pwd" || {
"You can find this new password in /etc/yunohost/mysql." >&2
# set new password with debconf
sudo debconf-set-selections << EOF
debconf-set-selections << EOF
$MYSQL_PKG mysql-server/root_password password $new_pwd
$MYSQL_PKG mysql-server/root_password_again password $new_pwd
EOF
# reconfigure Debian package
sudo dpkg-reconfigure -freadline -u "$MYSQL_PKG" 2>&1
dpkg-reconfigure -freadline -u "$MYSQL_PKG" 2>&1
}
# store new root password
echo "$new_pwd" | sudo tee /etc/yunohost/mysql
sudo chmod 400 /etc/yunohost/mysql
echo "$new_pwd" | tee /etc/yunohost/mysql
chmod 400 /etc/yunohost/mysql
# reload the grant tables
sudo mysqladmin -s -u root -p"$new_pwd" reload
mysqladmin -s -u root -p"$new_pwd" reload

View file

@ -1,3 +1,3 @@
backup_dir="$1/conf/ssowat"
sudo cp -a $backup_dir/. /etc/ssowat
cp -a $backup_dir/. /etc/ssowat

View file

@ -1,3 +1,3 @@
backup_dir="$1/data/home"
sudo cp -a $backup_dir/. /home
cp -a $backup_dir/. /home

View file

@ -1,4 +1,4 @@
backup_dir="$1/conf/ynh/firewall"
sudo cp -a $backup_dir/. /etc/yunohost
sudo yunohost firewall reload
cp -a $backup_dir/. /etc/yunohost
yunohost firewall reload

View file

@ -1,8 +1,7 @@
backup_dir="$1/conf/ynh/certs"
sudo mkdir -p /etc/yunohost/certs/
mkdir -p /etc/yunohost/certs/
sudo cp -a $backup_dir/. /etc/yunohost/certs/
sudo yunohost app ssowatconf
sudo service nginx reload
sudo service metronome reload
cp -a $backup_dir/. /etc/yunohost/certs/
service nginx reload
service metronome reload

View file

@ -1,8 +1,8 @@
backup_dir="$1/data/mail"
sudo cp -a $backup_dir/. /var/mail/ || echo 'No mail found'
sudo chown -R vmail:mail /var/mail/
cp -a $backup_dir/. /var/mail/ || echo 'No mail found'
chown -R vmail:mail /var/mail/
# Restart services to use migrated certs
sudo service postfix restart
sudo service dovecot restart
service postfix restart
service dovecot restart

View file

@ -1,7 +1,7 @@
backup_dir="$1/conf/xmpp"
sudo cp -a $backup_dir/etc/. /etc/metronome
sudo cp -a $backup_dir/var/. /var/lib/metronome
cp -a $backup_dir/etc/. /etc/metronome
cp -a $backup_dir/var/. /var/lib/metronome
# Restart to apply new conf and certs
sudo service metronome restart
service metronome restart

View file

@ -1,7 +1,7 @@
backup_dir="$1/conf/nginx"
# Copy all conf except apps specific conf located in DOMAIN.d
sudo find $backup_dir/ -mindepth 1 -maxdepth 1 -name '*.d' -or -exec sudo cp -a {} /etc/nginx/conf.d/ \;
find $backup_dir/ -mindepth 1 -maxdepth 1 -name '*.d' -or -exec cp -a {} /etc/nginx/conf.d/ \;
# Restart to use new conf and certs
sudo service nginx restart
service nginx restart

View file

@ -1,6 +1,6 @@
backup_dir="$1/conf/cron"
sudo cp -a $backup_dir/. /etc/cron.d
cp -a $backup_dir/. /etc/cron.d
# Restart just in case
sudo service cron restart
service cron restart

View file

@ -1,3 +1,3 @@
backup_dir="$1/conf/ynh"
sudo cp -a "${backup_dir}/current_host" /etc/yunohost/current_host
cp -a "${backup_dir}/current_host" /etc/yunohost/current_host

184
data/other/dnsbl_list.yml Normal file
View file

@ -0,0 +1,184 @@
# Used by GAFAM
- name: Spamhaus ZEN
dns_server: zen.spamhaus.org
website: https://www.spamhaus.org/zen/
ipv4: true
ipv6: true
domain: false
- name: Barracuda Reputation Block List
dns_server: b.barracudacentral.org
website: https://barracudacentral.org/rbl/
ipv4: true
ipv6: false
domain: false
- name: Hostkarma
dns_server: hostkarma.junkemailfilter.com
website: https://ipadmin.junkemailfilter.com/remove.php
ipv4: true
ipv6: false
domain: false
- name: ImproWare IP based spamlist
dns_server: spamrbl.imp.ch
website: https://antispam.imp.ch/
ipv4: true
ipv6: false
domain: false
- name: ImproWare IP based wormlist
dns_server: wormrbl.imp.ch
website: https://antispam.imp.ch/
ipv4: true
ipv6: false
domain: false
- name: Backscatterer.org
dns_server: ips.backscatterer.org
website: http://www.backscatterer.org/
ipv4: true
ipv6: false
domain: false
- name: inps.de
dns_server: dnsbl.inps.de
website: http://dnsbl.inps.de/
ipv4: true
ipv6: false
domain: false
- name: LASHBACK
dns_server: ubl.unsubscore.com
website: https://blacklist.lashback.com/
ipv4: true
ipv6: false
domain: false
- name: Mailspike.org
dns_server: bl.mailspike.net
website: http://www.mailspike.net/
ipv4: true
ipv6: false
domain: false
- name: NiX Spam
dns_server: ix.dnsbl.manitu.net
website: http://www.dnsbl.manitu.net/
ipv4: true
ipv6: false
domain: false
- name: REDHAWK
dns_server: access.redhawk.org
website: https://www.redhawk.org/SpamHawk/query.php
ipv4: true
ipv6: false
domain: false
- name: SORBS Open SMTP relays
dns_server: smtp.dnsbl.sorbs.net
website: http://www.sorbs.net/
ipv4: true
ipv6: false
domain: false
- name: SORBS Spamhost (last 28 days)
dns_server: recent.spam.dnsbl.sorbs.net
website: http://www.sorbs.net/
ipv4: true
ipv6: false
domain: false
- name: SORBS Spamhost (last 48 hours)
dns_server: new.spam.dnsbl.sorbs.net
website: http://www.sorbs.net/
ipv4: true
ipv6: false
domain: false
- name: SpamCop Blocking List
dns_server: bl.spamcop.net
website: https://www.spamcop.net/bl.shtml
ipv4: true
ipv6: false
domain: false
- name: Spam Eating Monkey SEM-BACKSCATTER
dns_server: backscatter.spameatingmonkey.net
website: https://spameatingmonkey.com/services
ipv4: true
ipv6: false
domain: false
- name: Spam Eating Monkey SEM-BLACK
dns_server: bl.spameatingmonkey.net
website: https://spameatingmonkey.com/services
ipv4: true
ipv6: false
domain: false
- name: Spam Eating Monkey SEM-IPV6BL
dns_server: bl.ipv6.spameatingmonkey.net
website: https://spameatingmonkey.com/services
ipv4: false
ipv6: true
domain: false
- name: SpamRATS! all
dns_server: all.spamrats.com
website: http://www.spamrats.com/
ipv4: true
ipv6: false
domain: false
- name: PSBL (Passive Spam Block List)
dns_server: psbl.surriel.com
website: http://psbl.surriel.com/
ipv4: true
ipv6: false
domain: false
- name: SWINOG
dns_server: dnsrbl.swinog.ch
website: https://antispam.imp.ch/
ipv4: true
ipv6: false
domain: false
- name: GBUdb Truncate
dns_server: truncate.gbudb.net
website: http://www.gbudb.com/truncate/index.jsp
ipv4: true
ipv6: false
domain: false
- name: Weighted Private Block List
dns_server: db.wpbl.info
website: http://www.wpbl.info/
ipv4: true
ipv6: false
domain: false
# Used by GAFAM
- name: Composite Blocking List
dns_server: cbl.abuseat.org
website: cbl.abuseat.org
ipv4: true
ipv6: false
domain: false
# Used by GAFAM
- name: SenderScore Blacklist
dns_server: bl.score.senderscore.com
website: https://senderscore.com
ipv4: true
ipv6: false
domain: false
- name: Invaluement
dns_server: sip.invaluement.com
website: https://www.invaluement.com/
ipv4: true
ipv6: false
domain: false
# Added cause it supports IPv6
- name: AntiCaptcha.NET IPv6
dns_server: dnsbl6.anticaptcha.net
website: http://anticaptcha.net/
ipv4: false
ipv6: true
domain: false
- name: SPFBL.net RBL
dns_server: dnsbl.spfbl.net
website: https://spfbl.net/en/dnsbl/
ipv4: true
ipv6: true
domain: true
- name: Suomispam Blacklist
dns_server: bl.suomispam.net
website: http://suomispam.net/
ipv4: true
ipv6: true
domain: false
- name: NordSpam
dns_server: bl.nordspam.com
website: https://www.nordspam.com/
ipv4: true
ipv6: true
domain: false

View file

@ -57,18 +57,24 @@ children:
objectClass:
- posixGroup
- groupOfNamesYnh
cn=visitors,ou=groups:
cn: visitors
gidNumber: "4003"
objectClass:
- posixGroup
- groupOfNamesYnh
depends_children:
cn=main.mail,ou=permission:
cn: main.mail
cn=mail.main,ou=permission:
cn: mail.main
gidNumber: "5001"
objectClass:
- posixGroup
- permissionYnh
groupPermission:
- "cn=all_users,ou=groups,dc=yunohost,dc=org"
cn=main.metronome,ou=permission:
cn: main.metronome
cn=xmpp.main,ou=permission:
cn: xmpp.main
gidNumber: "5002"
objectClass:
- posixGroup

View file

@ -32,7 +32,6 @@ nameserver 85.214.20.141
nameserver 195.160.173.53
# (DE) AS250
nameserver 194.150.168.168
nameserver 2001:4ce8::53
# (DE) Ideal-Hosting
nameserver 84.200.69.80
nameserver 2001:1608:10:25::1c04:b12f

View file

@ -3,7 +3,7 @@ auth_bind = yes
ldap_version = 3
base = ou=users,dc=yunohost,dc=org
user_attrs = uidNumber=500,gidNumber=8,mailuserquota=quota_rule=*:bytes=%$
user_filter = (&(objectClass=inetOrgPerson)(uid=%n)(permission=cn=main.mail,ou=permission,dc=yunohost,dc=org))
pass_filter = (&(objectClass=inetOrgPerson)(uid=%n)(permission=cn=main.mail,ou=permission,dc=yunohost,dc=org))
user_filter = (&(objectClass=inetOrgPerson)(uid=%n)(permission=cn=mail.main,ou=permission,dc=yunohost,dc=org))
pass_filter = (&(objectClass=inetOrgPerson)(uid=%n)(permission=cn=mail.main,ou=permission,dc=yunohost,dc=org))
default_pass_scheme = SSHA

View file

@ -8,15 +8,29 @@ mail_home = /var/mail/%n
mail_location = maildir:/var/mail/%n
mail_uid = 500
protocols = imap sieve
protocols = imap sieve {% if pop3_enabled == "True" %}pop3{% endif %}
mail_plugins = $mail_plugins quota
###############################################################################
# generated 2020-04-03, Mozilla Guideline v5.4, Dovecot 2.2.27, OpenSSL 1.1.0l, intermediate configuration
# https://ssl-config.mozilla.org/#server=dovecot&version=2.2.27&config=intermediate&openssl=1.1.0l&guideline=5.4
ssl = required
ssl = yes
ssl_cert = </etc/yunohost/certs/{{ main_domain }}/crt.pem
ssl_key = </etc/yunohost/certs/{{ main_domain }}/key.pem
ssl_protocols = !SSLv3
ssl_dh_parameters_length = 2048
# intermediate configuration
ssl_protocols = TLSv1.2
ssl_cipher_list = 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 = no
###############################################################################
passdb {
args = /etc/dovecot/dovecot-ldap.conf

View file

@ -63,7 +63,7 @@ bantime = 600
findtime = 600
# "maxretry" is the number of failures before a host get banned.
maxretry = 5
maxretry = 10
# "backend" specifies the backend used to get files modification.
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".

View file

@ -29,4 +29,3 @@ protocol = tcp
filter = yunohost
logpath = /var/log/nginx/*error.log
/var/log/nginx/*access.log
maxretry = 10

View file

@ -1,5 +0,0 @@
# Default is to launch glances with '-s' option.
DAEMON_ARGS="-s -B 127.0.0.1"
# Change to 'true' to have glances running at startup
RUN="true"

View file

@ -1,4 +1,5 @@
VirtualHost "{{ domain }}"
enable = true
ssl = {
key = "/etc/yunohost/certs/{{ domain }}/key.pem";
certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem";
@ -8,8 +9,63 @@ VirtualHost "{{ domain }}"
hostname = "localhost",
user = {
basedn = "ou=users,dc=yunohost,dc=org",
filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }})(permission=cn=main.metronome,ou=permission,dc=yunohost,dc=org))",
filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }})(permission=cn=xmpp.main,ou=permission,dc=yunohost,dc=org))",
usernamefield = "mail",
namefield = "cn",
},
}
-- Discovery items
disco_items = {
{ "muc.{{ domain }}" },
{ "pubsub.{{ domain }}" },
{ "jabber.{{ domain }}" },
{ "vjud.{{ domain }}" },
{ "xmpp-upload.{{ domain }}" },
};
-- contact_info = {
-- abuse = { "mailto:abuse@{{ domain }}", "xmpp:admin@{{ domain }}" };
-- admin = { "mailto:root@{{ domain }}", "xmpp:admin@{{ domain }}" };
-- };
------ Components ------
-- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports.
---Set up a MUC (multi-user chat) room server
Component "muc.{{ domain }}" "muc"
name = "{{ domain }} Chatrooms"
modules_enabled = {
"muc_limits";
"muc_log";
"muc_log_mam";
"muc_log_http";
"muc_vcard";
}
muc_event_rate = 0.5
muc_burst_factor = 10
---Set up a PubSub server
Component "pubsub.{{ domain }}" "pubsub"
name = "{{ domain }} Publish/Subscribe"
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
---Set up a HTTP Upload service
Component "xmpp-upload.{{ domain }}" "http_upload"
name = "{{ domain }} Sharing Service"
http_file_path = "/var/xmpp-upload/{{ domain }}/upload"
http_external_url = "https://xmpp-upload.{{ domain }}:443"
http_file_base_path = "/upload"
http_file_size_limit = 6*1024*1024
http_file_quota = 60*1024*1024
http_upload_file_size_limit = 100 * 1024 * 1024 -- bytes
http_upload_quota = 10 * 1024 * 1024 * 1024 -- bytes
---Set up a VJUD service
Component "vjud.{{ domain }}" "vjud"
vjud_disco_name = "{{ domain }} User Directory"

View file

@ -81,14 +81,6 @@ http_interfaces = { "127.0.0.1", "::1" }
-- Enable IPv6
use_ipv6 = true
-- Discovery items
disco_items = {
{ "muc.{{ main_domain }}" },
{ "pubsub.{{ main_domain }}" },
{ "upload.{{ main_domain }}" },
{ "vjud.{{ main_domain }}" }
};
-- BOSH configuration (mod_bosh)
consider_bosh_secure = true
cross_domain_bosh = true
@ -119,40 +111,6 @@ log = {
Component "localhost" "http"
modules_enabled = { "bosh" }
---Set up a MUC (multi-user chat) room server
Component "muc.{{ main_domain }}" "muc"
name = "{{ main_domain }} Chatrooms"
modules_enabled = {
"muc_limits";
"muc_log";
"muc_log_mam";
"muc_log_http";
"muc_vcard";
}
muc_event_rate = 0.5
muc_burst_factor = 10
---Set up a PubSub server
Component "pubsub.{{ main_domain }}" "pubsub"
name = "{{ main_domain }} Publish/Subscribe"
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
---Set up a HTTP Upload service
Component "upload.{{ main_domain }}" "http_upload"
name = "{{ main_domain }} Sharing Service"
http_file_size_limit = 6*1024*1024
http_file_quota = 60*1024*1024
---Set up a VJUD service
Component "vjud.{{ main_domain }}" "vjud"
ud_disco_name = "{{ main_domain }} User Directory"
----------- Virtual hosts -----------
-- You need to add a VirtualHost entry for each domain you wish Metronome to serve.
-- Settings under each VirtualHost entry apply *only* to that host.

View file

@ -0,0 +1,5 @@
location ^~ '/.well-known/acme-challenge/'
{
default_type "text/plain";
alias /tmp/acme-challenge-public/;
}

View file

@ -4,5 +4,5 @@ sub_filter_once on;
# Apply to other mime types than text/html
sub_filter_types application/xhtml+xml;
# Prevent YunoHost panel files from being blocked by specific app rules
location ~ (ynh_portal.js|ynh_overlay.css|ynh_userinfo.json) {
location ~ (ynh_portal.js|ynh_overlay.css|ynh_userinfo.json|ynhtheme/custom_portal.js|ynhtheme/custom_overlay.css) {
}

View file

@ -0,0 +1,34 @@
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m; # about 200000 sessions
ssl_session_tickets off;
# nginx 1.10 in stretch doesn't support TLS1.3 and Mozilla doesn't have any
# "modern" config recommendation with it.
# So until buster the modern conf is same as intermediate
{% if compatibility == "modern" %} {% else %} {% endif %}
# Ciphers with intermediate compatibility
# generated 2020-04-03, Mozilla Guideline v5.4, nginx 1.10.3, OpenSSL 1.1.0l, intermediate configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.10.3&config=intermediate&openssl=1.1.0l&guideline=5.4
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;
# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
# https://wiki.mozilla.org/Security/Guidelines/Web_Security
# https://observatory.mozilla.org/
more_set_headers "Content-Security-Policy : upgrade-insecure-requests";
more_set_headers "Content-Security-Policy-Report-Only : default-src https: data: 'unsafe-inline' 'unsafe-eval'";
more_set_headers "X-Content-Type-Options : nosniff";
more_set_headers "X-XSS-Protection : 1; mode=block";
more_set_headers "X-Download-Options : noopen";
more_set_headers "X-Permitted-Cross-Domain-Policies : none";
more_set_headers "X-Frame-Options : SAMEORIGIN";
# Disable gzip to protect against BREACH
# Read https://trac.nginx.org/nginx/ticket/1720 (text/html cannot be disabled!)
gzip off;

View file

@ -6,17 +6,23 @@ map $http_upgrade $connection_upgrade {
server {
listen 80;
listen [::]:80;
server_name {{ domain }};
server_name {{ domain }} xmpp-upload.{{ domain }};
access_by_lua_file /usr/share/ssowat/access.lua;
include /etc/nginx/conf.d/acme-challenge.conf.inc;
include /etc/nginx/conf.d/{{ domain }}.d/*.conf;
location /yunohost/admin {
return 301 https://$http_host$request_uri;
}
location /.well-known/autoconfig/mail/ {
location ^~ '/.well-known/ynh-diagnosis/' {
alias /tmp/.well-known/ynh-diagnosis/;
}
location ^~ '/.well-known/autoconfig/mail/' {
alias /var/www/.well-known/{{ domain }}/autoconfig/mail/;
}
@ -29,47 +35,14 @@ server {
listen [::]:443 ssl http2;
server_name {{ domain }};
include /etc/nginx/conf.d/security.conf.inc;
ssl_certificate /etc/yunohost/certs/{{ domain }}/crt.pem;
ssl_certificate_key /etc/yunohost/certs/{{ domain }}/key.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
{% if compatibility == "modern" %}
# Ciphers with modern compatibility
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern
# The following configuration use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...)
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
{% else %}
# As suggested by Mozilla : https://wiki.mozilla.org/Security/Server_Side_TLS and https://en.wikipedia.org/wiki/Curve25519
ssl_ecdh_curve secp521r1:secp384r1:prime256v1;
ssl_prefer_server_ciphers on;
# Ciphers with intermediate compatibility
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=intermediate
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
# 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;
{% endif %}
# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
# https://wiki.mozilla.org/Security/Guidelines/Web_Security
# https://observatory.mozilla.org/
{% if domain_cert_ca != "Self-signed" %}
more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload";
{% endif %}
more_set_headers "Content-Security-Policy : upgrade-insecure-requests";
more_set_headers "Content-Security-Policy-Report-Only : default-src https: data: 'unsafe-inline' 'unsafe-eval'";
more_set_headers "X-Content-Type-Options : nosniff";
more_set_headers "X-XSS-Protection : 1; mode=block";
more_set_headers "X-Download-Options : noopen";
more_set_headers "X-Permitted-Cross-Domain-Policies : none";
more_set_headers "X-Frame-Options : SAMEORIGIN";
{% if domain_cert_ca == "Let's Encrypt" %}
# OCSP settings
ssl_stapling on;
@ -79,9 +52,9 @@ server {
resolver_timeout 5s;
{% endif %}
# Disable gzip to protect against BREACH
# Read https://trac.nginx.org/nginx/ticket/1720 (text/html cannot be disabled!)
gzip off;
location ^~ '/.well-known/autoconfig/mail/' {
alias /var/www/.well-known/{{ domain }}/autoconfig/mail/;
}
access_by_lua_file /usr/share/ssowat/access.lua;
@ -93,3 +66,46 @@ server {
access_log /var/log/nginx/{{ domain }}-access.log;
error_log /var/log/nginx/{{ domain }}-error.log;
}
# vhost dedicated to XMPP http_upload
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name xmpp-upload.{{ domain }};
root /dev/null;
location /upload/ {
alias /var/xmpp-upload/{{ domain }}/upload/;
# Pass all requests to metronome, except for GET and HEAD requests.
limit_except GET HEAD {
proxy_pass http://localhost:5290;
}
include proxy_params;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'HEAD, GET, PUT, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization';
add_header 'Access-Control-Allow-Credentials' 'true';
client_max_body_size 105M; # Choose a value a bit higher than the max upload configured in XMPP server
}
include /etc/nginx/conf.d/security.conf.inc;
ssl_certificate /etc/yunohost/certs/{{ domain }}/crt.pem;
ssl_certificate_key /etc/yunohost/certs/{{ domain }}/key.pem;
{% if domain_cert_ca != "Self-signed" %}
more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload";
{% endif %}
{% if domain_cert_ca == "Let's Encrypt" %}
# OCSP settings
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/yunohost/certs/{{ domain }}/crt.pem;
resolver 127.0.0.1 127.0.1.1 valid=300s;
resolver_timeout 5s;
{% endif %}
access_log /var/log/nginx/xmpp-upload.{{ domain }}-access.log;
error_log /var/log/nginx/xmpp-upload.{{ domain }}-error.log;
}

View file

@ -15,48 +15,14 @@ server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
include /etc/nginx/conf.d/security.conf.inc;
ssl_certificate /etc/yunohost/certs/yunohost.org/crt.pem;
ssl_certificate_key /etc/yunohost/certs/yunohost.org/key.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
{% if compatibility == "modern" %}
# Ciphers with modern compatibility
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern
# Uncomment the following to use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...)
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
{% else %}
# As suggested by Mozilla : https://wiki.mozilla.org/Security/Server_Side_TLS and https://en.wikipedia.org/wiki/Curve25519
ssl_ecdh_curve secp521r1:secp384r1:prime256v1;
ssl_prefer_server_ciphers on;
# Ciphers with intermediate compatibility
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=intermediate
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
# 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;
{% endif %}
# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
# https://wiki.mozilla.org/Security/Guidelines/Web_Security
# https://observatory.mozilla.org/
more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload";
more_set_headers "Referrer-Policy : 'same-origin'";
more_set_headers "Content-Security-Policy : upgrade-insecure-requests; object-src 'none'; script-src https: 'unsafe-eval'";
more_set_headers "X-Content-Type-Options : nosniff";
more_set_headers "X-XSS-Protection : 1; mode=block";
more_set_headers "X-Download-Options : noopen";
more_set_headers "X-Permitted-Cross-Domain-Policies : none";
more_set_headers "X-Frame-Options : SAMEORIGIN";
# Disable gzip to protect against BREACH
# Read https://trac.nginx.org/nginx/ticket/1720 (text/html cannot be disabled!)
gzip off;
location / {
return 302 https://$http_host/yunohost/admin;

View file

@ -18,35 +18,45 @@ append_dot_mydomain = no
readme_directory = no
# -- TLS for incoming connections
# By default, TLS is disabled in the Postfix SMTP server, so no difference to
# plain Postfix is visible. Explicitly switch it on with "smtpd_tls_security_level = may".
smtpd_tls_security_level=may
###############################################################################
# generated 2020-04-03, Mozilla Guideline v5.4, Postfix 3.1.14, OpenSSL 1.1.0l, intermediate configuration
# https://ssl-config.mozilla.org/#server=postfix&version=3.1.14&config=intermediate&openssl=1.1.0l&guideline=5.4
# Sending AUTH data over an unencrypted channel poses a security risk.
# When TLS layer encryption is optional ("smtpd_tls_security_level = may"), it
# may however still be useful to only offer AUTH when TLS is active. To maintain
# compatibility with non-TLS clients, the default is to accept AUTH without
# encryption. In order to change this behavior, we set "smtpd_tls_auth_only = yes".
smtpd_tls_auth_only=yes
# (No modern conf support until we're on buster...)
# {% if compatibility == "intermediate" %} {% else %} {% endif %}
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/yunohost/certs/{{ main_domain }}/crt.pem
smtpd_tls_key_file = /etc/yunohost/certs/{{ main_domain }}/key.pem
smtpd_tls_exclude_ciphers = aNULL, MD5, DES, ADH, RC4, 3DES
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_loglevel=1
{% if compatibility == "intermediate" %}
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
{% else %}
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1
{% endif %}
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
# smtpd_tls_mandatory_ciphers = medium # (c.f. below)
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam.pem
# not actually 1024 bits, this applies to all DHE >= 1024 bits
# smtpd_tls_dh1024_param_file = /path/to/dhparam.pem
# This custom medium cipherlist recommendation only works if we have a DH ... which we don't, c.f. https://github.com/YunoHost/issues/issues/93
# On the other hand, the postfix doc strongly discourage tweaking this list ... So whatever, let's keep the mandatory_ciphers to high like we did before applying the Mozilla recommendation ...
#tls_medium_cipherlist = 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
tls_preempt_cipherlist = no
# Custom Yunohost stuff ... because we can't use the recommendation about medium cipher list ...
smtpd_tls_mandatory_ciphers=high
smtpd_tls_eecdh_grade = ultra
###############################################################################
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_loglevel=1
# -- TLS for outgoing connections
# Use TLS if this is supported by the remote SMTP server, otherwise use plaintext.
smtp_tls_security_level=may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_exclude_ciphers = $smtpd_tls_exclude_ciphers
smtp_tls_mandatory_ciphers= $smtpd_tls_mandatory_ciphers
smtp_tls_exclude_ciphers = aNULL, MD5, DES, ADH, RC4, 3DES
smtp_tls_mandatory_ciphers= high
smtp_tls_loglevel=1
# Configure Root CA certificates

View file

@ -1,5 +1,5 @@
server_host = localhost
server_port = 389
search_base = dc=yunohost,dc=org
query_filter = (&(objectClass=mailAccount)(mail=%s)(permission=cn=main.mail,ou=permission,dc=yunohost,dc=org))
query_filter = (&(objectClass=mailAccount)(mail=%s)(permission=cn=mail.main,ou=permission,dc=yunohost,dc=org))
result_attribute = uid

View file

@ -1,5 +1,5 @@
server_host = localhost
server_port = 389
search_base = dc=yunohost,dc=org
query_filter = (&(objectClass=mailAccount)(mail=%s)(permission=cn=main.mail,ou=permission,dc=yunohost,dc=org))
query_filter = (&(objectClass=mailAccount)(mail=%s)(permission=cn=mail.main,ou=permission,dc=yunohost,dc=org))
result_attribute = maildrop

View file

@ -75,6 +75,7 @@ index cn,mail eq
index gidNumber,uidNumber eq
index member,memberUid,uniqueMember eq
index virtualdomain eq
index permission eq
# Save the time that the entry gets modified, for database #1
lastmod on

View file

@ -0,0 +1,9 @@
[Service]
# Prevent slapd from getting killed by oom reaper as much as possible
OOMScoreAdjust=-1000
# If slapd exited (for instance if got killed) the service should not be
# considered as active anymore...
RemainAfterExit=no
# Automatically restart the service if the service gets down
Restart=always
RestartSec=3

View file

@ -192,7 +192,7 @@ authorityKeyIdentifier=keyid,issuer
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName=DNS:yunohost.org,DNS:www.yunohost.org,DNS:ns.yunohost.org
subjectAltName=DNS:yunohost.org,DNS:www.yunohost.org,DNS:ns.yunohost.org,DNS:xmpp-upload.yunohost.org
[ v3_ca ]

View file

@ -1,43 +0,0 @@
# The VCS to use.
#VCS="hg"
VCS="git"
#VCS="bzr"
#VCS="darcs"
# Options passed to git commit when run by etckeeper.
GIT_COMMIT_OPTIONS="--quiet"
# Options passed to hg commit when run by etckeeper.
HG_COMMIT_OPTIONS=""
# Options passed to bzr commit when run by etckeeper.
BZR_COMMIT_OPTIONS=""
# Options passed to darcs record when run by etckeeper.
DARCS_COMMIT_OPTIONS="-a"
# Uncomment to avoid etckeeper committing existing changes
# to /etc automatically once per day.
#AVOID_DAILY_AUTOCOMMITS=1
# Uncomment the following to avoid special file warning
# (the option is enabled automatically by cronjob regardless).
#AVOID_SPECIAL_FILE_WARNING=1
# Uncomment to avoid etckeeper committing existing changes to
# /etc before installation. It will cancel the installation,
# so you can commit the changes by hand.
#AVOID_COMMIT_BEFORE_INSTALL=1
# The high-level package manager that's being used.
# (apt, pacman-g2, yum, zypper etc)
HIGHLEVEL_PACKAGE_MANAGER=apt
# The low-level package manager that's being used.
# (dpkg, rpm, pacman, pacman-g2, etc)
LOWLEVEL_PACKAGE_MANAGER=dpkg
# To push each commit to a remote, put the name of the remote here.
# (eg, "origin" for git). Space-separated lists of multiple remotes
# also work (eg, "origin gitlab github" for git).
PUSH_REMOTE=""

View file

@ -1,37 +1,56 @@
nginx:
log: /var/log/nginx
avahi-daemon:
log: /var/log/daemon.log
dnsmasq:
log: /var/log/daemon.log
fail2ban:
log: /var/log/fail2ban.log
avahi-daemon: {}
dnsmasq: {}
dovecot:
log: [/var/log/mail.log,/var/log/mail.err]
postfix:
log: [/var/log/mail.log,/var/log/mail.err]
rspamd:
log: /var/log/rspamd/rspamd.log
redis-server:
log: /var/log/redis/redis-server.log
mysql:
log: [/var/log/mysql.log,/var/log/mysql.err]
alternates: ['mariadb']
glances: {}
ssh:
log: /var/log/auth.log
needs_exposed_ports: [993]
category: email
fail2ban:
log: /var/log/fail2ban.log
category: security
metronome:
log: [/var/log/metronome/metronome.log,/var/log/metronome/metronome.err]
slapd:
log: /var/log/syslog
needs_exposed_ports: [5222, 5269]
category: xmpp
mysql:
log: [/var/log/mysql.log,/var/log/mysql.err,/var/log/mysql/error.log]
actual_systemd_service: mariadb
category: database
nginx:
log: /var/log/nginx
test_conf: nginx -t
needs_exposed_ports: [80, 443]
category: web
nslcd: {}
php7.0-fpm:
log: /var/log/php7.0-fpm.log
test_conf: php-fpm7.0 --test
category: web
postfix:
log: [/var/log/mail.log,/var/log/mail.err]
actual_systemd_service: postfix@-
needs_exposed_ports: [25, 587]
category: email
redis-server:
log: /var/log/redis/redis-server.log
category: database
rspamd:
log: /var/log/rspamd/rspamd.log
category: email
slapd:
category: database
ssh:
log: /var/log/auth.log
test_conf: sshd -t
needs_exposed_ports: [22]
category: admin
yunohost-api:
log: /var/log/yunohost/yunohost-api.log
category: admin
yunohost-firewall:
need_lock: true
nslcd:
log: /var/log/syslog
test_status: iptables -S | grep "^-A INPUT" | grep " --dport" | grep -q ACCEPT
category: security
glances: null
nsswitch: null
ssl: null
yunohost: null

278
debian/changelog vendored
View file

@ -1,3 +1,281 @@
yunohost (3.8.1.1) testing; urgency=low
- [fix] Stupid issue about path in debian/install ...
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 19 Apr 2020 07:04:00 +0000
yunohost (3.8.1) testing; urgency=low
## Helpers (PHP, apt)
- New helpers for extra apt repo, PHP version install, and PHP fpm (#881, #928, #929)
- Pave the way to migration to php7.3 and future ones (#880, #926)
- Option in PHP helper to use a dedicated php service (#915)
## Diagnosis
- Many improvements in diagnosis mechanism (#923, #921, #940)
## Misc fixes, improvements
- custom_portal and custom_overlay redirect (#925)
- Improve systemd settings for slapd (#933)
- Spelling and typo corrections (#931)
- Improve translations for French, German, Catalan
Thanks to all contributors <3 ! (Kay0u, Maniack Crudelis, ljf, E.Gaspar,
xaloc33)
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 19 Apr 2020 06:20:00 +0000
yunohost (3.8.0) testing; urgency=low
# Major stuff
- [enh] New diagnosis system (#534, #872, #919, a416044, a354425, 4ab3653, decb372, e686dc6, b5d18d6, 69bc124, 937d339, cc2288c, aaa9805, 526a3a2)
- [enh] App categories (#778, #853)
- [enh] Support XMPP http upload (#831)
- [enh] Many small improvements in the way we manage services (#838, fa5c0e9, dd92a34, c97a839)
- [enh] Add subcategories management in bash completion (#839)
- [mod] Add conflict with apache2 and bind9, other minor changes in Depends (#909, 3bd6a7a, 0a482fd)
- [enh] Setting to enable POP3 in email stack (#791)
- [enh] Better UX for CLI/API to change maindomain (#796)
# Misc technical
- Update ciphers for nginx, postfix and dovecot according to new Mozilla recommendation (#913, #914)
- Get rid of domain-specific acme-challenge snippet, use a single snippet included in every conf (#917)
- [enh] Persist cookies between multiple ynh_local_curl calls for the same app (#884, #903)
- [fix] ynh_find_port didn't detect port already used on UDP (#827, #907)
- [fix] prevent firefox to mix CA and server certificate (#857)
- [enh] add operation logger for config panel (#869)
- [fix] psql helpers: Revoke sessions before dropping tables (#895)
- [fix] moulinette logs were never displayed #lol (#758)
# Tests, cleaning, refactoring
- Add core CI, improve/fix tests (#856, #863, 6eb8efb, c4590ab, 711cc35, 6c24755)
- Refactoring (#805, 101d3be, #784)
- Drop some very-old deprecated app helpers (though still somewhat supporting them through hacky patching) (#780)
- Drop glances and the old monitoring system (#821)
- Drop app_debug (#824)
- Drop app's status.json (#834)
- Drop ynh_add_skipped/(un)protected_uris helpers (#910)
- Use a common security.conf.inc instead of having cipher setting in each nginx's domain file (1285776, 4d99cbe, be8427d, 22b9565)
- Don't add weird tmp redirected_urls after postinstall (#902)
- Don't do weird stuff with yunohost-firewall during debian's postinst (978d9d5)
# i18n, messaging
- Unit tests / lint / cleaning for translation files (#901)
- Improve message wording, spelling (8b0c9e5, 9fe43b1, f69ab4c, 0decb64, 986f38f, 8d40c73, 8fe343a, 1d84f17)
- Improve translations for French, Catalan, Bengali (Bangladesh), Italian, Dutch, Norwegian Bokmål, Chinese, Occitan, Spanish, Esperanto, German, Nepali, Portuguese, Arabic, Russian, Hungarian, Hindi, Polish, Greek
Thanks to all contributors <3 ! (Aeris One, Aleks, Allan N., Alvaro, Armando F., Arthur L., Augustin T., Bram, ButterflyOfFire, Damien P., Gustavo M., Jeroen F., Jimmy M., Josué, Kay0u, Maniack Crudelis, Mario, Matthew D., Mélanie C., Patrick B., Quentí, Yasss Gurl, amirale qt, Elie G., ljf, pitchum, Romain R., tituspijean, xaloc33, yalh76)
-- Kay0u <pierre@kayou.io> Thu, 09 Apr 2020 19:59:18 +0000
yunohost (3.7.1.2) stable; urgency=low
- [fix] Be more robust against some situation where some archives are corrupted
- [fix] Make nginx regen-conf more robust against broken config or service failing to start, show info to help debugging
- [fix] Force-flush the regen-conf for nginx domain conf when adding/removing a domain...
- [fix] app_map : Make sure to return / and not empty string for stuff on domain root
- [fix] Improve ynh_systemd_action to wait for fail2ban to reload
- [fix] Improper use of logger.exception in app.py leading to infamous weird "KeyError: label"
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 27 Apr 2020 23:50:00 +0000
yunohost (3.7.1.1) stable; urgency=low
- [fix] lxc uid number is limited to 65536 by default (0c9a4509)
- [fix] also invalidate group cache when creating users (aaabf8c7)
- [fix] Make sure to have a path that include sbin for stupid cron jobs (f03bb82a)
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 12 Apr 2020 23:15:00 +0000
yunohost (3.7.1) stable; urgency=low
- [enh] Add ynh_permission_has_user helper (#905)
- [mod] Change behavior of ynh_setting_delete to try to make migrating away from legacy permissions easier (#906)
- [fix] app_config_apply should also return 'app' info (#918)
- [fix] uid/gid conflicts in user_create because of inconsistent comparison (#924)
- [fix] Ensure metronome owns its directories (1f623830, 031f8a6e)
- [mod] Remove useless sudos in helpers (be88a283)
- [enh] Improve message wording for services (3c844292)
- [enh] Attempt to anonymize data pasted to paste.yunohost.org (f56f4724)
- [enh] Lazy load yunohost.certificate to possibly improve perfs (af8981e4)
- [fix] Improve logging / debugging (1eef9b67, 7d323814, d17fcaf9, 210d5f3f)
Thanks to all contributors <3 ! (Bram, Kay0u, Maniack, Matthew D.)
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 9 Apr 2020 14:52:00 +0000
yunohost (3.7.0.12) stable; urgency=low
- Fix previous buggy hotfix about deleting existing primary groups ...
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 28 Mar 2020 14:52:00 +0000
yunohost (3.7.0.11) stable; urgency=low
- [fix] Mess due to automatic translation tools ~_~
-- Kay0u <pierre@kayou.io> Fri, 27 Mar 2020 23:49:45 +0000
yunohost (3.7.0.10) stable; urgency=low
- [fix] On some weird setup, this folder and content ain't readable by group ... gotta make sure to make rx for group other slapd will explode
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 27 Mar 2020 21:45:00 +0000
yunohost (3.7.0.9) stable; urgency=low
- [fix] Automatically remove existing system group if it exists when creating primary groups
- [fix] Require moulinette and ssowat to be at least 3.7 to avoid funky situations where regen-conf fails because moulinette ain't upgraded yet
- [i18n] Improve translations for Arabic, Bengali, Catalan, Chinese, Dutch, Esperanto, French, German, Greek, Hindi, Hungarian, Italian, Norwegian Bokmål, Occitan, Polish, Portuguese, Russian, Spanish
Thanks to all contributors <3 ! (Aeris One, Allan N., Alvaro, amirale qt, Armando F., ButterflyOfFire, Elie G., Gustavo M., Jeroen F., Kayou, Mario, Mélanie C., Patrick B., Quentí, tituspijean, xaloc33, yalh76, Yasss Gurl)
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 27 Mar 2020 21:00:00 +0000
yunohost (3.7.0.8) stable; urgency=low
- [fix] App_setting delete add if the key doesn't exist
-- Kay0u <pierre@kayou.io> Fri, 27 Mar 2020 00:36:46 +0000
yunohost (3.7.0.7) stable; urgency=low
- [fix] Allow public apps with no sso tile (#894)
- [fix] Slapd now index permission to avoid log error
Thanks to all contributors <3 ! (Aleks, Kay0u)
-- Kay0u <pierre@kayou.io> Thu, 26 Mar 2020 21:53:22 +0000
yunohost (3.7.0.6) testing; urgency=low
- [fix] Make sure the group permission update contains unique elements
Thanks to all contributors <3 ! (Aleks)
-- Kay0u <pierre@kayou.io> Sun, 15 Mar 2020 22:34:27 +0000
yunohost (3.7.0.5) testing; urgency=low
- [fix] Permission url (#871)
- [fix] DNS resolver (#859)
- [fix] Legacy permission management (#868, #855)
- [enh] More informations in hooks permission (#877)
Thanks to all contributors <3 ! (Bram, ljf, Aleks, Josué, Maniack, Kay0u)
-- Kay0u <pierre@kayou.io> Sun, 15 Mar 2020 15:07:24 +0000
yunohost (3.7.0.4) testing; urgency=low
- [fix] Also add all_users when allowing visitors (#855)
- [fix] Fix handling of skipped_uris (c.f. also SSOwat#149)
- [i18n] Improve translations for Catalan
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 2 Dec 2019 20:44:00 +0000
yunohost (3.7.0.3) testing; urgency=low
- [mod] Some refactoring for permissions create/update/reset (#837)
- [fix] Fix some edge cases for ynh_secure_remove and ynh_clean_check_starting
- [i18n] Improve translations for French, Catalan
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 23 Nov 2019 19:30:00 +0000
yunohost (3.7.0.2) testing; urgency=low
- [fix] Make sure the users actually exists when migrating legacy custom permissions
- [mod] Move debug log dump from ynh_exit_properly to the core after failed app operation (#833)
- [enh] Improve app_upgrade error management (#832)
- [mod] Refactor group permission (#837)
- [enh] Add permission name in permission callback when adding/removing allowed users (#836)
- [enh] Improve permission helpers (#840)
- [i18n] Improve translations for German, Catalan, Swedish, Spanish, Turkish, Basque, French, Esperanto, Occitan
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 15 Nov 2019 16:45:00 +0000
yunohost (3.7.0.1) testing; urgency=low
- Hotfix to avoid having a shitload of warnings displayed during the permission migration
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 31 Oct 2019 20:35:00 +0000
yunohost (3.7.0) testing; urgency=low
# ~ Major stuff
- [enh] Add group and permission mechanism (YunoHost#585, YunoHost#763, YunoHost#789, YunoHost#790, YunoHost#795, YunoHost#797, SSOwat#147, Moulinette#189, YunoHost-admin#257)
- [mod] Rework migration system to have independent migrations (YunoHost#768, YunoHost#774, YunoHost-admin#258)
- [enh] Many improvements in the way app action failures are handled (YunoHost#769, YunoHost#811)
- [enh] Improve checks for system anomalies after app operations (YunoHost#785)
- [mod] Spookier warnings for dangerous app installs (YunoHost#814, Moulinette/808f620)
- [enh] Support app manifests in toml (YunoHost#748, Moulinette#204, Moulinette/55515cb)
- [mod] Get rid of etckeeper (YunoHost#803)
- [enh] Quite a lot of messages improvements, string cleaning, language rework... (YunoHost#793, YunoHost#799, YunoHost#823, SSOwat#143, YunoHost#766, YunoHost#767, YunoHost/fd99ef0, YunoHost/92a6315, YunoHost-admin/10ea04a, Moulinette/599bec3, Moulinette#208, Moulinette#213, Moulinette/b7d415d, Moulinette/a8966b8, Moulinette/fdf9a71, Moulinette/d895ae3, Moulinette/bdf0a1c, YunoHost#817, YunoHost#823, YunoHost/79627d7, YunoHost/9ee3d23, YunoHost-admin#265)
- [i18n] Improved translations for Catalan, Occitan, French, Esperanto, Arabic, German, Spanish, Norwegian Bokmål, Portuguese
# Smaller or pretty technical fix/enh
- [enh] Add unit/functional tests for apps + improve other tests (YunoHost#779, YunoHost#808)
- [enh] Preparations for moulinette Python3 migration (Tox, Pytest and unit tests) (Moulinette#203, Moulinette#206, Moulinette#207, Moulinette#210, Moulinette#211 Moulinette#212, Moulinette/2403ee1, Moulinette/69b0d49, Moulinette/49c749c, Moulinette/2c84ee1, Moulinette/cef72f7, YunoHost/6365a26)
- [enh] Support python hooks (YunoHost#747)
- [enh] Upgrade n version + compatibility with arm64 (YunoHost#753)
- [enh] Add OpenLDAP TLS support (YunoHost#755, YunoHost/0a2d1c7, YunoHost/2dc8095)
- [enh] Improve PostgreSQL password security (YunoHost#762)
- [enh] Integrate actions/config-panel into operation logs (YunoHost#764)
- [mod] Assume that apps without any 'path' setting defined aren't webapps (YunoHost#765)
- [fix] Set dpkg vendor to YunoHost (YunoHost#749, YunoHost#772)
- [enh] Adding variable 'token' to data to redact from logs (YunoHost#783)
- [enh] Add --force and --dry-run options to 'yunohost dyndns update' (YunoHost#786)
- [fix] Don't throw a fatal error if we can't change the hostname (YunoHost/fe3ecd7)
- [enh] Dynamically evaluate proper mariadb-server-<version> (YunoHost/f0440fb)
- [fix] Bad format for backup info.json ... (YunoHost/7d0119a)
- [fix] Inline buttons responsiveness on migration screen (YunoHost-admin#259)
- [enh] Add debug logs to SSOwat (SSOwat#145)
- [enh] Add a write_to_yaml utility similar to write_to_json (Moulinette/2e2e627)
- [enh] Warn the user about long locks (Moulinette#205)
- [mod] Tweak stuff about setuptools and moulinette deps? (Moulinette/b739f27, Moulinette/da00fc9, Moulinette/d8cbbb0)
- [fix] Misc micro bugfixes or improvements (YunoHost#743, YunoHost#792, YunoHost/6f48d1d, YunoHost/d516cf8, YunoHost#819, Moulinette/83d9e77, YunoHost/63d364e, YunoHost/68e9724, YunoHost/0849adb, YunoHost/19dbe87, YunoHost/61931f2, YunoHost/6dc720f, YunoHost/4def4df, SSOwat#140, SSOwat#141, YunoHost#829)
- [doc] Fix doc building + add doc build tests with Tox (Moulinette/f1ac5b8, Moulinette/df7d478, Moulinette/74c8f79, Moulinette/bcf92c7, Moulinette/af2c80c, Moulinette/d52a574, Moulinette/307f660, Moulinette/dced104, Moulinette/ed3823b)
- [enh] READMEs improvements (YunoHost/b3398e7, SSOwat/ee67b6f, Moulinette/1541b74, Moulinette/ad1eeef, YunoHost/25afdd4, YunoHost/73741f6)
Thanks to all contributors <3 ! (accross all repo: Yunohost, Moulinette, SSOwat, Yunohost-admin) : advocatux, Aksel K., Aleks, Allan N., amirale qt, Armin P., Bram, ButterflyOfFire, Carles S. A., chema o. r., decentral1se, Emmanuel V., Etienne M., Filip B., Geoff M., htsr, Jibec, Josué, Julien J., Kayou, liberodark, ljf, lucaskev, Lukas D., madtibo, Martin D., Mélanie C., nr 458 h, pitfd, ppr, Quentí, sidddy, troll, tufek yamero, xaloc33, yalh76
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 31 Oct 2019 18:00:00 +0000
yunohost (3.6.5.3) stable; urgency=low
- [fix] More general grep for the php/sury dependency nightmare fix (followup of #809)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 29 Oct 2019 03:48:00 +0000
yunohost (3.6.5.2) stable; urgency=low
- [fix] Alex was drunk and released an epic stupid bug in stable (2623d385)
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 10 Oct 2019 01:00:00 +0000
yunohost (3.6.5.1) stable; urgency=low
- [mod] Change maxretry of fail2ban from 6 to 10 (fe8fd1b)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 08 Oct 2019 20:00:00 +0000
yunohost (3.6.5) stable; urgency=low
- [enh] Detect and warn early about unavailable full domains... (#798)
- [mod] Change maxretry of fail2ban from 6 to 10 (#802)
- [fix] Epicly ugly workaround for the goddamn dependency nighmare about sury fucking up php7.0 dependencies (#809)
- [fix] Support logfiles not ending with .log in logrotate ... (#810)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 08 Oct 2019 19:00:00 +0000
yunohost (3.6.4.6) stable; urgency=low
- [fix] Hopefully fix the issue about corrupted logs metadata files (d507d447, 1cec9d78)

30
debian/control vendored
View file

@ -11,27 +11,28 @@ Package: yunohost
Essential: yes
Architecture: all
Depends: ${python:Depends}, ${misc:Depends}
, moulinette (>= 2.7.1), ssowat (>= 2.7.1)
, moulinette (>= 3.7), ssowat (>= 3.7)
, python-psutil, python-requests, python-dnspython, python-openssl
, python-apt, python-miniupnpc, python-dbus, python-jinja2
, python-toml
, glances, apt-transport-https
, dnsutils, bind9utils, unzip, git, curl, cron, wget, jq
, ca-certificates, netcat-openbsd, iproute
, apt, apt-transport-https
, nginx, nginx-extras (>=1.6.2)
, php-fpm, php-ldap, php-intl
, mariadb-server, php-mysql | php-mysqlnd
, openssh-server, iptables, fail2ban, dnsutils, bind9utils
, openssl, ca-certificates, netcat-openbsd, iproute2
, slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd
, postfix-ldap, postfix-policyd-spf-perl, postfix-pcre, procmail, mailutils, postsrsd
, dovecot-ldap, dovecot-lmtpd, dovecot-managesieved
, dovecot-antispam, fail2ban, iptables
, nginx-extras (>=1.6.2), php-fpm, php-ldap, php-intl
, dnsmasq, openssl, avahi-daemon, libnss-mdns, resolvconf, libnss-myhostname
, dnsmasq, avahi-daemon, libnss-mdns, resolvconf, libnss-myhostname
, postfix, postfix-ldap, postfix-policyd-spf-perl, postfix-pcre
, dovecot-core, dovecot-ldap, dovecot-lmtpd, dovecot-managesieved, dovecot-antispam
, rspamd (>= 1.6.0), opendkim-tools, postsrsd, procmail, mailutils
, redis-server
, metronome
, rspamd (>= 1.6.0), redis-server, opendkim-tools
, haveged, fake-hwclock
, equivs, lsof
, git, curl, wget, cron, unzip, jq
, lsb-release, haveged, fake-hwclock, equivs, lsof
Recommends: yunohost-admin
, openssh-server, ntp, inetutils-ping | iputils-ping
, bash-completion, rsyslog, etckeeper
, ntp, inetutils-ping | iputils-ping
, bash-completion, rsyslog
, php-gd, php-curl, php-gettext, php-mcrypt
, python-pip
, unattended-upgrades
@ -43,6 +44,7 @@ Conflicts: iptables-persistent
, yunohost-config-dovecot, yunohost-config-slapd
, yunohost-config-nginx, yunohost-config-amavis
, yunohost-config-mysql, yunohost-predepends
, apache2, bind9
Replaces: moulinette-yunohost, yunohost-config
, yunohost-config-others, yunohost-config-postfix
, yunohost-config-dovecot, yunohost-config-slapd

2
debian/copyright vendored
View file

@ -1,5 +1,5 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://github.com/YunoHost/moulinette-yunohost
Source: https://github.com/YunoHost/yunohost
Files: *
Copyright: 2015 YUNOHOST.ORG

1
debian/install vendored
View file

@ -7,6 +7,7 @@ data/hooks/* /usr/share/yunohost/hooks/
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/* /usr/share/yunohost/yunohost-config/moulinette/
data/templates/* /usr/share/yunohost/templates/
data/helpers /usr/share/yunohost/

27
debian/postinst vendored
View file

@ -14,14 +14,11 @@ do_configure() {
echo "Regenerating configuration, this might take a while..."
yunohost tools regen-conf --output-as none
echo "Launching migrations.."
echo "Launching migrations..."
yunohost tools migrations migrate --auto
# restart yunohost-firewall if it's running
service yunohost-firewall status >/dev/null \
&& restart_yunohost_firewall \
|| echo "yunohost-firewall service is not running, you should " \
"consider to start it by doing 'service yunohost-firewall start'."
echo "Re-diagnosing server health..."
yunohost diagnosis run --force
fi
# Change dpkg vendor
@ -39,24 +36,6 @@ do_configure() {
pam-auth-update --package
}
restart_yunohost_firewall() {
echo "Restarting YunoHost firewall..."
deb-systemd-helper unmask yunohost-firewall.service >/dev/null || true
if deb-systemd-helper --quiet was-enabled yunohost-firewall.service; then
deb-systemd-helper enable yunohost-firewall.service >/dev/null || true
else
deb-systemd-helper update-state yunohost-firewall.service >/dev/null || true
fi
if [ -x /etc/init.d/yunohost-firewall ]; then
update-rc.d yunohost-firewall enable >/dev/null
if [ -n "$2" ]; then
invoke-rc.d yunohost-firewall restart >/dev/null || exit $?
fi
fi
}
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>

View file

@ -1,389 +1,110 @@
{
"action_invalid": "إجراء غير صالح '{action:s}'",
"admin_password": "كلمة السر الإدارية",
"admin_password_change_failed": "تعذرت عملية تعديل كلمة السر",
"admin_password_change_failed": "لا يمكن تعديل الكلمة السرية",
"admin_password_changed": "تم تعديل الكلمة السرية الإدارية",
"app_already_installed": "{app:s} تم تنصيبه مِن قبل",
"app_already_installed_cant_change_url": "",
"app_already_up_to_date": "{app:s} تم تحديثه مِن قَبل",
"app_argument_choice_invalid": "",
"app_argument_invalid": "",
"app_argument_required": "المُعامِل '{name:s}' مطلوب",
"app_change_no_change_url_script": "إنّ التطبيق {app_name:s} لا يدعم تغيير الرابط، مِن الممكن أنه يتوجب عليكم تحدثيه.",
"app_change_url_failed_nginx_reload": "فشلت عملية إعادة تشغيل nginx. ها هي نتيجة الأمر 'nginx -t':\n{nginx_errors:s}",
"app_change_url_identical_domains": "The old and new domain/url_path are identical ('{domain:s}{path:s}'), nothing to do.",
"app_change_url_no_script": "This application '{app_name:s}' doesn't support url modification yet. Maybe you should upgrade the application.",
"app_change_url_success": "Successfully changed {app:s} url to {domain:s}{path:s}",
"app_change_url_failed_nginx_reload": "فشلت عملية إعادة تشغيل NGINX. ها هي نتيجة الأمر 'nginx -t':\n{nginx_errors:s}",
"app_extraction_failed": "تعذر فك الضغط عن ملفات التنصيب",
"app_id_invalid": "Invalid app id",
"app_incompatible": "إن التطبيق {app} غير متوافق مع إصدار واي يونوهوست YunoHost الخاص بك",
"app_install_files_invalid": "ملفات التنصيب خاطئة",
"app_location_already_used": "The app '{app}' is already installed on that location ({path})",
"app_make_default_location_already_used": "Can't make the app '{app}' the default on the domain {domain} is already used by the other app '{other_app}'",
"app_location_install_failed": "Unable to install the app in this location because it conflit with the app '{other_app}' already installed on '{other_path}'",
"app_location_unavailable": "This url is not available or conflicts with an already installed app",
"app_manifest_invalid": "Invalid app manifest: {error}",
"app_no_upgrade": "ليس هناك أي تطبيق بحاجة إلى تحديث",
"app_not_correctly_installed": "يبدو أن التطبيق {app:s} لم يتم تنصيبه بشكل صحيح",
"app_not_installed": "إنّ التطبيق {app:s} غير مُنصَّب",
"app_not_properly_removed": "لم يتم حذف تطبيق {app:s} بشكلٍ جيّد",
"app_package_need_update": "The app {app} package needs to be updated to follow YunoHost changes",
"app_removed": "تمت إزالة تطبيق {app:s}",
"app_requirements_checking": "جار فحص الحزم اللازمة لـ {app}…",
"app_requirements_failed": "Unable to meet requirements for {app}: {error}",
"app_requirements_unmeet": "Requirements are not met for {app}, the package {pkgname} ({version}) must be {spec}",
"app_sources_fetch_failed": "تعذرت عملية جلب مصادر الملفات",
"app_unknown": "برنامج مجهول",
"app_unsupported_remote_type": "Unsupported remote type used for the app",
"app_upgrade_app_name": "جارٍ تحديث تطبيق {app}…",
"app_upgrade_failed": "تعذرت عملية ترقية {app:s}",
"app_upgrade_some_app_failed": "تعذرت عملية ترقية بعض التطبيقات",
"app_upgraded": "تم تحديث التطبيق {app:s}",
"appslist_corrupted_json": "Could not load the application lists. It looks like {filename:s} is corrupted.",
"appslist_could_not_migrate": "Could not migrate app list {appslist:s} ! Unable to parse the url... The old cron job has been kept in {bkp_file:s}.",
"appslist_fetched": "تم جلب قائمة تطبيقات {appslist:s}",
"appslist_migrating": "Migrating application list {appslist:s} …",
"appslist_name_already_tracked": "There is already a registered application list with name {name:s}.",
"appslist_removed": "تم حذف قائمة التطبيقات {appslist:s}",
"appslist_retrieve_bad_format": "Retrieved file for application list {appslist:s} is not valid",
"appslist_retrieve_error": "Unable to retrieve the remote application list {appslist:s}: {error:s}",
"appslist_unknown": "قائمة التطبيقات {appslist:s} مجهولة.",
"appslist_url_already_tracked": "There is already a registered application list with url {url:s}.",
"ask_current_admin_password": "كلمة السر الإدارية الحالية",
"ask_email": "عنوان البريد الإلكتروني",
"ask_firstname": "الإسم",
"ask_lastname": "اللقب",
"ask_list_to_remove": "القائمة المختارة للحذف",
"ask_main_domain": "النطاق الرئيسي",
"ask_new_admin_password": "كلمة السر الإدارية الجديدة",
"ask_password": "كلمة السر",
"ask_path": "المسار",
"backup_abstract_method": "This backup method hasn't yet been implemented",
"backup_action_required": "You must specify something to save",
"backup_app_failed": "Unable to back up the app '{app:s}'",
"backup_applying_method_borg": "Sending all files to backup into borg-backup repository…",
"backup_applying_method_copy": "جارٍ نسخ كافة الملفات إلى النسخة الإحتياطية …",
"backup_applying_method_custom": "Calling the custom backup method '{method:s}'…",
"backup_applying_method_tar": "جارٍ إنشاء ملف tar للنسخة الاحتياطية…",
"backup_archive_app_not_found": "App '{app:s}' not found in the backup archive",
"backup_archive_broken_link": "Unable to access backup archive (broken link to {path:s})",
"backup_archive_mount_failed": "Mounting the backup archive failed",
"backup_archive_name_exists": "The backup's archive name already exists",
"backup_archive_name_unknown": "Unknown local backup archive named '{name:s}'",
"backup_archive_open_failed": "Unable to open the backup archive",
"backup_archive_system_part_not_available": "System part '{part:s}' not available in this backup",
"backup_archive_writing_error": "Unable to add files to backup into the compressed archive",
"backup_ask_for_copying_if_needed": "Some files couldn't be prepared to be backuped using the method that avoid to temporarily waste space on the system. To perform the backup, {size:s}MB should be used temporarily. Do you agree?",
"backup_borg_not_implemented": "Borg backup method is not yet implemented",
"backup_cant_mount_uncompress_archive": "Unable to mount in readonly mode the uncompress archive directory",
"backup_cleaning_failed": "Unable to clean-up the temporary backup directory",
"backup_copying_to_organize_the_archive": "Copying {size:s}MB to organize the archive",
"backup_couldnt_bind": "Couldn't bind {src:s} to {dest:s}.",
"backup_applying_method_tar": "جارٍ إنشاء ملف TAR للنسخة الاحتياطية…",
"backup_created": "تم إنشاء النسخة الإحتياطية",
"backup_creating_archive": "جارٍ إنشاء ملف النسخة الاحتياطية…",
"backup_creation_failed": "Backup creation failed",
"backup_csv_addition_failed": "Unable to add files to backup into the CSV file",
"backup_csv_creation_failed": "Unable to create the CSV file needed for future restore operations",
"backup_custom_backup_error": "Custom backup method failure on 'backup' step",
"backup_custom_mount_error": "Custom backup method failure on 'mount' step",
"backup_custom_need_mount_error": "Custom backup method failure on 'need_mount' step",
"backup_delete_error": "Unable to delete '{path:s}'",
"backup_deleted": "The backup has been deleted",
"backup_extracting_archive": "Extracting the backup archive…",
"backup_hook_unknown": "Backup hook '{hook:s}' unknown",
"backup_invalid_archive": "نسخة إحتياطية غير صالحة",
"backup_method_borg_finished": "Backup into borg finished",
"backup_method_copy_finished": "إنتهت عملية النسخ الإحتياطي",
"backup_method_custom_finished": "Custom backup method '{method:s}' finished",
"backup_method_tar_finished": "Backup tar archive created",
"backup_no_uncompress_archive_dir": "Uncompress archive directory doesn't exist",
"backup_nothings_done": "ليس هناك أي شيء للحفظ",
"backup_output_directory_forbidden": "Forbidden output directory. Backups can't be created in /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var or /home/yunohost.backup/archives sub-folders",
"backup_output_directory_not_empty": "The output directory is not empty",
"backup_output_directory_required": "يتوجب عليك تحديد مجلد لتلقي النسخ الإحتياطية",
"backup_output_symlink_dir_broken": "You have a broken symlink instead of your archives directory '{path:s}'. You may have a specific setup to backup your data on an other filesystem, in this case you probably forgot to remount or plug your hard dirve or usb key.",
"backup_running_app_script": "Running backup script of app '{app:s}'...",
"backup_running_hooks": "Running backup hooks…",
"backup_system_part_failed": "Unable to backup the '{part:s}' system part",
"backup_unable_to_organize_files": "Unable to organize files in the archive with the quick method",
"backup_with_no_backup_script_for_app": "App {app:s} has no backup script. Ignoring.",
"backup_with_no_restore_script_for_app": "App {app:s} has no restore script, you won't be able to automatically restore the backup of this app.",
"certmanager_acme_not_configured_for_domain": "Certificate for domain {domain:s} does not appear to be correctly installed. Please run cert-install for this domain first.",
"certmanager_attempt_to_renew_nonLE_cert": "The certificate for domain {domain:s} is not issued by Let's Encrypt. Cannot renew it automatically!",
"certmanager_attempt_to_renew_valid_cert": "The certificate for domain {domain:s} is not about to expire! Use --force to bypass",
"certmanager_attempt_to_replace_valid_cert": "You are attempting to overwrite a good and valid certificate for domain {domain:s}! (Use --force to bypass)",
"certmanager_cannot_read_cert": "Something wrong happened when trying to open current certificate for domain {domain:s} (file: {file:s}), reason: {reason:s}",
"certmanager_cert_install_success": "تمت عملية تنصيب شهادة Let's Encrypt بنجاح على النطاق {domain:s} !",
"certmanager_cert_install_success_selfsigned": "نجحت عملية تثبيت الشهادة الموقعة ذاتيا الخاصة بالنطاق {domain:s}!",
"certmanager_cert_install_success_selfsigned": "نجحت عملية تثبيت الشهادة الموقعة ذاتيا الخاصة بالنطاق {domain:s}",
"certmanager_cert_renew_success": "نجحت عملية تجديد شهادة Let's Encrypt الخاصة باسم النطاق {domain:s} !",
"certmanager_cert_signing_failed": "فشل إجراء توقيع الشهادة الجديدة",
"certmanager_certificate_fetching_or_enabling_failed": "Sounds like enabling the new certificate for {domain:s} failed somehow…",
"certmanager_conflicting_nginx_file": "Unable to prepare domain for ACME challenge: the nginx configuration file {filepath:s} is conflicting and should be removed first",
"certmanager_couldnt_fetch_intermediate_cert": "Timed out when trying to fetch intermediate certificate from Let's Encrypt. Certificate installation/renewal aborted - please try again later.",
"certmanager_domain_cert_not_selfsigned": "The certificate for domain {domain:s} is not self-signed. Are you sure you want to replace it? (Use --force)",
"certmanager_domain_dns_ip_differs_from_public_ip": "The DNS 'A' record for domain {domain:s} is different from this server IP. If you recently modified your A record, please wait for it to propagate (some DNS propagation checkers are available online). (If you know what you are doing, use --no-checks to disable those checks.)",
"certmanager_domain_http_not_working": "It seems that the domain {domain:s} cannot be accessed through HTTP. Please check your DNS and nginx configuration is okay",
"certmanager_domain_not_resolved_locally": "The domain {domain:s} cannot be resolved from inside your Yunohost server. This might happen if you recently modified your DNS record. If so, please wait a few hours for it to propagate. If the issue persists, consider adding {domain:s} to /etc/hosts. (If you know what you are doing, use --no-checks to disable those checks.)",
"certmanager_domain_unknown": "النطاق مجهول {domain:s}",
"certmanager_error_no_A_record": "No DNS 'A' record found for {domain:s}. You need to make your domain name point to your machine to be able to install a Let's Encrypt certificate! (If you know what you are doing, use --no-checks to disable those checks.)",
"certmanager_hit_rate_limit": "Too many certificates already issued for exact set of domains {domain:s} recently. Please try again later. See https://letsencrypt.org/docs/rate-limits/ for more details",
"certmanager_http_check_timeout": "Timed out when server tried to contact itself through HTTP using public IP address (domain {domain:s} with ip {ip:s}). You may be experiencing hairpinning issue or the firewall/router ahead of your server is misconfigured.",
"certmanager_no_cert_file": "تعذرت عملية قراءة شهادة نطاق {domain:s} (الملف : {file:s})",
"certmanager_old_letsencrypt_app_detected": "",
"certmanager_self_ca_conf_file_not_found": "Configuration file not found for self-signing authority (file: {file:s})",
"certmanager_unable_to_parse_self_CA_name": "Unable to parse name of self-signing authority (file: {file:s})",
"custom_app_url_required": "You must provide a URL to upgrade your custom app {app:s}",
"custom_appslist_name_required": "You must provide a name for your custom app list",
"diagnosis_debian_version_error": "لم نتمكن من العثور على إصدار ديبيان : {error}",
"diagnosis_kernel_version_error": "Can't retrieve kernel version: {error}",
"diagnosis_monitor_disk_error": "Can't monitor disks: {error}",
"diagnosis_monitor_network_error": "Can't monitor network: {error}",
"diagnosis_monitor_system_error": "Can't monitor system: {error}",
"diagnosis_no_apps": "لم تقم بتنصيب أية تطبيقات بعد",
"dnsmasq_isnt_installed": "dnsmasq does not seem to be installed, please run 'apt-get remove bind9 && apt-get install dnsmasq'",
"domain_cannot_remove_main": "Cannot remove main domain. Set a new main domain first",
"domain_cert_gen_failed": "Unable to generate certificate",
"domain_created": "تم إنشاء النطاق",
"domain_creation_failed": "تعذرت عملية إنشاء النطاق",
"domain_deleted": "تم حذف النطاق",
"domain_deletion_failed": "Unable to delete domain",
"domain_dns_conf_is_just_a_recommendation": "This command shows you what is the *recommended* configuration. It does not actually set up the DNS configuration for you. It is your responsability to configure your DNS zone in your registrar according to this recommendation.",
"domain_dyndns_already_subscribed": "You've already subscribed to a DynDNS domain",
"domain_dyndns_dynette_is_unreachable": "Unable to reach YunoHost dynette, either your YunoHost is not correctly connected to the internet or the dynette server is down. Error: {error}",
"domain_dyndns_invalid": "Invalid domain to use with DynDNS",
"domain_dyndns_root_unknown": "Unknown DynDNS root domain",
"domain_exists": "اسم النطاق موجود مِن قبل",
"domain_hostname_failed": "Failed to set new hostname",
"domain_uninstall_app_first": "One or more apps are installed on this domain. Please uninstall them before proceeding to domain removal",
"domain_unknown": "النطاق مجهول",
"domain_zone_exists": "ملف منطقة أسماء النطاقات موجود مِن قبل",
"domain_zone_not_found": "DNS zone file not found for domain {:s}",
"domains_available": "النطاقات المتوفرة :",
"done": "تم",
"downloading": "عملية التنزيل جارية …",
"dyndns_could_not_check_provide": "Could not check if {provider:s} can provide {domain:s}.",
"dyndns_cron_installed": "The DynDNS cron job has been installed",
"dyndns_cron_remove_failed": "Unable to remove the DynDNS cron job",
"dyndns_cron_removed": "The DynDNS cron job has been removed",
"dyndns_ip_update_failed": "Unable to update IP address on DynDNS",
"dyndns_ip_updated": "لقد تم تحديث عنوان الإيبي الخاص بك على نظام أسماء النطاقات الديناميكي",
"dyndns_key_generating": "عملية توليد مفتاح نظام أسماء النطاقات جارية. يمكن للعملية أن تستغرق بعضا من الوقت…",
"dyndns_key_not_found": "لم يتم العثور على مفتاح DNS الخاص باسم النطاق هذا",
"dyndns_no_domain_registered": "No domain has been registered with DynDNS",
"dyndns_registered": "The DynDNS domain has been registered",
"dyndns_registration_failed": "Unable to register DynDNS domain: {error:s}",
"dyndns_domain_not_provided": "Dyndns provider {provider:s} cannot provide domain {domain:s}.",
"dyndns_unavailable": "Domain {domain:s} is not available.",
"executing_command": "Executing command '{command:s}'…",
"executing_script": "Executing script '{script:s}'…",
"extracting": "عملية فك الضغط جارية …",
"field_invalid": "Invalid field '{:s}'",
"firewall_reload_failed": "Unable to reload the firewall",
"firewall_reloaded": "The firewall has been reloaded",
"firewall_rules_cmd_failed": "Some firewall rules commands have failed. For more information, see the log.",
"format_datetime_short": "%m/%d/%Y %I:%M %p",
"global_settings_bad_choice_for_enum": "Bad value for setting {setting:s}, received {received_type:s}, except {expected_type:s}",
"global_settings_bad_type_for_setting": "Bad type for setting {setting:s}, received {received_type:s}, except {expected_type:s}",
"global_settings_cant_open_settings": "Failed to open settings file, reason: {reason:s}",
"global_settings_cant_serialize_settings": "Failed to serialize settings data, reason: {reason:s}",
"global_settings_cant_write_settings": "Failed to write settings file, reason: {reason:s}",
"global_settings_key_doesnt_exists": "The key '{settings_key:s}' doesn't exists in the global settings, you can see all the available keys by doing 'yunohost settings list'",
"global_settings_reset_success": "Success. Your previous settings have been backuped in {path:s}",
"global_settings_setting_example_bool": "Example boolean option",
"global_settings_setting_example_enum": "Example enum option",
"global_settings_setting_example_int": "Example int option",
"global_settings_setting_example_string": "Example string option",
"global_settings_unknown_setting_from_settings_file": "Unknown key in settings: '{setting_key:s}', discarding it and save it in /etc/yunohost/unkown_settings.json",
"global_settings_unknown_type": "Unexpected situation, the setting {setting:s} appears to have the type {unknown_type:s} but it's not a type supported by the system.",
"hook_exec_failed": "Script execution failed: {path:s}",
"hook_exec_not_terminated": "Script execution hasnt terminated: {path:s}",
"hook_list_by_invalid": "Invalid property to list hook by",
"hook_name_unknown": "Unknown hook name '{name:s}'",
"installation_complete": "إكتملت عملية التنصيب",
"installation_failed": "Installation failed",
"invalid_url_format": "Invalid URL format",
"ip6tables_unavailable": "You cannot play with ip6tables here. You are either in a container or your kernel does not support it",
"iptables_unavailable": "You cannot play with iptables here. You are either in a container or your kernel does not support it",
"ldap_init_failed_to_create_admin": "LDAP initialization failed to create admin user",
"ldap_initialized": "LDAP has been initialized",
"license_undefined": "undefined",
"mail_alias_remove_failed": "Unable to remove mail alias '{mail:s}'",
"mail_domain_unknown": "Unknown mail address domain '{domain:s}'",
"mail_forward_remove_failed": "Unable to remove mail forward '{mail:s}'",
"mailbox_used_space_dovecot_down": "Dovecot mailbox service need to be up, if you want to get mailbox used space",
"maindomain_change_failed": "Unable to change the main domain",
"maindomain_changed": "The main domain has been changed",
"migrate_tsig_end": "Migration to hmac-sha512 finished",
"migrate_tsig_failed": "Migrating the dyndns domain {domain} to hmac-sha512 failed, rolling back. Error: {error_code} - {error}",
"migrate_tsig_start": "Not secure enough key algorithm detected for TSIG signature of domain '{domain}', initiating migration to the more secure one hmac-sha512",
"migrate_tsig_wait": "لننتظر الآن 3 دقائق ريثما يأخذ خادم أسماء النطاقات الديناميكية بعين الاعتبار المفتاح الجديد…",
"main_domain_change_failed": "تعذّر تغيير النطاق الأساسي",
"main_domain_changed": "تم تغيير النطاق الأساسي",
"migrate_tsig_wait": "لننتظر الآن ثلاثة دقائق ريثما يأخذ خادم أسماء النطاقات الديناميكية بعين الاعتبار المفتاح الجديد…",
"migrate_tsig_wait_2": "دقيقتين …",
"migrate_tsig_wait_3": "دقيقة واحدة …",
"migrate_tsig_wait_4": "30 ثانية …",
"migrate_tsig_not_needed": "You do not appear to use a dyndns domain, so no migration is needed !",
"migrations_backward": "Migrating backward.",
"migrations_bad_value_for_target": "Invalid number for target argument, available migrations numbers are 0 or {}",
"migrations_cant_reach_migration_file": "Can't access migrations files at path %s",
"migrations_current_target": "Migration target is {}",
"migrations_error_failed_to_load_migration": "ERROR: failed to load migration {number} {name}",
"migrations_forward": "Migrating forward",
"migrations_loading_migration": "Loading migration {number} {name}…",
"migrations_migration_has_failed": "Migration {number} {name} has failed with exception {exception}, aborting",
"migrations_no_migrations_to_run": "No migrations to run",
"migrations_show_currently_running_migration": "Running migration {number} {name}…",
"migrations_show_last_migration": "Last ran migration is {}",
"migrations_skip_migration": "جارٍ تجاهل التهجير {id}…",
"monitor_disabled": "The server monitoring has been disabled",
"monitor_enabled": "The server monitoring has been enabled",
"monitor_glances_con_failed": "Unable to connect to Glances server",
"monitor_not_enabled": "Server monitoring is not enabled",
"monitor_period_invalid": "Invalid time period",
"monitor_stats_file_not_found": "Statistics file not found",
"monitor_stats_no_update": "No monitoring statistics to update",
"monitor_stats_period_unavailable": "No available statistics for the period",
"mountpoint_unknown": "Unknown mountpoint",
"mysql_db_creation_failed": "MySQL database creation failed",
"mysql_db_init_failed": "MySQL database init failed",
"mysql_db_initialized": "The MySQL database has been initialized",
"network_check_mx_ko": "DNS MX record is not set",
"network_check_smtp_ko": "Outbound mail (SMTP port 25) seems to be blocked by your network",
"network_check_smtp_ok": "Outbound mail (SMTP port 25) is not blocked",
"new_domain_required": "You must provide the new main domain",
"no_appslist_found": "No app list found",
"no_internet_connection": "Server is not connected to the Internet",
"no_ipv6_connectivity": "IPv6 connectivity is not available",
"no_restore_script": "No restore script found for the app '{app:s}'",
"not_enough_disk_space": "Not enough free disk space on '{path:s}'",
"package_not_installed": "Package '{pkgname}' is not installed",
"package_unexpected_error": "An unexpected error occurred processing the package '{pkgname}'",
"package_unknown": "Unknown package '{pkgname}'",
"packages_no_upgrade": "لا يوجد هناك أية حزمة بحاجة إلى تحديث",
"packages_upgrade_critical_later": "Critical packages ({packages:s}) will be upgraded later",
"packages_upgrade_failed": "Unable to upgrade all of the packages",
"path_removal_failed": "Unable to remove path {:s}",
"pattern_backup_archive_name": "Must be a valid filename with max 30 characters, and alphanumeric and -_. characters only",
"pattern_domain": "يتوجب أن يكون إسم نطاق صالح (مثل my-domain.org)",
"pattern_email": "يتوجب أن يكون عنوان بريد إلكتروني صالح (مثل someone@domain.org)",
"pattern_firstname": "Must be a valid first name",
"pattern_lastname": "Must be a valid last name",
"pattern_listname": "Must be alphanumeric and underscore characters only",
"pattern_mailbox_quota": "Must be a size with b/k/M/G/T suffix or 0 to disable the quota",
"pattern_password": "يتوجب أن تكون مكونة من 3 حروف على الأقل",
"pattern_port": "يجب أن يكون رقم منفذ صالح (مثال 0-65535)",
"pattern_port_or_range": "Must be a valid port number (i.e. 0-65535) or range of ports (e.g. 100:200)",
"pattern_positive_number": "يجب أن يكون عددا إيجابيا",
"pattern_username": "Must be lower-case alphanumeric and underscore characters only",
"port_already_closed": "Port {port:d} is already closed for {ip_version:s} connections",
"port_already_opened": "Port {port:d} is already opened for {ip_version:s} connections",
"port_available": "المنفذ {port:d} متوفر",
"port_unavailable": "Port {port:d} is not available",
"restore_action_required": "You must specify something to restore",
"restore_already_installed_app": "An app is already installed with the id '{app:s}'",
"restore_app_failed": "Unable to restore the app '{app:s}'",
"restore_cleaning_failed": "Unable to clean-up the temporary restoration directory",
"restore_complete": "Restore complete",
"restore_confirm_yunohost_installed": "Do you really want to restore an already installed system? [{answers:s}]",
"restore_extracting": "جارٍ فك الضغط عن الملفات التي نحتاجها من النسخة الاحتياطية…",
"restore_failed": "Unable to restore the system",
"restore_hook_unavailable": "Restoration script for '{part:s}' not available on your system and not in the archive either",
"restore_may_be_not_enough_disk_space": "Your system seems not to have enough disk space (freespace: {free_space:d} B, needed space: {needed_space:d} B, security margin: {margin:d} B)",
"restore_mounting_archive": "تنصيب النسخة الإحتياطية على المسار '{path:s}'",
"restore_not_enough_disk_space": "Not enough disk space (freespace: {free_space:d} B, needed space: {needed_space:d} B, security margin: {margin:d} B)",
"restore_nothings_done": "Nothing has been restored",
"restore_removing_tmp_dir_failed": "Unable to remove an old temporary directory",
"restore_running_app_script": "Running restore script of app '{app:s}'…",
"restore_running_hooks": "Running restoration hooks…",
"restore_system_part_failed": "Unable to restore the '{part:s}' system part",
"server_shutdown": "سوف ينطفئ الخادوم",
"server_shutdown_confirm": "سوف ينطفئ الخادوم حالا. متأكد ؟ [{answers:s}]",
"server_reboot": "سيعاد تشغيل الخادوم",
"server_reboot_confirm": "سيعاد تشغيل الخادوم في الحين. هل أنت متأكد ؟ [{answers:s}]",
"service_add_failed": "تعذرت إضافة خدمة '{service:s}'",
"service_added": "The service '{service:s}' has been added",
"service_already_started": "Service '{service:s}' has already been started",
"service_already_stopped": "إنّ خدمة '{service:s}' متوقفة مِن قبلُ",
"service_cmd_exec_failed": "Unable to execute command '{command:s}'",
"service_conf_file_backed_up": "The configuration file '{conf}' has been backed up to '{backup}'",
"service_conf_file_copy_failed": "Unable to copy the new configuration file '{new}' to '{conf}'",
"service_conf_file_kept_back": "The configuration file '{conf}' is expected to be deleted by service {service} but has been kept back.",
"service_conf_file_manually_modified": "The configuration file '{conf}' has been manually modified and will not be updated",
"service_conf_file_manually_removed": "The configuration file '{conf}' has been manually removed and will not be created",
"service_conf_file_remove_failed": "Unable to remove the configuration file '{conf}'",
"service_conf_file_removed": "The configuration file '{conf}' has been removed",
"service_conf_file_updated": "The configuration file '{conf}' has been updated",
"service_conf_new_managed_file": "The configuration file '{conf}' is now managed by the service {service}.",
"service_conf_up_to_date": "The configuration is already up-to-date for service '{service}'",
"service_conf_updated": "The configuration has been updated for service '{service}'",
"service_conf_would_be_updated": "The configuration would have been updated for service '{service}'",
"service_disable_failed": "",
"service_disabled": "تم تعطيل خدمة '{service:s}'",
"service_enable_failed": "",
"service_disabled": "لن يتم إطلاق خدمة '{service:s}' أثناء بداية تشغيل النظام.",
"service_enabled": "تم تنشيط خدمة '{service:s}'",
"service_no_log": "ليس لخدمة '{service:s}' أي سِجلّ للعرض",
"service_regenconf_dry_pending_applying": "Checking pending configuration which would have been applied for service '{service}'...",
"service_regenconf_failed": "Unable to regenerate the configuration for service(s): {services}",
"service_regenconf_pending_applying": "Applying pending configuration for service '{service}'...",
"service_remove_failed": "Unable to remove service '{service:s}'",
"service_removed": "تمت إزالة خدمة '{service:s}'",
"service_start_failed": "",
"service_started": "تم إطلاق تشغيل خدمة '{service:s}'",
"service_status_failed": "Unable to determine status of service '{service:s}'",
"service_stop_failed": "",
"service_stopped": "تمّ إيقاف خدمة '{service:s}'",
"service_unknown": "Unknown service '{service:s}'",
"ssowat_conf_generated": "The SSOwat configuration has been generated",
"ssowat_conf_updated": "The SSOwat configuration has been updated",
"ssowat_persistent_conf_read_error": "Error while reading SSOwat persistent configuration: {error:s}. Edit /etc/ssowat/conf.json.persistent file to fix the JSON syntax",
"ssowat_persistent_conf_write_error": "Error while saving SSOwat persistent configuration: {error:s}. Edit /etc/ssowat/conf.json.persistent file to fix the JSON syntax",
"system_upgraded": "تمت عملية ترقية النظام",
"system_username_exists": "Username already exists in the system users",
"unbackup_app": "App '{app:s}' will not be saved",
"unexpected_error": "An unexpected error occured",
"unit_unknown": "Unknown unit '{unit:s}'",
"unlimit": "دون تحديد الحصة",
"unrestore_app": "App '{app:s}' will not be restored",
"update_cache_failed": "Unable to update APT cache",
"updating_apt_cache": "جارٍ جلب قائمة حُزم النظام المحدّثة المتوفرة…",
"upgrade_complete": "إكتملت عملية الترقية و التحديث",
"upgrade_complete": "اكتملت عملية الترقية و التحديث",
"upgrading_packages": "عملية ترقية الحُزم جارية …",
"upnp_dev_not_found": "No UPnP device found",
"upnp_disabled": "تم تعطيل UPnP",
"upnp_enabled": "UPnP has been enabled",
"upnp_port_open_failed": "Unable to open UPnP ports",
"user_created": "تم إنشاء المستخدم",
"user_creation_failed": "Unable to create user",
"user_deleted": "تم حذف المستخدم",
"user_deletion_failed": "لا يمكن حذف المستخدم",
"user_home_creation_failed": "Unable to create user home folder",
"user_info_failed": "Unable to retrieve user information",
"user_unknown": "المستخدم {user:s} مجهول",
"user_update_failed": "لا يمكن تحديث المستخدم",
"user_updated": "تم تحديث المستخدم",
"yunohost_already_installed": "YunoHost is already installed",
"yunohost_ca_creation_failed": "تعذرت عملية إنشاء هيئة الشهادات",
"yunohost_ca_creation_success": "تم إنشاء هيئة الشهادات المحلية.",
"yunohost_configured": "YunoHost has been configured",
"yunohost_installing": "عملية تنصيب يونوهوست جارية …",
"yunohost_not_installed": "إنَّ واي يونوهوست ليس مُنَصَّب أو هو مثبت حاليا بشكل خاطئ. قم بتنفيذ الأمر 'yunohost tools postinstall'",
"migration_description_0003_migrate_to_stretch": "تحديث النظام إلى ديبيان ستريتش و واي يونوهوست 3.0",
"migration_0003_patching_sources_list": "عملية تصحيح ملف المصادر sources.lists جارية…",
"migration_0003_main_upgrade": "بداية عملية التحديث الأساسية…",
"migration_0003_fail2ban_upgrade": "بداية عملية تحديث fail2ban…",
"migration_0003_fail2ban_upgrade": "بداية عملية تحديث Fail2Ban…",
"migration_0003_not_jessie": "إن توزيعة ديبيان الحالية تختلف عن جيسي !",
"migration_description_0002_migrate_to_tsig_sha256": "يقوم بتحسين أمان TSIG لنظام أسماء النطاقات الديناميكة باستخدام SHA512 بدلًا مِن MD5",
"migration_0003_backward_impossible": "لا يُمكن إلغاء عملية الإنتقال إلى ستريتش.",
"migration_0003_system_not_fully_up_to_date": "إنّ نظامك غير مُحدَّث بعدُ لذا يرجى القيام بتحديث عادي أولا قبل إطلاق إجراء الإنتقال إلى نظام ستريتش.",
"migrations_list_conflict_pending_done": "لا يمكنك استخدام --previous و --done معًا على نفس سطر الأوامر.",
"service_description_avahi-daemon": "يسمح لك بالنفاذ إلى خادومك عبر الشبكة المحلية باستخدام yunohost.local",
"service_description_glances": "يقوم بمراقبة معلومات النظام على خادومك",
"service_description_metronome": "يُدير حسابات الدردشة الفورية XMPP",
"service_description_nginx": "يقوم بتوفير النفاذ و السماح بالوصول إلى كافة مواقع الويب المستضافة على خادومك",
"service_description_php5-fpm": "يقوم بتشغيل تطبيقات الـ PHP مع خادوم الويب nginx",
"service_description_postfix": "يقوم بإرسال و تلقي الرسائل البريدية الإلكترونية",
"service_description_yunohost-api": "يقوم بإدارة التفاعلات ما بين واجهة الويب لواي يونوهوست و النظام",
"log_category_404": "فئةالسجل '{category}' لا وجود لها",
"log_app_fetchlist": "إضافة قائمة للتطبيقات",
"log_app_removelist": "حذف قائمة للتطبيقات",
"log_app_change_url": "تعديل رابط تطبيق '{}'",
"log_app_install": "تنصيب تطبيق '{}'",
"log_app_remove": "حذف تطبيق '{}'",
@ -400,11 +121,10 @@
"log_letsencrypt_cert_install": "تنصيب شهادة Lets Encrypt على النطاق '{}'",
"log_selfsigned_cert_install": "تنصيب شهادة موقَّعَة ذاتيا على اسم النطاق '{}'",
"log_letsencrypt_cert_renew": "تجديد شهادة Let's Encrypt لـ '{}'",
"log_service_enable": "تنشيط خدمة '{}'",
"log_user_create": "إضافة المستخدم '{}'",
"log_user_delete": "حذف المستخدم '{}'",
"log_user_update": "تحديث معلومات المستخدم '{}'",
"log_tools_maindomain": "جعل '{}' كنطاق أساسي",
"log_domain_main_domain": "جعل '{}' كنطاق أساسي",
"log_tools_upgrade": "تحديث حُزم ديبيان",
"log_tools_shutdown": "إطفاء الخادم",
"log_tools_reboot": "إعادة تشغيل الخادم",
@ -412,11 +132,11 @@
"service_description_dnsmasq": "مُكلَّف بتحليل أسماء النطاقات (DNS)",
"service_description_mysql": "يقوم بتخزين بيانات التطبيقات (قواعد بيانات SQL)",
"service_description_rspamd": "يقوم بتصفية البريد المزعج و إدارة ميزات أخرى للبريد",
"service_description_yunohost-firewall": "يُدير فتح وإغلاق منافذ الإتصال إلى الخدمات",
"service_description_yunohost-firewall": "يُدير فتح وإغلاق منافذ الاتصال إلى الخدمات",
"users_available": "المستخدمون المتوفرون:",
"aborting": "إلغاء.",
"admin_password_too_long": "يرجى اختيار كلمة سرية أقصر مِن 127 حرف",
"app_not_upgraded": "لم يتم تحديث التطبيقات التالية: {apps}",
"app_not_upgraded": "",
"app_start_install": "جارٍ تثبيت التطبيق {app}…",
"app_start_remove": "جارٍ حذف التطبيق {app}…",
"app_start_restore": "جارٍ استرجاع التطبيق {app}…",
@ -425,23 +145,32 @@
"ask_new_path": "مسار جديد",
"global_settings_setting_security_password_admin_strength": "قوة الكلمة السرية الإدارية",
"global_settings_setting_security_password_user_strength": "قوة الكلمة السرية للمستخدم",
"log_app_addaccess": "إضافة ترخيص بالنفاذ إلى '{}'",
"password_too_simple_1": "يجب أن يكون طول الكلمة السرية على الأقل 8 حروف",
"service_description_php7.0-fpm": "يُشغّل التطبيقات المكتوبة بلغة الـ PHP على Nginx",
"updating_app_lists": "جارٍ جلب التحديثات المتوفرة الخاصة بالتطبيقات…",
"already_up_to_date": "كل شيء على ما يرام! ليس هناك ما يتطلّب تحديثًا!",
"service_description_php7.0-fpm": "يُشغّل التطبيقات المكتوبة بلغة الـ PHP على NGINX",
"already_up_to_date": "كل شيء على ما يرام. ليس هناك ما يتطلّب تحديثًا.",
"service_description_nslcd": "يدير اتصال متسخدمي واي يونوهوست عبر طرفية سطر الأوامر",
"service_description_slapd": "يخزّن المستخدمين والنطاقات والمعلومات المتعلقة بها",
"service_reloaded": "تم إعادة تحميل خدمة '{service:s}'",
"service_reloaded": "تم إعادة تشغيل خدمة '{service:s}'",
"service_restarted": "تم إعادة تشغيل خدمة '{service:s}'",
"group_unknown": "الفريق {group:s} مجهول",
"group_deletion_failed": "فشلت عملية حذف الفريق '{group}'",
"group_deletion_failed": "فشلت عملية حذف الفريق '{group}': {error}",
"group_deleted": "تم حذف الفريق '{group}'",
"group_created": "تم إنشاء الفريق '{group}' بنجاح",
"group_name_already_exist": "الفريق {name:s} موجود بالفعل",
"error_when_removing_sftpuser_group": "حدث خطأ أثناء محاولة حذف فريق sftpusers",
"group_created": "تم إنشاء الفريق '{group}'",
"dyndns_could_not_check_available": "لا يمكن التحقق مِن أنّ {domain:s} متوفر على {provider:s}.",
"backup_mount_archive_for_restore": "جارٍ تهيئة النسخة الاحتياطية للاسترجاع…",
"root_password_replaced_by_admin_password": "لقد تم استبدال كلمة سر الجذر root بالكلمة الإدارية لـ admin.",
"app_upgrade_stopped": "لقد تم إلغاء تحديث كافة التطبيقات لتجنب حادث بسبب فشل تحديث التطبيق السابق"
"app_action_broke_system": "يبدو أنّ هذا الإجراء أدّى إلى تحطيم هذه الخدمات المهمة: {services}",
"diagnosis_basesystem_host": "هذا الخادم يُشغّل ديبيان {debian_version}",
"diagnosis_basesystem_kernel": "هذا الخادم يُشغّل نواة لينكس {kernel_version}",
"diagnosis_basesystem_ynh_single_version": "{package} الإصدار: {version} ({repo})",
"diagnosis_basesystem_ynh_main_version": "هذا الخادم يُشغّل YunoHost {main_version} ({repo})",
"diagnosis_everything_ok": "كل شيء على ما يرام في {category}!",
"diagnosis_ip_connected_ipv4": "الخادم مُتّصل بالإنترنت عبر IPv4!",
"diagnosis_ip_connected_ipv6": "الخادم مُتّصل بالإنترنت عبر IPv6!",
"diagnosis_ip_not_connected_at_all": "يبدو أنّ الخادم غير مُتّصل بتاتا بالإنترنت!؟",
"app_install_failed": "لا يمكن تنصيب {app}: {error}",
"apps_already_up_to_date": "كافة التطبيقات مُحدّثة",
"app_remove_after_failed_install": "جارٍ حذف التطبيق بعدما فشل تنصيبها…",
"apps_catalog_updating": "جارٍ تحديث فهرس التطبيقات…",
"apps_catalog_update_success": "تم تحديث فهرس التطبيقات!"
}

View file

@ -1 +1,3 @@
{}
{
"password_too_simple_1": "পাসওয়ার্ডটি কমপক্ষে 8 টি অক্ষরের দীর্ঘ হওয়া দরকার"
}

View file

@ -1,113 +1,88 @@
{
"action_invalid": "Acció '{action:s}' invàlida",
"admin_password": "Contrasenya d'administració",
"admin_password_change_failed": "No s'ha pogut canviar la contrasenya",
"admin_password_change_failed": "No es pot canviar la contrasenya",
"admin_password_changed": "S'ha canviat la contrasenya d'administració",
"app_already_installed": "{app:s} ja està instal·lada",
"app_already_installed_cant_change_url": "Aquesta aplicació ja està instal·lada. La URL no és pot canviar únicament amb aquesta funció. Mireu a \"app changeurl\" si està disponible.",
"app_already_up_to_date": "{app:s} ja està actualitzada",
"app_argument_choice_invalid": "Aquesta opció no és vàlida per l'argument '{name:s}', ha de ser una de {choices:s}",
"app_argument_invalid": "Valor invàlid per l'argument '{name:s}':{error:s}",
"app_argument_choice_invalid": "Utilitzeu una de les opcions «{choices:s}» per l'argument «{name:s}»",
"app_argument_invalid": "Escolliu un valor vàlid per l'argument «{name:s}»: {error:s}",
"app_argument_required": "Es necessita l'argument '{name:s}'",
"app_change_no_change_url_script": "L'aplicació {app_name:s} encara no permet canviar la seva URL, es possible que s'hagi d'actualitzar.",
"app_change_url_failed_nginx_reload": "No s'ha pogut tornar a carregar nginx. Aquí teniu el resultat de \"nginx -t\":\n{nginx_errors:s}",
"app_change_url_failed_nginx_reload": "No s'ha pogut tornar a carregar NGINX. Aquí teniu el resultat de \"nginx -t\":\n{nginx_errors:s}",
"app_change_url_identical_domains": "L'antic i el nou domini/camí són idèntics ('{domain:s}{path:s}'), no hi ha res per fer.",
"app_change_url_no_script": "Aquesta aplicació '{app_name:s}' encara no permet modificar la URL. Potser s'ha d'actualitzar l'aplicació.",
"app_change_url_success": "La URL de {app:s} s'ha canviat correctament a {domain:s}{path:s}",
"app_change_url_no_script": "L'aplicació '{app_name:s}' encara no permet modificar la URL. Potser s'ha d'actualitzar.",
"app_change_url_success": "La URL de {app:s} ara és {domain:s}{path:s}",
"app_extraction_failed": "No s'han pogut extreure els fitxers d'instal·lació",
"app_id_invalid": "Id de l'aplicació incorrecte",
"app_incompatible": "L'aplicació {app} no és compatible amb la teva versió de YunoHost",
"app_install_files_invalid": "Fitxers d'instal·lació invàlids",
"app_location_already_used": "L'aplicació '{app}' ja està instal·lada en aquest camí ({path})",
"app_make_default_location_already_used": "No es pot fer l'aplicació '{app}' per defecte en el domini {domain} ja que ja és utilitzat per una altra aplicació '{other_app}'",
"app_location_install_failed": "No s'ha pogut instal·lar l'aplicació en aquest camí ja que entra en conflicte amb l'aplicació '{other_app}' ja instal·lada a '{other_path}'",
"app_location_unavailable": "Aquesta url no està disponible o entra en conflicte amb aplicacions ja instal·lades:\n{apps:s}",
"app_manifest_invalid": "Manifest d'aplicació incorrecte: {error}",
"app_no_upgrade": "No hi ha cap aplicació per actualitzar",
"app_id_invalid": "ID de l'aplicació incorrecte",
"app_install_files_invalid": "Aquests fitxers no es poden instal·lar",
"app_make_default_location_already_used": "No es pot fer l'aplicació '{app}' per defecte en el domini «{domain}» ja que ja és utilitzat per una altra aplicació '{other_app}'",
"app_location_unavailable": "Aquesta URL no està disponible o entra en conflicte amb aplicacions ja instal·lades:\n{apps:s}",
"app_manifest_invalid": "Hi ha algun error amb el manifest de l'aplicació: {error}",
"app_not_correctly_installed": "{app:s} sembla estar mal instal·lada",
"app_not_installed": "L'aplicació «{app:s}» no està instal·lada. Aquí hi ha la llista d'aplicacions instal·lades: {all_apps}",
"app_not_installed": "No s'ha trobat l'aplicació «{app:s}» en la llista d'aplicacions instal·lades: {all_apps}",
"app_not_properly_removed": "{app:s} no s'ha pogut suprimir correctament",
"app_package_need_update": "El paquet de l'aplicació {app} ha de ser actualitzat per poder seguir els canvis de YunoHost",
"app_removed": "{app:s} ha estat suprimida",
"app_requirements_checking": "Verificació dels paquets requerits per {app}…",
"app_requirements_failed": "No es poden satisfer els requeriments per {app}: {error}",
"app_requirements_unmeet": "No es compleixen els requeriments per {app}, el paquet {pkgname} ({version}) ha de ser {spec}",
"app_sources_fetch_failed": "No s'han pogut carregar els fitxers font, l'URL és correcta?",
"app_unknown": "Aplicació desconeguda",
"app_unsupported_remote_type": "El tipus remot utilitzat per l'aplicació no està suportat",
"app_upgrade_app_name": "Actualitzant l'aplicació {app}…",
"app_upgrade_failed": "No s'ha pogut actualitzar {app:s}",
"app_upgrade_app_name": "Actualitzant {app}…",
"app_upgrade_failed": "No s'ha pogut actualitzar {app:s}: {error}",
"app_upgrade_some_app_failed": "No s'han pogut actualitzar algunes aplicacions",
"app_upgraded": "{app:s} ha estat actualitzada",
"appslist_corrupted_json": "No s'han pogut carregar les llistes d'aplicacions. Sembla que {filename:s} està danyat.",
"appslist_could_not_migrate": "No s'ha pogut migrar la llista d'aplicacions {appslist:s}! No s'ha pogut analitzar la URL... L'antic cronjob s'ha guardat a {bkp_file:s}.",
"appslist_fetched": "S'ha descarregat la llista d'aplicacions {appslist:s} correctament",
"appslist_migrating": "Migrant la llista d'aplicacions {appslist:s}…",
"appslist_name_already_tracked": "Ja hi ha una llista d'aplicacions registrada amb el nom {name:s}.",
"appslist_removed": "S'ha eliminat la llista d'aplicacions {appslist:s}",
"appslist_retrieve_bad_format": "L'arxiu obtingut per la llista d'aplicacions {appslist:s} no és vàlid",
"appslist_retrieve_error": "No s'ha pogut obtenir la llista d'aplicacions remota {appslist:s}: {error:s}",
"appslist_unknown": "La llista d'aplicacions {appslist:s} es desconeguda.",
"appslist_url_already_tracked": "Ja hi ha una llista d'aplicacions registrada amb al URL {url:s}.",
"ask_current_admin_password": "Contrasenya d'administrador actual",
"ask_email": "Correu electrònic",
"app_upgraded": "S'ha actualitzat {app:s}",
"ask_email": "Adreça de correu electrònic",
"ask_firstname": "Nom",
"ask_lastname": "Cognom",
"ask_list_to_remove": "Llista per a suprimir",
"ask_main_domain": "Domini principal",
"ask_new_admin_password": "Nova contrasenya d'administrador",
"ask_password": "Contrasenya",
"ask_path": "Camí",
"backup_abstract_method": "Encara no s'ha implementat aquest mètode de copia de seguretat",
"backup_action_required": "S'ha d'especificar què s'ha de guardar",
"backup_abstract_method": "Encara està per implementar aquest mètode de còpia de seguretat",
"backup_app_failed": "No s'ha pogut fer la còpia de seguretat de l'aplicació \"{app:s}\"",
"backup_applying_method_borg": "Enviant tots els fitxers de la còpia de seguretat al repositori borg-backup…",
"backup_applying_method_copy": "Còpia de tots els fitxers a la còpia de seguretat…",
"backup_applying_method_custom": "Crida del mètode de còpia de seguretat personalitzat \"{method:s}\"…",
"backup_applying_method_tar": "Creació de l'arxiu tar de la còpia de seguretat…",
"backup_archive_app_not_found": "L'aplicació \"{app:s}\" no es troba dins l'arxiu de la còpia de seguretat",
"backup_applying_method_tar": "Creació de l'arxiu TAR de la còpia de seguretat…",
"backup_archive_app_not_found": "No s'ha pogut trobar l'aplicació «{app:s}» dins l'arxiu de la còpia de seguretat",
"backup_archive_broken_link": "No s'ha pogut accedir a l'arxiu de la còpia de seguretat (enllaç invàlid cap a {path:s})",
"backup_archive_mount_failed": "No s'ha pogut carregar l'arxiu de la còpia de seguretat",
"backup_archive_name_exists": "Ja hi ha una còpia de seguretat amb aquest nom",
"backup_archive_name_exists": "Ja hi ha una còpia de seguretat amb aquest nom.",
"backup_archive_name_unknown": "Còpia de seguretat local \"{name:s}\" desconeguda",
"backup_archive_open_failed": "No s'ha pogut obrir l'arxiu de la còpia de seguretat",
"backup_archive_system_part_not_available": "La part \"{part:s}\" del sistema no està disponible en aquesta copia de seguretat",
"backup_archive_writing_error": "No es poden afegir arxius a l'arxiu comprimit de la còpia de seguretat",
"backup_ask_for_copying_if_needed": "Alguns fitxers no s'han pogut preparar per la còpia de seguretat utilitzant el mètode que evita malgastar espai del sistema temporalment. Per fer la còpia de seguretat, s'han d'utilitzar {size:s}MB temporalment. Hi esteu d'acord?",
"backup_archive_system_part_not_available": "La part «{part:s}» del sistema no està disponible en aquesta copia de seguretat",
"backup_archive_writing_error": "No es poden afegir els arxius «{source:s}» (anomenats en l'arxiu «{dest:s}») a l'arxiu comprimit de la còpia de seguretat «{archive:s}»",
"backup_ask_for_copying_if_needed": "Voleu fer la còpia de seguretat utilitzant {size:s} MB temporalment? (S'utilitza aquest mètode ja que alguns dels fitxers no s'han pogut preparar utilitzar un mètode més eficient.)",
"backup_borg_not_implemented": "El mètode de còpia de seguretat Borg encara no està implementat",
"backup_cant_mount_uncompress_archive": "No es pot carregar en mode de lectura només el directori de l'arxiu descomprimit",
"backup_cant_mount_uncompress_archive": "No es pot carregar l'arxiu descomprimit com a protegit contra escriptura",
"backup_cleaning_failed": "No s'ha pogut netejar el directori temporal de la còpia de seguretat",
"backup_copying_to_organize_the_archive": "Copiant {size:s}MB per organitzar l'arxiu",
"backup_couldnt_bind": "No es pot lligar {src:s} amb {dest:s}.",
"backup_created": "S'ha creat la còpia de seguretat",
"backup_creating_archive": "Creant l'arxiu de la còpia de seguretat…",
"aborting": "Avortant.",
"app_not_upgraded": "Les següents aplicacions no s'han actualitzat: {apps}",
"app_start_install": "instal·lant l'aplicació {app}…",
"app_start_remove": "Eliminant l'aplicació {app}…",
"app_start_backup": "Recuperant els fitxers pels que s'ha de fer una còpia de seguretat per {app}…",
"app_start_restore": "Recuperant l'aplicació {app}…",
"app_not_upgraded": "L'aplicació «{failed_app}» no s'ha pogut actualitzar, i com a conseqüència l'actualització de les següents aplicacions ha estat cancel·lada: {apps}",
"app_start_install": "instal·lant l'aplicació «{app}»…",
"app_start_remove": "Eliminant l'aplicació «{app}»…",
"app_start_backup": "Recuperant els fitxers pels que s'ha de fer una còpia de seguretat per «{app}»…",
"app_start_restore": "Recuperant l'aplicació «{app}»…",
"app_upgrade_several_apps": "S'actualitzaran les següents aplicacions: {apps}",
"ask_new_domain": "Nou domini",
"ask_new_path": "Nou camí",
"backup_actually_backuping": "S'està creant un arxiu de còpia de seguretat a partir dels fitxers recuperats…",
"backup_creation_failed": "Ha fallat la creació de la còpia de seguretat",
"backup_actually_backuping": "Creant un arxiu de còpia de seguretat a partir dels fitxers recuperats…",
"backup_creation_failed": "No s'ha pogut crear l'arxiu de la còpia de seguretat",
"backup_csv_addition_failed": "No s'han pogut afegir fitxers per a fer-ne la còpia de seguretat al fitxer CSV",
"backup_csv_creation_failed": "No s'ha pogut crear el fitxer CSV necessari per a futures operacions de recuperació",
"backup_custom_backup_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa \"backup\"",
"backup_custom_mount_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa \"mount\"",
"backup_custom_need_mount_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa \"need_mount\"",
"backup_delete_error": "No s'ha pogut suprimir \"{path:s}\"",
"backup_csv_creation_failed": "No s'ha pogut crear el fitxer CSV necessari per a la restauració",
"backup_custom_backup_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa «backup»",
"backup_custom_mount_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa «mount»",
"backup_delete_error": "No s'ha pogut suprimir «{path:s}»",
"backup_deleted": "S'ha suprimit la còpia de seguretat",
"backup_extracting_archive": "Extraient l'arxiu de la còpia de seguretat…",
"backup_hook_unknown": "Script de còpia de seguretat \"{hook:s}\" desconegut",
"backup_invalid_archive": "Arxiu de còpia de seguretat no vàlid",
"backup_method_borg_finished": "La còpia de seguretat a borg ha acabat",
"backup_hook_unknown": "Script de còpia de seguretat «{hook:s}» desconegut",
"backup_invalid_archive": "Aquest no és un arxiu de còpia de seguretat",
"backup_method_borg_finished": "La còpia de seguretat a Borg ha acabat",
"backup_method_copy_finished": "La còpia de la còpia de seguretat ha acabat",
"backup_method_custom_finished": "El mètode de còpia de seguretat personalitzat \"{method:s}\" ha acabat",
"backup_method_tar_finished": "S'ha creat l'arxiu de còpia de seguretat tar",
"backup_method_tar_finished": "S'ha creat l'arxiu de còpia de seguretat TAR",
"backup_mount_archive_for_restore": "Preparant l'arxiu per la restauració…",
"good_practices_about_user_password": "Esteu a punt de definir una nova contrasenya d'usuari. La contrasenya ha de tenir un mínim de 8 caràcters ; tot i que és de bona pràctica utilitzar una contrasenya més llarga (és a dir una frase de contrasenya) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials).",
"good_practices_about_user_password": "Esteu a punt de definir una nova contrasenya d'usuari. La contrasenya ha de tenir un mínim de 8 caràcters; tot i que és de bona pràctica utilitzar una contrasenya més llarga (és a dir una frase de contrasenya) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials).",
"password_listed": "Aquesta contrasenya és una de les més utilitzades en el món. Si us plau utilitzeu-ne una més única.",
"password_too_simple_1": "La contrasenya ha de tenir un mínim de 8 caràcters",
"password_too_simple_2": "La contrasenya ha de tenir un mínim de 8 caràcters i ha de contenir dígits, majúscules i minúscules",
@ -115,71 +90,58 @@
"password_too_simple_4": "La contrasenya ha de tenir un mínim de 12 caràcters i tenir dígits, majúscules, minúscules i caràcters especials",
"backup_no_uncompress_archive_dir": "El directori de l'arxiu descomprimit no existeix",
"backup_nothings_done": "No hi ha res a guardar",
"backup_output_directory_forbidden": "Directori de sortida no permès. Les còpies de seguretat no es poden crear ni dins els directoris /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var ni dins els subdirectoris /home/yunohost.backup/archives",
"backup_output_directory_not_empty": "El directori de sortida no està buit",
"backup_output_directory_forbidden": "Escolliu un directori de sortida different. Les còpies de seguretat no es poden crear ni dins els directoris /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var ni dins els subdirectoris /home/yunohost.backup/archives",
"backup_output_directory_not_empty": "Heu d'escollir un directori de sortida buit",
"backup_output_directory_required": "Heu d'especificar un directori de sortida per la còpia de seguretat",
"backup_output_symlink_dir_broken": "Teniu un enllaç simbòlic trencat en lloc del directori dels arxius '{path:s}'. Pot ser teniu una configuració per la còpia de seguretat específica en un altre sistema de fitxers, si és el cas segurament heu oblidat muntar o connectar el disc dur o la clau USB.",
"backup_php5_to_php7_migration_may_fail": "No s'ha pogut convertir l'arxiu per suportar php7, la restauració de les vostres aplicacions pot fallar (raó: {error:s})",
"backup_output_symlink_dir_broken": "El directori del arxiu «{path:s}» es un enllaç simbòlic trencat. Pot ser heu oblidat muntar, tornar a muntar o connectar el mitja d'emmagatzematge al que apunta.",
"backup_php5_to_php7_migration_may_fail": "No s'ha pogut convertir l'arxiu per suportar PHP 7, pot ser que no es puguin restaurar les vostres aplicacions PHP (raó: {error:s})",
"backup_running_hooks": "Executant els scripts de la còpia de seguretat…",
"backup_system_part_failed": "No s'ha pogut fer la còpia de seguretat de la part \"{part:s}\" del sistema",
"backup_unable_to_organize_files": "No s'han pogut organitzar els fitxers dins de l'arxiu amb el mètode ràpid",
"backup_with_no_backup_script_for_app": "L'aplicació {app:s} no té un script de còpia de seguretat. Serà ignorat.",
"backup_with_no_restore_script_for_app": "L'aplicació {app:s} no té un script de restauració, no podreu restaurar automàticament la còpia de seguretat d'aquesta aplicació.",
"certmanager_acme_not_configured_for_domain": "El certificat pel domini {domain:s} sembla que no està instal·lat correctament. Si us plau executeu primer cert-install per aquest domini.",
"certmanager_attempt_to_renew_nonLE_cert": "El certificat pel domini {domain:s} no ha estat emès per Let's Encrypt. No es pot renovar automàticament!",
"certmanager_attempt_to_renew_valid_cert": "El certificat pel domini {domain:s} està a punt de caducar! (Utilitzeu --force si sabeu el que esteu fent)",
"backup_unable_to_organize_files": "No s'ha pogut utilitzar el mètode ràpid per organitzar els fitxers dins de l'arxiu",
"backup_with_no_backup_script_for_app": "L'aplicació «{app:s}» no té un script de còpia de seguretat. Serà ignorat.",
"backup_with_no_restore_script_for_app": "L'aplicació «{app:s}» no té un script de restauració, no podreu restaurar automàticament la còpia de seguretat d'aquesta aplicació.",
"certmanager_acme_not_configured_for_domain": "El certificat pel domini «{domain:s}» sembla que no està instal·lat correctament. Si us plau executeu primer «cert-install» per aquest domini.",
"certmanager_attempt_to_renew_nonLE_cert": "El certificat pel domini «{domain:s}» no ha estat emès per Let's Encrypt. No es pot renovar automàticament!",
"certmanager_attempt_to_renew_valid_cert": "El certificat pel domini «{domain:s}» està a punt de caducar! (Utilitzeu --force si sabeu el que esteu fent)",
"certmanager_attempt_to_replace_valid_cert": "Esteu intentant sobreescriure un certificat correcte i vàlid pel domini {domain:s}! (Utilitzeu --force per ometre)",
"certmanager_cannot_read_cert": "S'ha produït un error al intentar obrir el certificat actual pel domini {domain:s} (arxiu: {file:s}), raó: {reason:s}",
"certmanager_cert_install_success": "S'ha instal·lat correctament un certificat Let's Encrypt pel domini {domain:s}!",
"certmanager_cert_install_success_selfsigned": "S'ha instal·lat correctament un certificat auto-signat pel domini {domain:s}!",
"certmanager_cert_renew_success": "S'ha renovat correctament el certificat Let's Encrypt pel domini {domain:s}!",
"certmanager_cert_install_success": "S'ha instal·lat correctament un certificat Let's Encrypt pel domini «{domain:s}»",
"certmanager_cert_install_success_selfsigned": "S'ha instal·lat correctament un certificat auto-signat pel domini «{domain:s}»",
"certmanager_cert_renew_success": "S'ha renovat correctament el certificat Let's Encrypt pel domini «{domain:s}»",
"certmanager_cert_signing_failed": "No s'ha pogut firmar el nou certificat",
"certmanager_certificate_fetching_or_enabling_failed": "Sembla que l'activació del nou certificat per {domain:s} ha fallat…",
"certmanager_conflicting_nginx_file": "No s'ha pogut preparar el domini per al desafiament ACME: l'arxiu de configuració nginx {filepath:s} entra en conflicte i s'ha d'eliminar primer",
"certmanager_certificate_fetching_or_enabling_failed": "Sembla que utilitzar el nou certificat per {domain:s} ha fallat…",
"certmanager_conflicting_nginx_file": "No s'ha pogut preparar el domini per al desafiament ACME: l'arxiu de configuració NGINX {filepath:s} entra en conflicte i s'ha d'eliminar primer",
"certmanager_couldnt_fetch_intermediate_cert": "S'ha exhaurit el temps d'esperar al intentar recollir el certificat intermedi des de Let's Encrypt. La instal·lació/renovació del certificat s'ha cancel·lat - torneu a intentar-ho més tard.",
"certmanager_domain_cert_not_selfsigned": "El certificat pel domini {domain:s} no és auto-signat Esteu segur de voler canviar-lo? (Utilitzeu --force per fer-ho)",
"certmanager_domain_dns_ip_differs_from_public_ip": "El registre DNS \"A\" pel domini {domain:s} és diferent a l'adreça IP d'aquest servidor. Si heu modificat recentment el registre A, si us plau espereu a que es propagui (hi ha eines per verificar la propagació disponibles a internet). (Si sabeu el que esteu fent, podeu utilitzar --no-checks per desactivar aquestes comprovacions.)",
"certmanager_domain_http_not_working": "Sembla que el domini {domain:s} no és accessible via HTTP. Si us plau verifiqueu que les configuracions DNS i nginx siguin correctes",
"certmanager_domain_not_resolved_locally": "El domini {domain:s} no es pot resoldre dins del vostre servidor YunoHost. Això pot passar si heu modificat recentment el registre DNS. Si és així, si us plau espereu unes hores per a que es propagui. Si el problema continua, considereu afegir {domain:s} a /etc/hosts. (Si sabeu el que esteu fent, podeu utilitzar --no-checks per desactivar aquestes comprovacions.)",
"certmanager_domain_unknown": "Domini desconegut {domain:s}",
"certmanager_error_no_A_record": "No s'ha trobat cap registre DNS \"A\" per {domain:s}. Heu de fer que el vostre nom de domini apunti cap a la vostra màquina per tal de poder instal·lar un certificat Let's Encrypt! (Si sabeu el que esteu fent, podeu utilitzar --no-checks per desactivar aquestes comprovacions.)",
"certmanager_domain_cert_not_selfsigned": "El certificat pel domini {domain:s} no és auto-signat Esteu segur de voler canviar-lo? (Utilitzeu «--force» per fer-ho)",
"certmanager_domain_dns_ip_differs_from_public_ip": "El registre DNS \"A\" pel domini «{domain:s}» és diferent a l'adreça IP d'aquest servidor. Si heu modificat recentment el registre A, si us plau espereu a que es propagui (hi ha eines per verificar la propagació disponibles a internet). (Si sabeu el que esteu fent, podeu utilitzar «--no-checks» per desactivar aquestes comprovacions.)",
"certmanager_domain_http_not_working": "Sembla que el domini {domain:s} no és accessible via HTTP. Verifiqueu que les configuracions DNS i NGINX siguin correctes",
"certmanager_domain_unknown": "Domini desconegut «{domain:s}»",
"certmanager_error_no_A_record": "No s'ha trobat cap registre DNS «A» per «{domain:s}». Heu de fer que el vostre nom de domini apunti cap a la vostra màquina per tal de poder instal·lar un certificat Let's Encrypt. (Si sabeu el que esteu fent, podeu utilitzar «--no-checks» per desactivar aquestes comprovacions.)",
"certmanager_hit_rate_limit": "S'han emès massa certificats recentment per aquest mateix conjunt de dominis {domain:s}. Si us plau torneu-ho a intentar més tard. Consulteu https://letsencrypt.org/docs/rate-limits/ per obtenir més detalls",
"certmanager_http_check_timeout": "S'ha exhaurit el temps d'espera quan el servidor ha intentat contactar amb ell mateix via HTTP utilitzant la seva adreça IP pública (domini domain:s} amb IP {ip:s}). Pot ser degut a hairpinning o a que el talla focs/router al que està connectat el servidor estan mal configurats.",
"certmanager_http_check_timeout": "S'ha exhaurit el temps d'espera quan el servidor ha intentat contactar amb ell mateix via HTTP utilitzant la seva adreça IP pública (domini «{domain:s}» amb IP «{ip:s}»). Pot ser degut a hairpinning o a que el talla focs/router al que està connectat el servidor estan mal configurats.",
"certmanager_no_cert_file": "No s'ha pogut llegir l'arxiu del certificat pel domini {domain:s} (fitxer: {file:s})",
"certmanager_self_ca_conf_file_not_found": "No s'ha trobat el fitxer de configuració per l'autoritat del certificat auto-signat (fitxer: {file:s})",
"certmanager_unable_to_parse_self_CA_name": "No s'ha pogut analitzar el nom de l'autoritat del certificat auto-signat (fitxer: {file:s})",
"confirm_app_install_warning": "Atenció: aquesta aplicació funciona però no està ben integrada amb YunoHost. Algunes característiques com la autenticació única i la còpia de seguretat/restauració poden no estar disponibles. Voleu instal·lar-la de totes maneres? [{answers:s}] ",
"confirm_app_install_danger": "ATENCIÓ! Aquesta aplicació encara és experimental (si no és que no funciona directament) i és probable que trenqui el sistema! No hauríeu d'instal·lar-la a no ser que sapigueu el que feu. Esteu segurs de voler córrer aquest risc? [{answers:s}] ",
"confirm_app_install_thirdparty": "ATENCIÓ! La instal·lació d'aplicacions de terceres parts pot comprometre la integritat i seguretat del seu sistema. Faci-ho sota la seva responsabilitat.No hauríeu d'instal·lar-ne a no ser que sapigueu el que feu. Esteu segurs de voler córrer aquest risc? [{answers:s}] ",
"confirm_app_install_warning": "Atenció: Aquesta aplicació funciona, però no està ben integrada amb YunoHost. Algunes característiques com la autenticació única i la còpia de seguretat/restauració poden no estar disponibles. Voleu instal·lar-la de totes maneres? [{answers:s}] ",
"confirm_app_install_danger": "PERILL! Aquesta aplicació encara és experimental (si no és que no funciona directament)! No hauríeu d'instal·lar-la a no ser que sapigueu el que feu. No obtindreu CAP AJUDA si l'aplicació no funciona o trenca el sistema… Si accepteu el risc, escriviu «{answers:s}»",
"confirm_app_install_thirdparty": "PERILL! Aquesta aplicació no es part del catàleg d'aplicacions de YunoHost. La instal·lació d'aplicacions de terceres parts pot comprometre la integritat i seguretat del seu sistema. No hauríeu d'instal·lar-ne a no ser que sapigueu el que feu. No obtindreu CAP AJUDA si l'aplicació no funciona o trenca el sistema… Si accepteu el risc, escriviu «{answers:s}»",
"custom_app_url_required": "Heu de especificar una URL per actualitzar la vostra aplicació personalitzada {app:s}",
"custom_appslist_name_required": "Heu d'especificar un nom per la vostra llista d'aplicacions personalitzada",
"diagnosis_debian_version_error": "No s'ha pogut obtenir la versió Debian: {error}",
"diagnosis_kernel_version_error": "No s'ha pogut obtenir la versió del nucli: {error}",
"diagnosis_monitor_disk_error": "No es poden monitorar els discs: {error}",
"diagnosis_monitor_network_error": "No es pot monitorar la xarxa: {error}",
"diagnosis_monitor_system_error": "No es pot monitorar el sistema: {error}",
"diagnosis_no_apps": "No hi ha cap aplicació instal·lada",
"admin_password_too_long": "Trieu una contrasenya de menys de 127 caràcters",
"dpkg_is_broken": "No es pot fer això en aquest instant perquè dpkg/apt (els gestors de paquets del sistema) sembla estar mal configurat... Podeu intentar solucionar-ho connectant-vos per ssh i executant \"sudo dpkg --configure -a\".",
"dnsmasq_isnt_installed": "sembla que dnsmasq no està instal·lat, executeu \"apt-get remove bind9 && apt-get install dnsmasq\"",
"domain_cannot_remove_main": "No es pot eliminar el domini principal. S'ha d'establir un nou domini primer",
"dpkg_is_broken": "No es pot fer això en aquest instant perquè dpkg/APT (els gestors de paquets del sistema) sembla estar mal configurat… Podeu intentar solucionar-ho connectant-vos per SSH i executant «sudo dpkg --configure -a».",
"domain_cannot_remove_main": "No es pot eliminar «{domain:s}» ja que és el domini principal, primer s'ha d'establir un nou domini principal utilitzant «yunohost domain main-domain -n <un-altre-domini>»; aquí hi ha una llista dels possibles dominis: {other_domains:s}",
"domain_cert_gen_failed": "No s'ha pogut generar el certificat",
"domain_created": "S'ha creat el domini",
"domain_creation_failed": "No s'ha pogut crear el domini",
"domain_creation_failed": "No s'ha pogut crear el domini {domain}: {error}",
"domain_deleted": "S'ha eliminat el domini",
"domain_deletion_failed": "No s'ha pogut eliminar el domini",
"domain_deletion_failed": "No s'ha pogut eliminar el domini {domain}: {error}",
"domain_exists": "El domini ja existeix",
"app_action_cannot_be_ran_because_required_services_down": "Aquesta aplicació necessita serveis que estan aturats. Abans de continuar, hauríeu d'intentar arrancar de nou els serveis següents (i també investigar perquè estan aturats) : {services}",
"app_action_cannot_be_ran_because_required_services_down": "Aquests serveis necessaris haurien d'estar funcionant per poder executar aquesta acció: {services} Intenteu reiniciar-los per continuar (i possiblement investigar perquè estan aturats).",
"domain_dns_conf_is_just_a_recommendation": "Aquesta ordre mostra la configuració *recomanada*. En cap cas fa la configuració del DNS. És la vostra responsabilitat configurar la zona DNS en el vostre registrar en acord amb aquesta recomanació.",
"domain_dyndns_already_subscribed": "Ja us heu subscrit a un domini DynDNS",
"domain_dyndns_dynette_is_unreachable": "No s'ha pogut abastar la dynette YunoHost, o bé YunoHost no està connectat a internet correctament o bé el servidor dynette està caigut. Error: {error}",
"domain_dyndns_invalid": "Domini no vàlid per utilitzar amb DynDNS",
"domain_dyndns_root_unknown": "Domini DynDNS principal desconegut",
"domain_hostname_failed": "No s'ha pogut establir un nou nom d'amfitrió. Això podria causar problemes més tard (no és segur ... podria no passar res).",
"domain_hostname_failed": "No s'ha pogut establir un nou nom d'amfitrió. Això podria causar problemes més tard (podria no passar res).",
"domain_uninstall_app_first": "Hi ha una o més aplicacions instal·lades en aquest domini. Desinstal·leu les abans d'eliminar el domini",
"domain_unknown": "Domini desconegut",
"domain_zone_exists": "El fitxer de zona DNS ja existeix",
"domain_zone_not_found": "No s'ha trobat el fitxer de zona DNS pel domini {:s}",
"domains_available": "Dominis disponibles:",
"done": "Fet",
"downloading": "Descarregant…",
@ -187,68 +149,61 @@
"dyndns_could_not_check_available": "No s'ha pogut verificar la disponibilitat de {domain:s} a {provider:s}.",
"dyndns_ip_update_failed": "No s'ha pogut actualitzar l'adreça IP al DynDNS",
"dyndns_ip_updated": "S'ha actualitzat l'adreça IP al DynDNS",
"dyndns_key_generating": "S'està generant la clau DNS, això pot trigar una estona…",
"dyndns_key_generating": "S'està generant la clau DNS… això pot trigar una estona.",
"dyndns_key_not_found": "No s'ha trobat la clau DNS pel domini",
"dyndns_no_domain_registered": "No hi ha cap domini registrat amb DynDNS",
"dyndns_registered": "S'ha registrat el domini DynDNS",
"dyndns_registration_failed": "No s'ha pogut registrar el domini DynDNS: {error:s}",
"dyndns_domain_not_provided": "El proveïdor {provider:s} no pot oferir el domini {domain:s}.",
"dyndns_domain_not_provided": "El proveïdor de DynDNS {provider:s} no pot oferir el domini {domain:s}.",
"dyndns_unavailable": "El domini {domain:s} no està disponible.",
"executing_command": "Execució de l'ordre « {command:s} »…",
"executing_script": "Execució de l'script « {script:s} »…",
"extracting": "Extracció en curs…",
"dyndns_cron_installed": "S'ha instal·lat la tasca cron pel DynDNS",
"dyndns_cron_installed": "S'ha creat la tasca cron pel DynDNS",
"dyndns_cron_remove_failed": "No s'ha pogut eliminar la tasca cron per a DynDNS: {error}",
"dyndns_cron_removed": "S'ha eliminat la tasca cron pel DynDNS",
"experimental_feature": "Atenció: aquesta funcionalitat és experimental i no es considera estable, no s'ha d'utilitzar a excepció de saber el que esteu fent.",
"experimental_feature": "Atenció: Aquesta funcionalitat és experimental i no es considera estable, no s'ha d'utilitzar a excepció de saber el que esteu fent.",
"field_invalid": "Camp incorrecte « {:s} »",
"file_does_not_exist": "El camí {path:s} no existeix.",
"firewall_reload_failed": "No s'ha pogut tornar a carregar el tallafoc",
"firewall_reloaded": "S'ha tornat a carregar el tallafoc",
"firewall_rules_cmd_failed": "No s'han pogut aplicar algunes regles del tallafoc. Mireu el registre per a més informació.",
"format_datetime_short": "%d/%m/%Y %H:%M",
"global_settings_bad_choice_for_enum": "Opció pel paràmetre {setting:s} incorrecta, s'ha rebut «{choice:s}» però les opcions disponibles són: {available_choices:s}",
"firewall_reload_failed": "No s'ha pogut tornar a carregar el tallafocs",
"firewall_reloaded": "S'ha tornat a carregar el tallafocs",
"firewall_rules_cmd_failed": "No s'han pogut aplicar algunes regles del tallafocs. Més informació en el registre.",
"global_settings_bad_choice_for_enum": "Opció pel paràmetre {setting:s} incorrecta, s'ha rebut «{choice:s}», però les opcions disponibles són: {available_choices:s}",
"global_settings_bad_type_for_setting": "El tipus del paràmetre {setting:s} és incorrecte. S'ha rebut {received_type:s}, però s'esperava {expected_type:s}",
"global_settings_cant_open_settings": "No s'ha pogut obrir el fitxer de configuració, raó: {reason:s}",
"global_settings_cant_serialize_settings": "No s'ha pogut serialitzar les dades de configuració, raó: {reason:s}",
"global_settings_cant_write_settings": "No s'ha pogut escriure el fitxer de configuració, raó: {reason:s}",
"global_settings_key_doesnt_exists": "La clau « {settings_key:s} » no existeix en la configuració global, podeu veure totes les claus disponibles executant «yunohost settings list »",
"global_settings_reset_success": "Èxit. S'ha fet una còpia de seguretat de la configuració anterior a {path:s}",
"global_settings_reset_success": "S'ha fet una còpia de seguretat de la configuració anterior a {path:s}",
"global_settings_setting_example_bool": "Exemple d'opció booleana",
"global_settings_setting_example_enum": "Exemple d'opció de tipus enumeració",
"global_settings_setting_example_int": "Exemple d'opció de tipus enter",
"global_settings_setting_example_string": "Exemple d'opció de tipus cadena",
"global_settings_setting_security_nginx_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor web nginx. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)",
"global_settings_setting_security_nginx_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor web NGINX. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)",
"global_settings_setting_security_password_admin_strength": "Robustesa de la contrasenya d'administrador",
"global_settings_setting_security_password_user_strength": "Robustesa de la contrasenya de l'usuari",
"global_settings_setting_security_ssh_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor SSH. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)",
"global_settings_unknown_setting_from_settings_file": "Clau de configuració desconeguda: «{setting_key:s}», refusant-la i guardant-la a /etc/yunohost/settings-unknown.json",
"global_settings_unknown_setting_from_settings_file": "Clau de configuració desconeguda: «{setting_key:s}», refusada i guardada a /etc/yunohost/settings-unknown.json",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Permetre la clau d'hoste DSA (obsolet) per la configuració del servei SSH",
"global_settings_unknown_type": "Situació inesperada, la configuració {setting:s} sembla tenir el tipus {unknown_type:s} però no és un tipus reconegut pel sistema.",
"good_practices_about_admin_password": "Esteu a punt de definir una nova contrasenya d'administrador. La contrasenya ha de tenir un mínim de 8 caràcters ; tot i que és de bona pràctica utilitzar una contrasenya més llarga (és a dir una frase de contrasenya) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials).",
"hook_exec_failed": "No s'ha pogut executar l'script: {path:s}",
"hook_exec_not_terminated": "L'execució de l'script « {path:s} » no s'ha acabat correctament",
"hook_json_return_error": "No s'ha pogut llegir el retorn de l'script {path:s}. Error: {msg:s}. Contingut en brut: {raw_content}",
"hook_list_by_invalid": "Propietat per llistar les accions invàlida",
"good_practices_about_admin_password": "Esteu a punt de definir una nova contrasenya d'administrador. La contrasenya ha de tenir un mínim de 8 caràcters; tot i que és de bona pràctica utilitzar una contrasenya més llarga (és a dir una frase de contrasenya) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials).",
"hook_exec_failed": "No s'ha pogut executar el script: {path:s}",
"hook_exec_not_terminated": "El script no s'ha acabat correctament: {path:s}",
"hook_json_return_error": "No s'ha pogut llegir el retorn del script {path:s}. Error: {msg:s}. Contingut en brut: {raw_content}",
"hook_list_by_invalid": "Aquesta propietat no es pot utilitzar per llistar els hooks",
"hook_name_unknown": "Nom de script « {name:s} »desconegut",
"installation_complete": "Instal·lació completada",
"installation_failed": "Ha fallat la instal·lació",
"invalid_url_format": "Format d'URL invàlid",
"installation_failed": "Ha fallat alguna cosa amb la instal·lació",
"ip6tables_unavailable": "No podeu modificar les ip6tables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció",
"iptables_unavailable": "No podeu modificar les iptables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció",
"log_corrupted_md_file": "El fitxer de metadades yaml associat amb els registres està malmès: « {md_file} »\nError: {error}",
"log_corrupted_md_file": "El fitxer de metadades YAML associat amb els registres està malmès: « {md_file} »\nError: {error}",
"log_category_404": "La categoria de registres « {category} » no existeix",
"log_link_to_log": "El registre complet d'aquesta operació: «<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>»",
"log_help_to_get_log": "Per veure el registre de l'operació « {desc} », utilitzeu l'ordre «yunohost log display {name} »",
"log_link_to_failed_log": "L'operació « {dec} » ha fallat! Per obtenir ajuda, <a href=\"#/tools/logs/{name}\">proveïu el registre complete de l'operació clicant aquí</a>",
"log_help_to_get_failed_log": "L'operació « {dec} » ha fallat! Per obtenir ajuda, compartiu el registre complete de l'operació utilitzant l'ordre «yunohost log display {name} --share»",
"log_link_to_failed_log": "No s'ha pogut completar l'operació « {desc} ». Per obtenir ajuda, <a href=\"#/tools/logs/{name}\">proveïu el registre complete de l'operació clicant aquí</a>",
"log_help_to_get_failed_log": "No s'ha pogut completar l'operació « {desc} ». Per obtenir ajuda, compartiu el registre complete de l'operació utilitzant l'ordre «yunohost log display {name} --share»",
"log_does_exists": "No hi ha cap registre per l'operació amb el nom«{log} », utilitzeu «yunohost log list» per veure tots els registre d'operació disponibles",
"log_operation_unit_unclosed_properly": "L'operació no s'ha tancat de forma correcta",
"log_app_addaccess": "Afegir accés a « {} »",
"log_app_removeaccess": "Suprimeix accés a « {} »",
"log_app_clearaccess": "Suprimeix tots els accessos a « {} »",
"log_app_fetchlist": "Afegeix una llista d'aplicacions",
"log_app_removelist": "Elimina una llista d'aplicacions",
"log_app_change_url": "Canvia l'URL de l'aplicació « {} »",
"log_app_install": "Instal·la l'aplicació « {} »",
"log_app_remove": "Elimina l'aplicació « {} »",
@ -263,139 +218,99 @@
"log_domain_remove": "Elimina el domini « {} » de la configuració del sistema",
"log_dyndns_subscribe": "Subscriure's a un subdomini YunoHost « {} »",
"log_dyndns_update": "Actualitza la IP associada al subdomini YunoHost « {} »",
"log_letsencrypt_cert_install": "Instal·la el certificat Let's Encrypt al domini « {} »",
"log_letsencrypt_cert_install": "Instal·la un certificat Let's Encrypt al domini « {} »",
"log_selfsigned_cert_install": "Instal·la el certificat autosignat al domini « {} »",
"log_letsencrypt_cert_renew": "Renova el certificat Let's Encrypt de « {} »",
"log_service_enable": "Activa el servei « {} »",
"log_regen_conf": "Regenera la configuració del sistema « {} »",
"log_user_create": "Afegeix l'usuari « {} »",
"log_user_delete": "Elimina l'usuari « {} »",
"log_user_update": "Actualitza la informació de l'usuari « {} »",
"log_tools_maindomain": "Fes de « {} » el domini principal",
"log_tools_migrations_migrate_forward": "Migrar",
"log_tools_migrations_migrate_backward": "Migrar endarrera",
"log_domain_main_domain": "Fes de « {} » el domini principal",
"log_tools_migrations_migrate_forward": "Executa les migracions",
"log_tools_postinstall": "Fer la post instal·lació del servidor YunoHost",
"log_tools_upgrade": "Actualitza els paquets del sistema",
"log_tools_shutdown": "Apaga el servidor",
"log_tools_reboot": "Reinicia el servidor",
"already_up_to_date": "No hi ha res a fer! Tot està al dia!",
"already_up_to_date": "No hi ha res a fer. Tot està actualitzat.",
"dpkg_lock_not_available": "No es pot utilitzar aquesta comanda en aquest moment ja que sembla que un altre programa està utilitzant el lock de dpkg (el gestor de paquets del sistema)",
"global_settings_setting_security_postfix_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor Postfix. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)",
"ldap_init_failed_to_create_admin": "La inicialització de LDAP no ha pogut crear l'usuari admin",
"ldap_initialized": "S'ha iniciat LDAP",
"license_undefined": "indefinit",
"mail_alias_remove_failed": "No s'han pogut eliminar els alias del correu «{mail:s}»",
"mail_domain_unknown": "Domini d'adreça de correu «{domain:s}» desconegut",
"mail_alias_remove_failed": "No s'han pogut eliminar els àlies del correu «{mail:s}»",
"mail_domain_unknown": "El domini «{domain:s}» de l'adreça de correu no és vàlid. Utilitzeu un domini administrat per aquest servidor.",
"mail_forward_remove_failed": "No s'han pogut eliminar el reenviament de correu «{mail:s}»",
"mailbox_used_space_dovecot_down": "S'ha d'engegar el servei de correu Dovecot per poder obtenir l'espai utilitzat per la bústia de correu",
"mail_unavailable": "Aquesta adreça de correu esta reservada i ha de ser atribuïda automàticament el primer usuari",
"maindomain_change_failed": "No s'ha pogut canviar el domini principal",
"maindomain_changed": "S'ha canviat el domini principal",
"migrate_tsig_end": "La migració cap a hmac-sha512 s'ha acabat",
"migrate_tsig_failed": "Ha fallat la migració del domini dyndns {domain} cap a hmac-sha512, anul·lant les modificacions. Error: {error_code} - {error}",
"migrate_tsig_start": "L'algoritme de generació de claus no es prou segur per a la signatura TSIG del domini «{domain}», començant la migració cap a un de més segur hmac-sha512",
"migrate_tsig_wait": "Esperar 3 minuts per a que el servidor dyndns tingui en compte la nova clau…",
"mailbox_used_space_dovecot_down": "S'ha d'engegar el servei de correu Dovecot, per poder obtenir l'espai utilitzat per la bústia de correu",
"mail_unavailable": "Aquesta adreça de correu està reservada i ha de ser atribuïda automàticament el primer usuari",
"main_domain_change_failed": "No s'ha pogut canviar el domini principal",
"main_domain_changed": "S'ha canviat el domini principal",
"migrate_tsig_end": "La migració cap a HMAC-SHA-512 s'ha acabat",
"migrate_tsig_failed": "Ha fallat la migració del domini DynDNS «{domain}» cap a HMAC-SHA-512, anul·lant les modificacions. Error: {error_code}, {error}",
"migrate_tsig_start": "L'algoritme de generació de claus no es prou segur per a la signatura TSIG del domini «{domain}», començant la migració cap a un de més segur HMAC-SHA-512",
"migrate_tsig_wait": "Esperant tres minuts per a que el servidor DynDNS tingui en compte la nova clau…",
"migrate_tsig_wait_2": "2 minuts…",
"migrate_tsig_wait_3": "1 minut…",
"migrate_tsig_wait_4": "30 segons…",
"migrate_tsig_not_needed": "Sembla que no s'utilitza cap domini dyndns, no és necessari fer cap migració!",
"migrate_tsig_not_needed": "Sembla que no s'utilitza cap domini DynDNS, no és necessari fer cap migració.",
"migration_description_0001_change_cert_group_to_sslcert": "Canvia els permisos del grup dels certificats de «metronome»a «ssl-cert»",
"migration_description_0002_migrate_to_tsig_sha256": "Millora la seguretat de dyndns TSIG utilitzant SHA512 en lloc de MD5",
"migration_description_0002_migrate_to_tsig_sha256": "Millora la seguretat de DynDNS TSIG utilitzant SHA-512 en lloc de MD5",
"migration_description_0003_migrate_to_stretch": "Actualització del sistema a Debian Stretch i YunoHost 3.0",
"migration_description_0004_php5_to_php7_pools": "Tornar a configurar els pools PHP per utilitzar PHP 7 en lloc de PHP 5",
"migration_description_0005_postgresql_9p4_to_9p6": "Migració de les bases de dades de postgresql 9.4 a 9.6",
"migration_description_0005_postgresql_9p4_to_9p6": "Migració de les bases de dades de PostgreSQL 9.4 a 9.6",
"migration_description_0006_sync_admin_and_root_passwords": "Sincronitzar les contrasenyes admin i root",
"migration_description_0007_ssh_conf_managed_by_yunohost_step1": "La configuració SSH serà gestionada per YunoHost (pas 1, automàtic)",
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "La configuració SSH serà gestionada per YunoHost (pas 2, manual)",
"migration_description_0009_decouple_regenconf_from_services": "Desvincula el mecanisme regen-conf dels serveis",
"migration_description_0010_migrate_to_apps_json": "Elimina la appslists (desfasat) i utilitza la nova llista unificada «apps.json» en el seu lloc",
"migration_0003_backward_impossible": "La migració Stretch no és reversible.",
"migration_description_0010_migrate_to_apps_json": "Elimina els catàlegs d'aplicacions obsolets i utilitza la nova llista unificada «apps.json» en el seu lloc (obsolet, substituït per la migració 13)",
"migration_0003_start": "Ha començat la migració a Stretch. Els registres estaran disponibles a {logfile}.",
"migration_0003_patching_sources_list": "Modificant el fitxer sources.lists…",
"migration_0003_main_upgrade": "Començant l'actualització principal…",
"migration_0003_fail2ban_upgrade": "Començant l'actualització de fail2ban…",
"migration_0003_fail2ban_upgrade": "Començant l'actualització de Fail2Ban…",
"migration_0003_restoring_origin_nginx_conf": "El fitxer /etc/nginx/nginx.conf ha estat editat. La migració el tornarà al seu estat original... El fitxer anterior estarà disponible com a {backup_dest}.",
"migration_0003_yunohost_upgrade": "Començant l'actualització del paquet yunohost... La migració acabarà, però l'actualització actual es farà just després. Després de completar aquesta operació, pot ser que us hagueu de tornar a connectar a la web d'administració.",
"migration_0003_yunohost_upgrade": "Començant l'actualització del paquet YunoHost... La migració acabarà, però l'actualització actual es farà just després. Després de completar aquesta operació, pot ser que us hagueu de tornar a connectar a la web d'administració.",
"migration_0003_not_jessie": "La distribució Debian actual no és Jessie!",
"migration_0003_system_not_fully_up_to_date": "El vostre sistema no està completament actualitzat. S'ha de fer una actualització normal abans de fer la migració a Stretch.",
"migration_0003_still_on_jessie_after_main_upgrade": "Hi ha hagut un problema durant l'actualització principal: el sistema encara està amb Jessie!? Per investigar el problema, mireu el registres a {log}:s…",
"migration_0003_general_warning": "Tingueu en compte que la migració és una operació delicada. Tot i que l'equip de YunoHost a fet els possibles per revisar-la i provar-la, la migració pot provocar errors en parts del sistema o aplicacions.\n\nPer tant, recomanem:\n - Fer una còpia de seguretat de les dades o aplicacions importants. Més informació a https://yunohost.org/backup;\n - Sigueu pacient un cop llençada la migració: en funció de la connexió a internet i el maquinari, pot trigar fins a unes hores per actualitzar-ho tot.\n\nD'altra banda, el port per SMTP, utilitzat per clients de correu externs (com Thunderbird o K9-Mail) ha canviat de 465 (SSL/TLS) a 587 (STARTTLS). L'antic port 465 serà tancat automàticament i el nou port 587 serà obert en el tallafocs. Tots els usuaris *hauran* d'adaptar la configuració dels clients de correu en acord amb aquests canvis!",
"migration_0003_problematic_apps_warning": "Tingueu en compte que s'han detectat les aplicacions, possiblement, problemàtiques següents. Sembla que aquestes no s'han instal·lat des d'una applist o que no estan marcades com a «working». Per conseqüent, no podem garantir que segueixin funcionant després de l'actualització: {problematic_apps}",
"migration_0003_still_on_jessie_after_main_upgrade": "Hi ha hagut un problema durant l'actualització principal: El sistema encara està amb Jessie? Per investigar el problema, mireu el registres a {log}:s…",
"migration_0003_general_warning": "Tingueu en compte que la migració és una operació delicada. L'equip de YunoHost a fet els possibles per revisar-la i provar-la, però la migració pot provocar errors en parts del sistema o aplicacions.\n\nPer tant, es recomana:\n - Fer una còpia de seguretat de les dades o aplicacions importants. Més informació a https://yunohost.org/backup;\n - Sigueu pacient un cop llençada la migració: en funció de la connexió a internet i el maquinari, pot trigar fins a unes hores per actualitzar-ho tot.\n\nD'altra banda, el port per SMTP, utilitzat per clients de correu externs (com Thunderbird o K9-Mail) ha canviat de 465 (SSL/TLS) a 587 (STARTTLS). L'antic port (465) serà tancat automàticament, i el nou port (587) serà obert en el tallafocs. Tots els usuaris *hauran* d'adaptar la configuració dels clients de correu en acord amb aquests canvis.",
"migration_0003_problematic_apps_warning": "Tingueu en compte que s'han detectat les aplicacions, possiblement, problemàtiques següents. Sembla que aquestes no s'han instal·lat des d'un catàleg d'aplicacions, o que no estan marcades com a «working». Per conseqüent, no podem garantir que segueixin funcionant després de l'actualització: {problematic_apps}",
"migration_0003_modified_files": "Tingueu en compte que s'han detectat els següents fitxers que han estat modificats manualment i podrien sobreescriure's al final de l'actualització: {manually_modified_files}",
"migration_0005_postgresql_94_not_installed": "Postgresql no està instal·lat en el sistema. No hi ha res per fer!",
"migration_0005_postgresql_96_not_installed": "S'ha trobat Postgresql 9.4 instal·lat, però no Postgresql 9.6!? Alguna cosa estranya a passat en el sistema :( …",
"migration_0005_not_enough_space": "No hi ha prou espai disponible en {path} per fer la migració en aquest moment :(.",
"migration_0006_disclaimer": "YunoHost esperar que les contrasenyes admin i root estiguin sincronitzades. Fent aquesta migració, la contrasenya root serà reemplaçada per la contrasenya admin.",
"migration_0007_cancelled": "YunoHost no ha pogut millorar la gestió de la configuració SSH.",
"migration_0005_postgresql_94_not_installed": "PostgreSQL no està instal·lat en el sistema. No hi ha res per fer.",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 està instal·lat, però no PostgreSQL 9.6? Alguna cosa estranya a passat en el sistema :( …",
"migration_0005_not_enough_space": "Creu espai disponible en {path} per executar la migració.",
"migration_0006_disclaimer": "YunoHost esperar que les contrasenyes de admin i root estiguin sincronitzades. Aquesta migració canvia la contrasenya root per la contrasenya admin.",
"migration_0007_cancelled": "No s'ha pogut millorar la gestió de la configuració SSH.",
"migration_0007_cannot_restart": "No es pot reiniciar SSH després d'haver intentat cancel·lar la migració numero 6.",
"migration_0008_general_disclaimer": "Per millorar la seguretat del servidor, es recomana que sigui YunoHost qui gestioni la configuració SSH. La configuració SSH actual és diferent a la configuració recomanada. Si deixeu que YunoHost ho reconfiguri, la manera de connectar-se al servidor mitjançant SSH canviarà de la següent manera:",
"migration_0008_port": " - la connexió es farà utilitzant el port 22 en lloc del port SSH personalitzat actual. Es pot reconfigurar;",
"migration_0008_root": " - no es podrà connectar com a root a través de SSH. S'haurà d'utilitzar l'usuari admin per fer-ho;",
"migration_0008_dsa": " - es desactivarà la clau DSA. Per tant, es podria haver d'invalidar un missatge esgarrifós del client SSH, i tornar a verificar l'empremta digital del servidor;",
"migration_0008_warning": "Si heu entès els avisos i accepteu que YunoHost sobreescrigui la configuració actual, comenceu la migració. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.",
"migration_0008_no_warning": "No s'han detectat riscs importants per sobreescriure la configuració SSH, però no es pot estar del tot segur ;)! Si accepteu que YunoHost sobreescrigui la configuració actual, comenceu la migració. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.",
"migration_0009_not_needed": "Sembla que ja s'ha fet aquesta migració? Ometent.",
"migrations_backward": "Migració cap enrere.",
"migrations_bad_value_for_target": "Nombre invàlid pel paràmetre target, els nombres de migració disponibles són 0 o {}",
"migrations_cant_reach_migration_file": "No s'ha pogut accedir als fitxers de migració al camí %s",
"migrations_current_target": "La migració objectiu és {}",
"migrations_error_failed_to_load_migration": "ERROR: no s'ha pogut carregar la migració {number} {name}",
"migrations_forward": "Migració endavant",
"migrations_list_conflict_pending_done": "No es pot utilitzar --previous i --done al mateix temps.",
"migrations_loading_migration": "Carregant la migració {number} {name}…",
"migrations_migration_has_failed": "La migració {number} {name} ha fallat amb l'excepció {exception}, cancel·lant",
"migration_0008_port": "• La connexió es farà utilitzant el port 22 en lloc del port SSH personalitzat actual. Es pot reconfigurar;",
"migration_0008_root": "• No es podrà connectar com a root a través de SSH. S'haurà d'utilitzar l'usuari admin per fer-ho;",
"migration_0008_dsa": "• Es desactivarà la clau DSA. Per tant, es podria haver d'invalidar un missatge esgarrifós del client SSH, i tornar a verificar l'empremta digital del servidor;",
"migration_0008_warning": "Si heu entès els avisos i voleu que YunoHost sobreescrigui la configuració actual, comenceu la migració. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.",
"migration_0008_no_warning": "Hauria de ser segur sobreescriure la configuració SSH, però no es pot estar del tot segur! Executetu la migració per sobreescriure-la. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.",
"migration_0009_not_needed": "Sembla que ja s'ha fet aquesta migració… (?) Ometent.",
"migrations_cant_reach_migration_file": "No s'ha pogut accedir als fitxers de migració al camí «%s»",
"migrations_list_conflict_pending_done": "No es pot utilitzar «--previous» i «--done» al mateix temps.",
"migrations_loading_migration": "Carregant la migració {id}…",
"migrations_migration_has_failed": "La migració {id} ha fallat, cancel·lant. Error: {exception}",
"migrations_no_migrations_to_run": "No hi ha cap migració a fer",
"migrations_show_currently_running_migration": "Fent la migració {number} {name}…",
"migrations_show_last_migration": "L'última migració feta és {}",
"migrations_skip_migration": "Saltant migració {number} {name}…",
"migrations_success": "S'ha completat la migració {number} {name} amb èxit!",
"migrations_to_be_ran_manually": "La migració {number} {name} s'ha de fer manualment. Aneu a Eines > Migracions a la interfície admin, o executeu «yunohost tools migrations migrate».",
"migrations_need_to_accept_disclaimer": "Per fer la migració {number} {name}, heu d'acceptar aquesta clàusula de no responsabilitat:\n---\n{disclaimer}\n---\nSi accepteu fer la migració, torneu a executar l'ordre amb l'opció --accept-disclaimer.",
"monitor_disabled": "El monitoratge del servidor ha estat desactivat",
"monitor_enabled": "El monitoratge del servidor ha estat activat",
"monitor_glances_con_failed": "No s'ha pogut connectar al servidor Glances",
"monitor_not_enabled": "El monitoratge del servidor no està activat",
"monitor_period_invalid": "Període de temps invàlid",
"monitor_stats_file_not_found": "No s'ha pogut trobar el fitxer d'estadístiques",
"monitor_stats_no_update": "No hi ha dades de monitoratge per actualitzar",
"monitor_stats_period_unavailable": "No s'han trobat estadístiques per aquest període",
"mountpoint_unknown": "Punt de muntatge desconegut",
"mysql_db_creation_failed": "No s'ha pogut crear la base de dades MySQL",
"mysql_db_init_failed": "No s'ha pogut inicialitzar la base de dades MySQL",
"mysql_db_initialized": "S'ha inicialitzat la base de dades MySQL",
"network_check_mx_ko": "El registre DNS MX no està configurat",
"network_check_smtp_ko": "El tràfic de correu sortint (SMTP port 25) sembla que està bloquejat per la xarxa",
"network_check_smtp_ok": "El tràfic de correu sortint (SMTP port 25) no està bloquejat",
"new_domain_required": "S'ha d'especificar un nou domini principal",
"no_appslist_found": "No s'ha trobat cap llista d'aplicacions",
"migrations_skip_migration": "Saltant migració {id}…",
"migrations_to_be_ran_manually": "La migració {id} s'ha de fer manualment. Aneu a Eines → Migracions a la interfície admin, o executeu «yunohost tools migrations migrate».",
"migrations_need_to_accept_disclaimer": "Per fer la migració {id}, heu d'acceptar aquesta clàusula de no responsabilitat:\n---\n{disclaimer}\n---\nSi accepteu fer la migració, torneu a executar l'ordre amb l'opció «--accept-disclaimer».",
"no_internet_connection": "El servidor no està connectat a Internet",
"no_ipv6_connectivity": "La connectivitat IPv6 no està disponible",
"no_restore_script": "No hi ha cap script de restauració per l'aplicació «{app:s}»",
"not_enough_disk_space": "No hi ha prou espai en «{path:s}»",
"package_not_installed": "El paquet «{pkgname}» no està instal·lat",
"package_unexpected_error": "Hi ha hagut un error inesperat processant el paquet «{pkgname}»",
"package_unknown": "Paquet desconegut «{pkgname}»",
"packages_upgrade_critical_later": "Els paquets crítics ({packages:s}) seran actualitzats més tard",
"packages_upgrade_failed": "No s'han pogut actualitzar tots els paquets",
"path_removal_failed": "No s'ha pogut eliminar el camí {:s}",
"pattern_backup_archive_name": "Ha de ser un nom d'arxiu vàlid amb un màxim de 30 caràcters, compost per caràcters alfanumèrics i -_. exclusivament",
"pattern_domain": "Ha de ser un nom de domini vàlid (ex.: el-meu-domini.cat)",
"pattern_email": "Ha de ser una adreça de correu vàlida (ex.: algu@domini.cat)",
"pattern_firstname": "Ha de ser un nom vàlid",
"pattern_lastname": "Ha de ser un cognom vàlid",
"pattern_listname": "Ha d'estar compost per caràcters alfanumèrics i guió baix exclusivament",
"pattern_mailbox_quota": "Ha de ser una mida amb el sufix b/k/M/G/T o 0 per desactivar la quota",
"pattern_mailbox_quota": "Ha de ser una mida amb el sufix b/k/M/G/T o 0 per no tenir quota",
"pattern_password": "Ha de tenir un mínim de 3 caràcters",
"pattern_port": "Ha de ser un número de port vàlid (i.e. 0-65535)",
"pattern_port_or_range": "Ha de ser un número de port vàlid (i.e. 0-65535) o un interval de ports (ex. 100:200)",
"pattern_positive_number": "Ha de ser un nombre positiu",
"pattern_username": "Ha d'estar compost per caràcters alfanumèrics en minúscula i guió baix exclusivament",
"pattern_password_app": "Les contrasenyes no haurien de tenir els següents caràcters: {forbidden_chars}",
"pattern_password_app": "Les contrasenyes no poden de tenir els següents caràcters: {forbidden_chars}",
"port_already_closed": "El port {port:d} ja està tancat per les connexions {ip_version:s}",
"port_already_opened": "El port {port:d} ja està obert per les connexions {ip_version:s}",
"port_available": "El port {port:d} està disponible",
"port_unavailable": "El port {port:d} no està disponible",
"recommend_to_add_first_user": "La post instal·lació s'ha acabat, però YunoHost necessita com a mínim un usuari per funcionar correctament, hauríeu d'afegir un usuari executant «yunohost user create $username» o amb la interfície d'administració.",
"regenconf_file_backed_up": "S'ha guardat una còpia de seguretat del fitxer de configuració «{conf}» a «{backup}»",
"regenconf_file_copy_failed": "No s'ha pogut copiar el nou fitxer de configuració «{new}» a «{conf}»",
"regenconf_file_kept_back": "S'espera que el fitxer de configuració «{conf}» sigui suprimit per regen-conf (categoria {category}) però s'ha mantingut.",
@ -406,26 +321,24 @@
"regenconf_file_updated": "El fitxer de configuració «{conf}» ha estat actualitzat",
"regenconf_now_managed_by_yunohost": "El fitxer de configuració «{conf}» serà gestionat per YunoHost a partir d'ara (categoria {category}).",
"regenconf_up_to_date": "La configuració ja està al dia per la categoria «{category}»",
"regenconf_updated": "La configuració ha estat actualitzada per la categoria «{category}»",
"regenconf_updated": "S'ha actualitzat la configuració per la categoria «{category}»",
"regenconf_would_be_updated": "La configuració hagués estat actualitzada per la categoria «{category}»",
"regenconf_dry_pending_applying": "Verificació de la configuració pendent que s'hauria d'haver aplicat per la categoria «{category}»…",
"regenconf_failed": "No s'ha pogut regenerar la configuració per la/les categoria/es : {categories}",
"regenconf_pending_applying": "Aplicació de la configuració pendent per la categoria «{category}»…",
"restore_action_required": "S'ha d'especificar quelcom a restaurar",
"restore_already_installed_app": "Ja hi ha una aplicació instal·lada amb l'id «{app:s}»",
"restore_already_installed_app": "Una aplicació amb la ID «{app:s}» ja està instal·lada",
"restore_app_failed": "No s'ha pogut restaurar l'aplicació «{app:s}»",
"restore_cleaning_failed": "No s'ha pogut netejar el directori temporal de restauració",
"restore_complete": "Restauració completada",
"restore_confirm_yunohost_installed": "Esteu segur de voler restaurar un sistema ja instal·lat? [{answers:s}]",
"restore_extracting": "Extracció dels fitxers necessaris de l'arxiu…",
"restore_failed": "No s'ha pogut restaurar el sistema",
"restore_hook_unavailable": "L'script de restauració «{part:s}» no està disponible en el sistema i tampoc és en l'arxiu",
"restore_may_be_not_enough_disk_space": "Sembla que no hi ha prou espai disponible en el disc (espai lliure: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)",
"restore_mounting_archive": "Muntatge de l'arxiu a «{path:s}»",
"restore_not_enough_disk_space": "No hi ha prou espai disponible en el disc (espai lliure: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)",
"restore_hook_unavailable": "El script de restauració «{part:s}» no està disponible en el sistema i tampoc és en l'arxiu",
"restore_may_be_not_enough_disk_space": "Sembla que no hi ha prou espai disponible en el sistema (lliure: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)",
"restore_not_enough_disk_space": "No hi ha prou espai disponible (espai: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)",
"restore_nothings_done": "No s'ha restaurat res",
"restore_removing_tmp_dir_failed": "No s'ha pogut eliminar un directori temporal antic",
"restore_running_app_script": "Execució de l'script de restauració de l'aplicació «{app:s}»…",
"restore_running_app_script": "Restaurant l'aplicació «{app:s}»…",
"restore_running_hooks": "Execució dels hooks de restauració…",
"restore_system_part_failed": "No s'ha pogut restaurar la part «{part:s}» del sistema",
"root_password_desynchronized": "S'ha canviat la contrasenya d'administració, però YunoHost no ha pogut propagar-ho cap a la contrasenya root!",
@ -436,32 +349,29 @@
"server_reboot_confirm": "Es reiniciarà el servidor immediatament, n'esteu segur? [{answers:s}]",
"service_add_failed": "No s'ha pogut afegir el servei «{service:s}»",
"service_added": "S'ha afegit el servei «{service:s}»",
"service_already_started": "Ja s'ha iniciat el servei «{service:s}»",
"service_already_started": "El servei «{service:s}» ja està funcionant",
"service_already_stopped": "Ja s'ha aturat el servei «{service:s}»",
"service_cmd_exec_failed": "No s'ha pogut executar l'ordre «{command:s}»",
"service_description_avahi-daemon": "permet accedir al servidor via yunohost.local en la xarxa local",
"service_description_dnsmasq": "gestiona la resolució del nom de domini (DNS)",
"service_description_dovecot": "permet als clients de correu accedir/recuperar correus (via IMAP i POP3)",
"service_description_fail2ban": "protegeix contra els atacs de força bruta i a altres atacs provinents d'Internet",
"service_description_glances": "monitora la informació del sistema en el servidor",
"service_description_metronome": "gestiona els comptes de missatgeria instantània XMPP",
"service_description_mysql": "guarda les dades de les aplicacions (base de dades SQL)",
"service_description_nginx": "serveix o permet l'accés a totes les pàgines web allotjades en el servidor",
"service_description_nslcd": "gestiona les connexions shell dels usuaris YunoHost",
"service_description_php7.0-fpm": "executa les aplicacions escrites en PHP amb nginx",
"service_description_postfix": "utilitzat per enviar i rebre correus",
"service_description_redis-server": "una base de dades especialitzada per l'accés ràpid a dades, files d'espera i comunicació entre programes",
"service_description_rmilter": "verifica diferents paràmetres en els correus",
"service_description_rspamd": "filtra el correu brossa, i altres funcionalitats relacionades al correu",
"service_description_slapd": "guarda el usuaris, dominis i informació relacionada",
"service_description_ssh": "permet la connexió remota al servidor via terminal (protocol SSH)",
"service_description_yunohost-api": "gestiona les interaccions entre la interfície web de YunoHost i el sistema",
"service_description_yunohost-firewall": "gestiona els ports de connexió oberts i tancats als serveis",
"service_disable_failed": "No s'han pogut deshabilitar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_disabled": "S'ha deshabilitat el servei {service:s}",
"service_enable_failed": "No s'ha pogut activar el servei «{service:s}»\n\nRegistres recents: {log:s}",
"service_enabled": "S'ha activat el servei {service:s}",
"service_no_log": "No hi ha cap registre pel servei «{service:s}»",
"service_description_avahi-daemon": "Permet accedir al servidor via «yunohost.local» en la xarxa local",
"service_description_dnsmasq": "Gestiona la resolució del nom de domini (DNS)",
"service_description_dovecot": "Permet als clients de correu accedir/recuperar correus (via IMAP i POP3)",
"service_description_fail2ban": "Protegeix contra els atacs de força bruta i a altres atacs provinents d'Internet",
"service_description_metronome": "Gestiona els comptes de missatgeria instantània XMPP",
"service_description_mysql": "Guarda les dades de les aplicacions (base de dades SQL)",
"service_description_nginx": "Serveix o permet l'accés a totes les pàgines web allotjades en el servidor",
"service_description_nslcd": "Gestiona les connexions shell dels usuaris YunoHost",
"service_description_php7.0-fpm": "Executa les aplicacions escrites en PHP amb NGINX",
"service_description_postfix": "Utilitzat per enviar i rebre correus",
"service_description_redis-server": "Una base de dades especialitzada per l'accés ràpid a dades, files d'espera i comunicació entre programes",
"service_description_rspamd": "Filtra el correu brossa, i altres funcionalitats relacionades amb el correu",
"service_description_slapd": "Guarda el usuaris, dominis i informació relacionada",
"service_description_ssh": "Permet la connexió remota al servidor via terminal (protocol SSH)",
"service_description_yunohost-api": "Gestiona les interaccions entre la interfície web de YunoHost i el sistema",
"service_description_yunohost-firewall": "Gestiona els ports de connexió oberts i tancats als serveis",
"service_disable_failed": "No s'han pogut fer que el servei «{service:s}» no comenci a l'arrancada.\n\nRegistres recents: {logs:s}",
"service_disabled": "El servei «{service:s}» ja no començarà al arrancar el sistema.",
"service_enable_failed": "No s'ha pogut fer que el servei «{service:s}» comenci automàticament a l'arrancada.\n\nRegistres recents: {logs:s}",
"service_enabled": "El servei «{service:s}» començarà automàticament durant l'arrancada del sistema.",
"service_regen_conf_is_deprecated": "«yunohost service regen-conf» està desfasat! Utilitzeu «yunohost tools regen-conf» en el seu lloc.",
"service_remove_failed": "No s'ha pogut eliminar el servei «{service:s}»",
"service_removed": "S'ha eliminat el servei «{service:s}»",
@ -473,114 +383,218 @@
"service_reloaded_or_restarted": "S'ha tornat a carregar o s'ha reiniciat el servei «{service:s}»",
"service_start_failed": "No s'ha pogut iniciar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_started": "S'ha iniciat el servei «{service:s}»",
"service_status_failed": "No s'ha pogut determinar l'estat del servei «{service:s}»",
"service_stop_failed": "No s'ha pogut aturar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_stopped": "S'ha aturat el servei «{service:s}»",
"service_unknown": "Servei «{service:s}» desconegut",
"ssowat_conf_generated": "S'ha generat la configuració SSOwat",
"ssowat_conf_updated": "S'ha actualitzat la configuració SSOwat",
"ssowat_persistent_conf_read_error": "Error en llegir la configuració persistent de SSOwat: {error:s}. Modifiqueu el fitxer /etc/ssowat/conf.json.persistent per arreglar la sintaxi JSON",
"ssowat_persistent_conf_write_error": "Error guardant la configuració persistent de SSOwat: {error:s}. Modifiqueu el fitxer /etc/ssowat/conf.json.persistent per arreglar la sintaxi JSON",
"system_upgraded": "S'ha actualitzat el sistema",
"system_username_exists": "El nom d'usuari ja existeix en els usuaris de sistema",
"this_action_broke_dpkg": "Aquesta acció a trencat dpkg/apt (els gestors de paquets del sistema)… Podeu intentar resoldre el problema connectant-vos amb SSH i executant «sudo dpkg --configure -a».",
"tools_upgrade_at_least_one": "Especifiqueu --apps O --system",
"system_username_exists": "El nom d'usuari ja existeix en la llista d'usuaris de sistema",
"this_action_broke_dpkg": "Aquesta acció a trencat dpkg/APT (els gestors de paquets del sistema)… Podeu intentar resoldre el problema connectant-vos amb SSH i executant «sudo dpkg --configure -a».",
"tools_upgrade_at_least_one": "Especifiqueu «--apps», o «--system»",
"tools_upgrade_cant_both": "No es poden actualitzar tant el sistema com les aplicacions al mateix temps",
"tools_upgrade_cant_hold_critical_packages": "No es poden mantenir els paquets crítics…",
"tools_upgrade_cant_unhold_critical_packages": "No es poden deixar de mantenir els paquets crítics…",
"tools_upgrade_regular_packages": "Actualitzant els paquets «normals» (no relacionats amb YunoHost)…",
"tools_upgrade_regular_packages_failed": "No s'han pogut actualitzar els paquets següents: {packages_list}",
"tools_upgrade_special_packages": "Actualitzant els paquets «especials» (relacionats amb YunoHost)…",
"tools_upgrade_special_packages_explanation": "Aquesta acció s'acabarà, però l'actualització especial continuarà en segon pla. No comenceu cap altra acció al servidor en els pròxims ~10 minuts (depèn de la velocitat del maquinari). Un cop acabat, pot ser que us hagueu de tornar a connectar a la interfície d'administració. Els registres de l'actualització estaran disponibles a Eines > Registres (a la interfície d'administració) o amb «yunohost log list» (a la línia d'ordres).",
"tools_upgrade_special_packages_completed": "Actualització dels paquets YunoHost acabada!\nPremeu [Enter] per tornar a la línia d'ordres",
"tools_upgrade_special_packages_explanation": "Aquesta actualització especial continuarà en segon pla. No comenceu cap altra acció al servidor en els pròxims ~10 minuts (depèn de la velocitat del maquinari). Després d'això, pot ser que us hagueu de tornar a connectar a la interfície d'administració. Els registres de l'actualització estaran disponibles a Eines → Registres (a la interfície d'administració) o utilitzant «yunohost log list» (des de la línia d'ordres).",
"tools_upgrade_special_packages_completed": "Actualització dels paquets YunoHost acabada.\nPremeu [Enter] per tornar a la línia d'ordres",
"unbackup_app": "L'aplicació «{app:s}» no serà guardada",
"unexpected_error": "Hi ha hagut un error inesperat: {error}",
"unit_unknown": "Unitat desconeguda «{unit:s}»",
"unlimit": "Sense quota",
"unrestore_app": "L'aplicació «{app:s} no serà restaurada",
"update_apt_cache_failed": "No s'ha pogut actualitzar la memòria cau d'APT (el gestor de paquets de Debian). Aquí teniu les línies de sources.list que poden ajudar-vos a identificar les línies problemàtiques:\n{sourceslist}",
"update_apt_cache_failed": "No s'ha pogut actualitzar la memòria cau d'APT (el gestor de paquets de Debian). Aquí teniu les línies de sources.list, que poden ajudar-vos a identificar les línies problemàtiques:\n{sourceslist}",
"update_apt_cache_warning": "Hi ha hagut errors al actualitzar la memòria cau d'APT (el gestor de paquets de Debian). Aquí teniu les línies de sources.list que poden ajudar-vos a identificar les línies problemàtiques:\n{sourceslist}",
"updating_apt_cache": "Obtenció de les actualitzacions disponibles per als paquets del sistema…",
"updating_app_lists": "Obtenció de les actualitzacions disponibles per a les aplicacions…",
"upgrade_complete": "Actualització acabada",
"upgrading_packages": "Actualitzant els paquets…",
"upnp_dev_not_found": "No s'ha trobat cap dispositiu UPnP",
"upnp_disabled": "S'ha desactivat UPnP",
"upnp_enabled": "S'ha activat UPnP",
"upnp_port_open_failed": "No s'han pogut obrir els ports UPnP",
"upnp_port_open_failed": "No s'ha pogut obrir el port UPnP",
"user_created": "S'ha creat l'usuari",
"user_creation_failed": "No s'ha pogut crear l'usuari",
"user_creation_failed": "No s'ha pogut crear l'usuari {user}: {error}",
"user_deleted": "S'ha suprimit l'usuari",
"user_deletion_failed": "No s'ha pogut suprimir l'usuari",
"user_home_creation_failed": "No s'ha pogut crear la carpeta personal («home») de l'usuari",
"user_info_failed": "No s'ha pogut obtenir la informació de l'usuari",
"user_deletion_failed": "No s'ha pogut suprimir l'usuari {user}: {error}",
"user_home_creation_failed": "No s'ha pogut crear la carpeta personal «home» per l'usuari",
"user_unknown": "Usuari desconegut: {user:s}",
"user_update_failed": "No s'ha pogut actualitzar l'usuari",
"user_updated": "S'ha actualitzat l'usuari",
"user_update_failed": "No s'ha pogut actualitzar l'usuari {user}: {error}",
"user_updated": "S'ha canviat la informació de l'usuari",
"users_available": "Usuaris disponibles:",
"yunohost_already_installed": "YunoHost ja està instal·lat",
"yunohost_ca_creation_failed": "No s'ha pogut crear l'autoritat de certificació",
"yunohost_ca_creation_success": "S'ha creat l'autoritat de certificació local.",
"yunohost_configured": "S'ha configurat YunoHost",
"yunohost_configured": "YunoHost està configurat",
"yunohost_installing": "Instal·lació de YunoHost…",
"yunohost_not_installed": "YunoHost no està instal·lat o no està instal·lat correctament. Executeu «yunohost tools postinstall»",
"apps_permission_not_found": "No s'ha trobat cap permís per les aplicacions instal·lades",
"apps_permission_restoration_failed": "Ha fallat el permís «{permission:s}» per la restauració de l'aplicació {app:s}",
"yunohost_not_installed": "YunoHost no està instal·lat correctament. Executeu «yunohost tools postinstall»",
"backup_permission": "Permís de còpia de seguretat per l'aplicació {app:s}",
"edit_group_not_allowed": "No teniu autorització per modificar el grup {group:s}",
"edit_permission_with_group_all_users_not_allowed": "No podeu modificar els permisos del grup «all_users», s'ha d'utlilitzar «yunohost user permission clear APP» o «yunohost user permission add APP -u USER».",
"error_when_removing_sftpuser_group": "Error intentant eliminar el gruo sftpusers",
"group_already_allowed": "El grup «{group:s}» ja té el permís «{permission:s}» activat per l'aplicació «{app:s}»",
"group_already_disallowed": "El grup «{group:s}» ja té els permisos «{permission:s}» desactivats per l'aplicació «{app:s}»",
"group_name_already_exist": "El grup {name:s} ja existeix",
"group_created": "S'ha creat el grup «{group}»",
"group_creation_failed": "No s'ha pogut crear el grup «{group}»",
"group_creation_failed": "No s'ha pogut crear el grup «{group}»: {error}",
"group_deleted": "S'ha eliminat el grup «{group}»",
"group_deletion_failed": "No s'ha pogut eliminar el grup «{group}»",
"group_deletion_not_allowed": "El grup {group:s} no es pot eliminar manualment.",
"group_info_failed": "Ha fallat la informació del grup",
"group_deletion_failed": "No s'ha pogut eliminar el grup «{group}»: {error}",
"group_unknown": "Grup {group:s} desconegut",
"group_updated": "S'ha actualitzat el grup «{group}»",
"group_update_failed": "No s'ha pogut actualitzat el grup «{group}»",
"log_permission_add": "Afegir el permís «{}» per l'aplicació «{}»",
"log_permission_remove": "Suprimir el permís «{}»",
"log_permission_update": "Actualitzar el permís «{}» per l'aplicació «{}»",
"log_user_group_add": "Afegir grup «{}»",
"group_update_failed": "No s'ha pogut actualitzat el grup «{group}»: {error}",
"log_user_group_delete": "Eliminar grup «{}»",
"log_user_group_update": "Actualitzar grup «{}»",
"log_user_permission_add": "Actualitzar el permís «{}»",
"log_user_permission_remove": "Actualitzar el permís «{}»",
"mailbox_disabled": "La bústia de correu està desactivada per als usuaris {user:s}",
"migration_description_0011_setup_group_permission": "Configurar el grup d'usuaris i els permisos per les aplicacions i els serveis",
"mailbox_disabled": "La bústia de correu està desactivada per al usuari {user:s}",
"migration_description_0011_setup_group_permission": "Configurar els grups d'usuaris i els permisos per les aplicacions i els serveis",
"migration_0011_backup_before_migration": "Creant una còpia de seguretat de la base de dades LDAP i la configuració de les aplicacions abans d'efectuar la migració.",
"migration_0011_can_not_backup_before_migration": "No s'ha pogut fer la còpia de seguretat abans de la migració. No s'ha pogut fer la migració. Error: {error:s}",
"migration_0011_can_not_backup_before_migration": "No s'ha pogut completar la còpia de seguretat abans de que la migració fallés. Error: {error:s}",
"migration_0011_create_group": "Creant un grup per a cada usuari…",
"migration_0011_done": "Migració completa. Ja podeu gestionar grups d'usuaris.",
"migration_0011_LDAP_config_dirty": "Sembla que heu modificat manualment la configuració LDAP. Per fer aquesta migració s'ha d'actualitzar la configuració LDAP.\nGuardeu la configuració actual, reinicieu la configuració original amb l'ordre «yunohost tools regen-conf -f» i torneu a intentar la migració",
"migration_0011_done": "Migració completada. Ja podeu gestionar grups d'usuaris.",
"migration_0011_LDAP_update_failed": "Ha fallat l'actualització de LDAP. Error: {error:s}",
"migration_0011_migrate_permission": "Fent la migració dels permisos de la configuració de les aplicacions a LDAP…",
"migration_0011_migration_failed_trying_to_rollback": "La migració ha fallat … s'intenta tornar el sistema a l'estat anterior.",
"migration_0011_migration_failed_trying_to_rollback": "No s'ha pogut fer la migració… s'intenta tornar el sistema a l'estat anterior.",
"migration_0011_rollback_success": "S'ha tornat el sistema a l'estat anterior.",
"migration_0011_update_LDAP_database": "Actualitzant la base de dades LDAP…",
"migration_0011_update_LDAP_schema": "Actualitzant l'esquema LDAP…",
"need_define_permission_before": "Heu de tornar a redefinir els permisos utilitzant «yunohost user permission add -u USER» abans d'eliminar un grup permès",
"permission_already_clear": "Ja s'ha donat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_already_exist": "El permís «{permission:s}» ja existeix per l'aplicació {app:s}",
"permission_created": "S'ha creat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_creation_failed": "La creació del permís ha fallat",
"permission_deleted": "S'ha eliminat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_deletion_failed": "L'eliminació del permís «{permission:s}» per l'aplicació {app:s} ha fallat",
"permission_not_found": "No s'ha trobat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_name_not_valid": "El nom del permís «{permission:s}» no és vàlid",
"permission_update_failed": "L'actualització del permís ha fallat",
"permission_generated": "S'ha actualitzat la base de dades del permís",
"permission_updated": "S'ha actualitzat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_already_exist": "El permís «{permission:s}» ja existeix",
"permission_created": "S'ha creat el permís «{permission:s}»",
"permission_creation_failed": "No s'ha pogut crear el permís «{permission}»: {error}",
"permission_deleted": "S'ha eliminat el permís «{permission:s}»",
"permission_deletion_failed": "No s'ha pogut eliminar el permís «{permission:s}»: {error}",
"permission_not_found": "No s'ha trobat el permís «{permission:s}»",
"permission_update_failed": "No s'ha pogut actualitzar el permís «{permission}»: {error}",
"permission_updated": "S'ha actualitzat el permís «{permission:s}»",
"permission_update_nothing_to_do": "No hi ha cap permís per actualitzar",
"remove_main_permission_not_allowed": "No es pot eliminar el permís principal",
"remove_user_of_group_not_allowed": "No es pot eliminar l'usuari {user:s} del grup {group:s}",
"system_groupname_exists": "El nom de grup ja existeix en el sistema de grups",
"tools_update_failed_to_app_fetchlist": "No s'ha pogut actualitzar la llista d'aplicacions de YunoHost a causa de: {error}",
"user_already_in_group": "L'usuari {user:s} ja és en el grup {group:s}",
"user_not_in_group": "L'usuari {user:s} no és en el grup {group:s}",
"migration_description_0012_postgresql_password_to_md5_authentication": "Força l'autenticació postgresql a fer servir md5 per a les connexions locals"
"migration_description_0012_postgresql_password_to_md5_authentication": "Força l'autenticació PostgreSQL a fer servir MD5 per a les connexions locals",
"app_full_domain_unavailable": "Aquesta aplicació ha de ser instal·lada en el seu propi domini, però ja hi ha altres aplicacions instal·lades en el domini «{domain}». Podeu utilitzar un subdomini dedicat a aquesta aplicació.",
"migrations_not_pending_cant_skip": "Aquestes migracions no estan pendents, així que no poden ser omeses: {ids}",
"app_action_broke_system": "Aquesta acció sembla haver trencat els següents serveis importants: {services}",
"log_user_group_create": "Crear grup «{}»",
"log_user_permission_update": "Actualitzar els accessos per al permís «{}»",
"log_user_permission_reset": "Restablir el permís «{}»",
"permission_already_disallowed": "El grup «{group}» ja té el permís «{permission}» desactivat",
"migrations_already_ran": "Aquestes migracions ja s'han fet: {ids}",
"migrations_dependencies_not_satisfied": "Executeu aquestes migracions: «{dependencies_id}», abans la migració {id}.",
"migrations_failed_to_load_migration": "No s'ha pogut carregar la migració {id}: {error}",
"migrations_exclusive_options": "«--auto», «--skip», i «--force-rerun» són opcions mútuament excloents.",
"migrations_must_provide_explicit_targets": "Heu de proporcionar objectius explícits al utilitzar «--skip» o «--force-rerun»",
"migrations_no_such_migration": "No hi ha cap migració anomenada «{id}»",
"migrations_pending_cant_rerun": "Aquestes migracions encara estan pendents, així que no es poden tornar a executar: {ids}",
"migrations_running_forward": "Executant la migració {id}…",
"migrations_success_forward": "Migració {id} completada",
"apps_already_up_to_date": "Ja estan actualitzades totes les aplicacions",
"dyndns_provider_unreachable": "No s'ha pogut connectar amb el proveïdor DynDNS {provider}: o el vostre YunoHost no està ben connectat a Internet o el servidor dynette està caigut.",
"operation_interrupted": "S'ha interromput manualment l'operació?",
"group_already_exist": "El grup {group} ja existeix",
"group_already_exist_on_system": "El grup {group} ja existeix en els grups del sistema",
"group_cannot_be_deleted": "El grup {group} no es pot eliminar manualment.",
"group_user_already_in_group": "L'usuari {user} ja està en el grup {group}",
"group_user_not_in_group": "L'usuari {user} no està en el grup {group}",
"log_permission_create": "Crear el permís «{}»",
"log_permission_delete": "Eliminar el permís «{}»",
"migration_0011_failed_to_remove_stale_object": "No s'ha pogut eliminar l'objecte obsolet {dn}: {error}",
"permission_already_allowed": "El grup «{group}» ja té el permís «{permission}» activat",
"permission_cannot_remove_main": "No es permet eliminar un permís principal",
"user_already_exists": "L'usuari «{user}» ja existeix",
"app_install_failed": "No s'ha pogut instal·lar {app}: {error}",
"app_install_script_failed": "Hi ha hagut un error en el script d'instal·lació de l'aplicació",
"group_cannot_edit_all_users": "El grup «all_users» no es pot editar manualment. És un grup especial destinat a contenir els usuaris registrats a YunoHost",
"group_cannot_edit_visitors": "El grup «visitors» no es pot editar manualment. És un grup especial que representa els visitants anònims",
"group_cannot_edit_primary_group": "El grup «{group}» no es pot editar manualment. És el grup principal destinat a contenir un usuari específic.",
"log_permission_url": "Actualització de la URL associada al permís «{}»",
"migration_0011_slapd_config_will_be_overwritten": "Sembla que heu modificat manualment la configuració de sldap. Per aquesta migració crítica, YunoHost ha de forçar l'actualització de la configuració sldap. Es farà una còpia de seguretat a {conf_backup_folder}.",
"permission_already_up_to_date": "No s'ha actualitzat el permís perquè la petició d'afegir/eliminar ja corresponent a l'estat actual.",
"permission_currently_allowed_for_all_users": "El permís ha el té el grup de tots els usuaris (all_users) a més d'altres grups. Segurament s'hauria de revocar el permís a «all_users» o eliminar els altres grups als que s'ha atribuït.",
"permission_require_account": "El permís {permission} només té sentit per als usuaris que tenen un compte, i per tant no es pot activar per als visitants.",
"app_remove_after_failed_install": "Eliminant l'aplicació després que hagi fallat la instal·lació…",
"diagnosis_basesystem_ynh_main_version": "El servidor funciona amb YunoHost {main_version} ({repo})",
"diagnosis_ram_low": "El sistema només té {available} ({available_percent}%) de memòria RAM disponibles d'un total de {total}. Aneu amb compte.",
"diagnosis_swap_none": "El sistema no té swap. Hauríeu de considerar afegir un mínim de {recommended} de swap per evitar situacions en les que el sistema es queda sense memòria.",
"diagnosis_regenconf_manually_modified": "El fitxer de configuració {file} ha estat modificat manualment.",
"diagnosis_security_vulnerable_to_meltdown_details": "Per arreglar-ho, hauríeu d'actualitzar i reiniciar el sistema per tal de carregar el nou nucli de linux (o contactar amb el proveïdor del servidor si no funciona). Vegeu https://meltdownattack.com/ per a més informació.",
"diagnosis_http_could_not_diagnose": "No s'ha pogut diagnosticar si el domini és accessible des de l'exterior.",
"diagnosis_http_could_not_diagnose_details": "Error: {error}",
"domain_cannot_remove_main_add_new_one": "No es pot eliminar «{domain:s}» ja que és el domini principal i únic domini, primer s'ha d'afegir un altre domini utilitzant «yunohost domain add <un-altre-domini.com>», i després fer-lo el domini principal amb «yunohost domain main-domain -n <un-altre-domini.com>» i després es pot eliminar el domini «{domain:s}» utilitzant «yunohost domain remove {domain:s}».",
"diagnosis_basesystem_host": "El servidor funciona amb Debian {debian_version}",
"diagnosis_basesystem_kernel": "El servidor funciona amb el nucli de Linux {kernel_version}",
"diagnosis_basesystem_ynh_single_version": "{package} versió: {version}({repo})",
"diagnosis_basesystem_ynh_inconsistent_versions": "Esteu utilitzant versions inconsistents dels paquets de YunoHost… probablement a causa d'una actualització fallida o parcial.",
"diagnosis_display_tip_web": "Podeu anar a la secció de Diagnòstics (en la pantalla principal) per veure els errors que s'han trobat.",
"diagnosis_failed_for_category": "Ha fallat el diagnòstic per la categoria «{category}»: {error}",
"diagnosis_display_tip_cli": "Podeu executar «yunohost diagnosis show --issues» per mostrar els errors que s'han trobat.",
"diagnosis_cache_still_valid": "(La memòria cau encara és vàlida pel diagnòstic de {category}. No es tornar a diagnosticar de moment!)",
"diagnosis_cant_run_because_of_dep": "No es pot fer el diagnòstic per {category} mentre hi ha problemes importants relacionats amb {dep}.",
"diagnosis_ignored_issues": "(+ {nb_ignored} problema(es) ignorat(s))",
"diagnosis_found_errors": "S'ha trobat problema(es) important(s) {errors} relacionats amb {category}!",
"diagnosis_found_errors_and_warnings": "S'ha trobat problema(es) important(s) {errors} (i avis(os) {warnings}) relacionats amb {category}!",
"diagnosis_found_warnings": "S'han trobat ítems {warnings} que es podrien millorar per {category}.",
"diagnosis_everything_ok": "Tot sembla correcte per {category}!",
"diagnosis_failed": "No s'han pogut obtenir els resultats del diagnòstic per la categoria «{category}»: {error}",
"diagnosis_ip_connected_ipv4": "El servidor està connectat a Internet amb IPv4!",
"diagnosis_ip_no_ipv4": "El servidor no té una IPv4 que funcioni.",
"diagnosis_ip_connected_ipv6": "El servidor està connectat a Internet amb IPv6!",
"diagnosis_ip_no_ipv6": "El servidor no té una IPv6 que funcioni.",
"diagnosis_ip_not_connected_at_all": "Sembla que el servidor no està connectat a internet!?",
"diagnosis_ip_dnsresolution_working": "La resolució de nom de domini està funcionant!",
"diagnosis_ip_broken_dnsresolution": "La resolució de nom de domini falla per algun motiu… Està el tallafocs bloquejant les peticions DNS?",
"diagnosis_ip_broken_resolvconf": "La resolució de nom de domini sembla caiguda en el servidor, podria estar relacionat amb el fet que /etc/resolv.conf no apunta cap a 127.0.0.1.",
"diagnosis_ip_weird_resolvconf": "La resolució DNS sembla estar funcionant, però aneu amb compte ja que esteu utilitzant un versió personalitzada de /etc/resolv.conf.",
"diagnosis_ip_weird_resolvconf_details": "En canvi, aquest fitxer hauria de ser un enllaç simbòlic cap a /etc/resolvconf/run/resolv.conf i que aquest apunti cap a 127.0.0.1 (dnsmasq). La configuració del «resolver» real s'hauria de fer a /etc/resolv.dnsmaq.conf.",
"diagnosis_dns_good_conf": "Bona configuració DNS pel domini {domain} (categoria {category})",
"diagnosis_dns_bad_conf": "Configuració DNS incorrecta o inexistent pel domini {domain} (categoria {category})",
"diagnosis_dns_missing_record": "Segons la configuració DNS recomanada, hauríeu d'afegir un registre DNS\ntipus: {type}\nnom: {name}\nvalor: {value}.",
"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_services_bad_status": "El servei {service} està {status} :(",
"diagnosis_diskusage_verylow": "El lloc d'emmagatzematge {mountpoint} (en l'aparell {device}) només té disponibles {free} ({free_percent}%). Hauríeu de considerar alliberar una mica d'espai.",
"diagnosis_diskusage_low": "El lloc d'emmagatzematge {mountpoint} (en l'aparell {device}) només té disponibles {free} ({free_percent}%). Aneu amb compte.",
"diagnosis_diskusage_ok": "El lloc d'emmagatzematge {mountpoint} (en l'aparell {device}) encara té {free} ({free_percent}%) lliures!",
"diagnosis_ram_verylow": "El sistema només té {available} ({available_percent}%) de memòria RAM disponibles! (d'un total de {total})",
"diagnosis_ram_ok": "El sistema encara té {available} ({available_percent}%) de memòria RAM disponibles d'un total de {total}.",
"diagnosis_swap_notsomuch": "El sistema només té {total} de swap. Hauríeu de considerar tenir un mínim de {recommended} per evitar situacions en les que el sistema es queda sense memòria.",
"diagnosis_swap_ok": "El sistema té {total} de swap!",
"diagnosis_regenconf_allgood": "Tots els fitxers de configuració estan en acord amb la configuració recomanada!",
"diagnosis_regenconf_manually_modified_details": "No hauria de ser cap problema sempre i quan sapigueu el que esteu fent ;) !",
"diagnosis_regenconf_manually_modified_debian": "El fitxer de configuració {file} ha estat modificat manualment respecte al fitxer per defecte de Debian.",
"diagnosis_regenconf_manually_modified_debian_details": "No hauria de ser cap problema, però ho haureu de vigilar...",
"diagnosis_security_all_good": "No s'ha trobat cap vulnerabilitat de seguretat crítica.",
"diagnosis_security_vulnerable_to_meltdown": "Sembla que el sistema és vulnerable a la vulnerabilitat de seguretat crítica Meltdown",
"diagnosis_description_basesystem": "Sistema de base",
"diagnosis_description_ip": "Connectivitat a Internet",
"diagnosis_description_dnsrecords": "Registres DNS",
"diagnosis_description_services": "Verificació de l'estat dels serveis",
"diagnosis_description_systemresources": "Recursos del sistema",
"diagnosis_description_ports": "Exposició dels ports",
"diagnosis_description_regenconf": "Configuració del sistema",
"diagnosis_description_security": "Verificacions de seguretat",
"diagnosis_ports_could_not_diagnose": "No s'ha pogut diagnosticar si els ports són accessibles des de l'exterior.",
"diagnosis_ports_could_not_diagnose_details": "Error: {error}",
"diagnosis_ports_unreachable": "El port {port} no és accessible des de l'exterior.",
"diagnosis_ports_ok": "El port {port} és accessible des de l'exterior.",
"diagnosis_http_ok": "El domini {domain} és accessible per mitjà de HTTP des de fora de la xarxa local.",
"diagnosis_http_unreachable": "Sembla que el domini {domain} no és accessible a través de HTTP des de fora de la xarxa local.",
"diagnosis_unknown_categories": "Les següents categories són desconegudes: {categories}",
"apps_catalog_init_success": "S'ha iniciat el sistema de catàleg d'aplicacions!",
"apps_catalog_updating": "S'està actualitzant el catàleg d'aplicacions…",
"apps_catalog_failed_to_download": "No s'ha pogut descarregar el catàleg d'aplicacions {apps_catalog}: {error}",
"apps_catalog_obsolete_cache": "La memòria cau del catàleg d'aplicacions és buida o obsoleta.",
"apps_catalog_update_success": "S'ha actualitzat el catàleg d'aplicacions!",
"diagnosis_mail_ougoing_port_25_ok": "El port de sortida 25 no està bloquejat i els correus es poden enviar a altres servidors.",
"diagnosis_mail_outgoing_port_25_blocked": "Sembla que el port de sortida 25 està bloquejat. Hauríeu d'intentar desbloquejar-lo al panell de configuració del proveïdor d'accés a internet (o allotjador). Mentrestant, el servidor no podrà enviar correus a altres servidors.",
"diagnosis_description_mail": "Correu electrònic",
"migration_description_0013_futureproof_apps_catalog_system": "Migrar al nou sistema de catàleg d'aplicacions resistent al pas del temps",
"app_upgrade_script_failed": "Hi ha hagut un error en el script d'actualització de l'aplicació",
"diagnosis_services_bad_status_tip": "Podeu intentar reiniciar el servei, i si no funciona, podeu mirar els registres del servei utilitzant «yunohost service log {service}» o a través de «Serveis» a la secció de la pàgina web d'administració.",
"diagnosis_ports_forwarding_tip": "Per arreglar aquest problema, segurament s'ha de configurar el reenviament de ports en el router tal i com s'explica a https://yunohost.org/isp_box_config",
"diagnosis_http_bad_status_code": "El sistema de diagnòstic no ha pogut connectar amb el servidor. Podria ser que una altra màquina hagi contestat en lloc del servidor. S'hauria de comprovar que el reenviament del port 80 sigui correcte, que la configuració NGINX està actualitzada i que el reverse-proxy no està interferint.",
"diagnosis_no_cache": "Encara no hi ha memòria cau pel diagnòstic de la categoria «{category}»",
"diagnosis_http_timeout": "S'ha exhaurit el temps d'esperar intentant connectar amb el servidor des de l'exterior. Sembla que no s'hi pot accedir. S'hauria de comprovar que el reenviament del port 80 és correcte, que NGINX funciona, i que el tallafocs no està interferint.",
"diagnosis_http_connection_error": "Error de connexió: no s'ha pogut connectar amb el domini demanat, segurament és inaccessible.",
"yunohost_postinstall_end_tip": "S'ha completat la post-instal·lació. Per acabar la configuració, considereu:\n - afegir un primer usuari a través de la secció «Usuaris» a la pàgina web d'administració (o emprant «yunohost user create <username>» a la línia d'ordres);\n - diagnosticar possibles problemes a través de la secció «Diagnòstics» a la pàgina web d'administració (o emprant «yunohost diagnosis run» a la línia d'ordres);\n - llegir les seccions «Finalizing your setup» i «Getting to know Yunohost» a la documentació per administradors: https://yunohost.org/admindoc.",
"migration_description_0014_remove_app_status_json": "Eliminar els fitxers d'aplicació status.json heretats",
"diagnosis_services_running": "El servei {service} s'està executant!",
"diagnosis_services_conf_broken": "La configuració pel servei {service} està trencada!",
"diagnosis_ports_needed_by": "És necessari exposar aquest port per a les funcions {category} (servei {service})",
"global_settings_setting_pop3_enabled": "Activa el protocol POP3 per al servidor de correu",
"log_app_action_run": "Executa l'acció de l'aplicació «{}»",
"log_app_config_show_panel": "Mostra el taulell de configuració de l'aplicació «{}»",
"log_app_config_apply": "Afegeix la configuració a l'aplicació «{}»",
"diagnosis_never_ran_yet": "Sembla que el servidor s'ha configurat recentment i encara no hi cap informe de diagnòstic per mostrar. S'ha d'executar un diagnòstic complet primer, ja sigui des de la pàgina web d'administració o utilitzant la comanda «yunohost diagnosis run» al terminal.",
"diagnosis_description_web": "Web",
"diagnosis_basesystem_hardware_board": "El model de la targeta del servidor és {model}",
"diagnosis_basesystem_hardware": "L'arquitectura del maquinari del servidor és {virt} {arch}",
"group_already_exist_on_system_but_removing_it": "El grup {group} ja existeix en els grups del sistema, però YunoHost l'eliminarà…"
}

View file

@ -4,72 +4,52 @@
"admin_password_change_failed": "Passwort kann nicht geändert werden",
"admin_password_changed": "Das Administrator-Kennwort wurde geändert",
"app_already_installed": "{app:s} ist schon installiert",
"app_argument_choice_invalid": "Verwende einen der folgenden Werte {choices:s}",
"app_argument_invalid": "Wähle einen gültigen Wert für das Argument '{name: s}': {error: s}",
"app_argument_choice_invalid": "Wähle einen der folgenden Werte '{choices:s}' für das Argument '{name:s}'",
"app_argument_invalid": "Wähle einen gültigen Wert für das Argument '{name:s}': {error:s}",
"app_argument_required": "Argument '{name:s}' wird benötigt",
"app_extraction_failed": "Installationsdateien konnten nicht entpackt werden",
"app_id_invalid": "Falsche App-ID",
"app_install_files_invalid": "Diese Dateien können nicht installiert werden",
"app_location_already_used": "Die App ({app}) ist bereits hier ({path}) installiert",
"app_location_install_failed": "Die App kann dort nicht installiert werden, da ein Konflikt mit der App '{other_app}' besteht, die bereits in '{other_path}' installiert ist",
"app_manifest_invalid": "Mit dem App-Manifest stimmt etwas nicht: {error}",
"app_no_upgrade": "Alle Apps sind bereits aktuell",
"app_not_installed": "Die App {app:s} konnte nicht in der Liste installierter Apps gefunden werden: {all_apps}",
"app_recent_version_required": "Für {:s} benötigt eine aktuellere Version von moulinette",
"app_removed": "{app:s} wurde entfernt",
"app_sources_fetch_failed": "Quelldateien konnten nicht abgerufen werden, ist die URL korrekt?",
"app_unknown": "Unbekannte App",
"app_upgrade_failed": "{app:s} konnte nicht aktualisiert werden",
"app_upgraded": "{app:s} wurde erfolgreich aktualisiert",
"appslist_fetched": "Appliste {appslist:s} wurde erfolgreich heruntergelanden",
"appslist_removed": "Appliste {appslist:s} wurde erfolgreich entfernt",
"appslist_retrieve_error": "Entfernte Appliste {appslist:s} kann nicht empfangen werden: {error:s}",
"appslist_unknown": "Appliste {appslist:s} ist unbekannt.",
"ask_current_admin_password": "Derzeitiges Administrator-Kennwort",
"app_upgraded": "{app:s} aktualisiert",
"ask_email": "E-Mail-Adresse",
"ask_firstname": "Vorname",
"ask_lastname": "Nachname",
"ask_list_to_remove": "zu entfernende Liste",
"ask_main_domain": "Hauptdomain",
"ask_new_admin_password": "Neues Verwaltungskennwort",
"ask_password": "Passwort",
"backup_action_required": "Du musst etwas zum Speichern auswählen",
"backup_app_failed": "Konnte keine Sicherung für '{app:s}' erstellen",
"backup_app_failed": "Konnte keine Sicherung für die App '{app:s}' erstellen",
"backup_archive_app_not_found": "App '{app:s}' konnte in keiner Datensicherung gefunden werden",
"backup_archive_hook_not_exec": "Hook '{hook:s}' konnte für diese Datensicherung nicht ausgeführt werden",
"backup_archive_name_exists": "Datensicherung mit dem selben Namen existiert bereits",
"backup_archive_name_exists": "Datensicherung mit dem selben Namen existiert bereits.",
"backup_archive_name_unknown": "Unbekanntes lokale Datensicherung mit Namen '{name:s}' gefunden",
"backup_archive_open_failed": "Kann Sicherungsarchiv nicht öfnen",
"backup_cleaning_failed": "Temporäres Sicherungsverzeichnis konnte nicht geleert werden",
"backup_created": "Datensicherung komplett",
"backup_creating_archive": "Datensicherung wird erstellt…",
"backup_delete_error": "Pfad '{path:s}' konnte nicht gelöscht werden",
"backup_deleted": "Datensicherung wurde entfernt",
"backup_extracting_archive": "Entpacke Sicherungsarchiv...",
"backup_hook_unknown": "Datensicherungshook '{hook:s}' unbekannt",
"backup_invalid_archive": "Ungültige Datensicherung",
"backup_nothings_done": "Es gibt keine Änderungen zur Speicherung",
"backup_output_directory_forbidden": "Verbotenes Ausgabeverzeichnis. Datensicherung können nicht in /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var oder in Unterordnern von /home/yunohost.backup/archives erstellt werden",
"backup_output_directory_not_empty": "Ausgabeordner ist nicht leer",
"backup_deleted": "Backup wurde entfernt",
"backup_hook_unknown": "Der Datensicherungshook '{hook:s}' unbekannt",
"backup_invalid_archive": "Dies ist kein Backup-Archiv",
"backup_nothings_done": "Keine Änderungen zur Speicherung",
"backup_output_directory_forbidden": "Wähle ein anderes Ausgabeverzeichnis. Datensicherung können nicht in /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var oder in Unterordnern von /home/yunohost.backup/archives erstellt werden",
"backup_output_directory_not_empty": "Der gewählte Ausgabeordner sollte leer sein",
"backup_output_directory_required": "Für die Datensicherung muss ein Zielverzeichnis angegeben werden",
"backup_running_app_script": "Datensicherung für App '{app:s}' wurd durchgeführt...",
"backup_running_hooks": "Datensicherunghook wird ausgeführt…",
"custom_app_url_required": "Es muss eine URL angegeben werden, um deine benutzerdefinierte App {app:s} zu aktualisieren",
"custom_appslist_name_required": "Du musst einen Namen für deine benutzerdefinierte Appliste angeben",
"dnsmasq_isnt_installed": "dnsmasq scheint nicht installiert zu sein. Bitte führe 'apt-get remove bind9 && apt-get install dnsmasq' aus",
"domain_cert_gen_failed": "Zertifikat konnte nicht erzeugt werden",
"domain_created": "Die Domain wurde angelegt",
"domain_creation_failed": "Konnte Domain nicht erzeugen",
"domain_deleted": "Die Domain wurde gelöscht",
"domain_deletion_failed": "Konnte Domain nicht löschen",
"domain_dyndns_already_subscribed": "Du hast dich schon für eine DynDNS-Domain angemeldet",
"domain_dyndns_invalid": "Domain nicht mittels DynDNS nutzbar",
"domain_dyndns_root_unknown": "Unbekannte DynDNS Hauptdomain",
"domain_exists": "Die Domain existiert bereits",
"domain_uninstall_app_first": "Mindestens eine App ist noch für diese Domain installiert. Bitte deinstalliere zuerst die App, bevor du die Domain löschst",
"domain_unknown": "Unbekannte Domain",
"domain_zone_exists": "DNS Zonen Datei existiert bereits",
"domain_zone_not_found": "DNS Zonen Datei kann nicht für Domäne {:s} gefunden werden",
"done": "Erledigt",
"downloading": "Wird heruntergeladen…",
"dyndns_cron_installed": "DynDNS Cronjob erfolgreich angelegt",
@ -88,9 +68,6 @@
"firewall_reload_failed": "Die Firewall konnte nicht neu geladen werden",
"firewall_reloaded": "Die Firewall wurde neu geladen",
"firewall_rules_cmd_failed": "Einzelne Firewallregeln konnten nicht übernommen werden. Mehr Informationen sind im Log zu finden.",
"format_datetime_short": "%d/%m/%Y %I:%M %p",
"hook_argument_missing": "Fehlend Argument '{:s}'",
"hook_choice_invalid": "ungültige Wahl '{:s}'",
"hook_exec_failed": "Skriptausführung fehlgeschlagen: {path:s}",
"hook_exec_not_terminated": "Skriptausführung noch nicht beendet: {path:s}",
"hook_list_by_invalid": "Ungültiger Wert zur Anzeige von Hooks",
@ -100,53 +77,24 @@
"ip6tables_unavailable": "ip6tables kann nicht verwendet werden. Du befindest dich entweder in einem Container oder es wird nicht vom Kernel unterstützt",
"iptables_unavailable": "iptables kann nicht verwendet werden. Du befindest dich entweder in einem Container oder es wird nicht vom Kernel unterstützt",
"ldap_initialized": "LDAP wurde initialisiert",
"license_undefined": "Undeiniert",
"mail_alias_remove_failed": "E-Mail Alias '{mail:s}' konnte nicht entfernt werden",
"mail_domain_unknown": "Unbekannte Mail Domain '{domain:s}'",
"mail_forward_remove_failed": "Mailweiterleitung '{mail:s}' konnte nicht entfernt werden",
"maindomain_change_failed": "Die Hauptdomain konnte nicht geändert werden",
"maindomain_changed": "Die Hauptdomain wurde geändert",
"monitor_disabled": "Das Servermonitoring wurde erfolgreich deaktiviert",
"monitor_enabled": "Das Servermonitoring wurde aktiviert",
"monitor_glances_con_failed": "Verbindung mit Glances nicht möglich",
"monitor_not_enabled": "Servermonitoring ist nicht aktiviert",
"monitor_period_invalid": "Falscher Zeitraum",
"monitor_stats_file_not_found": "Statistikdatei nicht gefunden",
"monitor_stats_no_update": "Keine Monitoringstatistik zur Aktualisierung",
"monitor_stats_period_unavailable": "Keine Statistiken für den gewählten Zeitraum verfügbar",
"mountpoint_unknown": "Unbekannten Einhängepunkt",
"mysql_db_creation_failed": "MySQL Datenbankerzeugung fehlgeschlagen",
"mysql_db_init_failed": "MySQL Datenbankinitialisierung fehlgeschlagen",
"mysql_db_initialized": "Die MySQL Datenbank wurde initialisiert",
"network_check_mx_ko": "Es ist kein DNS MX Eintrag vorhanden",
"network_check_smtp_ko": "Ausgehender Mailverkehr (SMTP Port 25) scheint in deinem Netzwerk blockiert zu sein",
"network_check_smtp_ok": "Ausgehender Mailverkehr (SMTP Port 25) ist blockiert",
"new_domain_required": "Du musst eine neue Hauptdomain angeben",
"no_appslist_found": "Keine Appliste gefunden",
"main_domain_change_failed": "Die Hauptdomain konnte nicht geändert werden",
"main_domain_changed": "Die Hauptdomain wurde geändert",
"no_internet_connection": "Der Server ist nicht mit dem Internet verbunden",
"no_ipv6_connectivity": "Eine IPv6 Verbindung steht nicht zur Verfügung",
"no_restore_script": "Es konnte kein Wiederherstellungsskript für '{app:s}' gefunden werden",
"no_such_conf_file": "Datei {file:s}: konnte nicht kopiert werden, da diese nicht existiert",
"packages_no_upgrade": "Es müssen keine Pakete aktualisiert werden",
"packages_upgrade_critical_later": "Ein wichtiges Paket ({packages:s}) wird später aktualisiert",
"packages_upgrade_failed": "Es konnten nicht alle Pakete aktualisiert werden",
"path_removal_failed": "Pfad {:s} konnte nicht entfernt werden",
"pattern_backup_archive_name": "Ein gültiger Dateiname kann nur aus maximal 30 alphanumerischen sowie -_. Zeichen bestehen",
"pattern_domain": "Muss ein gültiger Domainname sein (z.B. meine-domain.org)",
"pattern_email": "Muss eine gültige E-Mail Adresse sein (z.B. someone@domain.org)",
"pattern_firstname": "Muss ein gültiger Vorname sein",
"pattern_lastname": "Muss ein gültiger Nachname sein",
"pattern_listname": "Kann nur Alphanumerische Zeichen oder Unterstriche enthalten",
"pattern_mailbox_quota": "Muss eine Größe inkl. b/k/M/G/T Suffix, oder 0 zum deaktivieren sein",
"pattern_password": "Muss mindestens drei Zeichen lang sein",
"pattern_port": "Es muss ein valider Port (zwischen 0 und 65535) angegeben werden",
"pattern_port_or_range": "Muss ein valider Port (z.B. 0-65535) oder ein Bereich (z.B. 100:200) sein",
"pattern_username": "Darf nur aus klein geschriebenen alphanumerischen Zeichen und Unterstrichen bestehen",
"port_already_closed": "Der Port {port:d} wurde bereits für {ip_version:s} Verbindungen geschlossen",
"port_already_opened": "Der Port {port:d} wird bereits von {ip_version:s} benutzt",
"port_available": "Der Port {port:d} ist verfügbar",
"port_unavailable": "Der Port {port:d} ist nicht verfügbar",
"restore_action_required": "Du musst etwas zum Wiederherstellen auswählen",
"restore_already_installed_app": "Es ist bereits eine App mit der ID '{app:s}' installiet",
"restore_app_failed": "App '{app:s}' konnte nicht wiederhergestellt werden",
"restore_cleaning_failed": "Das temporäre Wiederherstellungsverzeichnis konnte nicht geleert werden",
@ -157,38 +105,30 @@
"restore_nothings_done": "Es wurde nicht wiederhergestellt",
"restore_running_app_script": "Wiederherstellung wird ausfeührt für App '{app:s}'...",
"restore_running_hooks": "Wiederherstellung wird gestartet…",
"service_add_configuration": "Füge Konfigurationsdatei {file:s} hinzu",
"service_add_failed": "Der Dienst '{service:s}' kann nicht hinzugefügt werden",
"service_added": "Der Service '{service:s}' wurde erfolgreich hinzugefügt",
"service_already_started": "Der Dienst '{service:s}' läuft bereits",
"service_already_stopped": "Dienst '{service:s}' wurde bereits gestoppt",
"service_cmd_exec_failed": "Der Befehl '{command:s}' konnte nicht ausgeführt werden",
"service_configuration_conflict": "Die Datei {file:s} wurde zwischenzeitlich verändert. Bitte übernehme die Änderungen manuell oder nutze die Option --force (diese wird alle Änderungen überschreiben).",
"service_disable_failed": "Der Dienst '{service:s}' konnte nicht deaktiviert werden",
"service_disabled": "Der Dienst '{service:s}' wurde erfolgreich deaktiviert",
"service_enable_failed": "Der Dienst '{service:s}' konnte nicht aktiviert werden",
"service_enabled": "Der Dienst '{service:s}' wurde erfolgreich aktiviert",
"service_no_log": "Für den Dienst '{service:s}' kann kein Log angezeigt werden",
"service_remove_failed": "Der Dienst '{service:s}' konnte nicht entfernt werden",
"service_removed": "Der Dienst '{service:s}' wurde erfolgreich entfernt",
"service_start_failed": "Der Dienst '{service:s}' konnte nicht gestartet werden",
"service_started": "Der Dienst '{service:s}' wurde erfolgreich gestartet",
"service_status_failed": "Der Status von '{service:s}' kann nicht festgestellt werden",
"service_stop_failed": "Der Dienst '{service:s}' kann nicht gestoppt werden",
"service_stopped": "Der Dienst '{service:s}' wurde erfolgreich beendet",
"service_unknown": "Unbekannter Dienst '{service:s}'",
"services_configured": "Konfiguration erfolgreich erstellt",
"show_diff": "Es gibt folgende Änderungen:\n{diff:s}",
"ssowat_conf_generated": "Die Konfiguration von SSOwat war erfolgreich",
"ssowat_conf_updated": "Die persistente SSOwat Einstellung wurde aktualisiert",
"system_upgraded": "Das System wurde aktualisiert",
"system_username_exists": "Der Benutzername existiert bereits",
"unbackup_app": "App '{app:s}' konnte nicht gespeichert werden",
"unexpected_error": "Ein unerwarteter Fehler ist aufgetreten",
"unit_unknown": "Unbekannte Einheit '{unit:s}'",
"unlimit": "Kein Kontingent",
"unrestore_app": "App '{app:s}' kann nicht Wiederhergestellt werden",
"update_cache_failed": "Konnte APT cache nicht aktualisieren",
"updating_apt_cache": "Die Liste der verfügbaren Pakete wird aktualisiert…",
"upgrade_complete": "Upgrade vollständig",
"upgrading_packages": "Pakete werden aktualisiert…",
@ -201,7 +141,6 @@
"user_deleted": "Der Benutzer wurde entfernt",
"user_deletion_failed": "Nutzer konnte nicht gelöscht werden",
"user_home_creation_failed": "Benutzer Home konnte nicht erstellt werden",
"user_info_failed": "Nutzerinformationen können nicht angezeigt werden",
"user_unknown": "Unbekannter Benutzer: {user:s}",
"user_update_failed": "Benutzer kann nicht aktualisiert werden",
"user_updated": "Der Benutzer wurde aktualisiert",
@ -211,59 +150,33 @@
"yunohost_installing": "YunoHost wird installiert…",
"yunohost_not_installed": "YunoHost ist nicht oder unvollständig installiert worden. Bitte 'yunohost tools postinstall' ausführen",
"app_not_properly_removed": "{app:s} wurde nicht ordnungsgemäß entfernt",
"service_regenconf_failed": "Konnte die Konfiguration für folgende Dienste nicht neu erzeugen: {services}",
"not_enough_disk_space": "Zu wenig freier Speicherplatz unter '{path:s}' verfügbar",
"backup_creation_failed": "Erstellen des Backups fehlgeschlagen",
"service_conf_up_to_date": "Die Konfiguration für den Dienst '{service}' ist bereits aktuell",
"package_not_installed": "Das Paket '{pkgname}' ist nicht installiert",
"backup_creation_failed": "Konnte Backup-Archiv nicht erstellen",
"pattern_positive_number": "Muss eine positive Zahl sein",
"diagnosis_kernel_version_error": "Kann Kernelversion nicht abrufen: {error}",
"package_unexpected_error": "Ein unerwarteter Fehler trat bei der Verarbeitung des Pakets '{pkgname}' auf",
"app_incompatible": "Die Anwendung {app} ist nicht mit deiner YunoHost-Version kompatibel",
"app_not_correctly_installed": "{app:s} scheint nicht korrekt installiert zu sein",
"app_requirements_checking": "Überprüfe notwendige Pakete für {app}…",
"app_requirements_failed": "Anforderungen für {app} werden nicht erfüllt: {error}",
"app_requirements_unmeet": "Anforderungen für {app} werden nicht erfüllt, das Paket {pkgname} ({version}) muss {spec} sein",
"app_unsupported_remote_type": "Für die App wurde ein nicht unterstützer Steuerungstyp verwendet",
"backup_archive_broken_link": "Auf das Backup-Archiv konnte nicht zugegriffen werden (ungültiger Link zu {path:s})",
"diagnosis_debian_version_error": "Debian Version konnte nicht abgerufen werden: {error}",
"diagnosis_monitor_disk_error": "Festplatten können nicht aufgelistet werden: {error}",
"diagnosis_monitor_network_error": "Netzwerk kann nicht angezeigt werden: {error}",
"diagnosis_monitor_system_error": "System kann nicht angezeigt werden: {error}",
"diagnosis_no_apps": "Keine Anwendung ist installiert",
"domains_available": "Verfügbare Domains:",
"dyndns_key_not_found": "DNS-Schlüssel für die Domain wurde nicht gefunden",
"dyndns_no_domain_registered": "Es wurde keine Domain mit DynDNS registriert",
"ldap_init_failed_to_create_admin": "Die LDAP Initialisierung konnte keinen admin Benutzer erstellen",
"mailbox_used_space_dovecot_down": "Der Dovecot Mailbox Dienst muss gestartet sein, wenn du den von der Mailbox belegten Speicher angezeigen lassen willst",
"package_unknown": "Unbekanntes Paket '{pkgname}'",
"service_conf_file_backed_up": "Von der Konfigurationsdatei {conf} wurde ein Backup in {backup} erstellt",
"service_conf_file_copy_failed": "Die neue Konfigurationsdatei konnte von {new} nach {conf} nicht kopiert werden",
"service_conf_file_manually_modified": "Die Konfigurationsdatei {conf} wurde manuell verändert und wird nicht aktualisiert",
"service_conf_file_manually_removed": "Die Konfigurationsdatei {conf} wurde manuell entfern und wird nicht erstellt",
"service_conf_file_not_managed": "Die Konfigurationsdatei {conf} wurde noch nicht verwaltet und wird nicht aktualisiert",
"service_conf_file_remove_failed": "Die Konfigurationsdatei {conf} konnte nicht entfernt werden",
"service_conf_file_removed": "Die Konfigurationsdatei {conf} wurde entfernt",
"service_conf_file_updated": "Die Konfigurationsdatei {conf} wurde aktualisiert",
"service_conf_updated": "Die Konfigurationsdatei wurde für den Service {service} aktualisiert",
"service_conf_would_be_updated": "Die Konfigurationsdatei sollte für den Service {service} aktualisiert werden",
"ssowat_persistent_conf_read_error": "Ein Fehler ist aufgetreten, als die persistente SSOwat Konfiguration eingelesen wurde {error:s} Bearbeite die persistente Datei /etc/ssowat/conf.json , um die JSON syntax zu korregieren",
"ssowat_persistent_conf_write_error": "Ein Fehler ist aufgetreten, als die persistente SSOwat Konfiguration gespeichert wurde {error:s} Bearbeite die persistente Datei /etc/ssowat/conf.json , um die JSON syntax zu korregieren",
"certmanager_attempt_to_replace_valid_cert": "Du versuchst gerade eine richtiges und gültiges Zertifikat der Domain {domain:s} zu überschreiben! (Benutze --force , um diese Nachricht zu umgehen)",
"certmanager_domain_unknown": "Unbekannte Domain {domain:s}",
"certmanager_domain_cert_not_selfsigned": "Das Zertifikat der Domain {domain:s} is kein selbstsigniertes Zertifikat. Bist du dir sicher, dass du es ersetzen willst? (Benutze --force)",
"certmanager_certificate_fetching_or_enabling_failed": "Es scheint so als wäre die Aktivierung des Zertifikats für die Domain {domain:s} fehlgeschlagen...",
"certmanager_attempt_to_renew_nonLE_cert": "Das Zertifikat der Domain {domain:s} wurde nicht von Let's Encrypt ausgestellt. Es kann nicht automatisch erneuert werden!",
"certmanager_attempt_to_renew_valid_cert": "Das Zertifikat der Domain {domain:s} läuft in Kürze ab! Benutze --force um diese Nachricht zu umgehen",
"certmanager_attempt_to_renew_valid_cert": "Das Zertifikat der Domain {domain:s} läuft nicht in Kürze ab! (Benutze --force um diese Nachricht zu umgehen)",
"certmanager_domain_http_not_working": "Es scheint so, dass die Domain {domain:s} nicht über HTTP erreicht werden kann. Bitte überprüfe, ob deine DNS und nginx Konfiguration in Ordnung ist",
"certmanager_error_no_A_record": "Kein DNS 'A' Eintrag für die Domain {domain:s} gefunden. Dein Domainname muss auf diese Maschine weitergeleitet werden, um ein Let's Encrypt Zertifikat installieren zu können! (Wenn du weißt was du tust, kannst du --no-checks benutzen, um diese Überprüfung zu überspringen. )",
"certmanager_domain_dns_ip_differs_from_public_ip": "Der DNS 'A' Eintrag der Domain {domain:s} unterscheidet sich von dieser Server-IP. Wenn du gerade deinen A Eintrag verändert hast, warte bitte etwas, damit die Änderungen wirksam werden (du kannst die DNS Propagation mittels Website überprüfen) (Wenn du weißt was du tust, kannst du --no-checks benutzen, um diese Überprüfung zu überspringen. )",
"certmanager_domain_not_resolved_locally": "Die Domain {domain:s} konnte von innerhalb des Yunohost-Servers nicht aufgelöst werden. Das kann passieren, wenn du den DNS Eintrag vor Kurzem verändert hast. Falls dies der Fall ist, warte bitte ein paar Stunden, damit die Änderungen wirksam werden. Wenn der Fehler bestehen bleibt, ziehe in Betracht die Domain {domain:s} in /etc/hosts einzutragen. (Wenn du weißt was du tust, benutze --no-checks , um diese Nachricht zu umgehen. )",
"certmanager_cannot_read_cert": "Es ist ein Fehler aufgetreten, als es versucht wurde das aktuelle Zertifikat für die Domain {domain:s} zu öffnen (Datei: {file:s}), Grund: {reason:s}",
"certmanager_cert_install_success_selfsigned": "Ein selbstsigniertes Zertifikat für die Domain {domain:s} wurde erfolgreich installiert!",
"certmanager_cert_install_success": "Für die Domain {domain:s} wurde erfolgreich ein Let's Encrypt installiert!",
"certmanager_cert_renew_success": "Das Let's Encrypt Zertifikat für die Domain {domain:s} wurde erfolgreich erneuert!",
"certmanager_old_letsencrypt_app_detected": "\nYunohost hat erkannt, dass eine Version von 'letsencrypt' installiert ist, die mit den neuen, integrierten Zertifikatsmanagement-Features in Yunohost kollidieren. Wenn du die neuen Features nutzen willst, führe die folgenden Befehle aus:\n\n yunohost app remove letsencrypt\n yunohost domain cert-install\n\nAnm.: Diese Befehle werden die selbstsignierten und Let's Encrypt Zertifikate aller Domains neu installieren",
"certmanager_hit_rate_limit": "Es wurden innerhalb kurzer Zeit schon zu viele Zertifikate für die exakt gleiche Domain {domain:s} ausgestellt. Bitte versuche es später nochmal. Besuche https://letsencrypt.org/docs/rate-limits/ für mehr Informationen",
"certmanager_cert_signing_failed": "Signieren des neuen Zertifikats ist fehlgeschlagen",
"certmanager_no_cert_file": "Die Zertifikatsdatei für die Domain {domain:s} (Datei: {file:s}) konnte nicht gelesen werden",
@ -272,87 +185,134 @@
"certmanager_self_ca_conf_file_not_found": "Die Konfigurationsdatei der Zertifizierungsstelle für selbstsignierte Zertifikate wurde nicht gefunden (Datei {file:s})",
"certmanager_acme_not_configured_for_domain": "Das Zertifikat für die Domain {domain:s} scheint nicht richtig installiert zu sein. Bitte führe den Befehl cert-install für diese Domain nochmals aus.",
"certmanager_unable_to_parse_self_CA_name": "Der Name der Zertifizierungsstelle für selbstsignierte Zertifikate konnte nicht analysiert werden (Datei: {file:s})",
"app_package_need_update": "Es ist notwendig das Paket {app} zu aktualisieren, um Aktualisierungen für YunoHost zu erhalten",
"service_regenconf_dry_pending_applying": "Überprüfe ausstehende Konfigurationen, die für den Server {service} notwendig sind...",
"service_regenconf_pending_applying": "Überprüfe ausstehende Konfigurationen, die für den Server '{service}' notwendig sind...",
"certmanager_http_check_timeout": "Eine Zeitüberschreitung ist aufgetreten als der Server versuchte sich selbst über HTTP mit der öffentlichen IP (Domain {domain:s} mit der IP {ip:s}) zu erreichen. Möglicherweise ist dafür hairpinning oder eine falsch konfigurierte Firewall/Router deines Servers dafür verantwortlich.",
"certmanager_couldnt_fetch_intermediate_cert": "Eine Zeitüberschreitung ist aufgetreten als der Server versuchte die Teilzertifikate von Let's Encrypt zusammenzusetzen. Die Installation/Erneuerung des Zertifikats wurde abgebrochen - bitte versuche es später erneut.",
"appslist_retrieve_bad_format": "Die empfangene Datei der Appliste {appslist:s} ist ungültig",
"domain_hostname_failed": "Erstellen des neuen Hostnamens fehlgeschlagen",
"appslist_name_already_tracked": "Es gibt bereits eine registrierte App-Liste mit Namen {name:s}.",
"appslist_url_already_tracked": "Es gibt bereits eine registrierte Anwendungsliste mit dem URL {url:s}.",
"appslist_migrating": "Migriere Anwendungsliste {appslist:s} …",
"appslist_could_not_migrate": "Konnte Anwendungsliste {appslist:s} nicht migrieren. Konnte die URL nicht verarbeiten... Der alte Cron-Job wurde unter {bkp_file:s} beibehalten.",
"appslist_corrupted_json": "Konnte die Anwendungslisten. Es scheint, dass {filename:s} beschädigt ist.",
"yunohost_ca_creation_success": "Die lokale Zertifizierungs-Authorität wurde angelegt.",
"app_already_installed_cant_change_url": "Diese Application ist bereits installiert. Die URL kann durch diese Funktion nicht modifiziert werden. Überprüfe ob `app changeurl` verfügbar ist.",
"app_change_no_change_url_script": "Die Application {app_name:s} unterstützt das anpassen der URL noch nicht. Sie muss gegebenenfalls erweitert werden.",
"app_change_url_failed_nginx_reload": "NGINX konnte nicht neu gestartet werden. Hier ist der Output von 'nginx -t':\n{nginx_errors:s}",
"app_change_url_identical_domains": "Die alte und neue domain/url_path sind identisch: ('{domain:s} {path:s}'). Es gibt nichts zu tun.",
"app_already_up_to_date": "{app:s} ist schon aktuell",
"app_already_up_to_date": "{app:s} ist bereits aktuell",
"backup_abstract_method": "Diese Backup-Methode wird noch nicht unterstützt",
"backup_applying_method_tar": "Erstellen des Backup-tar Archives...",
"backup_applying_method_tar": "Erstellen des Backup-tar Archives",
"backup_applying_method_copy": "Kopiere alle Dateien ins Backup…",
"app_change_url_no_script": "Die Anwendung '{app_name:s}' unterstützt bisher keine URL-Modufikation. Vielleicht gibt es eine Aktualisierung.",
"app_location_unavailable": "Diese URL ist entweder nicht verfügbar oder steht in Konflikt mit den bereits installierten Apps:\n{apps: s}",
"app_change_url_no_script": "Die Anwendung '{app_name:s}' unterstützt bisher keine URL-Modifikation. Vielleicht sollte sie aktualisiert werden.",
"app_location_unavailable": "Diese URL ist nicht verfügbar oder wird von einer installierten Anwendung genutzt:\n{apps:s}",
"backup_applying_method_custom": "Rufe die benutzerdefinierte Backup-Methode '{method:s}' auf…",
"backup_archive_system_part_not_available": "Der System-Teil '{part:s}' ist in diesem Backup nicht enthalten",
"backup_archive_mount_failed": "Das Einbinden des Backup-Archives ist fehlgeschlagen",
"backup_archive_writing_error": "Die Dateien konnten nicht in der komprimierte Archiv-Backup hinzugefügt werden",
"backup_archive_writing_error": "Die Dateien '{source:s} (im Ordner '{dest:s}') konnten nicht in das komprimierte Archiv-Backup '{archive:s}' hinzugefügt werden",
"app_change_url_success": "{app:s} URL ist nun {domain:s}{path:s}",
"backup_applying_method_borg": "Sende alle Dateien zur Sicherung ins borg-backup repository…",
"invalid_url_format": "ungültiges URL Format",
"global_settings_bad_type_for_setting": "Falscher Typ für Einstellung {setting: s}. Empfangen: {receive_type: s}, aber erwartet: {expected_type: s}",
"global_settings_bad_choice_for_enum": "Falsche Wahl für die Einstellung {setting: s}. Habe '{choice: s}' erhalten, aber es stehen nur folgende Auswahlmöglichkeiten zur Verfügung: {available_choices: s}",
"file_does_not_exist": "Die Datei {path: s} existiert nicht.",
"global_settings_bad_type_for_setting": "Falscher Typ für Einstellung {setting:s}. Empfangen: {received_type:s}, aber erwartet: {expected_type:s}",
"global_settings_bad_choice_for_enum": "Falsche Wahl für die Einstellung {setting:s}. Habe '{choice:s}' erhalten, aber es stehen nur folgende Auswahlmöglichkeiten zur Verfügung: {available_choices:s}",
"file_does_not_exist": "Die Datei {path:s} existiert nicht.",
"experimental_feature": "Warnung: Diese Funktion ist experimentell und gilt nicht als stabil. Sie sollten sie nur verwenden, wenn Sie wissen, was Sie tun.",
"error_when_removing_sftpuser_group": "Fehler beim Versuch, die Gruppe sftpusers zu entfernen",
"edit_permission_with_group_all_users_not_allowed": "Sie dürfen die Berechtigung für die Gruppe \"all_users\" nicht bearbeiten. Verwenden Sie stattdessen \"yunohost user permission clear APP\" oder \"yunohost user permission add APP -u USER\".",
"edit_group_not_allowed": "Du bist nicht berechtigt zum Bearbeiten der Gruppe {group: s}",
"dyndns_domain_not_provided": "Der Dyndns-Anbieter {provider: s} kann die Domain(s) {domain: s} nicht bereitstellen.",
"dyndns_could_not_check_available": "Konnte nicht überprüfen, ob {domain: s} auf {provider: s} verfügbar ist.",
"dyndns_could_not_check_provide": "Konnte nicht überprüft, ob {provider: s} die Domain(s) {domain: s} bereitstellen kann.",
"domain_dyndns_dynette_is_unreachable": "YunoHost dynette kann nicht erreicht werden, entweder ist Ihr YunoHost nicht korrekt mit dem Internet verbunden oder der dynette-Server ist inaktiv. Fehler: {error}",
"dyndns_domain_not_provided": "Der DynDNS-Anbieter {provider:s} kann die Domain(s) {domain:s} nicht bereitstellen.",
"dyndns_could_not_check_available": "Konnte nicht überprüfen, ob {domain:s} auf {provider:s} verfügbar ist.",
"dyndns_could_not_check_provide": "Konnte nicht überprüft, ob {provider:s} die Domain(s) {domain:s} bereitstellen kann.",
"domain_dns_conf_is_just_a_recommendation": "Dieser Befehl zeigt Ihnen, was die * empfohlene * Konfiguration ist. Die DNS-Konfiguration wird NICHT für Sie eingerichtet. Es liegt in Ihrer Verantwortung, Ihre DNS-Zone in Ihrem Registrar gemäß dieser Empfehlung zu konfigurieren.",
"dpkg_lock_not_available": "Dieser Befehl kann momentan nicht ausgeführt werden, da anscheinend ein anderes Programm die Sperre von dpkg (dem Systempaket-Manager) verwendet",
"confirm_app_install_thirdparty": "WARNUNG! Das Installieren von Anwendungen von Drittanbietern kann die Integrität und Sicherheit Deines Systems beeinträchtigen. Du solltest es wahrscheinlich NICHT installieren, es sei denn, Du weisst, was Du tust. Bist du bereit, dieses Risiko einzugehen? [{answers: s}] ",
"confirm_app_install_danger": "WARNUNG! Diese Anwendung ist noch experimentell (wenn nicht ausdrücklich \"not working\"/\"funktioniert nicht\") und es ist wahrscheinlich, dass Dein System Schaden nimmt! Du solltest es wahrscheinlich NICHT installieren, es sei denn, Du weisst, was Du tust. Bist du bereit, dieses Risiko einzugehen? [{answers: s}] ",
"confirm_app_install_warning": "Warnung: Diese Anwendung funktioniert möglicherweise, ist jedoch nicht gut in YunoHost integriert. Einige Funktionen wie Single Sign-On und Backup / Restore sind möglicherweise nicht verfügbar. Trotzdem installieren? [{answers: s}] ",
"backup_with_no_restore_script_for_app": "App {app: s} hat kein Wiederherstellungsskript. Das Backup dieser App kann nicht automatisch wiederhergestellt werden.",
"backup_with_no_backup_script_for_app": "App {app: s} hat kein Sicherungsskript. Ignoriere es.",
"backup_unable_to_organize_files": "Dateien im Archiv können mit der schnellen Methode nicht organisiert werden",
"backup_system_part_failed": "Der Systemteil '{part: s}' kann nicht gesichert werden",
"backup_permission": "Sicherungsberechtigung für App {app: s}",
"backup_output_symlink_dir_broken": "Sie haben einen fehlerhaften Symlink anstelle Ihres Archivverzeichnisses '{path: s}'. Möglicherweise haben Sie ein spezielles Setup, um Ihre Daten auf einem anderen Dateisystem zu sichern. In diesem Fall haben Sie wahrscheinlich vergessen, Ihre Festplatte oder Ihren USB-Schlüssel erneut einzuhängen oder anzuschließen.",
"confirm_app_install_thirdparty": "WARNUNG! Das Installieren von Anwendungen von Drittanbietern kann die Integrität und Sicherheit Deines Systems beeinträchtigen. Du solltest es wahrscheinlich NICHT installieren, es sei denn, Du weisst, was Du tust. Bist du bereit, dieses Risiko einzugehen? [{answers:s}]",
"confirm_app_install_danger": "WARNUNG! Diese Anwendung ist noch experimentell (wenn nicht ausdrücklich \"not working\"/\"funktioniert nicht\") und es ist wahrscheinlich, dass Dein System Schaden nimmt! Du solltest es wahrscheinlich NICHT installieren, es sei denn, Du weisst, was Du tust. Bist du bereit, dieses Risiko einzugehen? [{answers:s}]",
"confirm_app_install_warning": "Warnung: Diese Anwendung funktioniert möglicherweise, ist jedoch nicht gut in YunoHost integriert. Einige Funktionen wie Single Sign-On und Backup / Restore sind möglicherweise nicht verfügbar. Trotzdem installieren? [{answers:s}] ",
"backup_with_no_restore_script_for_app": "Die App {app:s} hat kein Wiederherstellungsskript. Das Backup dieser App kann nicht automatisch wiederhergestellt werden.",
"backup_with_no_backup_script_for_app": "Die App {app:s} hat kein Sicherungsskript. Ignoriere es.",
"backup_unable_to_organize_files": "Dateien im Archiv konnten nicht mit der schnellen Methode organisiert werden",
"backup_system_part_failed": "Der Systemteil '{part:s}' konnte nicht gesichert werden",
"backup_permission": "Sicherungsberechtigung für App {app:s}",
"backup_output_symlink_dir_broken": "Ihr Archivverzeichnis '{path:s}' ist ein fehlerhafter Symlink. Vielleicht haben Sie vergessen, das Speichermedium, auf das er verweist, neu zu mounten oder einzustecken.",
"backup_mount_archive_for_restore": "Archiv für Wiederherstellung vorbereiten…",
"backup_method_tar_finished": "Sicherungs-Tar-Archiv erstellt",
"backup_method_custom_finished": "Benutzerdefinierte Sicherungsmethode '{method: s}' beendet",
"backup_method_tar_finished": "Tar-Backup-Archiv erstellt",
"backup_method_custom_finished": "Benutzerdefinierte Sicherungsmethode '{method:s}' beendet",
"backup_method_copy_finished": "Sicherungskopie beendet",
"backup_method_borg_finished": "Backup in Borg beendet",
"backup_custom_need_mount_error": "Bei der benutzerdefinierten Sicherungsmethode ist beim Arbeitsschritt \"Braucht ein Einhängen/Verbinden\" (need_mount) ein Fehler aufgetreten",
"backup_custom_mount_error": "Bei der benutzerdefinierten Sicherungsmethode ist beim Arbeitsschritt \"Einhängen/Verbinden\" ein Fehler aufgetreten",
"backup_custom_backup_error": "Bei der benutzerdefinierten Sicherungsmethode ist beim Arbeitsschritt \"Sicherung\" ein Fehler aufgetreten",
"backup_csv_creation_failed": "Die CSV-Datei, die für zukünftige Wiederherstellungsvorgänge erforderlich ist, kann nicht erstellt werden",
"backup_couldnt_bind": "{Src: s} konnte nicht an {dest: s} angebunden werden.",
"backup_csv_creation_failed": "Die zur Wiederherstellung erforderliche CSV-Datei kann nicht erstellt werden",
"backup_couldnt_bind": "{src:s} konnte nicht an {dest:s} angebunden werden.",
"backup_borg_not_implemented": "Die Borg-Sicherungsmethode ist noch nicht implementiert",
"backup_ask_for_copying_if_needed": "Einige Dateien konnten mit der Methode, die es vermeidet vorübergehend Speicherplatz auf dem System zu verschwenden, nicht gesichert werden. Zur Durchführung der Sicherung sollten vorübergehend {size: s} MB verwendet werden. Sind Sie einverstanden?",
"backup_actually_backuping": "Erstelle nun ein Backup-Archiv aus den gesammelten Dateien …",
"ask_path": "Pfad",
"backup_ask_for_copying_if_needed": "Möchten Sie die Sicherung mit {size:s} MB temporär durchführen? (Dieser Weg wird verwendet, da einige Dateien nicht mit einer effizienteren Methode vorbereitet werden konnten).",
"backup_actually_backuping": "Erstellt ein Backup-Archiv aus den gesammelten Dateien …",
"ask_new_path": "Neuer Pfad",
"ask_new_domain": "Neue Domain",
"apps_permission_restoration_failed": "Die Berechtigung '{permission: s}' für die Wiederherstellung der App {app: s} ist fehlgeschlagen",
"apps_permission_not_found": "Keine Berechtigung für die installierten Apps gefunden",
"app_upgrade_some_app_failed": "Einige Anwendungen können nicht aktualisiert werden",
"app_upgrade_app_name": "{App} wird jetzt aktualisiert…",
"app_upgrade_app_name": "{app} wird jetzt aktualisiert…",
"app_upgrade_several_apps": "Die folgenden Apps werden aktualisiert: {apps}",
"app_start_restore": "Anwendung {app} wird wiederhergestellt…",
"app_start_backup": "Sammeln von Dateien, die für {app} gesichert werden sollen…",
"app_start_remove": "Anwendung {app} wird entfernt…",
"app_start_install": "Anwendung {app} wird installiert…",
"app_not_upgraded": "Die App '{failed_app}' konnte nicht aktualisiert werden. Infolgedessen wurden die folgenden App-Upgrades abgebrochen: {apps}",
"app_make_default_location_already_used": "Die App \"{app}\" kann nicht als Standard für die Domain \"{domain}\" festgelegt werden. Sie wird bereits von der anderen App \"{other_app}\" verwendet",
"app_make_default_location_already_used": "Die App \"{app}\" kann nicht als Standard für die Domain \"{domain}\" festgelegt werden. Sie wird bereits von der App \"{other_app}\" verwendet",
"aborting": "Breche ab.",
"app_action_cannot_be_ran_because_required_services_down": "Diese App erfordert einige Dienste, die derzeit nicht verfügbar sind. Bevor Sie fortfahren, sollten Sie versuchen, die folgenden Dienste neu zu starten (und möglicherweise untersuchen, warum sie nicht verfügbar sind): {services}",
"app_action_cannot_be_ran_because_required_services_down": "Diese erforderlichen Dienste sollten zur Durchführung dieser Aktion laufen: {services}. Versuchen Sie, sie neu zu starten, um fortzufahren (und möglicherweise zu untersuchen, warum sie nicht verfügbar sind).",
"already_up_to_date": "Nichts zu tun. Alles ist bereits auf dem neusten Stand.",
"admin_password_too_long": "Bitte ein Passwort kürzer als 127 Zeichen wählen"
"admin_password_too_long": "Bitte ein Passwort kürzer als 127 Zeichen wählen",
"app_action_broke_system": "Diese Aktion scheint diese wichtigen Dienste unterbrochen zu haben: {services}",
"apps_already_up_to_date": "Alle Apps sind bereits aktuell",
"backup_copying_to_organize_the_archive": "Kopieren von {size:s} MB, um das Archiv zu organisieren",
"global_settings_setting_security_ssh_compatibility": "Kompatibilität vs. Sicherheitskompromiss für den SSH-Server. Beeinflusst die Chiffren (und andere sicherheitsrelevante Aspekte)",
"group_deleted": "Gruppe '{group}' gelöscht",
"group_deletion_failed": "Kann Gruppe '{group}' nicht löschen",
"dyndns_provider_unreachable": "Dyndns-Anbieter {provider} kann nicht erreicht werden: Entweder ist dein YunoHost nicht korrekt mit dem Internet verbunden oder der Dynette-Server ist ausgefallen.",
"group_created": "Gruppe '{group}' angelegt",
"group_creation_failed": "Kann Gruppe '{group}' nicht anlegen",
"group_unknown": "Die Gruppe '{group:s}' ist unbekannt",
"group_updated": "Gruppe '{group:s}' erneuert",
"group_update_failed": "Kann Gruppe '{group:s}' nicht anpassen",
"log_does_exists": "Es gibt kein Operationsprotokoll mit dem Namen'{log}', verwende'yunohost log list', um alle verfügbaren Operationsprotokolle anzuzeigen",
"log_operation_unit_unclosed_properly": "Die Operationseinheit wurde nicht richtig geschlossen",
"global_settings_setting_security_postfix_compatibility": "Kompatibilität vs. Sicherheitskompromiss für den Postfix-Server. Beeinflusst die Chiffren (und andere sicherheitsrelevante Aspekte)",
"log_category_404": "Die Log-Kategorie '{category}' existiert nicht",
"global_settings_unknown_type": "Unerwartete Situation, die Einstellung {setting:s} scheint den Typ {unknown_type:s} zu haben, ist aber kein vom System unterstützter Typ.",
"dpkg_is_broken": "Du kannst das gerade nicht tun, weil dpkg/APT (der Systempaketmanager) in einem defekten Zustand zu sein scheint.... Du kannst versuchen, dieses Problem zu lösen, indem du dich über SSH verbindest und `sudo dpkg --configure -a` ausführst.",
"global_settings_unknown_setting_from_settings_file": "Unbekannter Schlüssel in den Einstellungen: '{setting_key:s}', verwerfen und speichern in /etc/yunohost/settings-unknown.json",
"log_link_to_log": "Vollständiges Log dieser Operation: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
"global_settings_setting_example_bool": "Beispiel einer booleschen Option",
"log_help_to_get_log": "Um das Protokoll der Operation '{desc}' anzuzeigen, verwende den Befehl 'yunohost log display {name}'",
"global_settings_setting_security_nginx_compatibility": "Kompatibilität vs. Sicherheitskompromiss für den Webserver NGINX. Beeinflusst die Chiffren (und andere sicherheitsrelevante Aspekte)",
"backup_php5_to_php7_migration_may_fail": "Dein Archiv konnte nicht für PHP 7 konvertiert werden, Du kannst deine PHP-Anwendungen möglicherweise nicht wiederherstellen (Grund: {error:s})",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Erlaubt die Verwendung eines (veralteten) DSA-Hostkeys für die SSH-Daemon-Konfiguration",
"global_settings_setting_example_string": "Beispiel einer string Option",
"log_app_remove": "Entferne die Anwendung '{}'",
"global_settings_setting_example_int": "Beispiel einer int Option",
"global_settings_cant_open_settings": "Einstellungsdatei konnte nicht geöffnet werden, Grund: {reason:s}",
"global_settings_cant_write_settings": "Einstellungsdatei konnte nicht gespeichert werden, Grund: {reason:s}",
"log_app_install": "Installiere die Anwendung '{}'",
"global_settings_reset_success": "Frühere Einstellungen werden nun auf {path:s} gesichert",
"log_app_upgrade": "Upgrade der Anwendung '{}'",
"good_practices_about_admin_password": "Sie sind nun dabei, ein neues Administrationspasswort zu definieren. Das Passwort sollte mindestens 8 Zeichen lang sein - obwohl es sinnvoll ist, ein längeres Passwort (z.B. eine Passphrase) und/oder eine Variation von Zeichen (Groß- und Kleinschreibung, Ziffern und Sonderzeichen) zu verwenden.",
"log_corrupted_md_file": "Die mit Protokollen verknüpfte YAML-Metadatendatei ist beschädigt: '{md_file}\nFehler: {error}''",
"global_settings_cant_serialize_settings": "Einstellungsdaten konnten nicht serialisiert werden, Grund: {reason:s}",
"log_help_to_get_failed_log": "Der Vorgang'{desc}' konnte nicht abgeschlossen werden. Bitte teile das vollständige Protokoll dieser Operation mit dem Befehl 'yunohost log display {name} --share', um Hilfe zu erhalten",
"backup_no_uncompress_archive_dir": "Dieses unkomprimierte Archivverzeichnis gibt es nicht",
"log_app_change_url": "Ändere die URL der Anwendung '{}'",
"global_settings_setting_security_password_user_strength": "Stärke des Benutzerpassworts",
"good_practices_about_user_password": "Du bist nun dabei, ein neues Benutzerpasswort zu definieren. Das Passwort sollte mindestens 8 Zeichen lang sein - obwohl es ratsam ist, ein längeres Passwort (z.B. eine Passphrase) und/oder eine Variation von Zeichen (Groß- und Kleinschreibung, Ziffern und Sonderzeichen) zu verwenden.",
"global_settings_setting_example_enum": "Beispiel einer enum Option",
"log_link_to_failed_log": "Der Vorgang konnte nicht abgeschlossen werden '{desc}'. Bitte gib das vollständige Protokoll dieser Operation mit <a href=\"#/tools/logs/{name}\">Klicken Sie hier</a> an, um Hilfe zu erhalten",
"backup_cant_mount_uncompress_archive": "Das unkomprimierte Archiv konnte nicht als schreibgeschützt gemountet werden",
"backup_csv_addition_failed": "Es konnten keine Dateien zur Sicherung in die CSV-Datei hinzugefügt werden",
"global_settings_setting_security_password_admin_strength": "Stärke des Admin-Passworts",
"global_settings_key_doesnt_exists": "Der Schlüssel'{settings_key:s}' existiert nicht in den globalen Einstellungen, du kannst alle verfügbaren Schlüssel sehen, indem du 'yunohost settings list' ausführst",
"log_app_makedefault": "Mache '{}' zur Standard-Anwendung",
"hook_json_return_error": "Konnte die Rückkehr vom Einsprungpunkt {path:s} nicht lesen. Fehler: {msg:s}. Unformatierter Inhalt: {raw_content}",
"app_full_domain_unavailable": "Es tut uns leid, aber diese Anwendung erfordert die Installation auf einer eigenen Domain, aber einige andere Anwendungen sind bereits auf der Domäne'{domain}' installiert. Eine mögliche Lösung ist das Hinzufügen und Verwenden einer Subdomain, die dieser Anwendung zugeordnet ist.",
"app_install_failed": "Installation von {app} fehlgeschlagen: {error}",
"app_install_script_failed": "Im Installationsscript ist ein Fehler aufgetreten",
"app_remove_after_failed_install": "Entfernen der App nach fehlgeschlagener Installation…",
"app_upgrade_script_failed": "Es ist ein Fehler im App-Upgrade-Skript aufgetreten",
"diagnosis_basesystem_host": "Server läuft unter Debian {debian_version}.",
"diagnosis_basesystem_kernel": "Server läuft unter Linux-Kernel {kernel_version}",
"diagnosis_basesystem_ynh_single_version": "{package} Version: {version} ({repo})",
"diagnosis_basesystem_ynh_main_version": "Server läuft YunoHost {main_version} ({repo})",
"diagnosis_basesystem_ynh_inconsistent_versions": "Sie verwenden inkonsistente Versionen der YunoHost-Pakete... wahrscheinlich wegen eines fehlgeschlagenen oder teilweisen Upgrades.",
"diagnosis_display_tip_web": "Sie können den Abschnitt Diagnose (im Startbildschirm) aufrufen, um die gefundenen Probleme anzuzeigen.",
"apps_catalog_init_success": "Apps-Katalogsystem initialisiert!",
"apps_catalog_updating": "Aktualisierung des Applikationskatalogs...",
"apps_catalog_failed_to_download": "Der {apps_catalog} Apps-Katalog kann nicht heruntergeladen werden: {error}",
"apps_catalog_obsolete_cache": "Der Cache des Apps-Katalogs ist leer oder veraltet.",
"apps_catalog_update_success": "Der Apps-Katalog wurde aktualisiert!",
"password_too_simple_1": "Das Passwort muss mindestens 8 Zeichen lang sein",
"diagnosis_display_tip_cli": "Sie können 'yunohost diagnosis show --issues' ausführen, um die gefundenen Probleme anzuzeigen."
}

View file

@ -1 +1,3 @@
{}
{
"password_too_simple_1": "Ο κωδικός πρόσβασης πρέπει να έχει μήκος τουλάχιστον 8 χαρακτήρων"
}

View file

@ -3,76 +3,65 @@
"action_invalid": "Invalid action '{action:s}'",
"admin_password": "Administration password",
"admin_password_change_failed": "Cannot change password",
"admin_password_changed": "The administration password got changed",
"admin_password_changed": "The administration password was changed",
"admin_password_too_long": "Please choose a password shorter than 127 characters",
"already_up_to_date": "Nothing to do. Everything is already up-to-date.",
"app_action_cannot_be_ran_because_required_services_down": "This app requires some services which are currently down. Before continuing, you should try to restart the following services (and possibly investigate why they are down): {services}",
"app_action_broke_system": "This action seem to have broke these important services: {services}",
"app_action_cannot_be_ran_because_required_services_down": "These required services should be running to run this action: {services}. Try restarting them to continue (and possibly investigate why they are down).",
"app_action_broke_system": "This action seems to have broken these important services: {services}",
"app_already_installed": "{app:s} is already installed",
"app_already_installed_cant_change_url": "This app is already installed. The URL cannot be changed just by this function. Look into `app changeurl` if it's available.",
"app_already_installed_cant_change_url": "This app is already installed. The URL cannot be changed just by this function. Check in `app changeurl` if it's available.",
"app_already_up_to_date": "{app:s} is already up-to-date",
"app_argument_choice_invalid": "Use one of these choices '{choices:s}' for the argument '{name:s}'",
"app_argument_invalid": "Pick a valid value for the argument '{name:s}': {error:s}",
"app_argument_required": "Argument '{name:s}' is required",
"app_change_url_failed_nginx_reload": "Could not reload NGINX. Here is the output of 'nginx -t':\n{nginx_errors:s}",
"app_change_url_identical_domains": "The old and new domain/url_path are identical ('{domain:s}{path:s}'), nothing to do.",
"app_change_url_no_script": "This application '{app_name:s}' doesn't support URL modification yet. Maybe you should upgrade it.",
"app_change_url_no_script": "The app '{app_name:s}' doesn't support URL modification yet. Maybe you should upgrade it.",
"app_change_url_success": "{app:s} URL is now {domain:s}{path:s}",
"app_extraction_failed": "Could not extract the installation files",
"app_full_domain_unavailable": "Sorry, this app must be installed on a domain of its own, but other apps are already installed on the domain '{domain}'. You could use a subdomain dedicated to this app instead.",
"app_id_invalid": "Invalid app ID",
"app_incompatible": "The app {app} is incompatible with your YunoHost version",
"app_install_files_invalid": "These files cannot be installed",
"app_location_already_used": "The app '{app}' is already installed in ({path})",
"app_make_default_location_already_used": "Can't make the app '{app}' the default on the domain, {domain} is already in use by the other app '{other_app}'",
"app_location_install_failed": "Cannot install the app there because it conflicts with the app '{other_app}' already installed in '{other_path}'",
"app_install_failed": "Could not install {app}: {error}",
"app_install_script_failed": "An error occurred inside the app installation script",
"app_make_default_location_already_used": "Can't make the app '{app}' the default on the domain, '{domain}' is already in use by the other app '{other_app}'",
"app_location_unavailable": "This URL is either unavailable, or conflicts with the already installed app(s):\n{apps:s}",
"app_manifest_invalid": "Something is wrong with the app manifest: {error}",
"app_not_upgraded": "The app '{failed_app}' failed to upgrade, and as a consequence the following apps upgrades have been cancelled: {apps}",
"app_upgrade_stopped": "The upgrade of all applications has been stopped to prevent possible damage because the previous application failed to upgrade",
"app_not_upgraded": "The app '{failed_app}' failed to upgrade, and as a consequence the following apps' upgrades have been cancelled: {apps}",
"app_not_correctly_installed": "{app:s} seems to be incorrectly installed",
"app_not_installed": "Could not find the application '{app:s}' in the list of installed apps: {all_apps}",
"app_not_installed": "Could not find the app '{app:s}' in the list of installed apps: {all_apps}",
"app_not_properly_removed": "{app:s} has not been properly removed",
"app_package_need_update": "The app {app} package needs to be updated to follow YunoHost changes",
"app_removed": "{app:s} removed",
"app_requirements_checking": "Checking required packages for {app}…",
"app_requirements_failed": "Some requirements are not met for {app}: {error}",
"app_requirements_unmeet": "Requirements are not met for {app}, the package {pkgname} ({version}) must be {spec}",
"app_remove_after_failed_install": "Removing the app following the installation failure…",
"app_sources_fetch_failed": "Could not fetch sources files, is the URL correct?",
"app_start_install": "Installing application {app}…",
"app_start_remove": "Removing application {app}…",
"app_start_backup": "Collecting files to be backed up for {app}…",
"app_start_restore": "Restoring application {app}…",
"app_start_install": "Installing the app '{app}'…",
"app_start_remove": "Removing the app '{app}'…",
"app_start_backup": "Collecting files to be backed up for the app '{app}'…",
"app_start_restore": "Restoring the app '{app}'…",
"app_unknown": "Unknown app",
"app_unsupported_remote_type": "Unsupported remote type used for the app",
"app_upgrade_several_apps": "The following apps will be upgraded: {apps}",
"app_upgrade_app_name": "Now upgrading {app}…",
"app_upgrade_failed": "Could not upgrade {app:s}",
"app_upgrade_some_app_failed": "Some applications could not be upgraded",
"app_upgrade_failed": "Could not upgrade {app:s}: {error}",
"app_upgrade_script_failed": "An error occurred inside the app upgrade script",
"app_upgrade_some_app_failed": "Some apps could not be upgraded",
"app_upgraded": "{app:s} upgraded",
"apps_already_up_to_date": "All applications are already up-to-date",
"apps_permission_not_found": "No permission found for the installed apps",
"apps_permission_restoration_failed": "Grant the permission permission '{permission:s}' to restore {app:s}",
"appslist_corrupted_json": "Could not load the application lists. It looks like {filename:s} is damaged.",
"appslist_could_not_migrate": "Could not migrate the app list {appslist:s}! Could not parse the URL… The old cron job was kept kept in {bkp_file:s}.",
"appslist_fetched": "Updated application list {appslist:s} fetched",
"appslist_migrating": "Migrating application list {appslist:s}…",
"appslist_name_already_tracked": "A registered application list with name {name:s} already exists.",
"appslist_removed": "{appslist:s} application list removed",
"appslist_retrieve_bad_format": "Could not read the fetched application list {appslist:s}",
"appslist_retrieve_error": "Cannot retrieve the remote application list {appslist:s}: {error:s}",
"appslist_unknown": "Application list {appslist:s} unknown.",
"appslist_url_already_tracked": "There is already a registered application list with the URL {url:s}.",
"ask_current_admin_password": "Current administration password",
"apps_already_up_to_date": "All apps are already up-to-date",
"apps_catalog_init_success": "App catalog system initialized!",
"apps_catalog_updating": "Updating application catalog…",
"apps_catalog_failed_to_download": "Unable to download the {apps_catalog} app catalog: {error}",
"apps_catalog_obsolete_cache": "The app catalog cache is empty or obsolete.",
"apps_catalog_update_success": "The application catalog has been updated!",
"ask_email": "E-mail address",
"ask_firstname": "First name",
"ask_lastname": "Last name",
"ask_list_to_remove": "List to remove",
"ask_main_domain": "Main domain",
"ask_new_admin_password": "New administration password",
"ask_new_domain": "New domain",
"ask_new_path": "New path",
"ask_password": "Password",
"ask_path": "Path",
"backup_abstract_method": "This backup method has yet to be implemented",
"backup_actually_backuping": "Creating a backup archive from the collected files…",
"backup_app_failed": "Could not back up the app '{app:s}'",
@ -85,12 +74,14 @@
"backup_archive_name_exists": "A backup archive with this name already exists.",
"backup_archive_name_unknown": "Unknown local backup archive named '{name:s}'",
"backup_archive_open_failed": "Could not open the backup archive",
"backup_archive_cant_retrieve_info_json": "Could not load infos for archive '{archive}' ... The info.json cannot be retrieved (or is not a valid json).",
"backup_archive_corrupted": "It looks like the backup archive '{archive}' is corrupted : {error}",
"backup_archive_system_part_not_available": "System part '{part:s}' unavailable in this backup",
"backup_archive_writing_error": "Could not add the files '{source:s}' (named in the archive '{dest:s}') to be backed up into the compressed archive '{archive:s}'",
"backup_ask_for_copying_if_needed": "Some files could not be prepared for backup using the method that avoids temporarily wasting space on the system. To perform the backup, {size:s}MB will be temporarily. Do you agree?",
"backup_ask_for_copying_if_needed": "Do you want to perform the backup using {size:s} MB temporarily? (This way is used since some files could not be prepared using a more efficient method.)",
"backup_borg_not_implemented": "The Borg backup method is not yet implemented",
"backup_cant_mount_uncompress_archive": "Could not mount the uncompressed archive as write protected",
"backup_cleaning_failed": "Could not clean-up the temporary backup folder",
"backup_cleaning_failed": "Could not clean up the temporary backup folder",
"backup_copying_to_organize_the_archive": "Copying {size:s}MB to organize the archive",
"backup_couldnt_bind": "Could not bind {src:s} to {dest:s}.",
"backup_created": "Backup created",
@ -102,7 +93,6 @@
"backup_delete_error": "Could not delete '{path:s}'",
"backup_deleted": "Backup deleted",
"backup_hook_unknown": "The backup hook '{hook:s}' is unknown",
"backup_invalid_archive": "This is not a backup archive",
"backup_method_borg_finished": "Backup into Borg finished",
"backup_method_copy_finished": "Backup copy finalized",
"backup_method_custom_finished": "Custom backup method '{method:s}' finished",
@ -110,10 +100,10 @@
"backup_mount_archive_for_restore": "Preparing archive for restoration…",
"backup_no_uncompress_archive_dir": "There is no such uncompressed archive directory",
"backup_nothings_done": "Nothing to save",
"backup_output_directory_forbidden": "Pick a different output directory. Backups can not be created in /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var or /home/yunohost.backup/archives sub-folders",
"backup_output_directory_forbidden": "Pick a different output directory. Backups cannot be created in /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var or /home/yunohost.backup/archives sub-folders",
"backup_output_directory_not_empty": "You should pick an empty output directory",
"backup_output_directory_required": "You must provide an output directory for the backup",
"backup_output_symlink_dir_broken": "You have a broken symlink in place of your archive directory '{path:s}'. You may have a specific setup to backup your data on another filesystem, in this case you probably forgot to remount or plug in your hard-drive or USB key.",
"backup_output_symlink_dir_broken": "Your archive directory '{path:s}' is a broken symlink. Maybe you forgot to re/mount or plug in the storage medium it points to.",
"backup_permission": "Backup permission for app {app:s}",
"backup_php5_to_php7_migration_may_fail": "Could not convert your archive to support PHP 7, you may be unable to restore your PHP apps (reason: {error:s})",
"backup_running_hooks": "Running backup hooks…",
@ -121,7 +111,7 @@
"backup_unable_to_organize_files": "Could not use the quick method to organize files in the archive",
"backup_with_no_backup_script_for_app": "The app '{app:s}' has no backup script. Ignoring.",
"backup_with_no_restore_script_for_app": "The '{app:s}' has no restoration script, you will not be able to automatically restore the backup of this app.",
"certmanager_acme_not_configured_for_domain": "Certificate for the domain '{domain:s}' does not appear to be correctly installed. Please run 'cert-install' for this domain first.",
"certmanager_acme_not_configured_for_domain": "The ACME challenge cannot be ran for {domain} right now because its nginx conf lacks the corresponding code snippet... Please make sure that your nginx configuration is up to date using `yunohost tools regen-conf nginx --dry-run --with-diff`.",
"certmanager_attempt_to_renew_nonLE_cert": "The certificate for the domain '{domain:s}' is not issued by Let's Encrypt. Cannot renew it automatically!",
"certmanager_attempt_to_renew_valid_cert": "The certificate for the domain '{domain:s}' is not about to expire! (You may use --force if you know what you're doing)",
"certmanager_attempt_to_replace_valid_cert": "You are attempting to overwrite a good and valid certificate for domain {domain:s}! (Use --force to bypass)",
@ -131,36 +121,143 @@
"certmanager_cert_renew_success": "Let's Encrypt certificate renewed for the domain '{domain:s}'",
"certmanager_cert_signing_failed": "Could not sign the new certificate",
"certmanager_certificate_fetching_or_enabling_failed": "Trying to use the new certificate for {domain:s} did not work…",
"certmanager_conflicting_nginx_file": "Could not prepare domain for ACME challenge: the NGINX configuration file {filepath:s} is conflicting and should be removed first",
"certmanager_couldnt_fetch_intermediate_cert": "Timed out when trying to fetch intermediate certificate from Let's Encrypt. Certificate installation/renewal aborted—please try again later.",
"certmanager_domain_cert_not_selfsigned": "The certificate for domain {domain:s} is not self-signed. Are you sure you want to replace it? (Use '--force' to do so.)",
"certmanager_domain_dns_ip_differs_from_public_ip": "The DNS 'A' record for the domain '{domain:s}' is different from this server IP. If you recently modified your A record, please wait for it to propagate (some DNS propagation checkers are available online). (If you know what you are doing, use '--no-checks' to turn off those checks.)",
"certmanager_domain_dns_ip_differs_from_public_ip": "The DNS 'A' record for the domain '{domain:s}' is different from this server's IP. If you recently modified your A record, please wait for it to propagate (some DNS propagation checkers are available online). (If you know what you are doing, use '--no-checks' to turn off those checks.)",
"certmanager_domain_http_not_working": "It seems the domain {domain:s} cannot be accessed through HTTP. Check that your DNS and NGINX configuration is correct",
"certmanager_domain_unknown": "Unknown domain '{domain:s}'",
"certmanager_error_no_A_record": "No DNS 'A' record found for '{domain:s}'. You need to make your domain name point to your machine to be able to install a Let's Encrypt certificate. (If you know what you are doing, use '--no-checks' to turn off those checks.)",
"certmanager_warning_subdomain_dns_record": "Subdomain '{subdomain:s}' does not resolve to the same IP address as '{domain:s}'. Some features will not be available until you fix this and regenerate the certificate.",
"certmanager_hit_rate_limit": "Too many certificates already issued for this exact set of domains {domain:s} recently. Please try again later. See https://letsencrypt.org/docs/rate-limits/ for more details",
"certmanager_http_check_timeout": "Timed out when server tried to contact itself through HTTP using a public IP address (domain '{domain:s}' with IP '{ip:s}'). You may be experiencing a hairpinning issue, or the firewall/router ahead of your server is misconfigured.",
"certmanager_no_cert_file": "Could not read the certificate file for the domain {domain:s} (file: {file:s})",
"certmanager_self_ca_conf_file_not_found": "Could not find configuration file for self-signing authority (file: {file:s})",
"certmanager_unable_to_parse_self_CA_name": "Could not parse name of self-signing authority (file: {file:s})",
"confirm_app_install_warning": "Warning: This application may work, but is not well-integrated in YunoHost. Some features such as single sign-on and backup/restore might not be available. Install anyway? [{answers:s}] ",
"confirm_app_install_danger": "WARNING! This application is still experimental (if not explicitly not working) and it is likely to break your system! You should probably NOT install it unless you know what you are doing. Are you willing to take that risk? [{answers:s}] ",
"confirm_app_install_thirdparty": "WARNING! Installing third-party applications may compromise the integrity and security of your system. You should probably NOT install it unless you know what you are doing. Are you willing to take that risk? [{answers:s}] ",
"confirm_app_install_warning": "Warning: This app may work, but is not well-integrated in YunoHost. Some features such as single sign-on and backup/restore might not be available. Install anyway? [{answers:s}] ",
"confirm_app_install_danger": "DANGER! This app is known to be still experimental (if not explicitly not working)! You should probably NOT install it unless you know what you are doing. NO SUPPORT will be provided if this app doesn't work or breaks your system… If you are willing to take that risk anyway, type '{answers:s}'",
"confirm_app_install_thirdparty": "DANGER! This app is not part of Yunohost's app catalog. Installing third-party apps may compromise the integrity and security of your system. You should probably NOT install it unless you know what you are doing. NO SUPPORT will be provided if this app doesn't work or breaks your system… If you are willing to take that risk anyway, type '{answers:s}'",
"custom_app_url_required": "You must provide a URL to upgrade your custom app {app:s}",
"custom_appslist_name_required": "You must provide a name for your custom app list",
"diagnosis_debian_version_error": "Could not retrieve the Debian version: {error}",
"diagnosis_kernel_version_error": "Could not retrieve kernel version: {error}",
"diagnosis_monitor_disk_error": "Could not monitor disks: {error}",
"diagnosis_monitor_system_error": "Could not monitor system: {error}",
"diagnosis_no_apps": "No installed application",
"dpkg_is_broken": "You cannot do this right now because dpkg/APT (the system package managers) seems to be in a broken state… You can try to solve this issue by connecting through SSH and running `sudo dpkg --configure -a`.",
"dpkg_lock_not_available": "This command can't be ran right now because another program seems to be using the lock of dpkg (the system package manager)",
"domain_cannot_remove_main": "Cannot remove main domain. Set one first",
"diagnosis_basesystem_hardware": "Server hardware architecture is {virt} {arch}",
"diagnosis_basesystem_hardware_board": "Server board model is {model}",
"diagnosis_basesystem_host": "Server is running Debian {debian_version}",
"diagnosis_basesystem_kernel": "Server is running Linux kernel {kernel_version}",
"diagnosis_basesystem_ynh_single_version": "{package} version: {version} ({repo})",
"diagnosis_basesystem_ynh_main_version": "Server is running YunoHost {main_version} ({repo})",
"diagnosis_basesystem_ynh_inconsistent_versions": "You are running inconsistent versions of the YunoHost packages... most probably because of a failed or partial upgrade.",
"diagnosis_display_tip": "To see the issues found, you can go to the Diagnosis section of the webadmin, or run 'yunohost diagnosis show --issues' from the command-line.",
"diagnosis_failed_for_category": "Diagnosis failed for category '{category}': {error}",
"diagnosis_cache_still_valid": "(Cache still valid for {category} diagnosis. Won't re-diagnose it yet!)",
"diagnosis_cant_run_because_of_dep": "Can't run diagnosis for {category} while there are important issues related to {dep}.",
"diagnosis_ignored_issues": "(+ {nb_ignored} ignored issue(s))",
"diagnosis_found_errors": "Found {errors} significant issue(s) related to {category}!",
"diagnosis_found_errors_and_warnings": "Found {errors} significant issue(s) (and {warnings} warning(s)) related to {category}!",
"diagnosis_found_warnings": "Found {warnings} item(s) that could be improved for {category}.",
"diagnosis_everything_ok": "Everything looks good for {category}!",
"diagnosis_failed": "Failed to fetch diagnosis result for category '{category}': {error}",
"diagnosis_no_cache": "No diagnosis cache yet for category '{category}'",
"diagnosis_ip_connected_ipv4": "The server is connected to the Internet through IPv4 !",
"diagnosis_ip_no_ipv4": "The server does not have working IPv4.",
"diagnosis_ip_connected_ipv6": "The server is connected to the Internet through IPv6 !",
"diagnosis_ip_no_ipv6": "The server does not have working IPv6.",
"diagnosis_ip_global": "Global IP: <code>{global}</code>",
"diagnosis_ip_local": "Local IP: <code>{local}</code>",
"diagnosis_ip_not_connected_at_all": "The server does not seem to be connected to the Internet at all!?",
"diagnosis_ip_dnsresolution_working": "Domain name resolution is working!",
"diagnosis_ip_broken_dnsresolution": "Domain name resolution seems to be broken for some reason... Is a firewall blocking DNS requests ?",
"diagnosis_ip_broken_resolvconf": "Domain name resolution seems to be broken on your server, which seems related to <code>/etc/resolv.conf</code> not pointing to <code>127.0.0.1</code>.",
"diagnosis_ip_weird_resolvconf": "DNS resolution seems to be working, but it looks like you're using a custom <code>/etc/resolv.conf</code>.",
"diagnosis_ip_weird_resolvconf_details": "The file <code>/etc/resolv.conf</code> should be a symlink to <code>/etc/resolvconf/run/resolv.conf</code> itself pointing to <code>127.0.0.1</code> (dnsmasq). If you want to manually configure DNS resolvers, please edit <code>/etc/resolv.dnsmasq.conf</code>.",
"diagnosis_dns_good_conf": "DNS records are correctly configured for domain {domain} (category {category})",
"diagnosis_dns_bad_conf": "Some DNS records are missing or incorrect for domain {domain} (category {category})",
"diagnosis_dns_missing_record": "According to the recommended DNS configuration, you should add a DNS record with the following info.<br>Type: <code>{type}</code><br>Name: <code>{name}</code><br>Value: <code>{value}</code>",
"diagnosis_dns_discrepancy": "The following DNS record does not seem to follow the recommended configuration:<br>Type: <code>{type}</code><br>Name: <code>{name}</code><br>Current value: <code>{current}</code><br>Excepted value: <code>{value}</code>",
"diagnosis_dns_point_to_doc": "Please check the documentation at <a href='https://yunohost.org/dns_config'>https://yunohost.org/dns_config</a> if you need help about configuring DNS records.",
"diagnosis_services_running": "Service {service} is running!",
"diagnosis_services_conf_broken": "Configuration is broken for service {service}!",
"diagnosis_services_bad_status": "Service {service} is {status} :(",
"diagnosis_services_bad_status_tip": "You can try to <a href='#/services/{service}'>restart the service</a>, and if it doesn't work, have a look at <a href='#/services/{service}'>the service logs in the webadmin</a> (from the command line, you can do this with <cmd>yunohost service restart {service}</cmd> and <cmd>yunohost service log {service}</cmd>).",
"diagnosis_diskusage_verylow": "Storage <code>{mountpoint}</code> (on device <code>{device}</code>) has only {free} ({free_percent}%) space remaining (out of {total}). You should really consider cleaning up some space!",
"diagnosis_diskusage_low": "Storage <code>{mountpoint}</code> (on device <code>{device}</code>) has only {free} ({free_percent}%) space remaining (out of {total}). Be careful.",
"diagnosis_diskusage_ok": "Storage <code>{mountpoint}</code> (on device <code>{device}</code>) still has {free} ({free_percent}%) space left (out of {total})!",
"diagnosis_ram_verylow": "The system has only {available} ({available_percent}%) RAM available! (out of {total})",
"diagnosis_ram_low": "The system has {available} ({available_percent}%) RAM available (out of {total}). Be careful.",
"diagnosis_ram_ok": "The system still has {available} ({available_percent}%) RAM available out of {total}.",
"diagnosis_swap_none": "The system has no swap at all. You should consider adding at least {recommended} of swap to avoid situations where the system runs out of memory.",
"diagnosis_swap_notsomuch": "The system has only {total} swap. You should consider having at least {recommended} to avoid situations where the system runs out of memory.",
"diagnosis_swap_ok": "The system has {total} of swap!",
"diagnosis_mail_outgoing_port_25_ok": "The SMTP mail server is able to send emails (outgoing port 25 is not blocked).",
"diagnosis_mail_outgoing_port_25_blocked": "The SMTP mail server cannot send emails to other servers because outgoing port 25 is blocked in IPv{ipversion}.",
"diagnosis_mail_outgoing_port_25_blocked_details": "You should first try to unblock outgoing port 25 in your internet router interface or your hosting provider interface. (Some hosting provider may require you to send them a support ticket for this).",
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn": "Some providers won't let you unblock outgoing port 25 because they don't care about Net Neutrality.<br> - Some of them provide the alternative of <a href='https://yunohost.org/#/smtp_relay'>using a mail server relay</a> though it implies that the relay will be able to spy on your email traffic.<br>- A privacy-friendly alternative is to use a VPN *with a dedicated public IP* to bypass this kind of limits. See <a href='https://yunohost.org/#/vpn_advantage'>https://yunohost.org/#/vpn_advantage</a><br>- You can also consider switching to <a href='https://yunohost.org/#/isp'>a more net neutrality-friendly provider</a>",
"diagnosis_mail_ehlo_ok": "The SMTP mail server is reachable from the outside and therefore is able to receive emails!",
"diagnosis_mail_ehlo_unreachable": "The SMTP mail server is unreachable from the outside on IPv{ipversion}. It won't be able to receive emails.",
"diagnosis_mail_ehlo_unreachable_details": "Could not open a connection on port 25 to your server in IPv{ipversion}. It appears to be unreachable.<br>1. The most common cause for this issue is that port 25 <a href='https://yunohost.org/isp_box_config'>is not correctly forwarded to your server</a>.<br>2. You should also make sure that service postfix is running.<br>3. On more complex setups: make sure that no firewall or reverse-proxy is interfering.",
"diagnosis_mail_ehlo_bad_answer": "A non-SMTP service answered on port 25 on IPv{ipversion}",
"diagnosis_mail_ehlo_bad_answer_details": "It could be due to an other machine answering instead of your server.",
"diagnosis_mail_ehlo_wrong": "A different SMTP mail server answers on IPv{ipversion}. It will probably not be able to receive emails.",
"diagnosis_mail_ehlo_wrong_details": "The EHLO received by the remote diagnoser in IPv{ipversion} is different from your server's domain.<br>Received EHLO: <code>{wrong_ehlo}</code><br>Expected: {right_ehlo}<br>The most common cause for this issue is that port 25 <a href='https://yunohost.org/isp_box_config'>is not correctly forwarded to your server</a>. Alternatively, make sure that no firewall or reverse-proxy is interfering.",
"diagnosis_mail_ehlo_could_not_diagnose": "Could not diagnose if postfix mail server is reachable from outside in IPv{ipversion}.",
"diagnosis_mail_ehlo_could_not_diagnose_details": "Error: {error}",
"diagnosis_mail_fcrdns_ok": "Your reverse DNS is correctly configured!",
"diagnosis_mail_fcrdns_dns_missing": "No reverse DNS is defined in IPv{ipversion}. Some emails may fail to get delivered or may get flagged as spam.",
"diagnosis_mail_fcrdns_nok_details": "You should first try to configure the reverse DNS with <code>{ehlo_domain}</code> in your internet router interface or your hosting provider interface. (Some hosting provider may require you to send them a support ticket for this).",
"diagnosis_mail_fcrdns_nok_alternatives_4": "Some providers won't let you configure your reverse DNS (or their feature might be broken...). If you are experiencing issues because of this, consider the following solutions:<br> - Some ISP provide the alternative of <a href='https://yunohost.org/#/smtp_relay'>using a mail server relay</a> though it implies that the relay will be able to spy on your email traffic.<br>- A privacy-friendly alternative is to use a VPN *with a dedicated public IP* to bypass this kind of limits. See <a href='https://yunohost.org/#/vpn_advantage'>https://yunohost.org/#/vpn_advantage</a><br>- Finally, it's also possible to <a href='https://yunohost.org/#/isp'>change of provider</a>",
"diagnosis_mail_fcrdns_nok_alternatives_6": "Some providers won't let you configure your reverse DNS (or their feature might be broken...). If your reverse DNS is correctly configured for IPv4, you can try disabling the use of IPv6 when sending emails by running <cmd>yunohost settings set smtp.allow_ipv6 -v off</cmd>. Note: this last solution means that you won't be able to send or receive emails from the few IPv6-only servers out there.",
"diagnosis_mail_fcrdns_different_from_ehlo_domain": "The reverse DNS is not correctly configured in IPv{ipversion}. Some emails may fail to get delivered or may get flagged as spam.",
"diagnosis_mail_fcrdns_different_from_ehlo_domain_details": "Current reverse DNS: <code>{rdns_domain}</code><br>Expected value: <code>{ehlo_domain}</code>",
"diagnosis_mail_blacklist_ok": "The IPs and domains used by this server do not appear to be blacklisted",
"diagnosis_mail_blacklist_listed_by": "Your IP or domain <code>{item}</code> is blacklisted on {blacklist_name}",
"diagnosis_mail_blacklist_reason": "The blacklist reason is: {reason}",
"diagnosis_mail_blacklist_website": "After identifying why you are listed and fixed it, feel free to ask for delisting on {blacklist_website}",
"diagnosis_mail_queue_ok": "{nb_pending} pending emails in the mail queues",
"diagnosis_mail_queue_unavailable": "Can not consult number of pending emails in queue",
"diagnosis_mail_queue_unavailable_details": "Error: {error}",
"diagnosis_mail_queue_too_big": "Too many pending emails in mail queue ({nb_pending} emails)",
"diagnosis_regenconf_allgood": "All configurations files are in line with the recommended configuration!",
"diagnosis_regenconf_manually_modified": "Configuration file <code>{file}</code> appears to have been manually modified.",
"diagnosis_regenconf_manually_modified_details": "This is probably OK if you know what you're doing! YunoHost will stop updating this file automatically... But beware that YunoHost upgrades could contain important recommended changes. If you want to, you can inspect the differences with <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> and force the reset to the recommended configuration with <cmd>yunohost tools regen-conf {category} --force</cmd>",
"diagnosis_security_all_good": "No critical security vulnerability was found.",
"diagnosis_security_vulnerable_to_meltdown": "You appear vulnerable to the Meltdown criticial security vulnerability",
"diagnosis_security_vulnerable_to_meltdown_details": "To fix this, you should upgrade your system and reboot to load the new linux kernel (or contact your server provider if this doesn't work). See https://meltdownattack.com/ for more infos.",
"diagnosis_description_basesystem": "Base system",
"diagnosis_description_ip": "Internet connectivity",
"diagnosis_description_dnsrecords": "DNS records",
"diagnosis_description_services": "Services status check",
"diagnosis_description_systemresources": "System resources",
"diagnosis_description_ports": "Ports exposure",
"diagnosis_description_web": "Web",
"diagnosis_description_mail": "Email",
"diagnosis_description_regenconf": "System configurations",
"diagnosis_description_security": "Security checks",
"diagnosis_ports_could_not_diagnose": "Could not diagnose if ports are reachable from outside in IPv{ipversion}.",
"diagnosis_ports_could_not_diagnose_details": "Error: {error}",
"diagnosis_ports_unreachable": "Port {port} is not reachable from outside.",
"diagnosis_ports_partially_unreachable": "Port {port} is not reachable from outside in IPv{failed}.",
"diagnosis_ports_ok": "Port {port} is reachable from outside.",
"diagnosis_ports_needed_by": "Exposing this port is needed for {category} features (service {service})",
"diagnosis_ports_forwarding_tip": "To fix this issue, you most probably need to configure port forwarding on your internet router as described in <a href='https://yunohost.org/isp_box_config'>https://yunohost.org/isp_box_config</a>",
"diagnosis_http_hairpinning_issue": "Your local network does not seem to have hairpinning enabled.",
"diagnosis_http_hairpinning_issue_details": "This is probably because of your ISP box / router. As a result, people from outside your local network will be able to access your server as expected, but not people from inside the local network (like you, probably?). You may be able to improve the situation by having a look at <a href='https://yunohost.org/dns_local_network'>https://yunohost.org/dns_local_network</a>",
"diagnosis_http_could_not_diagnose": "Could not diagnose if domains are reachable from outside in IPv{ipversion}.",
"diagnosis_http_could_not_diagnose_details": "Error: {error}",
"diagnosis_http_ok": "Domain {domain} is reachable through HTTP from outside the local network.",
"diagnosis_http_timeout": "Timed-out while trying to contact your server from outside. It appears to be unreachable.<br>1. The most common cause for this issue is that port 80 (and 443) <a href='https://yunohost.org/isp_box_config'>are not correctly forwarded to your server</a>.<br>2. You should also make sure that the service nginx is running<br>3. On more complex setups: make sure that no firewall or reverse-proxy is interfering.",
"diagnosis_http_connection_error": "Connection error: could not connect to the requested domain, it's very likely unreachable.",
"diagnosis_http_bad_status_code": "It looks like another machine (maybe your internet router) answered instead of your server.<br>1. The most common cause for this issue is that port 80 (and 443) <a href='https://yunohost.org/isp_box_config'>are not correctly forwarded to your server</a>.<br>2. On more complex setups: make sure that no firewall or reverse-proxy is interfering.",
"diagnosis_http_unreachable": "Domain {domain} appears unreachable through HTTP from outside the local network.",
"diagnosis_http_partially_unreachable": "Domain {domain} appears unreachable through HTTP from outside the local network in IPv{failed}, though it works in IPv{passed}.",
"diagnosis_http_nginx_conf_not_up_to_date": "This domain's nginx configuration appears to have been modified manually, and prevents YunoHost from diagnosing if it's reachable on HTTP.",
"diagnosis_http_nginx_conf_not_up_to_date_details": "To fix the situation, inspect the difference with the command line using <cmd>yunohost tools regen-conf nginx --dry-run --with-diff</cmd> and if you're ok, apply the changes with <cmd>yunohost tools regen-conf nginx --force</cmd>.",
"diagnosis_unknown_categories": "The following categories are unknown: {categories}",
"diagnosis_never_ran_yet": "It looks like this server was setup recently and there's no diagnosis report to show yet. You should start by running a full diagnosis, either from the webadmin or using 'yunohost diagnosis run' from the command line.",
"domain_cannot_remove_main": "You cannot remove '{domain:s}' since it's the main domain, you first need to set another domain as the main domain using 'yunohost domain main-domain -n <another-domain>'; here is the list of candidate domains: {other_domains:s}",
"domain_cannot_add_xmpp_upload": "You cannot add domains starting with 'xmpp-upload.'. This kind of name is reserved for the XMPP upload feature integrated in YunoHost.",
"domain_cannot_remove_main_add_new_one": "You cannot remove '{domain:s}' since it's the main domain and your only domain, you need to first add another domain using 'yunohost domain add <another-domain.com>', then set is as the main domain using 'yunohost domain main-domain -n <another-domain.com>' and then you can remove the domain '{domain:s}' using 'yunohost domain remove {domain:s}'.'",
"domain_cert_gen_failed": "Could not generate certificate",
"domain_created": "Domain created",
"domain_creation_failed": "Could not create domain",
"domain_creation_failed": "Unable to create domain {domain}: {error}",
"domain_deleted": "Domain deleted",
"domain_deletion_failed": "Could not delete domain",
"domain_deletion_failed": "Unable to delete domain {domain}: {error}",
"domain_dns_conf_is_just_a_recommendation": "This command shows you the *recommended* configuration. It does not actually set up the DNS configuration for you. It is your responsability to configure your DNS zone in your registrar according to this recommendation.",
"domain_dyndns_already_subscribed": "You have already subscribed to a DynDNS domain",
"domain_dyndns_root_unknown": "Unknown DynDNS root domain",
@ -171,6 +268,8 @@
"domains_available": "Available domains:",
"done": "Done",
"downloading": "Downloading…",
"dpkg_is_broken": "You cannot do this right now because dpkg/APT (the system package managers) seems to be in a broken state… You can try to solve this issue by connecting through SSH and running `sudo dpkg --configure -a`.",
"dpkg_lock_not_available": "This command can't be run right now because another program seems to be using the lock of dpkg (the system package manager)",
"dyndns_could_not_check_provide": "Could not check if {provider:s} can provide {domain:s}.",
"dyndns_could_not_check_available": "Could not check if {domain:s} is available on {provider:s}.",
"dyndns_cron_installed": "DynDNS cron job created",
@ -181,14 +280,11 @@
"dyndns_key_generating": "Generating DNS key… It may take a while.",
"dyndns_key_not_found": "DNS key not found for the domain",
"dyndns_no_domain_registered": "No domain registered with DynDNS",
"dyndns_provider_unreachable": "Unable to reach Dyndns provider {provider}: either your YunoHost is not correctly connected to the internet or the dynette server is down.",
"dyndns_provider_unreachable": "Unable to reach DynDNS provider {provider}: either your YunoHost is not correctly connected to the internet or the dynette server is down.",
"dyndns_registered": "DynDNS domain registered",
"dyndns_registration_failed": "Could not register DynDNS domain: {error:s}",
"dyndns_domain_not_provided": "DynDNS provider {provider:s} cannot provide domain {domain:s}.",
"dyndns_unavailable": "The domain '{domain:s}' is unavailable.",
"edit_group_not_allowed": "You are not allowed to edit the group {group:s}",
"edit_permission_with_group_all_users_not_allowed": "You are not allowed to edit permission for the group 'all_users', use 'yunohost user permission clear APP' or 'yunohost user permission add APP -u USER' instead.",
"error_when_removing_sftpuser_group": "Could not remove the sftpusers group",
"executing_command": "Executing command '{command:s}'…",
"executing_script": "Executing script '{script:s}'…",
"extracting": "Extracting…",
@ -197,7 +293,7 @@
"file_does_not_exist": "The file {path:s} does not exist.",
"firewall_reload_failed": "Could not reload the firewall",
"firewall_reloaded": "Firewall reloaded",
"firewall_rules_cmd_failed": "Some firewall rules commands have failed. More info in log.",
"firewall_rules_cmd_failed": "Some firewall rule commands have failed. More info in log.",
"global_settings_bad_choice_for_enum": "Bad choice for setting {setting:s}, received '{choice:s}', but available choices are: {available_choices:s}",
"global_settings_bad_type_for_setting": "Bad type for setting {setting:s}, received {received_type:s}, expected {expected_type:s}",
"global_settings_cant_open_settings": "Could not open settings file, reason: {reason:s}",
@ -205,6 +301,7 @@
"global_settings_cant_write_settings": "Could not save settings file, reason: {reason:s}",
"global_settings_key_doesnt_exists": "The key '{settings_key:s}' does not exist in the global settings, you can see all the available keys by running 'yunohost settings list'",
"global_settings_reset_success": "Previous settings now backed up to {path:s}",
"global_settings_setting_pop3_enabled": "Enable the POP3 protocol for the mail server",
"global_settings_setting_example_bool": "Example boolean option",
"global_settings_setting_example_enum": "Example enum option",
"global_settings_setting_example_int": "Example int option",
@ -216,26 +313,32 @@
"global_settings_setting_security_postfix_compatibility": "Compatibility vs. security tradeoff for the Postfix server. Affects the ciphers (and other security-related aspects)",
"global_settings_unknown_setting_from_settings_file": "Unknown key in settings: '{setting_key:s}', discard it and save it in /etc/yunohost/settings-unknown.json",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Allow the use of (deprecated) DSA hostkey for the SSH daemon configuration",
"global_settings_setting_smtp_allow_ipv6": "Allow the use of IPv6 to receive and send mail",
"global_settings_unknown_type": "Unexpected situation, the setting {setting:s} appears to have the type {unknown_type:s} but it is not a type supported by the system.",
"good_practices_about_admin_password": "You are now about to define a new administration password. The password should be at-least 8 characters—though it is good practice to use a longer password (i.e. a passphrase) and/or to use a variation of characters (uppercase, lowercase, digits and special characters).",
"good_practices_about_user_password": "You are now about to define a new user password. The password should be at least 8 characters—though it is good practice to use longer password (i.e. a passphrase) and/or to a variation of characters (uppercase, lowercase, digits and special characters).",
"group_already_allowed": "Group '{group:s}' already has permission '{permission:s}' turned on for the app '{app:s}'",
"group_already_disallowed": "Group '{group:s}' already has permissions '{permission:s}' turned off for the app '{app:s}'",
"group_name_already_exist": "Group {name:s} already exists",
"good_practices_about_admin_password": "You are now about to define a new administration password. The password should be at least 8 characters long—though it is good practice to use a longer password (i.e. a passphrase) and/or to use a variation of characters (uppercase, lowercase, digits and special characters).",
"good_practices_about_user_password": "You are now about to define a new user password. The password should be at least 8 characters long—though it is good practice to use a longer password (i.e. a passphrase) and/or to a variation of characters (uppercase, lowercase, digits and special characters).",
"group_already_exist": "Group {group} already exists",
"group_already_exist_on_system": "Group {group} already exists in the system groups",
"group_already_exist_on_system_but_removing_it": "Group {group} already exists in the system groups, but YunoHost will remove it…",
"group_created": "Group '{group}' created",
"group_creation_failed": "Could not create the group '{group}'",
"group_creation_failed": "Could not create the group '{group}': {error}",
"group_cannot_edit_all_users": "The group 'all_users' cannot be edited manually. It is a special group meant to contain all users registered in YunoHost",
"group_cannot_edit_visitors": "The group 'visitors' cannot be edited manually. It is a special group representing anonymous visitors",
"group_cannot_edit_primary_group": "The group '{group}' cannot be edited manually. It is the primary group meant to contain only one specific user.",
"group_cannot_be_deleted": "The group {group} cannot be deleted manually.",
"group_deleted": "Group '{group}' deleted",
"group_deletion_failed": "Could not delete the group '{group}'",
"group_deletion_not_allowed": "The group {group:s} cannot be deleted manually.",
"group_deletion_failed": "Could not delete the group '{group}': {error}",
"group_unknown": "The group '{group:s}' is unknown",
"group_updated": "Group '{group}' updated",
"group_update_failed": "Could not update the group '{group}'",
"group_update_failed": "Could not update the group '{group}': {error}",
"group_user_already_in_group": "User {user} is already in group {group}",
"group_user_not_in_group": "User {user} is not in group {group}",
"hook_exec_failed": "Could not run script: {path:s}",
"hook_exec_not_terminated": "Script did not finish properly: {path:s}",
"hook_json_return_error": "Could not read return from hook {path:s}. Error: {msg:s}. Raw content: {raw_content}",
"hook_list_by_invalid": "This property can not be used to list hooks",
"hook_name_unknown": "Unknown hook name '{name:s}'",
"installation_complete": "Installation complete",
"installation_complete": "Installation completed",
"installation_failed": "Something went wrong with the installation",
"ip6tables_unavailable": "You cannot play with ip6tables here. You are either in a container or your kernel does not support it",
"iptables_unavailable": "You cannot play with iptables here. You are either in a container or your kernel does not support it",
@ -245,18 +348,16 @@
"log_help_to_get_log": "To view the log of the operation '{desc}', use the command 'yunohost log display {name}'",
"log_link_to_failed_log": "Could not complete the operation '{desc}'. Please provide the full log of this operation by <a href=\"#/tools/logs/{name}\">clicking here</a> to get help",
"log_help_to_get_failed_log": "The operation '{desc}' could not be completed. Please share the full log of this operation using the command 'yunohost log display {name} --share' to get help",
"log_does_exists": "There is not operation log with the name '{log}', use 'yunohost log list' to see all available operation logs",
"log_does_exists": "There is no operation log with the name '{log}', use 'yunohost log list' to see all available operation logs",
"log_operation_unit_unclosed_properly": "Operation unit has not been closed properly",
"log_app_addaccess": "Add access to '{}'",
"log_app_removeaccess": "Remove access to '{}'",
"log_app_clearaccess": "Remove all access to '{}'",
"log_app_fetchlist": "Add an application list",
"log_app_removelist": "Remove an application list",
"log_app_change_url": "Change the URL of '{}' application",
"log_app_install": "Install the '{}' application",
"log_app_remove": "Remove the '{}' application",
"log_app_upgrade": "Upgrade the '{}' application",
"log_app_makedefault": "Make '{}' the default application",
"log_app_change_url": "Change the URL of the '{}' app",
"log_app_install": "Install the '{}' app",
"log_app_remove": "Remove the '{}' app",
"log_app_upgrade": "Upgrade the '{}' app",
"log_app_makedefault": "Make '{}' the default app",
"log_app_action_run": "Run action of the '{}' app",
"log_app_config_show_panel": "Show the config panel of the '{}' app",
"log_app_config_apply": "Apply config to the '{}' app",
"log_available_on_yunopaste": "This log is now available via {url}",
"log_backup_restore_system": "Restore system from a backup archive",
"log_backup_restore_app": "Restore '{}' from a backup archive",
@ -266,38 +367,37 @@
"log_domain_remove": "Remove '{}' domain from system configuration",
"log_dyndns_subscribe": "Subscribe to a YunoHost subdomain '{}'",
"log_dyndns_update": "Update the IP associated with your YunoHost subdomain '{}'",
"log_letsencrypt_cert_install": "Install a Let's encrypt certificate on '{}' domain",
"log_permission_add": "Add the '{}' permission for the app '{}'",
"log_permission_remove": "Remove permission '{}'",
"log_permission_update": "Update permission '{}' for app '{}'",
"log_selfsigned_cert_install": "Install self signed certificate on '{}' domain",
"log_letsencrypt_cert_renew": "Renew '{}' Let's encrypt certificate",
"log_letsencrypt_cert_install": "Install a Let's Encrypt certificate on '{}' domain",
"log_permission_create": "Create permission '{}'",
"log_permission_delete": "Delete permission '{}'",
"log_permission_url": "Update url related to permission '{}'",
"log_selfsigned_cert_install": "Install self-signed certificate on '{}' domain",
"log_letsencrypt_cert_renew": "Renew '{}' Let's Encrypt certificate",
"log_regen_conf": "Regenerate system configurations '{}'",
"log_user_create": "Add '{}' user",
"log_user_delete": "Delete '{}' user",
"log_user_group_add": "Add '{}' group",
"log_user_group_create": "Create '{}' group",
"log_user_group_delete": "Delete '{}' group",
"log_user_group_update": "Update '{}' group",
"log_user_update": "Update user info of '{}'",
"log_user_permission_add": "Update '{}' permission",
"log_user_permission_remove": "Update '{}' permission",
"log_tools_maindomain": "Make '{}' the main domain",
"log_tools_migrations_migrate_forward": "Migrate forward",
"log_user_permission_update": "Update accesses for permission '{}'",
"log_user_permission_reset": "Reset permission '{}'",
"log_domain_main_domain": "Make '{}' the main domain",
"log_tools_migrations_migrate_forward": "Run migrations",
"log_tools_postinstall": "Postinstall your YunoHost server",
"log_tools_upgrade": "Upgrade system packages",
"log_tools_shutdown": "Shutdown your server",
"log_tools_reboot": "Reboot your server",
"ldap_init_failed_to_create_admin": "LDAP initialization could not create admin user",
"ldap_initialized": "LDAP initialized",
"license_undefined": "undefined",
"mail_alias_remove_failed": "Could not remove e-mail alias '{mail:s}'",
"mail_domain_unknown": "Unknown e-mail address for domain '{domain:s}'",
"mail_domain_unknown": "Invalid e-mail address for domain '{domain:s}'. Please, use a domain administrated by this server.",
"mail_forward_remove_failed": "Could not remove e-mail forwarding '{mail:s}'",
"mailbox_disabled": "E-mail turned off for user {user:s}",
"mailbox_used_space_dovecot_down": "The Dovecot mailbox service needs to be up, if you want to fetch used mailbox space",
"mailbox_used_space_dovecot_down": "The Dovecot mailbox service needs to be up if you want to fetch used mailbox space",
"mail_unavailable": "This e-mail address is reserved and shall be automatically allocated to the very first user",
"maindomain_change_failed": "Could not change the main domain",
"maindomain_changed": "The main domain now changed",
"main_domain_change_failed": "Unable to change the main domain",
"main_domain_changed": "The main domain has been changed",
"migrate_tsig_end": "Migration to HMAC-SHA-512 finished",
"migrate_tsig_failed": "Could not migrate the DynDNS domain '{domain}' to HMAC-SHA-512, rolling back. Error: {error_code}, {error}",
"migrate_tsig_start": "Insufficiently secure key algorithm detected for TSIG signature of the domain '{domain}', initiating migration to the more secure HMAC-SHA-512",
@ -315,48 +415,51 @@
"migration_description_0007_ssh_conf_managed_by_yunohost_step1": "Let the SSH configuration be managed by YunoHost (step 1, automatic)",
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "Let the SSH configuration be managed by YunoHost (step 2, manual)",
"migration_description_0009_decouple_regenconf_from_services": "Decouple the regen-conf mechanism from services",
"migration_description_0010_migrate_to_apps_json": "Remove deprecated applists and use the new unified 'apps.json' list instead",
"migration_description_0011_setup_group_permission": "Set up user group and set up permission for apps and services",
"migration_description_0010_migrate_to_apps_json": "Remove deprecated apps catalogs and use the new unified 'apps.json' list instead (outdated, replaced by migration 13)",
"migration_description_0011_setup_group_permission": "Set up user groups and permissions for apps and services",
"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_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…",
"migration_0003_fail2ban_upgrade": "Starting the Fail2Ban upgrade…",
"migration_0003_restoring_origin_nginx_conf": "Your file /etc/nginx/nginx.conf was edited somehow. The migration is going to reset to its original state first… The previous file will be available as {backup_dest}.",
"migration_0003_yunohost_upgrade": "Starting the YunoHost package upgrade… The migration will end, but the actual upgrade will happen immediately afterwards. After the operation is complete, you might have to log in on the webadmin page again.",
"migration_0003_restoring_origin_nginx_conf": "Your file /etc/nginx/nginx.conf was edited somehow. The migration is going to reset it to its original state first… The previous file will be available as {backup_dest}.",
"migration_0003_yunohost_upgrade": "Starting the YunoHost package upgrade… The migration will end, but the actual upgrade will happen immediately afterwards. After the operation is complete, you might have to log in to the webadmin page again.",
"migration_0003_not_jessie": "The current Debian distribution is not Jessie!",
"migration_0003_system_not_fully_up_to_date": "Your system is not fully up-to-date. Please perform a regular upgrade before running the migration to Stretch.",
"migration_0003_still_on_jessie_after_main_upgrade": "Something went wrong during the main upgrade: Is the system still on Jessie‽ To investigate the issue, please look at {log}:s…",
"migration_0003_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.\n\nAdditionally, the port for SMTP, used by external e-mail clients (like Thunderbird or K9-Mail) was changed from 465 (SSL/TLS) to 587 (STARTTLS). The old port (465) will automatically be closed, and the new port (587) will be opened in the firewall. You and your users *will* have to adapt the configuration of your e-mail clients accordingly.",
"migration_0003_problematic_apps_warning": "Please note that the following possibly problematic installed apps were detected. It looks like those were not installed from an applist, or are not flagged as 'working'. Consequently, it cannot be guaranteed that they will still work after the upgrade: {problematic_apps}",
"migration_0003_problematic_apps_warning": "Please note that the following possibly problematic installed apps were detected. It looks like those were not installed from an app catalog, or are not flagged as 'working'. Consequently, it cannot be guaranteed that they will still work after the upgrade: {problematic_apps}",
"migration_0003_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_0005_postgresql_94_not_installed": "PostgreSQL was not installed on your system. Nothing to do.",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 is installed, but not postgresql 9.6‽ Something weird might have happened on your system:(…",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 is installed, but not postgresql 9.6‽ Something weird might have happened on your system :(…",
"migration_0005_not_enough_space": "Make sufficient space available in {path} to run the migration.",
"migration_0006_disclaimer": "YunoHost now expects admin and root passwords to be synchronized. By running this migration, your root password is going to be replaced by the admin password.",
"migration_0007_cancelled": "YunoHost has failed to improve the way your SSH conf is managed.",
"migration_0006_disclaimer": "YunoHost now expects the admin and root passwords to be synchronized. This migration replaces your root password with the admin password.",
"migration_0007_cancelled": "Could not improve the way your SSH configuration is managed.",
"migration_0007_cannot_restart": "SSH can't be restarted after trying to cancel migration number 6.",
"migration_0008_general_disclaimer": "To improve the security of your server, it is recommended to let YunoHost manage the SSH configuration. Your current SSH setup differs from the recommendation. If you let YunoHost reconfigure it, the way you connect to your server through SSH will change thusly:",
"migration_0008_port": "• You will have to connect using port 22 instead of your current custom SSH port. Feel free to reconfigure it;",
"migration_0008_root": "• You will not be able to connect as root through SSH. Instead you should use the admin user;",
"migration_0008_dsa": "• The DSA key will be turned off. Hence, you might need to invalidate a spooky warning from your SSH client, and recheck the fingerprint of your server;",
"migration_0008_warning": "If you understand those warnings and agree to let YunoHost override your current configuration, run the migration. Otherwise, you can also skip the migration - though it is not recommended.",
"migration_0008_no_warning": "No major risk indentified concerning overriding your SSH configuration—one can however not be absolutely sure ;)! Run the migration to override it. Otherwise, you can also skip the migration - though it is not recommended.",
"migration_0008_warning": "If you understand those warnings and want YunoHost to override your current configuration, run the migration. Otherwise, you can also skip the migration, though it is not recommended.",
"migration_0008_no_warning": "Overriding your SSH configuration should be safe, though this cannot be promised! Run the migration to override it. Otherwise, you can also skip the migration, though it is not recommended.",
"migration_0009_not_needed": "This migration already happened somehow… (?) Skipping.",
"migration_0011_backup_before_migration": "Creating a backup of LDAP database and apps settings prior to the actual migration.",
"migration_0011_can_not_backup_before_migration": "Could not back up the system prior to migration. Error: {error:s}",
"migration_0011_can_not_backup_before_migration": "The backup of the system could not be completed before the migration failed. Error: {error:s}",
"migration_0011_create_group": "Creating a group for each user…",
"migration_0011_done": "Migration successful. You are now able to manage usergroups.",
"migration_0011_LDAP_config_dirty": "It look like that you customized your LDAP configuration. For this migration the LDAP configuration needs to be updated.\nYou need to save your actual configuration, reintialize the original configuration by running 'yunohost tools regen-conf -f' and retry the migration",
"migration_0011_done": "Migration completed. You are now able to manage usergroups.",
"migration_0011_slapd_config_will_be_overwritten": "It looks like you manually edited the slapd configuration. For this critical migration, YunoHost needs to force the update of the slapd configuration. The original files will be backuped in {conf_backup_folder}.",
"migration_0011_LDAP_update_failed": "Could not update LDAP. Error: {error:s}",
"migration_0011_migrate_permission": "Migrating permissions from apps settings to LDAP…",
"migration_0011_migration_failed_trying_to_rollback": "Migration failed… trying to roll back the system.",
"migration_0011_migration_failed_trying_to_rollback": "Could not migrate… trying to roll back the system.",
"migration_0011_rollback_success": "System rolled back.",
"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}",
"migrations_already_ran": "Those migrations are already done: {ids}",
"migrations_cant_reach_migration_file": "Could not access migrations files at path %s",
"migrations_dependencies_not_satisfied": "Cannot run migration {id} because first you need to run these migrations: {dependencies_id}",
"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}.",
"migrations_failed_to_load_migration": "Could not load migration {id}: {error}",
"migrations_exclusive_options": "'--auto', '--skip', and '--force-rerun' are mutually exclusive options.",
"migrations_list_conflict_pending_done": "You cannot use both '--previous' and '--done' at the same time.",
@ -365,73 +468,51 @@
"migrations_must_provide_explicit_targets": "You must provide explicit targets when using '--skip' or '--force-rerun'",
"migrations_need_to_accept_disclaimer": "To run the migration {id}, your must accept the following disclaimer:\n---\n{disclaimer}\n---\nIf you accept to run the migration, please re-run the command with the option '--accept-disclaimer'.",
"migrations_no_migrations_to_run": "No migrations to run",
"migrations_no_such_migration": "There is no migration called {id}",
"migrations_no_such_migration": "There is no migration called '{id}'",
"migrations_not_pending_cant_skip": "Those migrations are not pending, so cannot be skipped: {ids}",
"migrations_pending_cant_rerun": "Those migrations are still pending, so cannot be run again: {ids}",
"migrations_running_forward": "Running migration {id}…",
"migrations_skip_migration": "Skipping migration {id}…",
"migrations_success_forward": "Migration {id} completed",
"migrations_to_be_ran_manually": "Migration {id} has to be run manually. Please go to Tools → Migrations on the webadmin page, or run `yunohost tools migrations migrate`.",
"monitor_disabled": "Server monitoring now turned off",
"monitor_enabled": "Server monitoring now turned on",
"monitor_glances_con_failed": "Could not connect to Glances server",
"monitor_not_enabled": "Server monitoring is off",
"monitor_period_invalid": "Invalid time period",
"monitor_stats_file_not_found": "Statistics file not found",
"monitor_stats_no_update": "No monitoring statistics to update",
"monitor_stats_period_unavailable": "No available statistics for the period",
"mountpoint_unknown": "Unknown mountpoint",
"mysql_db_creation_failed": "MySQL database creation failed",
"mysql_db_init_failed": "MySQL database init failed",
"mysql_db_initialized": "The MySQL database now initialized",
"need_define_permission_before": "Redefine the permission using 'yunohost user permission add -u USER' before removing an allowed group",
"network_check_mx_ko": "DNS MX record is not set",
"network_check_smtp_ko": "Outbound e-mail (SMTP port 25) seems to be blocked by your network",
"network_check_smtp_ok": "Outbound e-mail (SMTP port 25) is not blocked",
"no_internet_connection": "Server not connected to the Internet",
"no_internet_connection": "The server is not connected to the Internet",
"not_enough_disk_space": "Not enough free space on '{path:s}'",
"operation_interrupted": "The operation was manually interrupted?",
"package_not_installed": "Package '{pkgname}' is not installed",
"package_unexpected_error": "An unexpected error occurred processing the package '{pkgname}'",
"package_unknown": "Unknown package '{pkgname}'",
"packages_upgrade_failed": "Could not upgrade all the packages",
"password_listed": "This password is among the most used password in the world. Please choose something more unique.",
"password_listed": "This password is among the most used passwords in the world. Please choose something more unique.",
"password_too_simple_1": "The password needs to be at least 8 characters long",
"password_too_simple_2": "The password needs to be at least 8 characters long and contain a digit, upper and lower characters",
"password_too_simple_3": "The password needs to be at least 8 characters long and contain a digit, upper, lower and special characters",
"password_too_simple_4": "The password needs to be at least 12 characters long and contain a digit, upper, lower and special characters",
"pattern_backup_archive_name": "Must be a valid filename with max 30 characters, alphanumeric and -_. characters only",
"pattern_domain": "Must be a valid domain name (e.g. my-domain.org)",
"pattern_email": "Must be a valid email address (e.g. someone@domain.org)",
"pattern_email": "Must be a valid e-mail address (e.g. someone@example.com)",
"pattern_firstname": "Must be a valid first name",
"pattern_lastname": "Must be a valid last name",
"pattern_listname": "Must be alphanumeric and underscore characters only",
"pattern_mailbox_quota": "Must be a size with b/k/M/G/T suffix or 0 to not have a quota",
"pattern_password": "Must be at least 3 characters long",
"pattern_port": "Must be a valid port number (i.e. 0-65535)",
"pattern_port_or_range": "Must be a valid port number (i.e. 0-65535) or range of ports (e.g. 100:200)",
"pattern_positive_number": "Must be a positive number",
"pattern_username": "Must be lower-case alphanumeric and underscore characters only",
"pattern_password_app": "Sorry, passwords can not contain the following characters: {forbidden_chars}",
"permission_already_clear": "Permission '{permission:s}' already clear for app {app:s}",
"permission_already_exist": "Permission '{permission:s}' for app {app:s} already exist",
"permission_created": "Permission '{permission:s}' for app {app:s} created",
"permission_creation_failed": "Could not grant permission",
"permission_deleted": "Permission '{permission:s}' for app {app:s} deleted",
"permission_deletion_failed": "Missing permission '{permission:s}' to delete the app '{app:s}'",
"permission_not_found": "Permission '{permission:s}' not found for the application '{app:s}'",
"permission_name_not_valid": "Pick an allowed permission name for '{permission:s}'",
"permission_update_failed": "Could not update permission",
"permission_generated": "Permission database updated",
"permission_updated": "Permission '{permission:s}' for the app '{app:s}' updated",
"permission_already_allowed": "Group '{group}' already has permission '{permission}' enabled",
"permission_already_disallowed": "Group '{group}' already has permission '{permission}' disabled",
"permission_already_exist": "Permission '{permission}' already exists",
"permission_already_up_to_date": "The permission was not updated because the addition/removal requests already match the current state.",
"permission_cannot_remove_main": "Removing a main permission is not allowed",
"permission_created": "Permission '{permission:s}' created",
"permission_creation_failed": "Could not create permission '{permission}': {error}",
"permission_currently_allowed_for_all_users": "This permission is currently granted to all users in addition to other groups. You probably want to either remove the 'all_users' permission or remove the other groups it is currently granted to.",
"permission_deleted": "Permission '{permission:s}' deleted",
"permission_deletion_failed": "Could not delete permission '{permission}': {error}",
"permission_not_found": "Permission '{permission:s}' not found",
"permission_update_failed": "Could not update permission '{permission}': {error}",
"permission_updated": "Permission '{permission:s}' updated",
"permission_update_nothing_to_do": "No permissions to update",
"permission_require_account": "Permission {permission} only makes sense for users having an account, and therefore cannot be enabled for visitors.",
"port_already_closed": "Port {port:d} is already closed for {ip_version:s} connections",
"port_already_opened": "Port {port:d} is already opened for {ip_version:s} connections",
"port_available": "Port {port:d} is available",
"port_unavailable": "Port {port:d} is not available",
"recommend_to_add_first_user": "The post-install is finished, but YunoHost needs at least one user to work correctly, you should add one using 'yunohost user create <username>' or do it from the admin interface.",
"remove_main_permission_not_allowed": "Removing the main permission is not allowed",
"remove_user_of_group_not_allowed": "You are not allowed to remove the user '{user:s}' in the group '{group:s}'",
"regenconf_file_backed_up": "Configuration file '{conf}' backed up to '{backup}'",
"regenconf_file_copy_failed": "Could not copy the new configuration file '{new}' to '{conf}'",
"regenconf_file_kept_back": "The configuration file '{conf}' is expected to be deleted by regen-conf (category {category}) but was kept back.",
@ -442,7 +523,7 @@
"regenconf_file_updated": "Configuration file '{conf}' updated",
"regenconf_now_managed_by_yunohost": "The configuration file '{conf}' is now managed by YunoHost (category {category}).",
"regenconf_up_to_date": "The configuration is already up-to-date for category '{category}'",
"regenconf_updated": "Configuration for category '{category}' updated",
"regenconf_updated": "Configuration updated for '{category}'",
"regenconf_would_be_updated": "The configuration would have been updated for category '{category}'",
"regenconf_dry_pending_applying": "Checking pending configuration which would have been applied for category '{category}'…",
"regenconf_failed": "Could not regenerate the configuration for category(s): {categories}",
@ -454,8 +535,8 @@
"restore_confirm_yunohost_installed": "Do you really want to restore an already installed system? [{answers:s}]",
"restore_extracting": "Extracting needed files from the archive…",
"restore_failed": "Could not restore system",
"restore_hook_unavailable": "The restoration script for '{part:s}' not available on your system and not in the archive either",
"restore_may_be_not_enough_disk_space": "Your system seems does not have enough space (free: {free_space:d} B, needed space: {needed_space:d} B, security margin: {margin:d} B)",
"restore_hook_unavailable": "Restoration script for '{part:s}' not available on your system and not in the archive either",
"restore_may_be_not_enough_disk_space": "Your system does not seem to have enough space (free: {free_space:d} B, needed space: {needed_space:d} B, security margin: {margin:d} B)",
"restore_not_enough_disk_space": "Not enough space (space: {free_space:d} B, needed space: {needed_space:d} B, security margin: {margin:d} B)",
"restore_nothings_done": "Nothing was restored",
"restore_removing_tmp_dir_failed": "Could not remove an old temporary directory",
@ -469,96 +550,86 @@
"server_reboot": "The server will reboot",
"server_reboot_confirm": "The server will reboot immediatly, are you sure? [{answers:s}]",
"service_add_failed": "Could not add the service '{service:s}'",
"service_added": "The service '{service:s}' added",
"service_already_started": "The service '{service:s}' has already been started",
"service_added": "The service '{service:s}' was added",
"service_already_started": "The service '{service:s}' is running already",
"service_already_stopped": "The service '{service:s}' has already been stopped",
"service_cmd_exec_failed": "Could not execute the command '{command:s}'",
"service_description_avahi-daemon": "Allows you to reach your server using 'yunohost.local' in your local network",
"service_description_dnsmasq": "Handles domain name resolution (DNS)",
"service_description_dovecot": "Allows e-mail clients to access/fetch email (via IMAP and POP3)",
"service_description_fail2ban": "Protects against brute-force and other kinds of attacks from the Internet",
"service_description_glances": "Monitors system info on your server",
"service_description_metronome": "Manage XMPP instant messaging accounts",
"service_description_mysql": "Stores applications data (SQL database)",
"service_description_mysql": "Stores app data (SQL database)",
"service_description_nginx": "Serves or provides access to all the websites hosted on your server",
"service_description_nslcd": "Handles YunoHost user shell connection",
"service_description_php7.0-fpm": "Runs applications written in PHP with NGINX",
"service_description_php7.0-fpm": "Runs apps written in PHP with NGINX",
"service_description_postfix": "Used to send and receive e-mails",
"service_description_redis-server": "A specialized database used for rapid data access, task queue, and communication between programs",
"service_description_rmilter": "Checks various parameters in e-mails",
"service_description_rspamd": "Filters spam, and other e-mail related features",
"service_description_slapd": "Stores users, domains and related info",
"service_description_ssh": "Allows you to connect remotely to your server via a terminal (SSH protocol)",
"service_description_yunohost-api": "Manages interactions between the YunoHost web interface and the system",
"service_description_yunohost-firewall": "Manages open and close connexion ports to services",
"service_disable_failed": "Could not turn off the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_disabled": "'{service:s}' service turned off",
"service_enable_failed": "Could not turn on the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_enabled": "'{service:s}' service turned off",
"service_no_log": "No log to display for service '{service:s}'",
"service_description_yunohost-firewall": "Manages open and close connection ports to services",
"service_disable_failed": "Could not make the service '{service:s}' not start at boot.\n\nRecent service logs:{logs:s}",
"service_disabled": "The service '{service:s}' will not be started anymore when system boots.",
"service_enable_failed": "Could not make the service '{service:s}' automatically start at boot.\n\nRecent service logs:{logs:s}",
"service_enabled": "The service '{service:s}' will now be automatically started during system boots.",
"service_regen_conf_is_deprecated": "'yunohost service regen-conf' is deprecated! Please use 'yunohost tools regen-conf' instead.",
"service_remove_failed": "Could not remove the service '{service:s}'",
"service_removed": "'{service:s}' service removed",
"service_removed": "Service '{service:s}' removed",
"service_reload_failed": "Could not reload the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_reloaded": "'{service:s}' service reloaded",
"service_reloaded": "Service '{service:s}' reloaded",
"service_restart_failed": "Could not restart the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_restarted": "'{service:s}' service restarted",
"service_restarted": "Service '{service:s}' restarted",
"service_reload_or_restart_failed": "Could not reload or restart the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_reloaded_or_restarted": "'{service:s}' service reloaded or restarted",
"service_reloaded_or_restarted": "The service '{service:s}' was reloaded or restarted",
"service_start_failed": "Could not start the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_started": "'{service:s}' service started",
"service_started": "Service '{service:s}' started",
"service_stop_failed": "Could not stop the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_stopped": "'{service:s}' service stopped",
"service_stopped": "Service '{service:s}' stopped",
"service_unknown": "Unknown service '{service:s}'",
"ssowat_conf_generated": "SSOwat configuration generated",
"ssowat_conf_updated": "SSOwat configuration updated",
"ssowat_persistent_conf_read_error": "Could not read persistent SSOwat configuration: {error:s}. Edit /etc/ssowat/conf.json.persistent file to fix the JSON syntax",
"ssowat_persistent_conf_write_error": "Could not save persistent SSOwat configuration: {error:s}. Edit /etc/ssowat/conf.json.persistent file to fix the JSON syntax",
"system_groupname_exists": "Groupname already exists in the system group",
"system_upgraded": "System upgraded",
"system_username_exists": "Username already exists in the list of system users",
"this_action_broke_dpkg": "This action broke dpkg/APT (the system package managers)… You can try to solve this issue by connecting through SSH and running `sudo dpkg --configure -a`.",
"tools_update_failed_to_app_fetchlist": "Could not update YunoHost's applists because: {error}",
"tools_upgrade_at_least_one": "Please specify '--apps', or '--system'",
"tools_upgrade_cant_both": "Cannot upgrade both system and apps at the same time",
"tools_upgrade_cant_hold_critical_packages": "Could not hold critical packages…",
"tools_upgrade_cant_unhold_critical_packages": "Could not to unhold critical packages…",
"tools_upgrade_cant_unhold_critical_packages": "Could not unhold critical packages…",
"tools_upgrade_regular_packages": "Now upgrading 'regular' (non-yunohost-related) packages…",
"tools_upgrade_regular_packages_failed": "Could not upgrade packages: {packages_list}",
"tools_upgrade_special_packages": "Now upgrading 'special' (yunohost-related) packages…",
"tools_upgrade_special_packages_explanation": "This action will end, but the actual special upgrade will continue in background. Please don't start any other action on your server in the next ~10 minutes (depending on your hardware speed). Once it i done, you may have to log in on the webadmin page again. The upgrade log will be available in Tools → Log (on the webadmin page) or through 'yunohost log list' (from the command line).",
"tools_upgrade_special_packages_explanation": "The special upgrade will continue in the background. Please don't start any other actions on your server for the next ~10 minutes (depending on hardware speed). After this, you may have to re-log in to the webadmin. The upgrade log will be available in Tools → Log (in the webadmin) or using 'yunohost log list' (from the command-line).",
"tools_upgrade_special_packages_completed": "YunoHost package upgrade completed.\nPress [Enter] to get the command line back",
"unbackup_app": "App '{app:s}' will not be saved",
"unexpected_error": "Something unexpected went wrong: {error}",
"unit_unknown": "Unknown unit '{unit:s}'",
"unlimit": "No quota",
"unrestore_app": "App '{app:s}' will not be restored",
"update_apt_cache_failed": "Could not to update the cache of APT (Debian's package manager). Here is a dump of the sources.list lines, which might help identify problematic lines: \n{sourceslist}",
"update_apt_cache_warning": "Something went wrong while updating the cache of APT (Debian's package manager). Here is a dump of the sources.list lines, which might help identify problematic lines: \n{sourceslist}",
"updating_apt_cache": "Fetching available upgrades for system packages…",
"updating_app_lists": "Fetching available upgrades for applications…",
"upgrade_complete": "Upgrade complete",
"upgrading_packages": "Upgrading packages…",
"upnp_dev_not_found": "No UPnP device found",
"upnp_disabled": "UPnP turned off",
"upnp_enabled": "UPnP turned on",
"upnp_port_open_failed": "Could not open port via UPnP",
"user_already_in_group": "The user '{user:}' is already in the '{group:s}' group",
"user_already_exists": "The user '{user}' already exists",
"user_created": "User created",
"user_creation_failed": "Could not create user",
"user_creation_failed": "Could not create user {user}: {error}",
"user_deleted": "User deleted",
"user_deletion_failed": "Could not delete user",
"user_deletion_failed": "Could not delete user {user}: {error}",
"user_home_creation_failed": "Could not create 'home' folder for user",
"user_info_failed": "Could not retrieve user info",
"user_not_in_group": "The user '{user:s}' is not in the group {group:s}",
"user_unknown": "Unknown user: {user:s}",
"user_update_failed": "Could not change user info",
"user_update_failed": "Could not update user {user}: {error}",
"user_updated": "User info changed",
"users_available": "Available users:",
"yunohost_already_installed": "YunoHost is already installed",
"yunohost_ca_creation_failed": "Could not create certificate authority",
"yunohost_ca_creation_success": "Local certification authority created.",
"yunohost_configured": "YunoHost now configured",
"yunohost_configured": "YunoHost is now configured",
"yunohost_installing": "Installing YunoHost…",
"yunohost_not_installed": "YunoHost is incorrectly or not correctly installed. Please run 'yunohost tools postinstall'"
"yunohost_not_installed": "YunoHost is not correctly installed. Please run 'yunohost tools postinstall'",
"yunohost_postinstall_end_tip": "The post-install completed! To finalize your setup, please consider:\n - adding a first user through the 'Users' section of the webadmin (or 'yunohost user create <username>' in command-line);\n - diagnose potential issues through the 'Diagnosis' section of the webadmin (or 'yunohost diagnosis run' in command-line);\n - reading the 'Finalizing your setup' and 'Getting to know Yunohost' parts in the admin documentation: https://yunohost.org/admindoc."
}

View file

@ -1,43 +1,595 @@
{
"admin_password_change_failed": "Malebla ŝanĝi pasvorton",
"admin_password_changed": "Pasvorto de la estro estas ŝanĝita",
"admin_password_change_failed": "Ne eblas ŝanĝi pasvorton",
"admin_password_changed": "La pasvorto de administrado ŝanĝiĝis",
"app_already_installed": "{app:s} estas jam instalita",
"app_already_up_to_date": "{app:s} estas ĝisdata",
"app_already_up_to_date": "{app:s} estas jam ĝisdata",
"app_argument_required": "Parametro {name:s} estas bezonata",
"app_change_url_identical_domains": "Malnovaj kaj novaj domajno/URL estas la sama ('{domain:s}{path:s}'), nenio fareblas.",
"app_change_url_success": "URL de appo {app:s} ŝanĝita al {domain:s}{path:s}",
"app_extraction_failed": "Malebla malkompaktigi instaldosierojn",
"app_id_invalid": "Nevalida apo id",
"app_incompatible": "Apo {app} ne estas kongrua kun via YunoHost versio",
"app_install_files_invalid": "Nevalidaj instaldosieroj",
"app_location_already_used": "Apo {app} jam estas instalita al tiu loco ({path})",
"user_updated": "Uzanto estas ĝisdatita",
"app_change_url_success": "{app:s} URL nun estas {domain:s} {path:s}",
"app_extraction_failed": "Ne povis ĉerpi la instalajn dosierojn",
"app_id_invalid": "Nevalida apo ID",
"app_install_files_invalid": "Ĉi tiuj dosieroj ne povas esti instalitaj",
"user_updated": "Uzantinformoj ŝanĝis",
"users_available": "Uzantoj disponeblaj :",
"yunohost_already_installed": "YunoHost estas jam instalita",
"yunohost_ca_creation_failed": "Ne eblas krei atestan aŭtoritaton",
"yunohost_ca_creation_success": "Loka atesta aŭtoritato estas kreita.",
"yunohost_ca_creation_failed": "Ne povis krei atestan aŭtoritaton",
"yunohost_ca_creation_success": "Loka atestila aŭtoritato kreiĝis.",
"yunohost_installing": "Instalante YunoHost…",
"service_description_glances": "monitoras sisteminformojn de via servilo",
"service_description_metronome": "mastrumas XMPP tujmesaĝilon kontojn",
"service_description_mysql": "stokas aplikaĵojn datojn (SQL datumbazo)",
"service_description_nginx": "servas aŭ permesas atingi ĉiujn retejojn gastigita sur via servilo",
"service_description_nslcd": "mastrumas Yunohost uzantojn konektojn per komanda linio",
"service_description_php7.0-fpm": "rulas aplikaĵojn skibita en PHP kun nginx",
"service_description_postfix": "uzita por sendi kaj ricevi retpoŝtojn",
"service_description_redis-server": "specialita datumbazo uzita por rapida datumo atingo, atendovicoj kaj komunikadoj inter programoj",
"service_description_rmilter": "kontrolas diversajn parametrojn en retpoŝtoj",
"service_description_rspamd": "filtras trudmesaĝojn, kaj aliaj funkcioj rilate al retpoŝto",
"service_description_slapd": "stokas uzantojn, domajnojn kaj rilatajn informojn",
"service_description_ssh": "permesas al vi konekti al via servilo kun fora terminalo (SSH protokolo)",
"service_description_yunohost-api": "mastrumas interagojn inter la YunoHost retinterfaco kaj la sistemo",
"service_description_yunohost-firewall": "mastrumas malfermitajn kaj fermitajn konektejojn al servoj",
"service_disable_failed": "Neebla malaktivigi servon '{service:s}'\n\nFreŝaj protokoloj de la servo : {logs:s}",
"service_disabled": "Servo '{service:s}' estas malaktivigita",
"service_description_metronome": "Mastrumas XMPP tujmesaĝilon kontojn",
"service_description_mysql": "Butikigas datumojn de programoj (SQL datumbazo)",
"service_description_nginx": "Servas aŭ permesas atingi ĉiujn retejojn gastigita sur via servilo",
"service_description_nslcd": "Mastrumas Yunohost uzantojn konektojn per komanda linio",
"service_description_php7.0-fpm": "Ekzekutas programojn skribitajn en PHP kun NGINX",
"service_description_postfix": "Uzita por sendi kaj ricevi retpoŝtojn",
"service_description_redis-server": "Specialita datumbazo uzita por rapida datumo atingo, atendovicoj kaj komunikadoj inter programoj",
"service_description_rspamd": "Filtras trudmesaĝojn, kaj aliaj funkcioj rilate al retpoŝto",
"service_description_slapd": "Stokas uzantojn, domajnojn kaj rilatajn informojn",
"service_description_ssh": "Permesas al vi konekti al via servilo kun fora terminalo (SSH protokolo)",
"service_description_yunohost-api": "Mastrumas interagojn inter la YunoHost retinterfaco kaj la sistemo",
"service_description_yunohost-firewall": "Administras malfermajn kaj fermajn konektajn havenojn al servoj",
"service_disable_failed": "Ne povis fari la servon '{service:s}' ne komenci ĉe la ekkuro.\n\nLastatempaj servaj protokoloj: {logs:s}",
"service_disabled": "La servo '{service:s}' ne plu komenciĝos kiam sistemo ekos.",
"action_invalid": "Nevalida ago « {action:s} »",
"admin_password": "Pasvorto de la estro",
"admin_password_too_long": "Bonvolu elekti pasvorton pli mallonga ol 127 signoj",
"already_up_to_date": "Neniu estas farenda! Ĉiu jam estas ĝisdata!",
"app_argument_choice_invalid": "Nevalida elekto por argumento « {name:s} », ĝi devas esti unu el {choices:s}",
"app_argument_invalid": "Nevalida valoro por argumento « {name:s} » : {error:s}",
"app_change_url_failed_nginx_reload": "Reŝargi nginx malsuksesis. Jen la eligo de « nginx -t » :\n{nginx_errors:s}"
"already_up_to_date": "Nenio por fari. Ĉio estas jam ĝisdatigita.",
"app_argument_choice_invalid": "Uzu unu el ĉi tiuj elektoj '{choices:s}' por la argumento '{name:s}'",
"app_argument_invalid": "Elektu validan valoron por la argumento '{name:s}': {error:s}",
"app_change_url_failed_nginx_reload": "Ne eblis reŝarĝi NGINX. Jen la eligo de 'nginx -t':\n{nginx_errors:s}",
"ask_new_admin_password": "Nova administrada pasvorto",
"app_action_broke_system": "Ĉi tiu ago ŝajne rompis ĉi tiujn gravajn servojn: {services}",
"app_unsupported_remote_type": "Malkontrolita fora speco uzita por la apliko",
"backup_archive_system_part_not_available": "Sistemo parto '{part:s}' ne haveblas en ĉi tiu rezervo",
"backup_abstract_method": "Ĉi tiu rezerva metodo ankoraŭ efektiviĝis",
"apps_already_up_to_date": "Ĉiuj aplikoj estas jam ĝisdatigitaj",
"backup_borg_not_implemented": "La kopia metodo de Borg ankoraŭ ne estas efektivigita",
"app_location_unavailable": "Ĉi tiu URL aŭ ne haveblas, aŭ konfliktas kun la jam instalita (j) apliko (j):\n{apps:s}",
"backup_archive_app_not_found": "Ne povis trovi la programon '{app:s}' en la rezerva ar archiveivo",
"backup_actually_backuping": "Krei rezervan ar archiveivon el la kolektitaj dosieroj …",
"backup_method_borg_finished": "Sekurkopio en Borg finiĝis",
"app_change_url_no_script": "La app '{app_name:s}' ankoraŭ ne subtenas URL-modifon. Eble vi devus altgradigi ĝin.",
"app_start_install": "Instali la programon '{app}' …",
"backup_created": "Sekurkopio kreita",
"app_make_default_location_already_used": "Ne povas igi la aplikon '{app}' defaŭlta sur la domajno, '{domain}' jam uziĝas de la alia app '{other_app}'",
"backup_method_copy_finished": "Rezerva kopio finis",
"app_not_properly_removed": "{app:s} ne estis ĝuste forigita",
"backup_archive_broken_link": "Ne povis aliri la rezervan ar archiveivon (rompita ligilo al {path:s})",
"app_requirements_checking": "Kontrolante postulatajn pakaĵojn por {app} …",
"app_not_installed": "Ne povis trovi la aplikon '{app:s}' en la listo de instalitaj programoj: {all_apps}",
"ask_new_path": "Nova vojo",
"backup_custom_mount_error": "Propra rezerva metodo ne povis preterpasi la paŝon 'monto'",
"app_upgrade_app_name": "Nun ĝisdatiganta {app} …",
"app_manifest_invalid": "Io misas pri la aplika manifesto: {error}",
"backup_cleaning_failed": "Ne povis purigi la provizoran rezervan dosierujon",
"backup_invalid_archive": "Ĉi tio ne estas rezerva ar archiveivo",
"backup_creation_failed": "Ne povis krei la rezervan ar archiveivon",
"backup_hook_unknown": "La rezerva hoko '{hook:s}' estas nekonata",
"backup_custom_backup_error": "Propra rezerva metodo ne povis preterpasi la paŝon \"sekurkopio\"",
"ask_main_domain": "Ĉefa domajno",
"backup_method_tar_finished": "TAR-rezerva ar archiveivo kreita",
"backup_cant_mount_uncompress_archive": "Ne povis munti la nekompresitan ar archiveivon kiel protektita kontraŭ skribo",
"app_action_cannot_be_ran_because_required_services_down": "Ĉi tiuj postulataj servoj devas funkcii por funkciigi ĉi tiun agon: {services}. Provu rekomenci ilin por daŭrigi (kaj eble esploru, kial ili malsupreniras).",
"backup_copying_to_organize_the_archive": "Kopiante {size:s} MB por organizi la ar archiveivon",
"backup_output_directory_forbidden": "Elektu malsaman elirejan dosierujon. Sekurkopioj ne povas esti kreitaj en sub-dosierujoj / bin, / boot, / dev, / ktp, / lib, / root, / run, / sbin, / sys, / usr, / var aŭ /home/yunohost.backup/archives",
"backup_no_uncompress_archive_dir": "Ne ekzistas tia nekompremita arkiva dosierujo",
"password_too_simple_1": "Pasvorto devas esti almenaŭ 8 signojn longa",
"app_upgrade_failed": "Ne povis ĝisdatigi {app:s}: {error}",
"app_upgrade_several_apps": "La sekvaj apliko estos altgradigitaj: {apps}",
"backup_archive_open_failed": "Ne povis malfermi la rezervan ar archiveivon",
"ask_lastname": "Familia nomo",
"app_start_backup": "Kolekti dosierojn por esti subtenata por la '{app}' …",
"backup_archive_name_exists": "Rezerva arkivo kun ĉi tiu nomo jam ekzistas.",
"backup_applying_method_tar": "Krei la rezervan TAR-ar archiveivon …",
"backup_method_custom_finished": "Propra rezerva metodo '{method:s}' finiĝis",
"app_already_installed_cant_change_url": "Ĉi tiu app estas jam instalita. La URL ne povas esti ŝanĝita nur per ĉi tiu funkcio. Rigardu \"app changeurl\" se ĝi haveblas.",
"app_not_correctly_installed": "{app:s} ŝajnas esti malĝuste instalita",
"app_removed": "{app:s} forigita",
"backup_delete_error": "Ne povis forigi '{path:s}'",
"backup_nothings_done": "Nenio por ŝpari",
"backup_applying_method_custom": "Nomante la kutiman rezervan metodon '{method:s}' …",
"backup_app_failed": "Ne eblis rezervi la programon '{app:s}'",
"app_upgrade_some_app_failed": "Iuj aplikoj ne povis esti altgradigitaj",
"app_start_remove": "Forigo de la apliko '{app}' …",
"backup_output_directory_not_empty": "Vi devas elekti malplenan eligitan dosierujon",
"backup_archive_writing_error": "Ne povis aldoni la dosierojn '{source:s}' (nomitaj en la ar theivo '{dest:s}') por esti rezervitaj en la kunpremita arkivo '{archive:s}'",
"ask_email": "Retpoŝta adreso",
"app_start_restore": "Restarigi la programon '{app}' …",
"backup_applying_method_copy": "Kopiante ĉiujn dosierojn al sekurkopio …",
"backup_couldnt_bind": "Ne povis ligi {src:s} al {dest:s}.",
"ask_password": "Pasvorto",
"app_requirements_unmeet": "Postuloj ne estas renkontitaj por {app}, la pakaĵo {pkgname} ({version}) devas esti {spec}",
"ask_firstname": "Antaŭnomo",
"backup_ask_for_copying_if_needed": "Ĉu vi volas realigi la sekurkopion uzante {size:s} MB provizore? (Ĉi tiu maniero estas uzata ĉar iuj dosieroj ne povus esti pretigitaj per pli efika metodo.)",
"backup_mount_archive_for_restore": "Preparante arkivon por restarigo …",
"backup_csv_creation_failed": "Ne povis krei la CSV-dosieron bezonatan por restarigo",
"backup_archive_name_unknown": "Nekonata loka rezerva ar archiveivo nomata '{name:s}'",
"backup_applying_method_borg": "Sendado de ĉiuj dosieroj al sekurkopio en borg-rezerva deponejo …",
"app_sources_fetch_failed": "Ne povis akiri fontajn dosierojn, ĉu la URL estas ĝusta?",
"ask_new_domain": "Nova domajno",
"app_unknown": "Nekonata apliko",
"app_not_upgraded": "La aplikaĵo '{failed_app}' ne ĝisdatigis, kaj pro tio la sekvaj ĝisdatigoj de aplikoj estis nuligitaj: {apps}",
"aborting": "Aborti.",
"app_upgraded": "{app:s} altgradigita",
"backup_deleted": "Rezerva forigita",
"backup_csv_addition_failed": "Ne povis aldoni dosierojn al sekurkopio en la CSV-dosiero",
"dpkg_lock_not_available": "Ĉi tiu komando ne povas funkcii nun ĉar alia programo uzas la seruron de dpkg (la administrilo de paka sistemo)",
"migration_0003_yunohost_upgrade": "Komenci la ĝisdatigon de YunoHost-pako ... La migrado finiĝos, sed la efektiva ĝisdatigo okazos tuj poste. Post kiam la operacio finiĝos, vi eble devos ensaluti denove sur la retpaĝo.",
"domain_dyndns_root_unknown": "Nekonata radika domajno DynDNS",
"field_invalid": "Nevalida kampo '{:s}'",
"log_app_makedefault": "Faru '{}' la defaŭlta apliko",
"migration_0003_still_on_jessie_after_main_upgrade": "Io okazis malbone dum la ĉefa ĝisdatigo: Ĉu la sistemo ankoraŭ estas en Jessie‽ Por esplori la aferon, bonvolu rigardi {log}:s …",
"migration_0011_can_not_backup_before_migration": "La sekurkopio de la sistemo ne povis finiĝi antaŭ ol la migrado malsukcesis. Eraro: {error:s}",
"migration_0011_create_group": "Krei grupon por ĉiu uzanto…",
"backup_system_part_failed": "Ne eblis sekurkopi la sistemon de '{part:s}'",
"global_settings_setting_security_postfix_compatibility": "Kongruo vs sekureca kompromiso por la Postfix-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
"group_unknown": "La grupo '{group:s}' estas nekonata",
"mailbox_disabled": "Retpoŝto malŝaltita por uzanto {user:s}",
"migration_description_0011_setup_group_permission": "Agordu uzantogrupon kaj starigu permeson por programoj kaj servoj",
"migration_0011_backup_before_migration": "Krei sekurkopion de LDAP-datumbazo kaj agordojn antaŭ la efektiva migrado.",
"migration_0011_migrate_permission": "Migrado de permesoj de agordoj al aplikoj al LDAP…",
"migration_0011_migration_failed_trying_to_rollback": "Ne povis migri ... provante redakti la sistemon.",
"migrations_dependencies_not_satisfied": "Rulu ĉi tiujn migradojn: '{dependencies_id}', antaŭ migrado {id}.",
"migrations_failed_to_load_migration": "Ne povis ŝarĝi migradon {id}: {error}",
"migrations_exclusive_options": "'--auto', '--skip' kaj '--force-rerun' estas reciproke ekskluzivaj ebloj.",
"migrations_must_provide_explicit_targets": "Vi devas provizi eksplicitajn celojn kiam vi uzas '--skip' aŭ '--force-rerun'",
"permission_update_failed": "Ne povis ĝisdatigi permeson '{permission}': {error}",
"permission_updated": "Ĝisdatigita \"{permission:s}\" rajtigita",
"permission_update_nothing_to_do": "Neniuj permesoj ĝisdatigi",
"tools_upgrade_cant_hold_critical_packages": "Ne povis teni kritikajn pakojn…",
"upnp_dev_not_found": "Neniu UPnP-aparato trovita",
"migration_description_0012_postgresql_password_to_md5_authentication": "Devigu PostgreSQL-aŭtentigon uzi MD5 por lokaj ligoj",
"migration_0011_done": "Migrado finiĝis. Vi nun kapablas administri uzantajn grupojn.",
"migration_0011_LDAP_update_failed": "Ne povis ĝisdatigi LDAP. Eraro: {error:s}",
"pattern_password": "Devas esti almenaŭ 3 signoj longaj",
"root_password_desynchronized": "La pasvorta administranto estis ŝanĝita, sed YunoHost ne povis propagandi ĉi tion al la radika pasvorto!",
"service_remove_failed": "Ne povis forigi la servon '{service:s}'",
"migration_0003_fail2ban_upgrade": "Komenci la ĝisdatigon Fail2Ban…",
"backup_permission": "Rezerva permeso por app {app:s}",
"log_user_group_delete": "Forigi grupon '{}'",
"log_user_group_update": "Ĝisdatigi grupon '{}'",
"migration_0005_postgresql_94_not_installed": "PostgreSQL ne estis instalita en via sistemo. Nenio por fari.",
"dyndns_provider_unreachable": "Ne povas atingi Dyndns-provizanton {provider}: ĉu via YunoHost ne estas ĝuste konektita al la interreto aŭ la dynette-servilo malŝaltiĝas.",
"good_practices_about_user_password": "Vi nun estas por difini novan uzantan pasvorton. La pasvorto devas esti almenaŭ 8 signoj - kvankam estas bone praktiki uzi pli longan pasvorton (t.e. pasfrazon) kaj / aŭ variaĵon de signoj (majuskloj, minuskloj, ciferoj kaj specialaj signoj).",
"group_updated": "Ĝisdatigita \"{group}\" grupo",
"group_already_exist": "Grupo {group} jam ekzistas",
"group_already_exist_on_system": "Grupo {group} jam ekzistas en la sistemaj grupoj",
"group_cannot_be_deleted": "La grupo {group} ne povas esti forigita permane.",
"group_update_failed": "Ne povis ĝisdatigi la grupon '{group}': {error}",
"group_user_already_in_group": "Uzanto {user} jam estas en grupo {group}",
"group_user_not_in_group": "Uzanto {user} ne estas en grupo {group}",
"installation_complete": "Kompleta instalado",
"log_category_404": "La loga kategorio '{category}' ne ekzistas",
"log_permission_create": "Krei permeson '{}'",
"log_permission_delete": "Forigi permeson '{}'",
"log_user_group_create": "Krei grupon '{}'",
"log_user_permission_update": "Mise à jour des accès pour la permission '{}'",
"log_user_permission_reset": "Restarigi permeson '{}'",
"mail_forward_remove_failed": "Ne povis forigi retpoŝton plusendante '{mail:s}'",
"migration_0011_rollback_success": "Sistemo ruliĝis reen.",
"migration_0011_update_LDAP_database": "Ĝisdatigante LDAP-datumbazon…",
"migration_0011_update_LDAP_schema": "Ĝisdatigante LDAP-skemon…",
"migration_0011_failed_to_remove_stale_object": "Ne povis forigi neuzatan objekton {dn}: {error}",
"migrations_already_ran": "Tiuj migradoj estas jam faritaj: {ids}",
"migrations_no_such_migration": "Estas neniu migrado nomata '{id}'",
"permission_already_allowed": "Grupo '{group}' jam havas rajtigitan permeson '{permission}'",
"permission_already_disallowed": "Grupo '{group}' jam havas permeson '{permission}' malebligita'",
"permission_cannot_remove_main": "Forigo de ĉefa permeso ne rajtas",
"permission_creation_failed": "Ne povis krei permeson '{permission}': {error}",
"user_already_exists": "La uzanto '{user}' jam ekzistas",
"migrations_pending_cant_rerun": "Tiuj migradoj ankoraŭ estas pritraktataj, do ne plu rajtas esti ekzekutitaj: {ids}",
"migrations_running_forward": "Kuranta migrado {id}…",
"migrations_success_forward": "Migrado {id} kompletigita",
"operation_interrupted": "La operacio estis permane interrompita?",
"permission_created": "Permesita '{permission:s}' kreita",
"permission_deleted": "Permesita \"{permission:s}\" forigita",
"permission_deletion_failed": "Ne povis forigi permeson '{permission}': {error}",
"permission_not_found": "Permesita \"{permission:s}\" ne trovita",
"restore_not_enough_disk_space": "Ne sufiĉa spaco (spaco: {free_space:d} B, necesa spaco: {needed_space:d} B, sekureca marĝeno: {margin:d} B)",
"tools_upgrade_regular_packages": "Nun ĝisdatigi 'regulajn' (ne-yunohost-rilatajn) pakojn …",
"tools_upgrade_special_packages_explanation": "La speciala ĝisdatigo daŭros en fono. Bonvolu ne komenci aliajn agojn en via servilo la sekvajn ~ 10 minutojn (depende de la aparata rapideco). Post tio, vi eble devos re-ensaluti sur la retadreso. La ĝisdatiga registro estos havebla en Iloj → Ensaluto (en la retadreso) aŭ uzante 'yunohost-logliston' (el la komandlinio).",
"unrestore_app": "App '{app:s}' ne restarigos",
"group_created": "Grupo '{group}' kreita",
"group_creation_failed": "Ne povis krei la grupon '{group}': {error}",
"group_deleted": "Grupo '{group}' forigita",
"group_deletion_failed": "Ne povis forigi la grupon '{group}': {error}",
"migrations_not_pending_cant_skip": "Tiuj migradoj ankoraŭ ne estas pritraktataj, do ne eblas preterlasi: {ids}",
"permission_already_exist": "Permesita '{permission}' jam ekzistas",
"domain_created": "Domajno kreita",
"migrate_tsig_wait_2": "2 minutoj …",
"log_user_create": "Aldonu uzanton '{}'",
"ip6tables_unavailable": "Vi ne povas ludi kun ip6tabloj ĉi tie. Vi estas en ujo aŭ via kerno ne subtenas ĝin",
"mail_unavailable": "Ĉi tiu retpoŝta adreso estas rezervita kaj aŭtomate estos atribuita al la unua uzanto",
"certmanager_domain_dns_ip_differs_from_public_ip": "La DNS 'A' rekordo por la domajno '{domain:s}' diferencas de ĉi tiu IP-servilo. Se vi lastatempe modifis vian A-registron, bonvolu atendi ĝin propagandi (iuj DNS-disvastigaj kontroliloj estas disponeblaj interrete). (Se vi scias, kion vi faras, uzu '--no-checks' por malŝalti tiujn ĉekojn.)",
"tools_upgrade_special_packages_completed": "Plenumis la ĝisdatigon de pakaĵoj de YunoHost.\nPremu [Enter] por retrovi la komandlinion",
"log_remove_on_failed_install": "Forigu '{}' post malsukcesa instalado",
"regenconf_file_manually_modified": "La agorddosiero '{conf}' estis modifita permane kaj ne estos ĝisdatigita",
"regenconf_would_be_updated": "La agordo estus aktualigita por la kategorio '{category}'",
"certmanager_cert_install_success_selfsigned": "Mem-subskribita atestilo nun instalita por la domajno '{domain:s}'",
"global_settings_unknown_setting_from_settings_file": "Nekonata ŝlosilo en agordoj: '{setting_key:s}', forĵetu ĝin kaj konservu ĝin en /etc/yunohost/settings-unknown.json",
"regenconf_file_backed_up": "Agordodosiero '{conf}' estis rezervita al '{backup}'",
"migration_0007_cannot_restart": "SSH ne rekomencas post provi nuligi la migradan numeron 6.",
"migration_description_0006_sync_admin_and_root_passwords": "Sinkronigu admin kaj radikajn pasvortojn",
"iptables_unavailable": "Vi ne povas ludi kun iptables ĉi tie. Vi estas en ujo aŭ via kerno ne subtenas ĝin",
"global_settings_cant_write_settings": "Ne eblis konservi agordojn, tial: {reason:s}",
"service_added": "La servo '{service:s}' aldonis",
"upnp_disabled": "UPnP malŝaltis",
"service_started": "Servo '{service:s}' komenciĝis",
"port_already_opened": "Haveno {port:d} estas jam malfermita por {ip_version:s} rilatoj",
"installation_failed": "Io okazis malbone kun la instalado",
"migrate_tsig_wait_3": "1 minuto …",
"certmanager_conflicting_nginx_file": "Ne povis prepari domajnon por ACME-defio: la agordo de NGINX {filepath:s} konfliktas kaj unue devas esti forigita",
"upgrading_packages": "Ĝisdatigi pakojn…",
"custom_app_url_required": "Vi devas provizi URL por altgradigi vian kutimon app {app:s}",
"service_reload_failed": "Ne povis reŝargi la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"packages_upgrade_failed": "Ne povis ĝisdatigi ĉiujn pakojn",
"hook_json_return_error": "Ne povis legi revenon de hoko {path:s}. Eraro: {msg:s}. Kruda enhavo: {raw_content}",
"dyndns_cron_removed": "DynDNS cron-laboro forigita",
"dyndns_key_not_found": "DNS-ŝlosilo ne trovita por la domajno",
"tools_upgrade_regular_packages_failed": "Ne povis ĝisdatigi pakojn: {packages_list}",
"service_start_failed": "Ne povis komenci la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"service_reloaded": "Servo '{service:s}' reŝargita",
"system_upgraded": "Sistemo ĝisdatigita",
"domain_deleted": "Domajno forigita",
"certmanager_acme_not_configured_for_domain": "Atestilo por la domajno '{domain:s}' ne ŝajnas esti ĝuste instalita. Bonvolu ekzekuti 'cert-instali' por ĉi tiu regado unue.",
"migration_description_0009_decouple_regenconf_from_services": "Malkonstruu la regen-konf-mekanismon de servoj",
"user_update_failed": "Ne povis ĝisdatigi uzanton {user}: {error}",
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "Lasu la SSH-agordon estu administrata de YunoHost (paŝo 2, manlibro)",
"restore_confirm_yunohost_installed": "Ĉu vi vere volas restarigi jam instalitan sistemon? [{answers:s}]",
"pattern_positive_number": "Devas esti pozitiva nombro",
"certmanager_error_no_A_record": "Neniu DNS 'A' rekordo trovita por '{domain:s}'. Vi bezonas atentigi vian domajnan nomon al via maŝino por povi instali atestilon Lasu-Ĉifri. (Se vi scias, kion vi faras, uzu '--no-checks' por malŝalti tiujn ĉekojn.)",
"update_apt_cache_failed": "Ne eblis ĝisdatigi la kaŝmemoron de APT (paka administranto de Debian). Jen rubujo de la sources.list-linioj, kiuj povus helpi identigi problemajn liniojn:\n{sourceslist}",
"migrations_no_migrations_to_run": "Neniuj migradoj por funkcii",
"executing_command": "Plenumanta komandon '{command:s}' …",
"certmanager_attempt_to_renew_nonLE_cert": "La atestilo por la domajno '{domain:s}' ne estas elsendita de Let's Encrypt. Ne eblas renovigi ĝin aŭtomate!",
"global_settings_setting_example_bool": "Ekzemplo bulea elekto",
"domain_dyndns_already_subscribed": "Vi jam abonis DynDNS-domajnon",
"log_letsencrypt_cert_renew": "Renovigu '{}' Let's Encrypt atestilon",
"migrate_tsig_start": "Detektita ŝlosila algoritmo nesufiĉa por TSIG-subskribo de la domajno '{domain}', komencanta migradon al la pli sekura HMAC-SHA-512",
"ldap_init_failed_to_create_admin": "LDAP-iniciato ne povis krei administran uzanton",
"backup_output_directory_required": "Vi devas provizi elirejan dosierujon por la sekurkopio",
"tools_upgrade_cant_unhold_critical_packages": "Ne povis malŝalti kritikajn pakojn…",
"log_link_to_log": "Plena ŝtipo de ĉi tiu operacio: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\"> {desc} </a>'",
"global_settings_cant_serialize_settings": "Ne eblis serialigi datumojn pri agordoj, motivo: {reason:s}",
"backup_running_hooks": "Kurado de apogaj hokoj …",
"certmanager_domain_unknown": "Nekonata domajno '{domain:s}'",
"unexpected_error": "Io neatendita iris malbone: {error}",
"password_listed": "Ĉi tiu pasvorto estas inter la plej uzataj pasvortoj en la mondo. Bonvolu elekti ion pli unikan.",
"migration_description_0007_ssh_conf_managed_by_yunohost_step1": "Lasu la SSH-agordon estu administrata de YunoHost (paŝo 1, aŭtomata)",
"migration_0009_not_needed": "Ĉi tiu migrado jam iel okazis ... (?) Saltado.",
"ssowat_conf_generated": "SSOwat-agordo generita",
"migrate_tsig_wait": "Atendante tri minutojn por ke la servilo DynDNS enkalkulu la novan ŝlosilon …",
"log_remove_on_failed_restore": "Forigu '{}' post malsukcesa restarigo de rezerva ar archiveivo",
"dpkg_is_broken": "Vi ne povas fari ĉi tion nun ĉar dpkg/APT (la administrantoj pri pakaĵaj sistemoj) ŝajnas esti rompita stato ... Vi povas provi solvi ĉi tiun problemon per konekto per SSH kaj funkcianta `sudo dpkg --configure -a`.",
"certmanager_cert_signing_failed": "Ne povis subskribi la novan atestilon",
"migration_description_0003_migrate_to_stretch": "Altgradigu la sistemon al Debian Stretch kaj YunoHost 3.0",
"log_tools_upgrade": "Ĝisdatigu sistemajn pakaĵojn",
"log_available_on_yunopaste": "Ĉi tiu protokolo nun haveblas per {url}",
"certmanager_http_check_timeout": "Ekdifinita kiam servilo provis kontakti sin per HTTP per publika IP-adreso (domajno '{domain:s}' kun IP '{ip:s}'). Vi eble spertas haŭtoproblemon, aŭ la fajroŝirmilo / enkursigilo antaŭ via servilo miskonfiguras.",
"pattern_port_or_range": "Devas esti valida haveno-nombro (t.e. 0-65535) aŭ gamo da havenoj (t.e. 100:200)",
"migrations_loading_migration": "Ŝarĝante migradon {id}…",
"pattern_mailbox_quota": "Devas esti grandeco kun la sufikso b/k/M/G/T aŭ 0 por ne havi kvoton",
"migration_0008_general_disclaimer": "Por plibonigi la sekurecon de via servilo, rekomendas lasi YunoHost administri la SSH-agordon. Via nuna SSH-aranĝo diferencas de la rekomendo. Se vi lasas YunoHost agordi ĝin, la maniero per kiu vi konektas al via servilo per SSH ŝanĝiĝos tiel:",
"user_deletion_failed": "Ne povis forigi uzanton {user}: {error}",
"backup_with_no_backup_script_for_app": "La app '{app:s}' ne havas sekretan skripton. Ignorante.",
"service_regen_conf_is_deprecated": "'yunohost service regen-conf' malakceptas! Bonvolu uzi anstataŭe 'yunohost tools regen-conf'.",
"global_settings_key_doesnt_exists": "La ŝlosilo '{settings_key:s}' ne ekzistas en la tutmondaj agordoj, vi povas vidi ĉiujn disponeblajn klavojn per uzado de 'yunohost settings list'",
"dyndns_no_domain_registered": "Neniu domajno registrita ĉe DynDNS",
"dyndns_could_not_check_available": "Ne povis kontroli ĉu {domain:s} haveblas sur {provider:s}.",
"global_settings_setting_example_enum": "Ekzemplo enum elekto",
"hook_exec_not_terminated": "Skripto ne finiĝis ĝuste: {path:s}",
"service_stopped": "Servo '{service:s}' ĉesis",
"restore_failed": "Ne povis restarigi sistemon",
"confirm_app_install_danger": "Danĝero! Ĉi tiu apliko estas konata ankoraŭ eksperimenta (se ne eksplicite ne funkcias)! Vi probable ne devas instali ĝin krom se vi scias kion vi faras. NENIU SUBTENO estos provizita se ĉi tiu app ne funkcias aŭ rompas vian sistemon ... Se vi pretas riski ĉiuokaze, tajpu '{answers:s}'",
"log_operation_unit_unclosed_properly": "Operaciumo ne estis fermita ĝuste",
"upgrade_complete": "Ĝisdatigo kompleta",
"upnp_enabled": "UPnP ŝaltis",
"mailbox_used_space_dovecot_down": "La retpoŝta servo de Dovecot devas funkcii, se vi volas akcepti uzitan poŝtan spacon",
"restore_system_part_failed": "Ne povis restarigi la sisteman parton '{part:s}'",
"service_stop_failed": "Ne povis maldaŭrigi la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"unbackup_app": "App '{app:s}' ne konserviĝos",
"updating_apt_cache": "Akirante haveblajn ĝisdatigojn por sistemaj pakoj…",
"tools_upgrade_at_least_one": "Bonvolu specifi '--apps' aŭ '--system'",
"service_already_stopped": "La servo '{service:s}' jam ĉesis",
"migration_0003_modified_files": "Bonvolu noti, ke la jenaj dosieroj estis trovitaj mane kaj modifitaj kaj povus esti anstataŭigitaj sekve de la ĝisdatigo: {manually_modified_files}",
"tools_upgrade_cant_both": "Ne eblas ĝisdatigi ambaŭ sistemon kaj programojn samtempe",
"restore_extracting": "Eltirante bezonatajn dosierojn el la ar theivo…",
"upnp_port_open_failed": "Ne povis malfermi havenon per UPnP",
"log_app_upgrade": "Ĝisdatigu la aplikon '{}'",
"log_help_to_get_failed_log": "La operacio '{desc}' ne povis finiĝi. Bonvolu dividi la plenan ŝtipon de ĉi tiu operacio per la komando 'yunohost log display {name} --share' por akiri helpon",
"migration_description_0002_migrate_to_tsig_sha256": "Plibonigu sekurecon de DynDNS TSIG-ĝisdatigoj per SHA-512 anstataŭ MD5",
"port_already_closed": "Haveno {port:d} estas jam fermita por {ip_version:s} rilatoj",
"hook_name_unknown": "Nekonata hoko-nomo '{name:s}'",
"migration_0003_system_not_fully_up_to_date": "Via sistemo ne estas plene ĝisdata. Bonvolu plenumi regulan ĝisdatigon antaŭ ol ruli la migradon al Stretch.",
"dyndns_could_not_check_provide": "Ne povis kontroli ĉu {provider:s} povas provizi {domain:s}.",
"dyndns_cron_remove_failed": "Ne povis forigi la cron-laboron DynDNS ĉar: {error}",
"restore_nothings_done": "Nenio estis restarigita",
"log_tools_postinstall": "Afiŝu vian servilon YunoHost",
"dyndns_unavailable": "La domajno '{domain:s}' ne haveblas.",
"experimental_feature": "Averto: Ĉi tiu funkcio estas eksperimenta kaj ne konsiderata stabila, vi ne uzu ĝin krom se vi scias kion vi faras.",
"root_password_replaced_by_admin_password": "Via radika pasvorto estis anstataŭigita per via administra pasvorto.",
"migration_description_0005_postgresql_9p4_to_9p6": "Migru datumbazojn de PostgreSQL 9.4 al 9.6",
"migration_0008_root": "• Vi ne povos konekti kiel radiko per SSH. Anstataŭe vi uzu la administran uzanton;",
"package_unknown": "Nekonata pako '{pkgname}'",
"domain_unknown": "Nekonata domajno",
"global_settings_setting_security_password_user_strength": "Uzanto pasvorta forto",
"restore_may_be_not_enough_disk_space": "Via sistemo ŝajnas ne havi sufiĉe da spaco (free:{free_space:d} B, necesa spaco: {needed_space:d} B, sekureca marĝeno: {margin:d} B)",
"log_corrupted_md_file": "La YAD-metadata dosiero asociita kun protokoloj estas damaĝita: '{md_file}\nEraro: {error} '",
"downloading": "Elŝutante …",
"user_deleted": "Uzanto forigita",
"service_enable_failed": "Ne povis fari la servon '{service:s}' aŭtomate komenci ĉe la ekkuro.\n\nLastatempaj servaj protokoloj: {logs:s}",
"tools_upgrade_special_packages": "Nun ĝisdatigi 'specialajn' (rilatajn al yunohost)…",
"domains_available": "Haveblaj domajnoj:",
"dyndns_registered": "Registrita domajno DynDNS",
"service_description_fail2ban": "Protektas kontraŭ bruta forto kaj aliaj specoj de atakoj de la interreto",
"file_does_not_exist": "La dosiero {path:s} ne ekzistas.",
"yunohost_not_installed": "YunoHost ne estas ĝuste instalita. Bonvolu prilabori 'yunohost tools postinstall'",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 estas instalita, sed ne postgresql 9.6‽ Io stranga eble okazis en via sistemo: (…",
"restore_removing_tmp_dir_failed": "Ne povis forigi malnovan provizoran dosierujon",
"certmanager_cannot_read_cert": "Io malbona okazis, kiam mi provis malfermi aktualan atestilon por domajno {domain:s} (dosiero: {file:s}), kialo: {reason:s}",
"service_removed": "Servo '{service:s}' forigita",
"certmanager_hit_rate_limit": "Tro multaj atestiloj jam eldonitaj por ĉi tiu ĝusta aro de domajnoj {domain:s} antaŭ nelonge. Bonvolu reprovi poste. Vidu https://letsencrypt.org/docs/rate-limits/ por pliaj detaloj",
"migration_0005_not_enough_space": "Disponigu sufiĉan spacon en {path} por ruli la migradon.",
"pattern_firstname": "Devas esti valida antaŭnomo",
"migration_description_0010_migrate_to_apps_json": "Forigu malvalorigitajn katalogajn programojn kaj uzu anstataŭe la novan unuigitan liston de \"apps.json\" (malaktuale anstataŭita per migrado 13)",
"domain_cert_gen_failed": "Ne povis generi atestilon",
"regenconf_file_kept_back": "La agorda dosiero '{conf}' estas atendita forigi per regen-conf (kategorio {category}), sed ĝi estis konservita.",
"migrate_tsig_wait_4": "30 sekundoj …",
"backup_with_no_restore_script_for_app": "La apliko \"{app:s}\" ne havas restarigan skripton, vi ne povos aŭtomate restarigi la sekurkopion de ĉi tiu apliko.",
"log_letsencrypt_cert_install": "Instalu atestilon Let's Encrypt sur '{}' regado",
"log_dyndns_update": "Ĝisdatigu la IP asociita kun via subdominio YunoHost '{}'",
"firewall_reload_failed": "Ne eblis reŝargi la firewall",
"confirm_app_install_warning": "Averto: Ĉi tiu aplikaĵo povas funkcii, sed ne bone integras en YunoHost. Iuj funkcioj kiel ekzemple aliĝilo kaj sekurkopio / restarigo eble ne haveblos. Instali ĉiuokaze? [{answers:s}] ",
"log_user_delete": "Forigi uzanton '{}'",
"dyndns_ip_updated": "Ĝisdatigis vian IP sur DynDNS",
"regenconf_up_to_date": "La agordo jam estas ĝisdatigita por kategorio '{category}'",
"migration_0003_patching_sources_list": "Patching the sources.lists …",
"global_settings_setting_security_ssh_compatibility": "Kongruo vs sekureca kompromiso por la SSH-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
"migrations_need_to_accept_disclaimer": "Por funkciigi la migradon {id}, via devas akcepti la sekvan malakcepton:\n---\n{disclaimer}\n---\nSe vi akceptas funkcii la migradon, bonvolu rekonduki la komandon kun la opcio '--accept-disclaimer'.",
"regenconf_file_remove_failed": "Ne povis forigi la agordodosieron '{conf}'",
"not_enough_disk_space": "Ne sufiĉe libera spaco sur '{path:s}'",
"migration_0006_disclaimer": "YunoHost nun atendas, ke la pasvortoj de admin kaj radiko estos sinkronigitaj. Ĉi tiu migrado anstataŭigas vian radikan pasvorton kun la administran pasvorton.",
"dyndns_ip_update_failed": "Ne povis ĝisdatigi IP-adreson al DynDNS",
"migration_description_0004_php5_to_php7_pools": "Rekonfigu la PHP-naĝejojn por uzi PHP 7 anstataŭ 5",
"ssowat_conf_updated": "SSOwat-agordo ĝisdatigita",
"log_link_to_failed_log": "Ne povis plenumi la operacion '{desc}'. Bonvolu provizi la plenan protokolon de ĉi tiu operacio per <a href=\"#/tools/logs/{name}\"> alklakante ĉi tie </a> por akiri helpon",
"user_home_creation_failed": "Ne povis krei dosierujon \"home\" por uzanto",
"pattern_backup_archive_name": "Devas esti valida dosiernomo kun maksimume 30 signoj, alfanombraj kaj -_. signoj nur",
"restore_cleaning_failed": "Ne eblis purigi la adresaron de provizora restarigo",
"dyndns_registration_failed": "Ne povis registri DynDNS-domajnon: {error:s}",
"migration_0003_not_jessie": "La nuna Debian-distribuo ne estas Jessie!",
"user_unknown": "Nekonata uzanto: {user:s}",
"migrations_to_be_ran_manually": "Migrado {id} devas funkcii permane. Bonvolu iri al Iloj → Migradoj en la retpaĝa paĝo, aŭ kuri `yunohost tools migrations migrate`.",
"migration_0008_warning": "Se vi komprenas tiujn avertojn kaj volas ke YunoHost preterlasu vian nunan agordon, faru la migradon. Alie, vi ankaŭ povas salti la migradon, kvankam ĝi ne rekomendas.",
"certmanager_cert_renew_success": "Ni Ĉifru atestilon renovigitan por la domajno '{domain:s}'",
"global_settings_reset_success": "Antaŭaj agordoj nun estas rezervitaj al {path:s}",
"pattern_domain": "Devas esti valida domajna nomo (t.e. mia-domino.org)",
"dyndns_key_generating": "Generi DNS-ŝlosilon ... Eble daŭros iom da tempo.",
"restore_running_app_script": "Restarigi la programon '{app:s}'…",
"migrations_skip_migration": "Salti migradon {id}…",
"regenconf_file_removed": "Agordodosiero '{conf}' forigita",
"log_tools_shutdown": "Enŝaltu vian servilon",
"password_too_simple_3": "La pasvorto bezonas almenaŭ 8 signojn kaj enhavas ciferon, majusklon, pli malaltan kaj specialajn signojn",
"migration_0003_general_warning": "Bonvolu noti, ke ĉi tiu migrado estas delikata operacio. La teamo de YunoHost faris sian plej bonan revizii kaj testi ĝin, sed la migrado eble ankoraŭ rompos partojn de la sistemo aŭ ĝiaj programoj.\n\nTial oni rekomendas al:\n - Elfari kopion de iuj kritikaj datumoj aŭ app. Pliaj informoj pri https://yunohost.org/backup;\n - Paciencu post lanĉo de la migrado: Depende de via interreta konekto kaj aparataro, eble daŭros kelkaj horoj ĝis ĉio ĝisdatigi.\n\nAldone, la haveno por SMTP, uzata de eksteraj retpoŝtaj klientoj (kiel Thunderbird aŭ K9-Mail) estis ŝanĝita de 465 (SSL / TLS) al 587 (STARTTLS). La malnova haveno (465) aŭtomate fermiĝos, kaj la nova haveno (587) malfermiĝos en la fajrejo. Vi kaj viaj uzantoj * devos adapti la agordon de viaj retpoŝtaj klientoj laŭe.",
"global_settings_setting_example_int": "Ekzemple int elekto",
"backup_output_symlink_dir_broken": "Via arkiva dosierujo '{path:s}' estas rompita ligilo. Eble vi forgesis restarigi aŭ munti aŭ enŝovi la stokadon, al kiu ĝi notas.",
"good_practices_about_admin_password": "Vi nun estas por difini novan administran pasvorton. La pasvorto devas esti almenaŭ 8 signoj - kvankam estas bone praktiki uzi pli longan pasvorton (t.e. pasfrazon) kaj / aŭ uzi variaĵon de signoj (majuskloj, minuskloj, ciferoj kaj specialaj signoj).",
"certmanager_attempt_to_renew_valid_cert": "La atestilo por la domajno '{domain:s}' ne finiĝos! (Vi eble uzos --force se vi scias kion vi faras)",
"restore_running_hooks": "Kurantaj restarigaj hokoj…",
"regenconf_pending_applying": "Aplikante pritraktata agordo por kategorio '{category}'…",
"service_description_dovecot": "Permesas al retpoŝtaj klientoj aliri / serĉi retpoŝton (per IMAP kaj POP3)",
"domain_dns_conf_is_just_a_recommendation": "Ĉi tiu komando montras al vi la *rekomenditan* agordon. Ĝi efektive ne agordas la DNS-agordon por vi. Via respondeco agordi vian DNS-zonon en via registristo laŭ ĉi tiu rekomendo.",
"backup_php5_to_php7_migration_may_fail": "Ne povis konverti vian ar archiveivon por subteni PHP 7, vi eble ne povas restarigi viajn PHP-programojn (kialo: {error:s})",
"log_backup_restore_system": "Restarigi sistemon de rezerva arkivo",
"log_app_change_url": "Ŝanĝu la URL de la apliko '{}'",
"service_already_started": "La servo '{service:s}' jam funkcias",
"global_settings_setting_security_password_admin_strength": "Admin pasvorta forto",
"service_reload_or_restart_failed": "Ne povis reŝargi aŭ rekomenci la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"migrations_list_conflict_pending_done": "Vi ne povas uzi ambaŭ '--previous' kaj '--done' samtempe.",
"server_shutdown_confirm": "La servilo haltos tuj, ĉu vi certas? [{answers:s}]",
"log_backup_restore_app": "Restarigu '{}' de rezerva ar archiveivo",
"log_does_exists": "Ne estas operacio-registro kun la nomo '{log}', uzu 'yunohost loglist' por vidi ĉiujn disponeblajn operaciojn",
"service_add_failed": "Ne povis aldoni la servon '{service:s}'",
"pattern_password_app": "Bedaŭrinde, pasvortoj ne povas enhavi jenajn signojn: {forbidden_chars}",
"this_action_broke_dpkg": "Ĉi tiu ago rompis dpkg / APT (la administrantoj pri la paka sistemo) ... Vi povas provi solvi ĉi tiun problemon per konekto per SSH kaj funkcianta `sudo dpkg --configure -a`.",
"log_regen_conf": "Regeneri sistemajn agordojn '{}'",
"restore_hook_unavailable": "La restariga skripto por '{part:s}' ne haveblas en via sistemo kaj ankaŭ ne en la ar theivo",
"log_dyndns_subscribe": "Aboni al YunoHost-subdominio '{}'",
"password_too_simple_4": "La pasvorto bezonas almenaŭ 12 signojn kaj enhavas ciferon, majuskle, pli malaltan kaj specialajn signojn",
"migration_0003_main_upgrade": "Komencanta ĉefa ĝisdatigo …",
"regenconf_file_updated": "Agordodosiero '{conf}' ĝisdatigita",
"log_help_to_get_log": "Por vidi la protokolon de la operacio '{desc}', uzu la komandon 'yunohost log display {name}'",
"global_settings_setting_security_nginx_compatibility": "Kongruo vs sekureca kompromiso por la TTT-servilo NGINX. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
"no_internet_connection": "La servilo ne estas konektita al la interreto",
"migration_0008_dsa": "• La DSA-ŝlosilo estos malŝaltita. Tial vi eble bezonos nuligi spuran averton de via SSH-kliento kaj revizii la fingrospuron de via servilo;",
"migration_0003_restoring_origin_nginx_conf": "Fileia dosiero /etc/nginx/nginx.conf estis iel redaktita. La migrado reaperos unue al sia originala stato ... La antaŭa dosiero estos havebla kiel {backup_dest}.",
"migrate_tsig_end": "Migrado al HMAC-SHA-512 finiĝis",
"restore_complete": "Restarigita",
"certmanager_couldnt_fetch_intermediate_cert": "Ekvilibrigita kiam vi provis ricevi interajn atestilojn de Let's Encrypt. Atestita instalado / renovigo nuligita - bonvolu reprovi poste.",
"hook_exec_failed": "Ne povis funkcii skripto: {path:s}",
"global_settings_cant_open_settings": "Ne eblis malfermi agordojn, tial: {reason:s}",
"user_created": "Uzanto kreita",
"service_description_avahi-daemon": "Permesas al vi atingi vian servilon uzante 'yunohost.local' en via loka reto",
"certmanager_attempt_to_replace_valid_cert": "Vi provas anstataŭigi bonan kaj validan atestilon por domajno {domain:s}! (Uzu --forte pretervidi)",
"regenconf_updated": "Agordo ĝisdatigita por '{category}'",
"update_apt_cache_warning": "Io iris malbone dum la ĝisdatigo de la kaŝmemoro de APT (paka administranto de Debian). Jen rubujo de la sources.list-linioj, kiuj povus helpi identigi problemajn liniojn:\n{sourceslist}",
"regenconf_dry_pending_applying": "Kontrolado de pritraktata agordo, kiu estus aplikita por kategorio '{category}'…",
"regenconf_file_copy_failed": "Ne povis kopii la novan agordodosieron '{new}' al '{conf}'",
"global_settings_setting_example_string": "Ekzemple korda elekto",
"restore_already_installed_app": "App kun la ID '{app:s}' estas jam instalita",
"mail_domain_unknown": "Nevalida retadreso por domajno '{domain:s}'. Bonvolu uzi domajnon administritan de ĉi tiu servilo.",
"migrations_cant_reach_migration_file": "Ne povis aliri migrajn dosierojn ĉe la vojo '% s'",
"pattern_email": "Devas esti valida retpoŝta adreso (t.e. iu@ekzemple.com)",
"mail_alias_remove_failed": "Ne povis forigi retpoŝton alias '{mail:s}'",
"regenconf_file_manually_removed": "La dosiero de agordo '{conf}' estis forigita permane, kaj ne estos kreita",
"domain_exists": "La domajno jam ekzistas",
"migration_description_0001_change_cert_group_to_sslcert": "Ŝanĝu grupajn permesojn de 'metronomo' al 'ssl-cert'",
"ldap_initialized": "LDAP inicializis",
"migrate_tsig_not_needed": "Vi ne ŝajnas uzi DynDNS-domajnon, do neniu migrado necesas.",
"certmanager_domain_cert_not_selfsigned": "La atestilo por domajno {domain:s} ne estas mem-subskribita. Ĉu vi certas, ke vi volas anstataŭigi ĝin? (Uzu '--force' por fari tion.)",
"certmanager_unable_to_parse_self_CA_name": "Ne povis trapasi nomon de mem-subskribinta aŭtoritato (dosiero: {file:s})",
"log_selfsigned_cert_install": "Instalu mem-subskribitan atestilon sur '{}' domajno",
"log_tools_reboot": "Reklamu vian servilon",
"certmanager_cert_install_success": "Ni Ĉifru atestilon nun instalitan por la domajno '{domain:s}'",
"global_settings_bad_choice_for_enum": "Malbona elekto por agordo {setting:s}, ricevita '{choice:s}', sed disponeblaj elektoj estas: {available_choices:s}",
"server_shutdown": "La servilo haltos",
"log_tools_migrations_migrate_forward": "Migri antaŭen",
"migration_0008_no_warning": "Supersalti vian SSH-agordon estu sekura, kvankam ĉi tio ne povas esti promesita! Ekfunkciu la migradon por superregi ĝin. Alie, vi ankaŭ povas salti la migradon, kvankam ĝi ne rekomendas.",
"regenconf_now_managed_by_yunohost": "La agorda dosiero '{conf}' nun estas administrata de YunoHost (kategorio {category}).",
"server_reboot_confirm": "Ĉu la servilo rekomencos tuj, ĉu vi certas? [{answers:s}]",
"log_app_install": "Instalu la aplikon '{}'",
"service_description_dnsmasq": "Traktas rezolucion de domajna nomo (DNS)",
"global_settings_unknown_type": "Neatendita situacio, la agordo {setting:s} ŝajnas havi la tipon {unknown_type:s} sed ĝi ne estas tipo subtenata de la sistemo.",
"migration_0003_problematic_apps_warning": "Bonvolu noti, ke la sekvaj eventuale problemaj instalitaj programoj estis detektitaj. Ŝajnas, ke tiuj ne estis instalitaj el app_katalogo aŭ ne estas markitaj kiel \"funkciantaj\". Tial ne eblas garantii, ke ili ankoraŭ funkcios post la ĝisdatigo: {problematic_apps}",
"domain_hostname_failed": "Ne povis agordi novan gastigilon. Ĉi tio eble kaŭzos problemon poste (eble bone).",
"server_reboot": "La servilo rekomenciĝos",
"regenconf_failed": "Ne povis regeneri la agordon por kategorio(j): {categories}",
"domain_uninstall_app_first": "Unu aŭ pluraj programoj estas instalitaj en ĉi tiu domajno. Bonvolu malinstali ilin antaŭ ol daŭrigi la domajnan forigon",
"service_unknown": "Nekonata servo '{service:s}'",
"migration_0003_start": "Komencante migradon al Stretch. La protokoloj haveblos en {logfile}.",
"domain_deletion_failed": "Ne eblas forigi domajnon {domain}: {error}",
"log_user_update": "Ĝisdatigu uzantinformojn de '{}'",
"user_creation_failed": "Ne povis krei uzanton {user}: {error}",
"migrations_migration_has_failed": "Migrado {id} ne kompletigis, abolis. Eraro: {exception}",
"done": "Farita",
"log_domain_remove": "Forigi domon '{}' de agordo de sistemo",
"hook_list_by_invalid": "Ĉi tiu posedaĵo ne povas esti uzata por listigi hokojn",
"confirm_app_install_thirdparty": "Danĝero! Ĉi tiu apliko ne estas parto de la aplika katalogo de Yunohost. Instali triajn aplikojn povas kompromiti la integrecon kaj sekurecon de via sistemo. Vi probable ne devas instali ĝin krom se vi scias kion vi faras. NENIU SUBTENO estos provizita se ĉi tiu app ne funkcias aŭ rompas vian sistemon ... Se vi pretas riski ĉiuokaze, tajpu '{answers:s}'",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Permesu uzon de (malaktuala) DSA-hostkey por la agordo de daemon SSH",
"dyndns_domain_not_provided": "Provizanto DynDNS {provider:s} ne povas provizi domajnon {domain:s}.",
"backup_unable_to_organize_files": "Ne povis uzi la rapidan metodon por organizi dosierojn en la ar archiveivo",
"password_too_simple_2": "La pasvorto bezonas almenaŭ 8 signojn kaj enhavas ciferon, majusklojn kaj minusklojn",
"executing_script": "Plenumanta skripto '{script:s}' …",
"service_cmd_exec_failed": "Ne povis plenumi la komandon '{command:s}'",
"migration_0007_cancelled": "Ne povis plibonigi la manieron kiel via SSH-agordo estas administrita.",
"migrate_tsig_failed": "Ne povis migri la DynDNS-domajnon '{domain}' al HMAC-SHA-512, ruliĝante. Eraro: {error_code}, {error}",
"pattern_lastname": "Devas esti valida familinomo",
"service_enabled": "La servo '{service:s}' nun aŭtomate komenciĝos dum sistemaj botoj.",
"certmanager_no_cert_file": "Ne povis legi la atestan dosieron por la domajno {domain:s} (dosiero: {file:s})",
"migration_0008_port": "• Vi devos konekti uzante la havenon 22 anstataŭ via nuna kutimo SSH-haveno. Sentu vin libera reconfiguri ĝin;",
"domain_creation_failed": "Ne eblas krei domajnon {domain}: {error}",
"certmanager_domain_http_not_working": "Ŝajnas ke la domajno {domain:s} ne atingeblas per HTTP. Kontrolu, ke via DNS kaj NGINX-agordo ĝustas",
"domain_cannot_remove_main": "Vi ne povas forigi '{domain:s}' ĉar ĝi estas la ĉefa domajno, vi bezonas unue agordi alian domajnon kiel la ĉefan domajnon per uzado de 'yunohost domain main-domain -n <another-domain>', jen la listo de kandidataj domajnoj. : {other_domains:s}",
"service_reloaded_or_restarted": "La servo '{service:s}' estis reŝarĝita aŭ rekomencita",
"log_domain_add": "Aldonu '{}' domajnon en sisteman agordon",
"global_settings_bad_type_for_setting": "Malbona tipo por agordo {setting:s}, ricevita {received_type:s}, atendata {expected_type:s}",
"unlimit": "Neniu kvoto",
"dyndns_cron_installed": "Kreita laboro DynDNS cron",
"system_username_exists": "Uzantnomo jam ekzistas en la listo de uzantoj de sistemo",
"firewall_reloaded": "Fajroŝirmilo reŝarĝis",
"service_restarted": "Servo '{service:s}' rekomencis",
"pattern_username": "Devas esti minuskulaj literoj kaj minuskloj nur",
"extracting": "Eltirante…",
"restore_app_failed": "Ne povis restarigi la programon '{app:s}'",
"yunohost_configured": "YunoHost nun estas agordita",
"certmanager_self_ca_conf_file_not_found": "Ne povis trovi agorddosieron por mem-subskriba aŭtoritato (dosiero: {file:s})",
"log_app_remove": "Forigu la aplikon '{}'",
"service_restart_failed": "Ne povis rekomenci la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"firewall_rules_cmd_failed": "Iuj komandoj pri fajroŝirmilo malsukcesis. Pliaj informoj en ensaluto.",
"certmanager_certificate_fetching_or_enabling_failed": "Provante uzi la novan atestilon por {domain:s} ne funkciis …",
"app_full_domain_unavailable": "Bedaŭrinde, ĉi tiu app devas esti instalita sur propra domajno, sed aliaj programoj jam estas instalitaj sur la domajno '{domain}'. Vi povus uzi subdominon dediĉitan al ĉi tiu app anstataŭe.",
"migration_0011_slapd_config_will_be_overwritten": "Ŝajnas ke vi permane redaktis la slapd-agordon. Por ĉi tiu kritika migrado, YunoHost bezonas devigi la ĝisdatigon de la slapd-agordo. La originalaj dosieroj estos rezervitaj en {conf_backup_folder}.",
"group_cannot_edit_all_users": "La grupo 'all_users' ne povas esti redaktita permane. Ĝi estas speciala grupo celita enhavi ĉiujn uzantojn registritajn en YunoHost",
"group_cannot_edit_visitors": "La grupo 'vizitantoj' ne povas esti redaktita permane. Ĝi estas speciala grupo reprezentanta anonimajn vizitantojn",
"group_cannot_edit_primary_group": "La grupo '{group}' ne povas esti redaktita permane. Ĝi estas la primara grupo celita enhavi nur unu specifan uzanton.",
"log_permission_url": "Ĝisdatigu url-rilataj al permeso '{}'",
"permission_already_up_to_date": "La permeso ne estis ĝisdatigita ĉar la petoj pri aldono/forigo jam kongruas kun la aktuala stato.",
"permission_currently_allowed_for_all_users": "Ĉi tiu permeso estas nuntempe donita al ĉiuj uzantoj aldone al aliaj grupoj. Vi probable volas aŭ forigi la permeson \"all_users\" aŭ forigi la aliajn grupojn, kiujn ĝi nuntempe donas.",
"app_install_failed": "Ne povis instali {app} : {error}",
"app_install_script_failed": "Eraro okazis en la skripto de instalado de la app",
"app_remove_after_failed_install": "Forigado de la app post la instala fiasko …",
"diagnosis_basesystem_host": "Servilo funkcias Debian {debian_version}.",
"apps_catalog_init_success": "Aplikoj katalogsistemo inicializita !",
"apps_catalog_updating": "Ĝisdatigante katalogo de aplikoj ...",
"apps_catalog_failed_to_download": "Ne eblas elŝuti la katalogon de {apps_catalog}: {error}",
"apps_catalog_obsolete_cache": "La kaŝmemoro de la katalogo de programoj estas malplena aŭ malaktuala.",
"apps_catalog_update_success": "La aplika katalogo estis ĝisdatigita!",
"diagnosis_basesystem_kernel": "Servilo funkcias Linuksan kernon {kernel_version}",
"diagnosis_basesystem_ynh_single_version": "{package} versio: {version} ({repo})",
"diagnosis_basesystem_ynh_main_version": "Servilo funkcias YunoHost {main_version} ({repo})",
"diagnosis_basesystem_ynh_inconsistent_versions": "Vi prizorgas malkonsekvencajn versiojn de la YunoHost-pakoj... plej probable pro malsukcesa aŭ parta ĝisdatigo.",
"diagnosis_display_tip_web": "Vi povas iri al la sekcio Diagnozo (en la hejmekrano) por vidi la trovitajn problemojn.",
"diagnosis_cache_still_valid": "(Kaŝmemoro ankoraŭ validas por {category} diagnozo. Ankoraŭ ne re-diagnoza!)",
"diagnosis_cant_run_because_of_dep": "Ne eblas fari diagnozon por {category} dum estas gravaj problemoj rilataj al {dep}.",
"diagnosis_display_tip_cli": "Vi povas aranĝi 'yunohost diagnosis show --issues' por aperigi la trovitajn problemojn.",
"diagnosis_failed_for_category": "Diagnozo malsukcesis por kategorio '{category}': {error}",
"app_upgrade_script_failed": "Eraro okazis en la skripto pri ĝisdatiga programo",
"diagnosis_diskusage_verylow": "Stokado {mountpoint} (sur aparato {device)) restas nur {free} ({free_percent}%) spaco. Vi vere konsideru purigi iom da spaco.",
"diagnosis_ram_verylow": "La sistemo nur restas {available} ({available_percent}%) RAM! (el {total})",
"diagnosis_mail_outgoing_port_25_blocked": "Eliranta haveno 25 ŝajnas esti blokita. Vi devas provi malŝlosi ĝin en via agorda panelo de provizanto (aŭ gastiganto). Dume la servilo ne povos sendi retpoŝtojn al aliaj serviloj.",
"diagnosis_http_bad_status_code": "Ne povis atingi vian servilon kiel atendite, ĝi redonis malbonan statuskodon. Povas esti, ke alia maŝino respondis anstataŭ via servilo. Vi devus kontroli, ke vi ĝuste redonas la havenon 80, ke via nginx-agordo ĝisdatigas kaj ke reverso-prokuro ne interbatalas.",
"main_domain_changed": "La ĉefa domajno estis ŝanĝita",
"yunohost_postinstall_end_tip": "La post-instalado finiĝis! Por fini vian agordon, bonvolu konsideri:\n - aldonado de unua uzanto tra la sekcio 'Uzantoj' de la retadreso (aŭ 'yunohost user create <username>' en komandlinio);\n - diagnozi problemojn atendantajn solvi por ke via servilo funkciu kiel eble plej glate tra la sekcio 'Diagnosis' de la retadministrado (aŭ 'yunohost diagnosis run' en komandlinio);\n - legante la partojn 'Finigi vian agordon' kaj 'Ekkoni Yunohost' en la administra dokumentado: https://yunohost.org/admindoc.",
"migration_description_0014_remove_app_status_json": "Forigi heredajn dosierojn",
"diagnosis_ip_connected_ipv4": "La servilo estas konektita al la interreto per IPv4 !",
"diagnosis_ip_no_ipv4": "La servilo ne havas funkciantan IPv4.",
"diagnosis_ip_connected_ipv6": "La servilo estas konektita al la interreto per IPv6 !",
"diagnosis_ip_no_ipv6": "La servilo ne havas funkciantan IPv6.",
"diagnosis_ip_not_connected_at_all": "La servilo tute ne ŝajnas esti konektita al la Interreto !?",
"diagnosis_ip_dnsresolution_working": "Rezolucio pri domajna nomo funkcias !",
"diagnosis_ip_weird_resolvconf": "DNS-rezolucio ŝajnas funkcii, sed atentu, ke vi ŝajnas uzi kutimon /etc/resolv.conf.",
"diagnosis_ip_weird_resolvconf_details": "Anstataŭe, ĉi tiu dosiero estu ligilo kun /etc/resolvconf/run/resolv.conf mem montrante al 127.0.0.1 (dnsmasq). La efektivaj solvantoj devas agordi per /etc/resolv.dnsmasq.conf.",
"diagnosis_dns_good_conf": "Bona DNS-agordo por domajno {domain} (kategorio {category})",
"diagnosis_dns_bad_conf": "Malbona / mankas DNS-agordo por domajno {domain} (kategorio {category})",
"diagnosis_ram_ok": "La sistemo ankoraŭ havas {available} ({available_percent}%) RAM forlasita de {total}.",
"diagnosis_swap_none": "La sistemo tute ne havas interŝanĝon. Vi devus pripensi aldoni almenaŭ {recommended} da interŝanĝo por eviti situaciojn en kiuj la sistemo restas sen memoro.",
"diagnosis_swap_notsomuch": "La sistemo havas nur {total}-interŝanĝon. Vi konsideru havi almenaŭ {recommended} por eviti situaciojn en kiuj la sistemo restas sen memoro.",
"diagnosis_regenconf_manually_modified_details": "Ĉi tio probable estas bona tiel longe kiel vi scias kion vi faras;)!",
"diagnosis_regenconf_manually_modified_debian": "Agordodosiero {file} estis modifita permane kompare kun la defaŭlta Debian.",
"diagnosis_regenconf_manually_modified_debian_details": "Ĉi tio probable estas bona, sed devas observi ĝin...",
"diagnosis_security_all_good": "Neniu kritika sekureca vundebleco estis trovita.",
"diagnosis_security_vulnerable_to_meltdown": "Vi ŝajnas vundebla al la kritiko-vundebleco de Meltdown",
"diagnosis_no_cache": "Neniu diagnoza kaŝmemoro por kategorio '{category}'",
"diagnosis_ip_broken_dnsresolution": "Rezolucio pri domajna nomo rompiĝas pro iu kialo ... Ĉu fajroŝirmilo blokas DNS-petojn ?",
"diagnosis_ip_broken_resolvconf": "Rezolucio pri domajna nomo ŝajnas esti rompita en via servilo, kiu ŝajnas rilata al /etc/resolv.conf ne notante 127.0.0.1.",
"diagnosis_dns_missing_record": "Laŭ la rekomendita DNS-agordo, vi devas aldoni DNS-registron kun\ntipo: {type}\nnomo: {name}\nvaloro: {value}",
"diagnosis_dns_discrepancy": "La DNS-registro kun tipo {type} kaj nomo {name} ne kongruas kun la rekomendita agordo.\nNuna valoro: {current}\nEsceptita valoro: {value}",
"diagnosis_services_conf_broken": "Agordo estas rompita por servo {service} !",
"diagnosis_services_bad_status": "Servo {service} estas {status} :(",
"diagnosis_ram_low": "La sistemo havas {available} ({available_percent}%) RAM forlasita de {total}. Estu zorgema.",
"diagnosis_swap_ok": "La sistemo havas {total} da interŝanĝoj!",
"diagnosis_mail_ougoing_port_25_ok": "Eliranta haveno 25 ne estas blokita kaj retpoŝto povas esti sendita al aliaj serviloj.",
"diagnosis_regenconf_allgood": "Ĉiuj agordaj dosieroj kongruas kun la rekomendita agordo!",
"diagnosis_regenconf_manually_modified": "Agordodosiero {file} estis permane modifita.",
"diagnosis_description_ip": "Interreta konektebleco",
"diagnosis_description_dnsrecords": "Registroj DNS",
"diagnosis_description_services": "Servo kontrolas staton",
"diagnosis_description_systemresources": "Rimedaj sistemoj",
"diagnosis_description_security": "Sekurecaj kontroloj",
"diagnosis_ports_could_not_diagnose": "Ne povis diagnozi, ĉu haveblaj havenoj de ekstere.",
"diagnosis_ports_could_not_diagnose_details": "Eraro: {error}",
"diagnosis_services_bad_status_tip": "Vi povas provi rekomenci la servon, kaj se ĝi ne funkcias, trarigardu la servajn protokolojn uzante 'yunohost service log {service}' aŭ tra la sekcio 'Servoj' de la retadreso.",
"diagnosis_security_vulnerable_to_meltdown_details": "Por ripari tion, vi devas ĝisdatigi vian sistemon kaj rekomenci por ŝarĝi la novan linux-kernon (aŭ kontaktu vian servilan provizanton se ĉi tio ne funkcias). Vidu https://meltdownattack.com/ por pliaj informoj.",
"diagnosis_description_basesystem": "Baza sistemo",
"diagnosis_description_regenconf": "Sistemaj agordoj",
"main_domain_change_failed": "Ne eblas ŝanĝi la ĉefan domajnon",
"log_domain_main_domain": "Faru '{}' kiel ĉefa domajno",
"diagnosis_http_timeout": "Tempolimigita dum provado kontakti vian servilon de ekstere. Ĝi ŝajnas esti neatingebla. Vi devus kontroli, ke vi ĝuste redonas la havenon 80, ke nginx funkcias kaj ke fajroŝirmilo ne interbatalas.",
"diagnosis_http_connection_error": "Rilata eraro: ne povis konektiĝi al la petita domajno, tre probable ĝi estas neatingebla.",
"migration_description_0013_futureproof_apps_catalog_system": "Migru al la nova katalogosistemo pri estontecaj programoj",
"diagnosis_ignored_issues": "(+ {nb_ignored} ignorataj aferoj))",
"diagnosis_found_errors": "Trovis {errors} signifa(j) afero(j) rilata al {category}!",
"diagnosis_found_errors_and_warnings": "Trovis {errors} signifaj problemo (j) (kaj {warnings} averto) rilataj al {category}!",
"diagnosis_diskusage_low": "Stokado {mountpoint} (sur aparato {device)) restas nur {free} ({free_percent}%) spaco. Estu zorgema.",
"diagnosis_diskusage_ok": "Stokado {mountpoint} (sur aparato {device) ankoraŭ restas {free} ({free_percent}%) spaco!",
"global_settings_setting_pop3_enabled": "Ebligu la protokolon POP3 por la poŝta servilo",
"diagnosis_unknown_categories": "La jenaj kategorioj estas nekonataj: {categories}",
"diagnosis_services_running": "Servo {service} funkcias!",
"diagnosis_ports_unreachable": "Haveno {port} ne atingeblas de ekstere.",
"diagnosis_ports_ok": "Haveno {port} atingeblas de ekstere.",
"diagnosis_ports_needed_by": "Eksponi ĉi tiun havenon necesas por servo {service}",
"diagnosis_ports_forwarding_tip": "Por solvi ĉi tiun problemon, plej probable vi devas agordi la plusendon de haveno en via interreta enkursigilo kiel priskribite en https://yunohost.org/isp_box_config",
"diagnosis_http_could_not_diagnose": "Ne povis diagnozi, ĉu atingeblas domajno de ekstere.",
"diagnosis_http_could_not_diagnose_details": "Eraro: {error}",
"diagnosis_http_ok": "Domajno {domain} atingeblas de ekstere.",
"diagnosis_http_unreachable": "Domajno {domain} estas atingebla per HTTP de ekstere.",
"domain_cannot_remove_main_add_new_one": "Vi ne povas forigi '{domain:s}' ĉar ĝi estas la ĉefa domajno kaj via sola domajno, vi devas unue aldoni alian domajnon uzante ''yunohost domain add <another-domain.com>', tiam agordi kiel ĉefan domajnon uzante 'yunohost domain main-domain -n <another-domain.com>' kaj tiam vi povas forigi la domajnon' {domain:s} 'uzante' yunohost domain remove {domain:s} '.'",
"permission_require_account": "Permesilo {permission} nur havas sencon por uzantoj, kiuj havas konton, kaj tial ne rajtas esti ebligitaj por vizitantoj.",
"diagnosis_found_warnings": "Trovitaj {warnings} ero (j) kiuj povus esti plibonigitaj por {category}.",
"diagnosis_everything_ok": "Ĉio aspektas bone por {category}!",
"diagnosis_failed": "Malsukcesis preni la diagnozan rezulton por kategorio '{category}': {error}",
"diagnosis_description_ports": "Ekspoziciaj havenoj",
"diagnosis_description_mail": "Retpoŝto",
"log_app_action_run": "Funkciigu agon de la apliko '{}'",
"log_app_config_show_panel": "Montri la agordan panelon de la apliko '{}'",
"log_app_config_apply": "Apliki agordon al la apliko '{}'"
}

View file

@ -9,82 +9,53 @@
"app_argument_required": "Se requiere el argumento '{name:s} 7'",
"app_extraction_failed": "No se pudieron extraer los archivos de instalación",
"app_id_invalid": "ID de la aplicación no válida",
"app_incompatible": "La aplicación {app} no es compatible con su versión de YunoHost",
"app_install_files_invalid": "Estos archivos no se pueden instalar",
"app_location_already_used": "La aplicación «{app}» ya está instalada en ({path})",
"app_location_install_failed": "No se puede instalar la aplicación ahí porque entra en conflicto con la aplicación «{other_app}» ya instalada en «{other_path}»",
"app_manifest_invalid": "Algo va mal con el manifiesto de la aplicación: {error}",
"app_no_upgrade": "Todas las aplicaciones están ya actualizadas",
"app_not_correctly_installed": "La aplicación {app:s} 8 parece estar incorrectamente instalada",
"app_not_installed": "No se pudo encontrar la aplicación «{app:s}» en la lista de aplicaciones instaladas: {all_apps}",
"app_not_properly_removed": "La {app:s} 0 no ha sido desinstalada correctamente",
"app_package_need_update": "El paquete de la aplicación {app} necesita ser actualizada debido a los cambios en YunoHost",
"app_recent_version_required": "{:s} requiere una versión más reciente de moulinette ",
"app_removed": "Eliminado {app:s}",
"app_requirements_checking": "Comprobando los paquetes necesarios para {app}…",
"app_requirements_failed": "No se cumplen algunos requisitos para {app}: {error}",
"app_requirements_unmeet": "No se cumplen los requisitos para {app}, el paquete {pkgname} ({version}) debe ser {spec}",
"app_sources_fetch_failed": "No se pudieron obtener los archivos con el código fuente, ¿es el URL correcto?",
"app_unknown": "Aplicación desconocida",
"app_unsupported_remote_type": "Tipo remoto no soportado por la aplicación",
"app_upgrade_failed": "No se pudo actualizar {app:s}",
"app_upgrade_failed": "No se pudo actualizar {app:s}: {error}",
"app_upgraded": "Actualizado {app:s}",
"appslist_fetched": "Obtenida lista de aplicaciones {appslist:s} actualizada",
"appslist_removed": "Eliminada la lista de aplicaciones {appslist:s}",
"appslist_retrieve_error": "No se puede recuperar la lista remota de aplicaciones {appslist:s}: {error:s}",
"appslist_unknown": "Lista de aplicaciones {appslist:s} desconocida.",
"ask_current_admin_password": "Contraseña administrativa actual",
"ask_email": "Dirección de correo electrónico",
"ask_firstname": "Nombre",
"ask_lastname": "Apellido",
"ask_list_to_remove": "Lista para desinstalar",
"ask_main_domain": "Dominio principal",
"ask_new_admin_password": "Nueva contraseña administrativa",
"ask_password": "Contraseña",
"backup_action_required": "Debe especificar algo que guardar",
"backup_app_failed": "No se pudo respaldar la aplicación «{app:s}»",
"backup_archive_app_not_found": "No se pudo encontrar la aplicación «{app:s}» en el archivo de respaldo",
"backup_archive_hook_not_exec": "El hook {hook:s} no ha sido ejecutado en esta copia de seguridad",
"backup_archive_name_exists": "Ya existe un archivo de respaldo con este nombre.",
"backup_archive_name_unknown": "Copia de seguridad local desconocida '{name:s}'",
"backup_archive_open_failed": "No se pudo abrir el archivo de respaldo",
"backup_cleaning_failed": "No se pudo limpiar la carpeta de respaldo temporal",
"backup_created": "Se ha creado la copia de seguridad",
"backup_creating_archive": "Creando el archivo de copia de seguridad…",
"backup_creation_failed": "No se pudo crear el archivo de respaldo",
"backup_delete_error": "No se pudo eliminar «{path:s}»",
"backup_deleted": "Eliminada la copia de seguridad",
"backup_extracting_archive": "Extrayendo el archivo de respaldo…",
"backup_hook_unknown": "El gancho «{hook:s}» de la copia de seguridad es desconocido",
"backup_invalid_archive": "Esto no es un archivo de respaldo",
"backup_nothings_done": "Nada que guardar",
"backup_output_directory_forbidden": "Elija un directorio de salida diferente. No se pueden crear copias de seguridad en las subcarpetas de /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var o /home/yunohost.backup/archives",
"backup_output_directory_not_empty": "Debe elegir un directorio de salida vacío",
"backup_output_directory_required": "Debe proporcionar un directorio de salida para la copia de seguridad",
"backup_running_app_script": "Ejecutando la script de copia de seguridad de la aplicación '{app:s}'...",
"backup_running_hooks": "Ejecutando los hooks de copia de seguridad...",
"custom_app_url_required": "Debe proporcionar una URL para actualizar su aplicación personalizada {app:s}",
"custom_appslist_name_required": "Debe proporcionar un nombre para su lista de aplicaciones personalizadas",
"diagnosis_debian_version_error": "No se pudo obtener la versión de Debian: {error}",
"diagnosis_kernel_version_error": "No se pudo obtener la versión del núcleo: {error}",
"diagnosis_monitor_disk_error": "No se pudieron monitorizar los discos: {error}",
"diagnosis_monitor_network_error": "No se pudo monitorizar la red: {error}",
"diagnosis_monitor_system_error": "No se pudo monitorizar el sistema: {error}",
"diagnosis_no_apps": "Aplicación no instalada",
"dnsmasq_isnt_installed": "Parece que dnsmasq no está instalado, ejecute «apt-get remove bind9 && apt-get install it»",
"domain_cert_gen_failed": "No se pudo generar el certificado",
"domain_created": "Dominio creado",
"domain_creation_failed": "No se pudo crear el dominio",
"domain_creation_failed": "No se pudo crear el dominio {domain}: {error}",
"domain_deleted": "Dominio eliminado",
"domain_deletion_failed": "No se pudo eliminar el dominio",
"domain_deletion_failed": "No se pudo eliminar el dominio {domain}: {error}",
"domain_dyndns_already_subscribed": "Ya se ha suscrito a un dominio de DynDNS",
"domain_dyndns_invalid": "Este dominio no se puede usar con DynDNS",
"domain_dyndns_root_unknown": "Dominio raíz de DynDNS desconocido",
"domain_exists": "El dominio ya existe",
"domain_uninstall_app_first": "Una o más aplicaciones están instaladas en este dominio. Debe desinstalarlas antes de eliminar el dominio",
"domain_unknown": "Dominio desconocido",
"domain_zone_exists": "El archivo de zona del DNS ya existe",
"domain_zone_not_found": "No se ha encontrado el archivo de zona del DNS para el dominio [:s]",
"done": "Hecho.",
"downloading": "Descargando…",
"dyndns_cron_installed": "Creado el trabajo de cron de DynDNS",
@ -104,10 +75,7 @@
"field_invalid": "Campo no válido '{:s}'",
"firewall_reload_failed": "No se pudo recargar el cortafuegos",
"firewall_reloaded": "Cortafuegos recargado",
"firewall_rules_cmd_failed": "Algunas órdenes de las reglas del cortafuegos han fallado. Más información en el registro.",
"format_datetime_short": "%d/%m/%Y %I:%M %p",
"hook_argument_missing": "Falta un parámetro '{:s}'",
"hook_choice_invalid": "Selección inválida '{:s}'",
"firewall_rules_cmd_failed": "Algunos comandos para aplicar reglas del cortafuegos han fallado. Más información en el registro.",
"hook_exec_failed": "No se pudo ejecutar el guión: {path:s}",
"hook_exec_not_terminated": "El guión no terminó correctamente:{path:s}",
"hook_list_by_invalid": "Esta propiedad no se puede usar para enumerar ganchos («hooks»)",
@ -117,98 +85,52 @@
"ip6tables_unavailable": "No puede modificar ip6tables aquí. O bien está en un 'container' o su kernel no soporta esta opción",
"iptables_unavailable": "No puede modificar iptables aquí. O bien está en un 'container' o su kernel no soporta esta opción",
"ldap_initialized": "Inicializado LDAP",
"license_undefined": "indefinido",
"mail_alias_remove_failed": "No se pudo eliminar el alias de correo «{mail:s}»",
"mail_domain_unknown": "Dirección de correo desconocida para el dominio «{domain:s}»",
"mail_domain_unknown": "Dirección de correo no válida para el dominio «{domain:s}». Use un dominio administrado por este servidor.",
"mail_forward_remove_failed": "No se pudo eliminar el reenvío de correo «{mail:s}»",
"maindomain_change_failed": "No se pudo cambiar el dominio principal",
"maindomain_changed": "El dominio principal ha cambiado",
"monitor_disabled": "Desactivada la monitorización del servidor",
"monitor_enabled": "Activada la monitorización del servidor",
"monitor_glances_con_failed": "No se pudo conectar al servidor de Glances",
"monitor_not_enabled": "La monitorización del servidor está apagada",
"monitor_period_invalid": "Período de tiempo no válido",
"monitor_stats_file_not_found": "No se pudo encontrar el archivo de estadísticas",
"monitor_stats_no_update": "No hay estadísticas de monitorización para actualizar",
"monitor_stats_period_unavailable": "No hay estadísticas para el período",
"mountpoint_unknown": "Punto de montaje desconocido",
"mysql_db_creation_failed": "Error al crear la base de datos de MySQL",
"mysql_db_init_failed": "Error al iniciar la base de datos de MySQL",
"mysql_db_initialized": "Inicializada la base de datos MySQL",
"network_check_mx_ko": "El registro DNS MX no está configurado",
"network_check_smtp_ko": "El correo saliente (SMTP puerto 25) parece estar bloqueado por su red",
"network_check_smtp_ok": "El correo saliente (SMTP puerto 25) no está bloqueado",
"new_domain_required": "Debe proporcionar el nuevo dominio principal",
"no_appslist_found": "No se ha encontrado ninguna lista de aplicaciones",
"main_domain_change_failed": "No se pudo cambiar el dominio principal",
"main_domain_changed": "El dominio principal ha cambiado",
"no_internet_connection": "El servidor no está conectado a Internet",
"no_ipv6_connectivity": "La conexión por IPv6 no está disponible",
"no_restore_script": "No se ha encontrado un script de restauración para la aplicación '{app:s}'",
"not_enough_disk_space": "No hay espacio libre suficiente en «{path:s}»",
"package_not_installed": "El paquete '{pkgname}' no está instalado",
"package_unexpected_error": "Ha ocurrido un error inesperado procesando el paquete '{pkgname}'",
"package_unknown": "Paquete desconocido '{pkgname}'",
"packages_no_upgrade": "No hay paquetes para actualizar",
"packages_upgrade_critical_later": "Los paquetes críticos ({packages:s}) serán actualizados más tarde",
"packages_upgrade_failed": "No se pudieron actualizar todos los paquetes",
"path_removal_failed": "No se pudo eliminar la ruta {:s}",
"pattern_backup_archive_name": "Debe ser un nombre de archivo válido con un máximo de 30 caracteres, solo se admiten caracteres alfanuméricos y los caracteres -_. (guiones y punto)",
"pattern_domain": "El nombre de dominio debe ser válido (por ejemplo mi-dominio.org)",
"pattern_email": "Debe ser una dirección de correo electrónico válida (por ejemplo, alguien@dominio.org)",
"pattern_email": "Debe ser una dirección de correo electrónico válida (p.ej. alguien@example.com)",
"pattern_firstname": "Debe ser un nombre válido",
"pattern_lastname": "Debe ser un apellido válido",
"pattern_listname": "Solo se pueden usar caracteres alfanuméricos y el guion bajo",
"pattern_mailbox_quota": "Debe ser un tamaño con el sufijo «b/k/M/G/T» o «0» para no tener una cuota",
"pattern_password": "Debe contener al menos 3 caracteres",
"pattern_port": "Debe ser un número de puerto válido (es decir, entre 0-65535)",
"pattern_port_or_range": "Debe ser un número de puerto válido (es decir entre 0-65535) o un intervalo de puertos (por ejemplo 100:200)",
"pattern_positive_number": "Deber ser un número positivo",
"pattern_username": "Solo puede contener caracteres alfanuméricos o el guión bajo",
"port_already_closed": "El puerto {port:d} ya está cerrado para las conexiones {ip_version:s}",
"port_already_opened": "El puerto {port:d} ya está abierto para las conexiones {ip_version:s}",
"port_available": "El puerto {port:d} está disponible",
"port_unavailable": "El puerto {port:d} no está disponible",
"restore_action_required": "Debe escoger algo que restaurar",
"restore_already_installed_app": "Una aplicación con el ID «{app:s}» ya está instalada",
"restore_app_failed": "No se pudo restaurar la aplicación «{app:s}»",
"restore_cleaning_failed": "No se pudo limpiar el directorio temporal de restauración",
"restore_complete": "Restaurada",
"restore_confirm_yunohost_installed": "¿Realmente desea restaurar un sistema ya instalado? [{answers:s}]",
"restore_failed": "No se pudo restaurar el sistema",
"restore_hook_unavailable": "El guión de restauración para «{part:s}» no está disponible en su sistema y tampoco en el archivo",
"restore_hook_unavailable": "El script de restauración para «{part:s}» no está disponible en su sistema y tampoco en el archivo",
"restore_nothings_done": "No se ha restaurado nada",
"restore_running_app_script": "Restaurando la aplicación «{app:s}»…",
"restore_running_hooks": "Ejecutando los ganchos de restauración…",
"service_add_failed": "No se pudo añadir el servicio «{service:s}»",
"service_added": "Añadido el servicio «{service:s}»",
"service_already_started": "El servicio «{service:s}» ya ha sido iniciado",
"service_already_started": "El servicio «{service:s}» ya está funcionando",
"service_already_stopped": "El servicio «{service:s}» ya ha sido detenido",
"service_cmd_exec_failed": "No se pudo ejecutar la orden «{command:s}»",
"service_conf_file_backed_up": "Se ha realizado una copia de seguridad del archivo de configuración '{conf}' en '{backup}'",
"service_conf_file_copy_failed": "No se puede copiar el nuevo archivo de configuración '{new}' a {conf}",
"service_conf_file_manually_modified": "El archivo de configuración '{conf}' ha sido modificado manualmente y no será actualizado",
"service_conf_file_manually_removed": "El archivo de configuración '{conf}' ha sido eliminado manualmente y no será creado",
"service_conf_file_not_managed": "El archivo de configuración '{conf}' no está gestionado y no será actualizado",
"service_conf_file_remove_failed": "No se puede eliminar el archivo de configuración '{conf}'",
"service_conf_file_removed": "El archivo de configuración '{conf}' ha sido eliminado",
"service_conf_file_updated": "El archivo de configuración '{conf}' ha sido actualizado",
"service_conf_up_to_date": "La configuración del servicio '{service}' ya está actualizada",
"service_conf_updated": "La configuración ha sido actualizada para el servicio '{service}'",
"service_conf_would_be_updated": "La configuración podría haber sido actualizada para el servicio '{service} 1'",
"service_disable_failed": "No se pudo desactivar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_disabled": "Desactivado el servicio «{service:s}»",
"service_disabled": "El servicio «{service:s}» ha sido desactivado",
"service_enable_failed": "No se pudo activar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_enabled": "Activado el servicio «{service:s}»",
"service_no_log": "No hay ningún registro para el servicio '{service:s}'",
"service_regenconf_dry_pending_applying": "Comprobando configuración pendiente que podría haber sido aplicada al servicio '{service}'...",
"service_regenconf_failed": "No se puede regenerar la configuración para el servicio(s): {services}",
"service_regenconf_pending_applying": "Aplicando la configuración pendiente para el servicio '{service}'...",
"service_enabled": "El servicio «{service:s}» ha sido desactivado",
"service_remove_failed": "No se pudo eliminar el servicio «{service:s}»",
"service_removed": "Eliminado el servicio «{service:s}»",
"service_start_failed": "No se pudo iniciar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_started": "Iniciado el servicio «{service:s}»",
"service_status_failed": "No se pudo determinar el estado del servicio «{service:s}»",
"service_stop_failed": "No se pudo detener el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_stopped": "Detenido el servicio «{service:s}»",
"service_stopped": "El servicio «{service:s}» se detuvo",
"service_unknown": "Servicio desconocido '{service:s}'",
"ssowat_conf_generated": "Generada la configuración de SSOwat",
"ssowat_conf_updated": "Actualizada la configuración de SSOwat",
@ -216,10 +138,8 @@
"system_username_exists": "El nombre de usuario ya existe en la lista de usuarios del sistema",
"unbackup_app": "La aplicación '{app:s}' no se guardará",
"unexpected_error": "Algo inesperado salió mal: {error}",
"unit_unknown": "Unidad desconocida '{unit:s}'",
"unlimit": "Sin cuota",
"unrestore_app": "La aplicación '{app:s}' no será restaurada",
"update_cache_failed": "No se pudo actualizar la caché de APT",
"updating_apt_cache": "Obteniendo las actualizaciones disponibles para los paquetes del sistema…",
"upgrade_complete": "Actualización finalizada",
"upgrading_packages": "Actualizando paquetes…",
@ -228,23 +148,20 @@
"upnp_enabled": "UPnP activado",
"upnp_port_open_failed": "No se pudo abrir el puerto vía UPnP",
"user_created": "Usuario creado",
"user_creation_failed": "No se pudo crear el usuario",
"user_creation_failed": "No se pudo crear el usuario {user}: {error}",
"user_deleted": "Usuario eliminado",
"user_deletion_failed": "No se pudo eliminar el usuario",
"user_deletion_failed": "No se pudo eliminar el usuario {user}: {error}",
"user_home_creation_failed": "No se pudo crear la carpeta «home» para el usuario",
"user_info_failed": "No se pudo obtener la información del usuario",
"user_unknown": "Usuario desconocido: {user:s}",
"user_update_failed": "No se pudo cambiar la información del usuario",
"user_update_failed": "No se pudo actualizar el usuario {user}: {error}",
"user_updated": "Cambiada la información de usuario",
"yunohost_already_installed": "YunoHost ya está instalado",
"yunohost_ca_creation_failed": "No se pudo crear la autoridad de certificación",
"yunohost_configured": "YunoHost está configurado",
"yunohost_configured": "YunoHost está ahora configurado",
"yunohost_installing": "Instalando YunoHost…",
"yunohost_not_installed": "YunoHost no está correctamente instalado. Ejecute «yunohost tools postinstall»",
"ldap_init_failed_to_create_admin": "La inicialización de LDAP no pudo crear el usuario «admin»",
"mailbox_used_space_dovecot_down": "El servicio de correo Dovecot debe estar funcionando si desea obtener el espacio usado por el buzón de correo",
"ssowat_persistent_conf_read_error": "No se pudo leer la configuración persistente de SSOwat: {error:s}. Edite el archivo /etc/ssowat/conf.json.persistent para corregir la sintaxis de JSON",
"ssowat_persistent_conf_write_error": "No se pudo guardar la configuración persistente de SSOwat: {error:s}. Edite el archivo /etc/ssowat/conf.json.persistent para corregir la sintaxis de JSON",
"certmanager_attempt_to_replace_valid_cert": "Está intentando sobrescribir un certificado correcto y válido para el dominio {domain:s}! (Use --force para omitir este mensaje)",
"certmanager_domain_unknown": "Dominio desconocido «{domain:s}»",
"certmanager_domain_cert_not_selfsigned": "El certificado para el dominio {domain:s} no es un certificado autofirmado. ¿Está seguro de que quiere reemplazarlo? (Use «--force» para hacerlo)",
@ -258,50 +175,38 @@
"certmanager_cert_install_success_selfsigned": "Instalado correctamente un certificado autofirmado para el dominio «{domain:s}»",
"certmanager_cert_install_success": "Instalado correctamente un certificado de Let's Encrypt para el dominio «{domain:s}»",
"certmanager_cert_renew_success": "Renovado correctamente el certificado de Let's Encrypt para el dominio «{domain:s}»",
"certmanager_old_letsencrypt_app_detected": "\nYunohost ha detectado que la aplicación 'letsencrypt' está instalada, esto produce conflictos con las nuevas funciones de administración de certificados integradas en Yunohost. Si desea utilizar las nuevas funciones integradas, ejecute los siguientes comandos para migrar su instalación:\n\n Yunohost app remove letsencrypt\n Yunohost domain cert-install\n\nP.D.: esto intentará reinstalar los certificados para todos los dominios con un certificado Let's Encrypt o con un certificado autofirmado",
"certmanager_hit_rate_limit": "Se han emitido demasiados certificados recientemente para este conjunto exacto de dominios {domain:s}. Pruebe de nuevo más tarde. Vea para más detalles https://letsencrypt.org/docs/rate-limits/",
"certmanager_cert_signing_failed": "No se pudo firmar el nuevo certificado",
"certmanager_no_cert_file": "No se pudo leer el certificado para el dominio {domain:s} (archivo: {file:s})",
"certmanager_conflicting_nginx_file": "No se pudo preparar el dominio para el desafío ACME: el archivo de configuración de NGINX {filepath:s} está en conflicto y debe ser eliminado primero",
"domain_cannot_remove_main": "No se puede eliminar el dominio principal. Configure uno primero",
"domain_cannot_remove_main": "No se puede eliminar el dominio principal. Primero debes configurar otro utilizando la linea de comando 'yunohost domain main-domain -n <otro_dominio>' donde <otro_dominio> es parte de esta lista: {other_domains:s}",
"certmanager_self_ca_conf_file_not_found": "No se pudo encontrar el archivo de configuración para la autoridad de autofirma (archivo: {file:s})",
"certmanager_unable_to_parse_self_CA_name": "No se pudo procesar el nombre de la autoridad de autofirma (archivo: {file:s})",
"domains_available": "Dominios disponibles:",
"backup_archive_broken_link": "No se pudo acceder al archivo de respaldo (enlace roto a {path:s})",
"certmanager_domain_not_resolved_locally": "El dominio {domain:s} no puede ser resuelto desde su servidor de YunoHost. Esto puede suceder si ha modificado su registro DNS recientemente. De ser así, espere unas horas para que se propague. Si el problema continúa, considere añadir {domain:s} a /etc/hosts. (Si sabe lo que está haciendo, use «--no-checks» para desactivar esas comprobaciones.)",
"certmanager_acme_not_configured_for_domain": "El certificado para el dominio «{domain:s}» no parece que esté instalado correctamente. Ejecute primero «cert-install» para este dominio.",
"certmanager_http_check_timeout": "Tiempo de espera agotado cuando el servidor intentaba conectarse consigo mismo a través de HTTP usando una dirección IP pública (dominio «{domain:s}» con IP «{ip:s}»). Puede que esté experimentando un problema de redirección («hairpinning»), o que el cortafuegos o el enrutador de su servidor esté mal configurado.",
"certmanager_couldnt_fetch_intermediate_cert": "Tiempo de espera agotado intentando obtener el certificado intermedio de Let's Encrypt. Cancelada la instalación o renovación del certificado. Vuelva a intentarlo más tarde.",
"appslist_retrieve_bad_format": "No se pudo leer la lista de aplicaciones obtenida {appslist:s}",
"domain_hostname_failed": "No se pudo establecer un nuevo nombre de anfitrión («hostname»). Esto podría causar problemas más tarde (no es seguro... podría ir bien).",
"yunohost_ca_creation_success": "Creada la autoridad de certificación local.",
"app_already_installed_cant_change_url": "Esta aplicación ya está instalada. No se puede cambiar el URL únicamente mediante esta función. Compruebe si está disponible la opción `app changeurl`.",
"app_change_no_change_url_script": "La aplicacion {app_name:s} aún no permite cambiar su URL, es posible que deba actualizarla.",
"app_change_url_failed_nginx_reload": "No se pudo recargar NGINX. Esta es la salida de «nginx -t»:\n{nginx_errors:s}",
"app_change_url_identical_domains": "El antiguo y nuevo dominio/url_path son idénticos ('{domain:s} {path:s}'), no se realizarán cambios.",
"app_change_url_no_script": "Esta aplicación «{app_name:s}» aún no permite la modificación de URLs. Quizás debería actualizarla.",
"app_change_url_no_script": "La aplicación «{app_name:s}» aún no permite la modificación de URLs. Quizás debería actualizarla.",
"app_change_url_success": "El URL de la aplicación {app:s} es ahora {domain:s} {path:s}",
"app_location_unavailable": "Este URL o no está disponible o está en conflicto con otra(s) aplicación(es) instalada(s):\n{apps:s}",
"app_already_up_to_date": "La aplicación {app:s} ya está actualizada",
"appslist_name_already_tracked": "Ya existe una lista de aplicaciones registradas con el nombre {name:s}.",
"appslist_url_already_tracked": "Ya existe una lista de aplicaciones registradas con el URL {url:s}.",
"appslist_migrating": "Migrando la lista de aplicaciones {appslist:s}…",
"appslist_could_not_migrate": "¡No se pudo migrar la lista de aplicaciones {appslist:s}! No se pudo analizar el URL… El antiguo trabajo de cron se mantuvo en {bkp_file:s}.",
"appslist_corrupted_json": "No se pudieron cargar las listas de aplicaciones. Parece que {filename:s} está dañado.",
"invalid_url_format": "Algo va mal con el URL",
"app_upgrade_some_app_failed": "No se pudieron actualizar algunas aplicaciones",
"app_make_default_location_already_used": "No puede hacer que la aplicación «{app}» sea la predeterminada en el dominio, {domain} ya está siendo usado por otra aplicación «{other_app}»",
"app_make_default_location_already_used": "No puede hacer que la aplicación «{app}» sea la predeterminada en el dominio, «{domain}» ya está siendo usado por otra aplicación «{other_app}»",
"app_upgrade_app_name": "Actualizando ahora {app}…",
"ask_path": "Camino",
"backup_abstract_method": "Este método de respaldo aún no se ha implementado",
"backup_applying_method_borg": "Enviando todos los archivos para la copia de seguridad al repositorio de borg-backup…",
"backup_applying_method_copy": "Copiando todos los archivos a la copia de seguridad…",
"backup_applying_method_custom": "Llamando al método de copia de seguridad personalizado «{method:s}»…",
"backup_applying_method_tar": "Creando el archivo TAR de respaldo…",
"backup_archive_mount_failed": "No se pudo montar el archivo de respaldo",
"backup_archive_system_part_not_available": "La parte del sistema «{part:s}» no está disponible en esta copia de seguridad",
"backup_archive_writing_error": "No se pudieron añadir los archivos «{source:s}» (llamados en el archivo «{dest:s}») para ser respaldados en el archivo comprimido «{archive:s}»",
"backup_ask_for_copying_if_needed": "No se pudieron preparar algunos archivos para la copia de seguridad usando el método que evita desperdiciar espacio temporalmente en el sistema. Para hacer la copia de seguridad, {size:s}MB se usarán temporalmente. ¿Está de acuerdo?",
"backup_ask_for_copying_if_needed": "¿Quiere realizar la copia de seguridad usando {size:s} MB temporalmente? (Se usa este modo ya que algunos archivos no se pudieron preparar usando un método más eficiente.)",
"backup_borg_not_implemented": "El método de respaldo de Borg aún no ha sido implementado",
"backup_cant_mount_uncompress_archive": "No se pudo montar el archivo descomprimido como protegido contra escritura",
"backup_copying_to_organize_the_archive": "Copiando {size:s}MB para organizar el archivo",
@ -309,7 +214,6 @@
"backup_csv_addition_failed": "No se pudo añadir archivos para respaldar en el archivo CSV",
"backup_csv_creation_failed": "No se pudo crear el archivo CSV necesario para la restauración",
"backup_custom_mount_error": "El método de respaldo personalizado no pudo superar el paso «mount»",
"backup_custom_need_mount_error": "El método de respaldo personalizado no pudo superar el paso «need_mount»",
"backup_no_uncompress_archive_dir": "No existe tal directorio de archivos sin comprimir",
"backup_php5_to_php7_migration_may_fail": "No se pudo convertir su archivo para que sea compatible con PHP 7, puede que no pueda restaurar sus aplicaciones de PHP (motivo: {error:s})",
"backup_system_part_failed": "No se pudo respaldar la parte del sistema «{part:s}»",
@ -320,33 +224,28 @@
"experimental_feature": "Aviso : esta funcionalidad es experimental y no se considera estable, no debería usarla a menos que sepa lo que está haciendo.",
"good_practices_about_user_password": "Está a punto de establecer una nueva contraseña de usuario. La contraseña debería de ser de al menos 8 caracteres, aunque es una buena práctica usar una contraseña más extensa (básicamente una frase) y/o usar caracteres de varias clases (mayúsculas, minúsculas, números y caracteres especiales).",
"password_listed": "Esta contraseña es una de las más usadas en el mundo. Elija algo más único.",
"password_too_simple_1": "La contraseña tiene que ser de al menos 8 caracteres de longitud",
"password_too_simple_1": "La contraseña debe tener al menos 8 caracteres de longitud",
"password_too_simple_2": "La contraseña tiene que ser de al menos 8 caracteres de longitud e incluir un número y caracteres en mayúsculas y minúsculas",
"password_too_simple_3": "La contraseña tiene que ser de al menos 8 caracteres de longitud e incluir un número, mayúsculas, minúsculas y caracteres especiales",
"password_too_simple_4": "La contraseña tiene que ser de al menos 12 caracteres de longitud e incluir un número, mayúsculas, minúsculas y caracteres especiales",
"users_available": "Usuarios disponibles:",
"user_not_in_group": "El usuario «{user:s}» no está en el grupo «{group:s}»",
"user_already_in_group": "El usuario «{user:}» ya está en el grupo «{group:s}»",
"updating_app_lists": "Obteniendo actualizaciones disponibles para las aplicaciones…",
"update_apt_cache_warning": "Algo fue mal durante la actualización de la caché de APT (gestor de paquetes de Debian). Aquí tiene un volcado de las líneas de sources.list que podría ayudarle a identificar las líneas problemáticas:\n{sourceslist}",
"update_apt_cache_failed": "No se pudo actualizar la caché de APT (gestor de paquetes de Debian). Aquí tiene un volcado de las líneas de sources.list que podría ayudarle a identificar las líneas problemáticas:\n{sourceslist}",
"tools_upgrade_special_packages_completed": "Actualización de paquetes de YunoHost completada.\nPulse [Intro] para regresar a la línea de órdenes",
"tools_upgrade_special_packages_explanation": "Esta acción terminará pero la actualización especial real continuará en segundo plano. No inicie ninguna otra acción en su servidor en aproximadamente 10 minutos (dependiendo de la velocidad de su hardware). Una vez que esté hecho, podría tener que volver a iniciar sesión en la administración web. El registro de actualización estará disponible en Herramientas → Registro (en la página de administración web) o mediante «yunohost log list» (desde la línea de órdenes).",
"tools_upgrade_special_packages_explanation": "Esta acción terminará pero la actualización especial real continuará en segundo plano. No inicie ninguna otra acción en su servidor en aproximadamente 10 minutos (dependiendo de la velocidad de su hardware). Una vez hecho, podría tener que volver a iniciar sesión en la administración web. El registro de actualización estará disponible en Herramientas → Registro (en la página de administración web) o mediante «yunohost log list» (desde la línea de órdenes).",
"tools_upgrade_special_packages": "Actualizando ahora paquetes «especiales» (relacionados con YunoHost)…",
"tools_upgrade_regular_packages_failed": "No se pudieron actualizar los paquetes: {packages_list}",
"tools_upgrade_regular_packages": "Actualizando ahora paquetes «normales» (no relacionados con YunoHost)…",
"tools_upgrade_cant_unhold_critical_packages": "No se pudieron liberar los paquetes críticos…",
"tools_upgrade_cant_unhold_critical_packages": "No se pudo liberar los paquetes críticos…",
"tools_upgrade_cant_hold_critical_packages": "No se pudieron retener los paquetes críticos…",
"tools_upgrade_cant_both": "No se puede actualizar el sistema y las aplicaciones al mismo tiempo",
"tools_upgrade_at_least_one": "Especifique «--apps», o «--system»",
"tools_update_failed_to_app_fetchlist": "No se pudo actualizar la lista de aplicaciones de YunoHost porque: {error}",
"this_action_broke_dpkg": "Esta acción rompió dpkg/APT(los gestores de paquetes del sistema)… Puede tratar de solucionar este problema conectando mediante SSH y ejecutando `sudo dpkg --configure -a`.",
"system_groupname_exists": "El nombre de grupo ya existe en el grupo del sistema",
"service_reloaded_or_restarted": "Recargado o reiniciado el servicio «{service:s}»",
"service_reloaded_or_restarted": "El servicio «{service:s}» ha sido recargado o reiniciado",
"service_reload_or_restart_failed": "No se pudo recargar o reiniciar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_restarted": "Reiniciado el servicio «{service:s}»",
"service_restart_failed": "No se pudo reiniciar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_reloaded": "Recargado el servicio «{service:s}»",
"service_reloaded": "El servicio «{service:s}» ha sido recargado",
"service_reload_failed": "No se pudo recargar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_regen_conf_is_deprecated": "¡«yunohost service regen-conf» está obsoleto! Use «yunohost tools regen-conf» en su lugar.",
"service_description_yunohost-firewall": "Gestiona los puertos de conexiones abiertos y cerrados a los servicios",
@ -354,15 +253,13 @@
"service_description_ssh": "Permite conectar a su servidor remotamente mediante un terminal (protocolo SSH)",
"service_description_slapd": "Almacena usuarios, dominios e información relacionada",
"service_description_rspamd": "Filtra correo no deseado y otras características relacionadas con el correo",
"service_description_rmilter": "Comprueba varios parámetros en el correo",
"service_description_redis-server": "Una base de datos especializada usada para el acceso rápido de datos, cola de tareas y comunicación entre programas",
"service_description_postfix": "Usado para enviar y recibir correos",
"service_description_php7.0-fpm": "Ejecuta aplicaciones escritas en PHP con NGINX",
"service_description_nslcd": "Maneja la conexión del intérprete de órdenes («shell») de usuario de YunoHost",
"service_description_nginx": "Sirve o proporciona acceso a todos los sitios web alojados en su servidor",
"service_description_mysql": "Almacena los datos de las aplicaciones (base de datos SQL)",
"service_description_mysql": "Almacena los datos de la aplicación (base de datos SQL)",
"service_description_metronome": "Gestionar las cuentas XMPP de mensajería instantánea",
"service_description_glances": "Supervisa la información del sistema en su servidor",
"service_description_fail2ban": "Protege contra ataques de fuerza bruta y otras clases de ataques desde Internet",
"service_description_dovecot": "Permite a los clientes de correo acceder/obtener correo (vía IMAP y POP3)",
"service_description_dnsmasq": "Maneja la resolución de nombres de dominio (DNS)",
@ -377,13 +274,13 @@
"restore_removing_tmp_dir_failed": "No se pudo eliminar un directorio temporal antiguo",
"restore_not_enough_disk_space": "Espacio insuficiente (espacio: {free_space:d} B, espacio necesario: {needed_space:d} B, margen de seguridad: {margin:d} B)",
"restore_mounting_archive": "Montando archivo en «{path:s}»",
"restore_may_be_not_enough_disk_space": "Parece que su sistema no tiene suficiente espacio (libre: {free_space:d} B, espacio necesario: {needed_space:d} B, margen de seguridad: {margin:d} B)",
"restore_may_be_not_enough_disk_space": "Parece que su sistema no tiene suficiente espacio libre (libre: {free_space:d} B, espacio necesario: {needed_space:d} B, margen de seguridad: {margin:d} B)",
"restore_extracting": "Extrayendo los archivos necesarios para el archivo…",
"regenconf_pending_applying": "Aplicando la configuración pendiente para la categoría «{category}»…",
"regenconf_failed": "No se pudo regenerar la configuración para la(s) categoría(s): {categories}",
"regenconf_dry_pending_applying": "Comprobando la configuración pendiente que habría sido aplicada para la categoría «{category}»…",
"regenconf_would_be_updated": "La configuración habría sido actualizada para la categoría «{category}»",
"regenconf_updated": "Actualizada la configuración para la categoría «{category}»",
"regenconf_updated": "Actualizada la configuración para la categoría '{category}'",
"regenconf_up_to_date": "Ya está actualizada la configuración para la categoría «{category}»",
"regenconf_now_managed_by_yunohost": "El archivo de configuración «{conf}» está gestionado ahora por YunoHost (categoría {category}).",
"regenconf_file_updated": "Actualizado el archivo de configuración «{conf}»",
@ -394,30 +291,25 @@
"regenconf_file_kept_back": "Se espera que el archivo de configuración «{conf}» sea eliminado por regen-conf (categoría {category}) pero ha sido retenido.",
"regenconf_file_copy_failed": "No se pudo copiar el nuevo archivo de configuración «{new}» a «{conf}»",
"regenconf_file_backed_up": "Archivo de configuración «{conf}» respaldado en «{backup}»",
"remove_user_of_group_not_allowed": "No tiene permiso para eliminar al usuario «{user:s}» en el grupo «{group:s}»",
"remove_main_permission_not_allowed": "No se permite eliminar el permiso principal",
"recommend_to_add_first_user": "La posinstalación ha terminado pero YunoHost necesita al menos un usuario para funcionar correctamente, debe añadir uno ejecutando «yunohost user create <nombredeusuario>» o usando la interfaz de administración.",
"permission_update_nothing_to_do": "No hay permisos para actualizar",
"permission_updated": "Actualizado el permiso «{permission:s}» para la aplicación «{app:s}»",
"permission_updated": "Actualizado el permiso «{permission:s}»",
"permission_generated": "Actualizada la base de datos de permisos",
"permission_update_failed": "No se pudo actualizar el permiso",
"permission_update_failed": "No se pudo actualizar el permiso '{permission}': {error}",
"permission_name_not_valid": "Elija un nombre de permiso permitido para «{permission:s}",
"permission_not_found": "No se encontró el permiso «{permission:s}» para la aplicación «{app:s}»",
"permission_deletion_failed": "Falta el permiso «{permission:s}» para eliminar la aplicación «{app:s}»",
"permission_deleted": "Eliminado el permiso «{permission:s}» para la aplicación {app:s}",
"permission_creation_failed": "No se pudo conceder el permiso",
"permission_created": "Creado el permiso «{permission:s}» para la aplicación {app:s}",
"permission_already_exist": "El permiso «{permission:s}» para la aplicación {app:s} ya existe",
"permission_already_clear": "El permiso «{permission:s}» ya está definido para la aplicación {app:s}",
"permission_not_found": "No se encontró el permiso «{permission:s}»",
"permission_deletion_failed": "No se pudo eliminar el permiso «{permission}»: {error}",
"permission_deleted": "Eliminado el permiso «{permission:s}»",
"permission_creation_failed": "No se pudo crear el permiso «{permission}»: {error}",
"permission_created": "Creado el permiso «{permission:s}»",
"permission_already_exist": "El permiso «{permission}» ya existe",
"pattern_password_app": "Las contraseñas no pueden incluir los siguientes caracteres: {forbidden_chars}",
"need_define_permission_before": "Redefina los permisos ejecutando «yunohost user permission add -u USUARIO» antes de eliminar un grupo permitido",
"migrations_to_be_ran_manually": "La migración {id} hay que ejecutarla manualmente. Vaya a Herramientas → Migraciones en la página web de administración o ejecute `yunohost tools migrations migrate`.",
"migrations_success_forward": "Migración {id} completada",
"migrations_skip_migration": "Omitiendo migración {id}…",
"migrations_running_forward": "Ejecutando migración {id}…",
"migrations_pending_cant_rerun": "Esas migraciones están aún pendientes, así que no se pueden volver a ejecutar: {ids}",
"migrations_not_pending_cant_skip": "Esas migraciones no están pendientes, así que no pueden ser omitidas: {ids}",
"migrations_no_such_migration": "No hay ninguna migración llamada {id}",
"migrations_no_such_migration": "No hay ninguna migración llamada «{id}»",
"migrations_no_migrations_to_run": "No hay migraciones que ejecutar",
"migrations_need_to_accept_disclaimer": "Para ejecutar la migración {id} debe aceptar el siguiente descargo de responsabilidad:\n---\n{disclaimer}\n---\nSi acepta ejecutar la migración, vuelva a ejecutar la orden con la opción «--accept-disclaimer».",
"migrations_must_provide_explicit_targets": "Necesita proporcionar objetivos explícitos al usar «--skip» or «--force-rerun»",
@ -426,47 +318,46 @@
"migrations_list_conflict_pending_done": "No puede usar «--previous» y «--done» al mismo tiempo.",
"migrations_exclusive_options": "«--auto», «--skip», and «--force-rerun» son opciones mutuamente excluyentes.",
"migrations_failed_to_load_migration": "No se pudo cargar la migración {id}: {error}",
"migrations_dependencies_not_satisfied": "No se puede ejecutar la migración {id} porque primero necesita ejecutar estas migraciones: {dependencies_id}",
"migrations_cant_reach_migration_file": "No se pudo acceder los archivos de migración en la ruta %s",
"migrations_dependencies_not_satisfied": "Ejecutar estas migraciones: «{dependencies_id}» antes de migrar {id}.",
"migrations_cant_reach_migration_file": "No se pudo acceder a los archivos de migración en la ruta «%s»",
"migrations_already_ran": "Esas migraciones ya se han realizado: {ids}",
"migration_0011_update_LDAP_schema": "Actualizando el esquema de LDAP…",
"migration_0011_update_LDAP_database": "Actualizando la base de datos de LDAP…",
"migration_0011_rollback_success": "Sistema revertido.",
"migration_0011_migration_failed_trying_to_rollback": "Migración fallida… intentando revertir el sistema.",
"migration_0011_migration_failed_trying_to_rollback": "No se pudo migrar… intentando revertir el sistema.",
"migration_0011_migrate_permission": "Migrando permisos desde la configuración de las aplicaciones a LDAP…",
"migration_0011_LDAP_update_failed": "No se pudo actualizar LDAP. Error: {error:s}",
"migration_0011_LDAP_config_dirty": "Parece que ha personalizado la configuración de LDAP. Para esta migración se necesita actualizar la configuración de LDAP.\nNecesita guardar su configuración actual, reiniciar la configuración original ejecutando «yunohost tools regen-conf -f» y reintentar la migración",
"migration_0011_done": "Migración correcta. Ahora puede gestionar los grupos de usuarios.",
"migration_0011_done": "Migración finalizada. Ahora puede gestionar los grupos de usuarios.",
"migration_0011_create_group": "Creando un grupo para cada usuario…",
"migration_0011_can_not_backup_before_migration": "No se pudo respaldar el sistema antes de la migración. Error: {error:s}",
"migration_0011_can_not_backup_before_migration": "El respaldo del sistema no se pudo completar antes de que la migración fallase. Error: {error:s}",
"migration_0011_backup_before_migration": "Creando un respaldo de la base de datos de LDAP y de la configuración de las aplicaciones antes de la migración real.",
"migration_0009_not_needed": "La migración ya ocurrió de algún modo… (?) Omitiendo.",
"migration_0008_no_warning": "No se ha detectado ningún riesgo importante con respecto a la anulación de su configuración SSH ¡sin embargo uno nunca puede estar absolutamente seguro ;)! Ejecute la migración para anularla. Por otra parte, puede omitir la migración aunque no esté recomendado.",
"migration_0008_warning": "Si entiende esos avisos y permite a YunoHost anular su configuración actual, ejecute la migración. Por otra parte puede omitir la migración, aunque no se recomienda.",
"migration_0008_no_warning": "Sobre escribir su configuración SSH debería ser seguro ¡aunque esto no se puede prometer! Ejecute la migración para ignorarla. Por otra parte puede omitir la migración, aunque no se recomienda.",
"migration_0008_warning": "Si entiende esos avisos y quiere que YunoHost ignore su configuración actual, ejecute la migración. Por otra parte puede omitir la migración, aunque no se recomienda.",
"migration_0008_dsa": "• Se desactivará la clave DSA. Así que podría tener que anular un aviso espeluznante de su cliente SSH y volver a comprobar la huella de su servidor;",
"migration_0008_root": "• No podrá conectarse como «root» a través de SSH. En su lugar debe usar el usuario «admin»;",
"migration_0008_port": "• Tendrá que conectarse usando el puerto 22 en vez de su actual puerto SSH personalizado. No dude en reconfigurarlo;",
"migration_0008_general_disclaimer": "Para mejorar la seguridad de su servidor, es recomendable permitir a YunoHost gestionar la configuración de SSH. Su actual configuración de SSH difiere de la recomendación. Si permite a YunoHost reconfigurarla, la manera en la que conecta con su servidor a través de SSH cambiará así:",
"migration_0007_cannot_restart": "No se puede reiniciar SSH después de intentar cancelar la migración número 6.",
"migration_0007_cancelled": "YunoHost no ha podido mejorar el modo en el que se gestiona su configuración de SSH.",
"migration_0006_disclaimer": "YunoHost espera ahora que las contraseñas de «admin» y «root» estén sincronizadas. Al ejecutar esta migración, su contraseña de «root» será reemplazada por la contraseña de administración.",
"migration_0007_cancelled": "No se pudo mejorar el modo en el que se gestiona su configuración de SSH.",
"migration_0006_disclaimer": "YunoHost espera ahora que las contraseñas de «admin» y «root» estén sincronizadas. Esta migración reemplaza su contraseña de «root» por la contraseña de «admin».",
"migration_0005_not_enough_space": "Tenga suficiente espacio libre disponible en {path} para ejecutar la migración.",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 está instalado pero no PostgreSQL 9.6 Algo raro podría haber ocurrido en su sistema:(…",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 está instalado pero no PostgreSQL 9.6. Algo raro podría haber ocurrido en su sistema:(…",
"migration_0005_postgresql_94_not_installed": "PostgreSQL no estaba instalado en su sistema. Nada que hacer.",
"migration_0003_modified_files": "Tenga en cuenta que se encontró que los siguientes archivos fueron modificados manualmente y podrían ser sobrescritos después de la actualización: {manually_modified_files}",
"migration_0003_problematic_apps_warning": "Tenga en cuenta que se detectaron las siguientes aplicaciones instaladas posiblemente problemáticas. Parece que no fueron instaladas desde una lista de aplicaciones o no estaban etiquetadas como «funciona». Así que no hay garantía de que aún funcionen después de la actualización: {problematic_apps}",
"migration_0003_problematic_apps_warning": "Tenga en cuenta que las aplicaciones listadas mas abajo fueron detectadas como 'posiblemente problemáticas'. Parece que no fueron instaladas desde una lista de aplicaciones o no estaban etiquetadas como 'funcional'. Así que no hay garantía de que aún funcionen después de la actualización: {problematic_apps}",
"migration_0003_general_warning": "Tenga en cuenta que esta migración es una operación delicada. El equipo de YunoHost ha hecho todo lo posible para revisarla y probarla, pero la migración aún podría romper parte del sistema o de sus aplicaciones.\n\nPor lo tanto, se recomienda que:\n - Realice una copia de seguridad de cualquier dato crítico o aplicación. Más información en https://yunohost.org/backup;\n - Tenga paciencia tras iniciar la migración: dependiendo de su conexión a Internet y de su hardware, podría tardar unas cuantas horas hasta que todo se actualice.\n\nAdemás, el puerto para SMTP usado por los clientes de correo externos (como Thunderbird o K9-Mail) cambió de 465 (SSL/TLS) a 587 (STARTTLS). El antiguo puerto (465) se cerrará automáticamente y el nuevo puerto (587) se abrirá en el cortafuegos. Todos los usuarios *tendrán* que adaptar la configuración de sus clientes de correo por lo tanto.",
"migration_0003_still_on_jessie_after_main_upgrade": "Algo fue mal durante la actualización principal: ⸘el sistema está aún en Jessie‽ Para investigar el problema, vea {log}:s…",
"migration_0003_system_not_fully_up_to_date": "Su sistema no está totalmente actualizado. Realice una actualización normal antes de ejecutar la migración a Stretch.",
"migration_0003_not_jessie": "¡La distribución de Debian actual no es Jessie!",
"migration_0003_yunohost_upgrade": "Iniciando la actualización del paquete YunoHost… La migración finalizará pero la actualización real ocurrirá inmediatamente después. Después de que la operación esté completada, podría tener que iniciar sesión en la página de administración de nuevo.",
"migration_0003_restoring_origin_nginx_conf": "Su archivo /etc/nginx/nginx.conf ha sido editado de algún modo. La migración lo devolverá a su estado original primero… El archivo anterior estará disponible como {backup_dest}.",
"migration_0003_yunohost_upgrade": "Iniciando la actualización del paquete YunoHost… la actualización ocurrirá inmediatamente después de que la migración finalizará. Después de que la operación esté completada, podría tener que iniciar sesión en la página de administración de nuevo.",
"migration_0003_restoring_origin_nginx_conf": "Su archivo /etc/nginx/nginx.conf ha sido editado. La migración lo devolverá a su estado original… El archivo anterior estará disponible como {backup_dest}.",
"migration_0003_fail2ban_upgrade": "Iniciando la actualización de Fail2Ban…",
"migration_0003_main_upgrade": "Iniciando la actualización principal…",
"migration_0003_patching_sources_list": "Corrigiendo «sources.lists»…",
"migration_0003_start": "Iniciando migración a Stretch. El registro estará disponible en {logfile}.",
"migration_description_0012_postgresql_password_to_md5_authentication": "Forzar a la autentificación de PostgreSQL a usar MD5 para las conexiones locales",
"migration_description_0011_setup_group_permission": "Configurar grupo de usuario y configurar permisos para aplicaciones y servicios",
"migration_description_0011_setup_group_permission": "Configurar grupo de usuario y permisos para aplicaciones y servicios",
"migration_description_0010_migrate_to_apps_json": "Eliminar las listas de aplicaciones («appslists») obsoletas y usar en su lugar la nueva lista unificada «apps.json»",
"migration_description_0009_decouple_regenconf_from_services": "Separar el mecanismo «regen-conf» de los servicios",
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "Permitir que la configuración de SSH la gestione YunoHost (paso 2, manual)",
@ -491,23 +382,16 @@
"log_tools_shutdown": "Apagar el servidor",
"log_tools_upgrade": "Actualizar paquetes del sistema",
"log_tools_postinstall": "Posinstalación del servidor YunoHost",
"log_tools_migrations_migrate_forward": "Migrar hacia adelante",
"log_tools_maindomain": "Convertir «{}» en el dominio principal",
"log_user_permission_remove": "Actualizar permiso «{}»",
"log_user_permission_add": "Actualizar permiso «{}»",
"log_tools_migrations_migrate_forward": "Inicializa la migración",
"log_user_update": "Actualizar la información de usuario de «{}»",
"log_user_group_update": "Actualizar grupo «{}»",
"log_user_group_delete": "Eliminar grupo «{}»",
"log_user_group_add": "Añadir grupo «{}»",
"log_user_delete": "Eliminar usuario «{}»",
"log_user_create": "Añadir usuario «{}»",
"log_regen_conf": "Regenerar la configuración del sistema «{}»",
"log_letsencrypt_cert_renew": "Renovar el certificado «{}» de Let's encrypt",
"log_selfsigned_cert_install": "Instalar certificado autofirmado en el dominio «{}»",
"log_permission_update": "Actualizar permiso «{}» para la aplicación «{}»",
"log_permission_remove": "Eliminar permiso «{}»",
"log_permission_add": "Añadir el permiso «{}» para la aplicación «{}»",
"log_letsencrypt_cert_install": "Instalar un certificado de Let's encrypt en el dominio «{}»",
"log_letsencrypt_cert_renew": "Renovar el certificado «{}» de Let's Encrypt",
"log_selfsigned_cert_install": "Instalar el certificado auto-firmado en el dominio '{}'",
"log_letsencrypt_cert_install": "Instalar un certificado de Let's Encrypt en el dominio «{}»",
"log_dyndns_update": "Actualizar la IP asociada con su subdominio de YunoHost «{}»",
"log_dyndns_subscribe": "Subscribirse a un subdomino de YunoHost «{}»",
"log_domain_remove": "Eliminar el dominio «{}» de la configuración del sistema",
@ -522,13 +406,8 @@
"log_app_remove": "Eliminar la aplicación «{}»",
"log_app_install": "Instalar la aplicación «{}»",
"log_app_change_url": "Cambiar el URL de la aplicación «{}»",
"log_app_removelist": "Eliminar una lista de aplicaciones",
"log_app_fetchlist": "Añadir una lista de aplicaciones",
"log_app_clearaccess": "Eliminar todos los accesos a «{}»",
"log_app_removeaccess": "Eliminar acceso a «{}»",
"log_app_addaccess": "Añadir acceso a «{}»",
"log_operation_unit_unclosed_properly": "La unidad de operación no se ha cerrado correctamente",
"log_does_exists": "No existe ningún registro de actividades con el nombre «{log}», ejecute «yunohost log list» para ver todos los registros de actividades disponibles",
"log_does_exists": "No existe ningún registro de actividades con el nombre '{log}', ejecute 'yunohost log list' para ver todos los registros de actividades disponibles",
"log_help_to_get_failed_log": "No se pudo completar la operación «{desc}». Para obtener ayuda, comparta el registro completo de esta operación ejecutando la orden «yunohost log display {name} --share»",
"log_link_to_failed_log": "No se pudo completar la operación «{desc}». Para obtener ayuda, proporcione el registro completo de esta operación <a href=\"#/tools/logs/{name}\">pulsando aquí</a>",
"log_help_to_get_log": "Para ver el registro de la operación «{desc}», ejecute la orden «yunohost log display {name}»",
@ -536,18 +415,13 @@
"log_category_404": "La categoría de registro «{category}» no existe",
"log_corrupted_md_file": "El archivo de metadatos YAML asociado con el registro está dañado: «{md_file}\nError: {error}»",
"hook_json_return_error": "No se pudo leer la respuesta del gancho {path:s}. Error: {msg:s}. Contenido sin procesar: {raw_content}",
"group_update_failed": "No se pudo actualizar el grupo «{group}»",
"group_update_failed": "No se pudo actualizar el grupo «{group}»: {error}",
"group_updated": "Grupo «{group}» actualizado",
"group_unknown": "El grupo «{group:s}» es desconocido",
"group_info_failed": "No se pudo mostrar la información del grupo",
"group_deletion_not_allowed": "No se puede eliminar el grupo {group:s} manualmente.",
"group_deletion_failed": "No se pudo eliminar el grupo «{group}»",
"group_deletion_failed": "No se pudo eliminar el grupo «{group}»: {error}",
"group_deleted": "Eliminado el grupo «{group}»",
"group_creation_failed": "No se pudo crear el grupo «{group}»",
"group_creation_failed": "No se pudo crear el grupo «{group}»: {error}",
"group_created": "Creado el grupo «{group}»",
"group_name_already_exist": "El grupo {name:s} ya existe",
"group_already_disallowed": "El grupo «{group:s}» ya tiene desactivado el permiso «{permission:s}» para la aplicación «{app:s}»",
"group_already_allowed": "El grupo «{group:s}» ya tiene activado el permiso «{permission:s}» para la aplicación «{app:s}»",
"good_practices_about_admin_password": "Va a establecer una nueva contraseña de administración. La contraseña debería tener al menos 8 caracteres, aunque es una buena práctica usar una contraseña más extensa (básicamente una frase) y/o usar caracteres de varias clases (mayúsculas, minúsculas, números y caracteres especiales).",
"global_settings_unknown_type": "Situación imprevista, la configuración {setting:s} parece tener el tipo {unknown_type:s} pero no es un tipo compatible con el sistema.",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Permitir el uso de la llave (obsoleta) DSA para la configuración del demonio SSH",
@ -569,20 +443,16 @@
"global_settings_bad_type_for_setting": "Tipo erróneo para la configuración {setting:s}, obtuvo {received_type:s}, esperado {expected_type:s}",
"global_settings_bad_choice_for_enum": "Opción errónea para la configuración {setting:s}, obtuvo «{choice:s}» pero las opciones disponibles son: {available_choices:s}",
"file_does_not_exist": "El archivo {path:s} no existe.",
"error_when_removing_sftpuser_group": "No se pudo eliminar el grupo sftpusers",
"edit_permission_with_group_all_users_not_allowed": "No puede editar el permiso para el grupo «all_users», utilice «yunohost user permission clear APLICACIÓN» o «yunohost user permission add APLICACIÓN -u USUARIO».",
"edit_group_not_allowed": "No tiene permiso para editar el grupo {group:s}",
"dyndns_could_not_check_available": "No se pudo comprobar si {domain:s} está disponible en {provider:s}.",
"domain_dyndns_dynette_is_unreachable": "No se pudo conectar a dynette de YunoHost. O su YunoHost no está correctamente conectado a Internet o el servidor dynette está caído. Error: {error}",
"domain_dns_conf_is_just_a_recommendation": "Esta orden muestra la configuración *recomendada*. No configura el DNS en realidad. Es su responsabilidad configurar la zona de DNS en su registrador según esta recomendación.",
"dpkg_lock_not_available": "Esta orden no se puede ejecutar en este momento porque otro programa parece que está usando el bloqueo de dpkg (el gestor de paquetes del sistema)",
"dpkg_lock_not_available": "Esta orden no se puede ejecutar en este momento ,parece que programa está usando el bloqueo de dpkg (el gestor de paquetes del sistema)",
"dpkg_is_broken": "No puede hacer esto en este momento porque dpkg/apt (los gestores de paquetes del sistema) parecen estar en un estado roto... Puede tratar de solucionar este problema conectando a través de SSH y ejecutando `sudo dpkg --configure -a`.",
"confirm_app_install_thirdparty": AVISO! Instalar aplicaciones de terceros podría comprometer la integridad y seguridad de su sistema. Probablemente NO debería instalarlas salvo que sepa lo que está haciendo. ¿Está dispuesto a correr ese riesgo? [{answers:s}] ",
"confirm_app_install_danger": AVISO! Esta aplicación es aún experimental (si no está funcionando expresamente) y ¡es probable que rompa su sistema! Probablemente NO debería instalarla salvo que sepa lo que está haciendo. ¿Está dispuesto a correr ese riesgo? [{answers:s}] ",
"confirm_app_install_thirdparty": PELIGRO! Esta aplicación no forma parte del catálogo de aplicaciones de YunoHost. Instalar aplicaciones de terceros podría comprometer la integridad y seguridad de su sistema. Probablemente NO debería instalarla salvo que sepa lo que está haciendo. No tendrá NINGUNA AYUDA si esta aplicación no funciona o rompe su sistema… Si está dispuesto a aceptar ese riesgo de todas formas, escriba «{answers:s}»",
"confirm_app_install_danger": PELIGRO! ¡Esta aplicación es conocida por ser aún experimental (o no funciona explícitamente)! Probablemente NO debería instalarla salvo que sepa lo que está haciendo. No tendrá NINGUNA AYUDA si esta aplicación no funciona o rompe su sistema… Si está dispuesto a aceptar ese riesgo de todas formas, escriba «{answers:s}»",
"confirm_app_install_warning": "Aviso: esta aplicación puede funcionar pero no está bien integrada en YunoHost. Algunas herramientas como la autentificación única y respaldo/restauración podrían no estar disponibles. ¿Instalar de todos modos? [{answers:s}] ",
"backup_unable_to_organize_files": "No se pudo usar el método rápido de organización de los archivos en el archivo",
"backup_permission": "Permiso de respaldo para la aplicación {app:s}",
"backup_output_symlink_dir_broken": "Tiene un enlace simbólico roto en vez del directorio «{path:s}» de su archivo. Puede que tenga una configuración específica para respaldar sus datos en otro sistema de archivos, en este caso probablemente olvidó remontar o conectar su disco duro o clave USB.",
"backup_output_symlink_dir_broken": "El directorio de su archivo «{path:s}» es un enlace simbólico roto. Tal vez olvidó (re)montarlo o conectarlo al medio de almacenamiento al que apunta.",
"backup_mount_archive_for_restore": "Preparando el archivo para la restauración…",
"backup_method_tar_finished": "Creado el archivo TAR de respaldo",
"backup_method_custom_finished": "Terminado el método «{method:s}» de respaldo personalizado",
@ -592,19 +462,141 @@
"backup_actually_backuping": "Creando un archivo de respaldo de los archivos obtenidos…",
"ask_new_path": "Nueva ruta",
"ask_new_domain": "Nuevo dominio",
"apps_permission_restoration_failed": "Otorgar el permiso «{permission:s}» para restaurar {app:s}",
"apps_permission_not_found": "No se han encontrado permisos para las aplicaciones instaladas",
"app_upgrade_several_apps": "Las siguientes aplicaciones se actualizarán: {apps}",
"app_start_restore": "Restaurando aplicación {app}…",
"app_start_backup": "Obteniendo archivos para el respaldo de {app}…",
"app_start_remove": "Eliminando aplicación {app}…",
"app_start_install": "Instalando aplicación {app}…",
"app_start_restore": "Restaurando aplicación «{app}»…",
"app_start_backup": "Obteniendo archivos para el respaldo de «{app}»…",
"app_start_remove": "Eliminando aplicación «{app}»…",
"app_start_install": "Instalando aplicación «{app}»…",
"app_not_upgraded": "Error al actualizar la aplicación «{failed_app}» y como consecuencia se han cancelado las actualizaciones de las siguientes aplicaciones: {apps}",
"app_action_cannot_be_ran_because_required_services_down": "Esta aplicación necesita algunos servicios que no están funcionando ahora. Antes de continuar, debería intentar reiniciar los siguientes servicios (y posiblemente investigar por qué no funcionan): {services}",
"app_action_cannot_be_ran_because_required_services_down": "Estos servicios necesarios deberían estar funcionando para ejecutar esta acción: {services}. Pruebe a reiniciarlos para continuar (y posiblemente investigar por qué están caídos).",
"already_up_to_date": "Nada que hacer. Todo está actualizado.",
"admin_password_too_long": "Elija una contraseña de menos de 127 caracteres",
"aborting": "Cancelando.",
"app_upgrade_stopped": "Se ha detenido la actualización de todas las aplicaciones para prevenir un posible daño porque la aplicación anterior no se pudo actualizar",
"app_action_broke_system": "Esta acción parece que ha roto estos importantes servicios: {services}",
"operation_interrupted": "¿Ha sido interrumpida la operación manualmente?"
"app_action_broke_system": "Esta acción parece que ha roto estos servicios importantes: {services}",
"operation_interrupted": "¿Ha sido interrumpida la operación manualmente?",
"apps_already_up_to_date": "Todas las aplicaciones están ya actualizadas",
"dyndns_provider_unreachable": "No se puede conectar con el proveedor de Dyndns {provider}: o su YunoHost no está correctamente conectado a Internet o el servidor dynette está caído.",
"group_already_exist": "El grupo {group} ya existe",
"group_already_exist_on_system": "El grupo {group} ya existe en los grupos del sistema",
"group_cannot_be_deleted": "El grupo {group} no se puede eliminar manualmente.",
"group_user_already_in_group": "El usuario {user} ya está en el grupo {group}",
"group_user_not_in_group": "El usuario {user} no está en el grupo {group}",
"log_permission_create": "Crear permiso «{}»",
"log_permission_delete": "Eliminar permiso «{}»",
"log_user_group_create": "Crear grupo «{}»",
"log_user_permission_update": "Actualizar los accesos para el permiso «{}»",
"log_user_permission_reset": "Restablecer permiso «{}»",
"migration_0011_failed_to_remove_stale_object": "No se pudo eliminar el objeto obsoleto {dn}: {error}",
"permission_already_allowed": "El grupo «{group}» ya tiene el permiso «{permission}» activado",
"permission_already_disallowed": "El grupo «{group}» ya tiene el permiso «{permission}» desactivado",
"permission_cannot_remove_main": "No está permitido eliminar un permiso principal",
"user_already_exists": "El usuario «{user}» ya existe",
"app_full_domain_unavailable": "Lamentablemente esta aplicación tiene que instalarse en un dominio propio pero ya hay otras aplicaciones instaladas en el dominio «{domain}». Podría usar un subdomino dedicado a esta aplicación en su lugar.",
"app_install_failed": "No se pudo instalar {app}: {error}",
"app_install_script_failed": "Ha ocurrido un error en el guión de instalación de la aplicación",
"group_cannot_edit_all_users": "El grupo «all_users» no se puede editar manualmente. Es un grupo especial destinado a contener todos los usuarios registrados en YunoHost",
"group_cannot_edit_visitors": "El grupo «visitors» no se puede editar manualmente. Es un grupo especial que representa a los visitantes anónimos",
"group_cannot_edit_primary_group": "El grupo «{group}» no se puede editar manualmente. Es el grupo primario destinado a contener solo un usuario específico.",
"log_permission_url": "Actualizar la URL relacionada con el permiso «{}»",
"migration_0011_slapd_config_will_be_overwritten": "Parece que ha editado manualmente la configuración de slapd. Para esta migración crítica, YunoHost necesita forzar la actualización de la configuración de slapd. Los archivos originales se respaldarán en {conf_backup_folder}.",
"permission_already_up_to_date": "El permiso no se ha actualizado porque las peticiones de incorporación o eliminación ya coinciden con el estado actual.",
"permission_currently_allowed_for_all_users": "Este permiso se concede actualmente a todos los usuarios además de los otros grupos. Probablemente quiere o eliminar el permiso de «all_users» o eliminar los otros grupos a los que está otorgado actualmente.",
"permission_require_account": "El permiso {permission} solo tiene sentido para usuarios con una cuenta y, por lo tanto, no se puede activar para visitantes.",
"app_remove_after_failed_install": "Eliminando la aplicación tras el fallo de instalación…",
"diagnosis_basesystem_host": "El servidor está ejecutando Debian {debian_version}.",
"diagnosis_basesystem_kernel": "El servidor está ejecutando el núcleo de Linux {kernel_version}",
"diagnosis_basesystem_ynh_single_version": "{package} versión: {version} ({repo})",
"diagnosis_basesystem_ynh_main_version": "El servidor está ejecutando YunoHost {main_version} ({repo})",
"diagnosis_basesystem_ynh_inconsistent_versions": "Está ejecutando versiones incoherentes de los paquetes de YunoHost... probablemente por una actualización errónea o parcial.",
"diagnosis_failed_for_category": "Diagnóstico fallido para la categoría «{category}» : {error}",
"diagnosis_cache_still_valid": "(Caché aún válida para el diagnóstico de {category}. ¡Aún no se ha rediagnosticado!)",
"diagnosis_found_errors_and_warnings": "¡Encontrado(s) error(es) significativo(s) {errors} (y aviso(s) {warnings}) relacionado(s) con {category}!",
"diagnosis_display_tip_web": "Puede ir a la sección de diagnóstico (en la pantalla principal) para ver los problemas encontrados.",
"diagnosis_display_tip_cli": "Puede ejecutar «yunohost diagnosis show --issues» para mostrar los problemas encontrados.",
"apps_catalog_init_success": "¡Sistema de catálogo de aplicaciones inicializado!",
"apps_catalog_updating": "Actualizando catálogo de aplicaciones...",
"apps_catalog_failed_to_download": "No se pudo descargar el catálogo de aplicaciones {apps_catalog}: {error}",
"apps_catalog_obsolete_cache": "La caché del catálogo de aplicaciones está vacía u obsoleta.",
"apps_catalog_update_success": "¡El catálogo de aplicaciones ha sido actualizado!",
"diagnosis_cant_run_because_of_dep": "No se puede ejecutar el diagnóstico para {category} mientras haya problemas importantes relacionados con {dep}.",
"diagnosis_ignored_issues": "(+ {nb_ignored} problema(s) ignorado(s))",
"diagnosis_found_errors": "¡Encontrado(s) error(es) significativo(s) {errors} relacionado(s) con {category}!",
"diagnosis_found_warnings": "Encontrado elemento(s) {warnings} que puede(n) ser mejorado(s) para {category}.",
"diagnosis_everything_ok": "¡Todo se ve bien para {category}!",
"app_upgrade_script_failed": "Ha ocurrido un error en el script de actualización de la app",
"diagnosis_no_cache": "Todavía no hay una caché de diagnóstico para la categoría '{category}'",
"diagnosis_ip_no_ipv4": "El servidor no cuenta con ipv4 funcional.",
"diagnosis_ip_not_connected_at_all": "¿¡Está conectado el servidor a internet!?",
"diagnosis_ip_broken_resolvconf": "DNS parece no funcionar en tu servidor, lo que parece estar relacionado con /etc/resolv.conf no apuntando a 127.0.0.1.",
"diagnosis_dns_missing_record": "Según la configuración DNS recomendada, deberías añadir un registro DNS\ntipo: {type}\nnombre: {name}\nvalor: {value}",
"diagnosis_diskusage_low": "El almacenamiento {mountpoint} (en dispositivo {device}) solo tiene {free} ({free_percent}%) de espacio disponible. Ten cuidado.",
"diagnosis_services_bad_status_tip": "Puedes intentar reiniciar el servicio, y si no funciona, echar un vistazo a los logs del servicio usando 'yunohost service log {service}' o a través de la sección 'Servicios' en webadmin.",
"diagnosis_ip_connected_ipv6": "¡El servidor está conectado a internet a través de IPv6!",
"diagnosis_ip_no_ipv6": "El servidor no cuenta con IPv6 funcional.",
"diagnosis_ip_dnsresolution_working": "¡DNS no está funcionando!",
"diagnosis_ip_broken_dnsresolution": "Parece que no funciona la resolución de nombre de dominio por alguna razón... ¿Hay algún firewall bloqueando peticiones DNS?",
"diagnosis_ip_weird_resolvconf": "Parece que DNS funciona, pero ten cuidado, porque estás utilizando /etc/resolv.conf modificado.",
"diagnosis_ip_weird_resolvconf_details": "En su lugar, este fichero debería ser un enlace simbólico a /etc/resolvconf/run/resolv.conf apuntando a 127.0.0.1 (dnsmasq). Los servidores de nombre de domino deben configurarse a través de /etc/resolv.dnsmasq.conf.",
"diagnosis_dns_good_conf": "Buena configuración DNS para el dominio {domain} (categoría {category})",
"diagnosis_dns_bad_conf": "Configuración mala o faltante de los DNS para el dominio {domain} (categoría {category})",
"diagnosis_dns_discrepancy": "El registro DNS con tipo {type} y nombre {name} no se corresponde a la configuración recomendada.\nValor actual: {current}\nValor esperado: {value}",
"diagnosis_services_bad_status": "El servicio {service} está {status} :(",
"diagnosis_diskusage_verylow": "El almacenamiento {mountpoint} (en el dispositivo {device}) sólo tiene {free} ({free_percent}%) de espacio disponible. Deberías considerar la posibilidad de limpiar algo de espacio.",
"diagnosis_diskusage_ok": "¡El almacenamiento {mountpoint} (en el dispositivo {device}) todavía tiene {free} ({free_percent}%) de espacio libre!",
"diagnosis_services_conf_broken": "¡Mala configuración para el servicio {service}!",
"diagnosis_services_running": "¡El servicio {service} está en ejecución!",
"diagnosis_failed": "No se ha podido obtener el resultado del diagnóstico para la categoría '{category}': {error}",
"diagnosis_ip_connected_ipv4": "¡El servidor está conectado a internet a través de IPv4!",
"diagnosis_security_vulnerable_to_meltdown_details": "Para corregir esto, debieras actualizar y reiniciar tu sistema para cargar el nuevo kernel de Linux (o contacta tu proveedor si esto no funciona). Mas información en https://meltdownattack.com/",
"diagnosis_ram_verylow": "Al sistema le queda solamente {available} ({available_percent}%) de RAM! (De un total de {total})",
"diagnosis_ram_low": "Al sistema le queda {available} ({available_percent}%) de RAM de un total de {total}. Cuidado.",
"diagnosis_ram_ok": "El sistema aun tiene {available} ({available_percent}%) de RAM de un total de {total}.",
"diagnosis_swap_none": "El sistema no tiene mas espacio de intercambio. Considera agregar por lo menos {recommended} de espacio de intercambio para evitar que el sistema se quede sin memoria.",
"diagnosis_swap_notsomuch": "Al sistema le queda solamente {total} de espacio de intercambio. Considera agregar al menos {recommended} para evitar que el sistema se quede sin memoria.",
"diagnosis_mail_ougoing_port_25_ok": "El puerto de salida 25 no esta bloqueado y los correos electrónicos pueden ser enviados a otros servidores.",
"diagnosis_mail_outgoing_port_25_blocked": "El puerto de salida 25 parece estar bloqueado. Intenta desbloquearlo con el panel de configuración de tu proveedor de servicios de Internet (o proveedor de halbergue). Mientras tanto, el servidor no podrá enviar correos electrónicos a otros servidores.",
"diagnosis_regenconf_allgood": "Todos los archivos de configuración están en linea con la configuración recomendada!",
"diagnosis_regenconf_manually_modified": "El archivo de configuración {file} fue modificado manualmente.",
"diagnosis_regenconf_manually_modified_details": "Esto este probablemente BIEN siempre y cuando sepas lo que estas haciendo ;) !",
"diagnosis_regenconf_manually_modified_debian": "El archivos de configuración {file} fue modificado manualmente comparado con el valor predeterminado de Debian.",
"diagnosis_regenconf_manually_modified_debian_details": "Esto este probablemente BIEN, pero igual no lo pierdas de vista...",
"diagnosis_security_all_good": "Ninguna vulnerabilidad critica de seguridad fue encontrada.",
"diagnosis_security_vulnerable_to_meltdown": "Pareces vulnerable a el colapso de vulnerabilidad critica de seguridad.",
"diagnosis_description_basesystem": "Sistema de base",
"diagnosis_description_ip": "Conectividad a Internet",
"diagnosis_description_dnsrecords": "Registro DNS",
"diagnosis_description_services": "Comprobación del estado de los servicios",
"diagnosis_description_ports": "Exposición de puertos",
"diagnosis_description_systemresources": "Recursos del sistema",
"diagnosis_swap_ok": "El sistema tiene {total} de espacio de intercambio!",
"diagnosis_ports_needed_by": "La apertura de este puerto es requerida para la funcionalidad {category} (service {service})",
"diagnosis_ports_ok": "El puerto {port} es accesible desde internet.",
"diagnosis_ports_unreachable": "El puerto {port} no es accesible desde internet.",
"diagnosis_ports_could_not_diagnose": "No se puede comprobar si los puertos están accesibles desde el exterior.",
"diagnosis_ports_could_not_diagnose_details": "Error: {error}",
"diagnosis_description_security": "Validación de seguridad",
"diagnosis_description_regenconf": "Configuraciones de sistema",
"diagnosis_description_mail": "Correo electrónico",
"diagnosis_description_web": "Web",
"diagnosis_basesystem_hardware_board": "El modelo de placa del servidor es {model}",
"diagnosis_basesystem_hardware": "La arquitectura material del servidor es {virt} {arch}",
"migration_description_0014_remove_app_status_json": "Supresión del archivo de aplicaciones heredado status.json",
"migration_description_0013_futureproof_apps_catalog_system": "Migración hacia el nuevo sistema de catalogo de aplicación a prueba del futuro",
"log_domain_main_domain": "Hacer de '{}' el dominio principal",
"log_app_config_apply": "Aplica la configuración de la aplicación '{}'",
"log_app_config_show_panel": "Muestra el panel de configuración de la aplicación '{}'",
"log_app_action_run": "Inicializa la acción de la aplicación '{}'",
"group_already_exist_on_system_but_removing_it": "El grupo {group} ya existe en el grupo de sistema, pero YunoHost lo suprimirá …",
"global_settings_setting_pop3_enabled": "Habilita el protocolo POP3 para el servidor de correo electrónico",
"domain_cannot_remove_main_add_new_one": "No se puede remover '{domain:s}' porque es su principal y único dominio. Primero debe agregar un nuevo dominio con la linea de comando 'yunohost domain add <another-domain.com>', entonces configurarlo como dominio principal con 'yunohost domain main-domain -n <another-domain.com>' y finalmente borrar el dominio '{domain:s}' con 'yunohost domain remove {domain:s}'.",
"diagnosis_never_ran_yet": "Este servidor todavía no tiene reportes de diagnostico. Puede iniciar un diagnostico completo desde la interface administrador web o con la linea de comando 'yunohost diagnosis run'.",
"diagnosis_unknown_categories": "Las siguientes categorías están desconocidas: {categories}",
"diagnosis_http_unreachable": "El dominio {domain} esta fuera de alcance desde internet y a través de HTTP.",
"diagnosis_http_bad_status_code": "El sistema de diagnostico no pudo comunicarse con su servidor. Puede ser otra maquina que contesto en lugar del servidor. Debería verificar en su firewall que el re-direccionamiento del puerto 80 esta correcto.",
"diagnosis_http_connection_error": "Error de conexión: Ne se pudo conectar al dominio solicitado,",
"diagnosis_http_timeout": "El intento de contactar a su servidor desde internet corrió fuera de tiempo. Al parece esta incomunicado. Debería verificar que nginx corre en el puerto 80, y que la redireción del puerto 80 no interfiere con en el firewall.",
"diagnosis_http_ok": "El Dominio {domain} es accesible desde internet a través de HTTP.",
"diagnosis_http_could_not_diagnose": "No se pudo verificar si el dominio es accesible desde internet.",
"diagnosis_http_could_not_diagnose_details": "Error: {error}",
"diagnosis_ports_forwarding_tip": "Para solucionar este incidente, debería configurar el \"port forwading\" en su router como especificado en https://yunohost.org/isp_box_config"
}

View file

@ -1 +1,3 @@
{}
{
"password_too_simple_1": "Pasahitzak gutxienez 8 karaktere izan behar ditu"
}

View file

@ -6,97 +6,67 @@
"app_already_installed": "{app:s} est déjà installé",
"app_argument_choice_invalid": "Choix invalide pour le paramètre '{name:s}', il doit être lun de {choices:s}",
"app_argument_invalid": "Valeur invalide pour le paramètre '{name:s}' : {error:s}",
"app_argument_missing": "Paramètre manquant « {:s} »",
"app_argument_required": "Le paramètre '{name:s}' est requis",
"app_extraction_failed": "Impossible dextraire les fichiers dinstallation",
"app_id_invalid": "Identifiant dapplication invalide",
"app_incompatible": "Lapplication {app} est incompatible avec votre version de YunoHost",
"app_install_files_invalid": "Fichiers dinstallation incorrects",
"app_location_already_used": "Lapplication '{app}' est déjà installée à cet emplacement ({path})",
"app_location_install_failed": "Impossible dinstaller lapplication à cet emplacement pour cause de conflit avec lapplication '{other_app}' déjà installée sur '{other_path}'",
"app_manifest_invalid": "Manifeste dapplication incorrect : {error}",
"app_no_upgrade": "Aucune application à mettre à jour",
"app_not_correctly_installed": "{app:s} semble être mal installé",
"app_not_installed": "L'application « {app:s} » nest pas installée. Voici la liste des applications installées: {all_apps}",
"app_not_installed": "Nous navons pas trouvé lapplication « {app:s} » dans la liste des applications installées: {all_apps}",
"app_not_properly_removed": "{app:s} na pas été supprimé correctement",
"app_package_need_update": "Le paquet de lapplication {app} doit être mis à jour pour être en adéquation avec les changements de YunoHost",
"app_recent_version_required": "{app:s} nécessite une version plus récente de YunoHost",
"app_removed": "{app:s} a été supprimé",
"app_removed": "{app:s} supprimé",
"app_requirements_checking": "Vérification des paquets requis pour {app} …",
"app_requirements_failed": "Impossible de satisfaire les pré-requis pour {app} : {error}",
"app_requirements_unmeet": "Les pré-requis de {app} ne sont pas satisfaits, le paquet {pkgname} ({version}) doit être {spec}",
"app_sources_fetch_failed": "Impossible de récupérer les fichiers sources, l'URL est-elle correcte ?",
"app_sources_fetch_failed": "Impossible de récupérer les fichiers sources, lURL est-elle correcte ?",
"app_unknown": "Application inconnue",
"app_unsupported_remote_type": "Ce type de commande à distance utilisé pour cette application n'est pas supporté",
"app_upgrade_failed": "Impossible de mettre à jour {app:s}",
"app_upgraded": "{app:s} a été mis à jour",
"appslist_fetched": "La liste dapplications {appslist:s} a été récupérée",
"appslist_removed": "La liste dapplications {appslist:s} a été supprimée",
"appslist_retrieve_error": "Impossible de récupérer la liste dapplications distante {appslist:s} : {error:s}",
"appslist_unknown": "La liste dapplications {appslist:s} est inconnue.",
"ask_current_admin_password": "Mot de passe dadministration actuel",
"app_unsupported_remote_type": "Ce type de commande à distance utilisé pour cette application nest pas supporté",
"app_upgrade_failed": "Impossible de mettre à jour {app:s} : {error}",
"app_upgraded": "{app:s} mis à jour",
"ask_email": "Adresse de courriel",
"ask_firstname": "Prénom",
"ask_lastname": "Nom",
"ask_list_to_remove": "Liste à supprimer",
"ask_main_domain": "Domaine principal",
"ask_new_admin_password": "Nouveau mot de passe dadministration",
"ask_password": "Mot de passe",
"backup_action_required": "Vous devez préciser ce qui est à sauvegarder",
"backup_app_failed": "Impossible de sauvegarder lapplication '{app:s}'",
"backup_archive_app_not_found": "Lapplication '{app:s}' na pas été trouvée dans larchive de la sauvegarde",
"backup_archive_hook_not_exec": "Le script « {hook:s} » n'a pas été exécuté dans cette sauvegarde",
"backup_archive_name_exists": "Une archive de sauvegarde avec ce nom existe déjà",
"backup_archive_name_exists": "Une archive de sauvegarde avec ce nom existe déjà.",
"backup_archive_name_unknown": "Larchive locale de sauvegarde nommée '{name:s}' est inconnue",
"backup_archive_open_failed": "Impossible douvrir larchive de sauvegarde",
"backup_archive_open_failed": "Impossible douvrir larchive de la sauvegarde",
"backup_cleaning_failed": "Impossible de nettoyer le dossier temporaire de sauvegarde",
"backup_created": "Sauvegarde terminée",
"backup_creating_archive": "Création de larchive de sauvegarde …",
"backup_creation_failed": "Impossible de créer la sauvegarde",
"backup_creation_failed": "Impossible de créer larchive de la sauvegarde",
"backup_delete_error": "Impossible de supprimer '{path:s}'",
"backup_deleted": "La sauvegarde a été supprimée",
"backup_extracting_archive": "Extraction de larchive de sauvegarde …",
"backup_hook_unknown": "Script de sauvegarde '{hook:s}' inconnu",
"backup_invalid_archive": "Archive de sauvegarde invalide",
"backup_nothings_done": "Il ny a rien à sauvegarder",
"backup_output_directory_forbidden": "Dossier de destination interdit. Les sauvegardes ne peuvent être créées dans les sous-dossiers /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var ou /home/yunohost.backup/archives",
"backup_output_directory_not_empty": "Le répertoire de destination n'est pas vide",
"backup_output_directory_not_empty": "Le répertoire de destination nest pas vide",
"backup_output_directory_required": "Vous devez spécifier un dossier de destination pour la sauvegarde",
"backup_running_app_script": "Lancement du script de sauvegarde de lapplication « {app:s} »...",
"backup_running_hooks": "Exécution des scripts de sauvegarde …",
"custom_app_url_required": "Vous devez spécifier une URL pour mettre à jour votre application personnalisée {app:s}",
"custom_appslist_name_required": "Vous devez spécifier un nom pour votre liste dapplications personnalisées",
"diagnosis_debian_version_error": "Impossible de déterminer la version de Debian : {error}",
"diagnosis_kernel_version_error": "Impossible de récupérer la version du noyau : {error}",
"diagnosis_monitor_disk_error": "Impossible de superviser les disques : {error}",
"diagnosis_monitor_network_error": "Impossible de superviser le réseau : {error}",
"diagnosis_monitor_system_error": "Impossible de superviser le système : {error}",
"diagnosis_no_apps": "Aucune application installée",
"dnsmasq_isnt_installed": "dnsmasq ne semble pas être installé, veuillez lancer 'apt-get remove bind9 && apt-get install dnsmasq'",
"domain_cert_gen_failed": "Impossible de générer le certificat",
"domain_created": "Le domaine a été créé",
"domain_creation_failed": "Impossible de créer le domaine",
"domain_creation_failed": "Impossible de créer le domaine {domain}: {error}",
"domain_deleted": "Le domaine a été supprimé",
"domain_deletion_failed": "Impossible de supprimer le domaine",
"domain_deletion_failed": "Impossible de supprimer le domaine {domain}:{error}",
"domain_dyndns_already_subscribed": "Vous avez déjà souscris à un domaine DynDNS",
"domain_dyndns_invalid": "Domaine incorrect pour un usage avec DynDNS",
"domain_dyndns_root_unknown": "Domaine DynDNS principal inconnu",
"domain_exists": "Le domaine existe déjà",
"domain_uninstall_app_first": "Une ou plusieurs applications sont installées sur ce domaine. Veuillez dabord les désinstaller avant de supprimer ce domaine",
"domain_unknown": "Domaine inconnu",
"domain_zone_exists": "Le fichier de zone DNS existe déjà",
"domain_zone_not_found": "Fichier de zone DNS introuvable pour le domaine {:s}",
"done": "Terminé",
"downloading": "Téléchargement en cours …",
"dyndns_cron_installed": "La tâche cron pour le domaine DynDNS a été installée",
"dyndns_cron_remove_failed": "Impossible de supprimer la tâche cron DynDNS parce que: {error}",
"dyndns_cron_removed": "La tâche cron pour le domaine DynDNS a été enlevée",
"dyndns_cron_installed": "La tâche cron pour le domaine DynDNS a été créée",
"dyndns_cron_remove_failed": "Impossible de supprimer la tâche cron DynDNS parce que : {error}",
"dyndns_cron_removed": "La tâche cron pour le domaine DynDNS enlevée",
"dyndns_ip_update_failed": "Impossible de mettre à jour ladresse IP sur le domaine DynDNS",
"dyndns_ip_updated": "Votre adresse IP a été mise à jour pour le domaine DynDNS",
"dyndns_key_generating": "La clé DNS est en cours de génération, cela peut prendre un certain temps …",
"dyndns_ip_updated": "Mise à jour de votre IP pour le domaine DynDNS",
"dyndns_key_generating": "Génération de la clé DNS …, cela peut prendre un certain temps.",
"dyndns_key_not_found": "Clé DNS introuvable pour le domaine",
"dyndns_no_domain_registered": "Aucun domaine na été enregistré avec DynDNS",
"dyndns_registered": "Le domaine DynDNS a été enregistré",
"dyndns_no_domain_registered": "Aucun domaine enregistré avec DynDNS",
"dyndns_registered": "Domaine DynDNS enregistré",
"dyndns_registration_failed": "Impossible denregistrer le domaine DynDNS : {error:s}",
"dyndns_unavailable": "Le domaine {domain:s} est indisponible.",
"executing_command": "Exécution de la commande '{command:s}' …",
@ -104,340 +74,244 @@
"extracting": "Extraction en cours …",
"field_invalid": "Champ incorrect : '{:s}'",
"firewall_reload_failed": "Impossible de recharger le pare-feu",
"firewall_reloaded": "Le pare-feu a été rechargé",
"firewall_rules_cmd_failed": "Certaines règles du pare-feu nont pas pu être appliquées. Pour plus dinformations, consultez le journal.",
"format_datetime_short": "%d/%m/%Y %H:%M",
"hook_argument_missing": "Argument manquant : '{:s}'",
"hook_choice_invalid": "Choix incorrect : '{:s}'",
"firewall_reloaded": "Pare-feu rechargé",
"firewall_rules_cmd_failed": "Certaines règles du pare-feu nont pas pu être appliquées. Plus dinfo dans le journal de log.",
"hook_exec_failed": "Échec de lexécution du script : {path:s}",
"hook_exec_not_terminated": "Lexécution du script {path:s} ne sest pas terminée correctement",
"hook_list_by_invalid": "Propriété invalide pour lister les actions par celle-ci",
"hook_name_unknown": "Nom de l'action '{name:s}' inconnu",
"hook_name_unknown": "Nom de laction '{name:s}' inconnu",
"installation_complete": "Installation terminée",
"installation_failed": "Échec de linstallation",
"installation_failed": "Quelque chose sest mal passé lors de linstallation",
"ip6tables_unavailable": "Vous ne pouvez pas jouer avec ip6tables ici. Vous êtes soit dans un conteneur, soit votre noyau ne le prend pas en charge",
"iptables_unavailable": "Vous ne pouvez pas jouer avec iptables ici. Vous êtes soit dans un conteneur, soit votre noyau ne le prend pas en charge",
"ldap_initialized": "Lannuaire LDAP a été initialisé",
"license_undefined": "indéfinie",
"ldap_initialized": "Lannuaire LDAP initialisé",
"mail_alias_remove_failed": "Impossible de supprimer lalias de courriel '{mail:s}'",
"mail_domain_unknown": "Le domaine '{domain:s}' pour l'adresse de courriel est inconnu",
"mail_domain_unknown": "Le domaine '{domain:s}' de cette adresse de courriel nest pas valide. Merci dutiliser un domaine administré par ce serveur.",
"mail_forward_remove_failed": "Impossible de supprimer le courriel de transfert '{mail:s}'",
"maindomain_change_failed": "Impossible de modifier le domaine principal",
"maindomain_changed": "Le domaine principal a été modifié",
"monitor_disabled": "La supervision du serveur a été désactivé",
"monitor_enabled": "La supervision du serveur a été activé",
"monitor_glances_con_failed": "Impossible de se connecter au serveur Glances",
"monitor_not_enabled": "Le suivi de létat du serveur nest pas activé",
"monitor_period_invalid": "Période de temps incorrecte",
"monitor_stats_file_not_found": "Le fichier de statistiques est introuvable",
"monitor_stats_no_update": "Aucune donnée de létat du serveur à mettre à jour",
"monitor_stats_period_unavailable": "Aucune statistique nest disponible pour la période",
"mountpoint_unknown": "Point de montage inconnu",
"mysql_db_creation_failed": "Impossible de créer la base de données MySQL",
"mysql_db_init_failed": "Impossible dinitialiser la base de données MySQL",
"mysql_db_initialized": "La base de données MySQL a été initialisée",
"network_check_mx_ko": "Lenregistrement DNS MX nest pas défini",
"network_check_smtp_ko": "Le trafic courriel sortant (port 25 SMTP) semble bloqué par votre réseau",
"network_check_smtp_ok": "Le trafic courriel sortant (port 25 SMTP) nest pas bloqué",
"new_domain_required": "Vous devez spécifier le nouveau domaine principal",
"no_appslist_found": "Aucune liste dapplications na été trouvée",
"main_domain_change_failed": "Impossible de modifier le domaine principal",
"main_domain_changed": "Le domaine principal modifié",
"no_internet_connection": "Le serveur nest pas connecté à Internet",
"no_ipv6_connectivity": "La connectivité IPv6 nest pas disponible",
"no_restore_script": "Le script de sauvegarde na pas été trouvé pour lapplication '{app:s}'",
"no_such_conf_file": "Le fichier {file:s} nexiste pas, il ne peut pas être copié",
"not_enough_disk_space": "Lespace disque est insuffisant sur '{path:s}'",
"package_not_installed": "Le paquet '{pkgname}' nest pas installé",
"package_unexpected_error": "Une erreur inattendue s'est produite lors du traitement du paquet '{pkgname}'",
"package_unknown": "Le paquet '{pkgname}' est inconnu",
"packages_no_upgrade": "Il ny a aucun paquet à mettre à jour",
"packages_upgrade_critical_later": "Les paquets critiques ({packages:s}) seront mis à jour ultérieurement",
"packages_upgrade_failed": "Impossible de mettre à jour tous les paquets",
"path_removal_failed": "Impossible de supprimer le chemin {:s}",
"pattern_backup_archive_name": "Doit être un nom de fichier valide avec un maximum de 30 caractères, et composé de caractères alphanumériques et -_. uniquement",
"pattern_domain": "Doit être un nom de domaine valide (ex : mon-domaine.fr)",
"pattern_email": "Doit être une adresse de courriel valide (ex. : pseudo@domaine.fr)",
"pattern_email": "Doit être une adresse de courriel valide (ex. : pseudo@example.com)",
"pattern_firstname": "Doit être un prénom valide",
"pattern_lastname": "Doit être un nom valide",
"pattern_listname": "Doit être composé uniquement de caractères alphanumériques et de tirets bas (aussi appelé tiret du 8 ou underscore)",
"pattern_mailbox_quota": "Doit avoir une taille suffixée avec b/k/M/G/T ou 0 pour désactiver le quota",
"pattern_password": "Doit être composé dau moins 3 caractères",
"pattern_port": "Doit être un numéro de port valide compris entre 0 et 65535",
"pattern_port_or_range": "Doit être un numéro de port valide compris entre 0 et 65535, ou une gamme de ports (exemple : 100:200)",
"pattern_positive_number": "Doit être un nombre positif",
"pattern_username": "Doit être composé uniquement de caractères alphanumériques minuscules et de tirets bas (aussi appelé tiret du 8 ou underscore)",
"port_already_closed": "Le port {port:d} est déjà fermé pour les connexions {ip_version:s}",
"port_already_opened": "Le port {port:d} est déjà ouvert pour les connexions {ip_version:s}",
"port_available": "Le port {port:d} est disponible",
"port_unavailable": "Le port {port:d} nest pas disponible",
"restore_action_required": "Vous devez préciser ce qui est à restaurer",
"restore_already_installed_app": "Une application est déjà installée avec lidentifiant '{app:s}'",
"restore_app_failed": "Impossible de restaurer lapplication '{app:s}'",
"restore_cleaning_failed": "Impossible de nettoyer le dossier temporaire de restauration",
"restore_complete": "Restauration terminée",
"restore_complete": "Restauré",
"restore_confirm_yunohost_installed": "Voulez-vous vraiment restaurer un système déjà installé ? [{answers:s}]",
"restore_failed": "Impossible de restaurer le système",
"restore_hook_unavailable": "Le script de restauration '{part:s}' nest pas disponible sur votre système, et ne l'est pas non plus dans larchive",
"restore_hook_unavailable": "Le script de restauration '{part:s}' nest pas disponible sur votre système, et ne lest pas non plus dans larchive",
"restore_nothings_done": "Rien na été restauré",
"restore_running_app_script": "Exécution du script de restauration de l'application '{app:s}' .…",
"restore_running_app_script": "Exécution du script de restauration de lapplication '{app:s}' …",
"restore_running_hooks": "Exécution des scripts de restauration …",
"service_add_configuration": "Ajout du fichier de configuration {file:s}",
"service_add_failed": "Impossible dajouter le service '{service:s}'",
"service_added": "Le service '{service:s}' a été ajouté",
"service_already_started": "Le service '{service:s}' est déjà démarré",
"service_already_started": "Le service '{service:s}' est déjà en cours dexécution",
"service_already_stopped": "Le service '{service:s}' est déjà arrêté",
"service_cmd_exec_failed": "Impossible dexécuter la commande '{command:s}'",
"service_conf_file_backed_up": "Le fichier de configuration '{conf}' a été sauvegardé dans '{backup}'",
"service_conf_file_copy_failed": "Impossible de copier le nouveau fichier de configuration '{new}' vers '{conf}'",
"service_conf_file_manually_modified": "Le fichier de configuration '{conf}' a été modifié manuellement et ne sera pas mis à jour",
"service_conf_file_manually_removed": "Le fichier de configuration '{conf}' a été supprimé manuellement et ne sera pas créé",
"service_conf_file_not_managed": "Le fichier de configuration « {conf} » n'est pas géré pour l'instant et ne sera pas mis à jour",
"service_conf_file_remove_failed": "Impossible de supprimer le fichier de configuration '{conf}'",
"service_conf_file_removed": "Le fichier de configuration '{conf}' a été supprimé",
"service_conf_file_updated": "Le fichier de configuration '{conf}' a été mis à jour",
"service_conf_up_to_date": "La configuration du service '{service}' est déjà à jour",
"service_conf_updated": "La configuration a été mise à jour pour le service '{service}'",
"service_conf_would_be_updated": "La configuration du service '{service}' aurait été mise à jour",
"service_configuration_conflict": "Le fichier {file:s} a été modifié depuis sa dernière génération. Veuillez y appliquer les modifications manuellement ou utiliser loption --force (ce qui écrasera toutes les modifications effectuées sur le fichier).",
"service_configured": "La configuration du service « {service:s} » a été générée avec succès",
"service_configured_all": "La configuration de tous les services a été générée avec succès",
"service_disable_failed": "Impossible de désactiver le service '{service:s}'\n\nJournaux historisés récents : {logs:s}",
"service_disabled": "Le service '{service:s}' a été désactivé",
"service_enable_failed": "Impossible dactiver le service '{service:s}'\n\nJournaux historisés récents : {logs:s}",
"service_enabled": "Le service '{service:s}' a été activé",
"service_no_log": "Aucun journal historisé à afficher pour le service '{service:s}'",
"service_regenconf_dry_pending_applying": "Vérification des configurations en attentes qui pourraient être appliquées au le service '{service}' …",
"service_regenconf_failed": "Impossible de régénérer la configuration pour les services : {services}",
"service_regenconf_pending_applying": "Application des configurations en attentes pour le service '{service}' …",
"service_disable_failed": "Impossible de ne pas lancer le service « {service:s} » au démarrage.\n\nJournaux récents du service : {logs:s}",
"service_disabled": "Le service « {service:s} » ne sera plus lancé au démarrage du système.",
"service_enable_failed": "Impossible de lancer automatiquement le service « {service:s} » au démarrage.\n\nJournaux récents du service : {logs:s}",
"service_enabled": "Le service « {service:s} » sera désormais lancé automatiquement au démarrage du système.",
"service_remove_failed": "Impossible de supprimer le service '{service:s}'",
"service_removed": "Le service '{service:s}' a été supprimé",
"service_removed": "Le service « {service:s} » a été supprimé",
"service_start_failed": "Impossible de démarrer le service '{service:s}'\n\nJournaux historisés récents : {logs:s}",
"service_started": "Le service '{service:s}' a été démarré",
"service_status_failed": "Impossible de déterminer le statut du service '{service:s}'",
"service_started": "Le service « {service:s} » a été démarré",
"service_stop_failed": "Impossible darrêter le service '{service:s}'\n\nJournaux historisés récents : {logs:s}",
"service_stopped": "Le service '{service:s}' a été arrêté",
"service_stopped": "Le service « {service:s} » a été arrêté",
"service_unknown": "Le service '{service:s}' est inconnu",
"services_configured": "La configuration a été générée avec succès",
"show_diff": "Voici les différences :\n{diff:s}",
"ssowat_conf_generated": "La configuration de SSOwat a été générée",
"ssowat_conf_updated": "La configuration de SSOwat a été mise à jour",
"system_upgraded": "Le système a été mis à jour",
"ssowat_conf_generated": "La configuration de SSOwat générée",
"ssowat_conf_updated": "La configuration de SSOwat mise à jour",
"system_upgraded": "Système mis à jour",
"system_username_exists": "Ce nom dutilisateur existe déjà dans les utilisateurs système",
"unbackup_app": "Lapplication '{app:s}' ne sera pas sauvegardée",
"unexpected_error": "Une erreur inattendue est survenue : {error}",
"unit_unknown": "L'unité '{unit:s}' est inconnue",
"unlimit": "Pas de quota",
"unrestore_app": "Lapplication '{app:s}' ne sera pas restaurée",
"update_cache_failed": "Impossible de mettre à jour le cache de l'outil de gestion avancée des paquets (APT)",
"updating_apt_cache": "Récupération des mises à jour disponibles pour les paquets du système …",
"upgrade_complete": "Mise à jour terminée",
"upgrading_packages": "Mise à jour des paquets en cours …",
"upnp_dev_not_found": "Aucun périphérique compatible UPnP na été trouvé",
"upnp_disabled": "UPnP a été désactivé",
"upnp_enabled": "UPnP a été activé",
"upnp_disabled": "UPnP désactivé",
"upnp_enabled": "UPnP activé",
"upnp_port_open_failed": "Impossible douvrir les ports UPnP",
"user_created": "Lutilisateur a été créé",
"user_creation_failed": "Impossible de créer lutilisateur",
"user_deleted": "Lutilisateur a été supprimé",
"user_deletion_failed": "Impossible de supprimer lutilisateur",
"user_created": "Lutilisateur créé",
"user_creation_failed": "Impossible de créer lutilisateur {user}: {error}",
"user_deleted": "Lutilisateur supprimé",
"user_deletion_failed": "Impossible de supprimer lutilisateur {user}: {error}",
"user_home_creation_failed": "Impossible de créer le dossier personnel de lutilisateur",
"user_info_failed": "Impossible de récupérer les informations de lutilisateur",
"user_unknown": "L'utilisateur {user:s} est inconnu",
"user_update_failed": "Impossible de modifier lutilisateur",
"user_unknown": "Lutilisateur {user:s} est inconnu",
"user_update_failed": "Impossible de mettre à jour lutilisateur {user}: {error}",
"user_updated": "Lutilisateur a été modifié",
"yunohost_already_installed": "YunoHost est déjà installé",
"yunohost_ca_creation_failed": "Impossible de créer lautorité de certification",
"yunohost_configured": "YunoHost a été configuré",
"yunohost_installing": "L'installation de YunoHost est en cours …",
"yunohost_not_installed": "YunoHost nest pas ou pas correctement installé. Veuillez exécuter 'yunohost tools postinstall'",
"yunohost_configured": "YunoHost est maintenant configuré",
"yunohost_installing": "Linstallation de YunoHost est en cours …",
"yunohost_not_installed": "YunoHost nest pas correctement installé. Veuillez exécuter 'yunohost tools postinstall'",
"certmanager_attempt_to_replace_valid_cert": "Vous êtes en train de vouloir remplacer un certificat correct et valide pour le domaine {domain:s} ! (Utilisez --force pour contourner cela)",
"certmanager_domain_unknown": "Domaine {domain:s} inconnu",
"certmanager_domain_cert_not_selfsigned": "Le certificat du domaine {domain:s} nest pas auto-signé. Voulez-vous vraiment le remplacer ? (Utilisez --force pour cela)",
"certmanager_certificate_fetching_or_enabling_failed": "Il semble que lactivation du nouveau certificat pour {domain:s} a échoué …",
"certmanager_attempt_to_renew_nonLE_cert": "Le certificat pour le domaine {domain:s} nest pas émis par Lets Encrypt. Impossible de le renouveler automatiquement !",
"certmanager_attempt_to_renew_valid_cert": "Le certificat pour le domaine {domain:s} n'est pas sur le point dexpirer ! (Vous pouvez utiliser --force si vous savez ce que vous faites)",
"certmanager_attempt_to_renew_valid_cert": "Le certificat pour le domaine {domain:s} nest pas sur le point dexpirer ! (Vous pouvez utiliser --force si vous savez ce que vous faites)",
"certmanager_domain_http_not_working": "Il semble que le domaine {domain:s} ne soit pas accessible via HTTP. Veuillez vérifier que vos configuration DNS et Nginx sont correctes",
"certmanager_error_no_A_record": "Aucun enregistrement DNS 'A' na été trouvé pour {domain:s}. Vous devez faire pointer votre nom de domaine vers votre machine pour être en mesure dinstaller un certificat Lets 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": "Lenregistrement DNS 'A' du domaine {domain:s} est différent de ladresse IP de ce serveur. Si vous avez récemment modifié votre enregistrement 'A', veuillez attendre sa propagation (quelques vérificateur 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": "Lenregistrement DNS 'A' du domaine {domain:s} est différent de ladresse IP de ce serveur. Si vous avez récemment modifié votre enregistrement 'A', veuillez attendre sa propagation (quelques 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 sest mal passé lors de la tentative douverture du certificat actuel pour le domaine {domain:s} (fichier : {file:s}), la cause est : {reason:s}",
"certmanager_cert_install_success_selfsigned": "Installation avec succès dun certificat auto-signé pour le domaine {domain:s} !",
"certmanager_cert_install_success": "Installation avec succès dun certificat Lets Encrypt pour le domaine {domain:s} !",
"certmanager_cert_renew_success": "Renouvellement avec succès dun certificat Lets Encrypt pour le domaine {domain:s} !",
"certmanager_old_letsencrypt_app_detected": "\nYunoHost a détecté que lapplication « letsencrypt » est installé, ce qui est en conflit avec les nouvelles fonctionnalités de gestion intégrée de certificats dans YunoHost. Si vous souhaitez utiliser ces nouvelles fonctionnalités intégrées, veuillez lancer les commandes suivantes pour migrer votre installation :\n\n yunohost app remove letsencrypt\n yunohost domain cert-install\n\nN.B. : cela tentera de réinstaller les certificats de tous les domaines avec un certificat Let's Encrypt ou ceux auto-signés",
"certmanager_cert_signing_failed": "La signature du nouveau certificat a échoué",
"certmanager_cert_install_success_selfsigned": "Le certificat auto-signé est maintenant installé pour le domaine « {domain:s} »",
"certmanager_cert_install_success": "Le certificat Lets Encrypt est maintenant installé pour le domaine « {domain:s} »",
"certmanager_cert_renew_success": "Certificat Lets Encrypt renouvelé pour le domaine '{domain:s}'",
"certmanager_cert_signing_failed": "Impossible de signer le nouveau certificat",
"certmanager_no_cert_file": "Impossible de lire le fichier du certificat pour le domaine {domain:s} (fichier : {file:s})",
"certmanager_conflicting_nginx_file": "Impossible de préparer le domaine pour le défi ACME : le fichier de configuration Nginx {filepath:s} est en conflit et doit être préalablement retiré",
"certmanager_conflicting_nginx_file": "Impossible de préparer le domaine pour le défi ACME : le fichier de configuration NGINX {filepath:s} est en conflit et doit être préalablement retiré",
"certmanager_hit_rate_limit": "Trop de certificats ont déjà été émis récemment pour ce même ensemble de domaines {domain:s}. Veuillez réessayer plus tard. Lisez https://letsencrypt.org/docs/rate-limits/ pour obtenir plus de détails sur les ratios et limitations",
"ldap_init_failed_to_create_admin": "Linitialisation de l'annuaire LDAP na pas réussi à créer lutilisateur admin",
"ssowat_persistent_conf_read_error": "Erreur lors de la lecture de la configuration persistante de SSOwat : {error:s}. Modifiez le fichier /etc/ssowat/conf.json.persistent pour réparer la syntaxe JSON",
"ssowat_persistent_conf_write_error": "Erreur lors de la sauvegarde de la configuration persistante de SSOwat : {error:s}. Modifiez le fichier /etc/ssowat/conf.json.persistent pour réparer la syntaxe JSON",
"domain_cannot_remove_main": "Impossible de supprimer le domaine principal. Définissez d'abord un nouveau domaine principal",
"ldap_init_failed_to_create_admin": "Linitialisation de lannuaire LDAP na pas réussi à créer lutilisateur admin",
"domain_cannot_remove_main": "Vous ne pouvez pas supprimer '{domain:s}' car il sagit du domaine principal. Vous devez dabord définir un autre domaine comme domaine principal à laide de 'yunohost domain main-domain -n <another-domain>', voici la liste des domaines candidats. : {other_domains:s}",
"certmanager_self_ca_conf_file_not_found": "Le fichier de configuration pour lautorité du certificat auto-signé est introuvable (fichier : {file:s})",
"certmanager_unable_to_parse_self_CA_name": "Impossible danalyser le nom de lautorité du certificat auto-signé (fichier : {file:s})",
"mailbox_used_space_dovecot_down": "Le service de courriel Dovecot doit être démarré, si vous souhaitez voir lespace disque occupé par la messagerie",
"mailbox_used_space_dovecot_down": "Le service de courriel Dovecot doit être démarré si vous souhaitez voir lespace disque occupé par la messagerie",
"domains_available": "Domaines disponibles :",
"backup_archive_broken_link": "Impossible daccéder à larchive de sauvegarde (lien invalide vers {path:s})",
"certmanager_acme_not_configured_for_domain": "Le certificat du domaine {domain:s} ne semble pas être correctement installé. Veuillez d'abord exécuter cert-install.",
"certmanager_domain_not_resolved_locally": "Le domaine {domain:s} ne peut être résolu depuis votre serveur YunoHost. Cela peut se produire si vous avez récemment modifié votre enregistrement DNS. Si c'est le cas, merci dattendre quelques heures quil se propage. Si le problème persiste, envisager dajouter {domain:s} au fichier /etc/hosts. (Si vous savez ce que vous faites, utilisez --no-checks pour désactiver ces vérifications.)",
"certmanager_http_check_timeout": "Expiration du délai lorsque le serveur a essayé de se contacter lui-même via HTTP en utilisant l'adresse IP public {ip:s} du domaine {domain:s}. Vous rencontrez peut-être un problème dhairpinning ou alors le pare-feu/routeur en amont de votre serveur est mal configuré.",
"certmanager_acme_not_configured_for_domain": "Le certificat du domaine {domain:s} ne semble pas être correctement installé. Veuillez dabord exécuter cert-install.",
"certmanager_http_check_timeout": "Expiration du délai lorsque le serveur a essayé de se contacter lui-même via HTTP en utilisant ladresse IP public {ip:s} du domaine {domain:s}. Vous rencontrez peut-être un problème dhairpinning ou alors le pare-feu/routeur en amont de votre serveur est mal configuré.",
"certmanager_couldnt_fetch_intermediate_cert": "Expiration du délai lors de la tentative de récupération du certificat intermédiaire depuis Lets Encrypt. Linstallation ou le renouvellement du certificat a été annulé. Veuillez réessayer plus tard.",
"appslist_retrieve_bad_format": "Le fichier récupéré pour la liste dapplications {appslist:s} nest pas valide",
"domain_hostname_failed": "Échec de lutilisation dun nouveau nom dhôte. Cela pourrait causer des soucis plus tard (mais ce nest pas sûr… peut-être que ça nen causera pas).",
"yunohost_ca_creation_success": "Lautorité de certification locale a été créée.",
"appslist_name_already_tracked": "Il y a déjà une liste dapplications enregistrée avec le nom {name:s}.",
"appslist_url_already_tracked": "Il y a déjà une liste dapplications enregistrée avec lURL {url:s}.",
"appslist_migrating": "Migration de la liste dapplications {appslist:s} …",
"appslist_could_not_migrate": "Impossible de migrer la liste {appslist:s} ! Impossible dexploiter lURL. Lancienne tâche programmée a été conservée dans {bkp_file:s}.",
"appslist_corrupted_json": "Impossible de charger la liste dapplications. Il semble que {filename:s} soit corrompu.",
"app_already_installed_cant_change_url": "Cette application est déjà installée. LURL ne peut pas être changé simplement par cette fonction. Regardez si cela est disponible avec `app changeurl`.",
"app_change_no_change_url_script": "Lapplication {app_name:s} ne prend pas encore en charge le changement dURL, vous pourriez avoir besoin de la mettre à jour.",
"domain_hostname_failed": "Échec de lutilisation dun nouveau nom dhôte. Cela pourrait causer des soucis plus tard (peut-être que ça nen causera pas).",
"yunohost_ca_creation_success": "Lautorité de certification locale créée.",
"app_already_installed_cant_change_url": "Cette application est déjà installée. LURL ne peut pas être changé simplement par cette fonction. Vérifiez si cela est disponible avec `app changeurl`.",
"app_change_url_failed_nginx_reload": "Le redémarrage de Nginx a échoué. Voici la sortie de 'nginx -t' :\n{nginx_errors:s}",
"app_change_url_identical_domains": "Lancien et le nouveau couple domaine/chemin_de_l'URL sont identiques pour ('{domain:s}{path:s}'), rien à faire.",
"app_change_url_identical_domains": "Lancien et le nouveau couple domaine/chemin_de_lURL sont identiques pour ('{domain:s}{path:s}'), rien à faire.",
"app_change_url_no_script": "Lapplication '{app_name:s}' ne prend pas encore en charge le changement dURL. Vous devriez peut-être la mettre à jour.",
"app_change_url_success": "LURL de lapplication {app:s} a été changée en {domain:s}{path:s}",
"app_location_unavailable": "Cette URL nest pas disponible ou est en conflit avec une application existante :\n{apps:s}",
"app_already_up_to_date": "{app:s} est déjà à jour",
"invalid_url_format": "Format dURL non valide",
"global_settings_bad_choice_for_enum": "Valeur du paramètre {setting:s} incorrecte. Reçu : {received_type:s}, mais les valeurs possibles sont : {expected_type:s}",
"global_settings_bad_choice_for_enum": "Valeur du paramètre {setting:s} incorrecte. Reçu : {choice:s}, mais les valeurs possibles sont : {available_choices:s}",
"global_settings_bad_type_for_setting": "Le type du paramètre {setting:s} est incorrect. Reçu {received_type:s} alors que {expected_type:s} était attendu",
"global_settings_cant_open_settings": "Échec de louverture du ficher de configurations car : {reason:s}",
"global_settings_cant_serialize_setings": "Échec de sérialisation des données de configurations, cause : {reason:s}",
"global_settings_cant_write_settings": "Échec décriture du fichier de configurations car : {reason:s}",
"global_settings_key_doesnt_exists": "La clef '{settings_key:s}' nexiste pas dans les configurations générales, vous pouvez voir toutes les clefs disponibles en saisissant 'yunohost settings list'",
"global_settings_reset_success": "Super ! Vos configurations précédentes ont été sauvegardées dans {path:s}",
"global_settings_reset_success": "Vos configurations précédentes ont été sauvegardées dans {path:s}",
"global_settings_setting_example_bool": "Exemple doption booléenne",
"global_settings_setting_example_int": "Exemple doption de type entier",
"global_settings_setting_example_string": "Exemple doption de type chaîne",
"global_settings_setting_example_enum": "Exemple doption de type énumération",
"global_settings_unknown_type": "Situation inattendue : la configuration {setting:s} semble avoir le type {unknown_type:s} mais celui-ci n'est pas pris en charge par le système.",
"global_settings_unknown_type": "Situation inattendue : la configuration {setting:s} semble avoir le type {unknown_type:s} mais celui-ci nest pas pris en charge par le système.",
"global_settings_unknown_setting_from_settings_file": "Clé inconnue dans les paramètres : '{setting_key:s}', rejet de cette clé et sauvegarde de celle-ci dans /etc/yunohost/unkown_settings.json",
"service_conf_new_managed_file": "Le fichier de configuration « {conf} » est désormais géré par le service {service}.",
"service_conf_file_kept_back": "Le fichier de configuration '{conf}' devait être supprimé par le service {service} mais a été conservé.",
"backup_abstract_method": "Cette méthode de sauvegarde na pas encore été implémentée",
"backup_applying_method_tar": "Création de larchive tar de la sauvegarde …",
"backup_abstract_method": "Cette méthode de sauvegarde reste à implémenter",
"backup_applying_method_tar": "Création de larchive TAR de la sauvegarde …",
"backup_applying_method_copy": "Copie de tous les fichiers à sauvegarder …",
"backup_applying_method_borg": "Envoi de tous les fichiers à sauvegarder dans le répertoire borg-backup…",
"backup_applying_method_borg": "Envoi de tous les fichiers à sauvegarder dans le répertoire borg-backup …",
"backup_applying_method_custom": "Appel de la méthode de sauvegarde personnalisée '{method:s}' …",
"backup_archive_system_part_not_available": "La partie '{part:s}' du système nest pas disponible dans cette sauvegarde",
"backup_archive_mount_failed": "Le montage de larchive de sauvegarde a échoué",
"backup_archive_writing_error": "Impossible d'ajouter des fichiers '{source:s}' (nommés dans l'archive : '{dest:s}') à sauvegarder dans l'archive compressée '{archive:s}'",
"backup_ask_for_copying_if_needed": "Certains fichiers nont pas pu être préparés pour être sauvegardés en utilisant la méthode qui évite temporairement de gaspiller de lespace sur le système. Pour réaliser la sauvegarde, {size:s} Mo doivent être temporairement utilisés. Acceptez-vous ?",
"backup_archive_writing_error": "Impossible dajouter des fichiers '{source:s}' (nommés dans larchive : '{dest:s}') à sauvegarder dans larchive compressée '{archive:s}'",
"backup_ask_for_copying_if_needed": "Voulez-vous effectuer la sauvegarde en utilisant {size:s} temporairement ? (Cette méthode est utilisée car certains fichiers nont pas pu être préparés avec une méthode plus efficace.)",
"backup_borg_not_implemented": "La méthode de sauvegarde Borg nest pas encore implémentée",
"backup_cant_mount_uncompress_archive": "Impossible de monter en lecture seule le dossier de larchive décompressée",
"backup_copying_to_organize_the_archive": "Copie de {size:s} Mo pour organiser larchive",
"backup_csv_creation_failed": "Impossible de créer le fichier CSV nécessaire aux opérations futures de restauration",
"backup_csv_creation_failed": "Impossible de créer le fichier CSV nécessaire à la restauration",
"backup_csv_addition_failed": "Impossible dajouter des fichiers à sauvegarder dans le fichier CSV",
"backup_custom_need_mount_error": "Échec de la méthode de sauvegarde personnalisée à létape 'need_mount'",
"backup_custom_backup_error": "Échec de la méthode de sauvegarde personnalisée à létape 'backup'",
"backup_custom_mount_error": "Échec de la méthode de sauvegarde personnalisée à létape 'mount'",
"backup_no_uncompress_archive_dir": "Le dossier de larchive décompressée nexiste pas",
"backup_method_tar_finished": "Larchive tar de la sauvegarde a été créée",
"backup_no_uncompress_archive_dir": "Ce dossier darchive décompressée nexiste pas",
"backup_method_tar_finished": "Larchive TAR de la sauvegarde a été créée",
"backup_method_copy_finished": "La copie de la sauvegarde est terminée",
"backup_method_borg_finished": "La sauvegarde dans Borg est terminée",
"backup_method_custom_finished": "La méthode de sauvegarde personnalisée '{method:s}' est terminée",
"backup_system_part_failed": "Impossible de sauvegarder la partie '{part:s}' du système",
"backup_unable_to_organize_files": "Impossible dorganiser les fichiers dans larchive avec la méthode rapide",
"backup_unable_to_organize_files": "Impossible dutiliser la méthode rapide pour organiser les fichiers dans larchive",
"backup_with_no_backup_script_for_app": "Lapplication {app:s} na pas de script de sauvegarde. Ignorer.",
"backup_with_no_restore_script_for_app": "Lapplication {app:s} na pas de script de restauration, vous ne pourrez pas restaurer automatiquement la sauvegarde de cette application.",
"backup_with_no_restore_script_for_app": "Lapplication « {app:s} » na pas de script de restauration, vous ne pourrez pas restaurer automatiquement la sauvegarde de cette application.",
"global_settings_cant_serialize_settings": "Échec de la sérialisation des données de paramétrage car : {reason:s}",
"restore_removing_tmp_dir_failed": "Impossible de sauvegarder un ancien dossier temporaire",
"restore_extracting": "Extraction des fichiers nécessaires depuis larchive …",
"restore_mounting_archive": "Montage de larchive dans '{path:s}'",
"restore_may_be_not_enough_disk_space": "Votre système semble ne pas avoir suffisamment despace disponible (L'espace libre est de {free_space:d} octets. Le besoin d'espace nécessaire est de {needed_space:d} octets. En appliquant une marge de sécurité, la quantité d'espace nécessaire est de {margin:d} octets)",
"restore_not_enough_disk_space": "Espace disponible insuffisant (L'espace libre est de {free_space:d} octets. Le besoin d'espace nécessaire est de {needed_space:d} octets. En appliquant une marge de sécurité, la quantité d'espace nécessaire est de {margin:d} octets)",
"restore_may_be_not_enough_disk_space": "Votre système semble ne pas avoir suffisamment despace disponible (Lespace libre est de {free_space:d} octets. Le besoin despace nécessaire est de {needed_space:d} octets. En appliquant une marge de sécurité, la quantité despace nécessaire est de {margin:d} octets)",
"restore_not_enough_disk_space": "Espace disponible insuffisant (Lespace libre est de {free_space:d} octets. Le besoin despace nécessaire est de {needed_space:d} octets. En appliquant une marge de sécurité, la quantité despace nécessaire est de {margin:d} octets)",
"restore_system_part_failed": "Impossible de restaurer la partie '{part:s}' du système",
"backup_couldnt_bind": "Impossible de lier {src:s} avec {dest:s}.",
"domain_dns_conf_is_just_a_recommendation": "Cette page montre la configuration *recommandée*. Elle ne configure *pas* le DNS pour vous. Il est de votre responsabilité que de configurer votre zone DNS chez votre fournisseur/registrar DNS avec cette recommandation.",
"domain_dyndns_dynette_is_unreachable": "Impossible de contacter la dynette YunoHost. Soit YunoHost nest pas correctement connecté à internet, soit le serveur de dynette est en panne. Erreur : {error}",
"migrations_backward": "Migration en arrière.",
"migrations_bad_value_for_target": "Nombre invalide pour le paramètre target, les numéros de migration sont 0 ou {}",
"migrations_cant_reach_migration_file": "Impossible daccéder aux fichiers de migrations avec le chemin %s",
"migrations_current_target": "La cible de migration est {}",
"migrations_error_failed_to_load_migration": "ERREUR : échec du chargement de migration {number} {name}",
"migrations_forward": "Migration en avant",
"migrations_loading_migration": "Chargement de la migration {number} {name} …",
"migrations_migration_has_failed": "La migration {number} {name} a échoué avec lexception {exception} : annulation",
"migrations_cant_reach_migration_file": "Impossible daccéder aux fichiers de migration via le chemin '%s'",
"migrations_loading_migration": "Chargement de la migration {id} …",
"migrations_migration_has_failed": "La migration {id} a échoué avec lexception {exception} : annulation",
"migrations_no_migrations_to_run": "Aucune migration à lancer",
"migrations_show_currently_running_migration": "Application de la migration {number} {name} …",
"migrations_show_last_migration": "La dernière migration appliquée est {}",
"migrations_skip_migration": "Ignorer et passer la migration {number} {name}…",
"server_shutdown": "Le serveur va éteindre",
"migrations_skip_migration": "Ignorer et passer la migration {id} …",
"server_shutdown": "Le serveur va séteindre",
"server_shutdown_confirm": "Le serveur va être éteint immédiatement, le voulez-vous vraiment ? [{answers:s}]",
"server_reboot": "Le serveur va redémarrer",
"server_reboot_confirm": "Le serveur va redémarrer immédiatement, le voulez-vous vraiment ? [{answers:s}]",
"app_upgrade_some_app_failed": "Impossible de mettre à jour certaines applications",
"ask_path": "Chemin",
"app_upgrade_some_app_failed": "Certaines applications nont pas été mises à jour",
"dyndns_could_not_check_provide": "Impossible de vérifier si {provider:s} peut fournir {domain:s}.",
"dyndns_domain_not_provided": "Le fournisseur DynDNS {provider:s} ne peut pas fournir le domaine {domain:s}.",
"app_make_default_location_already_used": "Impossible de configurer lapplication '{app}' par défaut pour le domaine {domain} car il est déjà utilisé par l'application '{other_app}'",
"app_make_default_location_already_used": "Impossible de configurer lapplication '{app}' par défaut pour le domaine '{domain}' car il est déjà utilisé par lapplication '{other_app}'",
"app_upgrade_app_name": "Mise à jour de lapplication {app} …",
"backup_output_symlink_dir_broken": "Vous avez un lien symbolique cassé à la place de votre dossier darchives « {path:s} ». Vous pourriez avoir une configuration personnalisée pour sauvegarder vos données sur un autre système de fichiers, dans ce cas vous avez probablement oublié de monter ou de connecter votre disque dur ou votre clé USB.",
"migrate_tsig_end": "La migration à hmac-sha512 est terminée",
"backup_output_symlink_dir_broken": "Votre répertoire darchivage '{path:s}' est un lien symbolique brisé. Peut-être avez-vous oublié de re/monter ou de brancher le support de stockage sur lequel il pointe.",
"migrate_tsig_end": "La migration à HMAC-SHA-512 est terminée",
"migrate_tsig_failed": "La migration du domaine DynDNS {domain} à hmac-sha512 a échoué. Annulation des modifications. Erreur : {error_code} - {error}",
"migrate_tsig_start": "Lalgorithme de génération des clefs nest pas suffisamment sécurisé pour la signature TSIG du domaine '{domain}', lancement de la migration vers hmac-sha512 qui est plus sécurisé",
"migrate_tsig_wait": "Attendre 3 minutes pour que le serveur DynDNS prenne en compte la nouvelle clef …",
"migrate_tsig_start": "Lalgorithme de génération des clefs nest pas suffisamment sécurisé pour la signature TSIG du domaine '{domain}', lancement de la migration vers HMAC-SHA-512 qui est plus sécurisé",
"migrate_tsig_wait": "Attendre trois minutes pour que le serveur DynDNS prenne en compte la nouvelle clef …",
"migrate_tsig_wait_2": "2 minutes …",
"migrate_tsig_wait_3": "1 minute …",
"migrate_tsig_wait_4": "30 secondes …",
"migrate_tsig_not_needed": "Il ne semble pas que vous utilisez un domaine DynDNS, donc aucune migration nest nécessaire !",
"app_checkurl_is_deprecated": "Packagers /!\\ 'app checkurl' est obsolète ! Utilisez 'app register-url' en remplacement !",
"migrate_tsig_wait_4": "30 secondes …",
"migrate_tsig_not_needed": "Il ne semble pas que vous utilisez un domaine DynDNS, donc aucune migration nest nécessaire.",
"migration_description_0001_change_cert_group_to_sslcert": "Changement des permissions de groupe des certificats de « metronome » à « ssl-cert »",
"migration_description_0002_migrate_to_tsig_sha256": "Amélioration de la sécurité de DynDNS TSIG en utilisant SHA512 au lieu de MD5",
"migration_description_0003_migrate_to_stretch": "Mise à niveau du système vers Debian Stretch et YunoHost 3.0",
"migration_0003_backward_impossible": "La migration Stretch nest pas réversible.",
"migration_0003_start": "Démarrage de la migration vers Stretch. Les journaux seront disponibles dans {logfile}.",
"migration_0003_patching_sources_list": "Modification du fichier sources.lists …",
"migration_0003_main_upgrade": "Démarrage de la mise à niveau principale …",
"migration_0003_fail2ban_upgrade": "Démarrage de la mise à niveau de fail2ban …",
"migration_0003_restoring_origin_nginx_conf": "Votre fichier /etc/nginx/nginx.conf a été modifié dune manière ou dune autre. La migration va dabords le réinitialiser à son état initial. Le fichier précédent sera disponible en tant que {backup_dest}.",
"migration_0003_restoring_origin_nginx_conf": "Votre fichier /etc/nginx/nginx.conf a été modifié dune manière ou dune autre. La migration va dabord le réinitialiser à son état initial. Le fichier précédent sera disponible en tant que {backup_dest}.",
"migration_0003_yunohost_upgrade": "Démarrage de la mise à niveau du paquet YunoHost. La migration se terminera, mais la mise à jour réelle aura lieu immédiatement après. Une fois cette opération terminée, vous pourriez avoir à vous reconnecter à ladministration via le panel web.",
"migration_0003_not_jessie": "La distribution Debian actuelle nest pas Jessie !",
"migration_0003_system_not_fully_up_to_date": "Votre système nest pas complètement à jour. Veuillez mener une mise à jour classique avant de lancer à migration à Stretch.",
"migration_0003_system_not_fully_up_to_date": "Votre système nest pas complètement à jour. Veuillez mener une mise à jour classique avant de lancer la migration à Stretch.",
"migration_0003_still_on_jessie_after_main_upgrade": "Quelque chose sest mal passé pendant la mise à niveau principale : le système est toujours sur Debian Jessie !? Pour investiguer sur le problème, veuillez regarder les journaux {log}:s …",
"migration_0003_general_warning": "Veuillez noter que cette migration est une opération délicate. Si léquipe YunoHost a fait de son mieux pour la relire et la tester, la migration pourrait tout de même casser des parties de votre système ou de vos applications.\n\nEn conséquence, nous vous recommandons :\n - de lancer une sauvegarde de vos données ou applications critiques. Plus dinformations sur https://yunohost.org/backup ;\n - dêtre patient après avoir lancé la migration : selon votre connexion internet et matériel, cela pourrait prendre jusquà quelques heures pour que tout soit à niveau.\n\nEn outre, le port SMTP utilisé par les clients de messagerie externes comme (Thunderbird ou K9-Mail) a été changé de 465 (SSL/TLS) à 587 (STARTTLS). Lancien port 465 sera automatiquement fermé et le nouveau port 587 sera ouvert dans le pare-feu. Vous et vos utilisateurs *devront* adapter la configuration de vos clients de messagerie en conséquence !",
"migration_0003_problematic_apps_warning": "Veuillez noter que des applications possiblement problématiques ont été détectées. Il semble quelles naient pas été installées depuis une liste dapplication ou quelles ne soit pas marquées comme « fonctionnelles ». En conséquence, nous ne pouvons pas garantir quelles fonctionneront après la mise à niveau : {problematic_apps}",
"migration_0003_general_warning": "Veuillez noter que cette migration est une opération délicate. Si léquipe YunoHost a fait de son mieux pour la relire et la tester, la migration pourrait tout de même casser des parties de votre système ou de vos applications.\n\nEn conséquence, nous vous recommandons :\n - de lancer une sauvegarde de vos données ou applications critiques. Plus dinformations sur https://yunohost.org/backup ;\n - dêtre patient après avoir lancé la migration : selon votre connexion internet et matériel, cela pourrait prendre jusquà quelques heures pour que tout soit à niveau.\n\nEn outre, le port SMTP utilisé par les clients de messagerie externes comme (Thunderbird ou K9-Mail) a été changé de 465 (SSL/TLS) à 587 (STARTTLS). Lancien port 465 sera automatiquement fermé et le nouveau port 587 sera ouvert dans le pare-feu. Vous et vos utilisateurs *devront* adapter la configuration de vos clients de messagerie en conséquence.",
"migration_0003_problematic_apps_warning": "Veuillez noter que les applications installées potentiellement problématiques suivantes ont été détectées. Il semble que celles-ci nont pas été installées à partir dun catalogue dapplications, ou ne sont pas marquées comme \"fonctionnelle\". Par conséquent, il ne peut pas être garanti quils fonctionneront toujours après la mise à niveau: {problematic_apps}",
"migration_0003_modified_files": "Veuillez noter que les fichiers suivants ont été détectés comme modifiés manuellement et pourraient être écrasés à la fin de la mise à niveau : {manually_modified_files}",
"migrations_list_conflict_pending_done": "Vous ne pouvez pas utiliser --previous et --done simultanément.",
"migrations_to_be_ran_manually": "La migration {number} {name} doit être lancée manuellement. Veuillez aller dans Outils > Migrations dans linterface admin, ou lancer `yunohost tools migrations migrate`.",
"migrations_need_to_accept_disclaimer": "Pour lancer la migration {number} {name}, vous devez accepter cette clause de non-responsabilité :\n---\n{disclaimer}\n---\nSi vous acceptez de lancer la migration, veuillez relancer la commande avec loption --accept-disclaimer.",
"service_description_avahi-daemon": "permet datteindre votre serveur via yunohost.local sur votre réseau local",
"service_description_dnsmasq": "gère la résolution des noms de domaine (DNS)",
"service_description_dovecot": "permet aux clients de messagerie daccéder/récupérer les courriels (via IMAP et POP3)",
"service_description_fail2ban": "protège contre les attaques brute-force et autres types dattaques venant dInternet",
"service_description_glances": "surveille les informations système de votre serveur",
"service_description_metronome": "gère les comptes de messagerie instantanée XMPP",
"service_description_mysql": "stocke les données des applications (bases de données SQL)",
"service_description_nginx": "sert ou permet laccès à tous les sites web hébergés sur votre serveur",
"service_description_nslcd": "gère la connexion en ligne de commande des utilisateurs YunoHost",
"service_description_php5-fpm": "exécute des applications écrites en PHP avec nginx",
"service_description_postfix": "utilisé pour envoyer et recevoir des courriels",
"service_description_redis-server": "une base de données spécialisée utilisée pour laccès rapide aux données, les files dattentes et la communication entre les programmes",
"service_description_rmilter": "vérifie divers paramètres dans les courriels",
"service_description_rspamd": "filtre le pourriel, et dautres fonctionnalités liées au courriel",
"service_description_slapd": "stocke les utilisateurs, domaines et leurs informations liées",
"service_description_ssh": "vous permet de vous connecter à distance à votre serveur via un terminal (protocole SSH)",
"service_description_yunohost-api": "permet les interactions entre linterface web de YunoHost et le système",
"service_description_yunohost-firewall": "gère l'ouverture et la fermeture des ports de connexion aux services",
"migrations_to_be_ran_manually": "La migration {id} doit être lancée manuellement. Veuillez aller dans Outils > Migrations dans linterface admin, ou lancer `yunohost tools migrations migrate`.",
"migrations_need_to_accept_disclaimer": "Pour lancer la migration {id}, vous devez accepter cette clause de non-responsabilité :\n---\n{disclaimer}\n---\nSi vous acceptez de lancer la migration, veuillez relancer la commande avec loption --accept-disclaimer.",
"service_description_avahi-daemon": "Vous permet datteindre votre serveur en utilisant «yunohost.local» sur votre réseau local",
"service_description_dnsmasq": "Gère la résolution des noms de domaine (DNS)",
"service_description_dovecot": "Permet aux clients de messagerie daccéder/récupérer les courriels (via IMAP et POP3)",
"service_description_fail2ban": "Protège contre les attaques brute-force et autres types dattaques venant dInternet",
"service_description_metronome": "Gère les comptes de messagerie instantanée XMPP",
"service_description_mysql": "Stocke les données des applications (bases de données SQL)",
"service_description_nginx": "Sert ou permet laccès à tous les sites web hébergés sur votre serveur",
"service_description_nslcd": "Gère la connexion en ligne de commande des utilisateurs YunoHost",
"service_description_postfix": "Utilisé pour envoyer et recevoir des courriels",
"service_description_redis-server": "Une base de données spécialisée utilisée pour laccès rapide aux données, les files dattentes et la communication entre les programmes",
"service_description_rspamd": "Filtre le pourriel, et dautres fonctionnalités liées au courriel",
"service_description_slapd": "Stocke les utilisateurs, domaines et leurs informations liées",
"service_description_ssh": "Vous permet de vous connecter à distance à votre serveur via un terminal (protocole SSH)",
"service_description_yunohost-api": "Permet les interactions entre linterface web de YunoHost et le système",
"service_description_yunohost-firewall": "Gère louverture et la fermeture des ports de connexion aux services",
"experimental_feature": "Attention : cette fonctionnalité est expérimentale et ne doit pas être considérée comme stable, vous ne devriez pas lutiliser à moins que vous ne sachiez ce que vous faites.",
"log_corrupted_md_file": "Le fichier yaml de métadonnées associé aux logs est corrompu : '{md_file}'\nErreur : {error}",
"log_corrupted_md_file": "Le fichier YAML de métadonnées associé aux logs est corrompu : '{md_file}'\nErreur : {error}",
"log_category_404": "Le journal de la catégorie '{category}' nexiste pas",
"log_link_to_log": "Journal historisé complet de cette opération : '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\"> {desc} </a>'",
"log_help_to_get_log": "Pour voir le journal historisé de cette opération '{desc}', utilisez la commande 'yunohost log display {name}'",
"log_link_to_failed_log": "Lopération '{desc}' a échouée ! Pour avoir de laide, merci <a href=\"#/tools/logs/{name}\"> de fournir le journal historisé complet de lopération en cliquant ici</a>",
"backup_php5_to_php7_migration_may_fail": "Impossible de convertir votre archive pour prendre en charge php7, vos applications php pourraient ne pas être restaurées (reason: {error:s})",
"log_help_to_get_failed_log": "Lopération '{desc}' a échouée ! Pour avoir de laide, merci de partager le journal historisé de cette opération en utilisant la commande 'yunohost log display {name} --share'",
"log_does_exists": "Il nexiste pas de journal historisé de lopération ayant pour nom '{log}', utiliser 'yunohost log list pour voir tous les fichiers de journaux historisés disponibles'",
"log_link_to_log": "Journal complet de cette opération : '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\"> {desc} </a>'",
"log_help_to_get_log": "Pour voir le journal de cette opération '{desc}', utilisez la commande 'yunohost log display {name}'",
"log_link_to_failed_log": "Lopération '{desc}' a échoué ! Pour obtenir de laide, merci de partager le journal de lopération en <a href=\"#/tools/logs/{name}\">cliquant ici</a>",
"backup_php5_to_php7_migration_may_fail": "Impossible de convertir votre archive pour prendre en charge PHP 7, vous pourriez ne plus pouvoir restaurer vos applications PHP (cause : {error:s})",
"log_help_to_get_failed_log": "Lopération '{desc}' a échoué ! Pour obtenir de laide, merci de partager le journal de lopération en utilisant la commande 'yunohost log display {name} --share'",
"log_does_exists": "Il nexiste pas de journal de lopération ayant pour nom '{log}', utiliser 'yunohost log list' pour voir tous les fichiers de journaux disponibles",
"log_operation_unit_unclosed_properly": "Lopération ne sest pas terminée correctement",
"log_app_addaccess": "Ajouter laccès à '{}'",
"log_app_removeaccess": "Enlever laccès à '{}'",
"log_app_clearaccess": "Retirer tous les accès à '{}'",
"log_app_fetchlist": "Ajouter une liste dapplication",
"log_app_removelist": "Enlever une liste dapplication",
"log_app_change_url": "Changer lURL de lapplication '{}'",
"log_app_install": "Installer lapplication '{}'",
"log_app_remove": "Enlever lapplication '{}'",
"log_app_upgrade": "Mettre à jour lapplication '{}'",
"log_app_makedefault": "Faire de '{}' lapplication par défaut",
"log_available_on_yunopaste": "Le journal historisé est désormais disponible via {url}",
"log_available_on_yunopaste": "Le journal est désormais disponible via {url}",
"log_backup_restore_system": "Restaurer le système depuis une archive de sauvegarde",
"log_backup_restore_app": "Restaurer '{}' depuis une sauvegarde",
"log_remove_on_failed_restore": "Retirer '{}' après un échec de restauration depuis une archive de sauvegarde",
@ -449,84 +323,78 @@
"log_letsencrypt_cert_install": "Installer le certificat Lets Encrypt sur le domaine '{}'",
"log_selfsigned_cert_install": "Installer le certificat auto-signé sur le domaine '{}'",
"log_letsencrypt_cert_renew": "Renouveler le certificat Lets Encrypt de '{}'",
"log_service_enable": "Activer le service '{}'",
"log_service_regen_conf": "Régénérer la configuration système de '{}'",
"log_user_create": "Ajouter lutilisateur '{}'",
"log_user_delete": "Supprimer lutilisateur '{}'",
"log_user_update": "Mettre à jour les informations de lutilisateur '{}'",
"log_tools_maindomain": "Faire de '{}' le domaine principal",
"log_tools_migrations_migrate_forward": "Migrer vers",
"log_tools_migrations_migrate_backward": "Revenir en arrière",
"log_domain_main_domain": "Faire de '{}' le domaine principal",
"log_tools_migrations_migrate_forward": "Éxecuter les migrations",
"log_tools_postinstall": "Faire la post-installation de votre serveur YunoHost",
"log_tools_upgrade": "Mettre à jour les paquets du système",
"log_tools_shutdown": "Éteindre votre serveur",
"log_tools_reboot": "Redémarrer votre serveur",
"mail_unavailable": "Cette adresse de courriel est réservée et doit être automatiquement attribuée au tout premier utilisateur",
"migration_description_0004_php5_to_php7_pools": "Reconfiguration des groupes PHP pour utiliser PHP 7 au lieu de PHP 5",
"migration_description_0004_php5_to_php7_pools": "Reconfigurer les espaces utilisateurs PHP pour utiliser PHP 7 au lieu de PHP 5",
"migration_description_0005_postgresql_9p4_to_9p6": "Migration des bases de données de PostgreSQL 9.4 vers PostgreSQL 9.6",
"migration_0005_postgresql_94_not_installed": "PostgreSQL na pas été installé sur votre système. Rien à faire !",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 a été trouvé et installé, mais pas PostgreSQL 9.6 !? Quelque chose détrange a dû arriver à votre système… :(",
"migration_0005_not_enough_space": "Il ny a pas assez despace libre de disponible sur {path} pour lancer maintenant la migration :(.",
"recommend_to_add_first_user": "La post-installation est terminée mais YunoHost a besoin dau moins un utilisateur pour fonctionner correctement. Vous devez en ajouter un en utilisant la commande 'yunohost user create $nomdutilisateur' ou bien via linterface dadministration web.",
"service_description_php7.0-fpm": "exécute des applications écrites en PHP avec Nginx",
"migration_0005_not_enough_space": "Laissez suffisamment despace disponible dans {path} pour exécuter la migration.",
"service_description_php7.0-fpm": "Exécute des applications écrites en PHP avec NGINX",
"users_available": "Liste des utilisateurs disponibles :",
"good_practices_about_admin_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe dadministration. Le mot de passe doit comporter au moins 8 caractères bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).",
"good_practices_about_user_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe utilisateur. Le mot de passe doit comporter au moins 8 caractères - bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères tels que : majuscules, minuscules, chiffres et caractères spéciaux.",
"migration_description_0006_sync_admin_and_root_passwords": "Synchroniser les mots de passe admin et root",
"migration_0006_disclaimer": "YunoHost sattendra désormais à ce que les mots de passe admin et root soient synchronisés. En exécutant cette migration, votre mot de passe root sera remplacé par le mot de passe administrateur.",
"migration_0006_done": "Votre mot de passe root a été remplacé par celui de votre adminitrateur.",
"password_listed": "Ce mot de passe est l'un des mots de passe les plus utilisés dans le monde. Veuillez choisir quelque chose d'un peu plus singulier.",
"migration_0006_disclaimer": "YunoHost sattend maintenant à ce que les mots de passe administrateur et racine soient synchronisés. Cette migration remplace votre mot de passe root par le mot de passe administrateur.",
"password_listed": "Ce mot de passe est lun des mots de passe les plus utilisés dans le monde. Veuillez choisir quelque chose dun peu plus singulier.",
"password_too_simple_1": "Le mot de passe doit comporter au moins 8 caractères",
"password_too_simple_2": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des majuscules et des minuscules",
"password_too_simple_3": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des majuscules, des minuscules et des caractères spéciaux",
"password_too_simple_4": "Le mot de passe doit comporter au moins 12 caractères et contenir des chiffres, des majuscules, des minuscules et des caractères spéciaux",
"root_password_desynchronized": "Le mot de passe administrateur a été changé, mais YunoHost na pas pu le propager au mot de passe root !",
"aborting": "Opération annulée.",
"app_not_upgraded": "Les applications suivantes n'ont pas été mises à jour : {apps}",
"app_start_install": "Installation de l'application {app} …",
"app_start_remove": "Suppression de l'application {app} …",
"app_start_backup": "Collecte des fichiers devant être sauvegardés pour {app} …",
"app_start_restore": "Restauration de l'application {app} …",
"aborting": "Annulation.",
"app_not_upgraded": "Lapplication {failed_app} na pas été mise à jour et par conséquence les applications suivantes nont pas été mises à jour : {apps}",
"app_start_install": "Installation de lapplication {app} …",
"app_start_remove": "Suppression de lapplication {app} …",
"app_start_backup": "Collecte des fichiers devant être sauvegardés pour lapplication {app} …",
"app_start_restore": "Restauration de lapplication {app} …",
"app_upgrade_several_apps": "Les applications suivantes seront mises à jour : {apps}",
"ask_new_domain": "Nouveau domaine",
"ask_new_path": "Nouveau chemin",
"backup_actually_backuping": "Création d'une archive de sauvegarde à partir des fichiers collectés …",
"backup_mount_archive_for_restore": "Préparation de l'archive pour restauration …",
"confirm_app_install_warning": "Avertissement : cette application peut fonctionner mais n'est pas bien intégrée dans YunoHost. Certaines fonctionnalités telles que l'authentification unique et la sauvegarde/restauration peuvent ne pas être disponibles. L'installer quand même ? [{answers:s}] ",
"confirm_app_install_danger": "AVERTISSEMENT ! Cette application est encore expérimentale (explicitement, elle ne fonctionne pas) et risque de casser votre système ! Vous ne devriez probablement PAS l'installer sans savoir ce que vous faites. Êtes-vous prêt à prendre ce risque ? [{answers:s}] ",
"confirm_app_install_thirdparty": "AVERTISSEMENT ! L'installation d'applications tierces peut compromettre l'intégrité et la sécurité de votre système. Vous ne devriez probablement PAS l'installer si vous ne savez pas ce que vous faites. Êtes-vous prêt à prendre ce risque ? [{answers:s}] ",
"backup_actually_backuping": "Création dune archive de sauvegarde à partir des fichiers collectés …",
"backup_mount_archive_for_restore": "Préparation de larchive pour restauration …",
"confirm_app_install_warning": "Avertissement : cette application peut fonctionner mais nest pas bien intégrée dans YunoHost. Certaines fonctionnalités telles que lauthentification unique et la sauvegarde/restauration peuvent ne pas être disponibles. Linstaller quand même ? [{answers:s}] ",
"confirm_app_install_danger": "DANGER ! Cette application est connue pour être encore expérimentale (si elle ne fonctionne pas explicitement) ! Vous ne devriez probablement PAS linstaller à moins de savoir ce que vous faites. AUCUN SUPPORT ne sera fourni si cette application ne fonctionne pas ou casse votre système … Si vous êtes prêt à prendre ce risque de toute façon, tapez '{answers:s}'",
"confirm_app_install_thirdparty": "DANGER ! Cette application ne fait pas partie du catalogue dapplications de YunoHost. Linstallation dapplications tierces peut compromettre lintégrité et la sécurité de votre système. Vous ne devriez probablement PAS linstaller à moins de savoir ce que vous faites. AUCUN SUPPORT ne sera fourni si cette application ne fonctionne pas ou casse votre système … Si vous êtes prêt à prendre ce risque de toute façon, tapez '{answers:s}'",
"dpkg_is_broken": "Vous ne pouvez pas faire ça maintenant car dpkg/apt (le gestionnaire de paquets du système) semble avoir laissé des choses non configurées. Vous pouvez essayer de résoudre ce problème en vous connectant via SSH et en exécutant `sudo dpkg --configure -a'.",
"dyndns_could_not_check_available": "Impossible de vérifier si {domain:s} est disponible chez {provider:s}.",
"file_does_not_exist": "Le fichier dont le chemin est {path:s} n'existe pas.",
"file_does_not_exist": "Le fichier dont le chemin est {path:s} nexiste pas.",
"global_settings_setting_security_password_admin_strength": "Qualité du mot de passe administrateur",
"global_settings_setting_security_password_user_strength": "Qualité du mot de passe de l'utilisateur",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Autoriser l'utilisation de la clé hôte DSA (obsolète) pour la configuration du service SSH",
"global_settings_setting_security_password_user_strength": "Qualité du mot de passe de lutilisateur",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Autoriser lutilisation de la clé hôte DSA (obsolète) pour la configuration du service SSH",
"hook_json_return_error": "Échec de la lecture au retour du script {path:s}. Erreur : {msg:s}. Contenu brut : {raw_content}",
"migration_description_0007_ssh_conf_managed_by_yunohost_step1": "La configuration SSH sera gérée par YunoHost (étape 1, automatique)",
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "La configuration SSH sera gérée par YunoHost (étape 2, manuelle)",
"migration_0007_cancelled": "YunoHost n'a pas réussi à améliorer la façon dont est gérée votre configuration SSH.",
"migration_0007_cannot_restart": "SSH ne peut pas être redémarré après avoir essayé d'annuler la migration numéro 6.",
"migration_0007_cancelled": "Impossible daméliorer la gestion de votre configuration SSH.",
"migration_0007_cannot_restart": "SSH ne peut pas être redémarré après avoir essayé dannuler la migration numéro 6.",
"migration_0008_general_disclaimer": "Pour améliorer la sécurité de votre serveur, il est recommandé de laisser YunoHost gérer la configuration SSH. Votre configuration SSH actuelle diffère de la configuration recommandée. Si vous laissez YunoHost la reconfigurer, la façon dont vous vous connectez à votre serveur via SSH changera comme suit :",
"migration_0008_port": " - vous devrez vous connecter en utilisant le port 22 au lieu de votre actuel port SSH personnalisé. N'hésitez pas à le reconfigurer ;",
"migration_0008_root": " - vous ne pourrez pas vous connecter en tant que root via SSH. Au lieu de cela, vous devrez utiliser l'utilisateur admin ;",
"migration_0008_dsa": " - la clé DSA sera désactivée. Par conséquent, il se peut que vous ayez besoin d'invalider un avertissement effrayant de votre client SSH afin de revérifier l'empreinte de votre serveur ;",
"migration_0008_warning": "Si vous comprenez ces avertissements et que vous acceptez de laisser YunoHost remplacer votre configuration actuelle, exécutez la migration. Sinon, vous pouvez également passer la migration, bien que cela ne soit pas recommandé.",
"migration_0008_no_warning": "Aucun risque majeur n'a été identifié concernant l'écrasement de votre configuration SSH - mais nous ne pouvons pas en être absolument sûrs ;) ! Si vous acceptez de laisser YunoHost remplacer votre configuration actuelle, exécutez la migration. Sinon, vous pouvez également passer la migration, bien que cela ne soit pas recommandé.",
"migration_0008_port": "- Vous devrez vous connecter en utilisant le port 22 au lieu de votre actuel port SSH personnalisé. Nhésitez pas à le reconfigurer ;",
"migration_0008_root": "- Vous ne pourrez pas vous connecter en tant que root via SSH. Au lieu de cela, vous devrez utiliser lutilisateur admin ;",
"migration_0008_dsa": "- La clé DSA sera désactivée. Par conséquent, il se peut que vous ayez besoin dinvalider un avertissement effrayant de votre client SSH afin de revérifier lempreinte de votre serveur ;",
"migration_0008_warning": "Si vous comprenez ces avertissements et souhaitez que YunoHost écrase votre configuration actuelle, exécutez la migration. Sinon, vous pouvez également ignorer la migration, bien que cela ne soit pas recommandé.",
"migration_0008_no_warning": "Remplacer votre configuration SSH devrait être sûr, bien que cela ne puisse être promis ! Exécutez la migration pour la remplacer. Sinon, vous pouvez également ignorer la migration, bien que cela ne soit pas recommandé.",
"migrations_success": "Migration {number} {name} réussie !",
"pattern_password_app": "Désolé, les mots de passe ne doivent pas contenir les caractères suivants : {forbidden_chars}",
"pattern_password_app": "Désolé, les mots de passe ne peuvent pas contenir les caractères suivants : {forbidden_chars}",
"root_password_replaced_by_admin_password": "Votre mot de passe root a été remplacé par votre mot de passe administrateur.",
"service_conf_now_managed_by_yunohost": "Le fichier de configuration '{conf}' est maintenant géré par YunoHost.",
"service_reload_failed": "Impossible de recharger le service '{service:s}'.\n\nJournaux historisés récents de ce service : {logs:s}",
"service_reloaded": "Le service '{service:s}' a été rechargé",
"service_reloaded": "Le service « {service:s} » a été rechargé",
"service_restart_failed": "Impossible de redémarrer le service '{service:s}'\n\nJournaux historisés récents de ce service : {logs:s}",
"service_restarted": "Le service '{service:s}' a été redémarré",
"service_restarted": "Le service « {service:s} » a été redémarré",
"service_reload_or_restart_failed": "Impossible de recharger ou de redémarrer le service '{service:s}'\n\nJournaux historisés récents de ce service : {logs:s}",
"service_reloaded_or_restarted": "Le service '{service:s}' a été rechargé ou redémarré",
"service_reloaded_or_restarted": "Le service « {service:s} » a été rechargé ou redémarré",
"this_action_broke_dpkg": "Cette action a laissé des paquets non configurés par dpkg/apt (les gestionnaires de paquets système). Vous pouvez essayer de résoudre ce problème en vous connectant via SSH et en exécutant `sudo dpkg --configure -a`.",
"app_action_cannot_be_ran_because_required_services_down": "Cette application requiert certains services qui sont actuellement arrêtés. Avant de continuer, vous devriez essayer de redémarrer les services suivants (et éventuellement rechercher pourquoi ils sont arrêtés) : {services}",
"admin_password_too_long": "Choisissez un mot de passe plus court que 127 caractères",
"app_action_cannot_be_ran_because_required_services_down": "Ces services requis doivent être en cours dexécution pour exécuter cette action: {services}. Essayez de les redémarrer pour continuer (et éventuellement rechercher pourquoi ils sont en panne).",
"admin_password_too_long": "Veuillez choisir un mot de passe de moins de 127 caractères",
"log_regen_conf": "Régénérer les configurations du système '{}'",
"migration_0009_not_needed": "Cette migration semble avoir déjà été jouée ? On l'ignore.",
"migration_0009_not_needed": "Cette migration semble avoir déjà été jouée ? On lignore.",
"regenconf_file_backed_up": "Le fichier de configuration '{conf}' a été sauvegardé sous '{backup}'",
"regenconf_file_copy_failed": "Impossible de copier le nouveau fichier de configuration '{new}' vers '{conf}'",
"regenconf_file_manually_modified": "Le fichier de configuration '{conf}' a été modifié manuellement et ne sera pas mis à jour",
@ -536,57 +404,209 @@
"regenconf_file_updated": "Le fichier de configuration '{conf}' a été mis à jour",
"regenconf_now_managed_by_yunohost": "Le fichier de configuration '{conf}' est maintenant géré par YunoHost (catégorie {category}).",
"regenconf_up_to_date": "La configuration est déjà à jour pour la catégorie '{category}'",
"already_up_to_date": "Il n'y a rien à faire ! Tout est déjà à jour !",
"global_settings_setting_security_nginx_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur web nginx. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
"global_settings_setting_security_ssh_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur SSH. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
"global_settings_setting_security_postfix_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur Postfix. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
"already_up_to_date": "Il ny a rien à faire ! Tout est déjà à jour !",
"global_settings_setting_security_nginx_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur web nginx. Affecte les cryptogrammes (et dautres aspects liés à la sécurité)",
"global_settings_setting_security_ssh_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur SSH. Affecte les cryptogrammes (et dautres aspects liés à la sécurité)",
"global_settings_setting_security_postfix_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur Postfix. Affecte les cryptogrammes (et dautres aspects liés à la sécurité)",
"migration_description_0009_decouple_regenconf_from_services": "Dissocier le mécanisme « regen-conf » des services",
"migration_description_0010_migrate_to_apps_json": "Supprimer les listes d'applications obsolètes et utiliser la nouvelle liste unifiée 'apps.json' à la place",
"migration_description_0010_migrate_to_apps_json": "Supprimer les catalogues dapplications obsolètes afin dutiliser la nouvelle liste unifiée 'apps.json' à la place (les anciens catalogues seront remplacés durant la migration 13)",
"regenconf_file_kept_back": "Le fichier de configuration '{conf}' devait être supprimé par « regen-conf » (catégorie {category}) mais a été conservé.",
"regenconf_updated": "La configuration a été mise à jour pour la catégorie '{category}'",
"regenconf_updated": "La configuration a été mise à jour pour '{category}'",
"regenconf_would_be_updated": "La configuration aurait dû être mise à jour pour la catégorie '{category}'",
"regenconf_dry_pending_applying": "Vérification de la configuration en attente qui aurait été appliquée pour la catégorie '{category}' …",
"regenconf_failed": "Impossible de régénérer la configuration pour la ou les catégorie(s) : '{categories}'",
"regenconf_pending_applying": "Applique la configuration en attente pour la catégorie '{category}' …",
"service_regen_conf_is_deprecated": "'yunohost service regen-conf' est obsolète ! Veuillez plutôt utiliser 'yunohost tools regen-conf' à la place.",
"tools_upgrade_at_least_one": "Veuillez spécifier --apps OU --system",
"tools_upgrade_at_least_one": "Veuillez spécifier '--apps' OU '--system'",
"tools_upgrade_cant_both": "Impossible de mettre à niveau le système et les applications en même temps",
"tools_upgrade_cant_hold_critical_packages": "Impossibilité de maintenir les paquets critiques...",
"tools_upgrade_regular_packages": "Mise à jour des paquets du système (non liés a YunoHost) ...",
"tools_upgrade_cant_hold_critical_packages": "Impossibilité de maintenir les paquets critiques",
"tools_upgrade_regular_packages": "Mise à jour des paquets du système (non liés a YunoHost) ",
"tools_upgrade_regular_packages_failed": "Impossible de mettre à jour les paquets suivants : {packages_list}",
"tools_upgrade_special_packages": "Mise à jour des paquets 'spécifiques' (liés a YunoHost) ...",
"tools_upgrade_special_packages_completed": "La mise à jour des paquets de YunoHost est finie!\nPressez [Entrée] pour revenir à la ligne de commande",
"updating_app_lists": "Récupération des mises à jour des applications disponibles…",
"dpkg_lock_not_available": "Cette commande ne peut être lancée maintenant car il semblerai qu'un autre programme utilise déjà le verrou dpkg du gestionnaire de paquets du système",
"tools_upgrade_cant_unhold_critical_packages": "Impossible de dé-marquer les paquets critiques ...",
"tools_upgrade_special_packages_explanation": "Cette opération prendra fin mais la mise à jour spécifique continuera en arrière-plan. Veuillez ne pas lancer d'autre action sur votre serveur dans les 10 prochaines minutes (en fonction de la vitesse de votre matériel). Une fois que c'est fait, vous devrez peut-être vous reconnecter sur le panel d'administration web. Le journal de la mise à jour sera disponible dans Outils > Log (dans le panel d'administration web) ou dans la liste des journaux YunoHost (en ligne de commande).",
"tools_upgrade_special_packages": "Mise à jour des paquets 'spécifiques' (liés a YunoHost) …",
"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 être exécutée actuellement car un autre programme semble utiliser le verrou de dpkg (gestionnaire de paquets)",
"tools_upgrade_cant_unhold_critical_packages": "Impossible de conserver les paquets critiques…",
"tools_upgrade_special_packages_explanation": "La mise à jour spéciale va continuer en arrière-plan. Veuillez ne pas lancer dautres actions sur votre serveur pendant environ 10 minutes (en fonction de la vitesse du matériel). Après cela, il vous faudra peut-être vous reconnecter à la webadmin. Le journal de mise à niveau sera disponible dans Outils → Journal (dans la webadmin) ou via \"yunohost log list\" (en 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}",
"apps_permission_not_found": "Aucune permission trouvée pour les applications installées",
"apps_permission_restoration_failed": "L'autorisation '{permission:s}' pour la restauration de l'application {app:s} a échoué",
"backup_permission": "Autorisation de sauvegarde pour l'application {app:s}",
"edit_group_not_allowed": "Vous n'êtes pas autorisé à modifier le groupe {group:s}",
"error_when_removing_sftpuser_group": "Erreur en essayant de supprimer le groupe sftpusers",
"group_created": "Le groupe '{group}' a créé avec succès",
"group_deleted": "Le groupe '{group}' a été supprimé",
"group_deletion_not_allowed": "Le groupe {group:s} ne peut pas être supprimé manuellement.",
"group_info_failed": "L'information sur le groupe a échoué",
"backup_permission": "Permission de sauvegarde pour lapplication {app:s}",
"group_created": "Le groupe '{group}' a été créé",
"group_deleted": "Suppression du groupe '{group}'",
"group_unknown": "Le groupe {group:s} est inconnu",
"group_updated": "Le groupe '{group}' a été mis à jour",
"group_update_failed": "La mise à jour du groupe '{group}' a échoué",
"group_already_allowed": "Le groupe '{group:s}' a déjà la permission '{permission:s}' activée pour l'application '{app:s}'",
"group_already_disallowed": "Le groupe '{group:s}' a déjà la permission '{permission:s}' désactivée pour l'application '{app:s}'",
"group_name_already_exist": "Le groupe {name:s} existe déjà",
"group_creation_failed": "Échec de la création du groupe '{group}'",
"group_deletion_failed": "Échec de la suppression du groupe '{group}'",
"edit_permission_with_group_all_users_not_allowed": "Vous n'êtes pas autorisé à modifier les permissions pour le groupe 'all_users', utilisez 'yunohost user permission clear APP' ou 'yunohost user permission add APP -u USER' à la place.",
"log_permission_add": "Ajouter l'autorisation '{}' pour l'application '{}'",
"log_permission_remove": "Supprimer l'autorisation '{}'",
"log_permission_update": "Mise à jour de l'autorisation '{}' pour l'application '{}'",
"log_user_group_add": "Ajouter '{}' au groupe",
"group_update_failed": "La mise à jour du groupe '{group}' a échoué : {error}",
"group_creation_failed": "Échec de la création du groupe '{group}': {error}",
"group_deletion_failed": "Échec de la suppression du groupe '{group}': {error}",
"log_user_group_delete": "Supprimer le groupe '{}'",
"log_user_group_update": "Mettre à jour '{}' pour le groupe",
"log_user_permission_add": "Mettre à jour l'autorisation pour '{}'",
"log_user_permission_remove": "Mettre à jour l'autorisation pour '{}'",
"mailbox_disabled": "La boîte aux lettres est désactivée pour l'utilisateur {user:s}"
"mailbox_disabled": "La boîte aux lettres est désactivée pour lutilisateur {user:s}",
"app_action_broke_system": "Cette action semble avoir cassé des services importants : {services}",
"apps_already_up_to_date": "Toutes les applications sont déjà à jour",
"migration_0011_create_group": "Création dun groupe pour chaque utilisateur…",
"migration_0011_done": "Migration terminée. Vous êtes maintenant en mesure de gérer des groupes dutilisateurs.",
"migrations_must_provide_explicit_targets": "Vous devez fournir des cibles explicites lorsque vous utilisez '--skip' ou '--force-rerun'",
"migrations_no_such_migration": "Il ny a pas de migration appelée '{id}'",
"migrations_pending_cant_rerun": "Ces migrations étant toujours en attente, vous ne pouvez pas les exécuter à nouveau : {ids}",
"migration_description_0012_postgresql_password_to_md5_authentication": "Forcer lauthentification PostgreSQL à utiliser MD5 pour les connexions locales",
"migrations_exclusive_options": "'auto', '--skip' et '--force-rerun' sont des options mutuellement exclusives.",
"migrations_not_pending_cant_skip": "Ces migrations ne sont pas en attente et ne peuvent donc pas être ignorées: {ids}",
"migration_0011_can_not_backup_before_migration": "La sauvegarde du système na pas pu être terminée avant léchec de la migration. Erreur: {error:s}",
"migration_0011_migrate_permission": "Migration des autorisations des paramètres des applications vers LDAP …",
"migration_0011_migration_failed_trying_to_rollback": "La migration a échoué… Tentative de restauration du système.",
"migration_0011_rollback_success": "Système restauré.",
"migration_0011_update_LDAP_database": "Mise à jour de la base de données LDAP…",
"migration_0011_backup_before_migration": "Création dune sauvegarde des paramètres de la base de données LDAP et des applications avant la migration.",
"permission_not_found": "Autorisation '{permission:s}' introuvable",
"permission_update_failed": "Impossible de mettre à jour la permission '{permission}' : {error}",
"permission_updated": "Permission '{permission:s}' mise à jour",
"permission_update_nothing_to_do": "Aucune autorisation pour mettre à jour",
"dyndns_provider_unreachable": "Impossible datteindre le fournisseur DynDNS {provider}: votre YunoHost nest pas correctement connecté à Internet ou le serveur Dynette est en panne.",
"migration_0011_update_LDAP_schema": "Mise à jour du schéma LDAP …",
"migrations_already_ran": "Ces migrations sont déjà effectuées : {ids}",
"migrations_dependencies_not_satisfied": "Exécutez ces migrations : '{dependencies_id}', avant migration {id}.",
"migrations_failed_to_load_migration": "Impossible de charger la migration {id}: {error}",
"migrations_running_forward": "Exécution de la migration {id} …",
"migrations_success_forward": "Migration {id} terminée",
"operation_interrupted": "Lopération a été interrompue manuellement ?",
"permission_already_exist": "Lautorisation '{permission}' existe déjà",
"permission_created": "Permission '{permission:s}' créée",
"permission_creation_failed": "Impossible de créer lautorisation '{permission}' : {error}",
"permission_deleted": "Permission '{permission:s}' supprimée",
"permission_deletion_failed": "Impossible de supprimer la permission '{permission}' : {error}",
"migration_description_0011_setup_group_permission": "Initialiser les groupes dutilisateurs et autorisations pour les applications et les services",
"migration_0011_LDAP_update_failed": "Impossible de mettre à jour LDAP. Erreur: {error:s}",
"group_already_exist": "Le groupe {group} existe déjà",
"group_already_exist_on_system": "Le groupe {group} existe déjà dans les groupes système",
"group_cannot_be_deleted": "Le groupe {group} ne peut pas être supprimé manuellement.",
"group_user_already_in_group": "Lutilisateur {user} est déjà dans le groupe {group}",
"group_user_not_in_group": "Lutilisateur {user} nest pas dans le groupe {group}",
"log_permission_create": "Créer permission '{}'",
"log_permission_delete": "Supprimer permission '{}'",
"log_user_group_create": "Créer '{}' groupe",
"log_user_permission_update": "Mise à jour des accès pour la permission '{}'",
"log_user_permission_reset": "Réinitialiser la permission '{}'",
"migration_0011_failed_to_remove_stale_object": "Impossible de supprimer un objet périmé {dn}: {error}",
"permission_already_allowed": "Le groupe '{group}' a déjà l'autorisation '{permission}' activée",
"permission_already_disallowed": "Le groupe '{group}' a déjà l'autorisation '{permission}' désactivé",
"permission_cannot_remove_main": "Supprimer une autorisation principale n'est pas autorisé",
"user_already_exists": "L'utilisateur '{user}' existe déjà",
"app_full_domain_unavailable": "Désolé, cette application doit être installée sur un domaine qui lui est propre, mais d'autres applications sont déjà installées sur le domaine '{domain}'. Vous pouvez utiliser un sous-domaine dédié à cette application à la place.",
"group_cannot_edit_all_users": "Le groupe 'all_users' ne peut pas être édité manuellement. C'est un groupe spécial destiné à contenir tous les utilisateurs enregistrés dans YunoHost",
"group_cannot_edit_visitors": "Le groupe 'visiteurs' ne peut pas être édité manuellement. C'est un groupe spécial représentant les visiteurs anonymes",
"group_cannot_edit_primary_group": "Le groupe '{group}' ne peut pas être édité manuellement. C'est le groupe principal destiné à ne contenir qu'un utilisateur spécifique.",
"log_permission_url": "Mise à jour de l'URL associée à l'autorisation '{}'",
"migration_0011_slapd_config_will_be_overwritten": "Il semble que vous ayez modifié manuellement la configuration de slapd. Pour cette migration critique, YunoHost doit forcer la mise à jour de la configuration de slapd. Les fichiers originaux seront sauvegardés dans {conf_backup_folder}.",
"permission_already_up_to_date": "Lautorisation na pas été mise à jour car les demandes dajout/suppression correspondent déjà à létat actuel.",
"permission_currently_allowed_for_all_users": "Cette autorisation est actuellement accordée à tous les utilisateurs en plus des autres groupes. Vous voudrez probablement soit supprimer lautorisation 'all_users', soit supprimer les autres groupes auxquels il est actuellement autorisé.",
"app_install_failed": "Impossible dinstaller {app}: {error}",
"app_install_script_failed": "Une erreur est survenue dans le script dinstallation de lapplication",
"permission_require_account": "Permission {permission} na de sens que pour les utilisateurs ayant un compte et ne peut donc pas être activé pour les visiteurs.",
"app_remove_after_failed_install": "Supprimer lapplication après léchec de linstallation …",
"diagnosis_display_tip_web": "Vous pouvez aller à la section Diagnostic (dans lécran daccueil) pour voir les problèmes rencontrés.",
"diagnosis_cant_run_because_of_dep": "Impossible dexécuter le diagnostic pour {category} alors quil existe des problèmes importants liés à {dep}.",
"diagnosis_found_errors": "Trouvé {errors} problème(s) significatif(s) lié(s) à {category} !",
"diagnosis_found_errors_and_warnings": "Trouvé {errors} problème(s) significatif(s) (et {warnings} (avertissement(s)) en relation avec {category} !",
"diagnosis_ip_not_connected_at_all": "Le serveur ne semble pas du tout connecté à Internet !?",
"diagnosis_ip_weird_resolvconf": "La résolution DNS semble fonctionner, mais soyez prudent en utilisant un fichier /etc/resolv.conf personnalisé.",
"diagnosis_ip_weird_resolvconf_details": "Au lieu de cela, ce fichier devrait être un lien symbolique vers /etc/resolvconf/run/resolv.conf lui-même pointant vers 127.0.0.1 (dnsmasq). Les résolveurs réels doivent être configurés dans /etc/resolv.dnsmasq.conf.",
"diagnosis_dns_missing_record": "Selon la configuration DNS recommandée, vous devez ajouter un enregistrement DNS\nType: {type}\nNom: {name}\nValeur {value}",
"diagnosis_diskusage_ok": "Le stockage {mountpoint} (sur le périphérique {device}) a encore {free} ({free_percent}%) despace libre !",
"diagnosis_ram_ok": "Le système dispose encore de {available} ({available_percent}%) de RAM sur {total}.",
"diagnosis_regenconf_allgood": "Tous les fichiers de configuration sont conformes à la configuration recommandée !",
"diagnosis_security_vulnerable_to_meltdown": "Vous semblez vulnérable à la vulnérabilité de sécurité critique de Meltdown",
"diagnosis_basesystem_host": "Le serveur utilise Debian {debian_version}",
"diagnosis_basesystem_kernel": "Le serveur utilise le noyau Linux {kernel_version}",
"diagnosis_basesystem_ynh_single_version": "{package} version: {version} ({repo})",
"diagnosis_basesystem_ynh_main_version": "Le serveur utilise YunoHost {main_version} ({repo})",
"diagnosis_basesystem_ynh_inconsistent_versions": "Vous exécutez des versions incohérentes des packages YunoHost … probablement à cause dune mise à niveau partielle ou échouée.",
"diagnosis_display_tip_cli": "Vous pouvez exécuter 'yunohost diagnosis show --issues' pour afficher les problèmes détectés.",
"diagnosis_failed_for_category": "Échec du diagnostic pour la catégorie '{category}': {error}",
"diagnosis_cache_still_valid": "(Le cache est encore valide pour le diagnostic {category}. Il ne sera pas re-diagnostiqué pour le moment!)",
"diagnosis_ignored_issues": "(+ {nb_ignored} questions ignorée(s))",
"diagnosis_found_warnings": "Trouvé {warnings} objet(s) pouvant être amélioré(s) pour {category}.",
"diagnosis_everything_ok": "Tout semble bien pour {category} !",
"diagnosis_failed": "Impossible dextraire le résultat du diagnostic pour la catégorie '{category}': {error}",
"diagnosis_ip_connected_ipv4": "Le serveur est connecté à Internet en IPv4 !",
"diagnosis_ip_no_ipv4": "Le serveur ne dispose pas dune adresse IPv4.",
"diagnosis_ip_connected_ipv6": "Le serveur est connecté à Internet en IPv6 !",
"diagnosis_ip_no_ipv6": "Le serveur ne dispose pas dune adresse IPv6.",
"diagnosis_ip_dnsresolution_working": "La résolution de nom de domaine fonctionne !",
"diagnosis_ip_broken_dnsresolution": "La résolution du nom de domaine semble interrompue pour une raison quelconque … Un pare-feu bloque-t-il les requêtes DNS ?",
"diagnosis_ip_broken_resolvconf": "La résolution du nom de domaine semble cassée sur votre serveur, ce qui semble lié au fait que /etc/resolv.conf ne pointe pas vers 127.0.0.1.",
"diagnosis_dns_good_conf": "Bonne configuration DNS pour le domaine {domain} (catégorie {category})",
"diagnosis_dns_bad_conf": "Configuration DNS incorrecte ou manquante pour le domaine {domain} (catégorie {category})",
"diagnosis_dns_discrepancy": "Lenregistrement DNS de type {0} et nom {1} ne correspond pas à la configuration recommandée. Valeur actuelle: {2}. Valeur exceptée: {3}. Vous pouvez consulter https://yunohost.org/dns_config pour plus dinformations.",
"diagnosis_services_bad_status": "Le service {service} est {status} :-(",
"diagnosis_diskusage_verylow": "Le stockage {mountpoint} (sur le périphérique {device}) ne dispose que de {free_abs_GB} Go ({free_percent}%). Vous devriez vraiment envisager de nettoyer un peu despace.",
"diagnosis_diskusage_low": "Le stockage {mountpoint} (sur le périphérique {device}) ne dispose que de {free_abs_GB} Go ({free_percent}%). Faites attention.",
"diagnosis_ram_verylow": "Le système ne dispose plus que de {available_abs_MB} MB ({available_percent}%) ! (sur {total_abs_MB} Mo)",
"diagnosis_ram_low": "Le système na plus de {available_abs_MB} MB ({available_percent}%) RAM sur {total_abs_MB} MB. Faites attention.",
"diagnosis_swap_none": "Le système na aucun échange. Vous devez envisager dajouter au moins 256 Mo de swap pour éviter les situations où le système manque de mémoire.",
"diagnosis_swap_notsomuch": "Le système ne dispose que de {total_MB} Mo de swap. Vous devez envisager davoir au moins 256 Mo pour éviter les situations où le système manque de mémoire.",
"diagnosis_swap_ok": "Le système dispose de {total_MB} Mo de swap !",
"diagnosis_dns_discrepancy": "Lenregistrement DNS de type {type} et nom {name} ne correspond pas à la configuration recommandée.\nValeur actuelle: {current}\nValeur attendue: {value}",
"diagnosis_services_bad_status": "Le service {service} est {status} :-(",
"diagnosis_diskusage_verylow": "Le stockage {mountpoint} (sur le périphérique {device}) ne dispose que de {free} ({free_percent}%). Vous devriez vraiment envisager de nettoyer un peu despace.",
"diagnosis_diskusage_low": "Le stockage {mountpoint} (sur le périphérique {device}) ne dispose que de {free} ({free_percent}%). Faites attention.",
"diagnosis_ram_verylow": "Le système ne dispose plus que de {available} ({available_percent}%)! (sur {total})",
"diagnosis_ram_low": "Le système na plus de {available} ({available_percent}%) RAM sur {total}. Faites attention.",
"diagnosis_swap_none": "Le système na aucun espace de swap. Vous devriez envisager dajouter au moins {recommended} de swap pour éviter les situations où le système manque de mémoire.",
"diagnosis_swap_notsomuch": "Le système ne dispose que de {total} de swap. Vous devez envisager davoir au moins {recommended} pour éviter les situations où le système manque de mémoire.",
"diagnosis_swap_ok": "Le système dispose de {total} de swap !",
"diagnosis_regenconf_manually_modified": "Le fichier de configuration {file} a été modifié manuellement.",
"diagnosis_regenconf_manually_modified_debian": "Le fichier de configuration {file} a été modifié manuellement par rapport à celui par défaut de Debian.",
"diagnosis_regenconf_manually_modified_details": "Cest probablement OK tant que vous savez ce que vous faites ;) !",
"diagnosis_regenconf_manually_modified_debian_details": "Cela peut probablement être OK, mais il faut garder un œil dessus …",
"diagnosis_security_all_good": "Aucune vulnérabilité de sécurité critique na été trouvée.",
"apps_catalog_init_success": "Système de catalogue dapplications initialisé !",
"apps_catalog_failed_to_download": "Impossible de télécharger le catalogue des applications {apps_catalog}:{error}",
"diagnosis_mail_outgoing_port_25_blocked": "Le port sortant 25 semble être bloqué. Vous devriez essayer de le débloquer dans le panneau de configuration de votre fournisseur de services Internet (ou hébergeur). En attendant, le serveur ne pourra pas envoyer de courrier électronique à dautres serveurs.",
"domain_cannot_remove_main_add_new_one": "Vous ne pouvez pas supprimer '{domain:s}' car il sagit du domaine principal et de votre seul domaine. Vous devez dabord ajouter un autre domaine à laide de 'yunohost domain add <another-domain.com>', puis définir comme domaine principal à laide de 'yunohost domain main-domain -n <nom-dun-autre-domaine.com>' et vous pouvez ensuite supprimer le domaine '{domain:s}' à laide de 'yunohost domain remove {domain:s}'.",
"diagnosis_security_vulnerable_to_meltdown_details": "Pour résoudre ce problème, vous devez mettre à niveau votre système et redémarrer pour charger le nouveau noyau Linux (ou contacter votre fournisseur de serveur si cela ne fonctionne pas). Voir https://meltdownattack.com/ pour plus dinformations.",
"diagnosis_description_basesystem": "Système de base",
"diagnosis_description_ip": "Connectivité Internet",
"diagnosis_description_dnsrecords": "Enregistrements DNS",
"diagnosis_description_services": "État des services",
"diagnosis_description_systemresources": "Ressources système",
"diagnosis_description_ports": "Exposition des ports",
"diagnosis_description_regenconf": "Configurations système",
"diagnosis_description_security": "Contrôles de sécurité",
"diagnosis_ports_could_not_diagnose": "Impossible de diagnostiquer si les ports sont accessibles de l'extérieur.",
"diagnosis_ports_could_not_diagnose_details": "Erreur: {error}",
"apps_catalog_updating": "Mise à jour du catalogue d'applications…",
"apps_catalog_obsolete_cache": "Le cache du catalogue d'applications est vide ou obsolète.",
"apps_catalog_update_success": "Le catalogue des applications a été mis à jour !",
"diagnosis_mail_ougoing_port_25_ok": "Le port sortant 25 nest pas bloqué et le courrier électronique peut être envoyé à dautres serveurs.",
"diagnosis_description_mail": "Email",
"diagnosis_ports_unreachable": "Le port {port} nest pas accessible de lextérieur.",
"diagnosis_ports_ok": "Le port {port} est accessible de lextérieur.",
"diagnosis_http_could_not_diagnose": "Impossible de diagnostiquer si le domaine est accessible de lextérieur.",
"diagnosis_http_could_not_diagnose_details": "Erreur: {error}",
"diagnosis_http_ok": "Le domaine {domain} est accessible en HTTP depuis lextérieur.",
"diagnosis_http_unreachable": "Le domaine {domain} est inaccessible en HTTP depuis lextérieur.",
"diagnosis_unknown_categories": "Les catégories suivantes sont inconnues: {categories}",
"migration_description_0013_futureproof_apps_catalog_system": "Migrer vers le nouveau système de catalogue dapplications à lépreuve du temps",
"app_upgrade_script_failed": "Une erreur sest produite durant lexécution du script de mise à niveau de lapplication",
"migration_description_0014_remove_app_status_json": "Supprimer les anciens fichiers dapplication status.json",
"diagnosis_services_running": "Le service {service} est en cours de fonctionnement !",
"diagnosis_services_conf_broken": "La configuration est cassée pour le service {service} !",
"diagnosis_ports_needed_by": "Rendre ce port accessible est nécessaire pour les fonctionnalités de type {category} (service {service})",
"diagnosis_ports_forwarding_tip": "Pour résoudre ce problème, vous devez probablement configurer la redirection de port sur votre routeur Internet comme décrit sur https://yunohost.org/isp_box_config",
"diagnosis_http_connection_error": "Erreur de connexion : impossible de se connecter au domaine demandé, il est probablement injoignable.",
"diagnosis_no_cache": "Pas encore de cache de diagnostique pour la catégorie « {category} »",
"yunohost_postinstall_end_tip": "La post-installation terminée! Pour finaliser votre configuration, il est recommendé de :\n - ajouter un premier utilisateur depuis la section \"Utilisateurs\" de linterface web (ou \"yunohost user create <nom dutilisateur>\" en ligne de commande);\n - diagnostiquer les potentiels problèmes dans la section \"Diagnostic\" de l'interface web (ou \"yunohost diagnosis run\" en ligne de commande);\n - lire les parties \"Finalisation de votre configuration\" et \"Découverte de Yunohost\" dans le guide de ladministrateur: https://yunohost.org/admindoc.",
"diagnosis_services_bad_status_tip": "Vous pouvez essayer de redémarrer le service. Si cela ne fonctionne pas, consultez les journaux de service à laide de 'yunohost service log {service}' ou de la section 'Services' dans la webadmin.",
"diagnosis_http_bad_status_code": "Le système de diagnostique na pas réussi à contacter votre serveur. Il se peut quune autre machine réponde à la place de votre serveur. Vérifiez que le port 80 est correctement redirigé, que votre configuration nginx est à jour et quun reverse-proxy ninterfère pas.",
"diagnosis_http_timeout": "Expiration du délai en essayant de contacter votre serveur de lextérieur. Il semble être inaccessible. Vérifiez que vous transférez correctement le port 80, que nginx est en cours dexécution et quun pare-feu ninterfère pas.",
"global_settings_setting_pop3_enabled": "Activer le protocole POP3 pour le serveur de messagerie",
"log_app_action_run": "Lancer laction de lapplication '{}'",
"log_app_config_show_panel": "Montrer le panneau de configuration de lapplication '{}'",
"log_app_config_apply": "Appliquer la configuration à lapplication '{}'",
"diagnosis_never_ran_yet": "Il apparaît que le serveur a été installé récemment et quil ny a pas encore eu de diagnostic. Vous devriez en lancer un depuis le webmin ou en utilisant 'yunohost diagnosis run' depuis la ligne de commande.",
"diagnosis_description_web": "Web",
"diagnosis_basesystem_hardware_board": "Le modèle de carte du serveur est {model}",
"diagnosis_basesystem_hardware": "Larchitecture du serveur est {virt} {arch}",
"group_already_exist_on_system_but_removing_it": "Le groupe {group} est déjà présent dans les groupes du système, mais YunoHost va le supprimer…",
"certmanager_warning_subdomain_dns_record": "Le sous-domaine '{subdomain:s}' ne résout pas vers la même adresse IP que '{domain:s}'. Certaines fonctionnalités seront indisponibles tant que vous naurez pas corrigé cela et regénéré le certificat.",
"domain_cannot_add_xmpp_upload": "Vous ne pouvez pas ajouter de domaine commençant par 'xmpp-upload.'. Ce type de nom est réservé à la fonctionnalité dupload XMPP intégrée dans YunoHost."
}

Some files were not shown because too many files have changed in this diff Show more