mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Compare commits
85 commits
debian/12.
...
dev
Author | SHA1 | Date | |
---|---|---|---|
|
a5049a8a13 | ||
|
6e84e3532a | ||
|
917cf251fb | ||
|
8a5f2808a1 | ||
68f35831e7 | |||
b91e9dd8f4 | |||
38b39ebaea | |||
ef17082768 | |||
e3ddb1dc4d | |||
|
5b37936d11 | ||
|
e82d20aa7b | ||
|
aff885e6b7 | ||
|
7a04462ccd | ||
|
606e246ec4 | ||
|
e3e8b903c7 | ||
|
488f563b45 | ||
|
3d4804be68 | ||
|
d4f774ad72 | ||
|
d8ab3e68a9 | ||
|
71b50549f5 | ||
|
a40874c305 | ||
|
9223d30a83 | ||
|
5ad9962757 | ||
|
4dfcc13a3f | ||
|
e11b61f49e | ||
|
243a34d2d5 | ||
|
ca2572d00b | ||
|
518c3bbbe2 | ||
|
9517b26c63 | ||
|
a6785d34bc | ||
|
7c79060467 | ||
|
007c13ce42 | ||
|
2102242a61 | ||
|
c409888a4b | ||
|
c14ebc8be4 | ||
|
9b0553580b | ||
|
bc2ed45e9d | ||
|
a76cd05e87 | ||
|
eb14e404d6 | ||
|
aae24614c4 | ||
|
51787a2f8b | ||
|
c5953b5420 | ||
|
4afff118e4 | ||
|
6113fde48a | ||
|
b734e2ea89 | ||
|
0a44d7cea4 | ||
|
5d3280c0fd | ||
|
8dc521a528 | ||
|
2e70143da2 | ||
|
3095496fe9 | ||
|
586d1c7f63 | ||
|
d63c61e0df | ||
|
4248b27b26 | ||
|
0f662d069c | ||
|
7ca710685e | ||
|
31d10079c7 | ||
|
980777ebf1 | ||
|
436826abf9 | ||
|
477fa63f46 | ||
|
9a6f7dac3b | ||
|
498006cab6 | ||
|
2f186b6f7f | ||
|
5708776df6 | ||
|
abdbb7efcd | ||
|
658ef88e47 | ||
|
4d5cc62540 | ||
|
f88e4cacdf | ||
|
36b9188aec | ||
|
c104dc6449 | ||
|
938e400865 | ||
|
de9980f31e | ||
|
f02d4a4376 | ||
|
92f4a605b8 | ||
|
df320a44cf | ||
|
6733526bee | ||
|
d0df3caed4 | ||
|
9083a5cc3d | ||
|
764fe6a7ba | ||
|
200f0272d5 | ||
|
9915559c40 | ||
|
760256f85d | ||
|
684c3d9b2c | ||
|
90c4034908 | ||
|
3deffdbd57 | ||
|
bc30805c7d |
192 changed files with 7286 additions and 7229 deletions
|
@ -1,10 +1,11 @@
|
|||
---
|
||||
stages:
|
||||
- lint
|
||||
- build
|
||||
- install
|
||||
- test
|
||||
- bot
|
||||
- lint
|
||||
- doc
|
||||
- translation
|
||||
|
||||
default:
|
||||
tags:
|
||||
|
@ -37,12 +38,17 @@ workflow:
|
|||
- if: $CI_COMMIT_TAG # For tags
|
||||
- if: $CI_COMMIT_REF_NAME == "ci-format-$CI_DEFAULT_BRANCH" # Ignore black formatting branch created by the CI
|
||||
when: never
|
||||
- if: $CI_COMMIT_REF_NAME == "actions/black" # Ignore black formatting branch created by the CI
|
||||
when: never
|
||||
- if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push" # If it's not the default branch and if it's a push, then do not trigger a build
|
||||
when: never
|
||||
- when: always
|
||||
|
||||
variables:
|
||||
YNH_BUILD_DIR: "/ynh-build"
|
||||
GIT_CLONE_PATH: '$CI_BUILDS_DIR/$CI_COMMIT_SHA/$CI_JOB_ID'
|
||||
YNH_SOURCE: "https://github.com/yunohost"
|
||||
YNH_DEBIAN: "bullseye"
|
||||
YNH_SKIP_DIAGNOSIS_DURING_UPGRADE: "true"
|
||||
|
||||
include:
|
||||
- template: Code-Quality.gitlab-ci.yml
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
generate-helpers-doc:
|
||||
stage: bot
|
||||
image: "before-install"
|
||||
needs: []
|
||||
before_script:
|
||||
- git config --global user.email "yunohost@yunohost.org"
|
||||
- git config --global user.name "$GITHUB_USER"
|
||||
script:
|
||||
- cd doc
|
||||
- python3 generate_helper_doc.py 2
|
||||
- python3 generate_helper_doc.py 2.1
|
||||
- python3 generate_resource_doc.py > resources.md
|
||||
- python3 generate_configpanel_and_formoptions_doc.py > forms.md
|
||||
- hub clone https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/doc.git doc_repo
|
||||
- cp helpers.v2.md doc_repo/pages/06.contribute/10.packaging_apps/20.scripts/10.helpers/packaging_app_scripts_helpers.md
|
||||
- cp helpers.v2.1.md doc_repo/pages/06.contribute/10.packaging_apps/20.scripts/12.helpers21/packaging_app_scripts_helpers_v21.md
|
||||
- cp resources.md doc_repo/pages/06.contribute/10.packaging_apps/10.manifest/10.appresources/packaging_app_manifest_resources.md
|
||||
- cp forms doc_repo/pages/06.contribute/15.dev/03.forms/forms.md
|
||||
- cd doc_repo
|
||||
# replace ${CI_COMMIT_REF_NAME} with ${CI_COMMIT_TAG} ?
|
||||
- hub checkout -b "${CI_COMMIT_REF_NAME}"
|
||||
- hub commit -am "[CI] Update app helpers/resources for ${CI_COMMIT_REF_NAME}"
|
||||
- hub pull-request -m "[CI] Update app helpers/resources for ${CI_COMMIT_REF_NAME}" -p # GITHUB_USER and GITHUB_TOKEN registered here https://gitlab.com/yunohost/yunohost/-/settings/ci_cd
|
||||
artifacts:
|
||||
paths:
|
||||
- doc/helpers.md
|
||||
- doc/resources.md
|
||||
only:
|
||||
- tags
|
||||
|
||||
autofix-translated-strings:
|
||||
stage: bot
|
||||
image: "before-install"
|
||||
needs: []
|
||||
before_script:
|
||||
- git config --global user.email "yunohost@yunohost.org"
|
||||
- git config --global user.name "$GITHUB_USER"
|
||||
- hub clone --branch ${CI_COMMIT_REF_NAME} "https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/yunohost.git" github_repo
|
||||
- cd github_repo
|
||||
script:
|
||||
# create a local branch that will overwrite distant one
|
||||
- git checkout -b "ci-autofix-translated-strings-${CI_COMMIT_REF_NAME}" --no-track
|
||||
- python3 maintenance/missing_i18n_keys.py --fix
|
||||
- python3 maintenance/autofix_locale_format.py
|
||||
- '[ $(git diff --ignore-blank-lines --ignore-all-space --ignore-space-at-eol --ignore-cr-at-eol | wc -l) != 0 ] || exit 0' # stop if there is nothing to commit
|
||||
- git commit -am "[CI] Reformat / remove stale translated strings" || true
|
||||
- git push -f origin "ci-autofix-translated-strings-${CI_COMMIT_REF_NAME}":"ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}"
|
||||
- hub pull-request -m "[CI] Reformat / remove stale translated strings" -b Yunohost:$CI_COMMIT_REF_NAME -p || true # GITHUB_USER and GITHUB_TOKEN registered here https://gitlab.com/yunohost/yunohost/-/settings/ci_cd
|
||||
only:
|
||||
variables:
|
||||
- $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
|
||||
changes:
|
||||
- locales/*
|
|
@ -1,27 +1,19 @@
|
|||
.build-stage:
|
||||
stage: build
|
||||
needs:
|
||||
- job: actionsmap
|
||||
- job: invalidcode311
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
variables:
|
||||
YNH_SOURCE: "https://github.com/yunohost"
|
||||
YNH_DEBIAN: "bookworm"
|
||||
YNH_BUILD_DIR: "$GIT_CLONE_PATH/build"
|
||||
before_script:
|
||||
- mkdir -p $YNH_BUILD_DIR
|
||||
- DEBIAN_FRONTEND=noninteractive apt update
|
||||
artifacts:
|
||||
paths:
|
||||
- ./*.deb
|
||||
|
||||
.build_script: &build_script
|
||||
- DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" install devscripts --no-install-recommends
|
||||
- cd $YNH_BUILD_DIR/$PACKAGE
|
||||
- git status || true
|
||||
- git log -n 1 || true
|
||||
- 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."
|
||||
- VERSION_TIMESTAMPED="${VERSION}+$(date +%Y%m%d%H%M)"
|
||||
- dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_TIMESTAMPED}" -D "unstable" --force-distribution "CI build."
|
||||
- debuild --no-lintian -us -uc
|
||||
- cp $YNH_BUILD_DIR/*.deb ${CI_PROJECT_DIR}/
|
||||
- cd ${CI_PROJECT_DIR}
|
||||
|
|
31
.gitlab/ci/doc.gitlab-ci.yml
Normal file
31
.gitlab/ci/doc.gitlab-ci.yml
Normal file
|
@ -0,0 +1,31 @@
|
|||
########################################
|
||||
# DOC
|
||||
########################################
|
||||
|
||||
generate-helpers-doc:
|
||||
stage: doc
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
before_script:
|
||||
- git config --global user.email "yunohost@yunohost.org"
|
||||
- git config --global user.name "$GITHUB_USER"
|
||||
script:
|
||||
- cd doc
|
||||
- python3 generate_helper_doc.py 2
|
||||
- python3 generate_helper_doc.py 2.1
|
||||
- python3 generate_resource_doc.py > resources.md
|
||||
- hub clone https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/doc.git doc_repo
|
||||
- cp helpers.v2.md doc_repo/pages/06.contribute/10.packaging_apps/20.scripts/10.helpers/packaging_app_scripts_helpers.md
|
||||
- cp helpers.v2.1.md doc_repo/pages/06.contribute/10.packaging_apps/20.scripts/12.helpers21/packaging_app_scripts_helpers_v21.md
|
||||
- cp resources.md doc_repo/pages/06.contribute/10.packaging_apps/10.manifest/10.appresources/packaging_app_manifest_resources.md
|
||||
- cd doc_repo
|
||||
# replace ${CI_COMMIT_REF_NAME} with ${CI_COMMIT_TAG} ?
|
||||
- hub checkout -b "${CI_COMMIT_REF_NAME}"
|
||||
- hub commit -am "[CI] Update app helpers/resources for ${CI_COMMIT_REF_NAME}"
|
||||
- hub pull-request -m "[CI] Update app helpers/resources for ${CI_COMMIT_REF_NAME}" -p # GITHUB_USER and GITHUB_TOKEN registered here https://gitlab.com/yunohost/yunohost/-/settings/ci_cd
|
||||
artifacts:
|
||||
paths:
|
||||
- doc/helpers.md
|
||||
- doc/resources.md
|
||||
only:
|
||||
- tags
|
|
@ -14,20 +14,14 @@
|
|||
|
||||
upgrade:
|
||||
extends: .install-stage
|
||||
image: "after-install"
|
||||
image: "core-tests"
|
||||
script:
|
||||
- apt-get update -o Acquire::Retries=3
|
||||
- systemctl restart nginx || journalctl -u nginx -n 50 --no-pager --no-hostname
|
||||
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
|
||||
- systemctl restart nginx || journalctl -u nginx -n 50 --no-pager --no-hostname
|
||||
|
||||
|
||||
install-postinstall:
|
||||
extends: .install-stage
|
||||
image: "before-install"
|
||||
script:
|
||||
- apt-get update -o Acquire::Retries=3
|
||||
- systemctl restart nginx || journalctl -u nginx -n 50 --no-pager --no-hostname
|
||||
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
|
||||
- systemctl restart nginx || journalctl -u nginx -n 50 --no-pager --no-hostname
|
||||
- yunohost tools postinstall -d domain.tld -u syssa -F 'Syssa Mine' -p the_password --ignore-dyndns --force-diskspace
|
||||
|
|
|
@ -3,38 +3,24 @@
|
|||
########################################
|
||||
# later we must fix lint and format-check jobs and remove "allow_failure"
|
||||
|
||||
actionsmap:
|
||||
lint39:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
needs: []
|
||||
script:
|
||||
- python -c 'import yaml; yaml.safe_load(open("share/actionsmap.yml"))'
|
||||
- python -c 'import yaml; yaml.safe_load(open("share/actionsmap-portal.yml"))'
|
||||
|
||||
lint311:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
allow_failure: true
|
||||
script:
|
||||
- tox -e py311-lint
|
||||
- tox -e py39-lint
|
||||
|
||||
invalidcode311:
|
||||
invalidcode39:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
script:
|
||||
- tox -e py311-invalidcode
|
||||
- tox -e py39-invalidcode
|
||||
|
||||
mypy:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
script:
|
||||
- tox -e py311-mypy
|
||||
|
||||
i18n-keys:
|
||||
stage: lint
|
||||
needs: []
|
||||
script:
|
||||
- python3 maintenance/missing_i18n_keys.py --check
|
||||
- tox -e py39-mypy
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
.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 ${CI_PROJECT_DIR}/*.deb
|
||||
|
||||
.test-stage:
|
||||
stage: test
|
||||
image: "after-install"
|
||||
image: "core-tests"
|
||||
variables:
|
||||
PYTEST_ADDOPTS: "--color=yes"
|
||||
before_script:
|
||||
|
@ -26,27 +25,36 @@
|
|||
# TESTS
|
||||
########################################
|
||||
|
||||
#full-tests:
|
||||
# stage: test
|
||||
# image: "before-install"
|
||||
# variables:
|
||||
# PYTEST_ADDOPTS: "--color=yes"
|
||||
# before_script:
|
||||
# - *install_debs
|
||||
# - yunohost tools postinstall -d domain.tld -u syssa -F 'Syssa Mine' -p the_password --ignore-dyndns --force-diskspace
|
||||
# script:
|
||||
# - python3 -m pytest --cov=yunohost tests/ src/tests/ --junitxml=report.xml
|
||||
# needs:
|
||||
# - job: build-yunohost
|
||||
# artifacts: true
|
||||
# - job: build-ssowat
|
||||
# artifacts: true
|
||||
# - job: build-moulinette
|
||||
# artifacts: true
|
||||
# coverage: '/TOTAL.*\s+(\d+%)/'
|
||||
# artifacts:
|
||||
# reports:
|
||||
# junit: report.xml
|
||||
full-tests:
|
||||
stage: test
|
||||
image: "before-install"
|
||||
variables:
|
||||
PYTEST_ADDOPTS: "--color=yes"
|
||||
before_script:
|
||||
- *install_debs
|
||||
- pip install mock pip pyOpenSSL pytest pytest-cov pytest-mock pytest-sugar requests-mock "packaging<22"
|
||||
- yunohost tools postinstall -d domain.tld -u syssa -F 'Syssa Mine' -p the_password --ignore-dyndns --force-diskspace
|
||||
script:
|
||||
- python3 -m pytest --cov=yunohost tests/ src/tests/ --junitxml=report.xml
|
||||
needs:
|
||||
- job: build-yunohost
|
||||
artifacts: true
|
||||
- job: build-ssowat
|
||||
artifacts: true
|
||||
- job: build-moulinette
|
||||
artifacts: true
|
||||
coverage: '/TOTAL.*\s+(\d+%)/'
|
||||
artifacts:
|
||||
reports:
|
||||
junit: report.xml
|
||||
|
||||
test-actionmap:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest tests/test_actionmap.py
|
||||
only:
|
||||
changes:
|
||||
- share/actionsmap.yml
|
||||
|
||||
test-helpers2:
|
||||
extends: .test-stage
|
||||
|
@ -64,134 +72,129 @@ test-domains:
|
|||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_domains.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/domain.py
|
||||
only:
|
||||
changes:
|
||||
- src/domain.py
|
||||
|
||||
test-dns:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_dns.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/dns.py
|
||||
# - src/utils/dns.py
|
||||
only:
|
||||
changes:
|
||||
- src/dns.py
|
||||
- src/utils/dns.py
|
||||
|
||||
test-apps:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_apps.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/app.py
|
||||
only:
|
||||
changes:
|
||||
- src/app.py
|
||||
|
||||
test-appscatalog:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_app_catalog.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/app_calalog.py
|
||||
only:
|
||||
changes:
|
||||
- src/app_calalog.py
|
||||
|
||||
test-appurl:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_appurl.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/app.py
|
||||
only:
|
||||
changes:
|
||||
- src/app.py
|
||||
|
||||
test-questions:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_questions.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/utils/config.py
|
||||
only:
|
||||
changes:
|
||||
- src/utils/config.py
|
||||
|
||||
test-app-config:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_app_config.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/app.py
|
||||
# - src/utils/config.py
|
||||
only:
|
||||
changes:
|
||||
- src/app.py
|
||||
- src/utils/config.py
|
||||
|
||||
test-app-resources:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_app_resources.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/app.py
|
||||
# - src/utils/resources.py
|
||||
only:
|
||||
changes:
|
||||
- src/app.py
|
||||
- src/utils/resources.py
|
||||
|
||||
test-changeurl:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_changeurl.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/app.py
|
||||
only:
|
||||
changes:
|
||||
- src/app.py
|
||||
|
||||
test-backuprestore:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_backuprestore.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/backup.py
|
||||
only:
|
||||
changes:
|
||||
- src/backup.py
|
||||
|
||||
test-permission:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_permission.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/permission.py
|
||||
only:
|
||||
changes:
|
||||
- src/permission.py
|
||||
|
||||
test-settings:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_settings.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/settings.py
|
||||
only:
|
||||
changes:
|
||||
- src/settings.py
|
||||
|
||||
test-user-group:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_user-group.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/user.py
|
||||
only:
|
||||
changes:
|
||||
- src/user.py
|
||||
|
||||
test-regenconf:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_regenconf.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/regenconf.py
|
||||
only:
|
||||
changes:
|
||||
- src/regenconf.py
|
||||
|
||||
test-service:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_service.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/service.py
|
||||
only:
|
||||
changes:
|
||||
- src/service.py
|
||||
|
||||
test-ldapauth:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_ldapauth.py
|
||||
# only:
|
||||
# changes:
|
||||
# - src/authenticators/*.py
|
||||
|
||||
test-sso-and-portalapi:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest src/tests/test_sso_and_portalapi.py
|
||||
only:
|
||||
changes:
|
||||
- src/authenticators/*.py
|
||||
|
|
36
.gitlab/ci/translation.gitlab-ci.yml
Normal file
36
.gitlab/ci/translation.gitlab-ci.yml
Normal file
|
@ -0,0 +1,36 @@
|
|||
########################################
|
||||
# TRANSLATION
|
||||
########################################
|
||||
test-i18n-keys:
|
||||
stage: translation
|
||||
script:
|
||||
- python3 maintenance/missing_i18n_keys.py --check
|
||||
only:
|
||||
changes:
|
||||
- locales/en.json
|
||||
- src/*.py
|
||||
- src/diagnosers/*.py
|
||||
|
||||
autofix-translated-strings:
|
||||
stage: translation
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
before_script:
|
||||
- git config --global user.email "yunohost@yunohost.org"
|
||||
- git config --global user.name "$GITHUB_USER"
|
||||
- hub clone --branch ${CI_COMMIT_REF_NAME} "https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/yunohost.git" github_repo
|
||||
- cd github_repo
|
||||
script:
|
||||
# create a local branch that will overwrite distant one
|
||||
- git checkout -b "ci-autofix-translated-strings-${CI_COMMIT_REF_NAME}" --no-track
|
||||
- python3 maintenance/missing_i18n_keys.py --fix
|
||||
- python3 maintenance/autofix_locale_format.py
|
||||
- '[ $(git diff --ignore-blank-lines --ignore-all-space --ignore-space-at-eol --ignore-cr-at-eol | wc -l) != 0 ] || exit 0' # stop if there is nothing to commit
|
||||
- git commit -am "[CI] Reformat / remove stale translated strings" || true
|
||||
- git push -f origin "ci-autofix-translated-strings-${CI_COMMIT_REF_NAME}":"ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}"
|
||||
- hub pull-request -m "[CI] Reformat / remove stale translated strings" -b Yunohost:$CI_COMMIT_REF_NAME -p || true # GITHUB_USER and GITHUB_TOKEN registered here https://gitlab.com/yunohost/yunohost/-/settings/ci_cd
|
||||
only:
|
||||
variables:
|
||||
- $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
|
||||
changes:
|
||||
- locales/*
|
|
@ -1,53 +0,0 @@
|
|||
#! /usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
import yunohost
|
||||
|
||||
# Default server configuration
|
||||
DEFAULT_HOST = "localhost"
|
||||
DEFAULT_PORT = 6788
|
||||
|
||||
|
||||
def _parse_api_args():
|
||||
"""Parse main arguments for the api"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
description="Run the YunoHost API to manage your server.",
|
||||
)
|
||||
srv_group = parser.add_argument_group("server configuration")
|
||||
srv_group.add_argument(
|
||||
"-h",
|
||||
"--host",
|
||||
action="store",
|
||||
default=DEFAULT_HOST,
|
||||
help="Host to listen on (default: %s)" % DEFAULT_HOST,
|
||||
)
|
||||
srv_group.add_argument(
|
||||
"-p",
|
||||
"--port",
|
||||
action="store",
|
||||
default=DEFAULT_PORT,
|
||||
type=int,
|
||||
help="Port to listen on (default: %d)" % DEFAULT_PORT,
|
||||
)
|
||||
glob_group = parser.add_argument_group("global arguments")
|
||||
glob_group.add_argument(
|
||||
"--debug",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Set log level to DEBUG",
|
||||
)
|
||||
glob_group.add_argument(
|
||||
"--help",
|
||||
action="help",
|
||||
help="Show this help message and exit",
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
opts = _parse_api_args()
|
||||
# Run the server
|
||||
yunohost.portalapi(debug=opts.debug, host=opts.host, port=opts.port)
|
|
@ -132,8 +132,12 @@ def main() -> bool:
|
|||
)
|
||||
continue
|
||||
|
||||
# Broadcast IPv4 and IPv6
|
||||
ips: List[str] = interfaces[interface]["ipv4"] + interfaces[interface]["ipv6"]
|
||||
# Only broadcast IPv4 because IPv6 is buggy ... because we ain't using python3-ifaddr >= 0.1.7
|
||||
# Buster only ships 0.1.6
|
||||
# Bullseye ships 0.1.7
|
||||
# To be re-enabled once we're on bullseye...
|
||||
# ips: List[str] = interfaces[interface]["ipv4"] + interfaces[interface]["ipv6"]
|
||||
ips: List[str] = interfaces[interface]["ipv4"]
|
||||
|
||||
# If at least one IP is listed
|
||||
if not ips:
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{% set interfaces_list = interfaces.split(' ') %}
|
||||
{% for interface in interfaces_list %}
|
||||
interface-name={{ domain }},{{ interface }}
|
||||
interface-name=xmpp-upload.{{ domain }},{{ interface }}
|
||||
{% endfor %}
|
||||
{% if ipv6 %}
|
||||
host-record={{ domain }},{{ ipv6 }}
|
||||
host-record=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
|
||||
srv-host=_xmpp-server._tcp.{{ domain }},{{ domain }},5269,0,5
|
||||
|
|
|
@ -13,8 +13,9 @@ protocols = imap sieve {% if pop3_enabled == "True" %}pop3{% endif %}
|
|||
mail_plugins = $mail_plugins quota notify push_notification
|
||||
|
||||
###############################################################################
|
||||
# generated 2023-06-13, Mozilla Guideline v5.7, Dovecot 2.3.19, OpenSSL 3.0.9, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.19&config=intermediate&openssl=3.0.9&guideline=5.7
|
||||
|
||||
# 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
|
||||
|
||||
|
@ -31,7 +32,7 @@ ssl_dh = </usr/share/yunohost/ffdhe2048.pem
|
|||
|
||||
# intermediate configuration
|
||||
ssl_min_protocol = TLSv1.2
|
||||
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
|
||||
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
ssl_prefer_server_ciphers = no
|
||||
|
||||
###############################################################################
|
||||
|
@ -141,6 +142,18 @@ plugin {
|
|||
sieve_before = /etc/dovecot/global_script/
|
||||
}
|
||||
|
||||
plugin {
|
||||
antispam_debug_target = syslog
|
||||
antispam_verbose_debug = 0
|
||||
antispam_backend = pipe
|
||||
antispam_spam_pattern_ignorecase = junk;spam
|
||||
antispam_trash_pattern_ignorecase = trash;papierkorb;deleted messages
|
||||
antispam_pipe_program = /usr/bin/rspamc
|
||||
antispam_pipe_program_args = -h;localhost:11334;-P;q1
|
||||
antispam_pipe_program_spam_arg = learn_spam
|
||||
antispam_pipe_program_notspam_arg = learn_ham
|
||||
}
|
||||
|
||||
plugin {
|
||||
quota = maildir:User quota
|
||||
quota_rule2 = SPAM:ignore
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
# See man 5 jail.conf for details.
|
||||
#
|
||||
# [DEFAULT]
|
||||
# bantime = 1h
|
||||
# bantime = 3600
|
||||
#
|
||||
# [sshd]
|
||||
# enabled = true
|
||||
|
@ -44,52 +44,10 @@ before = paths-debian.conf
|
|||
# MISCELLANEOUS OPTIONS
|
||||
#
|
||||
|
||||
# "bantime.increment" allows to use database for searching of previously banned ip's to increase a
|
||||
# default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32...
|
||||
#bantime.increment = true
|
||||
|
||||
# "bantime.rndtime" is the max number of seconds using for mixing with random time
|
||||
# to prevent "clever" botnets calculate exact time IP can be unbanned again:
|
||||
#bantime.rndtime =
|
||||
|
||||
# "bantime.maxtime" is the max number of seconds using the ban time can reach (doesn't grow further)
|
||||
#bantime.maxtime =
|
||||
|
||||
# "bantime.factor" is a coefficient to calculate exponent growing of the formula or common multiplier,
|
||||
# default value of factor is 1 and with default value of formula, the ban time
|
||||
# grows by 1, 2, 4, 8, 16 ...
|
||||
#bantime.factor = 1
|
||||
|
||||
# "bantime.formula" used by default to calculate next value of ban time, default value below,
|
||||
# the same ban time growing will be reached by multipliers 1, 2, 4, 8, 16, 32...
|
||||
#bantime.formula = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor
|
||||
#
|
||||
# more aggressive example of formula has the same values only for factor "2.0 / 2.885385" :
|
||||
#bantime.formula = ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)
|
||||
|
||||
# "bantime.multipliers" used to calculate next value of ban time instead of formula, corresponding
|
||||
# previously ban count and given "bantime.factor" (for multipliers default is 1);
|
||||
# following example grows ban time by 1, 2, 4, 8, 16 ... and if last ban count greater as multipliers count,
|
||||
# always used last multiplier (64 in example), for factor '1' and original ban time 600 - 10.6 hours
|
||||
#bantime.multipliers = 1 2 4 8 16 32 64
|
||||
# following example can be used for small initial ban time (bantime=60) - it grows more aggressive at begin,
|
||||
# for bantime=60 the multipliers are minutes and equal: 1 min, 5 min, 30 min, 1 hour, 5 hour, 12 hour, 1 day, 2 day
|
||||
#bantime.multipliers = 1 5 30 60 300 720 1440 2880
|
||||
|
||||
# "bantime.overalljails" (if true) specifies the search of IP in the database will be executed
|
||||
# cross over all jails, if false (default), only current jail of the ban IP will be searched
|
||||
#bantime.overalljails = false
|
||||
|
||||
# --------------------
|
||||
|
||||
# "ignoreself" specifies whether the local resp. own IP addresses should be ignored
|
||||
# (default is true). Fail2ban will not ban a host which matches such addresses.
|
||||
#ignoreself = true
|
||||
|
||||
# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban
|
||||
# will not ban a host which matches an address in this list. Several addresses
|
||||
# can be defined using space (and/or comma) separator.
|
||||
#ignoreip = 127.0.0.1/8 ::1
|
||||
# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not
|
||||
# ban a host which matches an address in this list. Several addresses can be
|
||||
# defined using space (and/or comma) separator.
|
||||
ignoreip = 127.0.0.1/8
|
||||
|
||||
# External command that will take an tagged arguments to ignore, e.g. <ip>,
|
||||
# and return true if the IP is to be ignored. False otherwise.
|
||||
|
@ -98,18 +56,15 @@ before = paths-debian.conf
|
|||
ignorecommand =
|
||||
|
||||
# "bantime" is the number of seconds that a host is banned.
|
||||
bantime = 10m
|
||||
bantime = 600
|
||||
|
||||
# A host is banned if it has generated "maxretry" during the last "findtime"
|
||||
# seconds.
|
||||
findtime = 10m
|
||||
findtime = 600
|
||||
|
||||
# "maxretry" is the number of failures before a host get banned.
|
||||
maxretry = 10
|
||||
|
||||
# "maxmatches" is the number of matches stored in ticket (resolvable via tag <matches> in actions).
|
||||
maxmatches = %(maxretry)s
|
||||
|
||||
# "backend" specifies the backend used to get files modification.
|
||||
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".
|
||||
# This option can be overridden in each jail as well.
|
||||
|
@ -158,13 +113,10 @@ logencoding = auto
|
|||
enabled = false
|
||||
|
||||
|
||||
# "mode" defines the mode of the filter (see corresponding filter implementation for more info).
|
||||
mode = normal
|
||||
|
||||
# "filter" defines the filter to use by the jail.
|
||||
# By default jails have names matching their filter name
|
||||
#
|
||||
filter = %(__name__)s[mode=%(mode)s]
|
||||
filter = %(__name__)s
|
||||
|
||||
|
||||
#
|
||||
|
@ -188,7 +140,7 @@ mta = sendmail
|
|||
# Default protocol
|
||||
protocol = tcp
|
||||
|
||||
# Specify chain where jumps would need to be added in ban-actions expecting parameter chain
|
||||
# Specify chain where jumps would need to be added in iptables-* actions
|
||||
chain = INPUT
|
||||
|
||||
# Ports to be banned
|
||||
|
@ -209,53 +161,51 @@ banaction = iptables-multiport
|
|||
banaction_allports = iptables-allports
|
||||
|
||||
# The simplest action to take: ban only
|
||||
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
|
||||
# ban & send an e-mail with whois report to the destemail.
|
||||
action_mw = %(action_)s
|
||||
%(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
action_mw = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
%(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
|
||||
# ban & send an e-mail with whois report and relevant log lines
|
||||
# to the destemail.
|
||||
action_mwl = %(action_)s
|
||||
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
|
||||
action_mwl = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
%(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
|
||||
|
||||
# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
|
||||
#
|
||||
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
|
||||
# to the destemail.
|
||||
action_xarf = %(action_)s
|
||||
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
|
||||
|
||||
# ban & send a notification to one or more of the 50+ services supported by Apprise.
|
||||
# See https://github.com/caronc/apprise/wiki for details on what is supported.
|
||||
#
|
||||
# You may optionally over-ride the default configuration line (containing the Apprise URLs)
|
||||
# by using 'apprise[config="/alternate/path/to/apprise.cfg"]' otherwise
|
||||
# /etc/fail2ban/apprise.conf is sourced for your supported notification configuration.
|
||||
# action = %(action_)s
|
||||
# apprise
|
||||
action_xarf = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath=%(logpath)s, port="%(port)s"]
|
||||
|
||||
# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
|
||||
# to the destemail.
|
||||
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
|
||||
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
|
||||
%(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
|
||||
|
||||
# Report block via blocklist.de fail2ban reporting service API
|
||||
#
|
||||
# See the IMPORTANT note in action.d/blocklist_de.conf for when to use this action.
|
||||
# Specify expected parameters in file action.d/blocklist_de.local or if the interpolation
|
||||
# `action_blocklist_de` used for the action, set value of `blocklist_de_apikey`
|
||||
# in your `jail.local` globally (section [DEFAULT]) or per specific jail section (resp. in
|
||||
# corresponding jail.d/my-jail.local file).
|
||||
# See the IMPORTANT note in action.d/blocklist_de.conf for when to
|
||||
# use this action. Create a file jail.d/blocklist_de.local containing
|
||||
# [Init]
|
||||
# blocklist_de_apikey = {api key from registration]
|
||||
#
|
||||
action_blocklist_de = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
|
||||
action_blocklist_de = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
|
||||
|
||||
# Report ban via abuseipdb.com.
|
||||
# Report ban via badips.com, and use as blacklist
|
||||
#
|
||||
# See action.d/abuseipdb.conf for usage example and details.
|
||||
# See BadIPsAction docstring in config/action.d/badips.py for
|
||||
# documentation for this action.
|
||||
#
|
||||
action_abuseipdb = abuseipdb
|
||||
# NOTE: This action relies on banaction being present on start and therefore
|
||||
# should be last action defined for a jail.
|
||||
#
|
||||
action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"]
|
||||
#
|
||||
# Report ban via badips.com (uses action.d/badips.conf for reporting only)
|
||||
#
|
||||
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"]
|
||||
|
||||
# Choose default action. To change, just override value of 'action' with the
|
||||
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local
|
||||
|
@ -273,10 +223,15 @@ action = %(action_)s
|
|||
|
||||
[sshd]
|
||||
|
||||
# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
|
||||
# normal (default), ddos, extra or aggressive (combines all).
|
||||
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
|
||||
#mode = normal
|
||||
port = ssh
|
||||
logpath = %(sshd_log)s
|
||||
backend = %(sshd_backend)s
|
||||
|
||||
|
||||
[sshd-ddos]
|
||||
# This jail corresponds to the standard configuration in Fail2ban.
|
||||
# The mail-whois action send a notification e-mail with a whois request
|
||||
# in the body.
|
||||
port = ssh
|
||||
logpath = %(sshd_log)s
|
||||
backend = %(sshd_backend)s
|
||||
|
@ -310,7 +265,7 @@ logpath = %(apache_error_log)s
|
|||
# for email addresses. The mail outputs are buffered.
|
||||
port = http,https
|
||||
logpath = %(apache_access_log)s
|
||||
bantime = 48h
|
||||
bantime = 172800
|
||||
maxretry = 1
|
||||
|
||||
|
||||
|
@ -346,7 +301,7 @@ maxretry = 2
|
|||
port = http,https
|
||||
logpath = %(apache_access_log)s
|
||||
maxretry = 1
|
||||
ignorecommand = %(fail2ban_confpath)s/filter.d/ignorecommands/apache-fakegooglebot <ip>
|
||||
ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot <ip>
|
||||
|
||||
|
||||
[apache-modsecurity]
|
||||
|
@ -366,15 +321,12 @@ maxretry = 1
|
|||
[openhab-auth]
|
||||
|
||||
filter = openhab
|
||||
banaction = %(banaction_allports)s
|
||||
action = iptables-allports[name=NoAuthFailures]
|
||||
logpath = /opt/openhab/logs/request.log
|
||||
|
||||
|
||||
# To use more aggressive http-auth modes set filter parameter "mode" in jail.local:
|
||||
# normal (default), aggressive (combines all), auth or fallback
|
||||
# See "tests/files/logs/nginx-http-auth" or "filter.d/nginx-http-auth.conf" for usage example and details.
|
||||
[nginx-http-auth]
|
||||
# mode = normal
|
||||
|
||||
port = http,https
|
||||
logpath = %(nginx_error_log)s
|
||||
|
||||
|
@ -390,10 +342,8 @@ logpath = %(nginx_error_log)s
|
|||
|
||||
port = http,https
|
||||
logpath = %(nginx_error_log)s
|
||||
maxretry = 2
|
||||
|
||||
[nginx-bad-request]
|
||||
port = http,https
|
||||
logpath = %(nginx_access_log)s
|
||||
|
||||
# Ban attackers that try to use PHP's URL-fopen() functionality
|
||||
# through GET/POST variables. - Experimental, with more than a year
|
||||
|
@ -427,8 +377,6 @@ logpath = %(lighttpd_error_log)s
|
|||
|
||||
port = http,https
|
||||
logpath = %(roundcube_errors_log)s
|
||||
# Use following line in your jail.local if roundcube logs to journal.
|
||||
#backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[openwebmail]
|
||||
|
@ -478,13 +426,11 @@ backend = %(syslog_backend)s
|
|||
|
||||
port = http,https
|
||||
logpath = /var/log/tomcat*/catalina.out
|
||||
#logpath = /var/log/guacamole.log
|
||||
|
||||
[monit]
|
||||
#Ban clients brute-forcing the monit gui login
|
||||
port = 2812
|
||||
logpath = /var/log/monit
|
||||
/var/log/monit.log
|
||||
|
||||
|
||||
[webmin-auth]
|
||||
|
@ -567,29 +513,27 @@ logpath = %(vsftpd_log)s
|
|||
# ASSP SMTP Proxy Jail
|
||||
[assp]
|
||||
|
||||
port = smtp,465,submission
|
||||
port = smtp,submission
|
||||
logpath = /root/path/to/assp/logs/maillog.txt
|
||||
|
||||
|
||||
[courier-smtp]
|
||||
|
||||
port = smtp,465,submission
|
||||
port = smtp,submission
|
||||
logpath = %(syslog_mail)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[postfix]
|
||||
# To use another modes set filter parameter "mode" in jail.local:
|
||||
mode = more
|
||||
port = smtp,465,submission
|
||||
|
||||
port = smtp,submission
|
||||
logpath = %(postfix_log)s
|
||||
backend = %(postfix_backend)s
|
||||
|
||||
|
||||
[postfix-rbl]
|
||||
|
||||
filter = postfix[mode=rbl]
|
||||
port = smtp,465,submission
|
||||
port = smtp,submission
|
||||
logpath = %(postfix_log)s
|
||||
backend = %(postfix_backend)s
|
||||
maxretry = 1
|
||||
|
@ -597,17 +541,14 @@ maxretry = 1
|
|||
|
||||
[sendmail-auth]
|
||||
|
||||
port = submission,465,smtp
|
||||
port = submission,smtp
|
||||
logpath = %(syslog_mail)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[sendmail-reject]
|
||||
# To use more aggressive modes set filter parameter "mode" in jail.local:
|
||||
# normal (default), extra or aggressive
|
||||
# See "tests/files/logs/sendmail-reject" or "filter.d/sendmail-reject.conf" for usage example and details.
|
||||
#mode = normal
|
||||
port = smtp,465,submission
|
||||
|
||||
port = smtp,submission
|
||||
logpath = %(syslog_mail)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
@ -615,7 +556,7 @@ backend = %(syslog_backend)s
|
|||
[qmail-rbl]
|
||||
|
||||
filter = qmail
|
||||
port = smtp,465,submission
|
||||
port = smtp,submission
|
||||
logpath = /service/qmail/log/main/current
|
||||
|
||||
|
||||
|
@ -623,14 +564,14 @@ logpath = /service/qmail/log/main/current
|
|||
# but can be set by syslog_facility in the dovecot configuration.
|
||||
[dovecot]
|
||||
|
||||
port = pop3,pop3s,imap,imaps,submission,465,sieve
|
||||
port = pop3,pop3s,imap,imaps,submission,sieve
|
||||
logpath = %(dovecot_log)s
|
||||
backend = %(dovecot_backend)s
|
||||
|
||||
|
||||
[sieve]
|
||||
|
||||
port = smtp,465,submission
|
||||
port = smtp,submission
|
||||
logpath = %(dovecot_log)s
|
||||
backend = %(dovecot_backend)s
|
||||
|
||||
|
@ -642,21 +583,20 @@ logpath = %(solidpop3d_log)s
|
|||
|
||||
|
||||
[exim]
|
||||
# see filter.d/exim.conf for further modes supported from filter:
|
||||
#mode = normal
|
||||
port = smtp,465,submission
|
||||
|
||||
port = smtp,submission
|
||||
logpath = %(exim_main_log)s
|
||||
|
||||
|
||||
[exim-spam]
|
||||
|
||||
port = smtp,465,submission
|
||||
port = smtp,submission
|
||||
logpath = %(exim_main_log)s
|
||||
|
||||
|
||||
[kerio]
|
||||
|
||||
port = imap,smtp,imaps,465
|
||||
port = imap,smtp,imaps
|
||||
logpath = /opt/kerio/mailserver/store/logs/security.log
|
||||
|
||||
|
||||
|
@ -667,15 +607,14 @@ logpath = /opt/kerio/mailserver/store/logs/security.log
|
|||
|
||||
[courier-auth]
|
||||
|
||||
port = smtp,465,submission,imap,imaps,pop3,pop3s
|
||||
port = smtp,submission,imaps,pop3,pop3s
|
||||
logpath = %(syslog_mail)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[postfix-sasl]
|
||||
|
||||
filter = postfix[mode=auth]
|
||||
port = smtp,465,submission,imap,imaps,pop3,pop3s
|
||||
port = smtp,submission,imap,imaps,pop3,pop3s
|
||||
# You might consider monitoring /var/log/mail.warn instead if you are
|
||||
# running postfix since it would provide the same log lines at the
|
||||
# "warn" level but overall at the smaller filesize.
|
||||
|
@ -692,7 +631,7 @@ backend = %(syslog_backend)s
|
|||
|
||||
[squirrelmail]
|
||||
|
||||
port = smtp,465,submission,imap,imap2,imaps,pop3,pop3s,http,https,socks
|
||||
port = smtp,submission,imap,imap2,imaps,pop3,pop3s,http,https,socks
|
||||
logpath = /var/lib/squirrelmail/prefs/squirrelmail_access_log
|
||||
|
||||
|
||||
|
@ -745,8 +684,8 @@ logpath = /var/log/named/security.log
|
|||
[nsd]
|
||||
|
||||
port = 53
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
logpath = /var/log/nsd.log
|
||||
|
||||
|
||||
|
@ -757,8 +696,9 @@ logpath = /var/log/nsd.log
|
|||
[asterisk]
|
||||
|
||||
port = 5060,5061
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s"]
|
||||
logpath = /var/log/asterisk/messages
|
||||
maxretry = 10
|
||||
|
||||
|
@ -766,22 +706,16 @@ maxretry = 10
|
|||
[freeswitch]
|
||||
|
||||
port = 5060,5061
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s"]
|
||||
logpath = /var/log/freeswitch.log
|
||||
maxretry = 10
|
||||
|
||||
|
||||
# enable adminlog; it will log to a file inside znc's directory by default.
|
||||
[znc-adminlog]
|
||||
|
||||
port = 6667
|
||||
logpath = /var/lib/znc/moddata/adminlog/znc.log
|
||||
|
||||
|
||||
# To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld] or
|
||||
# equivalent section:
|
||||
# log-warnings = 2
|
||||
# log-warning = 2
|
||||
#
|
||||
# for syslog (daemon facility)
|
||||
# [mysqld_safe]
|
||||
|
@ -797,14 +731,6 @@ logpath = %(mysql_log)s
|
|||
backend = %(mysql_backend)s
|
||||
|
||||
|
||||
[mssql-auth]
|
||||
# Default configuration for Microsoft SQL Server for Linux
|
||||
# See the 'mssql-conf' manpage how to change logpath or port
|
||||
logpath = /var/opt/mssql/log/errorlog
|
||||
port = 1433
|
||||
filter = mssql-auth
|
||||
|
||||
|
||||
# Log wrong MongoDB auth (for details see filter 'filter.d/mongodb-auth.conf')
|
||||
[mongodb-auth]
|
||||
# change port when running with "--shardsvr" or "--configsvr" runtime operation
|
||||
|
@ -823,8 +749,8 @@ logpath = /var/log/mongodb/mongodb.log
|
|||
|
||||
logpath = /var/log/fail2ban.log
|
||||
banaction = %(banaction_allports)s
|
||||
bantime = 1w
|
||||
findtime = 1d
|
||||
bantime = 604800 ; 1 week
|
||||
findtime = 86400 ; 1 day
|
||||
|
||||
|
||||
# Generic filter for PAM. Has to be used with action which bans all
|
||||
|
@ -860,31 +786,11 @@ logpath = /var/log/ejabberd/ejabberd.log
|
|||
[counter-strike]
|
||||
|
||||
logpath = /opt/cstrike/logs/L[0-9]*.log
|
||||
# Firewall: http://www.cstrike-planet.com/faq/6
|
||||
tcpport = 27030,27031,27032,27033,27034,27035,27036,27037,27038,27039
|
||||
udpport = 1200,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,27014,27015
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp"]
|
||||
|
||||
[softethervpn]
|
||||
port = 500,4500
|
||||
protocol = udp
|
||||
logpath = /usr/local/vpnserver/security_log/*/sec.log
|
||||
|
||||
[gitlab]
|
||||
port = http,https
|
||||
logpath = /var/log/gitlab/gitlab-rails/application.log
|
||||
|
||||
[grafana]
|
||||
port = http,https
|
||||
logpath = /var/log/grafana/grafana.log
|
||||
|
||||
[bitwarden]
|
||||
port = http,https
|
||||
logpath = /home/*/bwdata/logs/identity/Identity/log.txt
|
||||
|
||||
[centreon]
|
||||
port = http,https
|
||||
logpath = /var/log/centreon/login.log
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
|
||||
# consider low maxretry and a long bantime
|
||||
# nobody except your own Nagios server should ever probe nrpe
|
||||
|
@ -918,9 +824,7 @@ filter = apache-pass[knocking_url="%(knocking_url)s"]
|
|||
logpath = %(apache_access_log)s
|
||||
blocktype = RETURN
|
||||
returntype = DROP
|
||||
action = %(action_)s[blocktype=%(blocktype)s, returntype=%(returntype)s,
|
||||
actionstart_on_demand=false, actionrepair_on_unban=true]
|
||||
bantime = 1h
|
||||
bantime = 3600
|
||||
maxretry = 1
|
||||
findtime = 1
|
||||
|
||||
|
@ -928,8 +832,8 @@ findtime = 1
|
|||
[murmur]
|
||||
# AKA mumble-server
|
||||
port = 64738
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol=tcp, chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol=udp, chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
logpath = /var/log/mumble-server/mumble-server.log
|
||||
|
||||
|
||||
|
@ -947,34 +851,5 @@ logpath = /var/log/haproxy.log
|
|||
|
||||
[slapd]
|
||||
port = ldap,ldaps
|
||||
filter = slapd
|
||||
logpath = /var/log/slapd.log
|
||||
|
||||
[domino-smtp]
|
||||
port = smtp,ssmtp
|
||||
logpath = /home/domino01/data/IBM_TECHNICAL_SUPPORT/console.log
|
||||
|
||||
[phpmyadmin-syslog]
|
||||
port = http,https
|
||||
logpath = %(syslog_authpriv)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[zoneminder]
|
||||
# Zoneminder HTTP/HTTPS web interface auth
|
||||
# Logs auth failures to apache2 error log
|
||||
port = http,https
|
||||
logpath = %(apache_error_log)s
|
||||
|
||||
[traefik-auth]
|
||||
# to use 'traefik-auth' filter you have to configure your Traefik instance,
|
||||
# see `filter.d/traefik-auth.conf` for details and service example.
|
||||
port = http,https
|
||||
logpath = /var/log/traefik/access.log
|
||||
|
||||
[scanlogd]
|
||||
logpath = %(syslog_local0)s
|
||||
banaction = %(banaction_allports)s
|
||||
|
||||
[monitorix]
|
||||
port = 8080
|
||||
logpath = /var/log/monitorix-httpd
|
||||
|
|
|
@ -31,12 +31,3 @@ protocol = tcp
|
|||
filter = yunohost
|
||||
logpath = /var/log/nginx/*error.log
|
||||
/var/log/nginx/*access.log
|
||||
|
||||
[yunohost-portal]
|
||||
enabled = true
|
||||
port = http,https
|
||||
protocol = tcp
|
||||
filter = yunohost-portal
|
||||
logpath = /var/log/nginx/*error.log
|
||||
/var/log/nginx/*access.log
|
||||
maxretry = 20
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[Definition]
|
||||
failregex = ^<HOST> -.*\"POST /yunohost/portalapi/login HTTP/\d.\d\" 401
|
||||
ignoreregex =
|
|
@ -1,3 +1,24 @@
|
|||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Adrien Beudin
|
||||
#
|
||||
# $Revision: 2 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
failregex = ^<HOST> -.*\"POST /yunohost/api/login HTTP/\d.\d\" 401
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failure messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = helpers.lua:[0-9]+: authenticate\(\): Connection failed for: .*, client: <HOST>
|
||||
^<HOST> -.*\"POST /yunohost/api/login HTTP/\d.\d\" 401
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
|
75
conf/metronome/domain.tpl.cfg.lua
Normal file
75
conf/metronome/domain.tpl.cfg.lua
Normal file
|
@ -0,0 +1,75 @@
|
|||
VirtualHost "{{ domain }}"
|
||||
enable = true
|
||||
ssl = {
|
||||
key = "/etc/yunohost/certs/{{ domain }}/key.pem";
|
||||
certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem";
|
||||
}
|
||||
authentication = "ldap2"
|
||||
ldap = {
|
||||
hostname = "localhost",
|
||||
user = {
|
||||
basedn = "ou=users,dc=yunohost,dc=org",
|
||||
filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }})(permission=cn=xmpp.main,ou=permission,dc=yunohost,dc=org))",
|
||||
usernamefield = "mail",
|
||||
namefield = "cn",
|
||||
},
|
||||
}
|
||||
|
||||
-- Discovery items
|
||||
disco_items = {
|
||||
{ "muc.{{ domain }}" },
|
||||
{ "pubsub.{{ domain }}" },
|
||||
{ "jabber.{{ domain }}" },
|
||||
{ "vjud.{{ domain }}" },
|
||||
{ "xmpp-upload.{{ domain }}" },
|
||||
};
|
||||
|
||||
-- contact_info = {
|
||||
-- abuse = { "mailto:abuse@{{ domain }}", "xmpp:admin@{{ domain }}" };
|
||||
-- admin = { "mailto:root@{{ domain }}", "xmpp:admin@{{ domain }}" };
|
||||
-- };
|
||||
|
||||
------ Components ------
|
||||
-- You can specify components to add hosts that provide special services,
|
||||
-- like multi-user conferences, and transports.
|
||||
|
||||
---Set up a MUC (multi-user chat) room server
|
||||
Component "muc.{{ domain }}" "muc"
|
||||
name = "{{ domain }} Chatrooms"
|
||||
|
||||
modules_enabled = {
|
||||
"muc_limits";
|
||||
"muc_log";
|
||||
"muc_log_mam";
|
||||
"muc_log_http";
|
||||
"muc_vcard";
|
||||
}
|
||||
|
||||
muc_event_rate = 0.5
|
||||
muc_burst_factor = 10
|
||||
room_default_config = {
|
||||
logging = true,
|
||||
persistent = true
|
||||
};
|
||||
|
||||
---Set up a PubSub server
|
||||
Component "pubsub.{{ domain }}" "pubsub"
|
||||
name = "{{ domain }} Publish/Subscribe"
|
||||
|
||||
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
|
||||
|
||||
---Set up a HTTP Upload service
|
||||
Component "xmpp-upload.{{ domain }}" "http_upload"
|
||||
name = "{{ domain }} Sharing Service"
|
||||
|
||||
http_file_path = "/var/xmpp-upload/{{ domain }}/upload"
|
||||
http_external_url = "https://xmpp-upload.{{ domain }}:443"
|
||||
http_file_base_path = "/upload"
|
||||
http_file_size_limit = 6*1024*1024
|
||||
http_file_quota = 60*1024*1024
|
||||
http_upload_file_size_limit = 100 * 1024 * 1024 -- bytes
|
||||
http_upload_quota = 10 * 1024 * 1024 * 1024 -- bytes
|
||||
|
||||
---Set up a VJUD service
|
||||
Component "vjud.{{ domain }}" "vjud"
|
||||
vjud_disco_name = "{{ domain }} User Directory"
|
123
conf/metronome/metronome.cfg.lua
Normal file
123
conf/metronome/metronome.cfg.lua
Normal file
|
@ -0,0 +1,123 @@
|
|||
-- ** Metronome's config file example **
|
||||
--
|
||||
-- The format is exactly equal to Prosody's:
|
||||
--
|
||||
-- Lists are written { "like", "this", "one" }
|
||||
-- Lists can also be of { 1, 2, 3 } numbers, etc.
|
||||
-- Either commas, or semi-colons; may be used as seperators.
|
||||
--
|
||||
-- A table is a list of values, except each value has a name. An
|
||||
-- example would be:
|
||||
--
|
||||
-- ssl = { key = "keyfile.key", certificate = "certificate.cert" }
|
||||
--
|
||||
-- Tip: You can check that the syntax of this file is correct when you have finished
|
||||
-- by running: luac -p metronome.cfg.lua
|
||||
-- If there are any errors, it will let you know what and where they are, otherwise it
|
||||
-- will keep quiet.
|
||||
|
||||
-- Global settings go in this section
|
||||
|
||||
-- This is the list of modules Metronome will load on startup.
|
||||
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
|
||||
|
||||
modules_enabled = {
|
||||
-- Generally required
|
||||
"roster"; -- Allow users to have a roster. Recommended.
|
||||
"saslauth"; -- Authentication for clients. Recommended if you want to log in.
|
||||
"tls"; -- Add support for secure TLS on c2s/s2s connections
|
||||
"disco"; -- Service discovery
|
||||
|
||||
-- Not essential, but recommended
|
||||
"private"; -- Private XML storage (for room bookmarks, etc.)
|
||||
"vcard"; -- Allow users to set vCards
|
||||
"pep"; -- Allows setting of mood, tune, etc.
|
||||
"pubsub"; -- Publish-subscribe XEP-0060
|
||||
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
|
||||
"bidi"; -- Enables Bidirectional Server-to-Server Streams.
|
||||
|
||||
-- Nice to have
|
||||
"version"; -- Replies to server version requests
|
||||
"uptime"; -- Report how long server has been running
|
||||
"time"; -- Let others know the time here on this server
|
||||
"ping"; -- Replies to XMPP pings with pongs
|
||||
"register"; -- Allow users to register on this server using a client and change passwords
|
||||
"stream_management"; -- Allows clients and servers to use Stream Management
|
||||
"stanza_optimizations"; -- Allows clients to use Client State Indication and SIFT
|
||||
"message_carbons"; -- Allows clients to enable carbon copies of messages
|
||||
"mam"; -- Enable server-side message archives using Message Archive Management
|
||||
"push"; -- Enable Push Notifications via PubSub using XEP-0357
|
||||
"lastactivity"; -- Enables clients to know the last presence status of an user
|
||||
"adhoc_cm"; -- Allow to set client certificates to login through SASL External via adhoc
|
||||
"admin_adhoc"; -- administration adhoc commands
|
||||
"bookmarks"; -- XEP-0048 Bookmarks synchronization between PEP and Private Storage
|
||||
"sec_labels"; -- Allows to use a simplified version XEP-0258 Security Labels and related ACDFs.
|
||||
"privacy"; -- Add privacy lists and simple blocking command support
|
||||
|
||||
-- Other specific functionality
|
||||
--"admin_telnet"; -- administration console, telnet to port 5582
|
||||
--"admin_web"; -- administration web interface
|
||||
"bosh"; -- Enable support for BOSH clients, aka "XMPP over Bidirectional Streams over Synchronous HTTP"
|
||||
--"compression"; -- Allow clients to enable Stream Compression
|
||||
--"spim_block"; -- Require authorization via OOB form for messages from non-contacts and block unsollicited messages
|
||||
--"gate_guard"; -- Enable config-based blacklisting and hit-based auto-banning features
|
||||
--"incidents_handling"; -- Enable Incidents Handling support (can be administered via adhoc commands)
|
||||
--"server_presence"; -- Enables Server Buddies extension support
|
||||
--"service_directory"; -- Enables Service Directories extension support
|
||||
--"public_service"; -- Enables Server vCard support for public services in directories and advertises in features
|
||||
--"register_api"; -- Provides secure API for both Out-Of-Band and In-Band registration for E-Mail verification
|
||||
"websocket"; -- Enable support for WebSocket clients, aka "XMPP over WebSockets"
|
||||
};
|
||||
|
||||
-- Server PID
|
||||
pidfile = "/var/run/metronome/metronome.pid"
|
||||
|
||||
-- HTTP server
|
||||
http_ports = { 5290 }
|
||||
http_interfaces = { "127.0.0.1", "::1" }
|
||||
|
||||
--https_ports = { 5291 }
|
||||
--https_interfaces = { "127.0.0.1", "::1" }
|
||||
|
||||
-- Enable IPv6
|
||||
use_ipv6 = true
|
||||
|
||||
-- BOSH configuration (mod_bosh)
|
||||
consider_bosh_secure = true
|
||||
cross_domain_bosh = true
|
||||
|
||||
-- WebSocket configuration (mod_websocket)
|
||||
consider_websocket_secure = true
|
||||
cross_domain_websocket = true
|
||||
|
||||
-- Disable account creation by default, for security
|
||||
allow_registration = false
|
||||
|
||||
-- Use LDAP storage backend for all stores
|
||||
storage = "ldap"
|
||||
|
||||
-- stanza optimization
|
||||
csi_config_queue_all_muc_messages_but_mentions = false;
|
||||
|
||||
|
||||
-- Logging configuration
|
||||
log = {
|
||||
info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging
|
||||
error = "/var/log/metronome/metronome.err";
|
||||
-- "*syslog"; -- Uncomment this for logging to syslog
|
||||
-- "*console"; -- Log to the console, useful for debugging with daemonize=false
|
||||
}
|
||||
|
||||
------ Components ------
|
||||
-- You can specify components to add hosts that provide special services,
|
||||
-- like multi-user conferences, and transports.
|
||||
|
||||
---Set up a local BOSH service
|
||||
Component "localhost" "http"
|
||||
modules_enabled = { "bosh" }
|
||||
|
||||
----------- Virtual hosts -----------
|
||||
-- You need to add a VirtualHost entry for each domain you wish Metronome to serve.
|
||||
-- Settings under each VirtualHost entry apply *only* to that host.
|
||||
|
||||
Include "conf.d/*.cfg.lua"
|
270
conf/metronome/modules/ldap.lib.lua
Normal file
270
conf/metronome/modules/ldap.lib.lua
Normal file
|
@ -0,0 +1,270 @@
|
|||
-- vim:sts=4 sw=4
|
||||
|
||||
-- Prosody IM
|
||||
-- Copyright (C) 2008-2010 Matthew Wild
|
||||
-- Copyright (C) 2008-2010 Waqas Hussain
|
||||
-- Copyright (C) 2012 Rob Hoelz
|
||||
--
|
||||
-- This project is MIT/X11 licensed. Please see the
|
||||
-- COPYING file in the source package for more information.
|
||||
--
|
||||
|
||||
local ldap;
|
||||
local connection;
|
||||
local params = module:get_option("ldap");
|
||||
local format = string.format;
|
||||
local tconcat = table.concat;
|
||||
|
||||
local _M = {};
|
||||
|
||||
local config_params = {
|
||||
hostname = 'string',
|
||||
user = {
|
||||
basedn = 'string',
|
||||
namefield = 'string',
|
||||
filter = 'string',
|
||||
usernamefield = 'string',
|
||||
},
|
||||
groups = {
|
||||
basedn = 'string',
|
||||
namefield = 'string',
|
||||
memberfield = 'string',
|
||||
|
||||
_member = {
|
||||
name = 'string',
|
||||
admin = 'boolean?',
|
||||
},
|
||||
},
|
||||
admin = {
|
||||
_optional = true,
|
||||
basedn = 'string',
|
||||
namefield = 'string',
|
||||
filter = 'string',
|
||||
}
|
||||
}
|
||||
|
||||
local function run_validation(params, config, prefix)
|
||||
prefix = prefix or '';
|
||||
|
||||
-- verify that every required member of config is present in params
|
||||
for k, v in pairs(config) do
|
||||
if type(k) == 'string' and k:sub(1, 1) ~= '_' then
|
||||
local is_optional;
|
||||
if type(v) == 'table' then
|
||||
is_optional = v._optional;
|
||||
else
|
||||
is_optional = v:sub(-1) == '?';
|
||||
end
|
||||
|
||||
if not is_optional and params[k] == nil then
|
||||
return nil, prefix .. k .. ' is required';
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in pairs(params) do
|
||||
local expected_type = config[k];
|
||||
|
||||
local ok, err = true;
|
||||
|
||||
if type(k) == 'string' then
|
||||
-- verify that this key is present in config
|
||||
if k:sub(1, 1) == '_' or expected_type == nil then
|
||||
return nil, 'invalid parameter ' .. prefix .. k;
|
||||
end
|
||||
|
||||
-- type validation
|
||||
if type(expected_type) == 'string' then
|
||||
if expected_type:sub(-1) == '?' then
|
||||
expected_type = expected_type:sub(1, -2);
|
||||
end
|
||||
|
||||
if type(v) ~= expected_type then
|
||||
return nil, 'invalid type for parameter ' .. prefix .. k;
|
||||
end
|
||||
else -- it's a table (or had better be)
|
||||
if type(v) ~= 'table' then
|
||||
return nil, 'invalid type for parameter ' .. prefix .. k;
|
||||
end
|
||||
|
||||
-- recurse into child
|
||||
ok, err = run_validation(v, expected_type, prefix .. k .. '.');
|
||||
end
|
||||
else -- it's an integer (or had better be)
|
||||
if not config._member then
|
||||
return nil, 'invalid parameter ' .. prefix .. tostring(k);
|
||||
end
|
||||
ok, err = run_validation(v, config._member, prefix .. tostring(k) .. '.');
|
||||
end
|
||||
|
||||
if not ok then
|
||||
return ok, err;
|
||||
end
|
||||
end
|
||||
|
||||
return true;
|
||||
end
|
||||
|
||||
local function validate_config()
|
||||
if true then
|
||||
return true; -- XXX for now
|
||||
end
|
||||
|
||||
-- this is almost too clever (I mean that in a bad
|
||||
-- maintainability sort of way)
|
||||
--
|
||||
-- basically this allows a free pass for a key in group members
|
||||
-- equal to params.groups.namefield
|
||||
setmetatable(config_params.groups._member, {
|
||||
__index = function(_, k)
|
||||
if k == params.groups.namefield then
|
||||
return 'string';
|
||||
end
|
||||
end
|
||||
});
|
||||
|
||||
local ok, err = run_validation(params, config_params);
|
||||
|
||||
setmetatable(config_params.groups._member, nil);
|
||||
|
||||
if ok then
|
||||
-- a little extra validation that doesn't fit into
|
||||
-- my recursive checker
|
||||
local group_namefield = params.groups.namefield;
|
||||
for i, group in ipairs(params.groups) do
|
||||
if not group[group_namefield] then
|
||||
return nil, format('groups.%d.%s is required', i, group_namefield);
|
||||
end
|
||||
end
|
||||
|
||||
-- fill in params.admin if you can
|
||||
if not params.admin and params.groups then
|
||||
local admingroup;
|
||||
|
||||
for _, groupconfig in ipairs(params.groups) do
|
||||
if groupconfig.admin then
|
||||
admingroup = groupconfig;
|
||||
break;
|
||||
end
|
||||
end
|
||||
|
||||
if admingroup then
|
||||
params.admin = {
|
||||
basedn = params.groups.basedn,
|
||||
namefield = params.groups.memberfield,
|
||||
filter = group_namefield .. '=' .. admingroup[group_namefield],
|
||||
};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ok, err;
|
||||
end
|
||||
|
||||
-- what to do if connection isn't available?
|
||||
local function connect()
|
||||
return ldap.open_simple(params.hostname, params.bind_dn, params.bind_password, params.use_tls);
|
||||
end
|
||||
|
||||
-- this is abstracted so we can maintain persistent connections at a later time
|
||||
function _M.getconnection()
|
||||
return connect();
|
||||
end
|
||||
|
||||
function _M.getparams()
|
||||
return params;
|
||||
end
|
||||
|
||||
-- XXX consider renaming this...it doesn't bind the current connection
|
||||
function _M.bind(username, password)
|
||||
local conn = _M.getconnection();
|
||||
local filter = format('%s=%s', params.user.usernamefield, username);
|
||||
if params.user.usernamefield == 'mail' then
|
||||
filter = format('mail=%s@*', username);
|
||||
end
|
||||
|
||||
if filter then
|
||||
filter = _M.filter.combine_and(filter, params.user.filter);
|
||||
end
|
||||
|
||||
local who = _M.singlematch {
|
||||
attrs = params.user.usernamefield,
|
||||
base = params.user.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
|
||||
if who then
|
||||
who = who.dn;
|
||||
module:log('debug', '_M.bind - who: %s', who);
|
||||
else
|
||||
module:log('debug', '_M.bind - no DN found for username = %s', username);
|
||||
return nil, format('no DN found for username = %s', username);
|
||||
end
|
||||
|
||||
local conn, err = ldap.open_simple(params.hostname, who, password, params.use_tls);
|
||||
|
||||
if conn then
|
||||
conn:close();
|
||||
return true;
|
||||
end
|
||||
|
||||
return conn, err;
|
||||
end
|
||||
|
||||
function _M.singlematch(query)
|
||||
local ld = _M.getconnection();
|
||||
|
||||
query.sizelimit = 1;
|
||||
query.scope = 'subtree';
|
||||
|
||||
for dn, attribs in ld:search(query) do
|
||||
attribs.dn = dn;
|
||||
return attribs;
|
||||
end
|
||||
end
|
||||
|
||||
_M.filter = {};
|
||||
|
||||
function _M.filter.combine_and(...)
|
||||
local parts = { '(&' };
|
||||
|
||||
local arg = { ... };
|
||||
|
||||
for _, filter in ipairs(arg) do
|
||||
if filter:sub(1, 1) ~= '(' and filter:sub(-1) ~= ')' then
|
||||
filter = '(' .. filter .. ')'
|
||||
end
|
||||
parts[#parts + 1] = filter;
|
||||
end
|
||||
|
||||
parts[#parts + 1] = ')';
|
||||
|
||||
return tconcat(parts, '');
|
||||
end
|
||||
|
||||
do
|
||||
local ok, err;
|
||||
|
||||
metronome.unlock_globals();
|
||||
ok, ldap = pcall(require, 'lualdap');
|
||||
metronome.lock_globals();
|
||||
if not ok then
|
||||
module:log("error", "Failed to load the LuaLDAP library for accessing LDAP: %s", ldap);
|
||||
module:log("error", "More information on install LuaLDAP can be found at http://www.keplerproject.org/lualdap");
|
||||
return;
|
||||
end
|
||||
|
||||
if not params then
|
||||
module:log("error", "LDAP configuration required to use the LDAP storage module");
|
||||
return;
|
||||
end
|
||||
|
||||
ok, err = validate_config();
|
||||
|
||||
if not ok then
|
||||
module:log("error", "LDAP configuration is invalid: %s", tostring(err));
|
||||
return;
|
||||
end
|
||||
end
|
||||
|
||||
return _M;
|
90
conf/metronome/modules/mod_auth_ldap2.lua
Normal file
90
conf/metronome/modules/mod_auth_ldap2.lua
Normal file
|
@ -0,0 +1,90 @@
|
|||
-- vim:sts=4 sw=4
|
||||
|
||||
-- Metronome IM
|
||||
-- Copyright (C) 2008-2010 Matthew Wild
|
||||
-- Copyright (C) 2008-2010 Waqas Hussain
|
||||
-- Copyright (C) 2012 Rob Hoelz
|
||||
-- Copyright (C) 2015 YUNOHOST.ORG
|
||||
--
|
||||
-- This project is MIT/X11 licensed. Please see the
|
||||
-- COPYING file in the source package for more information.
|
||||
--
|
||||
-- https://github.com/YunoHost/yunohost-config-metronome/blob/unstable/lib/modules/mod_auth_ldap2.lua
|
||||
-- adapted to use common LDAP store on Metronome
|
||||
|
||||
local ldap = module:require 'ldap';
|
||||
local new_sasl = require 'util.sasl'.new;
|
||||
local jsplit = require 'util.jid'.split;
|
||||
|
||||
local log = module._log
|
||||
|
||||
if not ldap then
|
||||
return;
|
||||
end
|
||||
|
||||
function new_default_provider(host)
|
||||
local provider = { name = "ldap2" };
|
||||
log("debug", "initializing ldap2 authentication provider for host '%s'", host);
|
||||
|
||||
function provider.test_password(username, password)
|
||||
return ldap.bind(username, password);
|
||||
end
|
||||
|
||||
function provider.user_exists(username)
|
||||
local params = ldap.getparams()
|
||||
|
||||
local filter = ldap.filter.combine_and(params.user.filter, params.user.usernamefield .. '=' .. username);
|
||||
if params.user.usernamefield == 'mail' then
|
||||
filter = ldap.filter.combine_and(params.user.filter, 'mail=' .. username .. '@*');
|
||||
end
|
||||
|
||||
return ldap.singlematch {
|
||||
base = params.user.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
end
|
||||
|
||||
function provider.get_password(username)
|
||||
return nil, "Passwords unavailable for LDAP.";
|
||||
end
|
||||
|
||||
function provider.set_password(username, password)
|
||||
return nil, "Passwords unavailable for LDAP.";
|
||||
end
|
||||
|
||||
function provider.create_user(username, password)
|
||||
return nil, "Account creation/modification not available with LDAP.";
|
||||
end
|
||||
|
||||
function provider.get_sasl_handler(session)
|
||||
local testpass_authentication_profile = {
|
||||
session = session,
|
||||
plain_test = function(sasl, username, password, realm)
|
||||
return provider.test_password(username, password), true;
|
||||
end,
|
||||
order = { "plain_test" },
|
||||
};
|
||||
return new_sasl(module.host, testpass_authentication_profile);
|
||||
end
|
||||
|
||||
function provider.is_admin(jid)
|
||||
local admin_config = ldap.getparams().admin;
|
||||
|
||||
if not admin_config then
|
||||
return;
|
||||
end
|
||||
|
||||
local ld = ldap:getconnection();
|
||||
local username = jsplit(jid);
|
||||
local filter = ldap.filter.combine_and(admin_config.filter, admin_config.namefield .. '=' .. username);
|
||||
|
||||
return ldap.singlematch {
|
||||
base = admin_config.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
end
|
||||
|
||||
return provider;
|
||||
end
|
||||
|
||||
module:add_item("auth-provider", new_default_provider(module.host));
|
86
conf/metronome/modules/mod_legacyauth.lua
Normal file
86
conf/metronome/modules/mod_legacyauth.lua
Normal file
|
@ -0,0 +1,86 @@
|
|||
-- Prosody IM
|
||||
-- Copyright (C) 2008-2010 Matthew Wild
|
||||
-- Copyright (C) 2008-2010 Waqas Hussain
|
||||
--
|
||||
-- This project is MIT/X11 licensed. Please see the
|
||||
-- COPYING file in the source package for more information.
|
||||
--
|
||||
|
||||
|
||||
|
||||
local st = require "util.stanza";
|
||||
local t_concat = table.concat;
|
||||
|
||||
local secure_auth_only = module:get_option("c2s_require_encryption")
|
||||
or module:get_option("require_encryption")
|
||||
or not(module:get_option("allow_unencrypted_plain_auth"));
|
||||
|
||||
local sessionmanager = require "core.sessionmanager";
|
||||
local usermanager = require "core.usermanager";
|
||||
local nodeprep = require "util.encodings".stringprep.nodeprep;
|
||||
local resourceprep = require "util.encodings".stringprep.resourceprep;
|
||||
|
||||
module:add_feature("jabber:iq:auth");
|
||||
module:hook("stream-features", function(event)
|
||||
local origin, features = event.origin, event.features;
|
||||
if secure_auth_only and not origin.secure then
|
||||
-- Sorry, not offering to insecure streams!
|
||||
return;
|
||||
elseif not origin.username then
|
||||
features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up();
|
||||
end
|
||||
end);
|
||||
|
||||
module:hook("stanza/iq/jabber:iq:auth:query", function(event)
|
||||
local session, stanza = event.origin, event.stanza;
|
||||
|
||||
if session.type ~= "c2s_unauthed" then
|
||||
(session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections."));
|
||||
return true;
|
||||
end
|
||||
|
||||
if secure_auth_only and not session.secure then
|
||||
session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server"));
|
||||
return true;
|
||||
end
|
||||
|
||||
local username = stanza.tags[1]:child_with_name("username");
|
||||
local password = stanza.tags[1]:child_with_name("password");
|
||||
local resource = stanza.tags[1]:child_with_name("resource");
|
||||
if not (username and password and resource) then
|
||||
local reply = st.reply(stanza);
|
||||
session.send(reply:query("jabber:iq:auth")
|
||||
:tag("username"):up()
|
||||
:tag("password"):up()
|
||||
:tag("resource"):up());
|
||||
else
|
||||
username, password, resource = t_concat(username), t_concat(password), t_concat(resource);
|
||||
username = nodeprep(username);
|
||||
resource = resourceprep(resource)
|
||||
if not (username and resource) then
|
||||
session.send(st.error_reply(stanza, "modify", "bad-request"));
|
||||
return true;
|
||||
end
|
||||
if usermanager.test_password(username, session.host, password) then
|
||||
-- Authentication successful!
|
||||
local success, err = sessionmanager.make_authenticated(session, username);
|
||||
if success then
|
||||
local err_type, err_msg;
|
||||
success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource);
|
||||
if not success then
|
||||
session.send(st.error_reply(stanza, err_type, err, err_msg));
|
||||
session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager?
|
||||
return true;
|
||||
elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth
|
||||
session.send(st.error_reply(stanza, "cancel", "conflict", "The requested resource could not be assigned to this session."));
|
||||
session:close(); -- FIXME undo resource bind and auth instead of closing the session?
|
||||
return true;
|
||||
end
|
||||
end
|
||||
session.send(st.reply(stanza));
|
||||
else
|
||||
session.send(st.error_reply(stanza, "auth", "not-authorized"));
|
||||
end
|
||||
end
|
||||
return true;
|
||||
end);
|
243
conf/metronome/modules/mod_storage_ldap.lua
Normal file
243
conf/metronome/modules/mod_storage_ldap.lua
Normal file
|
@ -0,0 +1,243 @@
|
|||
-- vim:sts=4 sw=4
|
||||
|
||||
-- Metronome IM
|
||||
-- Copyright (C) 2008-2010 Matthew Wild
|
||||
-- Copyright (C) 2008-2010 Waqas Hussain
|
||||
-- Copyright (C) 2012 Rob Hoelz
|
||||
-- Copyright (C) 2015 YUNOHOST.ORG
|
||||
--
|
||||
-- This project is MIT/X11 licensed. Please see the
|
||||
-- COPYING file in the source package for more information.
|
||||
|
||||
----------------------------------------
|
||||
-- Constants and such --
|
||||
----------------------------------------
|
||||
|
||||
local setmetatable = setmetatable;
|
||||
|
||||
local get_config = require "core.configmanager".get;
|
||||
local ldap = module:require 'ldap';
|
||||
local vcardlib = module:require 'vcard';
|
||||
local st = require 'util.stanza';
|
||||
local gettime = require 'socket'.gettime;
|
||||
|
||||
local log = module._log
|
||||
|
||||
if not ldap then
|
||||
return;
|
||||
end
|
||||
|
||||
local CACHE_EXPIRY = 300;
|
||||
|
||||
----------------------------------------
|
||||
-- Utility Functions --
|
||||
----------------------------------------
|
||||
|
||||
local function ldap_record_to_vcard(record, format)
|
||||
return vcardlib.create {
|
||||
record = record,
|
||||
format = format,
|
||||
}
|
||||
end
|
||||
|
||||
local get_alias_for_user;
|
||||
|
||||
do
|
||||
local user_cache;
|
||||
local last_fetch_time;
|
||||
|
||||
local function populate_user_cache()
|
||||
local user_c = get_config(module.host, 'ldap').user;
|
||||
if not user_c then return; end
|
||||
|
||||
local ld = ldap.getconnection();
|
||||
|
||||
local usernamefield = user_c.usernamefield;
|
||||
local namefield = user_c.namefield;
|
||||
|
||||
user_cache = {};
|
||||
|
||||
for _, attrs in ld:search { base = user_c.basedn, scope = 'onelevel', filter = user_c.filter } do
|
||||
user_cache[attrs[usernamefield]] = attrs[namefield];
|
||||
end
|
||||
last_fetch_time = gettime();
|
||||
end
|
||||
|
||||
function get_alias_for_user(user)
|
||||
if last_fetch_time and last_fetch_time + CACHE_EXPIRY < gettime() then
|
||||
user_cache = nil;
|
||||
end
|
||||
if not user_cache then
|
||||
populate_user_cache();
|
||||
end
|
||||
return user_cache[user];
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
-- Base LDAP store class --
|
||||
----------------------------------------
|
||||
|
||||
local function ldap_store(config)
|
||||
local self = {};
|
||||
local config = config;
|
||||
|
||||
function self:get(username)
|
||||
return nil, "Data getting is not available for this storage backend";
|
||||
end
|
||||
|
||||
function self:set(username, data)
|
||||
return nil, "Data setting is not available for this storage backend";
|
||||
end
|
||||
|
||||
return self;
|
||||
end
|
||||
|
||||
local adapters = {};
|
||||
|
||||
----------------------------------------
|
||||
-- Roster Storage Implementation --
|
||||
----------------------------------------
|
||||
|
||||
adapters.roster = function (config)
|
||||
-- Validate configuration requirements
|
||||
if not config.groups then return nil; end
|
||||
|
||||
local self = ldap_store(config)
|
||||
|
||||
function self:get(username)
|
||||
local ld = ldap.getconnection();
|
||||
local contacts = {};
|
||||
|
||||
local memberfield = config.groups.memberfield;
|
||||
local namefield = config.groups.namefield;
|
||||
local filter = memberfield .. '=' .. tostring(username);
|
||||
|
||||
local groups = {};
|
||||
for _, config in ipairs(config.groups) do
|
||||
groups[ config[namefield] ] = config.name;
|
||||
end
|
||||
|
||||
log("debug", "Found %d group(s) for user %s", select('#', groups), username)
|
||||
|
||||
-- XXX this kind of relies on the way we do groups at INOC
|
||||
for _, attrs in ld:search { base = config.groups.basedn, scope = 'onelevel', filter = filter } do
|
||||
if groups[ attrs[namefield] ] then
|
||||
local members = attrs[memberfield];
|
||||
|
||||
for _, user in ipairs(members) do
|
||||
if user ~= username then
|
||||
local jid = user .. '@' .. module.host;
|
||||
local record = contacts[jid];
|
||||
|
||||
if not record then
|
||||
record = {
|
||||
subscription = 'both',
|
||||
groups = {},
|
||||
name = get_alias_for_user(user),
|
||||
};
|
||||
contacts[jid] = record;
|
||||
end
|
||||
|
||||
record.groups[ groups[ attrs[namefield] ] ] = true;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return contacts;
|
||||
end
|
||||
|
||||
function self:set(username, data)
|
||||
log("warn", "Setting data in Roster LDAP storage is not supported yet")
|
||||
return nil, "not supported";
|
||||
end
|
||||
|
||||
return self;
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
-- vCard Storage Implementation --
|
||||
----------------------------------------
|
||||
|
||||
adapters.vcard = function (config)
|
||||
-- Validate configuration requirements
|
||||
if not config.vcard_format or not config.user then return nil; end
|
||||
|
||||
local self = ldap_store(config)
|
||||
|
||||
function self:get(username)
|
||||
local ld = ldap.getconnection();
|
||||
local filter = config.user.usernamefield .. '=' .. tostring(username);
|
||||
|
||||
log("debug", "Retrieving vCard for user '%s'", username);
|
||||
|
||||
local match = ldap.singlematch {
|
||||
base = config.user.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
if match then
|
||||
match.jid = username .. '@' .. module.host
|
||||
return st.preserialize(ldap_record_to_vcard(match, config.vcard_format));
|
||||
else
|
||||
return nil, "username not found";
|
||||
end
|
||||
end
|
||||
|
||||
function self:set(username, data)
|
||||
log("warn", "Setting data in vCard LDAP storage is not supported yet")
|
||||
return nil, "not supported";
|
||||
end
|
||||
|
||||
return self;
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
-- Driver Definition --
|
||||
----------------------------------------
|
||||
|
||||
cache = {};
|
||||
|
||||
local driver = { name = "ldap" };
|
||||
|
||||
function driver:open(store)
|
||||
log("debug", "Opening ldap storage backend for host '%s' and store '%s'", module.host, store);
|
||||
|
||||
if not cache[module.host] then
|
||||
log("debug", "Caching adapters for the host '%s'", module.host);
|
||||
|
||||
local ad_config = get_config(module.host, "ldap");
|
||||
local ad_cache = {};
|
||||
for k, v in pairs(adapters) do
|
||||
ad_cache[k] = v(ad_config);
|
||||
end
|
||||
|
||||
cache[module.host] = ad_cache;
|
||||
end
|
||||
|
||||
local adapter = cache[module.host][store];
|
||||
|
||||
if not adapter then
|
||||
log("info", "Unavailable adapter for store '%s'", store);
|
||||
return nil, "unsupported-store";
|
||||
end
|
||||
return adapter;
|
||||
end
|
||||
|
||||
function driver:stores(username, type, pattern)
|
||||
return nil, "not implemented";
|
||||
end
|
||||
|
||||
function driver:store_exists(username, type)
|
||||
return nil, "not implemented";
|
||||
end
|
||||
|
||||
function driver:purge(username)
|
||||
return nil, "not implemented";
|
||||
end
|
||||
|
||||
function driver:nodes(type)
|
||||
return nil, "not implemented";
|
||||
end
|
||||
|
||||
module:add_item("data-driver", driver);
|
162
conf/metronome/modules/vcard.lib.lua
Normal file
162
conf/metronome/modules/vcard.lib.lua
Normal file
|
@ -0,0 +1,162 @@
|
|||
-- vim:sts=4 sw=4
|
||||
|
||||
-- Prosody IM
|
||||
-- Copyright (C) 2008-2010 Matthew Wild
|
||||
-- Copyright (C) 2008-2010 Waqas Hussain
|
||||
-- Copyright (C) 2012 Rob Hoelz
|
||||
--
|
||||
-- This project is MIT/X11 licensed. Please see the
|
||||
-- COPYING file in the source package for more information.
|
||||
--
|
||||
|
||||
local st = require 'util.stanza';
|
||||
|
||||
local VCARD_NS = 'vcard-temp';
|
||||
|
||||
local builder_methods = {};
|
||||
|
||||
local base64_encode = require('util.encodings').base64.encode;
|
||||
|
||||
function builder_methods:addvalue(key, value)
|
||||
self.vcard:tag(key):text(value):up();
|
||||
end
|
||||
|
||||
function builder_methods:addphotofield(tagname, format_section)
|
||||
local record = self.record;
|
||||
local format = self.format;
|
||||
local vcard = self.vcard;
|
||||
local config = format[format_section];
|
||||
|
||||
if not config then
|
||||
return;
|
||||
end
|
||||
|
||||
if config.extval then
|
||||
if record[config.extval] then
|
||||
local tag = vcard:tag(tagname);
|
||||
tag:tag('EXTVAL'):text(record[config.extval]):up();
|
||||
end
|
||||
elseif config.type and config.binval then
|
||||
if record[config.binval] then
|
||||
local tag = vcard:tag(tagname);
|
||||
tag:tag('TYPE'):text(config.type):up();
|
||||
tag:tag('BINVAL'):text(base64_encode(record[config.binval])):up();
|
||||
end
|
||||
else
|
||||
module:log('error', 'You have an invalid %s config section', tagname);
|
||||
return;
|
||||
end
|
||||
|
||||
vcard:up();
|
||||
end
|
||||
|
||||
function builder_methods:addregularfield(tagname, format_section)
|
||||
local record = self.record;
|
||||
local format = self.format;
|
||||
local vcard = self.vcard;
|
||||
|
||||
if not format[format_section] then
|
||||
return;
|
||||
end
|
||||
|
||||
local tag = vcard:tag(tagname);
|
||||
|
||||
for k, v in pairs(format[format_section]) do
|
||||
tag:tag(string.upper(k)):text(record[v]):up();
|
||||
end
|
||||
|
||||
vcard:up();
|
||||
end
|
||||
|
||||
function builder_methods:addmultisectionedfield(tagname, format_section)
|
||||
local record = self.record;
|
||||
local format = self.format;
|
||||
local vcard = self.vcard;
|
||||
|
||||
if not format[format_section] then
|
||||
return;
|
||||
end
|
||||
|
||||
for k, v in pairs(format[format_section]) do
|
||||
local tag = vcard:tag(tagname);
|
||||
|
||||
if type(k) == 'string' then
|
||||
tag:tag(string.upper(k)):up();
|
||||
end
|
||||
|
||||
for k2, v2 in pairs(v) do
|
||||
if type(v2) == 'boolean' then
|
||||
tag:tag(string.upper(k2)):up();
|
||||
else
|
||||
tag:tag(string.upper(k2)):text(record[v2]):up();
|
||||
end
|
||||
end
|
||||
|
||||
vcard:up();
|
||||
end
|
||||
end
|
||||
|
||||
function builder_methods:build()
|
||||
local record = self.record;
|
||||
local format = self.format;
|
||||
|
||||
self:addvalue( 'VERSION', '2.0');
|
||||
self:addvalue( 'FN', record[format.displayname]);
|
||||
self:addregularfield( 'N', 'name');
|
||||
self:addvalue( 'NICKNAME', record[format.nickname]);
|
||||
self:addphotofield( 'PHOTO', 'photo');
|
||||
self:addvalue( 'BDAY', record[format.birthday]);
|
||||
self:addmultisectionedfield('ADR', 'address');
|
||||
self:addvalue( 'LABEL', nil); -- we don't support LABEL...yet.
|
||||
self:addmultisectionedfield('TEL', 'telephone');
|
||||
self:addmultisectionedfield('EMAIL', 'email');
|
||||
self:addvalue( 'JABBERID', record.jid);
|
||||
self:addvalue( 'MAILER', record[format.mailer]);
|
||||
self:addvalue( 'TZ', record[format.timezone]);
|
||||
self:addregularfield( 'GEO', 'geo');
|
||||
self:addvalue( 'TITLE', record[format.title]);
|
||||
self:addvalue( 'ROLE', record[format.role]);
|
||||
self:addphotofield( 'LOGO', 'logo');
|
||||
self:addvalue( 'AGENT', nil); -- we don't support AGENT...yet.
|
||||
self:addregularfield( 'ORG', 'org');
|
||||
self:addvalue( 'CATEGORIES', nil); -- we don't support CATEGORIES...yet.
|
||||
self:addvalue( 'NOTE', record[format.note]);
|
||||
self:addvalue( 'PRODID', nil); -- we don't support PRODID...yet.
|
||||
self:addvalue( 'REV', record[format.rev]);
|
||||
self:addvalue( 'SORT-STRING', record[format.sortstring]);
|
||||
self:addregularfield( 'SOUND', 'sound');
|
||||
self:addvalue( 'UID', record[format.uid]);
|
||||
self:addvalue( 'URL', record[format.url]);
|
||||
self:addvalue( 'CLASS', nil); -- we don't support CLASS...yet.
|
||||
self:addregularfield( 'KEY', 'key');
|
||||
self:addvalue( 'DESC', record[format.description]);
|
||||
|
||||
return self.vcard;
|
||||
end
|
||||
|
||||
local function new_builder(params)
|
||||
local vcard_tag = st.stanza('vCard', { xmlns = VCARD_NS });
|
||||
|
||||
local object = {
|
||||
vcard = vcard_tag,
|
||||
__index = builder_methods,
|
||||
};
|
||||
|
||||
for k, v in pairs(params) do
|
||||
object[k] = v;
|
||||
end
|
||||
|
||||
setmetatable(object, object);
|
||||
|
||||
return object;
|
||||
end
|
||||
|
||||
local _M = {};
|
||||
|
||||
function _M.create(params)
|
||||
local builder = new_builder(params);
|
||||
|
||||
return builder:build();
|
||||
end
|
||||
|
||||
return _M;
|
8
conf/nginx/plain/yunohost_panel.conf.inc
Normal file
8
conf/nginx/plain/yunohost_panel.conf.inc
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Insert YunoHost button + portal overlay
|
||||
sub_filter </head> '<script type="text/javascript" src="/ynh_portal.js"></script><link type="text/css" rel="stylesheet" href="/ynh_overlay.css"><script type="text/javascript" src="/ynhtheme/custom_portal.js"></script><link type="text/css" rel="stylesheet" href="/ynhtheme/custom_overlay.css"></head>';
|
||||
sub_filter_once on;
|
||||
# Apply to other mime types than text/html
|
||||
sub_filter_types application/xhtml+xml;
|
||||
# Prevent YunoHost panel files from being blocked by specific app rules
|
||||
location ~ (ynh_portal.js|ynh_overlay.css|ynh_userinfo.json|ynhtheme/custom_portal.js|ynhtheme/custom_overlay.css) {
|
||||
}
|
7
conf/nginx/plain/yunohost_sso.conf.inc
Normal file
7
conf/nginx/plain/yunohost_sso.conf.inc
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Avoid the nginx path/alias traversal weakness ( #1037 )
|
||||
rewrite ^/yunohost/sso$ /yunohost/sso/ permanent;
|
||||
|
||||
location /yunohost/sso/ {
|
||||
# This is an empty location, only meant to avoid other locations
|
||||
# from matching /yunohost/sso, such that it's correctly handled by ssowat
|
||||
}
|
|
@ -3,16 +3,16 @@ ssl_session_cache shared:SSL:50m; # about 200000 sessions
|
|||
ssl_session_tickets off;
|
||||
|
||||
{% if compatibility == "modern" %}
|
||||
# generated 2023-06-13, Mozilla Guideline v5.7, nginx 1.22.1, OpenSSL 3.0.9, modern configuration
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.22.1&config=modern&openssl=3.0.9&guideline=5.7
|
||||
# generated 2020-08-14, Mozilla Guideline v5.6, nginx 1.14.2, OpenSSL 1.1.1d, modern configuration
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=modern&openssl=1.1.1d&guideline=5.6
|
||||
ssl_protocols TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
{% else %}
|
||||
# Ciphers with intermediate compatibility
|
||||
# generated 2023-06-13, Mozilla Guideline v5.7, nginx 1.22.1, OpenSSL 3.0.9, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.22.1&config=intermediate&openssl=3.0.9&guideline=5.7
|
||||
# generated 2020-08-14, Mozilla Guideline v5.6, nginx 1.14.2, OpenSSL 1.1.1d, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=intermediate&openssl=1.1.1d&guideline=5.6
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# Pre-defined FFDHE group (RFC 7919)
|
||||
|
|
|
@ -6,7 +6,7 @@ map $http_upgrade $connection_upgrade {
|
|||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name {{ domain }};
|
||||
server_name {{ domain }}{% if xmpp_enabled == "True" %} xmpp-upload.{{ domain }} muc.{{ domain }}{% endif %};
|
||||
|
||||
access_by_lua_file /usr/share/ssowat/access.lua;
|
||||
|
||||
|
@ -78,3 +78,48 @@ server {
|
|||
access_log /var/log/nginx/{{ domain }}-access.log;
|
||||
error_log /var/log/nginx/{{ domain }}-error.log;
|
||||
}
|
||||
|
||||
{% if xmpp_enabled == "True" %}
|
||||
# vhost dedicated to XMPP http_upload
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name xmpp-upload.{{ domain }};
|
||||
root /dev/null;
|
||||
|
||||
location /upload/ {
|
||||
alias /var/xmpp-upload/{{ domain }}/upload/;
|
||||
# Pass all requests to metronome, except for GET and HEAD requests.
|
||||
limit_except GET HEAD {
|
||||
proxy_pass http://localhost:5290;
|
||||
}
|
||||
|
||||
include proxy_params;
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header 'Access-Control-Allow-Methods' 'HEAD, GET, PUT, OPTIONS';
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization';
|
||||
add_header 'Access-Control-Allow-Credentials' 'true';
|
||||
client_max_body_size 105M; # Choose a value a bit higher than the max upload configured in XMPP server
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/security.conf.inc;
|
||||
|
||||
ssl_certificate /etc/yunohost/certs/{{ domain }}/crt.pem;
|
||||
ssl_certificate_key /etc/yunohost/certs/{{ domain }}/key.pem;
|
||||
|
||||
{% if domain_cert_ca != "selfsigned" %}
|
||||
more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload";
|
||||
{% endif %}
|
||||
{% if domain_cert_ca == "letsencrypt" %}
|
||||
# OCSP settings
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_trusted_certificate /etc/yunohost/certs/{{ domain }}/crt.pem;
|
||||
resolver 1.1.1.1 9.9.9.9 valid=300s;
|
||||
resolver_timeout 5s;
|
||||
{% endif %}
|
||||
|
||||
access_log /var/log/nginx/xmpp-upload.{{ domain }}-access.log;
|
||||
error_log /var/log/nginx/xmpp-upload.{{ domain }}-error.log;
|
||||
}
|
||||
{% endif %}
|
||||
|
|
|
@ -23,24 +23,3 @@ location = /yunohost/api/error/502 {
|
|||
add_header Content-Type text/plain;
|
||||
internal;
|
||||
}
|
||||
|
||||
location /yunohost/portalapi/ {
|
||||
|
||||
proxy_read_timeout 5s;
|
||||
proxy_pass http://127.0.0.1:6788/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
|
||||
# Custom 502 error page
|
||||
error_page 502 /yunohost/portalapi/error/502;
|
||||
}
|
||||
|
||||
|
||||
# Yunohost admin output complete 502 error page, so use only plain text.
|
||||
location = /yunohost/portalapi/error/502 {
|
||||
return 502 '502 - Bad Gateway';
|
||||
add_header Content-Type text/plain;
|
||||
internal;
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# Avoid the nginx path/alias traversal weakness ( #1037 )
|
||||
rewrite ^/yunohost/sso$ /yunohost/sso/ permanent;
|
||||
|
||||
location /yunohost/sso/ {
|
||||
alias /usr/share/yunohost/portal/;
|
||||
default_type text/html;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
location = /yunohost/sso/index.html {
|
||||
etag off;
|
||||
expires off;
|
||||
more_set_headers "Cache-Control: no-store, no-cache, must-revalidate";
|
||||
}
|
||||
|
||||
location /yunohost/sso/applogos/ {
|
||||
alias /usr/share/yunohost/applogos/;
|
||||
}
|
||||
|
||||
more_set_headers "Content-Security-Policy: upgrade-insecure-requests; default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; object-src 'none'; img-src 'self' data:;";
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
# General daemon config
|
||||
Socket inet:8891@localhost
|
||||
PidFile /run/opendkim/opendkim.pid
|
||||
UserID opendkim
|
||||
UMask 007
|
||||
|
||||
AutoRestart yes
|
||||
AutoRestartCount 10
|
||||
AutoRestartRate 10/1h
|
||||
|
||||
# Logging
|
||||
Syslog yes
|
||||
SyslogSuccess yes
|
||||
LogWhy yes
|
||||
|
||||
# Common signing and verification parameters. In Debian, the "From" header is
|
||||
# oversigned, because it is often the identity key used by reputation systems
|
||||
# and thus somewhat security sensitive.
|
||||
Canonicalization relaxed/simple
|
||||
Mode sv
|
||||
OversignHeaders From
|
||||
#On-BadSignature reject
|
||||
|
||||
# Key / signing table
|
||||
KeyTable file:/etc/dkim/keytable
|
||||
SigningTable refile:/etc/dkim/signingtable
|
||||
|
||||
# The trust anchor enables DNSSEC. In Debian, the trust anchor file is provided
|
||||
# by the package dns-root-data.
|
||||
TrustAnchorFile /usr/share/dns/root.key
|
||||
#Nameservers 127.0.0.1
|
|
@ -30,8 +30,8 @@ smtpd_tls_chain_files =
|
|||
tls_server_sni_maps = hash:/etc/postfix/sni
|
||||
|
||||
{% if compatibility == "intermediate" %}
|
||||
# generated 2023-06-13, Mozilla Guideline v5.7, Postfix 3.7.5, OpenSSL 3.0.9, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=postfix&version=3.7.5&config=intermediate&openssl=3.0.9&guideline=5.7
|
||||
# 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
|
||||
|
@ -41,10 +41,10 @@ smtpd_tls_mandatory_ciphers = medium
|
|||
# not actually 1024 bits, this applies to all DHE >= 1024 bits
|
||||
smtpd_tls_dh1024_param_file = /usr/share/yunohost/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:DHE-RSA-CHACHA20-POLY1305
|
||||
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 2023-06-13, Mozilla Guideline v5.7, Postfix 3.7.5, OpenSSL 3.0.9, modern configuration
|
||||
# https://ssl-config.mozilla.org/#server=postfix&version=3.7.5&config=modern&openssl=3.0.9&guideline=5.7
|
||||
# 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
|
||||
|
@ -182,10 +182,9 @@ smtp_header_checks = regexp:/etc/postfix/header_checks
|
|||
smtp_reply_filter = pcre:/etc/postfix/smtp_reply_filter
|
||||
|
||||
# Rmilter
|
||||
milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen} {auth_type}
|
||||
milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}
|
||||
milter_protocol = 6
|
||||
smtpd_milters = inet:localhost:8891
|
||||
non_smtpd_milters = inet:localhost:8891
|
||||
smtpd_milters = inet:localhost:11332
|
||||
|
||||
# Skip email without checking if milter has died
|
||||
milter_default_action = accept
|
||||
|
@ -212,3 +211,11 @@ smtp_sasl_security_options = noanonymous
|
|||
# where to find sasl_passwd
|
||||
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
|
||||
{% endif %}
|
||||
|
||||
{% if backup_mx_domains != "" %}
|
||||
# Backup MX (secondary MX)
|
||||
relay_domains = $mydestination {{backup_mx_domains}}
|
||||
relay_recipient_maps = hash:/etc/postfix/relay_recipients
|
||||
maximal_queue_lifetime = 20d
|
||||
{% endif %}
|
||||
|
||||
|
|
16
conf/rspamd/dkim_signing.conf
Normal file
16
conf/rspamd/dkim_signing.conf
Normal file
|
@ -0,0 +1,16 @@
|
|||
allow_envfrom_empty = true;
|
||||
allow_hdrfrom_mismatch = false;
|
||||
allow_hdrfrom_multiple = false;
|
||||
allow_username_mismatch = true;
|
||||
|
||||
auth_only = true;
|
||||
path = "/etc/dkim/$domain.$selector.key";
|
||||
selector = "mail";
|
||||
sign_local = true;
|
||||
symbol = "DKIM_SIGNED";
|
||||
try_fallback = true;
|
||||
use_domain = "header";
|
||||
use_esld = false;
|
||||
use_redis = false;
|
||||
key_prefix = "DKIM_KEYS";
|
||||
|
8
conf/rspamd/metrics.local.conf
Normal file
8
conf/rspamd/metrics.local.conf
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Metrics settings
|
||||
# This define overridden options.
|
||||
|
||||
actions {
|
||||
reject = 21;
|
||||
add_header = 8;
|
||||
greylist = 4;
|
||||
}
|
9
conf/rspamd/milter_headers.conf
Normal file
9
conf/rspamd/milter_headers.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
use = ["spam-header"];
|
||||
|
||||
routines {
|
||||
spam-header {
|
||||
header = "X-Spam";
|
||||
value = "Yes";
|
||||
remove = 1;
|
||||
}
|
||||
}
|
2
conf/rspamd/redis.conf
Normal file
2
conf/rspamd/redis.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
# set redis server
|
||||
servers = "127.0.0.1";
|
4
conf/rspamd/rspamd.sieve
Normal file
4
conf/rspamd/rspamd.sieve
Normal file
|
@ -0,0 +1,4 @@
|
|||
require ["fileinto"];
|
||||
if header :is "X-Spam" "Yes" {
|
||||
fileinto "Junk";
|
||||
}
|
|
@ -56,6 +56,7 @@ objectClass: groupOfNamesYnh
|
|||
gidNumber: 4002
|
||||
cn: all_users
|
||||
permission: cn=mail.main,ou=permission,dc=yunohost,dc=org
|
||||
permission: cn=xmpp.main,ou=permission,dc=yunohost,dc=org
|
||||
|
||||
dn: cn=visitors,ou=groups,dc=yunohost,dc=org
|
||||
objectClass: posixGroup
|
||||
|
@ -74,6 +75,17 @@ gidNumber: 5001
|
|||
showTile: FALSE
|
||||
authHeader: FALSE
|
||||
|
||||
dn: cn=xmpp.main,ou=permission,dc=yunohost,dc=org
|
||||
groupPermission: cn=all_users,ou=groups,dc=yunohost,dc=org
|
||||
cn: xmpp.main
|
||||
objectClass: posixGroup
|
||||
objectClass: permissionYnh
|
||||
isProtected: TRUE
|
||||
label: XMPP
|
||||
gidNumber: 5002
|
||||
showTile: FALSE
|
||||
authHeader: FALSE
|
||||
|
||||
dn: cn=ssh.main,ou=permission,dc=yunohost,dc=org
|
||||
cn: ssh.main
|
||||
objectClass: posixGroup
|
||||
|
|
|
@ -84,7 +84,7 @@ Subsystem sftp internal-sftp
|
|||
|
||||
# Apply following instructions to user with sftp perm only
|
||||
Match Group sftp.main,!ssh.main
|
||||
ForceCommand internal-sftp
|
||||
ForceCommand internal-sftp -u 0002
|
||||
# We can't restrict to /home/%u because the chroot base must be owned by root
|
||||
# So we chroot only on /home
|
||||
# See https://serverfault.com/questions/584986/bad-ownership-or-modes-for-chroot-directory-component
|
||||
|
@ -97,7 +97,7 @@ Match Group sftp.main,!ssh.main
|
|||
PermitUserRC no
|
||||
|
||||
Match Group sftp.app,!ssh.app
|
||||
ForceCommand internal-sftp
|
||||
ForceCommand internal-sftp -u 0002
|
||||
ChrootDirectory %h
|
||||
AllowTcpForwarding no
|
||||
AllowStreamLocalForwarding no
|
||||
|
|
|
@ -192,7 +192,7 @@ authorityKeyIdentifier=keyid,issuer
|
|||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
subjectAltName=DNS:yunohost.org,DNS:www.yunohost.org,DNS:ns.yunohost.org
|
||||
subjectAltName=DNS:yunohost.org,DNS:www.yunohost.org,DNS:ns.yunohost.org,DNS:xmpp-upload.yunohost.org
|
||||
|
||||
[ v3_ca ]
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@ fail2ban:
|
|||
log: /var/log/fail2ban.log
|
||||
category: security
|
||||
test_conf: fail2ban-server --test
|
||||
metronome:
|
||||
log: [/var/log/metronome/metronome.log,/var/log/metronome/metronome.err]
|
||||
needs_exposed_ports: [5222, 5269]
|
||||
category: xmpp
|
||||
ignore_if_package_is_not_installed: metronome
|
||||
mysql:
|
||||
log: [/var/log/mysql.log,/var/log/mysql.err,/var/log/mysql/error.log]
|
||||
actual_systemd_service: mariadb
|
||||
|
@ -23,22 +28,21 @@ nginx:
|
|||
# log: /var/log/php7.4-fpm.log
|
||||
# test_conf: php-fpm7.4 --test
|
||||
# category: web
|
||||
opendkim:
|
||||
category: email
|
||||
test_conf: opendkim -n
|
||||
postfix:
|
||||
log: [/var/log/mail.log,/var/log/mail.err]
|
||||
actual_systemd_service: postfix@-
|
||||
needs_exposed_ports: [25, 587]
|
||||
category: email
|
||||
postgresql:
|
||||
actual_systemd_service: 'postgresql@15-main'
|
||||
actual_systemd_service: 'postgresql@13-main'
|
||||
category: database
|
||||
ignore_if_package_is_not_installed: postgresql-15
|
||||
ignore_if_package_is_not_installed: postgresql-13
|
||||
redis-server:
|
||||
log: /var/log/redis/redis-server.log
|
||||
category: database
|
||||
ignore_if_package_is_not_installed: redis-server
|
||||
rspamd:
|
||||
log: /var/log/rspamd/rspamd.log
|
||||
category: email
|
||||
slapd:
|
||||
category: database
|
||||
test_conf: slapd -Tt
|
||||
|
@ -47,9 +51,6 @@ ssh:
|
|||
test_conf: sshd -t
|
||||
needs_exposed_ports: [22]
|
||||
category: admin
|
||||
yunohost-portal-api:
|
||||
log: /var/log/yunohost-portal-api.log
|
||||
category: userportal
|
||||
yunohost-api:
|
||||
log: /var/log/yunohost/yunohost-api.log
|
||||
category: admin
|
||||
|
@ -59,6 +60,21 @@ yunohost-firewall:
|
|||
category: security
|
||||
yunomdns:
|
||||
category: mdns
|
||||
glances: null
|
||||
nsswitch: null
|
||||
ssl: null
|
||||
yunohost: null
|
||||
bind9: null
|
||||
tahoe-lafs: null
|
||||
memcached: null
|
||||
udisks2: null
|
||||
udisk-glue: null
|
||||
amavis: null
|
||||
postgrey: null
|
||||
spamassassin: null
|
||||
rmilter: null
|
||||
php5-fpm: null
|
||||
php7.0-fpm: null
|
||||
php7.3-fpm: null
|
||||
nslcd: null
|
||||
avahi-daemon: null
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
[Unit]
|
||||
Description=YunoHost Portal API
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=ynh-portal
|
||||
Group=ynh-portal
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/yunohost-portal-api
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
TimeoutStopSec=30
|
||||
|
||||
# Sandboxing options to harden security
|
||||
# Details for these options: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
|
||||
NoNewPrivileges=yes
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
|
||||
RestrictNamespaces=yes
|
||||
RestrictRealtime=yes
|
||||
DevicePolicy=closed
|
||||
ProtectClock=yes
|
||||
ProtectHostname=yes
|
||||
ProtectProc=invisible
|
||||
ProtectSystem=full
|
||||
ProtectControlGroups=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
LockPersonality=yes
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap @cpu-emulation @privileged
|
||||
|
||||
# Denying access to capabilities that should not be relevant
|
||||
# Doc: https://man7.org/linux/man-pages/man7/capabilities.7.html
|
||||
CapabilityBoundingSet=~CAP_RAWIO CAP_MKNOD
|
||||
CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE
|
||||
CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_PACCT
|
||||
CapabilityBoundingSet=~CAP_LEASE CAP_LINUX_IMMUTABLE CAP_IPC_LOCK
|
||||
CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_WAKE_ALARM
|
||||
CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG
|
||||
CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE
|
||||
CapabilityBoundingSet=~CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW
|
||||
CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYSLOG
|
||||
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
69
debian/changelog
vendored
69
debian/changelog
vendored
|
@ -1,41 +1,52 @@
|
|||
yunohost (12.0.2) testing; urgency=low
|
||||
yunohost (11.2.30) stable; urgency=low
|
||||
|
||||
- Cleanup redis regen conf since redis ain't installed by default anymore (7b50c4eb6)
|
||||
- bullseye->bookworm: add a trick to flag the migration as done if it's still marked as pending (0503a38a7)
|
||||
- Sync with main branch
|
||||
- helpers v2.1: check if patches dir exists before getting realpath ([#1938](http://github.com/YunoHost/yunohost/pull/1938))
|
||||
- helpers v2.1: ynh_add_swap and ynh_smart_mktemp (aff885e6b)
|
||||
- helpers v2.1: fix ynh_restore_everything ([#1943](http://github.com/YunoHost/yunohost/pull/1943))
|
||||
- helpers v2.1: fix typo in docs: ynh_install_app_dependencies -> ynh_apt_install_dependencies ([#1939](http://github.com/YunoHost/yunohost/pull/1939))
|
||||
- helpers: fix syntax, disambiguate subshell syntax ([#1940](http://github.com/YunoHost/yunohost/pull/1940))
|
||||
- quality: Add maintenante/shfmt.sh for shell script formatting (68f35831e)
|
||||
- quality: Apply shfmt everywhere, fix tabs/space/indent (8a5f2808a, e3ddb1dc4, ef1708276, 38b39ebae, b91e9dd8f)
|
||||
|
||||
Thanks to all contributors <3 ! (Kayou)
|
||||
Thanks to all contributors <3 ! (Félix Piédallu, Josué Tille, OniriCorpe, selfhoster1312)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 01 Aug 2024 18:08:33 +0200
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 31 Aug 2024 19:26:59 +0200
|
||||
|
||||
yunohost (12.0.1) testing; urgency=low
|
||||
yunohost (11.2.29) stable; urgency=low
|
||||
|
||||
- The user portal and SSO system have been reworked and split into three distinct pieces
|
||||
- SSOwat only handling only the SSO/ACL logic (nginx lua middleware)
|
||||
- A new “portal API” (yunohost-portal-api) service delivering authentication cookies and allowing users to retrieve/update infos
|
||||
- A new portal front end (yunohost-portal)
|
||||
- More information on the release note on the forum
|
||||
- The base system does not install Mysql/Mariadb and PHP anymore
|
||||
- Rspamd (antispam system) and Metronome (XMPP server) are not part of the core anymore. Instead, they are now separate applications : rspamd_ynh and metronome_ynh
|
||||
- webadmin: rework cookie/session expiration mechanism. Cookies are now still valid after restarting the API (preventing clumsy disconnect during self-upgrades) and the cookie validity is automatically extended every time an API request is performed.
|
||||
- mail: DKIM email signing is now done using opendkim instead of rspamd
|
||||
- various compatibility tweakings for Bookworm
|
||||
- regenconf: update nginx and dovecot ciphers according to Mozilla recommendation
|
||||
- regenconf: update fail2ban config
|
||||
- configpanels: refactor to use pydantic for more typing and consistency, add proper autogenerated doc
|
||||
- apps: Yarn third-party repo is now available by default in apt config just like Sury, no need for an extra apt resource thingy
|
||||
- various legacy cleanups (more info on the release note on the forum)
|
||||
- perf: minimize regen-conf calls to yunohost settings get, and other misc lazy-loading optimizations
|
||||
- quality: simplify the logging mess
|
||||
- quality: rework ci tests workflow
|
||||
- apps: generalize replacing __INSTALL_DIR__ and __APP__ in config panel 'bind' statement to any setting (9b0553580)
|
||||
- apps/config panels: move the computation of the actual 'bind' value to the python core (a6785d34b)
|
||||
- perf: add cache for _get_app_settings() (c14ebc8be, 7c7906046)
|
||||
- quality: use _assert_is_installed for consistency instead of if not _is_intalled(app): raise (c409888a4)
|
||||
- i18n: Translations updated for Basque, French, Galician, Greek, Indonesian
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 26 Jul 2024 22:40:16 +0200
|
||||
Thanks to all contributors <3 ! (cjdw, craftrac, José M, ppr, xabirequejo)
|
||||
|
||||
yunohost (12.0.0) unstable; urgency=low
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 27 Aug 2024 14:46:26 +0200
|
||||
|
||||
- Tmp changelog to prepare Bookworm
|
||||
yunohost (11.2.28) stable; urgency=low
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 04 May 2023 20:30:19 +0200
|
||||
- ci: various changes due to CI infrastructure changes (200f0272d, 764fe6a7b, 9083a5cc3, d0df3caed, 6733526be, df320a44c, 92f4a605b, f02d4a437, c5953b542)
|
||||
- apps: exclude .well-known subpaths from conflict checks ([#1647](http://github.com/YunoHost/yunohost/pull/1647))
|
||||
- apps: in apt resource, fix empty string in packages_from_raw_bash breaking dpkg-build (a76cd05e8)
|
||||
- sftp: Tweak umask for SFTP ([#1384](http://github.com/YunoHost/yunohost/pull/1384))
|
||||
- mail: Be able to use postfix as a backup ("secondary") MX hosts ([#1253](http://github.com/YunoHost/yunohost/pull/1253))
|
||||
- diagnosis: Add check regarding rfkill blocking Wi-Fi card on RPi ([#1841](http://github.com/YunoHost/yunohost/pull/1841))
|
||||
- users: trigger hooks when adding or removing user into group (51787a2f8)
|
||||
- i18n: Translations updated for Basque, French, Indonesian, Russian
|
||||
|
||||
Thanks to all contributors <3 ! (cjdw, Emmanuel Averty, Ivan Davydov, ljf, ppr, Tagada, tituspijean, xabirequejo)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 25 Aug 2024 13:17:43 +0200
|
||||
|
||||
yunohost (11.2.27) stable; urgency=low
|
||||
|
||||
- apt resource: fix handling of empty 'packages' list breaking dpkg-deb call (3deffdbd5)
|
||||
- i18n: Translations updated for Indonesian, Turkish
|
||||
|
||||
Thanks to all contributors <3 ! (Ali Çırçır, cjdw)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 03 Aug 2024 18:41:27 +0200
|
||||
|
||||
yunohost (11.2.26) stable; urgency=low
|
||||
|
||||
|
|
40
debian/control
vendored
40
debian/control
vendored
|
@ -2,22 +2,21 @@ Source: yunohost
|
|||
Section: utils
|
||||
Priority: extra
|
||||
Maintainer: YunoHost Contributors <contrib@yunohost.org>
|
||||
Build-Depends: debhelper (>=9), debhelper-compat (= 13), dh-python, python3-all (>= 3.11), python3-yaml, python3-jinja2 (>= 3.0)
|
||||
Build-Depends: debhelper (>=9), debhelper-compat (= 13), dh-python, python3-all (>= 3.7), python3-yaml, python3-jinja2
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://yunohost.org/
|
||||
|
||||
Package: yunohost
|
||||
Essential: yes
|
||||
Architecture: all
|
||||
Depends: python3-all (>= 3.11),
|
||||
, moulinette (>= 12.0), ssowat (>= 12.0),
|
||||
Depends: ${python3:Depends}, ${misc:Depends}
|
||||
, moulinette (>= 11.1), moulinette (<< 12.0), ssowat (>= 11.1), ssowat (<< 12.0)
|
||||
, python3-psutil, python3-requests, python3-dnspython, python3-openssl
|
||||
, python3-miniupnpc, python3-dbus, python3-jinja2 (>= 3.0)
|
||||
, python3-miniupnpc, python3-dbus, python3-jinja2
|
||||
, python3-toml, python3-packaging, python3-publicsuffix2
|
||||
, python3-ldap, python3-zeroconf (>= 0.47), python3-lexicon,
|
||||
, python3-cryptography, python3-jwt, python3-passlib, python3-magic
|
||||
, python-is-python3, python3-pydantic, python3-email-validator
|
||||
, nginx, nginx-extras (>=1.22)
|
||||
, python3-ldap, python3-zeroconf (>= 0.36), python3-lexicon,
|
||||
, python-is-python3
|
||||
, nginx, nginx-extras (>=1.18)
|
||||
, apt, apt-transport-https, apt-utils, aptitude, dirmngr
|
||||
, openssh-server, iptables, fail2ban, bind9-dnsutils
|
||||
, openssl, ca-certificates, netcat-openbsd, iproute2
|
||||
|
@ -25,26 +24,31 @@ Depends: python3-all (>= 3.11),
|
|||
, dnsmasq, resolvconf, libnss-myhostname
|
||||
, postfix, postfix-ldap, postfix-policyd-spf-perl, postfix-pcre
|
||||
, dovecot-core, dovecot-ldap, dovecot-lmtpd, dovecot-managesieved, dovecot-antispam
|
||||
, opendkim-tools, opendkim, postsrsd, procmail, mailutils
|
||||
, rspamd, opendkim-tools, postsrsd, procmail, mailutils
|
||||
, redis-server
|
||||
, acl
|
||||
, git, curl, wget, cron, unzip, jq, bc, at, procps, j2cli
|
||||
, lsb-release, haveged, fake-hwclock, lsof, whois
|
||||
Recommends: yunohost-admin, yunohost-portal (>= 12.0)
|
||||
Recommends: yunohost-admin
|
||||
, ntp, inetutils-ping | iputils-ping
|
||||
, bash-completion, rsyslog
|
||||
, php7.4-common, php7.4-fpm, php7.4-ldap, php7.4-intl
|
||||
, mariadb-server, php7.4-mysql
|
||||
, php7.4-gd, php7.4-curl, php-php-gettext
|
||||
, python3-pip
|
||||
, unattended-upgrades
|
||||
, libdbd-ldap-perl, libnet-dns-perl
|
||||
, metronome (>=3.14.0)
|
||||
Conflicts: iptables-persistent
|
||||
, apache2
|
||||
, bind9
|
||||
, openresolv
|
||||
, systemd-resolved
|
||||
, nginx-extras (>= 1.23)
|
||||
, openssl (>= 3.1)
|
||||
, slapd (>= 2.6)
|
||||
, dovecot-core (>= 1:2.4)
|
||||
, fail2ban (>= 1.1)
|
||||
, iptables (>= 1.8.10)
|
||||
, nginx-extras (>= 1.19)
|
||||
, openssl (>= 3.0)
|
||||
, slapd (>= 2.4.58)
|
||||
, dovecot-core (>= 1:2.3.14)
|
||||
, redis-server (>= 5:6.1)
|
||||
, fail2ban (>= 0.11.3)
|
||||
, iptables (>= 1.8.8)
|
||||
Description: manageable and configured self-hosting server
|
||||
YunoHost aims to make self-hosting accessible to everyone. It configures
|
||||
an email, Web and IM server alongside a LDAP base. It also provides
|
||||
|
|
1
debian/install
vendored
1
debian/install
vendored
|
@ -6,4 +6,5 @@ conf/* /usr/share/yunohost/conf/
|
|||
locales/* /usr/share/yunohost/locales/
|
||||
doc/yunohost.8.gz /usr/share/man/man8/
|
||||
doc/bash_completion.d/* /etc/bash_completion.d/
|
||||
conf/metronome/modules/* /usr/lib/metronome/modules/
|
||||
src/* /usr/lib/python3/dist-packages/yunohost/
|
||||
|
|
8
debian/postinst
vendored
8
debian/postinst
vendored
|
@ -4,10 +4,6 @@ set -e
|
|||
|
||||
do_configure() {
|
||||
|
||||
mkdir -p /etc/yunohost
|
||||
mkdir -p /etc/yunohost/apps
|
||||
mkdir -p /etc/yunohost/portal
|
||||
|
||||
if [ ! -f /etc/yunohost/installed ]; then
|
||||
# If apps/ is not empty, we're probably already installed in the past and
|
||||
# something funky happened ...
|
||||
|
@ -31,14 +27,12 @@ do_configure() {
|
|||
yunohost tools migrations run --auto
|
||||
|
||||
echo "Re-diagnosing server health..."
|
||||
yunohost diagnosis run --force
|
||||
[[ -n "${YNH_SKIP_DIAGNOSIS_DURING_UPGRADE:-}" ]] && echo "(Skipping)" || yunohost diagnosis run --force
|
||||
|
||||
echo "Refreshing app catalog..."
|
||||
yunohost tools update apps --output-as none || true
|
||||
fi
|
||||
|
||||
systemctl restart yunohost-portal-api
|
||||
|
||||
# Trick to let yunohost handle the restart of the API,
|
||||
# to prevent the webadmin from cutting the branch it's sitting on
|
||||
if systemctl is-enabled yunohost-api --quiet
|
||||
|
|
|
@ -1,181 +0,0 @@
|
|||
import ast
|
||||
import datetime
|
||||
import subprocess
|
||||
|
||||
version = open("../debian/changelog").readlines()[0].split()[1].strip("()")
|
||||
today = datetime.datetime.now().strftime("%d/%m/%Y")
|
||||
|
||||
|
||||
def get_current_commit():
|
||||
p = subprocess.Popen(
|
||||
"git rev-parse --verify HEAD",
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
stdout, stderr = p.communicate()
|
||||
|
||||
current_commit = stdout.strip().decode("utf-8")
|
||||
return current_commit
|
||||
|
||||
|
||||
current_commit = get_current_commit()
|
||||
|
||||
|
||||
def print_config_panel_docs():
|
||||
fname = "../src/utils/configpanel.py"
|
||||
content = open(fname).read()
|
||||
|
||||
# NB: This magic is because we want to be able to run this script outside of a YunoHost context,
|
||||
# in which we cant really 'import' the file because it will trigger a bunch of moulinette/yunohost imports...
|
||||
tree = ast.parse(content)
|
||||
|
||||
ConfigPanelClasses = reversed(
|
||||
[
|
||||
c
|
||||
for c in tree.body
|
||||
if isinstance(c, ast.ClassDef)
|
||||
and c.name in {"SectionModel", "PanelModel", "ConfigPanelModel"}
|
||||
]
|
||||
)
|
||||
|
||||
print("## Configuration panel structure")
|
||||
|
||||
for c in ConfigPanelClasses:
|
||||
doc = ast.get_docstring(c)
|
||||
print("")
|
||||
print(f"### {c.name.replace('Model', '')}")
|
||||
print("")
|
||||
print(doc)
|
||||
print("")
|
||||
print("---")
|
||||
|
||||
|
||||
def print_form_doc():
|
||||
fname = "../src/utils/form.py"
|
||||
content = open(fname).read()
|
||||
|
||||
# NB: This magic is because we want to be able to run this script outside of a YunoHost context,
|
||||
# in which we cant really 'import' the file because it will trigger a bunch of moulinette/yunohost imports...
|
||||
tree = ast.parse(content)
|
||||
|
||||
OptionClasses = [
|
||||
c
|
||||
for c in tree.body
|
||||
if isinstance(c, ast.ClassDef) and c.name.endswith("Option")
|
||||
]
|
||||
|
||||
OptionDocString = {}
|
||||
|
||||
print("## List of all option types")
|
||||
|
||||
for c in OptionClasses:
|
||||
if not isinstance(c.body[0], ast.Expr):
|
||||
continue
|
||||
option_type = None
|
||||
|
||||
if c.name in {"BaseOption", "BaseInputOption"}:
|
||||
option_type = c.name
|
||||
elif c.body[1].target.id == "type":
|
||||
option_type = c.body[1].value.attr
|
||||
|
||||
generaltype = (
|
||||
c.bases[0].id.replace("Option", "").replace("Base", "").lower()
|
||||
if c.bases
|
||||
else None
|
||||
)
|
||||
|
||||
docstring = ast.get_docstring(c)
|
||||
if docstring:
|
||||
if "#### Properties" not in docstring:
|
||||
docstring += """
|
||||
#### Properties
|
||||
|
||||
- [common properties](#common-properties)"""
|
||||
OptionDocString[option_type] = {
|
||||
"doc": docstring,
|
||||
"generaltype": generaltype,
|
||||
}
|
||||
|
||||
# Dirty hack to have "BaseOption" as first and "BaseInputOption" as 2nd in list
|
||||
|
||||
base = OptionDocString.pop("BaseOption")
|
||||
baseinput = OptionDocString.pop("BaseInputOption")
|
||||
OptionDocString2 = {
|
||||
"BaseOption": base,
|
||||
"BaseInputOption": baseinput,
|
||||
}
|
||||
OptionDocString2.update(OptionDocString)
|
||||
|
||||
for option_type, infos in OptionDocString2.items():
|
||||
if option_type == "display_text":
|
||||
# display_text is kind of legacy x_x
|
||||
continue
|
||||
print("")
|
||||
if option_type == "BaseOption":
|
||||
print("### Common properties")
|
||||
elif option_type == "BaseInputOption":
|
||||
print("### Common inputs properties")
|
||||
else:
|
||||
print(
|
||||
f"### `{option_type}`"
|
||||
+ (f" ({infos['generaltype']})" if infos["generaltype"] else "")
|
||||
)
|
||||
print("")
|
||||
print(infos["doc"])
|
||||
print("")
|
||||
print("---")
|
||||
|
||||
|
||||
print(
|
||||
rf"""---
|
||||
title: Technical details for config panel structure and form option types
|
||||
template: docs
|
||||
taxonomy:
|
||||
category: docs
|
||||
routes:
|
||||
default: '/dev/forms'
|
||||
---
|
||||
|
||||
Doc auto-generated by [this script](https://github.com/YunoHost/yunohost/blob/{current_commit}/doc/generate_options_doc.py) on {today} (YunoHost version {version})
|
||||
|
||||
## Glossary
|
||||
|
||||
You may encounter some named types which are used for simplicity.
|
||||
|
||||
- `Translation`: a translated property
|
||||
- used for properties: `ask`, `help` and `Pattern.error`
|
||||
- a `dict` with locales as keys and translations as values:
|
||||
```toml
|
||||
ask.en = "The text in english"
|
||||
ask.fr = "Le texte en français"
|
||||
```
|
||||
It is not currently possible for translators to translate those string in weblate.
|
||||
- a single `str` for a single english default string
|
||||
```toml
|
||||
help = "The text in english"
|
||||
```
|
||||
- `JSExpression`: a `str` JS expression to be evaluated to `true` or `false`:
|
||||
- used for properties: `visible` and `enabled`
|
||||
- operators availables: `==`, `!=`, `>`, `>=`, `<`, `<=`, `!`, `&&`, `||`, `+`, `-`, `*`, `/`, `%` and `match()`
|
||||
- `Binding`: bind a value to a file/property/variable/getter/setter/validator
|
||||
- save the value in `settings.yaml` when not defined
|
||||
- nothing at all with `"null"`
|
||||
- a custom getter/setter/validator with `"null"` + a function starting with `get__`, `set__`, `validate__` in `scripts/config`
|
||||
- a variable/property in a file with `:__FINALPATH__/my_file.php`
|
||||
- a whole file with `__FINALPATH__/my_file.php`
|
||||
- `Pattern`: a `dict` with a regex to match the value against and an error message
|
||||
```toml
|
||||
pattern.regexp = '^[A-F]\d\d$'
|
||||
pattern.error = "Provide a room number such as F12: one uppercase and 2 numbers"
|
||||
# or with translated error
|
||||
pattern.error.en = "Provide a room number such as F12: one uppercase and 2 numbers"
|
||||
pattern.error.fr = "Entrez un numéro de salle comme F12: une lettre majuscule et deux chiffres."
|
||||
```
|
||||
- IMPORTANT: your `pattern.regexp` should be between simple quote, not double.
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
print_config_panel_docs()
|
||||
print_form_doc()
|
|
@ -1,4 +0,0 @@
|
|||
from yunohost.utils.configpanel import ConfigPanelModel
|
||||
|
||||
|
||||
print(ConfigPanelModel.schema_json(indent=2))
|
|
@ -21,6 +21,7 @@ case "$YNH_HELPERS_VERSION" in
|
|||
*)
|
||||
echo "Helpers are not available in version '$YNH_HELPERS_VERSION'." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
eval "$XTRACE_ENABLE"
|
||||
|
|
|
@ -19,8 +19,7 @@ ynh_install_apps() {
|
|||
local apps_dependencies=""
|
||||
|
||||
# For each app
|
||||
for one_app_and_its_args in "${apps_list[@]}"
|
||||
do
|
||||
for one_app_and_its_args in "${apps_list[@]}"; do
|
||||
# Retrieve the name of the app (part before ?)
|
||||
local one_app=$(cut -d "?" -f1 <<< "$one_app_and_its_args")
|
||||
[ -z "$one_app" ] && ynh_die --message="You didn't provided a YunoHost app to install"
|
||||
|
@ -28,8 +27,7 @@ ynh_install_apps() {
|
|||
yunohost tools update apps
|
||||
|
||||
# Installing or upgrading the app depending if it's installed or not
|
||||
if ! yunohost app list --output-as json --quiet | jq -e --arg id $one_app '.apps[] | select(.id == $id)' >/dev/null
|
||||
then
|
||||
if ! yunohost app list --output-as json --quiet | jq -e --arg id $one_app '.apps[] | select(.id == $id)' > /dev/null; then
|
||||
# Retrieve the arguments of the app (part after ?)
|
||||
local one_argument=""
|
||||
if [[ "$one_app_and_its_args" == *"?"* ]]; then
|
||||
|
@ -44,8 +42,7 @@ ynh_install_apps() {
|
|||
yunohost app upgrade $one_app
|
||||
fi
|
||||
|
||||
if [ ! -z "$apps_dependencies" ]
|
||||
then
|
||||
if [ ! -z "$apps_dependencies" ]; then
|
||||
apps_dependencies="$apps_dependencies, $one_app"
|
||||
else
|
||||
apps_dependencies="$one_app"
|
||||
|
@ -67,31 +64,26 @@ ynh_remove_apps() {
|
|||
local apps_dependencies=$(ynh_app_setting_get --app=$app --key=apps_dependencies)
|
||||
ynh_app_setting_delete --app=$app --key=apps_dependencies
|
||||
|
||||
if [ ! -z "$apps_dependencies" ]
|
||||
then
|
||||
if [ ! -z "$apps_dependencies" ]; then
|
||||
# Split the list of apps dependencies in an array
|
||||
local apps_dependencies_list=($(echo $apps_dependencies | tr ", " "\n"))
|
||||
|
||||
# For each apps dependencies
|
||||
for one_app in "${apps_dependencies_list[@]}"
|
||||
do
|
||||
for one_app in "${apps_dependencies_list[@]}"; do
|
||||
# Retrieve the list of installed apps
|
||||
local installed_apps_list=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
|
||||
local required_by=""
|
||||
local installed_app_required_by=""
|
||||
|
||||
# For each other installed app
|
||||
for one_installed_app in $installed_apps_list
|
||||
do
|
||||
for one_installed_app in $installed_apps_list; do
|
||||
# Retrieve the other apps dependencies
|
||||
one_installed_apps_dependencies=$(ynh_app_setting_get --app=$one_installed_app --key=apps_dependencies)
|
||||
if [ ! -z "$one_installed_apps_dependencies" ]
|
||||
then
|
||||
if [ ! -z "$one_installed_apps_dependencies" ]; then
|
||||
one_installed_apps_dependencies_list=($(echo $one_installed_apps_dependencies | tr ", " "\n"))
|
||||
|
||||
# For each dependency of the other apps
|
||||
for one_installed_app_dependency in "${one_installed_apps_dependencies_list[@]}"
|
||||
do
|
||||
for one_installed_app_dependency in "${one_installed_apps_dependencies_list[@]}"; do
|
||||
if [[ $one_installed_app_dependency == $one_app ]]; then
|
||||
required_by="$required_by $one_installed_app"
|
||||
fi
|
||||
|
@ -100,8 +92,7 @@ ynh_remove_apps() {
|
|||
done
|
||||
|
||||
# If $one_app is no more required
|
||||
if [[ -z "$required_by" ]]
|
||||
then
|
||||
if [[ -z "$required_by" ]]; then
|
||||
# Remove $one_app
|
||||
ynh_print_info --message="Removing of $one_app"
|
||||
yunohost app remove $one_app --purge
|
||||
|
@ -134,16 +125,14 @@ ynh_spawn_app_shell() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
|
||||
# Force Bash to be used to run this helper
|
||||
if [[ ! $0 =~ \/?bash$ ]]
|
||||
then
|
||||
if [[ ! $0 =~ \/?bash$ ]]; then
|
||||
ynh_print_err --message="Please use Bash as shell"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure the app is installed
|
||||
local installed_apps_list=($(yunohost app list --output-as json --quiet | jq -r .apps[].id))
|
||||
if [[ " ${installed_apps_list[*]} " != *" ${app} "* ]]
|
||||
then
|
||||
if [[ " ${installed_apps_list[*]} " != *" ${app} "* ]]; then
|
||||
ynh_print_err --message="$app is not in the apps list"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -156,49 +145,44 @@ ynh_spawn_app_shell() {
|
|||
|
||||
# Make sure the app has an install_dir setting
|
||||
local install_dir=$(ynh_app_setting_get --app=$app --key=install_dir)
|
||||
if [ -z "$install_dir" ]
|
||||
then
|
||||
if [ -z "$install_dir" ]; then
|
||||
ynh_print_err --message="$app has no install_dir setting (does it use packaging format >=2?)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Load the app's service name, or default to $app
|
||||
local service=$(ynh_app_setting_get --app=$app --key=service)
|
||||
[ -z "$service" ] && service=$app;
|
||||
[ -z "$service" ] && service=$app
|
||||
|
||||
# Export HOME variable
|
||||
export HOME=$install_dir;
|
||||
export HOME=$install_dir
|
||||
|
||||
# Load the Environment variables from the app's service
|
||||
local env_var=$(systemctl show $service.service -p "Environment" --value)
|
||||
[ -n "$env_var" ] && export $env_var;
|
||||
[ -n "$env_var" ] && export $env_var
|
||||
|
||||
# Force `php` to its intended version
|
||||
# We use `eval`+`export` since `alias` is not propagated to subshells, even with `export`
|
||||
local phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||
local phpflags=$(ynh_app_setting_get --app=$app --key=phpflags)
|
||||
if [ -n "$phpversion" ]
|
||||
then
|
||||
if [ -n "$phpversion" ]; then
|
||||
eval "php() { php${phpversion} ${phpflags} \"\$@\"; }"
|
||||
export -f php
|
||||
fi
|
||||
|
||||
# Source the EnvironmentFiles from the app's service
|
||||
local env_files=($(systemctl show $service.service -p "EnvironmentFiles" --value))
|
||||
if [ ${#env_files[*]} -gt 0 ]
|
||||
then
|
||||
if [ ${#env_files[*]} -gt 0 ]; then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
for file in ${env_files[*]}
|
||||
do
|
||||
for file in ${env_files[*]}; do
|
||||
[[ $file = /* ]] && source $file
|
||||
done
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Activate the Python environment, if it exists
|
||||
if [ -f $install_dir/venv/bin/activate ]
|
||||
then
|
||||
if [ -f $install_dir/venv/bin/activate ]; then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
source $install_dir/venv/bin/activate
|
||||
|
@ -207,7 +191,7 @@ ynh_spawn_app_shell() {
|
|||
|
||||
# cd into the WorkingDirectory set in the service, or default to the install_dir
|
||||
local env_dir=$(systemctl show $service.service -p "WorkingDirectory" --value)
|
||||
[ -z $env_dir ] && env_dir=$install_dir;
|
||||
[ -z $env_dir ] && env_dir=$install_dir
|
||||
cd $env_dir
|
||||
|
||||
# Spawn the app shell
|
||||
|
|
|
@ -266,8 +266,7 @@ ynh_install_app_dependencies() {
|
|||
# The (?<=php) syntax corresponds to lookbehind ;)
|
||||
local specific_php_version=$(echo $dependencies | grep -oP '(?<=php)[0-9.]+(?=-|\>|)' | sort -u)
|
||||
|
||||
if [[ -n "$specific_php_version" ]]
|
||||
then
|
||||
if [[ -n "$specific_php_version" ]]; then
|
||||
# Cover a small edge case where a packager could have specified "php7.4-pwet php5-gni" which is confusing
|
||||
[[ $(echo $specific_php_version | wc -l) -eq 1 ]] \
|
||||
|| ynh_die --message="Inconsistent php versions in dependencies ... found : $specific_php_version"
|
||||
|
@ -281,8 +280,7 @@ ynh_install_app_dependencies() {
|
|||
local old_php_fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
|
||||
local old_php_finalphpconf="$old_php_fpm_config_dir/pool.d/$app.conf"
|
||||
|
||||
if [[ -f "$old_php_finalphpconf" ]]
|
||||
then
|
||||
if [[ -f "$old_php_finalphpconf" ]]; then
|
||||
ynh_backup_if_checksum_is_different --file="$old_php_finalphpconf"
|
||||
ynh_remove_fpm_config
|
||||
fi
|
||||
|
@ -291,8 +289,7 @@ ynh_install_app_dependencies() {
|
|||
ynh_app_setting_set --app=$app --key=phpversion --value=$specific_php_version
|
||||
|
||||
# Set the default php version back as the default version for php-cli.
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
then
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
|
||||
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
fi
|
||||
elif grep --quiet 'php' <<< "$dependencies"; then
|
||||
|
@ -306,13 +303,11 @@ ynh_install_app_dependencies() {
|
|||
# upgrade script where ynh_install_app_dependencies is called with this
|
||||
# expected effect) Otherwise, any subsequent call will add dependencies
|
||||
# to those already present in the equivs control file.
|
||||
if [[ $YNH_INSTALL_APP_DEPENDENCIES_REPLACE == "true" ]]
|
||||
then
|
||||
if [[ $YNH_INSTALL_APP_DEPENDENCIES_REPLACE == "true" ]]; then
|
||||
YNH_INSTALL_APP_DEPENDENCIES_REPLACE="false"
|
||||
else
|
||||
local current_dependencies=""
|
||||
if ynh_package_is_installed --package="${dep_app}-ynh-deps"
|
||||
then
|
||||
if ynh_package_is_installed --package="${dep_app}-ynh-deps"; then
|
||||
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${dep_app}-ynh-deps) "
|
||||
current_dependencies=${current_dependencies// | /|}
|
||||
fi
|
||||
|
@ -337,8 +332,7 @@ EOF
|
|||
|
||||
# Trigger postgresql regenconf if we may have just installed postgresql
|
||||
local psql_installed2="$(ynh_package_is_installed "postgresql-$PSQL_VERSION" && echo yes || echo no)"
|
||||
if [[ "$psql_installed" != "$psql_installed2" ]]
|
||||
then
|
||||
if [[ "$psql_installed" != "$psql_installed2" ]]; then
|
||||
yunohost tools regen-conf postgresql
|
||||
fi
|
||||
|
||||
|
@ -382,16 +376,14 @@ ynh_remove_app_dependencies() {
|
|||
|
||||
# Edge case where the app dep may be on hold,
|
||||
# cf https://forum.yunohost.org/t/migration-error-cause-of-ffsync/20675/4
|
||||
if apt-mark showhold | grep -q -w ${dep_app}-ynh-deps
|
||||
then
|
||||
if apt-mark showhold | grep -q -w ${dep_app}-ynh-deps; then
|
||||
apt-mark unhold ${dep_app}-ynh-deps
|
||||
fi
|
||||
|
||||
# Remove the fake package and its dependencies if they not still used.
|
||||
# (except if dpkg doesn't know anything about the package,
|
||||
# which should be symptomatic of a failed install, and we don't want bash to report an error)
|
||||
if dpkg-query --show ${dep_app}-ynh-deps &>/dev/null
|
||||
then
|
||||
if dpkg-query --show ${dep_app}-ynh-deps &> /dev/null; then
|
||||
ynh_package_autopurge ${dep_app}-ynh-deps
|
||||
fi
|
||||
}
|
||||
|
@ -487,8 +479,10 @@ ynh_install_extra_repo() {
|
|||
if [[ "${repo_parts[0]}" == "deb" ]]; then
|
||||
index=1
|
||||
fi
|
||||
uri="${repo_parts[$index]}" ; index=$((index+1))
|
||||
suite="${repo_parts[$index]}" ; index=$((index+1))
|
||||
uri="${repo_parts[$index]}"
|
||||
index=$((index + 1))
|
||||
suite="${repo_parts[$index]}"
|
||||
index=$((index + 1))
|
||||
|
||||
# Get the components
|
||||
if (("${#repo_parts[@]}" > 0)); then
|
||||
|
|
|
@ -289,8 +289,7 @@ ynh_restore_file() {
|
|||
# Boring hack for nginx conf file mapped to php7.3
|
||||
# Note that there's no need to patch the fpm config because most php apps
|
||||
# will call "ynh_add_fpm_config" during restore, effectively recreating the file from scratch
|
||||
if [[ "${dest_path}" == "/etc/nginx/conf.d/"* ]] && grep 'php7.3.*sock' "${dest_path}"
|
||||
then
|
||||
if [[ "${dest_path}" == "/etc/nginx/conf.d/"* ]] && grep 'php7.3.*sock' "${dest_path}"; then
|
||||
sed -i 's/php7.3/php7.4/g' "${dest_path}"
|
||||
fi
|
||||
}
|
||||
|
@ -376,8 +375,7 @@ ynh_backup_if_checksum_is_different() {
|
|||
echo "$backup_file_checksum" # Return the name of the backup file
|
||||
if [ ${PACKAGE_CHECK_EXEC:-0} -eq 1 ]; then
|
||||
local file_path_base64=$(echo "$file" | base64 -w0)
|
||||
if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64}
|
||||
then
|
||||
if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64}; then
|
||||
ynh_print_warn "Diff with the original file:"
|
||||
diff --report-identical-files --unified --color=always /var/cache/yunohost/appconfbackup/original_${file_path_base64} $file >&2 || true
|
||||
fi
|
||||
|
@ -494,8 +492,7 @@ ynh_restore_upgradebackup() {
|
|||
yunohost app remove $app
|
||||
# Restore the backup
|
||||
yunohost backup restore $app_bck-pre-upgrade$backup_number --apps $app --force --debug
|
||||
if [[ -d /etc/yunohost/apps/$app ]]
|
||||
then
|
||||
if [[ -d /etc/yunohost/apps/$app ]]; then
|
||||
ynh_die --message="The app was restored to the way it was before the failed upgrade."
|
||||
else
|
||||
ynh_die --message="Uhoh ... Yunohost failed to restore the app to the way it was before the failed upgrade :|"
|
||||
|
|
|
@ -22,7 +22,7 @@ _ynh_app_config_get_one() {
|
|||
if [[ "$bind" == "settings" ]]; then
|
||||
ynh_die --message="File '${short_setting}' can't be stored in settings"
|
||||
fi
|
||||
old[$short_setting]="$(ls "$(echo $bind | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s@__FINALPATH__@${final_path:-}@ | sed s/__APP__/$app/)" 2>/dev/null || echo YNH_NULL)"
|
||||
old[$short_setting]="$(ls "$bind" 2> /dev/null || echo YNH_NULL)"
|
||||
file_hash[$short_setting]="true"
|
||||
|
||||
# Get multiline text from settings or from a full file
|
||||
|
@ -32,7 +32,7 @@ _ynh_app_config_get_one() {
|
|||
elif [[ "$bind" == *":"* ]]; then
|
||||
ynh_die --message="For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
|
||||
else
|
||||
old[$short_setting]="$(cat $(echo $bind | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s@__FINALPATH__@${final_path:-}@ | sed s/__APP__/$app/) 2>/dev/null || echo YNH_NULL)"
|
||||
old[$short_setting]="$(cat "$bind" 2> /dev/null || echo YNH_NULL)"
|
||||
fi
|
||||
|
||||
# Get value from a kind of key/value file
|
||||
|
@ -47,7 +47,7 @@ _ynh_app_config_get_one() {
|
|||
bind_after="$(echo "${bind_key_}" | cut -d'>' -f1)"
|
||||
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2 | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s@__FINALPATH__@${final_path:-}@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2)"
|
||||
old[$short_setting]="$(ynh_read_var_in_file --file="${bind_file}" --key="${bind_key_}" --after="${bind_after}")"
|
||||
|
||||
fi
|
||||
|
@ -73,7 +73,7 @@ _ynh_app_config_apply_one() {
|
|||
if [[ "$bind" == "settings" ]]; then
|
||||
ynh_die --message="File '${short_setting}' can't be stored in settings"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s@__FINALPATH__@${final_path:-}@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$bind"
|
||||
if [[ "${!short_setting}" == "" ]]; then
|
||||
ynh_backup_if_checksum_is_different --file="$bind_file"
|
||||
ynh_secure_remove --file="$bind_file"
|
||||
|
@ -98,7 +98,7 @@ _ynh_app_config_apply_one() {
|
|||
if [[ "$bind" == *":"* ]]; then
|
||||
ynh_die --message="For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s@__FINALPATH__@${final_path:-}@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$bind"
|
||||
ynh_backup_if_checksum_is_different --file="$bind_file"
|
||||
echo "${!short_setting}" > "$bind_file"
|
||||
ynh_store_file_checksum --file="$bind_file" --update_only
|
||||
|
@ -113,7 +113,7 @@ _ynh_app_config_apply_one() {
|
|||
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
|
||||
fi
|
||||
bind_key_=${bind_key_:-$short_setting}
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2 | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s@__FINALPATH__@${final_path:-}@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2)"
|
||||
|
||||
ynh_backup_if_checksum_is_different --file="$bind_file"
|
||||
ynh_write_var_in_file --file="${bind_file}" --key="${bind_key_}" --value="${!short_setting}" --after="${bind_after}"
|
||||
|
@ -126,60 +126,9 @@ _ynh_app_config_apply_one() {
|
|||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_ynh_app_config_get() {
|
||||
# From settings
|
||||
local lines
|
||||
lines=$(
|
||||
python3 <<EOL
|
||||
import toml
|
||||
from collections import OrderedDict
|
||||
with open("../config_panel.toml", "r") as f:
|
||||
file_content = f.read()
|
||||
loaded_toml = toml.loads(file_content, _dict=OrderedDict)
|
||||
|
||||
for panel_name, panel in loaded_toml.items():
|
||||
if not isinstance(panel, dict): continue
|
||||
bind_panel = panel.get('bind')
|
||||
for section_name, section in panel.items():
|
||||
if not isinstance(section, dict): continue
|
||||
bind_section = section.get('bind')
|
||||
if not bind_section:
|
||||
bind_section = bind_panel
|
||||
elif bind_section[-1] == ":" and bind_panel and ":" in bind_panel:
|
||||
regex, bind_panel_file = bind_panel.split(":")
|
||||
if ">" in bind_section:
|
||||
bind_section = bind_section + bind_panel_file
|
||||
else:
|
||||
bind_section = regex + bind_section + bind_panel_file
|
||||
|
||||
for name, param in section.items():
|
||||
if not isinstance(param, dict):
|
||||
continue
|
||||
|
||||
bind = param.get('bind')
|
||||
|
||||
if not bind:
|
||||
if bind_section:
|
||||
bind = bind_section
|
||||
else:
|
||||
bind = 'settings'
|
||||
elif bind[-1] == ":" and bind_section and ":" in bind_section:
|
||||
regex, bind_file = bind_section.split(":")
|
||||
if ">" in bind:
|
||||
bind = bind + bind_file
|
||||
else:
|
||||
bind = regex + bind + bind_file
|
||||
if bind == "settings" and param.get('type', 'string') == 'file':
|
||||
bind = 'null'
|
||||
|
||||
print('|'.join([
|
||||
name,
|
||||
param.get('type', 'string'),
|
||||
bind
|
||||
]))
|
||||
EOL
|
||||
)
|
||||
for line in $lines; do
|
||||
for line in $YNH_APP_CONFIG_PANEL_OPTIONS_TYPES_AND_BINDS; do
|
||||
# Split line into short_setting, type and bind
|
||||
IFS='|' read short_setting type bind <<< "$line"
|
||||
binds[${short_setting}]="$bind"
|
||||
|
@ -188,7 +137,6 @@ EOL
|
|||
formats[${short_setting}]=""
|
||||
ynh_app_config_get_one $short_setting $type $bind
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
_ynh_app_config_apply() {
|
||||
|
@ -350,5 +298,6 @@ ynh_app_config_run() {
|
|||
;;
|
||||
*)
|
||||
ynh_app_action_run $1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ ignoreregex =
|
|||
chown -R "$app:$app" "/var/log/$app"
|
||||
chmod -R u=rwX,g=rX,o= "/var/log/$app"
|
||||
|
||||
ynh_systemd_action --service_name=fail2ban --action=reload --line_match="(Started|Reloaded) fail2ban.service" --log_path=systemd
|
||||
ynh_systemd_action --service_name=fail2ban --action=reload --line_match="(Started|Reloaded) Fail2Ban Service" --log_path=systemd
|
||||
|
||||
local fail2ban_error="$(journalctl --no-hostname --unit=fail2ban | tail --lines=50 | grep "WARNING.*$app.*")"
|
||||
if [[ -n "$fail2ban_error" ]]; then
|
||||
|
|
|
@ -210,29 +210,24 @@ ynh_cleanup_go () {
|
|||
# List required Go versions
|
||||
local installed_apps=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
|
||||
local required_go_versions=""
|
||||
for installed_app in $installed_apps
|
||||
do
|
||||
for installed_app in $installed_apps; do
|
||||
local installed_app_go_version=$(ynh_app_setting_get --app=$installed_app --key="go_version")
|
||||
if [[ $installed_app_go_version ]]
|
||||
then
|
||||
if [[ $installed_app_go_version ]]; then
|
||||
required_go_versions="${installed_app_go_version}\n${required_go_versions}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove no more needed Go versions
|
||||
local installed_go_versions=$(goenv versions --bare --skip-aliases | grep -Ev '/')
|
||||
for installed_go_version in $installed_go_versions
|
||||
do
|
||||
if ! `echo ${required_go_versions} | grep "${installed_go_version}" 1>/dev/null 2>&1`
|
||||
then
|
||||
for installed_go_version in $installed_go_versions; do
|
||||
if ! $(echo ${required_go_versions} | grep "${installed_go_version}" 1> /dev/null 2>&1); then
|
||||
ynh_print_info --message="Removing of Go-$installed_go_version"
|
||||
$goenv_install_dir/bin/goenv uninstall --force "$installed_go_version"
|
||||
fi
|
||||
done
|
||||
|
||||
# If none Go version is required
|
||||
if [[ ! $required_go_versions ]]
|
||||
then
|
||||
if [[ ! $required_go_versions ]]; then
|
||||
# Remove goenv environment configuration
|
||||
ynh_print_info --message="Removing of goenv"
|
||||
ynh_secure_remove --file="$goenv_install_dir"
|
||||
|
|
|
@ -93,8 +93,7 @@ ynh_exec_err() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
ynh_print_err --message="$(eval $@)"
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
@ -114,8 +113,7 @@ ynh_exec_warn() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
ynh_print_warn --message="$(eval $@)"
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
@ -135,8 +133,7 @@ ynh_exec_warn_less() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
eval $@ 2>&1
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
@ -156,8 +153,7 @@ ynh_exec_quiet() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
eval $@ > /dev/null
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
@ -177,8 +173,7 @@ ynh_exec_fully_quiet() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
eval $@ > /dev/null 2>&1
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
|
|
@ -17,10 +17,8 @@ ynh_use_logrotate() {
|
|||
# Stupid patch to ignore legacy --non-append and --nonappend
|
||||
# which was never properly understood and improperly used and kind of bullshit
|
||||
local all_args=(${@})
|
||||
for I in $(seq 0 $(($# - 1)))
|
||||
do
|
||||
if [[ "${all_args[$I]}" == "--non-append" ]] || [[ "${all_args[$I]}" == "--nonappend" ]]
|
||||
then
|
||||
for I in $(seq 0 $(($# - 1))); do
|
||||
if [[ "${all_args[$I]}" == "--non-append" ]] || [[ "${all_args[$I]}" == "--nonappend" ]]; then
|
||||
unset all_args[$I]
|
||||
fi
|
||||
done
|
||||
|
@ -43,8 +41,7 @@ ynh_use_logrotate() {
|
|||
fi
|
||||
set +o noglob
|
||||
|
||||
for stuff in $logfile
|
||||
do
|
||||
for stuff in $logfile; do
|
||||
mkdir --parents $(dirname "$stuff")
|
||||
done
|
||||
|
||||
|
@ -76,8 +73,7 @@ $logfile {
|
|||
}
|
||||
EOF
|
||||
|
||||
if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]]
|
||||
then
|
||||
if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]]; then
|
||||
cat $tempconf > /etc/logrotate.d/$app
|
||||
else
|
||||
cat $tempconf >> /etc/logrotate.d/$app
|
||||
|
|
|
@ -39,19 +39,16 @@ ynh_mongo_exec() {
|
|||
eval=${eval:-0}
|
||||
|
||||
# If user is provided
|
||||
if [ -n "$user" ]
|
||||
then
|
||||
if [ -n "$user" ]; then
|
||||
user="--username=$user"
|
||||
|
||||
# If password is provided
|
||||
if [ -n "$password" ]
|
||||
then
|
||||
if [ -n "$password" ]; then
|
||||
password="--password=$password"
|
||||
fi
|
||||
|
||||
# If authenticationdatabase is provided
|
||||
if [ -n "$authenticationdatabase" ]
|
||||
then
|
||||
if [ -n "$authenticationdatabase" ]; then
|
||||
authenticationdatabase="--authenticationDatabase=$authenticationdatabase"
|
||||
else
|
||||
authenticationdatabase="--authenticationDatabase=admin"
|
||||
|
@ -62,23 +59,19 @@ ynh_mongo_exec() {
|
|||
fi
|
||||
|
||||
# If host is provided
|
||||
if [ -n "$host" ]
|
||||
then
|
||||
if [ -n "$host" ]; then
|
||||
host="--host=$host"
|
||||
fi
|
||||
|
||||
# If port is provided
|
||||
if [ -n "$port" ]
|
||||
then
|
||||
if [ -n "$port" ]; then
|
||||
port="--port=$port"
|
||||
fi
|
||||
|
||||
# If eval is not provided
|
||||
if [ $eval -eq 0 ]
|
||||
then
|
||||
if [ $eval -eq 0 ]; then
|
||||
# If database is provided
|
||||
if [ -n "$database" ]
|
||||
then
|
||||
if [ -n "$database" ]; then
|
||||
database="use $database"
|
||||
else
|
||||
database=""
|
||||
|
@ -91,8 +84,7 @@ quit()
|
|||
EOF
|
||||
else
|
||||
# If database is provided
|
||||
if [ -n "$database" ]
|
||||
then
|
||||
if [ -n "$database" ]; then
|
||||
database="$database"
|
||||
else
|
||||
database=""
|
||||
|
@ -186,8 +178,7 @@ ynh_mongo_database_exists() {
|
|||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")' --eval) -lt 0 ]
|
||||
then
|
||||
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")' --eval) -lt 0 ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
@ -343,8 +334,7 @@ ynh_install_mongo() {
|
|||
#
|
||||
ynh_remove_mongo() {
|
||||
# Only remove the mongodb service if it is not installed.
|
||||
if ! ynh_package_is_installed --package="mongodb*"
|
||||
then
|
||||
if ! ynh_package_is_installed --package="mongodb*"; then
|
||||
ynh_print_info --message="Removing MongoDB service..."
|
||||
mongodb_servicename=mongod
|
||||
# Remove the mongodb service
|
||||
|
|
|
@ -227,9 +227,6 @@ ynh_mysql_setup_db() {
|
|||
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
|
||||
db_pwd="${db_pwd:-$new_db_pwd}"
|
||||
|
||||
# Dirty patch for super-legacy apps
|
||||
dpkg --list | grep -q "^ii mariadb-server" || { ynh_print_warn "Packager: you called ynh_mysql_setup_db without declaring a dependency to mariadb-server. Please add it to your apt dependencies !"; ynh_apt install mariadb-server; }
|
||||
|
||||
ynh_mysql_create_db "$db_name" "$db_user" "$db_pwd"
|
||||
ynh_app_setting_set --app=$app --key=mysqlpwd --value=$db_pwd
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ ynh_remove_nginx_config() {
|
|||
ynh_systemd_action --service_name=nginx --action=reload
|
||||
}
|
||||
|
||||
|
||||
# Regen the nginx config in a change url context
|
||||
#
|
||||
# usage: ynh_change_url_nginx_config
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
readonly YNH_DEFAULT_PHP_VERSION=8.2
|
||||
readonly YNH_DEFAULT_PHP_VERSION=7.4
|
||||
# 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}
|
||||
|
@ -70,14 +70,17 @@ YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
|
|||
ynh_add_fpm_config() {
|
||||
local _globalphpversion=${phpversion-:}
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=vufg
|
||||
local -A args_array=([v]=phpversion= [u]=usage= [f]=footprint= [g]=group=)
|
||||
local legacy_args=vufpdg
|
||||
local -A args_array=([v]=phpversion= [u]=usage= [f]=footprint= [p]=package= [d]=dedicated_service [g]=group=)
|
||||
local group
|
||||
local phpversion
|
||||
local usage
|
||||
local footprint
|
||||
local package
|
||||
local dedicated_service
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
package=${package:-}
|
||||
group=${group:-}
|
||||
|
||||
# The default behaviour is to use the template.
|
||||
|
@ -89,21 +92,21 @@ ynh_add_fpm_config() {
|
|||
|
||||
# If no usage provided, default to the value existing in setting ... or to low
|
||||
local fpm_usage_in_setting=$(ynh_app_setting_get --app=$app --key=fpm_usage)
|
||||
if [ -z "$usage" ]
|
||||
then
|
||||
if [ -z "$usage" ]; then
|
||||
usage=${fpm_usage_in_setting:-low}
|
||||
ynh_app_setting_set --app=$app --key=fpm_usage --value=$usage
|
||||
fi
|
||||
|
||||
# If no footprint provided, default to the value existing in setting ... or to low
|
||||
local fpm_footprint_in_setting=$(ynh_app_setting_get --app=$app --key=fpm_footprint)
|
||||
if [ -z "$footprint" ]
|
||||
then
|
||||
if [ -z "$footprint" ]; then
|
||||
footprint=${fpm_footprint_in_setting:-low}
|
||||
ynh_app_setting_set --app=$app --key=fpm_footprint --value=$footprint
|
||||
fi
|
||||
|
||||
fi
|
||||
# Do not use a dedicated service by default
|
||||
dedicated_service=${dedicated_service:-0}
|
||||
|
||||
# Set the default PHP-FPM version by default
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
|
@ -120,23 +123,51 @@ ynh_add_fpm_config() {
|
|||
local old_php_fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
|
||||
local old_php_finalphpconf="$old_php_fpm_config_dir/pool.d/$app.conf"
|
||||
|
||||
if [[ -f "$old_php_finalphpconf" ]]
|
||||
then
|
||||
if [[ -f "$old_php_finalphpconf" ]]; then
|
||||
ynh_backup_if_checksum_is_different --file="$old_php_finalphpconf"
|
||||
ynh_remove_fpm_config
|
||||
fi
|
||||
fi
|
||||
|
||||
# Legacy args (packager should just list their php dependency as regular apt dependencies...
|
||||
if [ -n "$package" ]; then
|
||||
# Install the additionnal packages from the default repository
|
||||
ynh_print_warn --message "Argument --package of ynh_add_fpm_config is deprecated and to be removed in the future"
|
||||
ynh_install_app_dependencies "$package"
|
||||
fi
|
||||
|
||||
if [ $dedicated_service -eq 1 ]; then
|
||||
ynh_print_warn --message "Argument --dedicated_service of ynh_add_fpm_config is deprecated and to be removed in the future"
|
||||
local fpm_service="${app}-phpfpm"
|
||||
local fpm_config_dir="/etc/php/$phpversion/dedicated-fpm"
|
||||
else
|
||||
local fpm_service="php${phpversion}-fpm"
|
||||
local fpm_config_dir="/etc/php/$phpversion/fpm"
|
||||
fi
|
||||
|
||||
# Create the directory for FPM pools
|
||||
mkdir --parents "$fpm_config_dir/pool.d"
|
||||
|
||||
ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir"
|
||||
ynh_app_setting_set --app=$app --key=fpm_service --value="$fpm_service"
|
||||
ynh_app_setting_set --app=$app --key=fpm_dedicated_service --value="$dedicated_service"
|
||||
ynh_app_setting_set --app=$app --key=phpversion --value=$phpversion
|
||||
|
||||
# Migrate from mutual PHP service to dedicated one.
|
||||
if [ $dedicated_service -eq 1 ]; then
|
||||
local old_fpm_config_dir="/etc/php/$phpversion/fpm"
|
||||
# If a config file exist in the common pool, move it.
|
||||
if [ -e "$old_fpm_config_dir/pool.d/$app.conf" ]; then
|
||||
ynh_print_info --message="Migrate to a dedicated php-fpm service for $app."
|
||||
# Create a backup of the old file before migration
|
||||
ynh_backup_if_checksum_is_different --file="$old_fpm_config_dir/pool.d/$app.conf"
|
||||
# Remove the old PHP config file
|
||||
ynh_secure_remove --file="$old_fpm_config_dir/pool.d/$app.conf"
|
||||
# Reload PHP to release the socket and allow the dedicated service to use it
|
||||
ynh_systemd_action --service_name=php${phpversion}-fpm --action=reload
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $autogenconf == "false" ]; then
|
||||
# Usage 1, use the template in conf/php-fpm.conf
|
||||
local phpfpm_path="$YNH_APP_BASEDIR/conf/php-fpm.conf"
|
||||
|
@ -190,6 +221,48 @@ pm.process_idle_timeout = 10s
|
|||
local finalphpconf="$fpm_config_dir/pool.d/$app.conf"
|
||||
ynh_add_config --template="$phpfpm_path" --destination="$finalphpconf"
|
||||
|
||||
if [ -e "$YNH_APP_BASEDIR/conf/php-fpm.ini" ]; then
|
||||
ynh_print_warn --message="Packagers ! Please do not use a separate php ini file, merge your directives in the pool file instead."
|
||||
ynh_add_config --template="php-fpm.ini" --destination="$fpm_config_dir/conf.d/20-$app.ini"
|
||||
fi
|
||||
|
||||
if [ $dedicated_service -eq 1 ]; then
|
||||
# Create a dedicated php-fpm.conf for the service
|
||||
local globalphpconf=$fpm_config_dir/php-fpm-$app.conf
|
||||
|
||||
echo "[global]
|
||||
pid = /run/php/php__PHPVERSION__-fpm-__APP__.pid
|
||||
error_log = /var/log/php/fpm-php.__APP__.log
|
||||
syslog.ident = php-fpm-__APP__
|
||||
include = __FINALPHPCONF__
|
||||
" > $YNH_APP_BASEDIR/conf/php-fpm-$app.conf
|
||||
|
||||
ynh_add_config --template="php-fpm-$app.conf" --destination="$globalphpconf"
|
||||
|
||||
# Create a config for a dedicated PHP-FPM service for the app
|
||||
echo "[Unit]
|
||||
Description=PHP __PHPVERSION__ FastCGI Process Manager for __APP__
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
PIDFile=/run/php/php__PHPVERSION__-fpm-__APP__.pid
|
||||
ExecStart=/usr/sbin/php-fpm__PHPVERSION__ --nodaemonize --fpm-config __GLOBALPHPCONF__
|
||||
ExecReload=/bin/kill -USR2 \$MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
" > $YNH_APP_BASEDIR/conf/$fpm_service
|
||||
|
||||
# Create this dedicated PHP-FPM service
|
||||
ynh_add_systemd_config --service=$fpm_service --template=$fpm_service
|
||||
# Integrate the service in YunoHost admin panel
|
||||
yunohost service add $fpm_service --log /var/log/php/fpm-php.$app.log --description "Php-fpm dedicated to $app"
|
||||
# Configure log rotate
|
||||
ynh_use_logrotate --logfile=/var/log/php
|
||||
# Restart the service, as this service is either stopped or only for this app
|
||||
ynh_systemd_action --service_name=$fpm_service --action=restart
|
||||
else
|
||||
# Validate that the new php conf doesn't break php-fpm entirely
|
||||
if ! php-fpm${phpversion} --test 2> /dev/null; then
|
||||
php-fpm${phpversion} --test || true
|
||||
|
@ -197,6 +270,7 @@ pm.process_idle_timeout = 10s
|
|||
ynh_die --message="The new configuration broke php-fpm?"
|
||||
fi
|
||||
ynh_systemd_action --service_name=$fpm_service --action=reload
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove the dedicated PHP-FPM config
|
||||
|
@ -207,6 +281,8 @@ pm.process_idle_timeout = 10s
|
|||
ynh_remove_fpm_config() {
|
||||
local fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
|
||||
local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service)
|
||||
local dedicated_service=$(ynh_app_setting_get --app=$app --key=fpm_dedicated_service)
|
||||
dedicated_service=${dedicated_service:-0}
|
||||
# Get the version of PHP used by this app
|
||||
local phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||
|
||||
|
@ -220,7 +296,69 @@ ynh_remove_fpm_config() {
|
|||
fi
|
||||
|
||||
ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf"
|
||||
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 [ $dedicated_service -eq 1 ]; then
|
||||
# Remove the dedicated service PHP-FPM service for the app
|
||||
ynh_remove_systemd_config --service=$fpm_service
|
||||
# Remove the global PHP-FPM conf
|
||||
ynh_secure_remove --file="$fpm_config_dir/php-fpm-$app.conf"
|
||||
# Remove the service from the list of services known by YunoHost
|
||||
yunohost service remove $fpm_service
|
||||
elif ynh_package_is_installed --package="php${phpversion}-fpm"; then
|
||||
ynh_systemd_action --service_name=$fpm_service --action=reload
|
||||
fi
|
||||
|
||||
# If the PHP version used is not the default version for YunoHost
|
||||
# The second part with YNH_APP_PURGE is an ugly hack to guess that we're inside the remove script
|
||||
# (we don't actually care about its value, we just check its not empty hence it exists)
|
||||
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ] && [ -n "${YNH_APP_PURGE:-}" ] && dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
# Remove app dependencies ... but ideally should happen via an explicit call from packager
|
||||
ynh_remove_app_dependencies
|
||||
fi
|
||||
}
|
||||
|
||||
# Install another version of PHP.
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# Legacy, to be remove on bullseye
|
||||
#
|
||||
# usage: ynh_install_php --phpversion=phpversion [--package=packages]
|
||||
# | arg: -v, --phpversion= - Version of PHP to install.
|
||||
# | arg: -p, --package= - Additionnal PHP packages to install
|
||||
#
|
||||
# Requires YunoHost version 3.8.1 or higher.
|
||||
ynh_install_php() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=vp
|
||||
local -A args_array=([v]=phpversion= [p]=package=)
|
||||
local phpversion
|
||||
local package
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
package=${package:-}
|
||||
|
||||
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ]; then
|
||||
ynh_die --message="Do not use ynh_install_php to install php$YNH_DEFAULT_PHP_VERSION"
|
||||
fi
|
||||
|
||||
ynh_install_app_dependencies "$package"
|
||||
}
|
||||
|
||||
# Remove the specific version of PHP used by the app.
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# Legacy, to be remove on bullseye
|
||||
#
|
||||
# usage: ynh_remove_php
|
||||
#
|
||||
# Requires YunoHost version 3.8.1 or higher.
|
||||
ynh_remove_php() {
|
||||
ynh_remove_app_dependencies
|
||||
}
|
||||
|
||||
# Define the values to configure PHP-FPM
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
PSQL_ROOT_PWD_FILE=/etc/yunohost/psql
|
||||
PSQL_VERSION=15
|
||||
PSQL_VERSION=13
|
||||
|
||||
# Open a connection as a user
|
||||
#
|
||||
|
@ -199,8 +199,7 @@ ynh_psql_database_exists() {
|
|||
|
||||
# if psql is not there, we cannot check the db
|
||||
# though it could exists.
|
||||
if ! command -v psql
|
||||
then
|
||||
if ! command -v psql; then
|
||||
ynh_print_err -m "PostgreSQL is not installed, impossible to check for db existence."
|
||||
return 1
|
||||
elif ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT datname FROM pg_database WHERE datname='$database';" | grep --quiet "$database"; then
|
||||
|
|
|
@ -13,10 +13,8 @@ ynh_redis_get_free_db() {
|
|||
|
||||
db=0
|
||||
# default Debian setting is 15 databases
|
||||
for i in $(seq 0 "$max")
|
||||
do
|
||||
if ! echo "$result" | grep -q "db$i"
|
||||
then
|
||||
for i in $(seq 0 "$max"); do
|
||||
if ! echo "$result" | grep -q "db$i"; then
|
||||
db=$i
|
||||
break 1
|
||||
fi
|
||||
|
|
|
@ -210,8 +210,7 @@ ynh_install_ruby () {
|
|||
ynh_app_setting_set --app=$app --key=ruby_version --value=$final_ruby_version
|
||||
|
||||
# Remove app virtualenv
|
||||
if rbenv alias --list | grep --quiet "$app "
|
||||
then
|
||||
if rbenv alias --list | grep --quiet "$app "; then
|
||||
rbenv alias $app --remove
|
||||
fi
|
||||
|
||||
|
@ -267,29 +266,24 @@ ynh_cleanup_ruby () {
|
|||
# List required Ruby versions
|
||||
local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$')
|
||||
local required_ruby_versions=""
|
||||
for installed_app in $installed_apps
|
||||
do
|
||||
for installed_app in $installed_apps; do
|
||||
local installed_app_ruby_version=$(ynh_app_setting_get --app=$installed_app --key="ruby_version")
|
||||
if [[ -n "$installed_app_ruby_version" ]]
|
||||
then
|
||||
if [[ -n "$installed_app_ruby_version" ]]; then
|
||||
required_ruby_versions="${installed_app_ruby_version}\n${required_ruby_versions}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove no more needed Ruby versions
|
||||
local installed_ruby_versions=$(rbenv versions --bare --skip-aliases | grep -Ev '/')
|
||||
for installed_ruby_version in $installed_ruby_versions
|
||||
do
|
||||
if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"
|
||||
then
|
||||
for installed_ruby_version in $installed_ruby_versions; do
|
||||
if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"; then
|
||||
ynh_print_info --message="Removing Ruby-$installed_ruby_version"
|
||||
$rbenv_install_dir/bin/rbenv uninstall --force $installed_ruby_version
|
||||
fi
|
||||
done
|
||||
|
||||
# If none Ruby version is required
|
||||
if [[ -z "$required_ruby_versions" ]]
|
||||
then
|
||||
if [[ -z "$required_ruby_versions" ]]; then
|
||||
# Remove rbenv environment configuration
|
||||
ynh_print_info --message="Removing rbenv"
|
||||
ynh_secure_remove --file="$rbenv_install_dir"
|
||||
|
|
|
@ -18,7 +18,11 @@ ynh_app_setting_get() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
|
||||
if [[ $key =~ (unprotected|protected|skipped)_ ]]; then
|
||||
yunohost app setting $app $key
|
||||
else
|
||||
ynh_app_setting "get" "$app" "$key"
|
||||
fi
|
||||
}
|
||||
|
||||
# Set an application setting
|
||||
|
@ -41,7 +45,11 @@ ynh_app_setting_set() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
|
||||
if [[ $key =~ (unprotected|protected|skipped)_ ]]; then
|
||||
yunohost app setting $app $key -v $value
|
||||
else
|
||||
ynh_app_setting "set" "$app" "$key" "$value"
|
||||
fi
|
||||
}
|
||||
|
||||
# Set an application setting but only if the "$key" variable ain't set yet
|
||||
|
@ -98,7 +106,11 @@ ynh_app_setting_delete() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
|
||||
if [[ "$key" =~ (unprotected|skipped|protected)_ ]]; then
|
||||
yunohost app setting $app $key -d
|
||||
else
|
||||
ynh_app_setting "delete" "$app" "$key"
|
||||
fi
|
||||
}
|
||||
|
||||
# Small "hard-coded" interface to avoid calling "yunohost app" directly each
|
||||
|
|
|
@ -77,12 +77,10 @@ ynh_setup_source() {
|
|||
keep="${keep:-}"
|
||||
full_replace="${full_replace:-0}"
|
||||
|
||||
if test -e $YNH_APP_BASEDIR/manifest.toml && cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq -e '.resources.sources' >/dev/null
|
||||
then
|
||||
if test -e $YNH_APP_BASEDIR/manifest.toml && cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq -e '.resources.sources' > /dev/null; then
|
||||
source_id="${source_id:-main}"
|
||||
local sources_json=$(cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq ".resources.sources[\"$source_id\"]")
|
||||
if jq -re ".url" <<< "$sources_json"
|
||||
then
|
||||
if jq -re ".url" <<< "$sources_json"; then
|
||||
local arch_prefix=""
|
||||
else
|
||||
local arch_prefix=".$YNH_ARCH"
|
||||
|
@ -100,22 +98,16 @@ ynh_setup_source() {
|
|||
[[ -n "$src_url" ]] || ynh_die "No URL defined for source $source_id$arch_prefix ?"
|
||||
[[ -n "$src_sum" ]] || ynh_die "No sha256 sum defined for source $source_id$arch_prefix ?"
|
||||
|
||||
if [[ -z "$src_format" ]]
|
||||
then
|
||||
if [[ "$src_url" =~ ^.*\.zip$ ]] || [[ "$src_url" =~ ^.*/zipball/.*$ ]]
|
||||
then
|
||||
if [[ -z "$src_format" ]]; then
|
||||
if [[ "$src_url" =~ ^.*\.zip$ ]] || [[ "$src_url" =~ ^.*/zipball/.*$ ]]; then
|
||||
src_format="zip"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.gz$ ]] || [[ "$src_url" =~ ^.*\.tgz$ ]] || [[ "$src_url" =~ ^.*/tar\.gz/.*$ ]] || [[ "$src_url" =~ ^.*/tarball/.*$ ]]
|
||||
then
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.gz$ ]] || [[ "$src_url" =~ ^.*\.tgz$ ]] || [[ "$src_url" =~ ^.*/tar\.gz/.*$ ]] || [[ "$src_url" =~ ^.*/tarball/.*$ ]]; then
|
||||
src_format="tar.gz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.xz$ ]]
|
||||
then
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.xz$ ]]; then
|
||||
src_format="tar.xz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]
|
||||
then
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]; then
|
||||
src_format="tar.bz2"
|
||||
elif [[ -z "$src_extract" ]]
|
||||
then
|
||||
elif [[ -z "$src_extract" ]]; then
|
||||
src_extract="false"
|
||||
fi
|
||||
fi
|
||||
|
@ -142,12 +134,10 @@ ynh_setup_source() {
|
|||
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
|
||||
src_extract=${src_extract:-true}
|
||||
|
||||
if [[ "$src_extract" != "true" ]] && [[ "$src_extract" != "false" ]]
|
||||
then
|
||||
if [[ "$src_extract" != "true" ]] && [[ "$src_extract" != "false" ]]; then
|
||||
ynh_die "For source $source_id, expected either 'true' or 'false' for the extract parameter"
|
||||
fi
|
||||
|
||||
|
||||
# (Unused?) mecanism where one can have the file in a special local cache to not have to download it...
|
||||
local local_src="/opt/yunohost-apps-src/${YNH_APP_ID}/${source_id}"
|
||||
|
||||
|
@ -165,14 +155,12 @@ ynh_setup_source() {
|
|||
[ -n "$src_url" ] || ynh_die "Couldn't parse SOURCE_URL from $src_file_path ?"
|
||||
|
||||
# If the file was prefetched but somehow doesn't match the sum, rm and redownload it
|
||||
if [ -e "$src_filename" ] && ! echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status
|
||||
then
|
||||
if [ -e "$src_filename" ] && ! echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status; then
|
||||
rm -f "$src_filename"
|
||||
fi
|
||||
|
||||
# Only redownload the file if it wasnt prefetched
|
||||
if [ ! -e "$src_filename" ]
|
||||
then
|
||||
if [ ! -e "$src_filename" ]; then
|
||||
# NB. we have to declare the var as local first,
|
||||
# otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
|
||||
# because local always return 0 ...
|
||||
|
@ -183,8 +171,7 @@ ynh_setup_source() {
|
|||
fi
|
||||
|
||||
# Check the control sum
|
||||
if ! echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status
|
||||
then
|
||||
if ! echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status; then
|
||||
local actual_sum="$(${src_sumprg} ${src_filename} | cut --delimiter=' ' --fields=1)"
|
||||
local actual_size="$(du -hs ${src_filename} | cut --fields=1)"
|
||||
rm -f ${src_filename}
|
||||
|
@ -222,8 +209,7 @@ ynh_setup_source() {
|
|||
fi
|
||||
|
||||
if [[ "$src_extract" == "false" ]]; then
|
||||
if [[ -z "$src_rename" ]]
|
||||
then
|
||||
if [[ -z "$src_rename" ]]; then
|
||||
mv $src_filename $dest_dir
|
||||
else
|
||||
mv $src_filename $dest_dir/$src_rename
|
||||
|
|
|
@ -149,8 +149,7 @@ ynh_systemd_action() {
|
|||
# Also check the timeout using actual timestamp, because sometimes for some reason,
|
||||
# journalctl may take a huge time to run, and we end up waiting literally an entire hour
|
||||
# instead of 5 min ...
|
||||
if [[ "$(( $(date +%s) - $starttime))" -gt "$timeout" ]]
|
||||
then
|
||||
if [[ "$(($(date +%s) - $starttime))" -gt "$timeout" ]]; then
|
||||
i=$timeout
|
||||
break
|
||||
fi
|
||||
|
|
|
@ -83,8 +83,7 @@ ynh_add_config() {
|
|||
chmod 640 $destination
|
||||
_ynh_apply_default_permissions $destination
|
||||
|
||||
if [[ "$jinja" == 1 ]]
|
||||
then
|
||||
if [[ "$jinja" == 1 ]]; then
|
||||
# This is ran in a subshell such that the "export" does not "contaminate" the main process
|
||||
(
|
||||
export $(compgen -v)
|
||||
|
|
|
@ -22,8 +22,7 @@ YNH_APP_BASEDIR=${YNH_APP_BASEDIR:-$(realpath ..)}
|
|||
ynh_exit_properly() {
|
||||
local exit_code=$?
|
||||
|
||||
if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]]
|
||||
then
|
||||
if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]]; then
|
||||
rm -rf "/var/cache/yunohost/download/"
|
||||
fi
|
||||
|
||||
|
@ -67,8 +66,7 @@ ynh_abort_if_errors() {
|
|||
}
|
||||
|
||||
# When running an app script with packaging format >= 2, auto-enable ynh_abort_if_errors except for remove script
|
||||
if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} ge 2 && [[ ${YNH_APP_ACTION} != "remove" ]]
|
||||
then
|
||||
if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} ge 2 && [[ ${YNH_APP_ACTION} != "remove" ]]; then
|
||||
ynh_abort_if_errors
|
||||
fi
|
||||
|
||||
|
@ -149,8 +147,7 @@ _acceptable_path_to_delete() {
|
|||
local forbidden_paths=$(ls -d / /* /{var,home,usr}/* /etc/{default,sudoers.d,yunohost,cron*} /etc/yunohost/{apps,domains,hooks.d} /opt/yunohost 2> /dev/null)
|
||||
|
||||
# Legacy : A couple apps still have data in /home/$app ...
|
||||
if [[ -n "${app:-}" ]]
|
||||
then
|
||||
if [[ -n "${app:-}" ]]; then
|
||||
forbidden_paths=$(echo "$forbidden_paths" | grep -v "/home/$app")
|
||||
fi
|
||||
|
||||
|
@ -215,19 +212,16 @@ ynh_read_manifest() {
|
|||
|
||||
if [ ! -e "${manifest:-}" ]; then
|
||||
# If the manifest isn't found, try the common place for backup and restore script.
|
||||
if [ -e "$YNH_APP_BASEDIR/manifest.json" ]
|
||||
then
|
||||
if [ -e "$YNH_APP_BASEDIR/manifest.json" ]; then
|
||||
manifest="$YNH_APP_BASEDIR/manifest.json"
|
||||
elif [ -e "$YNH_APP_BASEDIR/manifest.toml" ]
|
||||
then
|
||||
elif [ -e "$YNH_APP_BASEDIR/manifest.toml" ]; then
|
||||
manifest="$YNH_APP_BASEDIR/manifest.toml"
|
||||
else
|
||||
ynh_die --message "No manifest found !?"
|
||||
fi
|
||||
fi
|
||||
|
||||
if echo "$manifest" | grep -q '\.json$'
|
||||
then
|
||||
if echo "$manifest" | grep -q '\.json$'; then
|
||||
jq ".$manifest_key" "$manifest" --raw-output
|
||||
else
|
||||
cat "$manifest" | python3 -c 'import json, toml, sys; print(json.dumps(toml.load(sys.stdin)))' | jq ".$manifest_key" --raw-output
|
||||
|
@ -373,25 +367,28 @@ ynh_compare_current_package_version() {
|
|||
_ynh_apply_default_permissions() {
|
||||
local target=$1
|
||||
|
||||
local ynh_requirement=$(ynh_read_manifest --manifest_key="requirements.yunohost" | tr -d '<>= ')
|
||||
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} ge 2 || [ -z "$ynh_requirement" ] || [ "$ynh_requirement" == "null" ] || dpkg --compare-versions $ynh_requirement ge 4.2; then
|
||||
chmod o-rwx $target
|
||||
chmod g-w $target
|
||||
chown -R root:root $target
|
||||
if ynh_system_user_exists $app; then
|
||||
chown $app:$app $target
|
||||
fi
|
||||
fi
|
||||
|
||||
# Crons should be owned by root
|
||||
# Also we don't want systemd conf, nginx conf or others stuff to be owned by the app,
|
||||
# otherwise they could self-edit their own systemd conf and escalate privilege
|
||||
if grep -qE '^(/etc/cron|/etc/php|/etc/nginx/conf.d|/etc/fail2ban|/etc/systemd/system)' <<< "$target"
|
||||
then
|
||||
if grep -qE '^(/etc/cron|/etc/php|/etc/nginx/conf.d|/etc/fail2ban|/etc/systemd/system)' <<< "$target"; then
|
||||
chmod 400 $target
|
||||
chown root:root $target
|
||||
fi
|
||||
}
|
||||
|
||||
int_to_bool() {
|
||||
sed -e 's/^1$/True/g' -e 's/^0$/False/g' -e 's/^true$/True/g' -e 's/^false$/False/g'
|
||||
sed -e 's/^1$/True/g' -e 's/^0$/False/g'
|
||||
}
|
||||
|
||||
toml_to_json() {
|
||||
|
|
|
@ -4,9 +4,9 @@ YNH_APT_INSTALL_DEPENDENCIES_REPLACE="true"
|
|||
|
||||
# Define and install dependencies with a equivs control file
|
||||
#
|
||||
# example : ynh_install_app_dependencies dep1 dep2 "dep3|dep4|dep5"
|
||||
# example : ynh_apt_install_dependencies dep1 dep2 "dep3|dep4|dep5"
|
||||
#
|
||||
# usage: ynh_install_app_dependencies dep [dep [...]]
|
||||
# usage: ynh_apt_install_dependencies dep [dep [...]]
|
||||
# | arg: dep - the package name to install in dependence.
|
||||
# | arg: "dep1|dep2|…" - You can specify alternatives. It will require to install (dep1 or dep2, etc).
|
||||
#
|
||||
|
@ -39,8 +39,7 @@ ynh_apt_install_dependencies() {
|
|||
# The (?<=php) syntax corresponds to lookbehind ;)
|
||||
local specific_php_version=$(grep -oP '(?<=php)[0-9.]+(?=-|\>|)' <<< "$dependencies" | sort -u)
|
||||
|
||||
if [[ -n "$specific_php_version" ]]
|
||||
then
|
||||
if [[ -n "$specific_php_version" ]]; then
|
||||
# Cover a small edge case where a packager could have specified "php7.4-pwet php5-gni" which is confusing
|
||||
[[ $(echo $specific_php_version | wc -l) -eq 1 ]] \
|
||||
|| ynh_die "Inconsistent php versions in dependencies ... found : $specific_php_version"
|
||||
|
@ -51,8 +50,7 @@ ynh_apt_install_dependencies() {
|
|||
|
||||
# If the PHP version changed, remove the old fpm conf
|
||||
if [ -n "$old_php_version" ] && [ "$old_php_version" != "$specific_php_version" ]; then
|
||||
if [[ -f "/etc/php/$php_version/fpm/pool.d/$app.conf" ]]
|
||||
then
|
||||
if [[ -f "/etc/php/$php_version/fpm/pool.d/$app.conf" ]]; then
|
||||
ynh_backup_if_checksum_is_different "/etc/php/$php_version/fpm/pool.d/$app.conf"
|
||||
ynh_config_remove_phpfpm
|
||||
fi
|
||||
|
@ -61,8 +59,7 @@ ynh_apt_install_dependencies() {
|
|||
ynh_app_setting_set --key=php_version --value=$specific_php_version
|
||||
|
||||
# Set the default php version back as the default version for php-cli.
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
then
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
|
||||
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
fi
|
||||
elif grep --quiet 'php' <<< "$dependencies"; then
|
||||
|
@ -72,18 +69,16 @@ ynh_apt_install_dependencies() {
|
|||
# Specific tweak related to Postgresql (cf end of the helper)
|
||||
local psql_installed="$(_ynh_apt_package_is_installed "postgresql-$PSQL_VERSION" && echo yes || echo no)"
|
||||
|
||||
# The first time we run ynh_install_app_dependencies, we will replace the
|
||||
# The first time we run ynh_apt_install_dependencies, we will replace the
|
||||
# entire control file (This is in particular meant to cover the case of
|
||||
# upgrade script where ynh_install_app_dependencies is called with this
|
||||
# upgrade script where ynh_apt_install_dependencies is called with this
|
||||
# expected effect) Otherwise, any subsequent call will add dependencies
|
||||
# to those already present in the equivs control file.
|
||||
if [[ $YNH_APT_INSTALL_DEPENDENCIES_REPLACE == "true" ]]
|
||||
then
|
||||
if [[ $YNH_APT_INSTALL_DEPENDENCIES_REPLACE == "true" ]]; then
|
||||
YNH_APT_INSTALL_DEPENDENCIES_REPLACE="false"
|
||||
else
|
||||
local current_dependencies=""
|
||||
if _ynh_apt_package_is_installed "${app_ynh_deps}"
|
||||
then
|
||||
if _ynh_apt_package_is_installed "${app_ynh_deps}"; then
|
||||
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${app_ynh_deps}) "
|
||||
current_dependencies=${current_dependencies// | /|}
|
||||
fi
|
||||
|
@ -145,8 +140,7 @@ EOF
|
|||
# Specific tweak related to Postgresql
|
||||
# -> trigger postgresql regenconf if we may have just installed postgresql
|
||||
local psql_installed2="$(_ynh_apt_package_is_installed "postgresql-$PSQL_VERSION" && echo yes || echo no)"
|
||||
if [[ "$psql_installed" != "$psql_installed2" ]]
|
||||
then
|
||||
if [[ "$psql_installed" != "$psql_installed2" ]]; then
|
||||
yunohost tools regen-conf postgresql
|
||||
fi
|
||||
|
||||
|
@ -168,16 +162,14 @@ ynh_apt_remove_dependencies() {
|
|||
|
||||
# Edge case where the app dep may be on hold,
|
||||
# cf https://forum.yunohost.org/t/migration-error-cause-of-ffsync/20675/4
|
||||
if apt-mark showhold | grep -q -w ${app_ynh_deps}
|
||||
then
|
||||
if apt-mark showhold | grep -q -w ${app_ynh_deps}; then
|
||||
apt-mark unhold ${app_ynh_deps}
|
||||
fi
|
||||
|
||||
# Remove the fake package and its dependencies if they not still used.
|
||||
# (except if dpkg doesn't know anything about the package,
|
||||
# which should be symptomatic of a failed install, and we don't want bash to report an error)
|
||||
if dpkg-query --show ${app_ynh_deps} &>/dev/null
|
||||
then
|
||||
if dpkg-query --show ${app_ynh_deps} &> /dev/null; then
|
||||
_ynh_apt autoremove --purge ${app_ynh_deps}
|
||||
fi
|
||||
}
|
||||
|
@ -206,8 +198,10 @@ ynh_apt_install_dependencies_from_extra_repository() {
|
|||
if [[ "${repo_parts[0]}" == "deb" ]]; then
|
||||
index=1
|
||||
fi
|
||||
uri="${repo_parts[$index]}" ; index=$((index+1))
|
||||
suite="${repo_parts[$index]}" ; index=$((index+1))
|
||||
uri="${repo_parts[$index]}"
|
||||
index=$((index + 1))
|
||||
suite="${repo_parts[$index]}"
|
||||
index=$((index + 1))
|
||||
|
||||
# Get the components
|
||||
if (("${#repo_parts[@]}" > 0)); then
|
||||
|
|
|
@ -27,13 +27,11 @@ ynh_backup() {
|
|||
local is_data=false
|
||||
|
||||
# If the path starts with /var/log/$app or $data_dir
|
||||
if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]])
|
||||
then
|
||||
if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]); then
|
||||
is_data=true
|
||||
fi
|
||||
|
||||
if [[ -n "${app:-}" ]]
|
||||
then
|
||||
if [[ -n "${app:-}" ]]; then
|
||||
local do_not_backup_data=$(ynh_app_setting_get --key=do_not_backup_data)
|
||||
fi
|
||||
|
||||
|
@ -135,15 +133,13 @@ ynh_restore() {
|
|||
|
||||
# If the path starts with /var/log/$app or $data_dir
|
||||
local is_data=false
|
||||
if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]])
|
||||
then
|
||||
if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]); then
|
||||
is_data=true
|
||||
fi
|
||||
|
||||
# If archive_path doesn't exist, search for a corresponding path in CSV
|
||||
if [ ! -d "$archive_path" ] && [ ! -f "$archive_path" ] && [ ! -L "$archive_path" ]; then
|
||||
if [[ "$is_data" == true ]]
|
||||
then
|
||||
if [[ "$is_data" == true ]]; then
|
||||
ynh_print_info "Skipping $target which doesn't exists in the archive, probably because restoring from a safety-backup-before-upgrade"
|
||||
# Assume it's not a big deal, we may be restoring a safety-backup-before-upgrade which doesnt contain those
|
||||
return 0
|
||||
|
@ -194,7 +190,7 @@ ynh_restore_everything() {
|
|||
# For each destination path begining by $REL_DIR
|
||||
cat ${YNH_BACKUP_CSV} | tr --delete $'\r' | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR.*\"$" \
|
||||
| while read line; do
|
||||
local ARCHIVE_PATH=$(echo "$line" | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR\K.*(?=\"$)")
|
||||
local ARCHIVE_PATH=$(echo "$line" | grep --only-matching --no-filename --perl-regexp "^\"\K.*(?=\",\"$REL_DIR.*\"$)")
|
||||
ynh_restore "$ARCHIVE_PATH"
|
||||
done
|
||||
}
|
||||
|
@ -256,8 +252,7 @@ ynh_backup_if_checksum_is_different() {
|
|||
echo "$backup_file_checksum" # Return the name of the backup file
|
||||
if ynh_in_ci_tests; then
|
||||
local file_path_base64=$(echo "$file" | base64 -w0)
|
||||
if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64}
|
||||
then
|
||||
if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64}; then
|
||||
ynh_print_warn "Diff with the original file:"
|
||||
diff --report-identical-files --unified --color=always /var/cache/yunohost/appconfbackup/original_${file_path_base64} $file >&2 || true
|
||||
fi
|
||||
|
|
|
@ -22,7 +22,7 @@ _ynh_app_config_get_one() {
|
|||
if [[ "$bind" == "settings" ]]; then
|
||||
ynh_die "File '${short_setting}' can't be stored in settings"
|
||||
fi
|
||||
old[$short_setting]="$(ls "$(echo $bind | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s/__APP__/$app/)" 2>/dev/null || echo YNH_NULL)"
|
||||
old[$short_setting]="$(ls "$bind" 2> /dev/null || echo YNH_NULL)"
|
||||
file_hash[$short_setting]="true"
|
||||
|
||||
# Get multiline text from settings or from a full file
|
||||
|
@ -32,7 +32,7 @@ _ynh_app_config_get_one() {
|
|||
elif [[ "$bind" == *":"* ]]; then
|
||||
ynh_die "For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
|
||||
else
|
||||
old[$short_setting]="$(cat $(echo $bind | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s/__APP__/$app/) 2>/dev/null || echo YNH_NULL)"
|
||||
old[$short_setting]="$(cat "$bind" 2> /dev/null || echo YNH_NULL)"
|
||||
fi
|
||||
|
||||
# Get value from a kind of key/value file
|
||||
|
@ -47,7 +47,7 @@ _ynh_app_config_get_one() {
|
|||
bind_after="$(echo "${bind_key_}" | cut -d'>' -f1)"
|
||||
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2 | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2)"
|
||||
old[$short_setting]="$(ynh_read_var_in_file --file="${bind_file}" --key="${bind_key_}" --after="${bind_after}")"
|
||||
|
||||
fi
|
||||
|
@ -73,7 +73,7 @@ _ynh_app_config_apply_one() {
|
|||
if [[ "$bind" == "settings" ]]; then
|
||||
ynh_die "File '${short_setting}' can't be stored in settings"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$bind"
|
||||
if [[ "${!short_setting}" == "" ]]; then
|
||||
ynh_backup_if_checksum_is_different "$bind_file"
|
||||
ynh_safe_rm "$bind_file"
|
||||
|
@ -84,8 +84,7 @@ _ynh_app_config_apply_one() {
|
|||
if [[ "${!short_setting}" != "$bind_file" ]]; then
|
||||
cp "${!short_setting}" "$bind_file"
|
||||
fi
|
||||
if _ynh_file_checksum_exists "$bind_file"
|
||||
then
|
||||
if _ynh_file_checksum_exists "$bind_file"; then
|
||||
ynh_store_file_checksum "$bind_file"
|
||||
fi
|
||||
ynh_print_info "File '$bind_file' overwritten with ${!short_setting}"
|
||||
|
@ -101,11 +100,10 @@ _ynh_app_config_apply_one() {
|
|||
if [[ "$bind" == *":"* ]]; then
|
||||
ynh_die "For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$bind"
|
||||
ynh_backup_if_checksum_is_different "$bind_file"
|
||||
echo "${!short_setting}" > "$bind_file"
|
||||
if _ynh_file_checksum_exists "$bind_file"
|
||||
then
|
||||
if _ynh_file_checksum_exists "$bind_file"; then
|
||||
ynh_store_file_checksum "$bind_file"
|
||||
fi
|
||||
ynh_print_info "File '$bind_file' overwritten with the content provided in question '${short_setting}'"
|
||||
|
@ -119,12 +117,11 @@ _ynh_app_config_apply_one() {
|
|||
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
|
||||
fi
|
||||
bind_key_=${bind_key_:-$short_setting}
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2 | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2)"
|
||||
|
||||
ynh_backup_if_checksum_is_different "$bind_file"
|
||||
ynh_write_var_in_file --file="${bind_file}" --key="${bind_key_}" --value="${!short_setting}" --after="${bind_after}"
|
||||
if _ynh_file_checksum_exists "$bind_file"
|
||||
then
|
||||
if _ynh_file_checksum_exists "$bind_file"; then
|
||||
ynh_store_file_checksum "$bind_file"
|
||||
fi
|
||||
|
||||
|
@ -135,60 +132,9 @@ _ynh_app_config_apply_one() {
|
|||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_ynh_app_config_get() {
|
||||
# From settings
|
||||
local lines
|
||||
lines=$(
|
||||
python3 <<EOL
|
||||
import toml
|
||||
from collections import OrderedDict
|
||||
with open("../config_panel.toml", "r") as f:
|
||||
file_content = f.read()
|
||||
loaded_toml = toml.loads(file_content, _dict=OrderedDict)
|
||||
|
||||
for panel_name, panel in loaded_toml.items():
|
||||
if not isinstance(panel, dict): continue
|
||||
bind_panel = panel.get('bind')
|
||||
for section_name, section in panel.items():
|
||||
if not isinstance(section, dict): continue
|
||||
bind_section = section.get('bind')
|
||||
if not bind_section:
|
||||
bind_section = bind_panel
|
||||
elif bind_section[-1] == ":" and bind_panel and ":" in bind_panel:
|
||||
regex, bind_panel_file = bind_panel.split(":")
|
||||
if ">" in bind_section:
|
||||
bind_section = bind_section + bind_panel_file
|
||||
else:
|
||||
bind_section = regex + bind_section + bind_panel_file
|
||||
|
||||
for name, param in section.items():
|
||||
if not isinstance(param, dict):
|
||||
continue
|
||||
|
||||
bind = param.get('bind')
|
||||
|
||||
if not bind:
|
||||
if bind_section:
|
||||
bind = bind_section
|
||||
else:
|
||||
bind = 'settings'
|
||||
elif bind[-1] == ":" and bind_section and ":" in bind_section:
|
||||
regex, bind_file = bind_section.split(":")
|
||||
if ">" in bind:
|
||||
bind = bind + bind_file
|
||||
else:
|
||||
bind = regex + bind + bind_file
|
||||
if bind == "settings" and param.get('type', 'string') == 'file':
|
||||
bind = 'null'
|
||||
|
||||
print('|'.join([
|
||||
name,
|
||||
param.get('type', 'string'),
|
||||
bind
|
||||
]))
|
||||
EOL
|
||||
)
|
||||
for line in $lines; do
|
||||
for line in $YNH_APP_CONFIG_PANEL_OPTIONS_TYPES_AND_BINDS; do
|
||||
# Split line into short_setting, type and bind
|
||||
IFS='|' read short_setting type bind <<< "$line"
|
||||
binds[${short_setting}]="$bind"
|
||||
|
@ -197,7 +143,6 @@ EOL
|
|||
formats[${short_setting}]=""
|
||||
ynh_app_config_get_one $short_setting $type $bind
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
_ynh_app_config_apply() {
|
||||
|
@ -359,5 +304,6 @@ ynh_app_config_run() {
|
|||
;;
|
||||
*)
|
||||
ynh_app_action_run $1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
|
|
@ -50,8 +50,7 @@ ynh_handle_getopts_args() {
|
|||
eval "$xtrace_enable"
|
||||
return
|
||||
# Validate that the first char is - because it should be something like --option=value or -o ...
|
||||
elif [[ "${1:0:1}" != "-" ]]
|
||||
then
|
||||
elif [[ "${1:0:1}" != "-" ]]; then
|
||||
ynh_die "It looks like you called the helper using positional arguments instead of keyword arguments ?"
|
||||
fi
|
||||
|
||||
|
|
|
@ -156,29 +156,24 @@ _ynh_go_cleanup () {
|
|||
# List required Go versions
|
||||
local installed_apps=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
|
||||
local required_go_versions=""
|
||||
for installed_app in $installed_apps
|
||||
do
|
||||
for installed_app in $installed_apps; do
|
||||
local installed_app_go_version=$(ynh_app_setting_get --app=$installed_app --key="go_version")
|
||||
if [[ $installed_app_go_version ]]
|
||||
then
|
||||
if [[ $installed_app_go_version ]]; then
|
||||
required_go_versions="${installed_app_go_version}\n${required_go_versions}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove no more needed Go versions
|
||||
local installed_go_versions=$(goenv versions --bare --skip-aliases | grep -Ev '/')
|
||||
for installed_go_version in $installed_go_versions
|
||||
do
|
||||
if ! `echo ${required_go_versions} | grep "${installed_go_version}" 1>/dev/null 2>&1`
|
||||
then
|
||||
for installed_go_version in $installed_go_versions; do
|
||||
if ! $(echo ${required_go_versions} | grep "${installed_go_version}" 1> /dev/null 2>&1); then
|
||||
ynh_print_info "Removing of Go-$installed_go_version"
|
||||
$GOENV_INSTALL_DIR/bin/goenv uninstall --force "$installed_go_version"
|
||||
fi
|
||||
done
|
||||
|
||||
# If none Go version is required
|
||||
if [[ ! $required_go_versions ]]
|
||||
then
|
||||
if [[ ! $required_go_versions ]]; then
|
||||
# Remove goenv environment configuration
|
||||
ynh_print_info "Removing of goenv"
|
||||
ynh_safe_rm "$GOENV_INSTALL_DIR"
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
# usage: ynh_die "Some message"
|
||||
ynh_die() {
|
||||
set +o xtrace # set +x
|
||||
if [[ -n "${1:-}" ]]
|
||||
then
|
||||
if [[ -n "${YNH_STDRETURN:-}" ]]
|
||||
then
|
||||
if [[ -n "${1:-}" ]]; then
|
||||
if [[ -n "${YNH_STDRETURN:-}" ]]; then
|
||||
python3 -c 'import yaml, sys; print(yaml.dump({"error": sys.stdin.read()}))' <<< "${1:-}" >> "$YNH_STDRETURN"
|
||||
fi
|
||||
echo "${1:-}" 1>&2
|
||||
|
@ -105,8 +103,7 @@ ynh_script_progression() {
|
|||
local expected_progression="$((($increment_progression + 1) * $progress_scale / $max_progression - $effective_progression))"
|
||||
|
||||
# Hack for the "--last" message
|
||||
if grep -qw 'completed' <<< "$1";
|
||||
then
|
||||
if grep -qw 'completed' <<< "$1"; then
|
||||
effective_progression=$progress_scale
|
||||
expected_progression=0
|
||||
fi
|
||||
|
|
|
@ -22,8 +22,7 @@ ynh_config_add_logrotate() {
|
|||
fi
|
||||
set +o noglob
|
||||
|
||||
for stuff in $logfile
|
||||
do
|
||||
for stuff in $logfile; do
|
||||
# Make sure the permissions of the parent dir are correct (otherwise the config file could be ignored and the corresponding logs never rotated)
|
||||
local dir=$(dirname "$stuff")
|
||||
mkdir --parents $dir
|
||||
|
@ -53,8 +52,7 @@ $logfile {
|
|||
}
|
||||
EOF
|
||||
|
||||
if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]]
|
||||
then
|
||||
if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]]; then
|
||||
cat $tempconf > /etc/logrotate.d/$app
|
||||
else
|
||||
cat $tempconf >> /etc/logrotate.d/$app
|
||||
|
|
|
@ -19,8 +19,7 @@ ynh_mongo_exec() {
|
|||
database="${database:-}"
|
||||
# ===========================================
|
||||
|
||||
if [ -n "$database" ]
|
||||
then
|
||||
if [ -n "$database" ]; then
|
||||
mongosh --quiet << EOF
|
||||
use $database
|
||||
${command}
|
||||
|
@ -111,8 +110,7 @@ ynh_mongo_database_exists() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")') -lt 0 ]
|
||||
then
|
||||
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")') -lt 0 ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
@ -262,8 +260,7 @@ ynh_install_mongo() {
|
|||
#
|
||||
ynh_remove_mongo() {
|
||||
# Only remove the mongodb service if it is not installed.
|
||||
if ! _ynh_apt_package_is_installed "mongodb*"
|
||||
then
|
||||
if ! _ynh_apt_package_is_installed "mongodb*"; then
|
||||
ynh_print_info "Removing MongoDB service..."
|
||||
mongodb_servicename=mongod
|
||||
# Remove the mongodb service
|
||||
|
|
|
@ -39,7 +39,6 @@ ynh_config_remove_nginx() {
|
|||
ynh_systemctl --service=nginx --action=reload
|
||||
}
|
||||
|
||||
|
||||
# Regen the nginx config in a change url context
|
||||
#
|
||||
# usage: ynh_config_change_url_nginx
|
||||
|
|
|
@ -13,10 +13,8 @@ ynh_redis_get_free_db() {
|
|||
|
||||
db=0
|
||||
# default Debian setting is 15 databases
|
||||
for i in $(seq 0 "$max")
|
||||
do
|
||||
if ! echo "$result" | grep -q "db$i"
|
||||
then
|
||||
for i in $(seq 0 "$max"); do
|
||||
if ! echo "$result" | grep -q "db$i"; then
|
||||
db=$i
|
||||
break 1
|
||||
fi
|
||||
|
|
|
@ -153,8 +153,7 @@ ynh_ruby_install () {
|
|||
ruby_version=$final_ruby_version
|
||||
|
||||
# Remove app virtualenv
|
||||
if rbenv alias --list | grep --quiet "$app "
|
||||
then
|
||||
if rbenv alias --list | grep --quiet "$app "; then
|
||||
rbenv alias $app --remove
|
||||
fi
|
||||
|
||||
|
@ -213,29 +212,24 @@ _ynh_ruby_cleanup () {
|
|||
# List required Ruby versions
|
||||
local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$')
|
||||
local required_ruby_versions=""
|
||||
for installed_app in $installed_apps
|
||||
do
|
||||
for installed_app in $installed_apps; do
|
||||
local installed_app_ruby_version=$(ynh_app_setting_get --app=$installed_app --key="ruby_version")
|
||||
if [[ -n "$installed_app_ruby_version" ]]
|
||||
then
|
||||
if [[ -n "$installed_app_ruby_version" ]]; then
|
||||
required_ruby_versions="${installed_app_ruby_version}\n${required_ruby_versions}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove no more needed Ruby versions
|
||||
local installed_ruby_versions=$(rbenv versions --bare --skip-aliases | grep -Ev '/')
|
||||
for installed_ruby_version in $installed_ruby_versions
|
||||
do
|
||||
if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"
|
||||
then
|
||||
for installed_ruby_version in $installed_ruby_versions; do
|
||||
if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"; then
|
||||
echo "Removing Ruby-$installed_ruby_version"
|
||||
$RBENV_INSTALL_DIR/bin/rbenv uninstall --force $installed_ruby_version
|
||||
fi
|
||||
done
|
||||
|
||||
# If none Ruby version is required
|
||||
if [[ -z "$required_ruby_versions" ]]
|
||||
then
|
||||
if [[ -z "$required_ruby_versions" ]]; then
|
||||
# Remove rbenv environment configuration
|
||||
echo "Removing rbenv"
|
||||
ynh_safe_rm "$RBENV_INSTALL_DIR"
|
||||
|
|
|
@ -125,15 +125,11 @@ EOF
|
|||
|
||||
# Legacy: auto-convert phpversion to php_version (for consistency with nodejs_version, ruby_version, ...)
|
||||
# This has to be here and not in the "php" code file because ynh_app_setting_set/delete need to be defined @_@
|
||||
if [[ -n "${app:-}" ]] && [[ -n "${phpversion:-}" ]]
|
||||
then
|
||||
if [[ -z "${php_version:-}" ]]
|
||||
then
|
||||
if [[ -n "${app:-}" ]] && [[ -n "${phpversion:-}" ]]; then
|
||||
if [[ -z "${php_version:-}" ]]; then
|
||||
php_version=$phpversion
|
||||
ynh_app_setting_set --key=php_version --value=$php_version
|
||||
fi
|
||||
ynh_app_setting_delete --key=phpversion
|
||||
unset phpversion
|
||||
fi
|
||||
|
||||
|
||||
|
|
|
@ -74,8 +74,7 @@ ynh_setup_source() {
|
|||
# ===========================================
|
||||
|
||||
local sources_json=$(ynh_read_manifest "resources.sources[\"$source_id\"]")
|
||||
if jq -re ".url" <<< "$sources_json"
|
||||
then
|
||||
if jq -re ".url" <<< "$sources_json"; then
|
||||
local arch_prefix=""
|
||||
else
|
||||
local arch_prefix=".$YNH_ARCH"
|
||||
|
@ -93,25 +92,18 @@ ynh_setup_source() {
|
|||
[[ -n "$src_url" ]] || ynh_die "No URL defined for source $source_id$arch_prefix ?"
|
||||
[[ -n "$src_sum" ]] || ynh_die "No sha256 sum defined for source $source_id$arch_prefix ?"
|
||||
|
||||
if [[ -z "$src_format" ]]
|
||||
then
|
||||
if [[ "$src_url" =~ ^.*\.zip$ ]] || [[ "$src_url" =~ ^.*/zipball/.*$ ]]
|
||||
then
|
||||
if [[ -z "$src_format" ]]; then
|
||||
if [[ "$src_url" =~ ^.*\.zip$ ]] || [[ "$src_url" =~ ^.*/zipball/.*$ ]]; then
|
||||
src_format="zip"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.gz$ ]] || [[ "$src_url" =~ ^.*\.tgz$ ]] || [[ "$src_url" =~ ^.*/tar\.gz/.*$ ]] || [[ "$src_url" =~ ^.*/tarball/.*$ ]]
|
||||
then
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.gz$ ]] || [[ "$src_url" =~ ^.*\.tgz$ ]] || [[ "$src_url" =~ ^.*/tar\.gz/.*$ ]] || [[ "$src_url" =~ ^.*/tarball/.*$ ]]; then
|
||||
src_format="tar.gz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.xz$ ]]
|
||||
then
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.xz$ ]]; then
|
||||
src_format="tar.xz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]
|
||||
then
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]; then
|
||||
src_format="tar.bz2"
|
||||
elif [[ "$src_url" =~ ^.*\.tar$ ]]
|
||||
then
|
||||
elif [[ "$src_url" =~ ^.*\.tar$ ]]; then
|
||||
src_format="tar"
|
||||
elif [[ -z "$src_extract" ]]
|
||||
then
|
||||
elif [[ -z "$src_extract" ]]; then
|
||||
src_extract="false"
|
||||
fi
|
||||
fi
|
||||
|
@ -120,8 +112,7 @@ ynh_setup_source() {
|
|||
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
|
||||
src_extract=${src_extract:-true}
|
||||
|
||||
if [[ "$src_extract" != "true" ]] && [[ "$src_extract" != "false" ]]
|
||||
then
|
||||
if [[ "$src_extract" != "true" ]] && [[ "$src_extract" != "false" ]]; then
|
||||
ynh_die "For source $source_id, expected either 'true' or 'false' for the extract parameter"
|
||||
fi
|
||||
|
||||
|
@ -135,14 +126,12 @@ ynh_setup_source() {
|
|||
[ -n "$src_url" ] || ynh_die "Couldn't parse SOURCE_URL from $src_file_path ?"
|
||||
|
||||
# If the file was prefetched but somehow doesn't match the sum, rm and redownload it
|
||||
if [ -e "$src_filename" ] && ! echo "${src_sum} ${src_filename}" | sha256sum --check --status
|
||||
then
|
||||
if [ -e "$src_filename" ] && ! echo "${src_sum} ${src_filename}" | sha256sum --check --status; then
|
||||
rm -f "$src_filename"
|
||||
fi
|
||||
|
||||
# Only redownload the file if it wasnt prefetched
|
||||
if [ ! -e "$src_filename" ]
|
||||
then
|
||||
if [ ! -e "$src_filename" ]; then
|
||||
# NB. we have to declare the var as local first,
|
||||
# otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
|
||||
# because local always return 0 ...
|
||||
|
@ -153,8 +142,7 @@ ynh_setup_source() {
|
|||
fi
|
||||
|
||||
# Check the control sum
|
||||
if ! echo "${src_sum} ${src_filename}" | sha256sum --check --status
|
||||
then
|
||||
if ! echo "${src_sum} ${src_filename}" | sha256sum --check --status; then
|
||||
local actual_sum="$(sha256sum ${src_filename} | cut --delimiter=' ' --fields=1)"
|
||||
local actual_size="$(du -hs ${src_filename} | cut --fields=1)"
|
||||
rm -f ${src_filename}
|
||||
|
@ -185,8 +173,7 @@ ynh_setup_source() {
|
|||
mkdir --parents "$dest_dir"
|
||||
|
||||
if [[ "$src_extract" == "false" ]]; then
|
||||
if [[ -z "$src_rename" ]]
|
||||
then
|
||||
if [[ -z "$src_rename" ]]; then
|
||||
mv $src_filename $dest_dir
|
||||
else
|
||||
mv $src_filename $dest_dir/$src_rename
|
||||
|
@ -224,8 +211,8 @@ ynh_setup_source() {
|
|||
fi
|
||||
|
||||
# Apply patches
|
||||
if [ -d "$YNH_APP_BASEDIR/patches/" ]; then
|
||||
local patches_folder=$(realpath "$YNH_APP_BASEDIR/patches/$source_id")
|
||||
if [ -d "$patches_folder" ]; then
|
||||
pushd "$dest_dir"
|
||||
for patchfile in "$patches_folder/"*.patch; do
|
||||
echo "Applying $patchfile"
|
||||
|
|
|
@ -68,8 +68,7 @@ ynh_systemctl() {
|
|||
# ===========================================
|
||||
|
||||
# On CI, use length=100 because it's sometime hell to debug otherwise for super-long output
|
||||
if ynh_in_ci_tests && [ $length -le 20 ]
|
||||
then
|
||||
if ynh_in_ci_tests && [ $length -le 20 ]; then
|
||||
length=100
|
||||
fi
|
||||
|
||||
|
@ -139,8 +138,7 @@ ynh_systemctl() {
|
|||
# Also check the timeout using actual timestamp, because sometimes for some reason,
|
||||
# journalctl may take a huge time to run, and we end up waiting literally an entire hour
|
||||
# instead of 5 min ...
|
||||
if [[ "$(( $(date +%s) - $starttime))" -gt "$timeout" ]]
|
||||
then
|
||||
if [[ "$(($(date +%s) - $starttime))" -gt "$timeout" ]]; then
|
||||
i=$timeout
|
||||
break
|
||||
fi
|
||||
|
@ -160,8 +158,7 @@ ynh_systemctl() {
|
|||
fi
|
||||
|
||||
# If we tried to reload/start/restart the service but systemctl consider it to be still inactive/broken, then handle it as a failure
|
||||
if ([ "$action" == "reload" ] || [ "$action" == "start" ] || [ "$action" == "restart" ]) && ! systemctl --quiet is-active $service
|
||||
then
|
||||
if ([ "$action" == "reload" ] || [ "$action" == "start" ] || [ "$action" == "restart" ]) && ! systemctl --quiet is-active $service; then
|
||||
_ynh_clean_check_starting
|
||||
return 1
|
||||
fi
|
||||
|
|
|
@ -70,8 +70,7 @@ ynh_config_add() {
|
|||
chmod 640 $destination
|
||||
_ynh_apply_default_permissions $destination
|
||||
|
||||
if [[ "$jinja" == 1 ]]
|
||||
then
|
||||
if [[ "$jinja" == 1 ]]; then
|
||||
# This is ran in a subshell such that the "export" does not "contaminate" the main process
|
||||
(
|
||||
export $(compgen -v)
|
||||
|
|
|
@ -9,8 +9,7 @@ YNH_APP_BASEDIR=${YNH_APP_BASEDIR:-$(realpath ..)}
|
|||
ynh_exit_properly() {
|
||||
local exit_code=$?
|
||||
|
||||
if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]]
|
||||
then
|
||||
if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]]; then
|
||||
rm -rf "/var/cache/yunohost/download/"
|
||||
fi
|
||||
|
||||
|
@ -47,8 +46,7 @@ ynh_abort_if_errors() {
|
|||
}
|
||||
|
||||
# When running an app script, auto-enable ynh_abort_if_errors except for remove script
|
||||
if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && [[ "${YNH_APP_ACTION}" != "remove" ]]
|
||||
then
|
||||
if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && [[ "${YNH_APP_ACTION}" != "remove" ]]; then
|
||||
ynh_abort_if_errors
|
||||
fi
|
||||
|
||||
|
@ -124,8 +122,7 @@ _acceptable_path_to_delete() {
|
|||
local forbidden_paths=$(ls -d / /* /{var,home,usr}/* /etc/{default,sudoers.d,yunohost,cron*} /etc/yunohost/{apps,domains,hooks.d} /opt/yunohost 2> /dev/null)
|
||||
|
||||
# Legacy : A couple apps still have data in /home/$app ...
|
||||
if [[ -n "${app:-}" ]]
|
||||
then
|
||||
if [[ -n "${app:-}" ]]; then
|
||||
forbidden_paths=$(echo "$forbidden_paths" | grep -v "/home/$app")
|
||||
fi
|
||||
|
||||
|
@ -231,23 +228,19 @@ _ynh_apply_default_permissions() {
|
|||
# App files can have files of their own
|
||||
if ynh_system_user_exists --username="$app"; then
|
||||
# If this is a file in $install_dir or $data_dir : it should be owned and read+writable by $app only
|
||||
if [ -f "$target" ] && (is_in_dir "$target" "${install_dir:-}" || is_in_dir "$target" "${data_dir:-}" || is_in_dir "$target" "/etc/$app")
|
||||
then
|
||||
if [ -f "$target" ] && (is_in_dir "$target" "${install_dir:-}" || is_in_dir "$target" "${data_dir:-}" || is_in_dir "$target" "/etc/$app"); then
|
||||
chmod 600 "$target"
|
||||
chown "$app:$app" "$target"
|
||||
return
|
||||
fi
|
||||
# If this is the install dir (so far this is the only way this helper is called with a directory)
|
||||
if [ "$target" == "${install_dir:-}" ]
|
||||
then
|
||||
if [ "$target" == "${install_dir:-}" ]; then
|
||||
# Read the group from the install_dir manifest resource
|
||||
local group="$(ynh_read_manifest 'resources.install_dir.group' | sed 's/null//g' | sed "s/__APP__/$app/g" | cut -f1 -d:)"
|
||||
if [[ -z "$group" ]]
|
||||
then
|
||||
if [[ -z "$group" ]]; then
|
||||
# We set the group to www-data for webapps that do serve static assets, which therefore need to be readable by nginx ...
|
||||
# The fact that the app needs this is infered by the existence of an nginx.conf and the presence of "alias" or "root" directive
|
||||
if grep -q '^\s*alias\s\|^\s*root\s' "$YNH_APP_BASEDIR/conf/nginx.conf" 2>/dev/null;
|
||||
then
|
||||
if grep -q '^\s*alias\s\|^\s*root\s' "$YNH_APP_BASEDIR/conf/nginx.conf" 2> /dev/null; then
|
||||
group="www-data"
|
||||
# Or default to "$app"
|
||||
else
|
||||
|
@ -407,41 +400,37 @@ ynh_spawn_app_shell() {
|
|||
|
||||
# Load the app's service name, or default to $app
|
||||
local service=$(ynh_app_setting_get --app=$app --key=service)
|
||||
[ -z "$service" ] && service=$app;
|
||||
[ -z "$service" ] && service=$app
|
||||
|
||||
# Export HOME variable
|
||||
export HOME=$install_dir;
|
||||
export HOME=$install_dir
|
||||
|
||||
# Load the Environment variables from the app's service
|
||||
local env_var=$(systemctl show $service.service -p "Environment" --value)
|
||||
[ -n "$env_var" ] && export $env_var;
|
||||
[ -n "$env_var" ] && export $env_var
|
||||
|
||||
# Force `php` to its intended version
|
||||
# We use `eval`+`export` since `alias` is not propagated to subshells, even with `export`
|
||||
local phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||
local phpflags=$(ynh_app_setting_get --app=$app --key=phpflags)
|
||||
if [ -n "$phpversion" ]
|
||||
then
|
||||
if [ -n "$phpversion" ]; then
|
||||
eval "php() { php${phpversion} ${phpflags} \"\$@\"; }"
|
||||
export -f php
|
||||
fi
|
||||
|
||||
# Source the EnvironmentFiles from the app's service
|
||||
local env_files=($(systemctl show $service.service -p "EnvironmentFiles" --value))
|
||||
if [ ${#env_files[*]} -gt 0 ]
|
||||
then
|
||||
if [ ${#env_files[*]} -gt 0 ]; then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
for file in ${env_files[*]}
|
||||
do
|
||||
for file in ${env_files[*]}; do
|
||||
[[ $file = /* ]] && source $file
|
||||
done
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Activate the Python environment, if it exists
|
||||
if [ -f $install_dir/venv/bin/activate ]
|
||||
then
|
||||
if [ -f $install_dir/venv/bin/activate ]; then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
source $install_dir/venv/bin/activate
|
||||
|
@ -450,9 +439,145 @@ ynh_spawn_app_shell() {
|
|||
|
||||
# cd into the WorkingDirectory set in the service, or default to the install_dir
|
||||
local env_dir=$(systemctl show $service.service -p "WorkingDirectory" --value)
|
||||
[ -z $env_dir ] && env_dir=$install_dir;
|
||||
[ -z $env_dir ] && env_dir=$install_dir
|
||||
cd $env_dir
|
||||
|
||||
# Spawn the app shell
|
||||
su -s /bin/bash $app
|
||||
}
|
||||
|
||||
# Add swap
|
||||
#
|
||||
# usage: ynh_add_swap --size=SWAP in Mb
|
||||
# | arg: -s, --size= - Amount of SWAP to add in Mb.
|
||||
ynh_add_swap() {
|
||||
if systemd-detect-virt --container --quiet; then
|
||||
ynh_print_warn --message="You are inside a container/VM. swap will not be added, but that can cause troubles for the app $app. Please make sure you have enough RAM available."
|
||||
return
|
||||
fi
|
||||
|
||||
# Declare an array to define the options of this helper.
|
||||
declare -Ar args_array=([s]=size=)
|
||||
local size
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
local swap_max_size=$(($size * 1024))
|
||||
|
||||
local free_space=$(df --output=avail / | sed 1d)
|
||||
# Because we don't want to fill the disk with a swap file, divide by 2 the available space.
|
||||
local usable_space=$(($free_space / 2))
|
||||
|
||||
SD_CARD_CAN_SWAP=${SD_CARD_CAN_SWAP:-0}
|
||||
|
||||
# Swap on SD card only if it's is specified
|
||||
if ynh_is_main_device_a_sd_card && [ "$SD_CARD_CAN_SWAP" == "0" ]; then
|
||||
ynh_print_warn --message="The main mountpoint of your system '/' is on an SD card, swap will not be added to prevent some damage of this one, but that can cause troubles for the app $app. If you still want activate the swap, you can relaunch the command preceded by 'SD_CARD_CAN_SWAP=1'"
|
||||
return
|
||||
fi
|
||||
|
||||
# Compare the available space with the size of the swap.
|
||||
# And set a acceptable size from the request
|
||||
if [ $usable_space -ge $swap_max_size ]; then
|
||||
local swap_size=$swap_max_size
|
||||
elif [ $usable_space -ge $(($swap_max_size / 2)) ]; then
|
||||
local swap_size=$(($swap_max_size / 2))
|
||||
elif [ $usable_space -ge $(($swap_max_size / 3)) ]; then
|
||||
local swap_size=$(($swap_max_size / 3))
|
||||
elif [ $usable_space -ge $(($swap_max_size / 4)) ]; then
|
||||
local swap_size=$(($swap_max_size / 4))
|
||||
else
|
||||
echo "Not enough space left for a swap file" >&2
|
||||
local swap_size=0
|
||||
fi
|
||||
|
||||
# If there's enough space for a swap, and no existing swap here
|
||||
if [ $swap_size -ne 0 ] && [ ! -e /swap_$app ]; then
|
||||
# Create file
|
||||
truncate -s 0 /swap_$app
|
||||
|
||||
# set the No_COW attribute on the swapfile with chattr
|
||||
chattr +C /swap_$app
|
||||
|
||||
# Preallocate space for the swap file, fallocate may sometime not be used, use dd instead in this case
|
||||
if ! fallocate -l ${swap_size}K /swap_$app; then
|
||||
dd if=/dev/zero of=/swap_$app bs=1024 count=${swap_size}
|
||||
fi
|
||||
chmod 0600 /swap_$app
|
||||
# Create the swap
|
||||
mkswap /swap_$app
|
||||
# And activate it
|
||||
swapon /swap_$app
|
||||
# Then add an entry in fstab to load this swap at each boot.
|
||||
echo -e "/swap_$app swap swap defaults 0 0 #Swap added by $app" >> /etc/fstab
|
||||
fi
|
||||
}
|
||||
|
||||
ynh_del_swap() {
|
||||
# If there a swap at this place
|
||||
if [ -e /swap_$app ]; then
|
||||
# Clean the fstab
|
||||
sed -i "/#Swap added by $app/d" /etc/fstab
|
||||
# Desactive the swap file
|
||||
swapoff /swap_$app
|
||||
# And remove it
|
||||
rm /swap_$app
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if the device of the main mountpoint "/" is an SD card
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# return 0 if it's an SD card, else 1
|
||||
ynh_is_main_device_a_sd_card() {
|
||||
if [ "$(systemd-detect-virt)" != "none" ]; then
|
||||
# Assume virtualization does not take place on SD card
|
||||
return 1
|
||||
fi
|
||||
|
||||
local main_device=$(lsblk --output PKNAME --noheadings $(findmnt / --nofsroot --uniq --output source --noheadings --first-only))
|
||||
|
||||
if echo $main_device | grep --quiet "mmc" && [ $(tail -n1 /sys/block/$main_device/queue/rotational) == "0" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check available space before creating a temp directory.
|
||||
#
|
||||
# usage: ynh_smart_mktemp --min_size="Min size"
|
||||
#
|
||||
# | arg: -s, --min_size= - Minimal size needed for the temporary directory, in Mb
|
||||
ynh_smart_mktemp() {
|
||||
# Declare an array to define the options of this helper.
|
||||
declare -Ar args_array=([s]=min_size=)
|
||||
local min_size
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
min_size="${min_size:-300}"
|
||||
# Transform the minimum size from megabytes to kilobytes
|
||||
min_size=$(($min_size * 1024))
|
||||
|
||||
# Check if there's enough free space in a directory
|
||||
is_there_enough_space() {
|
||||
local free_space=$(df --output=avail "$1" | sed 1d)
|
||||
test $free_space -ge $min_size
|
||||
}
|
||||
|
||||
if is_there_enough_space /tmp; then
|
||||
local tmpdir=/tmp
|
||||
elif is_there_enough_space /var; then
|
||||
local tmpdir=/var
|
||||
elif is_there_enough_space /; then
|
||||
local tmpdir=/
|
||||
elif is_there_enough_space /home; then
|
||||
local tmpdir=/home
|
||||
else
|
||||
ynh_die "Insufficient free space to continue..."
|
||||
fi
|
||||
|
||||
echo "$(mktemp --directory --tmpdir="$tmpdir")"
|
||||
}
|
||||
|
|
13
hooks/backup/27-data_xmpp
Normal file
13
hooks/backup/27-data_xmpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#!/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}/data/xmpp"
|
||||
|
||||
ynh_backup /var/lib/metronome "${backup_dir}/var_lib_metronome"
|
||||
ynh_backup /var/xmpp-upload/ "${backup_dir}/var_xmpp-upload"
|
|
@ -2,167 +2,15 @@
|
|||
|
||||
set -e
|
||||
|
||||
base_folder_and_perm_init() {
|
||||
|
||||
#############################
|
||||
# Base yunohost conf folder #
|
||||
#############################
|
||||
|
||||
mkdir -p /etc/yunohost
|
||||
# NB: x permission for 'others' is important for ssl-cert (and maybe mdns), otherwise slapd will fail to start because can't access the certs
|
||||
chmod 755 /etc/yunohost
|
||||
|
||||
################
|
||||
# Logs folders #
|
||||
################
|
||||
|
||||
mkdir -p /var/log/yunohost
|
||||
chown root:root /var/log/yunohost
|
||||
chmod 750 /var/log/yunohost
|
||||
|
||||
##################
|
||||
# Portal folders #
|
||||
##################
|
||||
|
||||
getent passwd ynh-portal &>/dev/null || useradd --no-create-home --shell /usr/sbin/nologin --system --user-group ynh-portal
|
||||
|
||||
mkdir -p /etc/yunohost/portal
|
||||
chmod 500 /etc/yunohost/portal
|
||||
chown ynh-portal:ynh-portal /etc/yunohost/portal
|
||||
|
||||
mkdir -p /usr/share/yunohost/portal/customassets
|
||||
chmod 775 /usr/share/yunohost/portal/customassets
|
||||
chown root:root /usr/share/yunohost/portal/customassets
|
||||
|
||||
touch /var/log/yunohost-portalapi.log
|
||||
chown ynh-portal:root /var/log/yunohost-portalapi.log
|
||||
chmod 600 /var/log/yunohost-portalapi.log
|
||||
|
||||
###############################
|
||||
# Sessions folder and secrets #
|
||||
###############################
|
||||
|
||||
# Portal
|
||||
mkdir -p /var/cache/yunohost-portal/sessions
|
||||
chown ynh-portal:www-data /var/cache/yunohost-portal
|
||||
chmod 510 /var/cache/yunohost-portal
|
||||
chown ynh-portal:www-data /var/cache/yunohost-portal/sessions
|
||||
chmod 710 /var/cache/yunohost-portal/sessions
|
||||
|
||||
# Webadmin
|
||||
mkdir -p /var/cache/yunohost/sessions
|
||||
chown root:root /var/cache/yunohost/sessions
|
||||
chmod 700 /var/cache/yunohost/sessions
|
||||
|
||||
if test -e /etc/yunohost/installed
|
||||
then
|
||||
# Initialize session secrets
|
||||
# Obviously we only do this in the post_regen, ie during the postinstall, because we don't want every pre-installed instance to have the same secret
|
||||
if [ ! -e /etc/yunohost/.admin_cookie_secret ]; then
|
||||
dd if=/dev/urandom bs=1 count=1000 2>/dev/null | tr --complement --delete 'A-Za-z0-9' | head -c 64 > /etc/yunohost/.admin_cookie_secret
|
||||
fi
|
||||
chown root:root /etc/yunohost/.admin_cookie_secret
|
||||
chmod 400 /etc/yunohost/.admin_cookie_secret
|
||||
|
||||
if [ ! -e /etc/yunohost/.ssowat_cookie_secret ]; then
|
||||
# NB: we need this to be exactly 32 char long, because it is later used as a key for AES256
|
||||
dd if=/dev/urandom bs=1 count=1000 2>/dev/null | tr --complement --delete 'A-Za-z0-9' | head -c 32 > /etc/yunohost/.ssowat_cookie_secret
|
||||
fi
|
||||
chown ynh-portal:root /etc/yunohost/.ssowat_cookie_secret
|
||||
chmod 400 /etc/yunohost/.ssowat_cookie_secret
|
||||
fi
|
||||
|
||||
##################
|
||||
# Domain folders #
|
||||
##################
|
||||
|
||||
mkdir -p /etc/yunohost/domains
|
||||
chown root /etc/yunohost/domains
|
||||
chmod 700 /etc/yunohost/domains
|
||||
|
||||
###############
|
||||
# App folders #
|
||||
###############
|
||||
|
||||
mkdir -p /etc/yunohost/apps
|
||||
chown root /etc/yunohost/apps
|
||||
chmod 700 /etc/yunohost/apps
|
||||
|
||||
#####################
|
||||
# Apps data folders #
|
||||
#####################
|
||||
|
||||
mkdir -p /home/yunohost.app
|
||||
chmod 755 /home/yunohost.app
|
||||
|
||||
################
|
||||
# Certs folder #
|
||||
################
|
||||
|
||||
mkdir -p /etc/yunohost/certs
|
||||
chown -R root:ssl-cert /etc/yunohost/certs
|
||||
chmod 750 /etc/yunohost/certs
|
||||
# We do this with find because there could be a lot of them...
|
||||
find /etc/yunohost/certs/ -type f -exec chmod 640 {} \;
|
||||
find /etc/yunohost/certs/ -type d -exec chmod 750 {} \;
|
||||
|
||||
##################
|
||||
# Backup folders #
|
||||
##################
|
||||
|
||||
mkdir -p /home/yunohost.backup/archives
|
||||
chmod 770 /home/yunohost.backup
|
||||
chmod 770 /home/yunohost.backup/archives
|
||||
|
||||
if test -e /etc/yunohost/installed
|
||||
then
|
||||
# The admins group only exist after the postinstall
|
||||
chown root:admins /home/yunohost.backup
|
||||
chown root:admins /home/yunohost.backup/archives
|
||||
else
|
||||
chown root:root /home/yunohost.backup
|
||||
chown root:root /home/yunohost.backup/archives
|
||||
fi
|
||||
|
||||
########
|
||||
# Misc #
|
||||
########
|
||||
|
||||
mkdir -p /etc/yunohost/hooks.d
|
||||
chown root /etc/yunohost/hooks.d
|
||||
chmod 700 /etc/yunohost/hooks.d
|
||||
|
||||
mkdir -p /var/cache/yunohost/repo
|
||||
chown root:root /var/cache/yunohost
|
||||
chmod 700 /var/cache/yunohost
|
||||
|
||||
[ ! -e /var/www/.well-known/ynh-diagnosis/ ] || chmod 775 /var/www/.well-known/ynh-diagnosis/
|
||||
|
||||
if test -e /etc/yunohost/installed
|
||||
then
|
||||
setfacl -m g:all_users:--- /var/www
|
||||
setfacl -m g:all_users:--- /var/log/nginx
|
||||
setfacl -m g:all_users:--- /etc/yunohost
|
||||
setfacl -m g:all_users:--- /etc/ssowat
|
||||
fi
|
||||
}
|
||||
|
||||
do_init_regen() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "You must be root to run this script" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd /usr/share/yunohost/conf/yunohost
|
||||
|
||||
base_folder_and_perm_init
|
||||
|
||||
# Empty ssowat json persistent conf
|
||||
echo "{}" >'/etc/ssowat/conf.json.persistent'
|
||||
chmod 644 /etc/ssowat/conf.json.persistent
|
||||
chown root:root /etc/ssowat/conf.json.persistent
|
||||
echo "{}" >'/etc/ssowat/conf.json'
|
||||
chmod 644 /etc/ssowat/conf.json
|
||||
chown root:root /etc/ssowat/conf.json
|
||||
|
||||
# Empty service conf
|
||||
touch /etc/yunohost/services.yml
|
||||
[[ -d /etc/yunohost ]] || mkdir -p /etc/yunohost
|
||||
|
||||
# set default current_host
|
||||
[[ -f /etc/yunohost/current_host ]] \
|
||||
|
@ -176,9 +24,39 @@ do_init_regen() {
|
|||
[[ -d /etc/skel/media ]] \
|
||||
|| (mkdir -p /media && ln -s /media /etc/skel/media)
|
||||
|
||||
# YunoHost services
|
||||
# Cert folders
|
||||
mkdir -p /etc/yunohost/certs
|
||||
chown -R root:ssl-cert /etc/yunohost/certs
|
||||
chmod 750 /etc/yunohost/certs
|
||||
|
||||
# App folders
|
||||
mkdir -p /etc/yunohost/apps
|
||||
chmod 700 /etc/yunohost/apps
|
||||
mkdir -p /home/yunohost.app
|
||||
chmod 755 /home/yunohost.app
|
||||
|
||||
# Domain settings
|
||||
mkdir -p /etc/yunohost/domains
|
||||
chmod 700 /etc/yunohost/domains
|
||||
|
||||
# Backup folders
|
||||
mkdir -p /home/yunohost.backup/archives
|
||||
chmod 750 /home/yunohost.backup/archives
|
||||
chown root:root /home/yunohost.backup/archives # This is later changed to root:admins once the admins group exists
|
||||
|
||||
# Empty ssowat json persistent conf
|
||||
echo "{}" > '/etc/ssowat/conf.json.persistent'
|
||||
chmod 644 /etc/ssowat/conf.json.persistent
|
||||
chown root:root /etc/ssowat/conf.json.persistent
|
||||
|
||||
# Empty service conf
|
||||
touch /etc/yunohost/services.yml
|
||||
|
||||
mkdir -p /var/cache/yunohost/repo
|
||||
chown root:root /var/cache/yunohost
|
||||
chmod 700 /var/cache/yunohost
|
||||
|
||||
cp yunohost-api.service /etc/systemd/system/yunohost-api.service
|
||||
cp yunohost-portal-api.service /etc/systemd/system/yunohost-portal-api.service
|
||||
cp yunohost-firewall.service /etc/systemd/system/yunohost-firewall.service
|
||||
cp yunoprompt.service /etc/systemd/system/yunoprompt.service
|
||||
|
||||
|
@ -187,9 +65,6 @@ do_init_regen() {
|
|||
systemctl enable yunohost-api.service --quiet
|
||||
systemctl start yunohost-api.service
|
||||
|
||||
systemctl enable yunohost-portal-api.service --quiet
|
||||
systemctl start yunohost-portal-api.service
|
||||
|
||||
# Enable yunoprompt (in particular for installs from ISO where we want this to show on first boot instead of asking for a login/password)
|
||||
systemctl enable yunoprompt --quiet
|
||||
|
||||
|
@ -199,8 +74,7 @@ do_init_regen() {
|
|||
|
||||
# Change dpkg vendor
|
||||
# see https://wiki.debian.org/Derivatives/Guidelines#Vendor
|
||||
if readlink -f /etc/dpkg/origins/default | grep -q debian;
|
||||
then
|
||||
if readlink -f /etc/dpkg/origins/default | grep -q debian; then
|
||||
rm -f /etc/dpkg/origins/default
|
||||
ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default
|
||||
fi
|
||||
|
@ -254,8 +128,7 @@ EOF
|
|||
fi
|
||||
|
||||
# Skip ntp if inside a container (inspired from the conf of systemd-timesyncd)
|
||||
if systemctl | grep -q 'ntp.service'
|
||||
then
|
||||
if systemctl | grep -q 'ntp.service'; then
|
||||
mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/
|
||||
cat > ${pending_dir}/etc/systemd/system/ntp.service.d/ynh-override.conf << EOF
|
||||
[Unit]
|
||||
|
@ -284,7 +157,6 @@ HandleLidSwitchExternalPower=ignore
|
|||
EOF
|
||||
|
||||
cp yunohost-api.service ${pending_dir}/etc/systemd/system/yunohost-api.service
|
||||
cp yunohost-portal-api.service ${pending_dir}/etc/systemd/system/yunohost-portal-api.service
|
||||
cp yunohost-firewall.service ${pending_dir}/etc/systemd/system/yunohost-firewall.service
|
||||
cp yunoprompt.service ${pending_dir}/etc/systemd/system/yunoprompt.service
|
||||
cp proc-hidepid.service ${pending_dir}/etc/systemd/system/proc-hidepid.service
|
||||
|
@ -299,59 +171,73 @@ EOF
|
|||
do_post_regen() {
|
||||
regen_conf_files=$1
|
||||
|
||||
# Re-mkdir / apply permission to all basic folders etc
|
||||
base_folder_and_perm_init
|
||||
######################
|
||||
# Enfore permissions #
|
||||
######################
|
||||
|
||||
# Legacy log tree structure
|
||||
if [ ! -e /var/log/yunohost/operations ]
|
||||
then
|
||||
mkdir -p /var/log/yunohost/operations
|
||||
fi
|
||||
if [ -d /var/log/yunohost/categories/operation ] && [ ! -L /var/log/yunohost/categories/operation ]
|
||||
then
|
||||
# (we use find -type f instead of mv /folder/* to make sure to also move hidden files which are not included in globs by default)
|
||||
find /var/log/yunohost/categories/operation/ -type f -print0 | xargs -0 -I {} mv {} /var/log/yunohost/operations/
|
||||
# Attempt to delete the old dir (because we want it to be a symlink) or just rename it if it can't be removed (not empty) for some reason
|
||||
rmdir /var/log/yunohost/categories/operation || mv /var/log/yunohost/categories/operation /var/log/yunohost/categories/operation.old
|
||||
ln -s /var/log/yunohost/operations /var/log/yunohost/categories/operation
|
||||
fi
|
||||
chmod 770 /home/yunohost.backup
|
||||
chmod 770 /home/yunohost.backup/archives
|
||||
chmod 700 /var/cache/yunohost
|
||||
chown root:admins /home/yunohost.backup
|
||||
chown root:admins /home/yunohost.backup/archives
|
||||
chown root:root /var/cache/yunohost
|
||||
|
||||
[ ! -e /var/www/.well-known/ynh-diagnosis/ ] || chmod 775 /var/www/.well-known/ynh-diagnosis/
|
||||
|
||||
# NB: x permission for 'others' is important for ssl-cert (and maybe mdns), otherwise slapd will fail to start because can't access the certs
|
||||
chmod 755 /etc/yunohost
|
||||
|
||||
# Make sure conf files why may be created by apps are owned and writable only by root
|
||||
find /etc/systemd/system/*.service -type f | xargs -r chown root:root
|
||||
find /etc/systemd/system/*.service -type f | xargs -r chmod 0644
|
||||
|
||||
if ls -l /etc/php/*/fpm/pool.d/*.conf 2>/dev/null
|
||||
then
|
||||
if ls -l /etc/php/*/fpm/pool.d/*.conf; then
|
||||
chown root:root /etc/php/*/fpm/pool.d/*.conf
|
||||
chmod 644 /etc/php/*/fpm/pool.d/*.conf
|
||||
fi
|
||||
|
||||
# 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 {} \;
|
||||
|
||||
find /etc/cron.*/yunohost-* -type f -exec chmod 755 {} \;
|
||||
find /etc/cron.d/yunohost-* -type f -exec chmod 644 {} \;
|
||||
find /etc/cron.*/yunohost-* -type f -exec chown root:root {} \;
|
||||
|
||||
setfacl -m g:all_users:--- /var/www
|
||||
setfacl -m g:all_users:--- /var/log/nginx
|
||||
setfacl -m g:all_users:--- /etc/yunohost
|
||||
setfacl -m g:all_users:--- /etc/ssowat
|
||||
|
||||
for USER in $(yunohost user list --quiet --output-as json | jq -r '.users | .[] | .username'); do
|
||||
[ ! -e "/home/$USER" ] || setfacl -m g:all_users:--- /home/$USER
|
||||
done
|
||||
|
||||
# Domain settings
|
||||
mkdir -p /etc/yunohost/domains
|
||||
|
||||
# Misc configuration / state files
|
||||
chown root:root $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2> /dev/null | grep -vw mdns.yml)
|
||||
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)
|
||||
[[ ! -e /etc/yunohost/domains ]] || (chown root /etc/yunohost/domains && chmod 700 /etc/yunohost/domains)
|
||||
|
||||
# Create ssh.app and sftp.app groups if they don't exist yet
|
||||
grep -q '^ssh.app:' /etc/group || groupadd ssh.app
|
||||
grep -q '^sftp.app:' /etc/group || groupadd sftp.app
|
||||
|
||||
# Propagates changes in systemd service config overrides
|
||||
if systemctl | grep -q 'ntp.service'
|
||||
then
|
||||
if systemctl | grep -q 'ntp.service'; then
|
||||
[[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || {
|
||||
systemctl daemon-reload
|
||||
systemctl restart ntp
|
||||
}
|
||||
fi
|
||||
|
||||
[[ ! "$regen_conf_files" =~ "nftables.service.d/ynh-override.conf" ]] || systemctl daemon-reload
|
||||
[[ ! "$regen_conf_files" =~ "login.conf.d/ynh-override.conf" ]] || {
|
||||
systemctl daemon-reload
|
||||
|
@ -359,7 +245,6 @@ do_post_regen() {
|
|||
}
|
||||
[[ ! "$regen_conf_files" =~ "yunohost-firewall.service" ]] || systemctl daemon-reload
|
||||
[[ ! "$regen_conf_files" =~ "yunohost-api.service" ]] || systemctl daemon-reload
|
||||
[[ ! "$regen_conf_files" =~ "yunohost-portal-api.service" ]] || systemctl daemon-reload
|
||||
|
||||
if [[ "$regen_conf_files" =~ "yunoprompt.service" ]]; then
|
||||
systemctl daemon-reload
|
||||
|
@ -372,19 +257,14 @@ do_post_regen() {
|
|||
systemctl $action proc-hidepid --quiet --now
|
||||
fi
|
||||
|
||||
systemctl enable yunohost-portal-api.service --quiet
|
||||
systemctl is-active yunohost-portal-api --quiet || systemctl start yunohost-portal-api.service
|
||||
|
||||
# Change dpkg vendor
|
||||
# see https://wiki.debian.org/Derivatives/Guidelines#Vendor
|
||||
if readlink -f /etc/dpkg/origins/default | grep -q debian;
|
||||
then
|
||||
if readlink -f /etc/dpkg/origins/default | grep -q debian; then
|
||||
rm -f /etc/dpkg/origins/default
|
||||
ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default
|
||||
fi
|
||||
|
||||
if test -e /etc/yunohost/installed && test -e /etc/profile.d/check_yunohost_is_installed.sh
|
||||
then
|
||||
if test -e /etc/yunohost/installed && test -e /etc/profile.d/check_yunohost_is_installed.sh; then
|
||||
rm /etc/profile.d/check_yunohost_is_installed.sh
|
||||
fi
|
||||
}
|
||||
|
|
|
@ -106,8 +106,7 @@ do_post_regen() {
|
|||
main_domain=$(cat /etc/yunohost/current_host)
|
||||
|
||||
# Automigrate legacy folder
|
||||
if [ -e /usr/share/yunohost/yunohost-config/ssl/yunoCA ]
|
||||
then
|
||||
if [ -e /usr/share/yunohost/yunohost-config/ssl/yunoCA ]; then
|
||||
mv /usr/share/yunohost/yunohost-config/ssl/yunoCA/* ${ssl_dir}
|
||||
rm -rf /usr/share/yunohost/yunohost-config
|
||||
# Overwrite openssl.cnf because it may still contain references to the old yunoCA dir
|
||||
|
|
|
@ -9,16 +9,17 @@ do_pre_regen() {
|
|||
|
||||
cd /usr/share/yunohost/conf/ssh
|
||||
|
||||
# Support different strategy for security configurations
|
||||
export compatibility="$(jq -r '.ssh_compatibility' <<< "$YNH_SETTINGS")"
|
||||
export port="$(jq -r '.ssh_port' <<< "$YNH_SETTINGS")"
|
||||
export password_authentication="$(jq -r '.ssh_password_authentication' <<< "$YNH_SETTINGS" | int_to_bool)"
|
||||
export ssh_keys=$(ls /etc/ssh/ssh_host_{ed25519,rsa,ecdsa}_key 2>/dev/null || true)
|
||||
|
||||
# do not listen to IPv6 if unavailable
|
||||
[[ -f /proc/net/if_inet6 ]] && ipv6_enabled=true || ipv6_enabled=false
|
||||
export ipv6_enabled
|
||||
|
||||
ssh_keys=$(ls /etc/ssh/ssh_host_{ed25519,rsa,ecdsa}_key 2> /dev/null || true)
|
||||
|
||||
# Support different strategy for security configurations
|
||||
export compatibility="$(yunohost settings get 'security.ssh.ssh_compatibility')"
|
||||
export port="$(yunohost settings get 'security.ssh.ssh_port')"
|
||||
export password_authentication="$(yunohost settings get 'security.ssh.ssh_password_authentication' | int_to_bool)"
|
||||
export ssh_keys
|
||||
export ipv6_enabled
|
||||
ynh_render_template "sshd_config" "${pending_dir}/etc/ssh/sshd_config"
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,10 @@ config="/usr/share/yunohost/conf/slapd/config.ldif"
|
|||
db_init="/usr/share/yunohost/conf/slapd/db_init.ldif"
|
||||
|
||||
do_init_regen() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "You must be root to run this script" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
do_pre_regen ""
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ do_pre_regen() {
|
|||
|
||||
# Add sury
|
||||
mkdir -p ${pending_dir}/etc/apt/sources.list.d/
|
||||
echo "deb [signed-by=/etc/apt/trusted.gpg.d/extra_php_version.gpg] https://packages.sury.org/php/ $(lsb_release --codename --short) main" > "${pending_dir}/etc/apt/sources.list.d/extra_php_version.list"
|
||||
echo "deb https://packages.sury.org/php/ $(lsb_release --codename --short) main" > "${pending_dir}/etc/apt/sources.list.d/extra_php_version.list"
|
||||
|
||||
# Ban some packages from sury
|
||||
echo "
|
||||
|
@ -27,20 +27,6 @@ Pin: origin \"packages.sury.org\"
|
|||
Pin-Priority: -1" >> "${pending_dir}/etc/apt/preferences.d/extra_php_version"
|
||||
done
|
||||
|
||||
# Add yarn
|
||||
echo "deb [signed-by=/etc/apt/trusted.gpg.d/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > "${pending_dir}/etc/apt/sources.list.d/yarn.list"
|
||||
|
||||
# Ban everything from Yarn except Yarn
|
||||
echo "
|
||||
Package: *
|
||||
Pin: origin \"dl.yarnpkg.com\"
|
||||
Pin-Priority: -1
|
||||
|
||||
Package: yarn
|
||||
Pin: origin \"dl.yarnpkg.com\"
|
||||
Pin-Priority: 500" >>"${pending_dir}/etc/apt/preferences.d/yarn"
|
||||
|
||||
# Ban apache2, bind9
|
||||
echo "
|
||||
|
||||
# PLEASE READ THIS WARNING AND DON'T EDIT THIS FILE
|
||||
|
@ -70,7 +56,6 @@ Pin: release *
|
|||
Pin-Priority: -1
|
||||
" >> "${pending_dir}/etc/apt/preferences.d/ban_packages"
|
||||
|
||||
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
|
@ -82,20 +67,12 @@ do_post_regen() {
|
|||
|
||||
# Add sury key
|
||||
# We do this only at the post regen and if the key doesn't already exists, because we don't want the regenconf to fuck everything up if the regenconf runs while the network is down
|
||||
if [[ ! -s /etc/apt/trusted.gpg.d/extra_php_version.gpg ]]
|
||||
then
|
||||
if [[ ! -s /etc/apt/trusted.gpg.d/extra_php_version.gpg ]]; then
|
||||
wget --timeout 900 --quiet "https://packages.sury.org/php/apt.gpg" --output-document=- | gpg --dearmor > "/etc/apt/trusted.gpg.d/extra_php_version.gpg"
|
||||
fi
|
||||
|
||||
# Similar to Sury
|
||||
if [[ ! -s /etc/apt/trusted.gpg.d/yarn.gpg ]]
|
||||
then
|
||||
wget --timeout 900 --quiet "https://dl.yarnpkg.com/debian/pubkey.gpg" --output-document=- | gpg --dearmor >"/etc/apt/trusted.gpg.d/yarn.gpg"
|
||||
fi
|
||||
|
||||
# Make sure php7.4 is the default version when using php in cli
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
then
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
|
||||
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
fi
|
||||
}
|
||||
|
|
91
hooks/conf_regen/12-metronome
Executable file
91
hooks/conf_regen/12-metronome
Executable file
|
@ -0,0 +1,91 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if ! dpkg --list | grep -q 'ii *metronome '; then
|
||||
echo 'metronome is not installed, skipping'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
do_pre_regen() {
|
||||
pending_dir=$1
|
||||
|
||||
cd /usr/share/yunohost/conf/metronome
|
||||
|
||||
# create directories for pending conf
|
||||
metronome_dir="${pending_dir}/etc/metronome"
|
||||
metronome_conf_dir="${metronome_dir}/conf.d"
|
||||
mkdir -p "$metronome_conf_dir"
|
||||
|
||||
# retrieve variables
|
||||
main_domain=$(cat /etc/yunohost/current_host)
|
||||
|
||||
# install main conf file
|
||||
cat metronome.cfg.lua \
|
||||
| sed "s/{{ main_domain }}/${main_domain}/g" \
|
||||
> "${metronome_dir}/metronome.cfg.lua"
|
||||
|
||||
# Trick such that old conf files are flagged as to remove
|
||||
for domain in $YNH_DOMAINS; do
|
||||
touch "${metronome_conf_dir}/${domain}.cfg.lua"
|
||||
done
|
||||
|
||||
# add domain conf files
|
||||
domain_list="$(yunohost domain list --features xmpp --output-as json | jq -r ".domains[]")"
|
||||
for domain in $domain_list; do
|
||||
cat domain.tpl.cfg.lua \
|
||||
| sed "s/{{ domain }}/${domain}/g" \
|
||||
> "${metronome_conf_dir}/${domain}.cfg.lua"
|
||||
done
|
||||
|
||||
# remove old domain conf files
|
||||
conf_files=$(ls -1 /etc/metronome/conf.d \
|
||||
| awk '/^[^\.]+\.[^\.]+.*\.cfg\.lua$/ { print $1 }')
|
||||
for file in $conf_files; do
|
||||
domain=${file%.cfg.lua}
|
||||
[[ $YNH_DOMAINS =~ $domain ]] \
|
||||
|| touch "${metronome_conf_dir}/${file}"
|
||||
done
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
regen_conf_files=$1
|
||||
|
||||
# retrieve variables
|
||||
main_domain=$(cat /etc/yunohost/current_host)
|
||||
|
||||
# create metronome directories for domains
|
||||
for domain in $YNH_MAIN_DOMAINS; do
|
||||
mkdir -p "/var/lib/metronome/${domain//./%2e}/pep"
|
||||
# http_upload directory must be writable by metronome and readable by nginx
|
||||
mkdir -p "/var/xmpp-upload/${domain}/upload"
|
||||
# sgid bit allows that file created in that dir will be owned by www-data
|
||||
# despite the fact that metronome ain't in the www-data group
|
||||
chmod g+s "/var/xmpp-upload/${domain}/upload"
|
||||
done
|
||||
|
||||
# fix some permissions
|
||||
[ ! -e '/var/xmpp-upload' ] || chown -R metronome:www-data "/var/xmpp-upload/"
|
||||
[ ! -e '/var/xmpp-upload' ] || chmod 750 "/var/xmpp-upload/"
|
||||
|
||||
# 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/
|
||||
|
||||
if [[ -z "$(ls /etc/metronome/conf.d/*.cfg.lua 2> /dev/null)" ]]; then
|
||||
if systemctl is-enabled metronome &> /dev/null; then
|
||||
systemctl disable metronome --now 2> /dev/null
|
||||
fi
|
||||
else
|
||||
if ! systemctl is-enabled metronome &> /dev/null; then
|
||||
systemctl enable metronome --now 2> /dev/null
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
[[ -z "$regen_conf_files" ]] \
|
||||
|| systemctl restart metronome
|
||||
fi
|
||||
}
|
||||
|
||||
do_$1_regen ${@:2}
|
|
@ -4,20 +4,25 @@ set -e
|
|||
|
||||
. /usr/share/yunohost/helpers
|
||||
|
||||
do_base_regen() {
|
||||
do_init_regen() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "You must be root to run this script" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pending_dir=$1
|
||||
nginx_dir="${pending_dir}/etc/nginx"
|
||||
cd /usr/share/yunohost/conf/nginx
|
||||
|
||||
nginx_dir="/etc/nginx"
|
||||
nginx_conf_dir="${nginx_dir}/conf.d"
|
||||
mkdir -p "$nginx_conf_dir"
|
||||
|
||||
# install plain conf files
|
||||
cp acme-challenge.conf.inc "$nginx_conf_dir"
|
||||
cp global.conf "$nginx_conf_dir"
|
||||
cp ssowat.conf "$nginx_conf_dir"
|
||||
cp yunohost_http_errors.conf.inc "$nginx_conf_dir"
|
||||
cp yunohost_sso.conf.inc "$nginx_conf_dir"
|
||||
cp plain/* "$nginx_conf_dir"
|
||||
|
||||
# probably run with init: just disable default site, restart NGINX and exit
|
||||
rm -f "${nginx_dir}/sites-enabled/default"
|
||||
|
||||
export compatibility="intermediate"
|
||||
ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc"
|
||||
ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf"
|
||||
ynh_render_template "yunohost_admin.conf.inc" "${nginx_conf_dir}/yunohost_admin.conf.inc"
|
||||
|
@ -25,17 +30,6 @@ do_base_regen() {
|
|||
|
||||
mkdir -p $nginx_conf_dir/default.d/
|
||||
cp "redirect_to_admin.conf" $nginx_conf_dir/default.d/
|
||||
}
|
||||
|
||||
do_init_regen() {
|
||||
|
||||
cd /usr/share/yunohost/conf/nginx
|
||||
|
||||
export compatibility="intermediate"
|
||||
do_base_regen ""
|
||||
|
||||
# probably run with init: just disable default site, restart NGINX and exit
|
||||
rm -f "${nginx_dir}/sites-enabled/default"
|
||||
|
||||
# Restart nginx if conf looks good, otherwise display error and exit unhappy
|
||||
nginx -t 2> /dev/null || {
|
||||
|
@ -59,21 +53,27 @@ do_pre_regen() {
|
|||
nginx_conf_dir="${nginx_dir}/conf.d"
|
||||
mkdir -p "$nginx_conf_dir"
|
||||
|
||||
export webadmin_allowlist_enabled="$(jq -r '.webadmin_allowlist_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
|
||||
if [ "$webadmin_allowlist_enabled" == "True" ]; then
|
||||
export webadmin_allowlist="$(jq -r '.webadmin_allowlist' <<< "$YNH_SETTINGS" | sed 's/^null$//g')"
|
||||
# install / update plain conf files
|
||||
cp plain/* "$nginx_conf_dir"
|
||||
# remove the panel overlay if this is specified in settings
|
||||
panel_overlay=$(yunohost settings get 'misc.portal.ssowat_panel_overlay_enabled' | int_to_bool)
|
||||
if [ "$panel_overlay" == "False" ]; then
|
||||
echo "#" > "${nginx_conf_dir}/yunohost_panel.conf.inc"
|
||||
fi
|
||||
|
||||
# Support different strategy for security configurations
|
||||
export redirect_to_https="$(jq -r '.nginx_redirect_to_https' <<< "$YNH_SETTINGS" | int_to_bool)"
|
||||
export compatibility="$(jq -r '.nginx_compatibility' <<< "$YNH_SETTINGS" | int_to_bool)"
|
||||
export experimental="$(jq -r '.security_experimental_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
|
||||
# retrieve variables
|
||||
main_domain=$(cat /etc/yunohost/current_host)
|
||||
|
||||
do_base_regen "${pending_dir}"
|
||||
# Support different strategy for security configurations
|
||||
export redirect_to_https="$(yunohost settings get 'security.nginx.nginx_redirect_to_https' | int_to_bool)"
|
||||
export compatibility="$(yunohost settings get 'security.nginx.nginx_compatibility')"
|
||||
export experimental="$(yunohost settings get 'security.experimental.security_experimental_enabled' | int_to_bool)"
|
||||
ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc"
|
||||
|
||||
cert_status=$(yunohost domain cert status --json)
|
||||
|
||||
# add domain conf files
|
||||
xmpp_domain_list="$(yunohost domain list --features xmpp --output-as json | jq -r ".domains[]")"
|
||||
mail_domain_list="$(yunohost domain list --features mail_in mail_out --output-as json | jq -r ".domains[]")"
|
||||
for domain in $YNH_DOMAINS; do
|
||||
domain_conf_dir="${nginx_conf_dir}/${domain}.d"
|
||||
|
@ -86,16 +86,19 @@ do_pre_regen() {
|
|||
export domain_cert_ca=$(echo $cert_status \
|
||||
| jq ".certificates.\"$domain\".CA_type" \
|
||||
| tr -d '"')
|
||||
if echo "$mail_domain_list" | grep -q "^$domain$"
|
||||
then
|
||||
if echo "$xmpp_domain_list" | grep -q "^$domain$"; then
|
||||
export xmpp_enabled="True"
|
||||
else
|
||||
export xmpp_enabled="False"
|
||||
fi
|
||||
if echo "$mail_domain_list" | grep -q "^$domain$"; then
|
||||
export mail_enabled="True"
|
||||
else
|
||||
export mail_enabled="False"
|
||||
fi
|
||||
|
||||
ynh_render_template "server.tpl.conf" "${nginx_conf_dir}/${domain}.conf"
|
||||
if [ $mail_enabled == "True" ]
|
||||
then
|
||||
if [ $mail_enabled == "True" ]; then
|
||||
ynh_render_template "autoconfig.tpl.xml" "${mail_autoconfig_dir}/config-v1.1.xml"
|
||||
fi
|
||||
|
||||
|
@ -103,8 +106,15 @@ do_pre_regen() {
|
|||
|
||||
done
|
||||
|
||||
# Legacy file to remove, but we can't really remove it because it may be included by app confs...
|
||||
echo "# The old yunohost panel/tile/button doesn't exists anymore" > "$nginx_conf_dir"/yunohost_panel.conf.inc
|
||||
export webadmin_allowlist_enabled=$(yunohost settings get security.webadmin.webadmin_allowlist_enabled | int_to_bool)
|
||||
if [ "$webadmin_allowlist_enabled" == "True" ]; then
|
||||
export webadmin_allowlist=$(yunohost settings get security.webadmin.webadmin_allowlist)
|
||||
fi
|
||||
ynh_render_template "yunohost_admin.conf.inc" "${nginx_conf_dir}/yunohost_admin.conf.inc"
|
||||
ynh_render_template "yunohost_api.conf.inc" "${nginx_conf_dir}/yunohost_api.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/
|
||||
|
||||
# remove old domain conf files
|
||||
conf_files=$(ls -1 /etc/nginx/conf.d \
|
||||
|
@ -131,8 +141,7 @@ do_pre_regen() {
|
|||
do_post_regen() {
|
||||
regen_conf_files=$1
|
||||
|
||||
if ls -l /etc/nginx/conf.d/*.d/*.conf
|
||||
then
|
||||
if ls -l /etc/nginx/conf.d/*.d/*.conf; then
|
||||
chown root:root /etc/nginx/conf.d/*.d/*.conf
|
||||
chmod 644 /etc/nginx/conf.d/*.d/*.conf
|
||||
fi
|
||||
|
|
|
@ -22,19 +22,19 @@ do_pre_regen() {
|
|||
main_domain=$(cat /etc/yunohost/current_host)
|
||||
|
||||
# Support different strategy for security configurations
|
||||
export compatibility="$(jq -r '.postfix_compatibility' <<< "$YNH_SETTINGS")"
|
||||
export compatibility="$(yunohost settings get 'security.postfix.postfix_compatibility')"
|
||||
|
||||
# Add possibility to specify a relay
|
||||
# Could be useful with some isp with no 25 port open or more complex setup
|
||||
export relay_port=""
|
||||
export relay_user=""
|
||||
export relay_host=""
|
||||
export relay_enabled="$(jq -r '.smtp_relay_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
|
||||
export relay_enabled="$(yunohost settings get 'email.smtp.smtp_relay_enabled' | int_to_bool)"
|
||||
if [ "${relay_enabled}" == "True" ]; then
|
||||
relay_host="$(jq -r '.smtp_relay_host' <<< "$YNH_SETTINGS")"
|
||||
relay_port="$(jq -r '.smtp_relay_port' <<< "$YNH_SETTINGS")"
|
||||
relay_user="$(jq -r '.smtp_relay_user' <<< "$YNH_SETTINGS")"
|
||||
relay_password="$(jq -r '.smtp_relay_password' <<< "$YNH_SETTINGS")"
|
||||
relay_host="$(yunohost settings get 'email.smtp.smtp_relay_host')"
|
||||
relay_port="$(yunohost settings get 'email.smtp.smtp_relay_port')"
|
||||
relay_user="$(yunohost settings get 'email.smtp.smtp_relay_user')"
|
||||
relay_password="$(yunohost settings get 'email.smtp.smtp_relay_password')"
|
||||
|
||||
# Avoid to display "Relay account paswword" to other users
|
||||
touch ${postfix_dir}/sasl_passwd
|
||||
|
@ -45,6 +45,19 @@ do_pre_regen() {
|
|||
|
||||
cat <<< "[${relay_host}]:${relay_port} ${relay_user}:${relay_password}" > ${postfix_dir}/sasl_passwd
|
||||
fi
|
||||
|
||||
# Use this postfix server as a backup MX
|
||||
export backup_mx_domains="$(yunohost settings get 'email.smtp.smtp_backup_mx_domains' | sed "s/,/ /g")"
|
||||
export backup_mx_emails="$(yunohost settings get 'email.smtp.smtp_backup_mx_emails_whitelisted' | sed "s/,/ /g")"
|
||||
rm -f ${postfix_dir}/relay_recipients
|
||||
touch ${postfix_dir}/relay_recipients
|
||||
if [ -n "${backup_mx_domains}" ] && [ -n "${backup_mx_emails}" ]; then
|
||||
for mail in ${backup_mx_emails}; do
|
||||
echo "$mail OK" >> ${postfix_dir}/relay_recipients
|
||||
done
|
||||
postmap ${postfix_dir}/relay_recipients
|
||||
fi
|
||||
|
||||
export main_domain
|
||||
export domain_list="$(yunohost domain list --features mail_in mail_out --output-as json | jq -r ".domains[]" | tr '\n' ' ')"
|
||||
ynh_render_template "main.cf" "${postfix_dir}/main.cf"
|
||||
|
@ -56,7 +69,7 @@ do_pre_regen() {
|
|||
> "${default_dir}/postsrsd"
|
||||
|
||||
# adapt it for IPv4-only hosts
|
||||
ipv6="$(jq -r '.smtp_allow_ipv6' <<< "$YNH_SETTINGS" | int_to_bool)"
|
||||
ipv6="$(yunohost settings get 'email.smtp.smtp_allow_ipv6' | int_to_bool)"
|
||||
if [ "$ipv6" == "False" ] || [ ! -f /proc/net/if_inet6 ]; then
|
||||
sed -i \
|
||||
's/ \[::ffff:127.0.0.0\]\/104 \[::1\]\/128//g' \
|
||||
|
@ -78,6 +91,11 @@ do_post_regen() {
|
|||
postmap /etc/postfix/sasl_passwd
|
||||
fi
|
||||
|
||||
if [ -e /etc/postfix/relay_recipients ]; then
|
||||
chmod 750 /etc/postfix/relay_recipients*
|
||||
chown postfix:root /etc/postfix/relay_recipients*
|
||||
fi
|
||||
|
||||
postmap -F hash:/etc/postfix/sni
|
||||
|
||||
python3 -c 'from yunohost.app import regen_mail_app_user_config_for_dovecot_and_postfix as r; r(only="postfix")'
|
||||
|
|
|
@ -16,7 +16,7 @@ do_pre_regen() {
|
|||
cp dovecot-ldap.conf "${dovecot_dir}/dovecot-ldap.conf"
|
||||
cp dovecot.sieve "${dovecot_dir}/global_script/dovecot.sieve"
|
||||
|
||||
export pop3_enabled="$(jq -r '.pop3_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
|
||||
export pop3_enabled="$(yunohost settings get 'email.pop3.pop3_enabled' | int_to_bool)"
|
||||
export main_domain=$(cat /etc/yunohost/current_host)
|
||||
export domain_list="$(yunohost domain list --features mail_in mail_out --output-as json | jq -r ".domains[]" | tr '\n' ' ')"
|
||||
|
||||
|
@ -42,7 +42,7 @@ do_post_regen() {
|
|||
|
||||
# create vmail user
|
||||
id vmail > /dev/null 2>&1 \
|
||||
|| { mkdir -p /var/vmail; adduser --system --ingroup mail --uid 500 vmail --home /var/vmail --no-create-home; }
|
||||
|| adduser --system --ingroup mail --uid 500 vmail --home /var/vmail --no-create-home
|
||||
|
||||
# Delete legacy home for vmail that existed in the past but was empty, poluting /home/
|
||||
[ ! -e /home/vmail ] || rmdir --ignore-fail-on-non-empty /home/vmail
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
do_pre_regen() {
|
||||
pending_dir=$1
|
||||
|
||||
cd /usr/share/yunohost/conf/opendkim
|
||||
|
||||
install -D -m 644 opendkim.conf "${pending_dir}/etc/opendkim.conf"
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
mkdir -p /etc/dkim
|
||||
|
||||
# Create / empty those files because we're force-regenerating them
|
||||
echo "" > /etc/dkim/keytable
|
||||
echo "" > /etc/dkim/signingtable
|
||||
|
||||
# create DKIM key for domains
|
||||
domain_list="$(yunohost domain list --features mail_in mail_out --output-as json | jq -r ".domains[]" | tr '\n' ' ')"
|
||||
for domain in $domain_list; do
|
||||
domain_key="/etc/dkim/${domain}.mail.key"
|
||||
[ ! -f "$domain_key" ] && {
|
||||
# We use a 1024 bit size because nsupdate doesn't seem to be able to
|
||||
# handle 2048...
|
||||
opendkim-genkey --domain="$domain" \
|
||||
--selector=mail --directory=/etc/dkim -b 1024
|
||||
mv /etc/dkim/mail.private "$domain_key"
|
||||
mv /etc/dkim/mail.txt "/etc/dkim/${domain}.mail.txt"
|
||||
}
|
||||
|
||||
echo "mail._domainkey.${domain} ${domain}:mail:${domain_key}" >> /etc/dkim/keytable
|
||||
echo "*@$domain mail._domainkey.${domain}" >> /etc/dkim/signingtable
|
||||
done
|
||||
|
||||
chown -R opendkim /etc/dkim/
|
||||
chmod 700 /etc/dkim/
|
||||
|
||||
systemctl restart opendkim
|
||||
}
|
||||
|
||||
do_$1_regen ${@:2}
|
65
hooks/conf_regen/31-rspamd
Executable file
65
hooks/conf_regen/31-rspamd
Executable file
|
@ -0,0 +1,65 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
do_pre_regen() {
|
||||
pending_dir=$1
|
||||
|
||||
cd /usr/share/yunohost/conf/rspamd
|
||||
|
||||
install -D -m 644 metrics.local.conf \
|
||||
"${pending_dir}/etc/rspamd/local.d/metrics.conf"
|
||||
install -D -m 644 dkim_signing.conf \
|
||||
"${pending_dir}/etc/rspamd/local.d/dkim_signing.conf"
|
||||
install -D -m 644 rspamd.sieve \
|
||||
"${pending_dir}/etc/dovecot/global_script/rspamd.sieve"
|
||||
install -D -m 644 redis.conf \
|
||||
"${pending_dir}/etc/rspamd/local.d/redis.conf"
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
|
||||
##
|
||||
## DKIM key generation
|
||||
##
|
||||
|
||||
# create DKIM directory with proper permission
|
||||
mkdir -p /etc/dkim
|
||||
chown _rspamd /etc/dkim
|
||||
|
||||
# create DKIM key for domains
|
||||
domain_list="$(yunohost domain list --features mail_in mail_out --output-as json | jq -r ".domains[]" | tr '\n' ' ')"
|
||||
for domain in $domain_list; do
|
||||
domain_key="/etc/dkim/${domain}.mail.key"
|
||||
[ ! -f "$domain_key" ] && {
|
||||
# We use a 1024 bit size because nsupdate doesn't seem to be able to
|
||||
# handle 2048...
|
||||
opendkim-genkey --domain="$domain" \
|
||||
--selector=mail --directory=/etc/dkim -b 1024
|
||||
mv /etc/dkim/mail.private "$domain_key"
|
||||
mv /etc/dkim/mail.txt "/etc/dkim/${domain}.mail.txt"
|
||||
}
|
||||
done
|
||||
|
||||
# fix DKIM keys permissions
|
||||
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
|
||||
|
||||
# compile sieve script
|
||||
[[ "$regen_conf_files" =~ rspamd\.sieve ]] && {
|
||||
sievec /etc/dovecot/global_script/rspamd.sieve
|
||||
chown -R vmail:mail /etc/dovecot/global_script
|
||||
systemctl restart dovecot
|
||||
}
|
||||
|
||||
# Restart rspamd due to the upgrade
|
||||
# https://rspamd.com/announce/2016/08/01/rspamd-1.3.1.html
|
||||
systemctl -q restart rspamd.service
|
||||
}
|
||||
|
||||
do_$1_regen ${@:2}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue