diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 9642e92f6..953e2940f 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -13,10 +13,3 @@
## How to test
...
-
-## Validation
-
-- [ ] Principle agreement 0/2 :
-- [ ] Quick review 0/1 :
-- [ ] Simple test 0/1 :
-- [ ] Deep review 0/1 :
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7459ae982..eb34de38e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,132 +1,22 @@
stages:
- - postinstall
+ - build
+ - install
- tests
- lint
+ - doc
-########################################
-# POSTINSTALL
-########################################
+default:
+ tags:
+ - yunohost-ci
+ # All jobs are interruptible by default
+ interruptible: true
-postinstall:
- image: before-postinstall
- stage: postinstall
- script:
- - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns
+variables:
+ YNH_BUILD_DIR: "ynh-build"
-########################################
-# TESTS
-########################################
-
-.test-stage:
- image: after-postinstall
- stage: tests
- 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"
-
-root-tests:
- extends: .test-stage
- script:
- - py.test tests
-
-test-apps:
- extends: .test-stage
- script:
- - cd src/yunohost
- - py.test tests/test_apps.py
-
-test-appscatalog:
- extends: .test-stage
- script:
- - cd src/yunohost
- - py.test tests/test_appscatalog.py
-
-test-appurl:
- extends: .test-stage
- script:
- - cd src/yunohost
- - py.test tests/test_appurl.py
-
-test-backuprestore:
- extends: .test-stage
- script:
- - cd src/yunohost
- - py.test tests/test_backuprestore.py
-
-test-changeurl:
- extends: .test-stage
- script:
- - cd src/yunohost
- - py.test tests/test_changeurl.py
-
-test-permission:
- extends: .test-stage
- script:
- - cd src/yunohost
- - py.test tests/test_permission.py
-
-test-settings:
- extends: .test-stage
- script:
- - cd src/yunohost
- - py.test tests/test_settings.py
-
-test-user-group:
- extends: .test-stage
- script:
- - cd src/yunohost
- - py.test tests/test_user-group.py
-
-test-regenconf:
- extends: .test-stage
- script:
- - cd src/yunohost
- - py.test tests/test_regenconf.py
-
-########################################
-# LINTER
-########################################
-
-.lint-stage:
- image: before-postinstall
- stage: lint
- before_script:
- - apt-get install python-pip -y
- - mkdir -p .pip
- - pip install -U pip
- - hash -d pip
- - pip --cache-dir=.pip install tox
- cache:
- paths:
- - .pip
- - .tox
- key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"
-
-lint:
- extends: .lint-stage
- allow_failure: true
- script:
- - tox -e lint
-
-# Disabled, waiting for buster
-#format-check:
-# extends: .lint-stage
-# script:
-# - black --check --diff
\ No newline at end of file
+include:
+ - local: .gitlab/ci/build.gitlab-ci.yml
+ - local: .gitlab/ci/install.gitlab-ci.yml
+ - local: .gitlab/ci/test.gitlab-ci.yml
+ - local: .gitlab/ci/lint.gitlab-ci.yml
+ - local: .gitlab/ci/doc.gitlab-ci.yml
diff --git a/.gitlab/ci/build.gitlab-ci.yml b/.gitlab/ci/build.gitlab-ci.yml
new file mode 100644
index 000000000..67232ba1f
--- /dev/null
+++ b/.gitlab/ci/build.gitlab-ci.yml
@@ -0,0 +1,52 @@
+.build-stage:
+ stage: build
+ image: "before-install"
+ variables:
+ YNH_SOURCE: "https://github.com/yunohost"
+ before_script:
+ - mkdir -p $YNH_BUILD_DIR
+ artifacts:
+ paths:
+ - $YNH_BUILD_DIR/*.deb
+
+.build_script: &build_script
+ - cd $YNH_BUILD_DIR/$PACKAGE
+ - VERSION=$(dpkg-parsechangelog -S Version 2>/dev/null)
+ - VERSION_NIGHTLY="${VERSION}+$(date +%Y%m%d%H%M)"
+ - dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_NIGHTLY}" -D "unstable" --force-distribution "Daily build."
+ - debuild --no-lintian -us -uc
+
+########################################
+# BUILD DEB
+########################################
+
+build-yunohost:
+ extends: .build-stage
+ variables:
+ PACKAGE: "yunohost"
+ script:
+ - git ls-files | xargs tar -czf archive.tar.gz
+ - mkdir -p $YNH_BUILD_DIR/$PACKAGE
+ - cat archive.tar.gz | tar -xz -C $YNH_BUILD_DIR/$PACKAGE
+ - rm archive.tar.gz
+ - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE
+ - *build_script
+
+
+build-ssowat:
+ extends: .build-stage
+ variables:
+ PACKAGE: "ssowat"
+ script:
+ - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE
+ - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE
+ - *build_script
+
+build-moulinette:
+ extends: .build-stage
+ variables:
+ PACKAGE: "moulinette"
+ script:
+ - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE
+ - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE
+ - *build_script
diff --git a/.gitlab/ci/doc.gitlab-ci.yml b/.gitlab/ci/doc.gitlab-ci.yml
new file mode 100644
index 000000000..b246cc238
--- /dev/null
+++ b/.gitlab/ci/doc.gitlab-ci.yml
@@ -0,0 +1,14 @@
+########################################
+# DOC
+########################################
+
+generate-helpers-doc:
+ stage: doc
+ image: "before-install"
+ needs: []
+ script:
+ - cd doc
+ - python generate_helper_doc.py
+ artifacts:
+ paths:
+ - doc/helpers.html
diff --git a/.gitlab/ci/install.gitlab-ci.yml b/.gitlab/ci/install.gitlab-ci.yml
new file mode 100644
index 000000000..eb5187e11
--- /dev/null
+++ b/.gitlab/ci/install.gitlab-ci.yml
@@ -0,0 +1,37 @@
+.install-stage:
+ stage: install
+ needs:
+ - job: build-yunohost
+ artifacts: true
+ - job: build-ssowat
+ artifacts: true
+ - job: build-moulinette
+ artifacts: true
+
+########################################
+# INSTALL DEB
+########################################
+
+upgrade:
+ extends: .install-stage
+ image: "after-install"
+ script:
+ - apt-get update -o Acquire::Retries=3
+ - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb
+
+
+install-postinstall:
+ extends: .install-stage
+ image: "before-install"
+ script:
+ - apt-get update -o Acquire::Retries=3
+ - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb
+ - systemctl -q stop apt-daily.timer
+ - systemctl -q stop apt-daily-upgrade.timer
+ - systemctl -q stop apt-daily.service
+ - systemctl -q stop apt-daily-upgrade.service
+ - systemctl -q disable apt-daily.timer
+ - systemctl -q disable apt-daily-upgrade.timer
+ - systemctl -q disable apt-daily.service
+ - systemctl -q disable apt-daily-upgrade.service
+ - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns
diff --git a/.gitlab/ci/lint.gitlab-ci.yml b/.gitlab/ci/lint.gitlab-ci.yml
new file mode 100644
index 000000000..c6967d5a5
--- /dev/null
+++ b/.gitlab/ci/lint.gitlab-ci.yml
@@ -0,0 +1,24 @@
+########################################
+# LINTER
+########################################
+
+lint:
+ stage: lint
+ image: "before-install"
+ needs: []
+ allow_failure: true
+ script:
+ - tox -e lint
+
+invalidcode:
+ stage: lint
+ image: "before-install"
+ needs: []
+ script:
+ - tox -e invalidcode
+
+# Disabled, waiting for buster
+#format-check:
+# extends: .lint-stage
+# script:
+# - black --check --diff
diff --git a/.gitlab/ci/test.gitlab-ci.yml b/.gitlab/ci/test.gitlab-ci.yml
new file mode 100644
index 000000000..12379342a
--- /dev/null
+++ b/.gitlab/ci/test.gitlab-ci.yml
@@ -0,0 +1,128 @@
+.install_debs: &install_debs
+ - systemctl -q stop apt-daily.timer
+ - systemctl -q stop apt-daily-upgrade.timer
+ - systemctl -q stop apt-daily.service
+ - systemctl -q stop apt-daily-upgrade.service
+ - systemctl -q disable apt-daily.timer
+ - systemctl -q disable apt-daily-upgrade.timer
+ - systemctl -q disable apt-daily.service
+ - systemctl -q disable apt-daily-upgrade.service
+ - apt-get update -o Acquire::Retries=3
+ - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb
+
+.test-stage:
+ stage: tests
+ image: "after-install"
+ variables:
+ PYTEST_ADDOPTS: "--color=yes"
+ before_script:
+ - *install_debs
+ cache:
+ paths:
+ - src/yunohost/tests/apps
+ key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"
+ needs:
+ - job: build-yunohost
+ artifacts: true
+ - job: build-ssowat
+ artifacts: true
+ - job: build-moulinette
+ artifacts: true
+ - job: upgrade
+
+
+########################################
+# TESTS
+########################################
+
+full-tests:
+ stage: tests
+ image: "before-install"
+ variables:
+ PYTEST_ADDOPTS: "--color=yes"
+ before_script:
+ - *install_debs
+ - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns
+ script:
+ - pytest --cov=yunohost tests/ src/yunohost/tests/ --junitxml=report.xml
+ needs:
+ - job: build-yunohost
+ artifacts: true
+ - job: build-ssowat
+ artifacts: true
+ - job: build-moulinette
+ artifacts: true
+ artifacts:
+ reports:
+ junit: report.xml
+
+root-tests:
+ extends: .test-stage
+ script:
+ - py.test tests
+
+test-apps:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_apps.py
+
+test-appscatalog:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_appscatalog.py
+
+test-appurl:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_appurl.py
+
+test-apps-arguments-parsing:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_apps_arguments_parsing.py
+
+test-backuprestore:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_backuprestore.py
+
+test-changeurl:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_changeurl.py
+
+test-permission:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_permission.py
+
+test-settings:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_settings.py
+
+test-user-group:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_user-group.py
+
+test-regenconf:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_regenconf.py
+
+test-service:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - py.test tests/test_service.py
diff --git a/bin/yunohost b/bin/yunohost
index b640c8c52..546d2d913 100755
--- a/bin/yunohost
+++ b/bin/yunohost
@@ -5,70 +5,28 @@ import os
import sys
import argparse
-# Either we are in a development environment or not
-IN_DEVEL = False
+sys.path.insert(0, "/usr/lib/moulinette/")
+import yunohost
-# Level for which loggers will log
-LOGGERS_LEVEL = 'DEBUG'
-TTY_LOG_LEVEL = 'INFO'
-
-# Handlers that will be used by loggers
-# - file: log to the file LOG_DIR/LOG_FILE
-# - tty: log to current tty
-LOGGERS_HANDLERS = ['file', 'tty']
-
-# Directory and file to be used by logging
-LOG_DIR = '/var/log/yunohost'
-LOG_FILE = 'yunohost-cli.log'
-
-# Check and load - as needed - development environment
-if not __file__.startswith('/usr/'):
- IN_DEVEL = True
-if IN_DEVEL:
- basedir = os.path.abspath('%s/../' % os.path.dirname(__file__))
- if os.path.isdir(os.path.join(basedir, 'moulinette')):
- sys.path.insert(0, basedir)
- LOG_DIR = os.path.join(basedir, 'log')
-
-
-import moulinette
-from moulinette.actionsmap import ActionsMap
-from moulinette.interfaces.cli import colorize, get_locale
-
-
-# Initialization & helpers functions -----------------------------------
-
-def _die(message, title='Error:'):
- """Print error message and exit"""
- print('%s %s' % (colorize(title, 'red'), message))
- sys.exit(1)
def _parse_cli_args():
"""Parse additional arguments for the cli"""
parser = argparse.ArgumentParser(add_help=False)
- parser.add_argument('--no-cache',
- action='store_false', default=True, dest='use_cache',
- help="Don't use actions map cache",
- )
parser.add_argument('--output-as',
choices=['json', 'plain', 'none'], default=None,
- help="Output result in another format",
+ help="Output result in another format"
)
parser.add_argument('--debug',
action='store_true', default=False,
- help="Log and print debug messages",
+ help="Log and print debug messages"
)
parser.add_argument('--quiet',
action='store_true', default=False,
- help="Don't produce any output",
+ help="Don't produce any output"
)
parser.add_argument('--timeout',
type=int, default=None,
- help="Number of seconds before this command will timeout because it can't acquire the lock (meaning that another command is currently running), by default there is no timeout and the command will wait until it can get the lock",
- )
- parser.add_argument('--admin-password',
- default=None, dest='password', metavar='PASSWORD',
- help="The admin password to use to authenticate",
+ help="Number of seconds before this command will timeout because it can't acquire the lock (meaning that another command is currently running), by default there is no timeout and the command will wait until it can get the lock"
)
# deprecated arguments
parser.add_argument('--plain',
@@ -88,96 +46,6 @@ def _parse_cli_args():
return (parser, opts, args)
-def _init_moulinette(debug=False, quiet=False):
- """Configure logging and initialize the moulinette"""
- # Define loggers handlers
- handlers = set(LOGGERS_HANDLERS)
- if quiet and 'tty' in handlers:
- handlers.remove('tty')
- elif 'tty' not in handlers:
- handlers.append('tty')
-
- root_handlers = set(handlers)
- if not debug and 'tty' in root_handlers:
- root_handlers.remove('tty')
-
- # Define loggers level
- level = LOGGERS_LEVEL
- tty_level = TTY_LOG_LEVEL
- if debug:
- tty_level = 'DEBUG'
-
- # Custom logging configuration
- logging = {
- 'version': 1,
- 'disable_existing_loggers': True,
- 'formatters': {
- 'tty-debug': {
- 'format': '%(relativeCreated)-4d %(fmessage)s'
- },
- 'precise': {
- 'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
- },
- },
- 'filters': {
- 'action': {
- '()': 'moulinette.utils.log.ActionFilter',
- },
- },
- 'handlers': {
- 'tty': {
- 'level': tty_level,
- 'class': 'moulinette.interfaces.cli.TTYHandler',
- 'formatter': 'tty-debug' if debug else '',
- },
- 'file': {
- 'class': 'logging.FileHandler',
- 'formatter': 'precise',
- 'filename': '%s/%s' % (LOG_DIR, LOG_FILE),
- 'filters': ['action'],
- },
- },
- 'loggers': {
- 'yunohost': {
- 'level': level,
- 'handlers': handlers,
- 'propagate': False,
- },
- 'moulinette': {
- 'level': level,
- 'handlers': [],
- 'propagate': True,
- },
- 'moulinette.interface': {
- 'level': level,
- 'handlers': handlers,
- 'propagate': False,
- },
- },
- 'root': {
- 'level': level,
- 'handlers': root_handlers,
- },
- }
-
- # Create log directory
- if not os.path.isdir(LOG_DIR):
- try:
- os.makedirs(LOG_DIR, 0750)
- except os.error as e:
- _die(str(e))
-
- # Initialize moulinette
- moulinette.init(logging_config=logging, _from_source=IN_DEVEL)
-
-def _retrieve_namespaces():
- """Return the list of namespaces to load"""
- ret = ['yunohost']
- for n in ActionsMap.get_namespaces():
- # Append YunoHost modules
- if n.startswith('ynh_'):
- 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"
@@ -188,33 +56,18 @@ if os.environ["PATH"] != default_path:
if __name__ == '__main__':
if os.geteuid() != 0:
- # since moulinette isn't initialized, we can't use m18n here
- sys.stderr.write("\033[1;31mError:\033[0m yunohost command must be " \
+ sys.stderr.write("\033[1;31mError:\033[0m yunohost command must be "
"run as root or with sudo.\n")
sys.exit(1)
parser, opts, args = _parse_cli_args()
- _init_moulinette(opts.debug, opts.quiet)
-
- # Check that YunoHost is installed
- if not os.path.isfile('/etc/yunohost/installed') and \
- (len(args) < 2 or (args[0] +' '+ args[1] != 'tools postinstall' and \
- args[0] +' '+ args[1] != 'backup restore' and \
- args[0] +' '+ args[1] != 'log display')):
-
- from moulinette import m18n
- # Init i18n
- m18n.load_namespace('yunohost')
- m18n.set_locale(get_locale())
-
- # Print error and exit
- _die(m18n.n('yunohost_not_installed'), m18n.g('error'))
# Execute the action
- ret = moulinette.cli(
- _retrieve_namespaces(), args,
- use_cache=opts.use_cache, output_as=opts.output_as,
- password=opts.password, parser_kwargs={'top_parser': parser},
+ yunohost.cli(
+ debug=opts.debug,
+ quiet=opts.quiet,
+ output_as=opts.output_as,
timeout=opts.timeout,
+ args=args,
+ parser=parser
)
- sys.exit(ret)
diff --git a/bin/yunohost-api b/bin/yunohost-api
index e518c34b0..cc849590a 100755
--- a/bin/yunohost-api
+++ b/bin/yunohost-api
@@ -1,52 +1,16 @@
#! /usr/bin/python
# -*- coding: utf-8 -*-
-import os
import sys
import argparse
-# Either we are in a development environment or not
-IN_DEVEL = False
+sys.path.insert(0, "/usr/lib/moulinette/")
+import yunohost
# Default server configuration
DEFAULT_HOST = 'localhost'
DEFAULT_PORT = 6787
-# Level for which loggers will log
-LOGGERS_LEVEL = 'DEBUG'
-API_LOGGER_LEVEL = 'INFO'
-
-# Handlers that will be used by loggers
-# - file: log to the file LOG_DIR/LOG_FILE
-# - api: serve logs through the api
-# - console: log to stderr
-LOGGERS_HANDLERS = ['file', 'api']
-
-# Directory and file to be used by logging
-LOG_DIR = '/var/log/yunohost'
-LOG_FILE = 'yunohost-api.log'
-
-# Check and load - as needed - development environment
-if not __file__.startswith('/usr/'):
- IN_DEVEL = True
-if IN_DEVEL:
- basedir = os.path.abspath('%s/../' % os.path.dirname(__file__))
- if os.path.isdir(os.path.join(basedir, 'moulinette')):
- sys.path.insert(0, basedir)
- LOG_DIR = os.path.join(basedir, 'log')
-
-
-import moulinette
-from moulinette.actionsmap import ActionsMap
-from moulinette.interfaces.cli import colorize
-
-
-# Initialization & helpers functions -----------------------------------
-
-def _die(message, title='Error:'):
- """Print error message and exit"""
- print('%s %s' % (colorize(title, 'red'), message))
- sys.exit(1)
def _parse_api_args():
"""Parse main arguments for the api"""
@@ -62,149 +26,19 @@ def _parse_api_args():
action='store', default=DEFAULT_PORT, type=int,
help="Port to listen on (default: %d)" % DEFAULT_PORT,
)
- srv_group.add_argument('--no-websocket',
- action='store_true', default=True, dest='use_websocket',
- help="Serve without WebSocket support, used to handle "
- "asynchronous responses such as the messages",
- )
glob_group = parser.add_argument_group('global arguments')
- glob_group.add_argument('--no-cache',
- action='store_false', default=True, dest='use_cache',
- help="Don't use actions map cache",
- )
glob_group.add_argument('--debug',
action='store_true', default=False,
help="Set log level to DEBUG",
)
- glob_group.add_argument('--verbose',
- action='store_true', default=False,
- help="Be verbose in the output",
- )
glob_group.add_argument('--help',
action='help', help="Show this help message and exit",
)
return parser.parse_args()
-def _init_moulinette(use_websocket=True, debug=False, verbose=False):
- """Configure logging and initialize the moulinette"""
- # Define loggers handlers
- handlers = set(LOGGERS_HANDLERS)
- if not use_websocket and 'api' in handlers:
- handlers.remove('api')
- if verbose and 'console' not in handlers:
- handlers.add('console')
- root_handlers = handlers - set(['api'])
-
- # Define loggers level
- level = LOGGERS_LEVEL
- api_level = API_LOGGER_LEVEL
- if debug:
- level = 'DEBUG'
- api_level = 'DEBUG'
-
- # Custom logging configuration
- logging = {
- 'version': 1,
- 'disable_existing_loggers': True,
- 'formatters': {
- 'console': {
- 'format': '%(relativeCreated)-5d %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
- },
- 'precise': {
- 'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
- },
- },
- 'filters': {
- 'action': {
- '()': 'moulinette.utils.log.ActionFilter',
- },
- },
- 'handlers': {
- 'api': {
- 'level': api_level,
- 'class': 'moulinette.interfaces.api.APIQueueHandler',
- },
- 'file': {
- 'class': 'logging.handlers.WatchedFileHandler',
- 'formatter': 'precise',
- 'filename': '%s/%s' % (LOG_DIR, LOG_FILE),
- 'filters': ['action'],
- },
- 'console': {
- 'class': 'logging.StreamHandler',
- 'formatter': 'console',
- 'stream': 'ext://sys.stdout',
- 'filters': ['action'],
- },
- },
- 'loggers': {
- 'yunohost': {
- 'level': level,
- 'handlers': handlers,
- 'propagate': False,
- },
- 'moulinette': {
- 'level': level,
- 'handlers': [],
- 'propagate': True,
- },
- 'gnupg': {
- 'level': 'INFO',
- 'handlers': [],
- 'propagate': False,
- },
- },
- 'root': {
- 'level': level,
- 'handlers': root_handlers,
- },
- }
-
- # Create log directory
- if not os.path.isdir(LOG_DIR):
- try:
- os.makedirs(LOG_DIR, 0750)
- except os.error as e:
- _die(str(e))
-
- # Initialize moulinette
- moulinette.init(logging_config=logging, _from_source=IN_DEVEL)
-
-def _retrieve_namespaces():
- """Return the list of namespaces to load"""
- ret = ['yunohost']
- for n in ActionsMap.get_namespaces():
- # Append YunoHost modules
- if n.startswith('ynh_'):
- ret.append(n)
- return ret
-
-
-# Callbacks for additional routes --------------------------------------
-
-def is_installed():
- """
- Check whether YunoHost is installed or not
-
- """
- installed = False
- if os.path.isfile('/etc/yunohost/installed'):
- installed = True
- return { 'installed': installed }
-
-
-# Main action ----------------------------------------------------------
if __name__ == '__main__':
opts = _parse_api_args()
- _init_moulinette(opts.use_websocket, opts.debug, opts.verbose)
-
# Run the server
- ret = moulinette.api(
- _retrieve_namespaces(),
- host=opts.host, port=opts.port, routes={
- ('GET', '/installed'): is_installed,
- }, use_cache=opts.use_cache, use_websocket=opts.use_websocket
- )
- sys.exit(ret)
+ yunohost.api(debug=opts.debug, host=opts.host, port=opts.port)
diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml
index 61f4862e6..1124e3938 100644
--- a/data/actionsmap/yunohost.yml
+++ b/data/actionsmap/yunohost.yml
@@ -1000,7 +1000,6 @@ service:
choices:
- 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:
@@ -1696,6 +1695,9 @@ diagnosis:
--share:
help: Share the logs using yunopaste
action: store_true
+ --human-readable:
+ help: Show a human-readable output
+ action: store_true
run:
action_help: Run diagnosis
@@ -1710,6 +1712,9 @@ diagnosis:
--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
+ --email:
+ help: Send an email to root with issues found (this is meant to be used by cron job)
+ action: store_true
ignore:
action_help: Configure some diagnosis results to be ignored and therefore not considered as actual issues
diff --git a/data/helpers.d/apt b/data/helpers.d/apt
index 82e3ab40c..377464786 100644
--- a/data/helpers.d/apt
+++ b/data/helpers.d/apt
@@ -10,6 +10,7 @@
# Requires YunoHost version 3.3.1 or higher.
ynh_wait_dpkg_free() {
local try
+ set +o xtrace # set +x
# With seq 1 17, timeout will be almost 30 minutes
for try in `seq 1 17`
do
@@ -32,13 +33,16 @@ ynh_wait_dpkg_free() {
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."
+ set -o xtrace # set -x
return 1
fi
done 9<<< "$(ls -1 $dpkg_dir)"
+ set -o xtrace # set -x
return 0
fi
done
echo "apt still used, but timeout reached !"
+ set -o xtrace # set -x
}
# Check either a package is installed or not
@@ -96,7 +100,7 @@ ynh_package_version() {
# Requires YunoHost version 2.4.0.3 or higher.
ynh_apt() {
ynh_wait_dpkg_free
- LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get --assume-yes $@
+ LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get --assume-yes --quiet -o=Acquire::Retries=3 -o=Dpkg::Use-Pty=0 $@
}
# Update package index files
@@ -256,15 +260,17 @@ ynh_install_app_dependencies () {
# And we have packages from sury installed (7.0.33-10+weirdshiftafter instead of 7.0.33-0 on debian)
if dpkg --list | grep "php7.0" | grep --quiet --invert-match "7.0.33-0+deb9"
then
- # And sury ain't already installed
- if ! grep --line-number --recursive --quiet "sury" /etc/apt/sources.list*
+ # And sury ain't already in sources.lists
+ if ! grep --recursive --quiet "^ *deb.*sury" /etc/apt/sources.list*
then
# Re-add sury
- ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version
+ ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version --priority=600
# Pin this sury repository to prevent sury of doing shit
- 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
+ for package_to_not_upgrade in "php" "php-fpm" "php-mysql" "php-xml" "php-zip" "php-mbstring" "php-ldap" "php-gd" "php-curl" "php-bz2" "php-json" "php-sqlite3" "php-intl" "openssl" "libssl1.1" "libssl-dev"
+ do
+ ynh_pin_repo --package="$package_to_not_upgrade" --pin="origin \"packages.sury.org\"" --priority="-1" --name=extra_php_version --append
+ done
fi
fi
fi
@@ -329,8 +335,6 @@ ynh_remove_app_dependencies () {
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]
@@ -436,7 +440,8 @@ ynh_install_extra_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
+ # Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
+ wget --timeout 900 --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
@@ -462,8 +467,8 @@ ynh_remove_extra_repo () {
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"
+ ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.gpg" > /dev/null
+ ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.asc" > /dev/null
# Update the list of package to exclude the old repo
ynh_package_update
diff --git a/data/helpers.d/fail2ban b/data/helpers.d/fail2ban
index d8777a16d..f9bdd89b2 100644
--- a/data/helpers.d/fail2ban
+++ b/data/helpers.d/fail2ban
@@ -134,7 +134,7 @@ EOF
ynh_systemd_action --service_name=fail2ban --action=reload --line_match="(Started|Reloaded) Fail2Ban Service" --log_path=systemd
- local fail2ban_error="$(journalctl --unit=fail2ban | tail --lines=50 | grep "WARNING.*$app.*")"
+ local fail2ban_error="$(journalctl --no-hostname --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"
diff --git a/data/helpers.d/getopts b/data/helpers.d/getopts
index 10c06930c..a4bbe20e6 100644
--- a/data/helpers.d/getopts
+++ b/data/helpers.d/getopts
@@ -80,10 +80,10 @@ ynh_handle_getopts_args () {
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}}"
+ # Replace long option with = (match the beginning of the argument)
+ arguments[arg]="$(echo "${arguments[arg]}" | sed "s/^--${args_array[$option_flag]}/-${option_flag} /")"
+ # And long option without = (match the whole line)
+ arguments[arg]="$(echo "${arguments[arg]}" | sed "s/^--${args_array[$option_flag]%=}$/-${option_flag} /")"
done
done
diff --git a/data/helpers.d/hardware b/data/helpers.d/hardware
index 6702a8548..0771c81d8 100644
--- a/data/helpers.d/hardware
+++ b/data/helpers.d/hardware
@@ -25,17 +25,17 @@ ynh_get_ram () {
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 ]
+ if [ $free -eq $total ]
then
+ ynh_print_warn --message="You have to choose --free or --total when using ynh_get_ram"
+ ram=0
+ # Use the total amount of ram
+ elif [ $free -eq 1 ]
+ then
+ 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 free ram
local ram=$free_ram_swap
if [ $ignore_swap -eq 1 ]
@@ -49,6 +49,10 @@ ynh_get_ram () {
fi
elif [ $total -eq 1 ]
then
+ 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 ram=$total_ram_swap
if [ $ignore_swap -eq 1 ]
then
@@ -59,9 +63,6 @@ ynh_get_ram () {
# 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
diff --git a/data/helpers.d/logging b/data/helpers.d/logging
index c79090e25..45b5b7e67 100644
--- a/data/helpers.d/logging
+++ b/data/helpers.d/logging
@@ -80,7 +80,7 @@ ynh_print_warn () {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
- ynh_print_log "\e[93m\e[1m[WARN]\e[0m ${message}" >&2
+ ynh_print_log "${message}" >&2
}
# Print an error on stderr
@@ -97,7 +97,7 @@ ynh_print_err () {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
- ynh_print_log "\e[91m\e[1m[ERR]\e[0m ${message}" >&2
+ ynh_print_log "[Error] ${message}" >&2
}
# Execute a command and print the result as an error
@@ -216,7 +216,7 @@ base_time=$(date +%s)
# | 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: -l, --last - Use for the last call of the helper, to fill the progression bar.
#
# Requires YunoHost version 3.5.0 or higher.
ynh_script_progression () {
@@ -332,7 +332,7 @@ ynh_debug () {
if [ -n "$message" ]
then
- ynh_print_log "\e[34m\e[1m[DEBUG]\e[0m ${message}" >&2
+ ynh_print_log "[Debug] ${message}" >&2
fi
if [ "$trace" == "1" ]
diff --git a/data/helpers.d/mysql b/data/helpers.d/mysql
index 84acc1029..05f75e0a2 100644
--- a/data/helpers.d/mysql
+++ b/data/helpers.d/mysql
@@ -44,8 +44,13 @@ ynh_mysql_execute_as_root() {
ynh_handle_getopts_args "$@"
database="${database:-}"
+ if [ -n "$database" ]
+ then
+ database="--database=$database"
+ fi
+
ynh_mysql_connect_as --user="root" --password="$(cat $MYSQL_ROOT_PWD_FILE)" \
- --database="$database" <<< "$sql"
+ $database <<< "$sql"
}
# Execute a command from a file as root user
@@ -65,8 +70,14 @@ ynh_mysql_execute_file_as_root() {
ynh_handle_getopts_args "$@"
database="${database:-}"
+ if [ -n "$database" ]
+ then
+ database="--database=$database"
+ fi
+
+
ynh_mysql_connect_as --user="root" --password="$(cat $MYSQL_ROOT_PWD_FILE)" \
- --database="$database" < "$file"
+ $database < "$file"
}
# Create a database and grant optionnaly privilegies to a user
diff --git a/data/helpers.d/nodejs b/data/helpers.d/nodejs
index efb50ae37..75472c278 100644
--- a/data/helpers.d/nodejs
+++ b/data/helpers.d/nodejs
@@ -1,5 +1,6 @@
#!/bin/bash
+n_version=6.5.1
n_install_dir="/opt/node_n"
node_version_path="$n_install_dir/n/versions/node"
# N_PREFIX is the directory of n, it needs to be loaded as a environment variable.
@@ -16,8 +17,8 @@ ynh_install_n () {
ynh_print_info --message="Installation of N - Node.js version management"
# Build an app.src for n
mkdir --parents "../conf"
- echo "SOURCE_URL=https://github.com/tj/n/archive/v4.1.0.tar.gz
-SOURCE_SUM=3983fa3f00d4bf85ba8e21f1a590f6e28938093abe0bb950aeea52b1717471fc" > "../conf/n.src"
+ echo "SOURCE_URL=https://github.com/tj/n/archive/v${n_version}.tar.gz
+SOURCE_SUM=5833f15893b9951a9ed59487e87b6c181d96b83a525846255872c4f92f0d25dd" > "../conf/n.src"
# Download and extract n
ynh_setup_source --dest_dir="$n_install_dir/git" --source_id=n
# Install n
@@ -28,14 +29,38 @@ SOURCE_SUM=3983fa3f00d4bf85ba8e21f1a590f6e28938093abe0bb950aeea52b1717471fc" > "
# Load the version of node for an app, and set variables.
#
# ynh_use_nodejs has to be used in any app scripts before using node for the first time.
+# This helper will provide alias and variables to use in your scripts.
#
-# 2 variables are available:
-# - $nodejs_path: The absolute path of node for the chosen version.
+# To use npm or node, use the alias `ynh_npm` and `ynh_node`
+# Those alias will use the correct version installed for the app
+# For example: use `ynh_npm install` instead of `npm install`
+#
+# With `sudo` or `ynh_exec_as`, use instead the fallback variables `$ynh_npm` and `$ynh_node`
+# And propagate $PATH to sudo with $ynh_node_load_PATH
+# Exemple: `ynh_exec_as $app $ynh_node_load_PATH $ynh_npm install`
+#
+# $PATH contains the path of the requested version of node.
+# However, $PATH is duplicated into $node_PATH to outlast any manipulation of $PATH
+# You can use the variable `$ynh_node_load_PATH` to quickly load your node version
+# in $PATH for an usage into a separate script.
+# Exemple: $ynh_node_load_PATH $final_path/script_that_use_npm.sh`
+#
+#
+# Finally, to start a nodejs service with the correct version, 2 solutions
+# Either the app is dependent of node or npm, but does not called it directly.
+# In such situation, you need to load PATH
+# `Environment="__NODE_ENV_PATH__"`
+# `ExecStart=__FINALPATH__/my_app`
+# You will replace __NODE_ENV_PATH__ with $ynh_node_load_PATH
+#
+# Or node start the app directly, then you don't need to load the PATH variable
+# `ExecStart=__YNH_NODE__ my_app run`
+# You will replace __YNH_NODE__ with $ynh_node
+#
+#
+# 2 other variables are also available
+# - $nodejs_path: The absolute path to node binaries for the chosen version.
# - $nodejs_version: Just the version number of node for this app. Stored as 'nodejs_version' in settings.yml.
-# And 2 alias stored in variables:
-# - $nodejs_use_version: An old variable, not used anymore. Keep here to not break old apps
-# NB: $PATH will contain the path to node, it has to be propagated to any other shell which needs to use it.
-# That's means it has to be added to any systemd script.
#
# usage: ynh_use_nodejs
#
@@ -43,15 +68,26 @@ SOURCE_SUM=3983fa3f00d4bf85ba8e21f1a590f6e28938093abe0bb950aeea52b1717471fc" > "
ynh_use_nodejs () {
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
- 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"
+ # Allow alias to be used into bash script
+ shopt -s expand_aliases
+
+ # Create an alias for the specific version of node and a variable as fallback
+ ynh_node="$nodejs_path/node"
+ alias ynh_node="$ynh_node"
+ # And npm
+ ynh_npm="$nodejs_path/npm"
+ alias ynh_npm="$ynh_npm"
+
# Load the path of this version of node in $PATH
if [[ :$PATH: != *":$nodejs_path"* ]]; then
PATH="$nodejs_path:$PATH"
fi
+ node_PATH="$PATH"
+ # Create an alias to easily load the PATH
+ ynh_node_load_PATH="PATH=$node_PATH"
}
# Install a specific version of nodejs
@@ -64,6 +100,8 @@ ynh_use_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
#
+# Refer to ynh_use_nodejs for more information about available commands and variables
+#
# Requires YunoHost version 2.7.12 or higher.
ynh_install_nodejs () {
# Use n, https://github.com/tj/n to manage the nodejs versions
@@ -88,7 +126,10 @@ ynh_install_nodejs () {
test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n
# If n is not previously setup, install it
- if ! test $(n --version > /dev/null 2>&1)
+ if ! $n_install_dir/bin/n --version > /dev/null 2>&1
+ then
+ ynh_install_n
+ elif dpkg --compare-versions "$($n_install_dir/bin/n --version)" lt $n_version
then
ynh_install_n
fi
diff --git a/data/helpers.d/php b/data/helpers.d/php
index e8de6d9ff..7ff671317 100644
--- a/data/helpers.d/php
+++ b/data/helpers.d/php
@@ -1,6 +1,6 @@
#!/bin/bash
-readonly YNH_DEFAULT_PHP_VERSION=7.0
+readonly YNH_DEFAULT_PHP_VERSION=7.3
# 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}
@@ -148,8 +148,14 @@ ynh_add_fpm_config () {
if [ $use_template -eq 1 ]
then
- # Usage 1, use the template in ../conf/php-fpm.conf
- cp ../conf/php-fpm.conf "$finalphpconf"
+ # Usage 1, use the template in conf/php-fpm.conf
+ local phpfpm_path="../conf/php-fpm.conf"
+ if [ ! -e "$phpfpm_path" ]; then
+ phpfpm_path="../settings/conf/php-fpm.conf" # Into the restore script, the php-fpm template is not at the same place
+ fi
+ # Make sure now that the template indeed exists
+ [ -e "$phpfpm_path" ] || ynh_die --message="Unable to find template to configure php-fpm."
+ cp "$phpfpm_path" "$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"
@@ -297,7 +303,10 @@ ynh_remove_fpm_config () {
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 [ -e $fpm_config_dir/conf.d/20-$app.ini ]
+ then
+ ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini"
+ fi
# If the php version used is not the default version for YunoHost
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ]
@@ -345,7 +354,7 @@ ynh_install_php () {
fi
# Add an extra repository for those packages
- ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version
+ ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version --priority=600
# Install requested dependencies from this extra repository.
# Install php-fpm first, otherwise php will install apache as a dependency.
@@ -356,8 +365,10 @@ ynh_install_php () {
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
+ for package_to_not_upgrade in "php" "php-fpm" "php-mysql" "php-xml" "php-zip" "php-mbstring" "php-ldap" "php-gd" "php-curl" "php-bz2" "php-json" "php-sqlite3" "php-intl" "openssl" "libssl1.1" "libssl-dev"
+ do
+ ynh_pin_repo --package="$package_to_not_upgrade" --pin="origin \"packages.sury.org\"" --priority="-1" --name=extra_php_version --append
+ done
# Advertise service in admin panel
yunohost service add php${phpversion}-fpm --log "/var/log/php${phpversion}-fpm.log"
diff --git a/data/helpers.d/postgresql b/data/helpers.d/postgresql
index e2bef8746..11b9c0fed 100644
--- a/data/helpers.d/postgresql
+++ b/data/helpers.d/postgresql
@@ -1,6 +1,7 @@
#!/bin/bash
PSQL_ROOT_PWD_FILE=/etc/yunohost/psql
+PSQL_VERSION=11
# Open a connection as a user
#
@@ -45,8 +46,13 @@ ynh_psql_execute_as_root() {
ynh_handle_getopts_args "$@"
database="${database:-}"
+ if [ -n "$database" ]
+ then
+ database="--database=$database"
+ fi
+
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
- --database="$database" <<<"$sql"
+ $database <<<"$sql"
}
# Execute a command from a file as root user
@@ -66,8 +72,13 @@ ynh_psql_execute_file_as_root() {
ynh_handle_getopts_args "$@"
database="${database:-}"
+ if [ -n "$database" ]
+ then
+ database="--database=$database"
+ fi
+
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
- --database="$database" <"$file"
+ $database <"$file"
}
# Create a database and grant optionnaly privilegies to a user
@@ -212,7 +223,7 @@ ynh_psql_drop_user() {
# usage: ynh_psql_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
-# | arg: -p, --db_pwd= - Password of the database. If not given, a password will be generated
+# | arg: -p, --db_pwd= - Password of the database. If not provided, a password will be generated
#
# After executing this helper, the password of the created database will be available in $db_pwd
# It will also be stored as "psqlpwd" into the app settings.
@@ -228,12 +239,14 @@ ynh_psql_setup_db() {
# 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}"
-
if ! ynh_psql_user_exists --user=$db_user; then
+ local new_db_pwd=$(ynh_string_random) # Generate a random password
+ # If $db_pwd is not provided, use new_db_pwd instead for db_pwd
+ db_pwd="${db_pwd:-$new_db_pwd}"
+
ynh_psql_create_user "$db_user" "$db_pwd"
+ elif [ -z $db_pwd ]; then
+ ynh_die --message="The user $db_user exists, please provide his password"
fi
ynh_psql_create_db "$db_name" "$db_user" # Create the database
@@ -273,6 +286,7 @@ ynh_psql_remove_db() {
}
# Create a master password and set up global settings
+# It also make sure that postgresql is installed and running
# Please always call this script in install and restore scripts
#
# usage: ynh_psql_test_if_first_run
@@ -280,45 +294,38 @@ ynh_psql_remove_db() {
# Requires YunoHost version 2.7.13 or higher.
ynh_psql_test_if_first_run() {
- if [ -f "$PSQL_ROOT_PWD_FILE" ]
+ # Make sure postgresql is indeed installed
+ dpkg --list | grep -q "ii postgresql-$PSQL_VERSION" || ynh_die "postgresql-$PSQL_VERSION is not installed !?"
+
+ # Check for some weird issue where postgresql could be installed but etc folder would not exist ...
+ [ -e "/etc/postgresql/$PSQL_VERSION" ] || ynh_die "It looks like postgresql was not properly configured ? /etc/postgresql/$PSQL_VERSION is missing ... Could be due to a locale issue, c.f.https://serverfault.com/questions/426989/postgresql-etc-postgresql-doesnt-exist"
+
+ # Make sure postgresql is started and enabled
+ # (N.B. : to check the active state, we check the cluster state because
+ # postgresql could be flagged as active even though the cluster is in
+ # failed state because of how the service is configured..)
+ systemctl is-active postgresql@$PSQL_VERSION-main -q || ynh_systemd_action --service_name=postgresql --action=restart
+ systemctl is-enabled postgresql -q || systemctl enable postgresql --quiet
+
+ # If this is the very first time, we define the root password
+ # and configure a few things
+ if [ ! -f "$PSQL_ROOT_PWD_FILE" ]
then
- ynh_print_info --message="PostgreSQL is already installed, no need to create master password"
- return
+ local pg_hba=/etc/postgresql/$PSQL_VERSION/main/pg_hba.conf
+
+ local psql_root_password="$(ynh_string_random)"
+ echo "$psql_root_password" >$PSQL_ROOT_PWD_FILE
+ sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$psql_root_password'" postgres
+
+ # force all user to connect to local databases using hashed passwords
+ # https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF
+ # Note: we can't use peer since YunoHost create users with nologin
+ # See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user
+ ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba"
+
+ # Integrate postgresql service in yunohost
+ yunohost service add postgresql --log "/var/log/postgresql/"
+
+ ynh_systemd_action --service_name=postgresql --action=reload
fi
-
- 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"
- fi
- fi
-
- ynh_systemd_action --service_name=postgresql --action=start
-
- sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$psql_root_password'" postgres
-
- # force all user to connect to local databases using hashed passwords
- # https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF
- # Note: we can't use peer since YunoHost create users with nologin
- # See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user
- ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba"
-
- # Advertise service in admin panel
- yunohost service add postgresql --log "$logfile"
-
- systemctl enable postgresql
- ynh_systemd_action --service_name=postgresql --action=reload
}
diff --git a/data/helpers.d/systemd b/data/helpers.d/systemd
index 613f023fa..5c5fda852 100644
--- a/data/helpers.d/systemd
+++ b/data/helpers.d/systemd
@@ -58,7 +58,7 @@ ynh_add_systemd_config () {
ynh_store_file_checksum --file="$finalsystemdconf"
chown root: "$finalsystemdconf"
- systemctl enable $service
+ systemctl enable $service --quiet
systemctl daemon-reload
}
@@ -81,7 +81,7 @@ ynh_remove_systemd_config () {
if [ -e "$finalsystemdconf" ]
then
ynh_systemd_action --service_name=$service --action=stop
- systemctl disable $service
+ systemctl disable $service --quiet
ynh_secure_remove --file="$finalsystemdconf"
systemctl daemon-reload
fi
@@ -145,7 +145,7 @@ ynh_systemd_action() {
if ! systemctl $action $service_name
then
# Show syslog for this service
- ynh_exec_err journalctl --no-pager --lines=$length --unit=$service_name
+ ynh_exec_err journalctl --quiet --no-hostname --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
@@ -183,7 +183,7 @@ ynh_systemd_action() {
then
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:"
- ynh_exec_warn journalctl --no-pager --lines=$length --unit=$service_name
+ ynh_exec_warn journalctl --quiet --no-hostname --no-pager --lines=$length --unit=$service_name
if [ -e "$log_path" ]
then
ynh_print_warn --message="\-\-\-"
diff --git a/data/helpers.d/utils b/data/helpers.d/utils
index 81db1fb21..95f8ddc52 100644
--- a/data/helpers.d/utils
+++ b/data/helpers.d/utils
@@ -144,7 +144,13 @@ ynh_setup_source () {
then # Use the local source file if it is present
cp $local_src $src_filename
else # If not, download the source
- local out=`wget --no-verbose --output-document=$src_filename $src_url 2>&1` || ynh_print_err --message="$out"
+ # NB. we have to declare the var as local first,
+ # otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
+ # because local always return 0 ...
+ local out
+ # Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
+ out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
+ || ynh_die --message="$out"
fi
# Check the control sum
diff --git a/data/hooks/backup/05-conf_ldap b/data/hooks/backup/05-conf_ldap
index 75b4c2075..e3e8e455d 100755
--- a/data/hooks/backup/05-conf_ldap
+++ b/data/hooks/backup/05-conf_ldap
@@ -10,7 +10,8 @@ source /usr/share/yunohost/helpers
backup_dir="${1}/conf/ldap"
# Backup the configuration
-ynh_backup "/etc/ldap/slapd.conf" "${backup_dir}/slapd.conf"
+ynh_backup "/etc/ldap/ldap.conf" "${backup_dir}/ldap.conf"
+ynh_backup "/etc/ldap/slapd.ldif" "${backup_dir}/slapd.ldif"
slapcat -b cn=config -l "${backup_dir}/cn=config.master.ldif"
# Backup the database
diff --git a/data/hooks/backup/11-conf_ynh_mysql b/data/hooks/backup/11-conf_ynh_mysql
deleted file mode 100755
index 031707337..000000000
--- a/data/hooks/backup/11-conf_ynh_mysql
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-# Exit hook on subcommand error or unset variable
-set -eu
-
-# Source YNH helpers
-source /usr/share/yunohost/helpers
-
-# Backup destination
-backup_dir="${1}/conf/ynh/mysql"
-
-# Save MySQL root password
-ynh_backup "/etc/yunohost/mysql" "${backup_dir}/root_pwd"
diff --git a/data/hooks/conf_regen/01-yunohost b/data/hooks/conf_regen/01-yunohost
index 236619079..c4120d487 100755
--- a/data/hooks/conf_regen/01-yunohost
+++ b/data/hooks/conf_regen/01-yunohost
@@ -55,14 +55,63 @@ do_pre_regen() {
fi
# 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
+ # 0 and 20min, 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
+0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably"
EOF
+ # legacy stuff to avoid yunohost reporting etckeeper as manually modified
+ # (this make sure that the hash is null / file is flagged as to-delete)
+ mkdir -p $pending_dir/etc/etckeeper
+ touch $pending_dir/etc/etckeeper/etckeeper.conf
+
+ # Skip ntp if inside a container (inspired from the conf of systemd-timesyncd)
+ mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/
+ echo "
+[Unit]
+ConditionCapability=CAP_SYS_TIME
+ConditionVirtualization=!container
+" > ${pending_dir}/etc/systemd/system/ntp.service.d/ynh-override.conf
+
+ # Make nftable conflict with yunohost-firewall
+ mkdir -p ${pending_dir}/etc/systemd/system/nftables.service.d/
+ cat > ${pending_dir}/etc/systemd/system/nftables.service.d/ynh-override.conf << EOF
+[Unit]
+# yunohost-firewall and nftables conflict with each other
+Conflicts=yunohost-firewall.service
+ConditionFileIsExecutable=!/etc/init.d/yunohost-firewall
+ConditionPathExists=!/etc/systemd/system/multi-user.target.wants/yunohost-firewall.service
+EOF
+}
+
+do_post_regen() {
+ regen_conf_files=$1
+
+ ######################
+ # Enfore permissions #
+ ######################
+
+ # Certs
+ # We do this with find because there could be a lot of them...
+ chown -R root:ssl-cert /etc/yunohost/certs
+ chmod 750 /etc/yunohost/certs
+ find /etc/yunohost/certs/ -type f -exec chmod 640 {} \;
+ find /etc/yunohost/certs/ -type d -exec chmod 750 {} \;
+
+ # Misc configuration / state files
+ chown root:root $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null)
+ chmod 600 $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null)
+
+ # Apps folder, custom hooks folder
+ [[ ! -e /etc/yunohost/hooks.d ]] || (chown root /etc/yunohost/hooks.d && chmod 700 /etc/yunohost/hooks.d)
+ [[ ! -e /etc/yunohost/apps ]] || (chown root /etc/yunohost/apps && chmod 700 /etc/yunohost/apps)
+
+ # Propagates changes in systemd service config overrides
+ [[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || { systemctl daemon-reload; systemctl restart ntp; }
+ [[ ! "$regen_conf_files" =~ "nftables.service.d/ynh-override.conf" ]] || systemctl daemon-reload
}
_update_services() {
@@ -74,7 +123,7 @@ with open('services.yml') as f:
new_services = yaml.load(f)
with open('/etc/yunohost/services.yml') as f:
- services = yaml.load(f)
+ services = yaml.load(f) or {}
updated = False
@@ -132,6 +181,7 @@ case "$1" in
do_pre_regen $4
;;
post)
+ do_post_regen $4
;;
init)
do_init_regen
diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl
index a893b21e1..310a5d526 100755
--- a/data/hooks/conf_regen/02-ssl
+++ b/data/hooks/conf_regen/02-ssl
@@ -69,12 +69,11 @@ do_init_regen() {
-out "${ssl_dir}/certs/yunohost_crt.pem" \
-batch >>$LOGFILE 2>&1
- last_cert=$(ls $ssl_dir/newcerts/*.pem | sort -V | tail -n 1)
chmod 640 "${ssl_dir}/certs/yunohost_key.pem"
- chmod 640 "$last_cert"
+ chmod 640 "${ssl_dir}/certs/yunohost_crt.pem"
cp "${ssl_dir}/certs/yunohost_key.pem" "$ynh_key"
- cp "$last_cert" "$ynh_crt"
+ cp "${ssl_dir}/certs/yunohost_crt.pem" "$ynh_crt"
ln -sf "$ynh_crt" /etc/ssl/certs/yunohost_crt.pem
ln -sf "$ynh_key" /etc/ssl/private/yunohost_key.pem
fi
diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd
index 9b2c20138..9f808b58e 100755
--- a/data/hooks/conf_regen/06-slapd
+++ b/data/hooks/conf_regen/06-slapd
@@ -12,27 +12,52 @@ do_init_regen() {
do_pre_regen ""
- # fix some permissions
- chown root:openldap /etc/ldap/slapd.conf
+ systemctl daemon-reload
+
+ _regenerate_slapd_conf
+
+ # Enforce permissions
+ chown root:openldap /etc/ldap/slapd.ldif
chown -R openldap:openldap /etc/ldap/schema/
usermod -aG ssl-cert openldap
- # check the slapd config file at first
- slaptest -Q -u -f /etc/ldap/slapd.conf
-
- # regenerate LDAP config directory from slapd.conf
- rm -Rf /etc/ldap/slapd.d
- mkdir /etc/ldap/slapd.d
- slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/ 2>&1
- chown -R openldap:openldap /etc/ldap/slapd.d/
-
service slapd restart
}
+_regenerate_slapd_conf() {
+
+ # Validate the new slapd config
+ # To do so, we have to use the .ldif to generate the config directory
+ # so we use a temporary directory slapd_new.d
+ rm -Rf /etc/ldap/slapd_new.d
+ mkdir /etc/ldap/slapd_new.d
+ slapadd -n0 -l /etc/ldap/slapd.ldif -F /etc/ldap/slapd_new.d/ 2>&1
+ # Actual validation (-Q is for quiet, -u is for dry-run)
+ slaptest -Q -u -F /etc/ldap/slapd_new.d
+
+ # "Commit" / apply the new config (meaning we delete the old one and replace
+ # it with the new one)
+ rm -Rf /etc/ldap/slapd.d
+ mv /etc/ldap/slapd_new.d /etc/ldap/slapd.d
+
+ chown -R openldap:openldap /etc/ldap/slapd.d/
+}
+
do_pre_regen() {
pending_dir=$1
- cd /usr/share/yunohost/templates/slapd
+ # remove temporary backup file
+ rm -f "$tmp_backup_dir_file"
+
+ # Define if we need to migrate from hdb to mdb
+ curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2>/dev/null | awk '{print $2}')
+ if [ -e /etc/ldap/slapd.conf ] && [ -n "$curr_backend" ] && \
+ [ $curr_backend != 'mdb' ]; then
+ backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)"
+ mkdir -p "$backup_dir"
+ slapcat -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif"
+ echo "$backup_dir" > "$tmp_backup_dir_file"
+ fi
# create needed directories
ldap_dir="${pending_dir}/etc/ldap"
@@ -40,28 +65,15 @@ do_pre_regen() {
mkdir -p "$ldap_dir" "$schema_dir"
# remove legacy configuration file
- [ ! -f /etc/ldap/slapd-yuno.conf ] \
- || touch "${pending_dir}/etc/ldap/slapd-yuno.conf"
+ [ ! -f /etc/ldap/slapd-yuno.conf ] || touch "${ldap_dir}/slapd-yuno.conf"
+ [ ! -f /etc/ldap/slapd.conf ] || touch "${ldap_dir}/slapd.conf"
+ [ ! -f /etc/ldap/schema/yunohost.schema ] || touch "${schema_dir}/yunohost.schema"
- # remove temporary backup file
- rm -f "$tmp_backup_dir_file"
-
- # retrieve current and new backends
- curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2>/dev/null | awk '{print $2}')
- new_backend=$(grep '^database' slapd.conf | awk '{print $2}')
-
- # save current database before any conf changes
- if [[ -n "$curr_backend" && "$curr_backend" != "$new_backend" ]]; then
- backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)"
- mkdir -p "$backup_dir"
- slapcat -b dc=yunohost,dc=org \
- -l "${backup_dir}/dc=yunohost-dc=org.ldif"
- echo "$backup_dir" > "$tmp_backup_dir_file"
- fi
+ cd /usr/share/yunohost/templates/slapd
# copy configuration files
- cp -a ldap.conf slapd.conf "$ldap_dir"
- cp -a sudo.schema mailserver.schema yunohost.schema "$schema_dir"
+ cp -a ldap.conf slapd.ldif "$ldap_dir"
+ cp -a sudo.ldif mailserver.ldif permission.ldif "$schema_dir"
mkdir -p ${pending_dir}/etc/systemd/system/slapd.service.d/
cp systemd-override.conf ${pending_dir}/etc/systemd/system/slapd.service.d/ynh-override.conf
@@ -72,19 +84,13 @@ do_pre_regen() {
do_post_regen() {
regen_conf_files=$1
- # ensure that slapd.d exists
- mkdir -p /etc/ldap/slapd.d
-
# fix some permissions
- echo "Making sure we have the right permissions needed ..."
+ echo "Enforce permissions on ldap/slapd directories and certs ..."
# penldap user should be in the ssl-cert group to let it access the certificate for TLS
usermod -aG ssl-cert openldap
- chown root:openldap /etc/ldap/slapd.conf
+ chown root:openldap /etc/ldap/slapd.ldif
chown -R openldap:openldap /etc/ldap/schema/
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$"
@@ -95,29 +101,17 @@ do_post_regen() {
[ -z "$regen_conf_files" ] && exit 0
- # check the slapd config file at first
- slaptest -Q -u -f /etc/ldap/slapd.conf
+ # regenerate LDAP config directory from slapd.conf
+ echo "Regenerate LDAP config directory from slapd.ldif"
+ _regenerate_slapd_conf
- # check if a backup should be restored
+ # If there's a backup, re-import its data
backup_dir=$(cat "$tmp_backup_dir_file" 2>/dev/null || true)
if [[ -n "$backup_dir" && -f "${backup_dir}/dc=yunohost-dc=org.ldif" ]]; then
# regenerate LDAP config directory and import database as root
- # since the admin user may be unavailable
- echo "Regenerate LDAP config directory and import the database using slapadd"
- sh -c "rm -Rf /etc/ldap/slapd.d;
- mkdir /etc/ldap/slapd.d;
- slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d;
- chown -R openldap:openldap /etc/ldap/slapd.d;
- slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org \
- -l '${backup_dir}/dc=yunohost-dc=org.ldif';
- chown -R openldap:openldap /var/lib/ldap" 2>&1
- else
- # regenerate LDAP config directory from slapd.conf
- echo "Regenerate LDAP config directory from slapd.conf"
- rm -Rf /etc/ldap/slapd.d
- mkdir /etc/ldap/slapd.d
- slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/ 2>&1
- chown -R openldap:openldap /etc/ldap/slapd.d/
+ echo "Import the database using slapadd"
+ slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif"
+ chown -R openldap:openldap /var/lib/ldap 2>&1
fi
echo "Running slapdindex"
@@ -157,6 +151,9 @@ case "$1" in
init)
do_init_regen
;;
+ apply_config)
+ do_post_regen /etc/ldap/slapd.ldif
+ ;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
diff --git a/data/hooks/conf_regen/12-metronome b/data/hooks/conf_regen/12-metronome
index 7e8c7eb0c..31d11555a 100755
--- a/data/hooks/conf_regen/12-metronome
+++ b/data/hooks/conf_regen/12-metronome
@@ -57,6 +57,9 @@ do_post_regen() {
done
# fix some permissions
+
+ # metronome should be in ssl-cert group to let it access SSL certificates
+ usermod -aG ssl-cert metronome
chown -R metronome: /var/lib/metronome/
chown -R metronome: /etc/metronome/conf.d/
diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx
index 4924b6f91..a7574b070 100755
--- a/data/hooks/conf_regen/15-nginx
+++ b/data/hooks/conf_regen/15-nginx
@@ -26,6 +26,9 @@ do_init_regen() {
ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc"
ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf"
+ mkdir -p $nginx_conf_dir/default.d/
+ cp "redirect_to_admin.conf" $nginx_conf_dir/default.d/
+
# Restart nginx if conf looks good, otherwise display error and exit unhappy
nginx -t 2>/dev/null || { nginx -t; exit 1; }
systemctl restart nginx || { journalctl --no-pager --lines=10 -u nginx >&2; exit 1; }
@@ -77,6 +80,8 @@ do_pre_regen() {
done
ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf"
+ mkdir -p $nginx_conf_dir/default.d/
+ cp "redirect_to_admin.conf" $nginx_conf_dir/default.d/
# remove old domain conf files
conf_files=$(ls -1 /etc/nginx/conf.d \
diff --git a/data/hooks/conf_regen/31-rspamd b/data/hooks/conf_regen/31-rspamd
index 861549e27..6da4af643 100755
--- a/data/hooks/conf_regen/31-rspamd
+++ b/data/hooks/conf_regen/31-rspamd
@@ -42,6 +42,8 @@ do_post_regen() {
chown _rspamd /etc/dkim/*.mail.key
chmod 400 /etc/dkim/*.mail.key
+ [ ! -e /var/log/rspamd ] || chown _rspamd:_rspamd /var/log/rspamd
+
regen_conf_files=$1
[ -z "$regen_conf_files" ] && exit 0
diff --git a/data/hooks/conf_regen/34-mysql b/data/hooks/conf_regen/34-mysql
index 43f9fdde1..ac2395f34 100755
--- a/data/hooks/conf_regen/34-mysql
+++ b/data/hooks/conf_regen/34-mysql
@@ -15,6 +15,18 @@ do_pre_regen() {
do_post_regen() {
regen_conf_files=$1
+ # mysql is supposed to be an alias to mariadb... but in some weird case is not
+ # c.f. https://forum.yunohost.org/t/mysql-ne-fonctionne-pas/11661
+ # Playing with enable/disable allows to recreate the proper symlinks.
+ if [ ! -e /etc/systemd/system/mysql.service ]
+ then
+ systemctl stop mysql -q
+ systemctl disable mysql -q
+ systemctl disable mariadb -q
+ systemctl enable mariadb -q
+ systemctl is-active mariadb -q || systemctl start mariadb
+ fi
+
if [ ! -f /etc/yunohost/mysql ]; then
# ensure that mysql is running
diff --git a/data/hooks/conf_regen/40-glances b/data/hooks/conf_regen/40-glances
deleted file mode 100755
index 70b8f4b5a..000000000
--- a/data/hooks/conf_regen/40-glances
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-
-set -e
-
-do_pre_regen() {
- pending_dir=$1
-
- cd /usr/share/yunohost/templates/glances
-
- install -D -m 644 glances.default "${pending_dir}/etc/default/glances"
-}
-
-do_post_regen() {
- regen_conf_files=$1
-
- [[ -z "$regen_conf_files" ]] \
- || service glances restart
-}
-
-FORCE=${2:-0}
-DRY_RUN=${3:-0}
-
-case "$1" in
- pre)
- do_pre_regen $4
- ;;
- post)
- do_post_regen $4
- ;;
- *)
- echo "hook called with unknown argument \`$1'" >&2
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/data/hooks/conf_regen/43-dnsmasq b/data/hooks/conf_regen/43-dnsmasq
index 8a2985f34..75d74b09c 100755
--- a/data/hooks/conf_regen/43-dnsmasq
+++ b/data/hooks/conf_regen/43-dnsmasq
@@ -64,8 +64,21 @@ do_post_regen() {
systemctl restart resolvconf
fi
- [[ -z "$regen_conf_files" ]] \
- || service dnsmasq restart
+ # Some stupid things like rabbitmq-server used by onlyoffice won't work if
+ # the *short* hostname doesn't exists in /etc/hosts -_-
+ short_hostname=$(hostname -s)
+ grep -q "127.0.0.1.*$short_hostname" /etc/hosts || echo -e "\n127.0.0.1\t$short_hostname" >>/etc/hosts
+
+ [[ -n "$regen_conf_files" ]] || return
+
+ # Remove / disable services likely to conflict with dnsmasq
+ for SERVICE in systemd-resolved bind9
+ do
+ systemctl is-enabled $SERVICE &>/dev/null && systemctl disable $SERVICE 2>/dev/null
+ systemctl is-active $SERVICE &>/dev/null && systemctl stop $SERVICE
+ done
+
+ systemctl restart dnsmasq
}
FORCE=${2:-0}
diff --git a/data/hooks/diagnosis/00-basesystem.py b/data/hooks/diagnosis/00-basesystem.py
index 51926924a..ec802c870 100644
--- a/data/hooks/diagnosis/00-basesystem.py
+++ b/data/hooks/diagnosis/00-basesystem.py
@@ -1,9 +1,11 @@
#!/usr/bin/env python
import os
+import json
+import subprocess
from moulinette.utils.process import check_output
-from moulinette.utils.filesystem import read_file
+from moulinette.utils.filesystem import read_file, read_json, write_to_json
from yunohost.diagnosis import Diagnoser
from yunohost.utils.packages import ynh_packages_version
@@ -32,7 +34,7 @@ class BaseSystemDiagnoser(Diagnoser):
# Also possibly the board name
if os.path.exists("/proc/device-tree/model"):
- model = read_file('/proc/device-tree/model').strip()
+ model = read_file('/proc/device-tree/model').strip().replace('\x00', '')
hardware["data"]["model"] = model
hardware["details"] = ["diagnosis_basesystem_hardware_board"]
@@ -74,5 +76,75 @@ class BaseSystemDiagnoser(Diagnoser):
details=ynh_version_details)
+ 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"]
+ )
+
+ 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 BaseSystemDiagnoser(args, env, loggers).diagnose()
diff --git a/data/hooks/diagnosis/10-ip.py b/data/hooks/diagnosis/10-ip.py
index fe4993935..b18b4f435 100644
--- a/data/hooks/diagnosis/10-ip.py
+++ b/data/hooks/diagnosis/10-ip.py
@@ -108,7 +108,7 @@ class IPDiagnoser(Diagnoser):
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")
+ routes = check_output("ip -%s route show table all" % protocol).split("\n")
def is_default_route(r):
# Typically the default route starts with "default"
diff --git a/data/hooks/diagnosis/12-dnsrecords.py b/data/hooks/diagnosis/12-dnsrecords.py
index 560127bb0..91dec7006 100644
--- a/data/hooks/diagnosis/12-dnsrecords.py
+++ b/data/hooks/diagnosis/12-dnsrecords.py
@@ -12,9 +12,7 @@ from yunohost.utils.network import dig
from yunohost.diagnosis import Diagnoser
from yunohost.domain import domain_list, _build_dns_conf, _get_maindomain
-# We put here domains we know has dyndns provider, but that are not yet
-# registered in the public suffix list
-PENDING_SUFFIX_LIST = ['ynh.fr', 'netlib.re']
+YNH_DYNDNS_DOMAINS = ['nohost.me', 'noho.st', 'ynh.fr']
class DNSRecordsDiagnoser(Diagnoser):
@@ -38,7 +36,7 @@ class DNSRecordsDiagnoser(Diagnoser):
psl = PublicSuffixList()
domains_from_registrar = [psl.get_public_suffix(domain) for domain in all_domains]
domains_from_registrar = [domain for domain in domains_from_registrar if "." in domain]
- domains_from_registrar = set(domains_from_registrar) - set(PENDING_SUFFIX_LIST)
+ domains_from_registrar = set(domains_from_registrar) - set(YNH_DYNDNS_DOMAINS + ["netlib.re"])
for report in self.check_expiration_date(domains_from_registrar):
yield report
@@ -100,7 +98,13 @@ class DNSRecordsDiagnoser(Diagnoser):
summary=summary)
if discrepancies:
- output["details"] = ["diagnosis_dns_point_to_doc"] + discrepancies
+ # For ynh-managed domains (nohost.me etc...), tell people to try to "yunohost dyndns update --force"
+ if any(domain.endswith(ynh_dyndns_domain) for ynh_dyndns_domain in YNH_DYNDNS_DOMAINS):
+ output["details"] = ["diagnosis_dns_try_dyndns_update_force"]
+ # Otherwise point to the documentation
+ else:
+ output["details"] = ["diagnosis_dns_point_to_doc"]
+ output["details"] += discrepancies
yield output
diff --git a/data/hooks/diagnosis/14-ports.py b/data/hooks/diagnosis/14-ports.py
index bd68c60d6..38f6e0089 100644
--- a/data/hooks/diagnosis/14-ports.py
+++ b/data/hooks/diagnosis/14-ports.py
@@ -87,7 +87,7 @@ class PortsDiagnoser(Diagnoser):
# 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", []))
+ return any(record["data"].get("AAAA:@") in ["OK", "WRONG"] for record in dnsrecords.get("items", []))
if failed == 4 or ipv6_is_important():
yield dict(meta={"port": port},
diff --git a/data/hooks/diagnosis/24-mail.py b/data/hooks/diagnosis/24-mail.py
index bc159c3b7..a483e676d 100644
--- a/data/hooks/diagnosis/24-mail.py
+++ b/data/hooks/diagnosis/24-mail.py
@@ -126,7 +126,7 @@ class MailDiagnoser(Diagnoser):
query += '.ip6.arpa'
# Do the DNS Query
- status, value = dig(query, 'PTR')
+ status, value = dig(query, 'PTR', resolvers="force_external")
if status == "nok":
yield dict(meta={"test": "mail_fcrdns", "ipversion": ipversion},
data={"ip": ip, "ehlo_domain": self.ehlo_domain},
diff --git a/data/hooks/diagnosis/30-services.py b/data/hooks/diagnosis/30-services.py
index 6217d89d3..d0fe50ae9 100644
--- a/data/hooks/diagnosis/30-services.py
+++ b/data/hooks/diagnosis/30-services.py
@@ -21,7 +21,7 @@ class ServicesDiagnoser(Diagnoser):
data={"status": result["status"], "configuration": result["configuration"]})
if result["status"] != "running":
- item["status"] = "ERROR"
+ item["status"] = "ERROR" if result["status"] != "unknown" else "WARNING"
item["summary"] = "diagnosis_services_bad_status"
item["details"] = ["diagnosis_services_bad_status_tip"]
diff --git a/data/hooks/diagnosis/50-systemresources.py b/data/hooks/diagnosis/50-systemresources.py
index 5007f8ede..682fb897f 100644
--- a/data/hooks/diagnosis/50-systemresources.py
+++ b/data/hooks/diagnosis/50-systemresources.py
@@ -45,14 +45,15 @@ class SystemResourcesDiagnoser(Diagnoser):
item = dict(meta={"test": "swap"},
data={"total": human_size(swap.total), "recommended": "512 MiB"})
if swap.total <= 1 * MB:
- item["status"] = "ERROR"
+ item["status"] = "INFO"
item["summary"] = "diagnosis_swap_none"
- elif swap.total < 500 * MB:
- item["status"] = "WARNING"
+ elif swap.total < 450 * MB:
+ item["status"] = "INFO"
item["summary"] = "diagnosis_swap_notsomuch"
else:
item["status"] = "SUCCESS"
item["summary"] = "diagnosis_swap_ok"
+ item["details"] = ["diagnosis_swap_tip"]
yield item
# FIXME : add a check that swapiness is low if swap is on a sdcard...
@@ -61,40 +62,36 @@ class SystemResourcesDiagnoser(Diagnoser):
# Disks usage
#
- disk_partitions = psutil.disk_partitions()
+ disk_partitions = sorted(psutil.disk_partitions(), key=lambda k: k.mountpoint)
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)
+ free_percent = 100 - round_(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})
+ data={"device": device,
+ # N.B.: we do not use usage.total because we want
+ # to take into account the 5% security margin
+ # correctly (c.f. the doc of psutil ...)
+ "total": human_size(usage.used+usage.free),
+ "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"
+ # We have an additional absolute constrain on / and /var because
+ # system partitions are critical, having them full may prevent
+ # upgrades etc...
+ if free_percent < 2.5 or (mountpoint in ["/", "/var"] and usage.free < 1 * GB):
+ item["status"] = "ERROR"
+ item["summary"] = "diagnosis_diskusage_verylow"
+ elif free_percent < 5 or (mountpoint in ["/", "/var"] and usage.free < 2 * GB):
+ item["status"] = "WARNING"
+ item["summary"] = "diagnosis_diskusage_low"
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"
+ item["status"] = "SUCCESS"
+ item["summary"] = "diagnosis_diskusage_ok"
yield item
diff --git a/data/hooks/diagnosis/90-security.py b/data/hooks/diagnosis/90-security.py
deleted file mode 100644
index d281042b0..000000000
--- a/data/hooks/diagnosis/90-security.py
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/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()
diff --git a/data/hooks/restore/05-conf_ldap b/data/hooks/restore/05-conf_ldap
index 74093136d..bdc1ebcdf 100644
--- a/data/hooks/restore/05-conf_ldap
+++ b/data/hooks/restore/05-conf_ldap
@@ -39,6 +39,9 @@ else
# Restore the configuration
mv /etc/ldap/slapd.d "$TMPDIR"
mkdir -p /etc/ldap/slapd.d
+ cp -a "${backup_dir}/ldap.conf" /etc/ldap/ldap.conf
+ cp -a "${backup_dir}/slapd.ldif" /etc/ldap/slapd.ldif
+ # Legacy thing but we need it to force the regen-conf in case of it exist
cp -a "${backup_dir}/slapd.conf" /etc/ldap/slapd.conf
slapadd -F /etc/ldap/slapd.d -b cn=config \
-l "${backup_dir}/cn=config.master.ldif" \
diff --git a/data/hooks/restore/11-conf_ynh_mysql b/data/hooks/restore/11-conf_ynh_mysql
index f54641d6f..11353425a 100644
--- a/data/hooks/restore/11-conf_ynh_mysql
+++ b/data/hooks/restore/11-conf_ynh_mysql
@@ -1,42 +1,5 @@
-backup_dir="$1/conf/ynh/mysql"
-MYSQL_PKG="$(dpkg --list | sed -ne 's/^ii \(mariadb-server-[[:digit:].]\+\) .*$/\1/p')"
+# We don't backup/restore mysql password anymore
+# c.f. https://github.com/YunoHost/yunohost/pull/912
-. /usr/share/yunohost/helpers
-
-# ensure that mysql is running
-service mysql status >/dev/null 2>&1 \
- || service mysql start
-
-# retrieve current and new password
-[ -f /etc/yunohost/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
-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" \
- "applications, and is going to reset the MySQL root password." \
- "You can find this new password in /etc/yunohost/mysql." >&2
-
- # set new password with debconf
- 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
- dpkg-reconfigure -freadline -u "$MYSQL_PKG" 2>&1
-}
-
-# store new root password
-echo "$new_pwd" | tee /etc/yunohost/mysql
-chmod 400 /etc/yunohost/mysql
-
-# reload the grant tables
-mysqladmin -s -u root -p"$new_pwd" reload
+# This is a dummy empty file as a workaround for
+# https://github.com/YunoHost/issues/issues/1553 until it is fixed
diff --git a/data/other/ffdhe2048.pem b/data/other/ffdhe2048.pem
new file mode 100644
index 000000000..9b182b720
--- /dev/null
+++ b/data/other/ffdhe2048.pem
@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
+87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
+YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
+7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
+ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
+-----END DH PARAMETERS-----
diff --git a/data/templates/dovecot/dovecot.conf b/data/templates/dovecot/dovecot.conf
index 8fc0e75ae..d64b15356 100644
--- a/data/templates/dovecot/dovecot.conf
+++ b/data/templates/dovecot/dovecot.conf
@@ -14,18 +14,16 @@ 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
+# generated 2020-05-02, Mozilla Guideline v5.4, Dovecot 2.3.4.1, OpenSSL 1.1.1d, intermediate configuration
+# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.4.1&config=intermediate&openssl=1.1.1d&guideline=5.4
ssl = required
ssl_cert = openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048
-#ssl_dhparam /etc/ssl/private/dh2048.pem;
+# Pre-defined FFDHE group (RFC 7919)
+# From https://ssl-config.mozilla.org/ffdhe2048.txt
+# https://security.stackexchange.com/a/149818
+ssl_dhparam /usr/share/yunohost/other/ffdhe2048.pem;
+{% 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 "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 "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";
diff --git a/data/templates/nginx/yunohost_admin.conf b/data/templates/nginx/yunohost_admin.conf
index 3df838c4a..8a7a40231 100644
--- a/data/templates/nginx/yunohost_admin.conf
+++ b/data/templates/nginx/yunohost_admin.conf
@@ -2,13 +2,7 @@ server {
listen 80 default_server;
listen [::]:80 default_server;
- location / {
- return 302 https://$http_host/yunohost/admin;
- }
-
- location /yunohost/admin {
- return 301 https://$http_host$request_uri;
- }
+ include /etc/nginx/conf.d/default.d/*.conf;
}
server {
@@ -22,23 +16,13 @@ server {
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'";
-
- location / {
- return 302 https://$http_host/yunohost/admin;
- }
location /yunohost {
- # Block crawlers bot
- if ($http_user_agent ~ (crawl|Googlebot|Slurp|spider|bingbot|tracker|click|parser|spider|facebookexternalhit) ) {
- return 403;
- }
- # X-Robots-Tag to precise the rules applied.
- add_header X-Robots-Tag "nofollow, noindex, noarchive, nosnippet";
# Redirect most of 404 to maindomain.tld/yunohost/sso
access_by_lua_file /usr/share/ssowat/access.lua;
}
include /etc/nginx/conf.d/yunohost_admin.conf.inc;
include /etc/nginx/conf.d/yunohost_api.conf.inc;
+ include /etc/nginx/conf.d/default.d/*.conf;
}
diff --git a/data/templates/nslcd/nslcd.conf b/data/templates/nslcd/nslcd.conf
index 091ecb7cc..7cfe73e07 100644
--- a/data/templates/nslcd/nslcd.conf
+++ b/data/templates/nslcd/nslcd.conf
@@ -15,6 +15,18 @@ base dc=yunohost,dc=org
# The LDAP protocol version to use.
#ldap_version 3
+# The DN to bind with for normal lookups.
+#binddn cn=annonymous,dc=example,dc=net
+#bindpw secret
+
+# The DN used for password modifications by root.
+#rootpwmoddn cn=admin,dc=example,dc=com
+
+# SSL options
+#ssl off
+#tls_reqcert never
+tls_cacertfile /etc/ssl/certs/ca-certificates.crt
+
# The search scope.
#scope sub
diff --git a/data/templates/nsswitch/nsswitch.conf b/data/templates/nsswitch/nsswitch.conf
index b55e01b02..8f46e4f5d 100644
--- a/data/templates/nsswitch/nsswitch.conf
+++ b/data/templates/nsswitch/nsswitch.conf
@@ -1,12 +1,8 @@
# /etc/nsswitch.conf
-#
-# Example configuration of GNU Name Service Switch functionality.
-# If you have the `glibc-doc-reference' and `info' packages installed, try:
-# `info libc "Name Service Switch"' for information about this file.
-passwd: compat ldap
-group: compat ldap
-shadow: compat ldap
+passwd: files systemd ldap
+group: files systemd ldap
+shadow: files ldap
gshadow: files
hosts: files myhostname mdns4_minimal [NOTFOUND=return] dns
diff --git a/data/templates/postfix/main.cf b/data/templates/postfix/main.cf
index 61cbfa2e6..18e457a76 100644
--- a/data/templates/postfix/main.cf
+++ b/data/templates/postfix/main.cf
@@ -170,7 +170,7 @@ smtpd_milters = inet:localhost:11332
milter_default_action = accept
# Avoid to send simultaneously too many emails
-smtp_destination_concurrency_limit = 1
+smtp_destination_concurrency_limit = 2
default_destination_rate_delay = 5s
# Avoid email adress scanning
diff --git a/data/templates/slapd/mailserver.schema b/data/templates/slapd/mailserver.ldif
similarity index 79%
rename from data/templates/slapd/mailserver.schema
rename to data/templates/slapd/mailserver.ldif
index 23d0d24bd..849d1d9e1 100644
--- a/data/templates/slapd/mailserver.schema
+++ b/data/templates/slapd/mailserver.ldif
@@ -2,58 +2,62 @@
## Version 0.1
## Adrien Beudin
+dn: cn=mailserver,cn=schema,cn=config
+objectClass: olcSchemaConfig
+cn: mailserver
+#
# Attributes
-attributetype ( 1.3.6.1.4.1.40328.1.20.2.1
+olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.1
NAME 'maildrop'
DESC 'Mail addresses where mails are forwarded -- ie forwards'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
-
-attributetype ( 1.3.6.1.4.1.40328.1.20.2.2
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.2
NAME 'mailalias'
DESC 'Mail addresses accepted by this account -- ie aliases'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
-
-attributetype ( 1.3.6.1.4.1.40328.1.20.2.3
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.3
NAME 'mailenable'
DESC 'Mail Account validity'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{8})
-
-attributetype ( 1.3.6.1.4.1.40328.1.20.2.4
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.4
NAME 'mailbox'
DESC 'Mailbox path where mails are delivered'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
-
-attributetype ( 1.3.6.1.4.1.40328.1.20.2.5
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.5
NAME 'virtualdomain'
DESC 'A mail domain name'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
-
-attributetype ( 1.3.6.1.4.1.40328.1.20.2.6
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.6
NAME 'virtualdomaindescription'
DESC 'Virtual domain description'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
-
-attributetype ( 1.3.6.1.4.1.40328.1.20.2.7
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.7
NAME 'mailuserquota'
DESC 'Mailbox quota for a user'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} SINGLE-VALUE )
-
+#
# Mail Account Objectclass
-objectclass ( 1.3.6.1.4.1.40328.1.1.2.1
+olcObjectClasses: ( 1.3.6.1.4.1.40328.1.1.2.1
NAME 'mailAccount'
DESC 'Mail Account'
SUP top
@@ -65,9 +69,9 @@ objectclass ( 1.3.6.1.4.1.40328.1.1.2.1
mailalias $ maildrop $ mailenable $ mailbox $ mailuserquota
)
)
-
+#
# Mail Domain Objectclass
-objectclass ( 1.3.6.1.4.1.40328.1.1.2.2
+olcObjectClasses: ( 1.3.6.1.4.1.40328.1.1.2.2
NAME 'mailDomain'
DESC 'Domain mail entry'
SUP top
@@ -79,9 +83,9 @@ objectclass ( 1.3.6.1.4.1.40328.1.1.2.2
virtualdomaindescription $ mailuserquota
)
)
-
+#
# Mail Group Objectclass
-objectclass ( 1.3.6.1.4.1.40328.1.1.2.3
+olcObjectClasses: ( 1.3.6.1.4.1.40328.1.1.2.3
NAME 'mailGroup' SUP top AUXILIARY
DESC 'Mail Group'
MUST ( mail )
diff --git a/data/templates/slapd/yunohost.schema b/data/templates/slapd/permission.ldif
similarity index 55%
rename from data/templates/slapd/yunohost.schema
rename to data/templates/slapd/permission.ldif
index 7da60a20c..a97249d07 100644
--- a/data/templates/slapd/yunohost.schema
+++ b/data/templates/slapd/permission.ldif
@@ -1,33 +1,35 @@
-#dn: cn=yunohost,cn=schema,cn=config
-#objectClass: olcSchemaConfig
-#cn: yunohost
+# Yunohost schema for group and permission support
+
+dn: cn=yunohost,cn=schema,cn=config
+objectClass: olcSchemaConfig
+cn: yunohost
# ATTRIBUTES
# For Permission
-attributetype ( 1.3.6.1.4.1.17953.9.1.1 NAME 'permission'
+olcAttributeTypes: ( 1.3.6.1.4.1.17953.9.1.1 NAME 'permission'
DESC 'Yunohost permission on user and group side'
SUP distinguishedName )
-attributetype ( 1.3.6.1.4.1.17953.9.1.2 NAME 'groupPermission'
+olcAttributeTypes: ( 1.3.6.1.4.1.17953.9.1.2 NAME 'groupPermission'
DESC 'Yunohost permission for a group on permission side'
SUP distinguishedName )
-attributetype ( 1.3.6.1.4.1.17953.9.1.3 NAME 'inheritPermission'
+olcAttributeTypes: ( 1.3.6.1.4.1.17953.9.1.3 NAME 'inheritPermission'
DESC 'Yunohost permission for user on permission side'
SUP distinguishedName )
-attributetype ( 1.3.6.1.4.1.17953.9.1.4 NAME 'URL'
+olcAttributeTypes: ( 1.3.6.1.4.1.17953.9.1.4 NAME 'URL'
DESC 'Yunohost application URL'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
# OBJECTCLASS
# For Applications
-objectclass ( 1.3.6.1.4.1.17953.9.2.1 NAME 'groupOfNamesYnh'
+olcObjectClasses: ( 1.3.6.1.4.1.17953.9.2.1 NAME 'groupOfNamesYnh'
DESC 'Yunohost user group'
SUP top AUXILIARY
MAY ( member $ businessCategory $ seeAlso $ owner $ ou $ o $ permission ) )
-objectclass ( 1.3.6.1.4.1.17953.9.2.2 NAME 'permissionYnh'
+olcObjectClasses: ( 1.3.6.1.4.1.17953.9.2.2 NAME 'permissionYnh'
DESC 'a Yunohost application'
SUP top AUXILIARY
MUST cn
MAY ( groupPermission $ inheritPermission $ URL ) )
# For User
-objectclass ( 1.3.6.1.4.1.17953.9.2.3 NAME 'userPermissionYnh'
+olcObjectClasses: ( 1.3.6.1.4.1.17953.9.2.3 NAME 'userPermissionYnh'
DESC 'a Yunohost application'
SUP top AUXILIARY
MAY ( permission ) )
diff --git a/data/templates/slapd/slapd.conf b/data/templates/slapd/slapd.conf
deleted file mode 100644
index 0750b43aa..000000000
--- a/data/templates/slapd/slapd.conf
+++ /dev/null
@@ -1,154 +0,0 @@
-# This is the main slapd configuration file. See slapd.conf(5) for more
-# info on the configuration options.
-
-#######################################################################
-# Global Directives:
-
-# Features to permit
-#allow bind_v2
-
-# Schema and objectClass definitions
-include /etc/ldap/schema/core.schema
-include /etc/ldap/schema/cosine.schema
-include /etc/ldap/schema/nis.schema
-include /etc/ldap/schema/inetorgperson.schema
-include /etc/ldap/schema/mailserver.schema
-include /etc/ldap/schema/sudo.schema
-include /etc/ldap/schema/yunohost.schema
-
-# Where the pid file is put. The init.d script
-# will not stop the server if you change this.
-pidfile /var/run/slapd/slapd.pid
-
-# List of arguments that were passed to the server
-argsfile /var/run/slapd/slapd.args
-
-# Read slapd.conf(5) for possible values
-loglevel none
-
-# Hashes to be used in generation of user passwords
-password-hash {SSHA}
-
-# Where the dynamically loaded modules are stored
-modulepath /usr/lib/ldap
-moduleload back_mdb
-moduleload memberof
-
-# The maximum number of entries that is returned for a search operation
-sizelimit 500
-
-# The tool-threads parameter sets the actual amount of cpu's that is used
-# for indexing.
-tool-threads 1
-
-# TLS Support
-TLSCertificateFile /etc/yunohost/certs/yunohost.org/crt.pem
-TLSCertificateKeyFile /etc/yunohost/certs/yunohost.org/key.pem
-
-#######################################################################
-# Specific Backend Directives for mdb:
-# Backend specific directives apply to this backend until another
-# 'backend' directive occurs
-backend mdb
-
-#######################################################################
-# Specific Directives for database #1, of type mdb:
-# Database specific directives apply to this databasse until another
-# 'database' directive occurs
-database mdb
-
-# The base of your directory in database #1
-suffix "dc=yunohost,dc=org"
-
-# rootdn directive for specifying a superuser on the database. This is needed
-# for syncrepl.
-# rootdn "cn=admin,dc=yunohost,dc=org"
-
-# Where the database file are physically stored for database #1
-directory "/var/lib/ldap"
-
-# Indexing options for database #1
-index objectClass eq
-index uid,sudoUser eq,sub
-index entryCSN,entryUUID eq
-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
-
-# Checkpoint the BerkeleyDB database periodically in case of system
-# failure and to speed slapd shutdown.
-checkpoint 512 30
-
-# The userPassword by default can be changed
-# by the entry owning it if they are authenticated.
-# Others should not be able to see it, except the
-# admin entry below
-# These access lines apply to database #1 only
-access to attrs=userPassword,shadowLastChange
- by dn="cn=admin,dc=yunohost,dc=org" write
- by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
- by anonymous auth
- by self write
- by * none
-
-# Personnal information can be changed by the entry
-# owning it if they are authenticated.
-# Others should be able to see it.
-access to attrs=cn,gecos,givenName,mail,maildrop,displayName,sn
- by dn="cn=admin,dc=yunohost,dc=org" write
- by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
- by self write
- by * read
-
-# Ensure read access to the base for things like
-# supportedSASLMechanisms. Without this you may
-# have problems with SASL not knowing what
-# mechanisms are available and the like.
-# Note that this is covered by the 'access to *'
-# ACL below too but if you change that as people
-# are wont to do you'll still need this if you
-# want SASL (and possible other things) to work
-# happily.
-access to dn.base="" by * read
-
-# The admin dn has full write access, everyone else
-# can read everything.
-access to *
- by dn="cn=admin,dc=yunohost,dc=org" write
- by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
- by group/groupOfNames/Member="cn=admin,ou=groups,dc=yunohost,dc=org" write
- by * read
-
-# Configure Memberof Overlay (used for Yunohost permission)
-
-# Link user <-> group
-#dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config
-overlay memberof
-memberof-group-oc groupOfNamesYnh
-memberof-member-ad member
-memberof-memberof-ad memberOf
-memberof-dangling error
-memberof-refint TRUE
-
-# Link permission <-> groupes
-#dn: olcOverlay={1}memberof,olcDatabase={1}mdb,cn=config
-overlay memberof
-memberof-group-oc permissionYnh
-memberof-member-ad groupPermission
-memberof-memberof-ad permission
-memberof-dangling error
-memberof-refint TRUE
-
-# Link permission <-> user
-#dn: olcOverlay={2}memberof,olcDatabase={1}mdb,cn=config
-overlay memberof
-memberof-group-oc permissionYnh
-memberof-member-ad inheritPermission
-memberof-memberof-ad permission
-memberof-dangling error
-memberof-refint TRUE
diff --git a/data/templates/slapd/slapd.ldif b/data/templates/slapd/slapd.ldif
new file mode 100644
index 000000000..d3ed2e053
--- /dev/null
+++ b/data/templates/slapd/slapd.ldif
@@ -0,0 +1,235 @@
+# OpenLDAP server configuration for Yunohost
+# ------------------------------------------
+#
+# Because of the Yunohost's regen-conf mechanism, it is NOT POSSIBLE to
+# edit the config database using an LDAP request.
+#
+# If you wish to edit the config database, you should edit THIS file
+# and update the config database based on this file.
+#
+# Config database customization:
+# 1. Edit this file as you want.
+# 2. Apply your modifications. For this just run this following command in a shell:
+# $ /usr/share/yunohost/hooks/conf_regen/06-slapd apply_config
+#
+# Note that if you customize this file, YunoHost's regen-conf will NOT
+# overwrite this file. But that also means that you should be careful about
+# upgrades, because they may ship important/necessary changes to this
+# configuration that you will have to propagate yourself.
+
+#
+# Main configuration
+#
+dn: cn=config
+objectClass: olcGlobal
+cn: config
+olcConfigFile: /etc/ldap/slapd.conf
+olcConfigDir: /etc/ldap/slapd.d/
+# List of arguments that were passed to the server
+olcArgsFile: /var/run/slapd/slapd.args
+#
+olcAttributeOptions: lang-
+olcAuthzPolicy: none
+olcConcurrency: 0
+olcConnMaxPending: 100
+olcConnMaxPendingAuth: 1000
+olcIdleTimeout: 0
+olcIndexSubstrIfMaxLen: 4
+olcIndexSubstrIfMinLen: 2
+olcIndexSubstrAnyLen: 4
+olcIndexSubstrAnyStep: 2
+olcIndexIntLen: 4
+olcListenerThreads: 1
+olcLocalSSF: 71
+# Read slapd.conf(5) for possible values
+olcLogLevel: None
+# Where the pid file is put. The init.d script
+# will not stop the server if you change this.
+olcPidFile: /var/run/slapd/slapd.pid
+olcReverseLookup: FALSE
+olcThreads: 16
+# TLS Support
+olcTLSCertificateFile: /etc/yunohost/certs/yunohost.org/crt.pem
+olcTLSCertificateKeyFile: /etc/yunohost/certs/yunohost.org/key.pem
+olcTLSVerifyClient: never
+olcTLSProtocolMin: 0.0
+# The tool-threads parameter sets the actual amount of cpu's that is used
+# for indexing.
+olcToolThreads: 1
+structuralObjectClass: olcGlobal
+
+#
+# Schema and objectClass definitions
+#
+dn: cn=schema,cn=config
+objectClass: olcSchemaConfig
+cn: schema
+
+include: file:///etc/ldap/schema/core.ldif
+include: file:///etc/ldap/schema/cosine.ldif
+include: file:///etc/ldap/schema/nis.ldif
+include: file:///etc/ldap/schema/inetorgperson.ldif
+include: file:///etc/ldap/schema/mailserver.ldif
+include: file:///etc/ldap/schema/sudo.ldif
+include: file:///etc/ldap/schema/permission.ldif
+
+#
+# Module management
+#
+dn: cn=module{0},cn=config
+objectClass: olcModuleList
+cn: module{0}
+# Where the dynamically loaded modules are stored
+olcModulePath: /usr/lib/ldap
+olcModuleLoad: {0}back_mdb
+olcModuleLoad: {1}memberof
+structuralObjectClass: olcModuleList
+
+#
+# Frontend database
+#
+dn: olcDatabase={-1}frontend,cn=config
+objectClass: olcDatabaseConfig
+objectClass: olcFrontendConfig
+olcDatabase: {-1}frontend
+olcAddContentAcl: FALSE
+olcLastMod: TRUE
+olcSchemaDN: cn=Subschema
+# Hashes to be used in generation of user passwords
+olcPasswordHash: {SSHA}
+structuralObjectClass: olcDatabaseConfig
+
+#
+# Config database Configuration (#0)
+#
+dn: olcDatabase={0}config,cn=config
+objectClass: olcDatabaseConfig
+olcDatabase: {0}config
+# Give access to root user.
+# This give the possiblity to the admin to customize the LDAP configuration
+olcAccess: {0}to * by * none
+olcAddContentAcl: TRUE
+olcLastMod: TRUE
+olcRootDN: cn=config
+structuralObjectClass: olcDatabaseConfig
+
+#
+# Main database Configuration (#1)
+#
+dn: olcDatabase={1}mdb,cn=config
+objectClass: olcDatabaseConfig
+objectClass: olcMdbConfig
+olcDatabase: {1}mdb
+# The base of your directory in database #1
+olcSuffix: dc=yunohost,dc=org
+#
+# The userPassword by default can be changed
+# by the entry owning it if they are authenticated.
+# Others should not be able to see it, except the
+# admin entry below
+# These access lines apply to database #1 only
+olcAccess: {0}to attrs=userPassword,shadowLastChange
+ by dn.base="cn=admin,dc=yunohost,dc=org" write
+ by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
+ by anonymous auth
+ by self write
+ by * none
+#
+# Personnal information can be changed by the entry
+# owning it if they are authenticated.
+# Others should be able to see it.
+olcAccess: {1}to attrs=cn,gecos,givenName,mail,maildrop,displayName,sn
+ by dn.base="cn=admin,dc=yunohost,dc=org" write
+ by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
+ by self write
+ by * read
+#
+# Ensure read access to the base for things like
+# supportedSASLMechanisms. Without this you may
+# have problems with SASL not knowing what
+# mechanisms are available and the like.
+# Note that this is covered by the 'access to *'
+# ACL below too but if you change that as people
+# are wont to do you'll still need this if you
+# want SASL (and possible other things) to work
+# happily.
+olcAccess: {2}to dn.base=""
+ by * read
+#
+# The admin dn has full write access, everyone else
+# can read everything.
+olcAccess: {3}to *
+ by dn.base="cn=admin,dc=yunohost,dc=org" write
+ by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
+ by group/groupOfNames/member.exact="cn=admin,ou=groups,dc=yunohost,dc=org" write
+ by * read
+#
+olcAddContentAcl: FALSE
+# Save the time that the entry gets modified, for database #1
+olcLastMod: TRUE
+# Where the database file are physically stored for database #1
+olcDbDirectory: /var/lib/ldap
+# Checkpoint the BerkeleyDB database periodically in case of system
+# failure and to speed slapd shutdown.
+olcDbCheckpoint: 512 30
+olcDbNoSync: FALSE
+# Indexing options for database #1
+olcDbIndex: objectClass eq
+olcDbIndex: entryUUID eq
+olcDbIndex: entryCSN eq
+olcDbIndex: cn eq
+olcDbIndex: uid eq,sub
+olcDbIndex: uidNumber eq
+olcDbIndex: gidNumber eq
+olcDbIndex: sudoUser eq,sub
+olcDbIndex: member eq
+olcDbIndex: mail eq
+olcDbIndex: memberUid eq
+olcDbIndex: uniqueMember eq
+olcDbIndex: virtualdomain eq
+olcDbIndex: permission eq
+olcDbMaxSize: 10485760
+structuralObjectClass: olcMdbConfig
+
+#
+# Configure Memberof Overlay (used for Yunohost permission)
+#
+
+# Link user <-> group
+dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcMemberOf
+olcOverlay: {0}memberof
+olcMemberOfDangling: error
+olcMemberOfDanglingError: constraintViolation
+olcMemberOfRefInt: TRUE
+olcMemberOfGroupOC: groupOfNamesYnh
+olcMemberOfMemberAD: member
+olcMemberOfMemberOfAD: memberOf
+structuralObjectClass: olcMemberOf
+
+# Link permission <-> groupes
+dn: olcOverlay={1}memberof,olcDatabase={1}mdb,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcMemberOf
+olcOverlay: {1}memberof
+olcMemberOfDangling: error
+olcMemberOfDanglingError: constraintViolation
+olcMemberOfRefInt: TRUE
+olcMemberOfGroupOC: permissionYnh
+olcMemberOfMemberAD: groupPermission
+olcMemberOfMemberOfAD: permission
+structuralObjectClass: olcMemberOf
+
+# Link permission <-> user
+dn: olcOverlay={2}memberof,olcDatabase={1}mdb,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcMemberOf
+olcOverlay: {2}memberof
+olcMemberOfDangling: error
+olcMemberOfDanglingError: constraintViolation
+olcMemberOfRefInt: TRUE
+olcMemberOfGroupOC: permissionYnh
+olcMemberOfMemberAD: inheritPermission
+olcMemberOfMemberOfAD: permission
+structuralObjectClass: olcMemberOf
diff --git a/data/templates/slapd/sudo.schema b/data/templates/slapd/sudo.ldif
similarity index 72%
rename from data/templates/slapd/sudo.schema
rename to data/templates/slapd/sudo.ldif
index d3e95e00c..a7088c855 100644
--- a/data/templates/slapd/sudo.schema
+++ b/data/templates/slapd/sudo.ldif
@@ -1,76 +1,78 @@
#
# OpenLDAP schema file for Sudo
-# Save as /etc/openldap/schema/sudo.schema
+# Save as /etc/openldap/schema/sudo.ldif
#
-attributetype ( 1.3.6.1.4.1.15953.9.1.1
+dn: cn=sudo,cn=schema,cn=config
+objectClass: olcSchemaConfig
+cn: sudo
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.1
NAME 'sudoUser'
DESC 'User(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
-attributetype ( 1.3.6.1.4.1.15953.9.1.2
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.2
NAME 'sudoHost'
DESC 'Host(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
-attributetype ( 1.3.6.1.4.1.15953.9.1.3
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.3
NAME 'sudoCommand'
DESC 'Command(s) to be executed by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
-attributetype ( 1.3.6.1.4.1.15953.9.1.4
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.4
NAME 'sudoRunAs'
DESC 'User(s) impersonated by sudo (deprecated)'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
-attributetype ( 1.3.6.1.4.1.15953.9.1.5
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.5
NAME 'sudoOption'
DESC 'Options(s) followed by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
-attributetype ( 1.3.6.1.4.1.15953.9.1.6
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.6
NAME 'sudoRunAsUser'
DESC 'User(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
-attributetype ( 1.3.6.1.4.1.15953.9.1.7
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.7
NAME 'sudoRunAsGroup'
DESC 'Group(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
-attributetype ( 1.3.6.1.4.1.15953.9.1.8
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.8
NAME 'sudoNotBefore'
DESC 'Start of time interval for which the entry is valid'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
-
-attributetype ( 1.3.6.1.4.1.15953.9.1.9
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.9
NAME 'sudoNotAfter'
DESC 'End of time interval for which the entry is valid'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
-
-attributeTypes ( 1.3.6.1.4.1.15953.9.1.10
+#
+olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.10
NAME 'sudoOrder'
DESC 'an integer to order the sudoRole entries'
EQUALITY integerMatch
ORDERING integerOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
-
-objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+#
+olcObjectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
DESC 'Sudoer Entries'
MUST ( cn )
- MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $
- description )
+ MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $ description )
)
diff --git a/data/templates/ssh/sshd_config b/data/templates/ssh/sshd_config
index 8dc0e8dfc..bd3efdef3 100644
--- a/data/templates/ssh/sshd_config
+++ b/data/templates/ssh/sshd_config
@@ -27,9 +27,6 @@ HostKey {{ key }}{% endfor %}
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
{% endif %}
-# Use kernel sandbox mechanisms where possible in unprivileged processes
-UsePrivilegeSeparation sandbox
-
# LogLevel VERBOSE logs user's key fingerprint on login.
# Needed to have a clear audit track of which key was using to log in.
SyslogFacility AUTH
diff --git a/data/templates/unattended/02periodic b/data/templates/unattended/02periodic
deleted file mode 100644
index f16105466..000000000
--- a/data/templates/unattended/02periodic
+++ /dev/null
@@ -1,5 +0,0 @@
-# https://wiki.debian.org/UnattendedUpgrades#automatic_call_via_.2Fetc.2Fapt.2Fapt.conf.d.2F02periodic
-APT::Periodic::Enable "1";
-APT::Periodic::Update-Package-Lists "1";
-APT::Periodic::Unattended-Upgrade "1";
-APT::Periodic::Verbose "1";
diff --git a/data/templates/unattended/50unattended-upgrades b/data/templates/unattended/50unattended-upgrades
deleted file mode 100644
index 49b600a3b..000000000
--- a/data/templates/unattended/50unattended-upgrades
+++ /dev/null
@@ -1,36 +0,0 @@
-// Automatically upgrade packages from these (origin, archive) pairs
-Unattended-Upgrade::Allowed-Origins {
- "${distro_id} stable";
- "${distro_id} testing";
- "Depot-Debian testing";
- "${distro_id} ${distro_codename}-security";
- "${distro_id} ${distro_codename}-updates";
-// "${distro_id} ${distro_codename}-proposed-updates";
-};
-
-// List of packages to not update
-Unattended-Upgrade::Package-Blacklist {
-// "vim";
-// "libc6";
-// "libc6-dev";
-// "libc6-i686";
-};
-
-// Send email to this address for problems or packages upgrades
-// If empty or unset then no email is sent, make sure that you
-// have a working mail setup on your system. The package 'mailx'
-// must be installed or anything that provides /usr/bin/mail.
-//Unattended-Upgrade::Mail "root@localhost";
-
-// Do automatic removal of new unused dependencies after the upgrade
-// (equivalent to apt-get autoremove)
-Unattended-Upgrade::Remove-Unused-Dependencies "true";
-
-// Automatically reboot *WITHOUT CONFIRMATION* if a
-// the file /var/run/reboot-required is found after the upgrade
-Unattended-Upgrade::Automatic-Reboot "false";
-
-
-// Use apt bandwidth limit feature, this example limits the download
-// speed to 70kb/sec
-//Acquire::http::Dl-Limit "70";
diff --git a/data/templates/yunohost/services.yml b/data/templates/yunohost/services.yml
index e1dd57e55..73ae9403e 100644
--- a/data/templates/yunohost/services.yml
+++ b/data/templates/yunohost/services.yml
@@ -20,10 +20,9 @@ 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
+php7.3-fpm:
+ log: /var/log/php7.3-fpm.log
+ test_conf: php-fpm7.3 --test
category: web
postfix:
log: [/var/log/mail.log,/var/log/mail.err]
@@ -64,3 +63,5 @@ postgrey: null
spamassassin: null
rmilter: null
php5-fpm: null
+php7.0-fpm: null
+nslcd: null
diff --git a/debian/changelog b/debian/changelog
index c119d57e7..0fc8ef27b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,260 @@
+yunohost (4.0.4) stable; urgency=low
+
+ - Debugging and robustness improvements for postgresql 9.6 -> 11 and xtables->nftables migrations (accc2da4, 59bd7d66, 4cb6f7fd, 4b14402c)
+
+ -- Alexandre Aubin Doc auto-generated by this script on {{data.date}} (Yunohost version {{data.version}})App helpers
+{{ category }}
@@ -70,7 +72,7 @@
- Dude, show me the code ! + Dude, show me the code !
@@ -81,9 +83,6 @@ {% endfor %} {% endfor %} -Generated by this script on {{data.date}} (Yunohost version {{data.version}})
- -