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 ac3584630..eb34de38e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,124 +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
- - 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
+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..d2dbbaa80
--- /dev/null
+++ b/.gitlab/ci/build.gitlab-ci.yml
@@ -0,0 +1,54 @@
+.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:
+ - DEBIAN_DEPENDS=$(cat debian/control | tr "," "\n" | grep -Po "ssowat \([>,=,<]+ .*\)" | grep -Po "[0-9]+([.][0-9]+)?" | head -n 1)
+ - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $DEBIAN_DEPENDS $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
+ - 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:
+ - DEBIAN_DEPENDS=$(cat debian/control | tr "," "\n" | grep -Po "moulinette \([>,=,<]+ .*\)" | grep -Po "[0-9]+([.][0-9]+)?" | head -n 1)
+ - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $DEBIAN_DEPENDS $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
+ - 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..1df4fc4b9
--- /dev/null
+++ b/.gitlab/ci/install.gitlab-ci.yml
@@ -0,0 +1,29 @@
+.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
+ - 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..8db1ee756
--- /dev/null
+++ b/.gitlab/ci/lint.gitlab-ci.yml
@@ -0,0 +1,43 @@
+########################################
+# LINTER
+########################################
+# later we must fix lint and format-check jobs and remove "allow_failure"
+
+lint27:
+ stage: lint
+ image: "before-install"
+ needs: []
+ allow_failure: true
+ script:
+ - tox -e py27-lint
+
+lint37:
+ stage: lint
+ image: "before-install"
+ needs: []
+ allow_failure: true
+ script:
+ - tox -e py37-lint
+
+invalidcode27:
+ stage: lint
+ image: "before-install"
+ needs: []
+ script:
+ - tox -e py27-invalidcode
+
+invalidcode37:
+ stage: lint
+ image: "before-install"
+ allow_failure: true
+ needs: []
+ script:
+ - tox -e py37-invalidcode
+
+format-check:
+ stage: lint
+ image: "before-install"
+ needs: []
+ allow_failure: true
+ script:
+ - tox -e py37-black
diff --git a/.gitlab/ci/test.gitlab-ci.yml b/.gitlab/ci/test.gitlab-ci.yml
new file mode 100644
index 000000000..ef21731f3
--- /dev/null
+++ b/.gitlab/ci/test.gitlab-ci.yml
@@ -0,0 +1,120 @@
+.install_debs: &install_debs
+ - 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:
+ - python -m 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:
+ - python -m pytest tests
+
+test-apps:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_apps.py
+
+test-appscatalog:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_appscatalog.py
+
+test-appurl:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_appurl.py
+
+test-apps-arguments-parsing:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_apps_arguments_parsing.py
+
+test-backuprestore:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_backuprestore.py
+
+test-changeurl:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_changeurl.py
+
+test-permission:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_permission.py
+
+test-settings:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_settings.py
+
+test-user-group:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_user-group.py
+
+test-regenconf:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_regenconf.py
+
+test-service:
+ extends: .test-stage
+ script:
+ - cd src/yunohost
+ - python -m pytest tests/test_service.py
diff --git a/.travis.yml b/.travis.yml
index 8674d4d03..9a0f40674 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,12 +2,18 @@ language: python
matrix:
allow_failures:
- - env: TOXENV=lint
+ - env: TOXENV=py27-lint
+ - env: TOXENV=py37-lint
+ - env: TOXENV=py37-invalidcode
include:
- python: 2.7
- env: TOXENV=py27
+ env: TOXENV=py27-lint
- python: 2.7
- env: TOXENV=lint
+ env: TOXENV=py27-invalidcode
+ - python: 3.7
+ env: TOXENV=py37-lint
+ - python: 3.7
+ env: TOXENV=py37-invalidcode
install:
- pip install tox
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 a748e4533..195220938 100644
--- a/data/actionsmap/yunohost.yml
+++ b/data/actionsmap/yunohost.yml
@@ -99,13 +99,7 @@ user:
- "pattern_lastname"
-m:
full: --mail
- help: Main unique email address
- extra:
- ask: ask_email
- required: True
- pattern: &pattern_email
- - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$
- - "pattern_email"
+ help: (Deprecated, see --domain) Main unique email address
-p:
full: --password
help: User password
@@ -116,6 +110,13 @@ user:
- !!str ^.{3,}$
- "pattern_password"
comment: good_practices_about_user_password
+ -d:
+ full: --domain
+ help: Domain for the email address and xmpp account
+ extra:
+ pattern: &pattern_domain
+ - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$
+ - "pattern_domain"
-q:
full: --mailbox-quota
help: Mailbox size quota
@@ -157,7 +158,9 @@ user:
-m:
full: --mail
extra:
- pattern: *pattern_email
+ pattern: &pattern_email
+ - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$
+ - "pattern_email"
-p:
full: --change-password
help: New password to set
@@ -419,9 +422,7 @@ domain:
domain:
help: Domain name to add
extra:
- pattern: &pattern_domain
- - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$
- - "pattern_domain"
+ pattern: *pattern_domain
-d:
full: --dyndns
help: Subscribe to the DynDNS service
@@ -660,6 +661,10 @@ app:
-f:
full: --file
help: Folder or tarball for upgrade
+ -F:
+ full: --force
+ help: Force the update, even though the app is up to date
+ action: store_true
### app_change_url()
change-url:
@@ -847,10 +852,6 @@ backup:
-o:
full: --output-directory
help: Output directory for the backup
- -r:
- full: --no-compress
- help: Do not create an archive file
- action: store_true
--methods:
help: List of backup methods to apply (copy or tar by default)
nargs: "*"
@@ -996,7 +997,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:
@@ -1632,17 +1632,19 @@ log:
action_help: List logs
api: GET /logs
arguments:
- category:
- help: Log category to display (default operations), could be operation, history, package, system, access, service or app
- nargs: "*"
-l:
full: --limit
- help: Maximum number of logs
+ help: Maximum number of operations to list (default to 50)
type: int
+ default: 50
-d:
full: --with-details
help: Show additional infos (e.g. operation success) but may significantly increase command time. Consider using --limit in combination with this.
action: store_true
+ -s:
+ full: --with-suboperations
+ help: Include metadata about operations that are not the main operation but are sub-operations triggered by another ongoing operation... (e.g. initializing groups/permissions when installing an app)
+ action: store_true
### log_display()
display:
@@ -1663,6 +1665,10 @@ log:
full: --filter-irrelevant
help: Do not show some lines deemed not relevant (like set +x or helper argument parsing)
action: store_true
+ -s:
+ full: --with-suboperations
+ help: Include metadata about sub-operations of this operation... (e.g. initializing groups/permissions when installing an app)
+ action: store_true
#############################
@@ -1692,6 +1698,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
@@ -1706,6 +1715,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/actionsmap/yunohost_completion.py b/data/actionsmap/yunohost_completion.py
index 45d15f16c..f4fee30ca 100644
--- a/data/actionsmap/yunohost_completion.py
+++ b/data/actionsmap/yunohost_completion.py
@@ -15,15 +15,17 @@ THIS_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
ACTIONSMAP_FILE = THIS_SCRIPT_DIR + '/yunohost.yml'
BASH_COMPLETION_FILE = THIS_SCRIPT_DIR + '/../bash-completion.d/yunohost'
+
def get_dict_actions(OPTION_SUBTREE, category):
ACTIONS = [action for action in OPTION_SUBTREE[category]["actions"].keys()
- if not action.startswith('_')]
+ if not action.startswith('_')]
ACTIONS_STR = '{}'.format(' '.join(ACTIONS))
- DICT = { "actions_str": ACTIONS_STR }
+ DICT = {"actions_str": ACTIONS_STR}
return DICT
+
with open(ACTIONSMAP_FILE, 'r') as stream:
# Getting the dictionary containning what actions are possible per category
@@ -40,10 +42,10 @@ with open(ACTIONSMAP_FILE, 'r') as stream:
ACTIONS_DICT[category]["subcategories_str"] = ""
if "subcategories" in OPTION_TREE[category].keys():
- SUBCATEGORIES = [ subcategory for subcategory in OPTION_TREE[category]["subcategories"].keys() ]
+ SUBCATEGORIES = [subcategory for subcategory in OPTION_TREE[category]["subcategories"].keys()]
SUBCATEGORIES_STR = '{}'.format(' '.join(SUBCATEGORIES))
-
+
ACTIONS_DICT[category]["subcategories_str"] = SUBCATEGORIES_STR
for subcategory in SUBCATEGORIES:
diff --git a/data/helpers b/data/helpers
index a56a6a57a..5ec562f61 100644
--- a/data/helpers
+++ b/data/helpers
@@ -1,7 +1,8 @@
# -*- shell-script -*-
-# TODO : use --regex to validate against a namespace
+set +x
for helper in $(run-parts --list /usr/share/yunohost/helpers.d 2>/dev/null) ; do
[ -r $helper ] && . $helper || true
done
+set -x
diff --git a/data/helpers.d/apt b/data/helpers.d/apt
index 3b4b199d0..1a4a9f74a 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,11 @@ ynh_install_app_dependencies () {
# And we have packages from sury installed (7.0.33-10+weirdshiftafter instead of 7.0.33-0 on debian)
if dpkg --list | grep "php7.0" | grep --quiet --invert-match "7.0.33-0+deb9"
then
- # And sury ain't already installed
- if ! grep --line-number --recursive --quiet "sury" /etc/apt/sources.list*
+ # And sury ain't already in sources.lists
+ if ! grep --recursive --quiet "^ *deb.*sury" /etc/apt/sources.list*
then
# Re-add sury
- ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version
-
- # 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
+ 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
fi
fi
fi
@@ -329,8 +329,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]
@@ -463,8 +461,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/logging b/data/helpers.d/logging
index d5f4f5eec..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
@@ -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 3ad0c400f..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
@@ -125,7 +126,10 @@ ynh_install_nodejs () {
test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n
# If n is not previously setup, install it
- if ! test $(n --version > /dev/null 2>&1)
+ if ! $n_install_dir/bin/n --version > /dev/null 2>&1
+ then
+ ynh_install_n
+ elif dpkg --compare-versions "$($n_install_dir/bin/n --version)" lt $n_version
then
ynh_install_n
fi
diff --git a/data/helpers.d/php b/data/helpers.d/php
index e8de6d9ff..489c448a8 100644
--- a/data/helpers.d/php
+++ b/data/helpers.d/php
@@ -1,37 +1,37 @@
#!/bin/bash
-readonly YNH_DEFAULT_PHP_VERSION=7.0
-# Declare the actual php version to use.
-# A packager willing to use another version of php can override the variable into its _common.sh.
+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}
-# Create a dedicated php-fpm config
+# Create a dedicated PHP-FPM config
#
# usage 1: ynh_add_fpm_config [--phpversion=7.X] [--use_template] [--package=packages] [--dedicated_service]
-# | arg: -v, --phpversion= - Version of php to use.
+# | arg: -v, --phpversion= - Version of PHP to use.
# | arg: -t, --use_template - Use this helper in template mode.
-# | arg: -p, --package= - Additionnal php packages to install
-# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one.
+# | arg: -p, --package= - Additionnal PHP packages to install
+# | arg: -d, --dedicated_service - Use a dedicated PHP-FPM service instead of the common one.
#
# -----------------------------------------------------------------------------
#
# usage 2: ynh_add_fpm_config [--phpversion=7.X] --usage=usage --footprint=footprint [--package=packages] [--dedicated_service]
-# | arg: -v, --phpversion= - Version of php to use.
+# | arg: -v, --phpversion= - Version of PHP to use.
# | arg: -f, --footprint= - Memory footprint of the service (low/medium/high).
-# low - Less than 20Mb of ram by pool.
-# medium - Between 20Mb and 40Mb of ram by pool.
-# high - More than 40Mb of ram by pool.
-# Or specify exactly the footprint, the load of the service as Mb by pool instead of having a standard value.
+# low - Less than 20 MB of RAM by pool.
+# medium - Between 20 MB and 40 MB of RAM by pool.
+# high - More than 40 MB of RAM by pool.
+# Or specify exactly the footprint, the load of the service as MB by pool instead of having a standard value.
# To have this value, use the following command and stress the service.
# watch -n0.5 ps -o user,cmd,%cpu,rss -u APP
#
# | arg: -u, --usage= - Expected usage of the service (low/medium/high).
-# low - Personal usage, behind the sso.
+# low - Personal usage, behind the SSO.
# medium - Low usage, few people or/and publicly accessible.
# high - High usage, frequently visited website.
#
-# | arg: -p, --package= - Additionnal php packages to install for a specific version of php
-# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one.
+# | arg: -p, --package= - Additionnal PHP packages to install for a specific version of PHP
+# | arg: -d, --dedicated_service - Use a dedicated PHP-FPM service instead of the common one.
#
#
# The footprint of the service will be used to defined the maximum footprint we can allow, which is half the maximum RAM.
@@ -85,7 +85,7 @@ ynh_add_fpm_config () {
# Set the default PHP-FPM version by default
phpversion="${phpversion:-$YNH_PHP_VERSION}"
- # If the requested php version is not the default version for YunoHost
+ # If the requested PHP version is not the default version for YunoHost
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ]
then
# If the argument --package is used, add the packages to ynh_install_php to install them from sury
@@ -95,7 +95,7 @@ ynh_add_fpm_config () {
else
local additionnal_packages=""
fi
- # Install this specific version of php.
+ # Install this specific version of PHP.
ynh_install_php --phpversion="$phpversion" "$additionnal_packages"
elif [ -n "$package" ]
then
@@ -118,7 +118,7 @@ ynh_add_fpm_config () {
fpm_service="php5-fpm"
fi
- # Create the directory for fpm pools
+ # Create the directory for FPM pools
mkdir --parents "$fpm_config_dir/pool.d"
ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir"
@@ -127,7 +127,7 @@ ynh_add_fpm_config () {
ynh_app_setting_set --app=$app --key=phpversion --value=$phpversion
finalphpconf="$fpm_config_dir/pool.d/$app.conf"
- # Migrate from mutual php service to dedicated one.
+ # Migrate from mutual PHP service to dedicated one.
if [ $dedicated_service -eq 1 ]
then
local old_fpm_config_dir="/etc/php/$phpversion/fpm"
@@ -137,9 +137,9 @@ ynh_add_fpm_config () {
ynh_print_info --message="Migrate to a dedicated php-fpm service for $app."
# Create a backup of the old file before migration
ynh_backup_if_checksum_is_different --file="$old_fpm_config_dir/pool.d/$app.conf"
- # Remove the old php config file
+ # Remove the old PHP config file
ynh_secure_remove --file="$old_fpm_config_dir/pool.d/$app.conf"
- # Reload php to release the socket and allow the dedicated service to use it
+ # Reload PHP to release the socket and allow the dedicated service to use it
ynh_systemd_action --service_name=php${phpversion}-fpm --action=reload
fi
fi
@@ -148,21 +148,27 @@ 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"
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="$finalphpconf"
else
- # Usage 2, generate a php-fpm config file with ynh_get_scalable_phpfpm
+ # Usage 2, generate a PHP-FPM config file with ynh_get_scalable_phpfpm
# Store settings
ynh_app_setting_set --app=$app --key=fpm_footprint --value=$footprint
ynh_app_setting_set --app=$app --key=fpm_usage --value=$usage
- # Define the values to use for the configuration of php.
+ # Define the values to use for the configuration of PHP.
ynh_get_scalable_phpfpm --usage=$usage --footprint=$footprint
# Copy the default file
@@ -175,7 +181,7 @@ ynh_add_fpm_config () {
ynh_replace_string --match_string="^group = .*" --replace_string="group = $app" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*chdir = .*" --replace_string="chdir = $final_path" --target_file="$finalphpconf"
- # Configure fpm children
+ # Configure FPM children
ynh_replace_string --match_string=".*pm = .*" --replace_string="pm = $php_pm" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_children = .*" --replace_string="pm.max_children = $php_max_children" --target_file="$finalphpconf"
ynh_replace_string --match_string=".*pm.max_requests = .*" --replace_string="pm.max_requests = 500" --target_file="$finalphpconf"
@@ -232,7 +238,7 @@ ynh_add_fpm_config () {
ynh_replace_string --match_string="^[; ]*syslog.ident *=.*" --replace_string="syslog.ident = php-fpm-$app" --target_file="$globalphpconf"
ynh_replace_string --match_string="^[; ]*include *=.*" --replace_string="include = $finalphpconf" --target_file="$globalphpconf"
- # Create a config for a dedicated php-fpm service for the app
+ # Create a config for a dedicated PHP-FPM service for the app
echo "[Unit]
Description=PHP $phpversion FastCGI Process Manager for $app
After=network.target
@@ -247,7 +253,7 @@ ExecReload=/bin/kill -USR2 \$MAINPID
WantedBy=multi-user.target
" > ../conf/$fpm_service
- # Create this dedicated php-fpm service
+ # Create this dedicated PHP-FPM service
ynh_add_systemd_config --service=$fpm_service --template=$fpm_service
# Integrate the service in YunoHost admin panel
yunohost service add $fpm_service --log /var/log/php/fpm-php.$app.log --log_type file --description "Php-fpm dedicated to $app"
@@ -256,12 +262,12 @@ WantedBy=multi-user.target
# Restart the service, as this service is either stopped or only for this app
ynh_systemd_action --service_name=$fpm_service --action=restart
else
- # Reload php, to not impact other parts of the system using php
+ # Reload PHP, to not impact other parts of the system using PHP
ynh_systemd_action --service_name=$fpm_service --action=reload
fi
}
-# Remove the dedicated php-fpm config
+# Remove the dedicated PHP-FPM config
#
# usage: ynh_remove_fpm_config
#
@@ -271,13 +277,13 @@ ynh_remove_fpm_config () {
local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service)
local dedicated_service=$(ynh_app_setting_get --app=$app --key=fpm_dedicated_service)
dedicated_service=${dedicated_service:-0}
- # Get the version of php used by this app
+ # Get the version of PHP used by this app
local phpversion=$(ynh_app_setting_get $app phpversion)
# Assume default PHP-FPM version by default
phpversion="${phpversion:-$YNH_DEFAULT_PHP_VERSION}"
- # Assume default php files if not set
+ # Assume default PHP files if not set
if [ -z "$fpm_config_dir" ]
then
fpm_config_dir="/etc/php/$YNH_DEFAULT_PHP_VERSION/fpm"
@@ -286,34 +292,37 @@ ynh_remove_fpm_config () {
if [ $dedicated_service -eq 1 ]
then
- # Remove the dedicated service php-fpm service for the app
+ # Remove the dedicated service PHP-FPM service for the app
ynh_remove_systemd_config --service=$fpm_service
- # Remove the global php-fpm conf
+ # Remove the global PHP-FPM conf
ynh_secure_remove --file="$fpm_config_dir/php-fpm-$app.conf"
- # Remove the service from the list of services known by Yunohost
+ # Remove the service from the list of services known by YunoHost
yunohost service remove $fpm_service
elif ynh_package_is_installed --package="php${phpversion}-fpm"; then
ynh_systemd_action --service_name=$fpm_service --action=reload
fi
ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf"
- ynh_exec_warn_less ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini"
+ if [ -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 the PHP version used is not the default version for YunoHost
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ]
then
- # Remove this specific version of php
+ # Remove this specific version of PHP
ynh_remove_php
fi
}
-# Install another version of php.
+# Install another version of PHP.
#
# [internal]
#
# usage: ynh_install_php --phpversion=phpversion [--package=packages]
-# | arg: -v, --phpversion= - Version of php to install.
-# | arg: -p, --package= - Additionnal php packages to install
+# | arg: -v, --phpversion= - Version of PHP to install.
+# | arg: -p, --package= - Additionnal PHP packages to install
#
# Requires YunoHost version 3.8.1 or higher.
ynh_install_php () {
@@ -340,30 +349,26 @@ ynh_install_php () {
# Do not add twice the same line
if ! grep --quiet "$YNH_APP_INSTANCE_NAME:" "/etc/php/ynh_app_version"
then
- # Store the ID of this app and the version of php requested for it
+ # Store the ID of this app and the version of PHP requested for it
echo "$YNH_APP_INSTANCE_NAME:$phpversion" | tee --append "/etc/php/ynh_app_version"
fi
# Add an extra repository for those packages
- ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version
+ 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.
+ # Install PHP-FPM first, otherwise PHP will install apache as a dependency.
ynh_add_app_dependencies --package="php${phpversion}-fpm"
ynh_add_app_dependencies --package="php$phpversion php${phpversion}-common $package"
- # Set the default php version back as the default version for php-cli.
+ # Set the default PHP version back as the default version for php-cli.
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
- # Pin this extra repository after packages are installed to prevent sury of doing shit
- ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version
- ynh_pin_repo --package="php${YNH_DEFAULT_PHP_VERSION}*" --pin="origin \"packages.sury.org\"" --priority=600 --name=extra_php_version --append
-
# Advertise service in admin panel
yunohost service add php${phpversion}-fpm --log "/var/log/php${phpversion}-fpm.log"
}
-# Remove the specific version of php used by the app.
+# Remove the specific version of PHP used by the app.
#
# [internal]
#
@@ -371,7 +376,7 @@ ynh_install_php () {
#
# Requires YunoHost version 3.8.1 or higher.
ynh_remove_php () {
- # Get the version of php used by this app
+ # Get the version of PHP used by this app
local phpversion=$(ynh_app_setting_get $app phpversion)
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ] || [ -z "$phpversion" ]
@@ -389,7 +394,7 @@ ynh_remove_php () {
# Remove the line for this app
sed --in-place "/$YNH_APP_INSTANCE_NAME:$phpversion/d" "/etc/php/ynh_app_version"
- # If no other app uses this version of php, remove it.
+ # If no other app uses this version of PHP, remove it.
if ! grep --quiet "$phpversion" "/etc/php/ynh_app_version"
then
# Remove the service from the admin panel
@@ -397,26 +402,26 @@ ynh_remove_php () {
yunohost service remove php${phpversion}-fpm
fi
- # Purge php dependencies for this version.
+ # Purge PHP dependencies for this version.
ynh_package_autopurge "php$phpversion php${phpversion}-fpm php${phpversion}-common"
fi
}
-# Define the values to configure php-fpm
+# Define the values to configure PHP-FPM
#
# [internal]
#
# usage: ynh_get_scalable_phpfpm --usage=usage --footprint=footprint [--print]
# | arg: -f, --footprint= - Memory footprint of the service (low/medium/high).
-# low - Less than 20Mb of ram by pool.
-# medium - Between 20Mb and 40Mb of ram by pool.
-# high - More than 40Mb of ram by pool.
-# Or specify exactly the footprint, the load of the service as Mb by pool instead of having a standard value.
+# low - Less than 20 MB of RAM by pool.
+# medium - Between 20 MB and 40 MB of RAM by pool.
+# high - More than 40 MB of RAM by pool.
+# Or specify exactly the footprint, the load of the service as MB by pool instead of having a standard value.
# To have this value, use the following command and stress the service.
# watch -n0.5 ps -o user,cmd,%cpu,rss -u APP
#
# | arg: -u, --usage= - Expected usage of the service (low/medium/high).
-# low - Personal usage, behind the sso.
+# low - Personal usage, behind the SSO.
# medium - Low usage, few people or/and publicly accessible.
# high - High usage, frequently visited website.
#
@@ -487,7 +492,7 @@ ynh_get_scalable_phpfpm () {
# Define pm.max_children
# The value of pm.max_children is the total amount of ram divide by 2 and divide again by the footprint of a pool for this app.
- # So if php-fpm start the maximum of children, it won't exceed half of the ram.
+ # So if PHP-FPM start the maximum of children, it won't exceed half of the ram.
php_max_children=$(( $max_ram / 2 / $footprint ))
# If process manager is set as static, use half less children.
# Used as static, there's always as many children as the value of pm.max_children
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 9c2f40618..95f8ddc52 100644
--- a/data/helpers.d/utils
+++ b/data/helpers.d/utils
@@ -144,8 +144,13 @@ ynh_setup_source () {
then # Use the local source file if it is present
cp $local_src $src_filename
else # If not, download the source
+ # NB. we have to declare the var as local first,
+ # otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
+ # because local always return 0 ...
+ local out
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
- local out=`wget --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1` || ynh_print_err --message="$out"
+ out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
+ || ynh_die --message="$out"
fi
# Check the control sum
@@ -431,9 +436,8 @@ ynh_app_upstream_version () {
local manifest
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
- manifest="${manifest:-../manifest.json}"
- version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
+ version_key=$YNH_APP_MANIFEST_VERSION
echo "${version_key/~ynh*/}"
}
@@ -456,9 +460,8 @@ ynh_app_package_version () {
local manifest
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
- manifest="${manifest:-../manifest.json}"
- version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
+ version_key=$YNH_APP_MANIFEST_VERSION
echo "${version_key/*~ynh/}"
}
@@ -511,3 +514,49 @@ ynh_check_app_version_changed () {
fi
echo $return_value
}
+
+# Compare the current package version against another version given as an argument.
+# This is really useful when we need to do some actions only for some old package versions.
+#
+# example: ynh_compare_current_package_version --comparison lt --version 2.3.2~ynh1
+# This example will check if the installed version is lower than (lt) the version 2.3.2~ynh1
+#
+# Generally you might probably use it as follow in the upgrade script
+#
+# if ynh_compare_current_package_version --comparaison lt --version 2.3.2~ynh1
+# then
+# # Do something that is needed for the package version older than 2.3.2~ynh1
+# fi
+#
+# usage: ynh_compare_current_package_version --comparison lt|le|eq|ne|ge|gt
+# | arg: --comparison - Comparison type. Could be : lt (lower than), le (lower or equal),
+# | eq (equal), ne (not equal), ge (greater or equal), gt (greater than)
+# | arg: --version - The version to compare. Need to be a version in the yunohost package version type (like 2.3.1~ynh4)
+#
+# Return 0 if the evaluation is true. 1 if false.
+#
+# Requires YunoHost version 3.8.0 or higher.
+ynh_compare_current_package_version() {
+ local legacy_args=cv
+ declare -Ar args_array=( [c]=comparison= [v]=version= )
+ local version
+ local comparison
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ local current_version=$YNH_APP_CURRENT_VERSION
+
+ # Check the syntax of the versions
+ if [[ ! $version =~ '~ynh' ]] || [[ ! $current_version =~ '~ynh' ]]
+ then
+ ynh_die "Invalid argument for version."
+ fi
+
+ # Check validity of the comparator
+ if [[ ! $comparison =~ (lt|le|eq|ne|ge|gt) ]]; then
+ ynh_die "Invialid comparator must be : lt, le, eq, ne, ge, gt"
+ fi
+
+ # Return the return value of dpkg --compare-versions
+ dpkg --compare-versions $current_version $comparison $version
+}
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/10-apt b/data/hooks/conf_regen/10-apt
new file mode 100755
index 000000000..4ce838e4c
--- /dev/null
+++ b/data/hooks/conf_regen/10-apt
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+set -e
+
+do_pre_regen() {
+ pending_dir=$1
+
+ mkdir --parents "${pending_dir}/etc/apt/preferences.d"
+
+ for package 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
+ echo "
+Package: $package
+Pin: origin \"packages.sury.org\"
+Pin-Priority: -1" >> "/etc/apt/preferences.d/extra_php_version"
+ done
+}
+
+do_post_regen() {
+ regen_conf_files=$1
+}
+
+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/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..87ed722a7 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 -R _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..e7b0531e8 100755
--- a/data/hooks/conf_regen/43-dnsmasq
+++ b/data/hooks/conf_regen/43-dnsmasq
@@ -27,14 +27,13 @@ do_pre_regen() {
ipv6=$(curl -s -6 https://ip6.yunohost.org 2>/dev/null || true)
ynh_validate_ip6 "$ipv6" || ipv6=''
+ export ipv4
+ export ipv6
+
# add domain conf files
for domain in $YNH_DOMAINS; do
- cat domain.tpl \
- | sed "s/{{ domain }}/${domain}/g" \
- | sed "s/{{ ip }}/${ipv4}/g" \
- > "${dnsmasq_dir}/${domain}"
- [[ -n $ipv6 ]] \
- && echo "address=/${domain}/${ipv6}" >> "${dnsmasq_dir}/${domain}"
+ export domain
+ ynh_render_template "domain.tpl" "${dnsmasq_dir}/${domain}"
done
# remove old domain conf files
@@ -64,8 +63,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..8773f8b53 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"]
@@ -61,10 +63,10 @@ class BaseSystemDiagnoser(Diagnoser):
ynh_core_version = ynh_packages["yunohost"]["version"]
consistent_versions = all(infos["version"][:3] == ynh_core_version[:3] for infos in ynh_packages.values())
ynh_version_details = [("diagnosis_basesystem_ynh_single_version",
- {"package":package,
+ {"package": package,
"version": infos["version"],
"repo": infos["repo"]}
- )
+ )
for package, infos in ynh_packages.items()]
yield dict(meta={"test": "ynh_versions"},
@@ -73,6 +75,75 @@ class BaseSystemDiagnoser(Diagnoser):
summary="diagnosis_basesystem_ynh_main_version" if consistent_versions else "diagnosis_basesystem_ynh_inconsistent_versions",
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..b74b3907e 100644
--- a/data/hooks/diagnosis/14-ports.py
+++ b/data/hooks/diagnosis/14-ports.py
@@ -3,9 +3,9 @@
import os
from yunohost.diagnosis import Diagnoser
-from yunohost.utils.error import YunohostError
from yunohost.service import _get_services
+
class PortsDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
@@ -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/21-web.py b/data/hooks/diagnosis/21-web.py
index c1f6d912a..94665a6e6 100644
--- a/data/hooks/diagnosis/21-web.py
+++ b/data/hooks/diagnosis/21-web.py
@@ -8,7 +8,6 @@ from moulinette.utils.filesystem import read_file
from yunohost.diagnosis import Diagnoser
from yunohost.domain import domain_list
-from yunohost.utils.error import YunohostError
DIAGNOSIS_SERVER = "diagnosis.yunohost.org"
diff --git a/data/hooks/diagnosis/24-mail.py b/data/hooks/diagnosis/24-mail.py
index bc159c3b7..fca9345ab 100644
--- a/data/hooks/diagnosis/24-mail.py
+++ b/data/hooks/diagnosis/24-mail.py
@@ -47,7 +47,6 @@ class MailDiagnoser(Diagnoser):
status="SUCCESS",
summary="diagnosis_mail_" + name + "_ok")
-
def check_outgoing_port_25(self):
"""
Check outgoing port 25 is open and not blocked by router
@@ -64,7 +63,6 @@ class MailDiagnoser(Diagnoser):
details=["diagnosis_mail_outgoing_port_25_blocked_details",
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn"])
-
def check_ehlo(self):
"""
Check the server is reachable from outside and it's the good one
@@ -99,7 +97,6 @@ class MailDiagnoser(Diagnoser):
summary="diagnosis_mail_ehlo_wrong",
details=["diagnosis_mail_ehlo_wrong_details"])
-
def check_fcrdns(self):
"""
Check the reverse DNS is well defined by doing a Forward-confirmed
@@ -126,7 +123,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},
@@ -148,7 +145,6 @@ class MailDiagnoser(Diagnoser):
summary="diagnosis_mail_fcrdns_different_from_ehlo_domain",
details=details)
-
def check_blacklist(self):
"""
Check with dig onto blacklist DNS server
@@ -225,7 +221,6 @@ class MailDiagnoser(Diagnoser):
status="SUCCESS",
summary="diagnosis_mail_queue_ok")
-
def get_ips_checked(self):
outgoing_ipversions = []
outgoing_ips = []
@@ -245,5 +240,6 @@ class MailDiagnoser(Diagnoser):
outgoing_ips.append(global_ipv6)
return (outgoing_ipversions, outgoing_ips)
+
def main(args, env, loggers):
return MailDiagnoser(args, env, loggers).diagnose()
diff --git a/data/hooks/diagnosis/30-services.py b/data/hooks/diagnosis/30-services.py
index 6217d89d3..562d48d6d 100644
--- a/data/hooks/diagnosis/30-services.py
+++ b/data/hooks/diagnosis/30-services.py
@@ -5,6 +5,7 @@ import os
from yunohost.diagnosis import Diagnoser
from yunohost.service import service_status
+
class ServicesDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
@@ -21,7 +22,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"]
@@ -36,5 +37,6 @@ class ServicesDiagnoser(Diagnoser):
yield item
+
def main(args, env, loggers):
return ServicesDiagnoser(args, env, loggers).diagnose()
diff --git a/data/hooks/diagnosis/50-systemresources.py b/data/hooks/diagnosis/50-systemresources.py
index 66d27866a..f0fac4974 100644
--- a/data/hooks/diagnosis/50-systemresources.py
+++ b/data/hooks/diagnosis/50-systemresources.py
@@ -1,9 +1,13 @@
#!/usr/bin/env python
import os
import psutil
+import subprocess
+import datetime
+import re
from yunohost.diagnosis import Diagnoser
+
class SystemResourcesDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
@@ -13,7 +17,7 @@ class SystemResourcesDiagnoser(Diagnoser):
def run(self):
MB = 1024**2
- GB = MB*1024
+ GB = MB * 1024
#
# RAM
@@ -45,14 +49,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...
@@ -75,7 +80,7 @@ class SystemResourcesDiagnoser(Diagnoser):
# 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),
+ "total": human_size(usage.used + usage.free),
"free": human_size(usage.free),
"free_percent": free_percent})
@@ -92,13 +97,54 @@ class SystemResourcesDiagnoser(Diagnoser):
item["status"] = "SUCCESS"
item["summary"] = "diagnosis_diskusage_ok"
-
yield item
+ #
+ # Recent kills by oom_reaper
+ #
+
+ kills_count = self.recent_kills_by_oom_reaper()
+ if kills_count:
+ kills_summary = "\n".join(["%s (x%s)" % (proc, count) for proc, count in kills_count])
+
+ yield dict(meta={"test": "oom_reaper"},
+ status="WARNING",
+ summary="diagnosis_processes_killed_by_oom_reaper",
+ data={"kills_summary": kills_summary})
+
+ def recent_kills_by_oom_reaper(self):
+ if not os.path.exists("/var/log/kern.log"):
+ return []
+
+ def analyzed_kern_log():
+
+ cmd = 'tail -n 10000 /var/log/kern.log | grep "oom_reaper: reaped process" || true'
+ out = subprocess.check_output(cmd, shell=True).strip()
+ lines = out.split("\n") if out else []
+
+ now = datetime.datetime.now()
+
+ for line in reversed(lines):
+ # Lines look like :
+ # Aug 25 18:48:21 yolo kernel: [ 9623.613667] oom_reaper: reaped process 11509 (uwsgi), now anon-rss:0kB, file-rss:0kB, shmem-rss:328kB
+ date_str = str(now.year) + " " + " ".join(line.split()[:3])
+ date = datetime.datetime.strptime(date_str, '%Y %b %d %H:%M:%S')
+ diff = now - date
+ if diff.days >= 1:
+ break
+ process_killed = re.search(r"\(.*\)", line).group().strip("()")
+ yield process_killed
+
+ processes = list(analyzed_kern_log())
+ kills_count = [(p, len([p_ for p_ in processes if p_ == p])) for p in set(processes)]
+ kills_count = sorted(kills_count, key=lambda p: p[1], reverse=True)
+
+ return kills_count
+
def human_size(bytes_):
# Adapted from https://stackoverflow.com/a/1094933
- for unit in ['','ki','Mi','Gi','Ti','Pi','Ei','Zi']:
+ for unit in ['', 'ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
if abs(bytes_) < 1024.0:
return "%s %sB" % (round_(bytes_), unit)
bytes_ /= 1024.0
@@ -113,5 +159,6 @@ def round_(n):
n = int(round(n))
return n
+
def main(args, env, loggers):
return SystemResourcesDiagnoser(args, env, loggers).diagnose()
diff --git a/data/hooks/diagnosis/70-regenconf.py b/data/hooks/diagnosis/70-regenconf.py
index 0dff71b5b..396f64a0f 100644
--- a/data/hooks/diagnosis/70-regenconf.py
+++ b/data/hooks/diagnosis/70-regenconf.py
@@ -2,7 +2,6 @@
import os
-import subprocess
from yunohost.diagnosis import Diagnoser
from yunohost.regenconf import _get_regenconf_infos, _calculate_hash
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/dnsmasq/domain.tpl b/data/templates/dnsmasq/domain.tpl
index bbfc2864c..f4c8d6c4c 100644
--- a/data/templates/dnsmasq/domain.tpl
+++ b/data/templates/dnsmasq/domain.tpl
@@ -1,4 +1,9 @@
-address=/{{ domain }}/{{ ip }}
+address=/{{ domain }}/{{ ipv4 }}
+address=/xmpp-upload.{{ domain }}/{{ ipv4 }}
+{% if ipv6 %}
+address=/{{ domain }}/{{ ipv6 }}
+address=/xmpp-upload.{{ domain }}/{{ ipv6 }}
+{% endif %}
txt-record={{ domain }},"v=spf1 mx a -all"
mx-host={{ domain }},{{ domain }},5
srv-host=_xmpp-client._tcp.{{ domain }},{{ domain }},5222,0,5
diff --git a/data/templates/dovecot/dovecot.conf b/data/templates/dovecot/dovecot.conf
index 8fc0e75ae..ee8511f83 100644
--- a/data/templates/dovecot/dovecot.conf
+++ b/data/templates/dovecot/dovecot.conf
@@ -14,18 +14,19 @@ 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-08-18, Mozilla Guideline v5.6, Dovecot 2.3.4, OpenSSL 1.1.1d, intermediate configuration
+# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.4&config=intermediate&openssl=1.1.1d&guideline=5.6
ssl = required
ssl_cert = /path/to/dhparam
+ssl_dh = 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/server.tpl.conf b/data/templates/nginx/server.tpl.conf
index 29af9f532..8bd689a92 100644
--- a/data/templates/nginx/server.tpl.conf
+++ b/data/templates/nginx/server.tpl.conf
@@ -14,7 +14,7 @@ server {
include /etc/nginx/conf.d/{{ domain }}.d/*.conf;
- location /yunohost/admin {
+ location /yunohost {
return 301 https://$http_host$request_uri;
}
@@ -60,6 +60,7 @@ server {
include /etc/nginx/conf.d/{{ domain }}.d/*.conf;
+ include /etc/nginx/conf.d/yunohost_sso.conf.inc;
include /etc/nginx/conf.d/yunohost_admin.conf.inc;
include /etc/nginx/conf.d/yunohost_api.conf.inc;
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 4d27498c4..61aa27211 100644
--- a/data/templates/postfix/main.cf
+++ b/data/templates/postfix/main.cf
@@ -19,34 +19,35 @@ readme_directory = no
# -- TLS for incoming connections
###############################################################################
-# generated 2020-04-03, Mozilla Guideline v5.4, Postfix 3.1.14, OpenSSL 1.1.0l, intermediate configuration
-# https://ssl-config.mozilla.org/#server=postfix&version=3.1.14&config=intermediate&openssl=1.1.0l&guideline=5.4
-
-# (No modern conf support until we're on buster...)
-# {% if compatibility == "intermediate" %} {% else %} {% endif %}
-
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/yunohost/certs/{{ main_domain }}/crt.pem
smtpd_tls_key_file = /etc/yunohost/certs/{{ main_domain }}/key.pem
+
+{% if compatibility == "intermediate" %}
+# generated 2020-08-18, Mozilla Guideline v5.6, Postfix 3.4.14, OpenSSL 1.1.1d, intermediate configuration
+# https://ssl-config.mozilla.org/#server=postfix&version=3.4.14&config=intermediate&openssl=1.1.1d&guideline=5.6
+
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
-# smtpd_tls_mandatory_ciphers = medium # (c.f. below)
+smtpd_tls_mandatory_ciphers = medium
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam.pem
# not actually 1024 bits, this applies to all DHE >= 1024 bits
-# smtpd_tls_dh1024_param_file = /path/to/dhparam.pem
+smtpd_tls_dh1024_param_file = /usr/share/yunohost/other/ffdhe2048.pem
+
+tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
+{% else %}
+# generated 2020-08-18, Mozilla Guideline v5.6, Postfix 3.4.14, OpenSSL 1.1.1d, modern configuration
+# https://ssl-config.mozilla.org/#server=postfix&version=3.4.14&config=modern&openssl=1.1.1d&guideline=5.6
+
+smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2
+smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2
+{% endif %}
-# This custom medium cipherlist recommendation only works if we have a DH ... which we don't, c.f. https://github.com/YunoHost/issues/issues/93
-# On the other hand, the postfix doc strongly discourage tweaking this list ... So whatever, let's keep the mandatory_ciphers to high like we did before applying the Mozilla recommendation ...
-#tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
tls_preempt_cipherlist = no
-
-# Custom Yunohost stuff ... because we can't use the recommendation about medium cipher list ...
-smtpd_tls_mandatory_ciphers=high
-smtpd_tls_eecdh_grade = ultra
###############################################################################
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_loglevel=1
@@ -178,7 +179,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..d6ba6d553 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,303 @@
+yunohost (4.1.0) testing; urgency=low
+
+ - Tmp bump of the version number to fix CI (c.f. Breaks: yunohost(<<4.1) in moulinette)
+
+yunohost (4.0.7) stable; urgency=low
+
+ - [fix] Require explicitly php7.3-foo packages because in some cases Sury's php7.4- packages are installed and php7.3-fpm doesn't get installed ... (1288159a)
+ - [fix] Make sure app nginx confs do not prevent the loading of /yunohost/sso (#1044)
+
+ Thanks to all contributors <3 ! (Kayou, ljf)
+
+ -- 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}})
- -