Compare commits

..

85 commits

Author SHA1 Message Date
Alexandre Aubin
a5049a8a13 Update changelog for 11.2.30 2024-08-31 19:30:00 +02:00
Alexandre Aubin
6e84e3532a
Merge pull request #1943 from YunoHost/fix_ynh_restore_everything
Fix ynh_restore_everything
2024-08-31 18:59:47 +02:00
Josué Tille
917cf251fb
Fix ynh_restore_everything 2024-08-31 18:51:16 +02:00
selfhoster1312
8a5f2808a1 Apply shfmt everywhere 2024-08-31 12:22:40 +02:00
68f35831e7 Add maintenante/shfmt.sh for shell script formatting
Thanks @selfhoster1312 <3
2024-08-31 12:22:40 +02:00
b91e9dd8f4 helpersv2.1: Tabs to spaces 2024-08-31 11:01:20 +02:00
38b39ebaea helpersv1: Tabs to spaces 2024-08-31 11:01:20 +02:00
ef17082768 Fix tabs in hooks script 2024-08-31 11:01:20 +02:00
e3ddb1dc4d Fix tabs and indentations in metronome 2024-08-31 11:01:20 +02:00
Alexandre Aubin
5b37936d11
Merge pull request #1940 from selfhoster1312/fix-syntax
Disambiguate subshell (it's not arithmetics!)
2024-08-30 19:10:58 +02:00
selfhoster1312
e82d20aa7b Disambiguate subshell (it's not arithmetics!) 2024-08-30 19:10:35 +02:00
selfhoster1312
aff885e6b7 helpers v2.1: ynh_add_swap and ynh_smart_mktemp 2024-08-30 15:43:50 +02:00
Alexandre Aubin
7a04462ccd
Merge pull request #1939 from selfhoster1312/rename-helper
docs: ynh_install_app_dependencies -> ynh_apt_install_dependencies
2024-08-29 17:47:29 +02:00
selfhoster1312
606e246ec4 docs: ynh_install_app_dependencies -> ynh_apt_install_dependencies 2024-08-29 17:41:41 +02:00
Alexandre Aubin
e3e8b903c7
Merge pull request #1938 from YunoHost/check-patches-dir
2.1 helpers: check if patches dir exists before getting realpath
2024-08-29 00:27:13 +02:00
OniriCorpe
488f563b45 2.1 helpers: check if the patches directory exists before trying to get its realpath 2024-08-28 23:03:57 +02:00
Alexandre Aubin
3d4804be68 Update changelog for 11.2.29 2024-08-27 14:48:10 +02:00
Alexandre Aubin
d4f774ad72 quality: fix typing issue 2024-08-27 14:45:37 +02:00
Alexandre Aubin
d8ab3e68a9
Merge pull request #1933 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-08-27 14:45:28 +02:00
xabirequejo
71b50549f5 Translated using Weblate (Basque)
Currently translated at 100.0% (811 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-08-27 13:12:44 +02:00
craftrac
a40874c305 Translated using Weblate (Greek)
Currently translated at 1.1% (9 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/el/
2024-08-27 13:12:44 +02:00
cjdw
9223d30a83 Translated using Weblate (Indonesian)
Currently translated at 100.0% (811 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-08-27 13:12:44 +02:00
José M
5ad9962757 Translated using Weblate (Galician)
Currently translated at 100.0% (811 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/gl/
2024-08-27 13:12:44 +02:00
ppr
4dfcc13a3f Translated using Weblate (French)
Currently translated at 99.6% (808 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/
2024-08-27 13:12:44 +02:00
xabirequejo
e11b61f49e Translated using Weblate (Basque)
Currently translated at 100.0% (811 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-08-27 13:12:44 +02:00
cjdw
243a34d2d5 Translated using Weblate (Indonesian)
Currently translated at 100.0% (811 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-08-27 13:12:44 +02:00
José M
ca2572d00b Translated using Weblate (Galician)
Currently translated at 100.0% (811 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/gl/
2024-08-27 13:12:44 +02:00
Alexandre Aubin
518c3bbbe2
Merge pull request #1935 from YunoHost/actions/black
Format Python code with Black
2024-08-27 13:12:40 +02:00
alexAubin
9517b26c63 🎨 Format Python code with Black 2024-08-27 11:11:57 +00:00
Alexandre Aubin
a6785d34bc apps/config panels: move the computation of the actual 'bind' value to core to avoid having an epic python snippets in the bash code.. 2024-08-27 13:11:32 +02:00
Alexandre Aubin
7c79060467 perf: hmmm try to fix race condition in previous cache system ? 2024-08-26 20:52:21 +02:00
Alexandre Aubin
007c13ce42
Merge pull request #1934 from YunoHost/actions/black
Format Python code with Black
2024-08-26 20:21:24 +02:00
alexAubin
2102242a61 🎨 Format Python code with Black 2024-08-26 18:20:38 +00:00
Alexandre Aubin
c409888a4b quality: use _assert_is_installed for consistency instead of if not _is_intalled(app): raise 2024-08-26 20:20:10 +02:00
Alexandre Aubin
c14ebc8be4 perf: add cache for _get_app_settings() 2024-08-26 20:20:02 +02:00
Alexandre Aubin
9b0553580b apps: generalize replacing __INSTALL_DIR__ and __APP__ in config panel 'bind' statement to any setting 2024-08-26 20:16:48 +02:00
Alexandre Aubin
bc2ed45e9d Update changelog for 11.2.28 2024-08-25 13:22:38 +02:00
Alexandre Aubin
a76cd05e87 apps: in apt resource, fix empty string in packages_from_raw_bash breaking dpkg-build 2024-08-25 13:17:12 +02:00
yunohost-bot
eb14e404d6 [CI] Reformat / remove stale translated strings 2024-08-19 01:58:58 +02:00
zamentur
aae24614c4 🎨 Format Python code with Black 2024-08-19 01:58:36 +02:00
Emmanuel Averty
51787a2f8b trigger hooks when adding or removing user into group 2024-08-19 00:56:59 +02:00
Alexandre Aubin
c5953b5420 ci: try to fix the full test not working because i removed the pytest install @_@ 2024-08-18 22:44:27 +02:00
Alexandre Aubin
4afff118e4
Merge pull request #1930 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-08-18 13:20:48 +02:00
ppr
6113fde48a Translated using Weblate (French)
Currently translated at 99.5% (807 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/
2024-08-18 10:54:48 +02:00
xabirequejo
b734e2ea89 Translated using Weblate (Basque)
Currently translated at 100.0% (811 of 811 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-08-18 10:54:48 +02:00
Alexandre Aubin
0a44d7cea4
Merge pull request #1929 from YunoHost/ci-autofix-translated-strings-dev
[CI] Reformat / remove stale translated strings
2024-08-16 16:19:17 +02:00
yunohost-bot
5d3280c0fd [CI] Reformat / remove stale translated strings 2024-08-16 14:18:35 +00:00
Alexandre Aubin
8dc521a528
Merge pull request #1927 from YunoHost/actions/black
Format Python code with Black
2024-08-16 16:10:13 +02:00
alexAubin
2e70143da2 🎨 Format Python code with Black 2024-08-16 14:09:58 +00:00
Alexandre Aubin
3095496fe9
Merge pull request #1928 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-08-16 16:09:39 +02:00
xabirequejo
586d1c7f63 Translated using Weblate (Basque)
Currently translated at 100.0% (809 of 809 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-08-16 16:07:14 +02:00
tituspijean
d63c61e0df
Add diagnoser about rfkill blocking Wi-Fi card (#1841) 2024-08-16 16:07:10 +02:00
Alexandre Aubin
4248b27b26
Merge pull request #1926 from YunoHost/ci-autofix-translated-strings-dev
[CI] Reformat / remove stale translated strings
2024-08-16 01:21:58 +02:00
yunohost-bot
0f662d069c [CI] Reformat / remove stale translated strings 2024-08-15 23:10:02 +00:00
Alexandre Aubin
7ca710685e
Merge pull request #1253 from YunoHost/backup_mx
[enh] Be able to use postfix as a backup ("secondary") MX hosts
2024-08-16 00:55:21 +02:00
Alexandre Aubin
31d10079c7
Merge pull request #1384 from YunoHost/enh-conserver-group-permission-in-sftp
[enh] Tweak umask for SFTP
2024-08-16 00:45:35 +02:00
ljf (zamentur)
980777ebf1 [enh] Conserver group permission 2024-08-16 00:31:59 +02:00
ljf
436826abf9 [enh] Be able to use postfix as a backup mx hosts 2024-08-15 23:44:07 +02:00
Alexandre Aubin
477fa63f46
Merge pull request #1923 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-08-15 22:22:53 +02:00
xabirequejo
9a6f7dac3b Translated using Weblate (Basque)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-08-15 21:36:33 +02:00
cjdw
498006cab6 Translated using Weblate (Indonesian)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-08-15 21:36:33 +02:00
cjdw
2f186b6f7f Translated using Weblate (Indonesian)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-08-15 21:36:33 +02:00
cjdw
5708776df6 Translated using Weblate (Indonesian)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-08-15 21:36:33 +02:00
Ivan Davydov
abdbb7efcd Translated using Weblate (Russian)
Currently translated at 40.9% (330 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/ru/
2024-08-15 21:36:33 +02:00
xabirequejo
658ef88e47 Translated using Weblate (Basque)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-08-15 21:36:33 +02:00
Tagadda
4d5cc62540 🎨 Format Python code with Black 2024-08-15 21:36:29 +02:00
Tagada
f88e4cacdf
Merge pull request #1647 from YunoHost/enh_well-known
[enh] exclude .well-known subpaths from conflict checks
2024-08-15 20:50:17 +02:00
Tagada
36b9188aec
Update src/app.py
Co-authored-by: tituspijean <titus+yunohost@pijean.ovh>
2024-08-15 20:41:09 +02:00
Alexandre Aubin
c104dc6449
Merge pull request #1924 from YunoHost/actions/black
Format Python code with Black
2024-08-08 20:38:16 +02:00
alexAubin
938e400865 🎨 Format Python code with Black 2024-08-08 18:36:00 +00:00
Alexandre Aubin
de9980f31e Zblerg 2024-08-08 20:35:36 +02:00
Alexandre Aubin
f02d4a4376 ci: more optimization, lets not install pytest etc because it should already be in the image 2024-08-08 19:47:53 +02:00
Alexandre Aubin
92f4a605b8 ci: do not run on black PR 2024-08-08 19:41:29 +02:00
Alexandre Aubin
df320a44cf ci: ignore boring warning 'Could not identify correctly the dns zone for domain sub.domain.tld' 2024-08-08 19:37:50 +02:00
Alexandre Aubin
6733526bee ci: try skipping diagnosis during upgrade to speed things up a bit? 2024-08-08 19:37:50 +02:00
Alexandre Aubin
d0df3caed4 ci: propagate misc tweaks for CI speedup made on bookworm 2024-08-08 19:37:50 +02:00
Alexandre Aubin
9083a5cc3d ci: ughr ok, dunno what i was thinking, partially revert the previous commit, go to sleep Aleks ffs 2024-08-08 05:39:52 +02:00
Alexandre Aubin
764fe6a7ba ci: smol optimization to avoid installing unecessary pip dependencies? 2024-08-08 05:26:00 +02:00
Alexandre Aubin
200f0272d5 ci: propagate new CI image names 2024-08-08 01:53:58 +02:00
Alexandre Aubin
9915559c40 Update changelog for 11.2.27 2024-08-03 18:42:08 +02:00
Alexandre Aubin
760256f85d
Merge pull request #1922 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-08-03 18:41:19 +02:00
Ali Çırçır
684c3d9b2c Translated using Weblate (Turkish)
Currently translated at 3.8% (31 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/tr/
2024-08-03 18:37:48 +02:00
cjdw
90c4034908 Translated using Weblate (Indonesian)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-08-03 18:37:48 +02:00
Alexandre Aubin
3deffdbd57 apt resource: fix handling of empty 'packages' list breaking dpkg-deb call 2024-08-03 18:37:40 +02:00
tituspijean
bc30805c7d
[enh] exclude .well-known subpaths from conflict checks 2023-04-17 13:18:10 +02:00
192 changed files with 7286 additions and 7229 deletions

View file

@ -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

View file

@ -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/*

View file

@ -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}

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View 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/*

View file

@ -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)

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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
logpath = %(postfix_log)s
backend = %(postfix_backend)s
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

View file

@ -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

View file

@ -1,3 +0,0 @@
[Definition]
failregex = ^<HOST> -.*\"POST /yunohost/portalapi/login HTTP/\d.\d\" 401
ignoreregex =

View file

@ -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 =

View 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"

View 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"

View 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;

View 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));

View 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);

View 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);

View 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;

View 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) {
}

View 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
}

View file

@ -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)

View file

@ -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 %}

View file

@ -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;
}

View file

@ -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:;";
}

View file

@ -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

View file

@ -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 %}

View 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";

View file

@ -0,0 +1,8 @@
# Metrics settings
# This define overridden options.
actions {
reject = 21;
add_header = 8;
greylist = 4;
}

View 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
View file

@ -0,0 +1,2 @@
# set redis server
servers = "127.0.0.1";

4
conf/rspamd/rspamd.sieve Normal file
View file

@ -0,0 +1,4 @@
require ["fileinto"];
if header :is "X-Spam" "Yes" {
fileinto "Junk";
}

View file

@ -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

View file

@ -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

View file

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

View file

@ -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

View file

@ -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
View file

@ -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, 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
View file

@ -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
View file

@ -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
View file

@ -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

View file

@ -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()

View file

@ -1,4 +0,0 @@
from yunohost.utils.configpanel import ConfigPanelModel
print(ConfigPanelModel.schema_json(indent=2))

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Entrypoint for the helpers scripts
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
# Helpers version can be specified via an environment variable or default to 1.
YNH_HELPERS_VERSION=${YNH_HELPERS_VERSION:-1}
@ -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"

View file

@ -7,52 +7,49 @@
#
# Requires YunoHost version *.*.* or higher.
ynh_install_apps() {
# Declare an array to define the options of this helper.
local legacy_args=a
local -A args_array=([a]=apps=)
local apps
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=a
local -A args_array=([a]=apps=)
local apps
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Split the list of apps in an array
local apps_list=($(echo $apps | tr " " "\n"))
local apps_dependencies=""
# For each app
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"
# Split the list of apps in an array
local apps_list=($(echo $apps | tr " " "\n"))
local apps_dependencies=""
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
# Retrieve the arguments of the app (part after ?)
local one_argument=""
if [[ "$one_app_and_its_args" == *"?"* ]]; then
one_argument=$(cut -d "?" -f2- <<< "$one_app_and_its_args")
one_argument="--args $one_argument"
fi
# Install the app with its arguments
yunohost app install $one_app $one_argument
else
# Upgrade the app
yunohost app upgrade $one_app
fi
# For each app
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"
if [ ! -z "$apps_dependencies" ]
then
apps_dependencies="$apps_dependencies, $one_app"
else
apps_dependencies="$one_app"
fi
done
yunohost tools update apps
ynh_app_setting_set --app=$app --key=apps_dependencies --value="$apps_dependencies"
# 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
# Retrieve the arguments of the app (part after ?)
local one_argument=""
if [[ "$one_app_and_its_args" == *"?"* ]]; then
one_argument=$(cut -d "?" -f2- <<< "$one_app_and_its_args")
one_argument="--args $one_argument"
fi
# Install the app with its arguments
yunohost app install $one_app $one_argument
else
# Upgrade the app
yunohost app upgrade $one_app
fi
if [ ! -z "$apps_dependencies" ]; then
apps_dependencies="$apps_dependencies, $one_app"
else
apps_dependencies="$one_app"
fi
done
ynh_app_setting_set --app=$app --key=apps_dependencies --value="$apps_dependencies"
}
# Remove other YunoHost apps
@ -63,53 +60,47 @@ ynh_install_apps() {
#
# Requires YunoHost version *.*.* or higher.
ynh_remove_apps() {
# Retrieve the apps dependencies of the app
local apps_dependencies=$(ynh_app_setting_get --app=$app --key=apps_dependencies)
ynh_app_setting_delete --app=$app --key=apps_dependencies
# Retrieve the apps dependencies of the app
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
# 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
# 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=""
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 other installed app
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
one_installed_apps_dependencies_list=($(echo $one_installed_apps_dependencies | tr ", " "\n"))
# For each apps dependencies
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 dependency of the other apps
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
done
fi
done
# For each other installed app
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
one_installed_apps_dependencies_list=($(echo $one_installed_apps_dependencies | tr ", " "\n"))
# If $one_app is no more required
if [[ -z "$required_by" ]]
then
# Remove $one_app
ynh_print_info --message="Removing of $one_app"
yunohost app remove $one_app --purge
else
ynh_print_info --message="$one_app was not removed because it's still required by${required_by}"
fi
done
fi
# For each dependency of the other apps
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
done
fi
done
# If $one_app is no more required
if [[ -z "$required_by" ]]; then
# Remove $one_app
ynh_print_info --message="Removing of $one_app"
yunohost app remove $one_app --purge
else
ynh_print_info --message="$one_app was not removed because it's still required by${required_by}"
fi
done
fi
}
# Spawn a Bash shell with the app environment loaded
@ -126,90 +117,83 @@ ynh_remove_apps() {
# from the app's service configuration file (defaults to $app.service, overridable by the packager with `service` setting).
# If the app relies on a specific PHP version, then `php` will be aliased that version. The PHP command will also be appended with the `phpflags` settings.
ynh_spawn_app_shell() {
# Declare an array to define the options of this helper.
local legacy_args=a
local -A args_array=([a]=app=)
local app
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=a
local -A args_array=([a]=app=)
local app
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Force Bash to be used to run this helper
if [[ ! $0 =~ \/?bash$ ]]
then
ynh_print_err --message="Please use Bash as shell"
exit 1
fi
# Force Bash to be used to run this helper
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
ynh_print_err --message="$app is not in the apps list"
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
ynh_print_err --message="$app is not in the apps list"
exit 1
fi
# Make sure the app has its own user
if ! id -u "$app" &>/dev/null; then
ynh_print_err --message="There is no \"$app\" system user"
exit 1
fi
# Make sure the app has its own user
if ! id -u "$app" &> /dev/null; then
ynh_print_err --message="There is no \"$app\" system user"
exit 1
fi
# 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
ynh_print_err --message="$app has no install_dir setting (does it use packaging format >=2?)"
exit 1
fi
# 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
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;
# Load the app's service name, or default to $app
local service=$(ynh_app_setting_get --app=$app --key=service)
[ -z "$service" ] && service=$app
# Export HOME variable
export HOME=$install_dir;
# Export HOME variable
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;
# 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
# 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
eval "php() { php${phpversion} ${phpflags} \"\$@\"; }"
export -f php
fi
# 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
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
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
set -a
for file in ${env_files[*]}
do
[[ $file = /* ]] && source $file
done
set +a
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
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
set -a
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
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
set -a
source $install_dir/venv/bin/activate
set +a
fi
# Activate the Python environment, if it exists
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
set +a
fi
# 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;
cd $env_dir
# 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
cd $env_dir
# Spawn the app shell
su -s /bin/bash $app
# Spawn the app shell
su -s /bin/bash $app
}

View file

@ -14,7 +14,7 @@ ynh_wait_dpkg_free() {
# With seq 1 17, timeout will be almost 30 minutes
for try in $(seq 1 17); do
# Check if /var/lib/dpkg/lock is used by another process
if lsof /var/lib/dpkg/lock >/dev/null; then
if lsof /var/lib/dpkg/lock > /dev/null; then
echo "apt is already in use..."
# Sleep an exponential time at each round
sleep $((try * try))
@ -32,7 +32,7 @@ ynh_wait_dpkg_free() {
set -o xtrace # set -x
return 1
fi
done 9<<<"$(ls -1 $dpkg_dir)"
done 9<<< "$(ls -1 $dpkg_dir)"
set -o xtrace # set -x
return 0
fi
@ -58,8 +58,8 @@ ynh_package_is_installed() {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
dpkg-query --show --showformat='${Status}' "$package" 2>/dev/null \
| grep --count "ok installed" &>/dev/null
dpkg-query --show --showformat='${Status}' "$package" 2> /dev/null \
| grep --count "ok installed" &> /dev/null
}
# Get the version of an installed package
@ -82,7 +82,7 @@ ynh_package_version() {
ynh_handle_getopts_args "$@"
if ynh_package_is_installed "$package"; then
dpkg-query --show --showformat='${Version}' "$package" 2>/dev/null
dpkg-query --show --showformat='${Version}' "$package" 2> /dev/null
else
echo ''
fi
@ -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,20 +303,18 @@ 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
dependencies="$current_dependencies, $dependencies"
fi
cat >/tmp/${dep_app}-ynh-deps.control <<EOF # Make a control file for equivs-build
cat > /tmp/${dep_app}-ynh-deps.control << EOF # Make a control file for equivs-build
Section: misc
Priority: optional
Package: ${dep_app}-ynh-deps
@ -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
@ -372,7 +366,7 @@ ynh_add_app_dependencies() {
#
# Requires YunoHost version 2.6.4 or higher.
ynh_remove_app_dependencies() {
local dep_app=${app//_/-} # Replace all '_' by '-'
local dep_app=${app//_/-} # Replace all '_' by '-'
local current_dependencies=""
if ynh_package_is_installed --package="${dep_app}-ynh-deps"; then
@ -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,11 +479,13 @@ 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
if (("${#repo_parts[@]}" > 0)); then
component="${repo_parts[*]:$index}"
fi
@ -512,7 +506,7 @@ ynh_install_extra_repo() {
if [ -n "$key" ] && [[ "$key" != "trusted=yes" ]]; then
mkdir --parents "/etc/apt/trusted.gpg.d"
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
wget --timeout 900 --quiet "$key" --output-document=- | gpg --dearmor | $wget_append /etc/apt/trusted.gpg.d/$name.gpg >/dev/null
wget --timeout 900 --quiet "$key" --output-document=- | gpg --dearmor | $wget_append /etc/apt/trusted.gpg.d/$name.gpg > /dev/null
fi
# Update the list of package with the new repo

View file

@ -162,7 +162,7 @@ ynh_backup() {
# ==============================================================================
local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g')
local dest=$(echo "${dest_path}" | sed --regexp-extended 's/"/\"\"/g')
echo "\"${src}\",\"${dest}\"" >>"${YNH_BACKUP_CSV}"
echo "\"${src}\",\"${dest}\"" >> "${YNH_BACKUP_CSV}"
# ==============================================================================
@ -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
@ -412,7 +410,7 @@ ynh_delete_file_checksum() {
#
ynh_backup_archive_exists() {
yunohost backup list --output-as json --quiet \
| jq -e --arg archive "$1" '.archives | index($archive)' >/dev/null
| jq -e --arg archive "$1" '.archives | index($archive)' > /dev/null
}
# Make a backup in case of failed upgrade
@ -455,7 +453,7 @@ ynh_backup_before_upgrade() {
# If the backup succeeded, remove the previous backup
if ynh_backup_archive_exists "$app_bck-pre-upgrade$old_backup_number"; then
# Remove the previous backup only if it exists
yunohost backup delete $app_bck-pre-upgrade$old_backup_number >/dev/null
yunohost backup delete $app_bck-pre-upgrade$old_backup_number > /dev/null
fi
else
ynh_die --message="Backup failed, the upgrade process was aborted."
@ -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 :|"

View file

@ -6,11 +6,11 @@ _ynh_app_config_get_one() {
local bind="$3"
local getter="get__${short_setting}"
# Get value from getter if exists
if type -t $getter 2>/dev/null | grep -q '^function$' 2>/dev/null; then
if type -t $getter 2> /dev/null | grep -q '^function$' 2> /dev/null; then
old[$short_setting]="$($getter)"
formats[${short_setting}]="yaml"
elif [[ "$bind" == *"("* ]] && type -t "get__${bind%%(*}" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
elif [[ "$bind" == *"("* ]] && type -t "get__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
old[$short_setting]="$("get__${bind%%(*}" $short_setting $type $bind)"
formats[${short_setting}]="yaml"
@ -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
@ -59,10 +59,10 @@ _ynh_app_config_apply_one() {
local type="${types[$short_setting]}"
if [ "${changed[$short_setting]}" == "true" ]; then
# Apply setter if exists
if type -t $setter 2>/dev/null | grep -q '^function$' 2>/dev/null; then
if type -t $setter 2> /dev/null | grep -q '^function$' 2> /dev/null; then
$setter
elif [[ "$bind" == *"("* ]] && type -t "set__${bind%%(*}" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
elif [[ "$bind" == *"("* ]] && type -t "set__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
"set__${bind%%(*}" $short_setting $type $bind
elif [[ "$bind" == "null" ]]; then
@ -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,9 +98,9 @@ _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"
echo "${!short_setting}" > "$bind_file"
ynh_store_file_checksum --file="$bind_file" --update_only
ynh_print_info --message="File '$bind_file' overwritten with the content provided in question '${short_setting}'"
@ -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,69 +126,17 @@ _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"
IFS='|' read short_setting type bind <<< "$line"
binds[${short_setting}]="$bind"
types[${short_setting}]="$type"
file_hash[${short_setting}]=""
formats[${short_setting}]=""
ynh_app_config_get_one $short_setting $type $bind
done
}
_ynh_app_config_apply() {
@ -258,9 +206,9 @@ _ynh_app_config_validate() {
for short_setting in "${!old[@]}"; do
[[ "${changed[$short_setting]}" == "false" ]] && continue
local result=""
if type -t validate__$short_setting | grep -q '^function$' 2>/dev/null; then
if type -t validate__$short_setting | grep -q '^function$' 2> /dev/null; then
result="$(validate__$short_setting)"
elif [[ "$bind" == *"("* ]] && type -t "validate__${bind%%(*}" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
elif [[ "$bind" == *"("* ]] && type -t "validate__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
"validate__${bind%%(*}" $short_setting
fi
if [ -n "$result" ]; then
@ -315,7 +263,7 @@ ynh_app_config_apply() {
ynh_app_action_run() {
local runner="run__$1"
# Get value from getter if exists
if type -t "$runner" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
if type -t "$runner" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
$runner
#ynh_return "result:"
#ynh_return "$(echo "${result}" | sed 's/^/ /g')"
@ -333,22 +281,23 @@ ynh_app_config_run() {
declare -Ag formats=()
case $1 in
show)
ynh_app_config_get
ynh_app_config_show
;;
apply)
max_progression=4
ynh_script_progression --message="Reading config panel description and current configuration..."
ynh_app_config_get
show)
ynh_app_config_get
ynh_app_config_show
;;
apply)
max_progression=4
ynh_script_progression --message="Reading config panel description and current configuration..."
ynh_app_config_get
ynh_app_config_validate
ynh_app_config_validate
ynh_script_progression --message="Applying the new configuration..."
ynh_app_config_apply
ynh_script_progression --message="Configuration of $app completed" --last
;;
*)
ynh_app_action_run $1
ynh_script_progression --message="Applying the new configuration..."
ynh_app_config_apply
ynh_script_progression --message="Configuration of $app completed" --last
;;
*)
ynh_app_action_run $1
;;
esac
}

View file

@ -82,7 +82,7 @@ port = __PORTS__
filter = __APP__
logpath = __LOGPATH__
maxretry = __MAX_RETRY__
" >"$YNH_APP_BASEDIR/conf/f2b_jail.conf"
" > "$YNH_APP_BASEDIR/conf/f2b_jail.conf"
echo "
[INCLUDES]
@ -90,7 +90,7 @@ before = common.conf
[Definition]
failregex = __FAILREGEX__
ignoreregex =
" >"$YNH_APP_BASEDIR/conf/f2b_filter.conf"
" > "$YNH_APP_BASEDIR/conf/f2b_filter.conf"
fi
ynh_add_config --template="f2b_jail.conf" --destination="/etc/fail2ban/jail.d/$app.conf"
@ -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

View file

@ -20,7 +20,7 @@
# | arg: $@ - Simply "$@" to tranfert all the positionnal arguments to the function
#
# This helper need an array, named "args_array" with all the arguments used by the helper
# that want to use ynh_handle_getopts_args
# that want to use ynh_handle_getopts_args
# Be carreful, this array has to be an associative array, as the following example:
# local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
# Let's explain this array:
@ -180,7 +180,7 @@ ynh_handle_getopts_args() {
# If not, enter in legacy mode and manage the arguments as positionnal ones..
# Dot not echo, to prevent to go through a helper output. But print only in the log.
set -x
echo "! Helper used in legacy mode !" >/dev/null
echo "! Helper used in legacy mode !" > /dev/null
set +x
local i
for i in $(seq 0 $((${#arguments[@]} - 1))); do

View file

@ -1,11 +1,11 @@
#!/bin/bash
ynh_go_try_bash_extension() {
if [ -x src/configure ]; then
src/configure && make -C src || {
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
}
fi
if [ -x src/configure ]; then
src/configure && make -C src || {
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
}
fi
}
goenv_install_dir="/opt/goenv"
@ -51,7 +51,7 @@ export GOENV_ROOT="$goenv_install_dir"
# usage: ynh_use_go
#
# Requires YunoHost version 3.2.2 or higher.
ynh_use_go () {
ynh_use_go() {
go_version=$(ynh_app_setting_get --app=$app --key=go_version)
# Get the absolute path of this version of Go
@ -73,7 +73,7 @@ ynh_use_go () {
# Sets the local application-specific Go version
pushd $install_dir
$goenv_install_dir/bin/goenv local $go_version
$goenv_install_dir/bin/goenv local $go_version
popd
}
@ -93,10 +93,10 @@ ynh_use_go () {
# | arg: -v, --go_version= - Version of go to install.
#
# Requires YunoHost version 3.2.2 or higher.
ynh_install_go () {
ynh_install_go() {
# Declare an array to define the options of this helper.
local legacy_args=v
local -A args_array=( [v]=go_version= )
local -A args_array=([v]=go_version=)
local go_version
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -113,34 +113,34 @@ ynh_install_go () {
# Install or update goenv
mkdir -p $goenv_install_dir
pushd "$goenv_install_dir"
if ! [ -x "$goenv_install_dir/bin/goenv" ]; then
ynh_print_info --message="Downloading goenv..."
git init -q
git remote add origin https://github.com/syndbg/goenv.git
else
ynh_print_info --message="Updating goenv..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
ynh_go_try_bash_extension
goenv=$goenv_install_dir/bin/goenv
if ! [ -x "$goenv_install_dir/bin/goenv" ]; then
ynh_print_info --message="Downloading goenv..."
git init -q
git remote add origin https://github.com/syndbg/goenv.git
else
ynh_print_info --message="Updating goenv..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
ynh_go_try_bash_extension
goenv=$goenv_install_dir/bin/goenv
popd
# Install or update xxenv-latest
goenv_latest_dir="$goenv_install_dir/plugins/xxenv-latest"
mkdir -p "$goenv_latest_dir"
pushd "$goenv_latest_dir"
if ! [ -x "$goenv_latest_dir/bin/goenv-latest" ]; then
ynh_print_info --message="Downloading xxenv-latest..."
git init -q
git remote add origin https://github.com/momo-lab/xxenv-latest.git
else
ynh_print_info --message="Updating xxenv-latest..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
if ! [ -x "$goenv_latest_dir/bin/goenv-latest" ]; then
ynh_print_info --message="Downloading xxenv-latest..."
git init -q
git remote add origin https://github.com/momo-lab/xxenv-latest.git
else
ynh_print_info --message="Updating xxenv-latest..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
popd
# Enable caching
@ -167,7 +167,7 @@ ynh_install_go () {
ynh_cleanup_go
# Set environment for Go users
echo "#goenv
echo "#goenv
export GOENV_ROOT=$goenv_install_dir
export PATH=\"$goenv_install_dir/bin:$PATH\"
eval \"\$(goenv init -)\"
@ -182,7 +182,7 @@ eval \"\$(goenv init -)\"
# This helper will also cleanup Go versions
#
# usage: ynh_remove_go
ynh_remove_go () {
ynh_remove_go() {
local go_version=$(ynh_app_setting_get --app="$app" --key="go_version")
# Load goenv path in PATH
@ -205,34 +205,29 @@ ynh_remove_go () {
# If no app uses Go, goenv will be also removed.
#
# usage: ynh_cleanup_go
ynh_cleanup_go () {
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"

View file

@ -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
@ -199,7 +194,7 @@ ynh_exec_and_print_stderr_only_if_error() {
rc=0
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
"$@" 2> "$logfile" || rc="$?"
if (( rc != 0 )); then
if ((rc != 0)); then
ynh_exec_warn cat "$logfile"
ynh_secure_remove "$logfile"
return "$rc"
@ -216,7 +211,7 @@ ynh_exec_and_print_stderr_only_if_error() {
#
# Requires YunoHost version 3.2.0 or higher.
ynh_print_OFF() {
exec {BASH_XTRACEFD}>/dev/null
exec {BASH_XTRACEFD}> /dev/null
}
# Restore the logging after ynh_print_OFF
@ -229,7 +224,7 @@ ynh_print_OFF() {
ynh_print_ON() {
exec {BASH_XTRACEFD}>&1
# Print an echo only for the log, to be able to know that ynh_print_ON has been called.
echo ynh_print_ON >/dev/null
echo ynh_print_ON > /dev/null
}
# Initial definitions for ynh_script_progression
@ -271,9 +266,9 @@ ynh_script_progression() {
# Always activate time when running inside CI tests
if [ ${PACKAGE_CHECK_EXEC:-0} -eq 1 ]; then
time=${time:-1}
time=${time:-1}
else
time=${time:-0}
time=${time:-0}
fi
last=${last:-0}
@ -298,8 +293,8 @@ ynh_script_progression() {
local weight_values=$(($(echo "$weight_valuesA" "$weight_valuesB" | grep -v -E '^\s*$' | tr '\n' '+' | sed 's/+$/+0/g')))
# max_progression is a total number of calls to this helper.
# Less the number of calls with a weight value.
# Plus the total of weight values
# Less the number of calls with a weight value.
# Plus the total of weight values
max_progression=$(($helper_calls - $weight_calls + $weight_values))
fi
@ -329,7 +324,7 @@ ynh_script_progression() {
local print_exec_time=""
if [ $time -eq 1 ] && [ "$exec_time" -gt 10 ]; then
print_exec_time=" [$(bc <<< "scale=1; $exec_time / 60" ) minutes]"
print_exec_time=" [$(bc <<< "scale=1; $exec_time / 60") minutes]"
fi
ynh_print_info "[$progression_bar] > ${message}${print_exec_time}"
@ -343,5 +338,5 @@ ynh_script_progression() {
#
# Requires YunoHost version 3.6.0 or higher.
ynh_return() {
echo "$1" >>"$YNH_STDRETURN"
echo "$1" >> "$YNH_STDRETURN"
}

View file

@ -16,11 +16,9 @@ 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
local all_args=(${@})
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
@ -54,7 +51,7 @@ ynh_use_logrotate() {
fi
local tempconf="$(mktemp)"
cat << EOF >$tempconf
cat << EOF > $tempconf
$logfile {
# Rotate if the logfile exceeds 100Mo
size 100M
@ -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

View file

@ -6,100 +6,92 @@
# example: ynh_mongo_exec --command="db.getMongo().getDBNames().indexOf(\"wekan\")"
#
# usage: ynh_mongo_exec [--user=user] [--password=password] [--authenticationdatabase=authenticationdatabase] [--database=database] [--host=host] [--port=port] --command="command" [--eval]
# | arg: -u, --user= - The user name to connect as
# | arg: -p, --password= - The user password
# | arg: -d, --authenticationdatabase= - The authenticationdatabase to connect to
# | arg: -d, --database= - The database to connect to
# | arg: -h, --host= - The host to connect to
# | arg: -P, --port= - The port to connect to
# | arg: -c, --command= - The command to evaluate
# | arg: -e, --eval - Evaluate instead of execute the command.
# | arg: -u, --user= - The user name to connect as
# | arg: -p, --password= - The user password
# | arg: -d, --authenticationdatabase= - The authenticationdatabase to connect to
# | arg: -d, --database= - The database to connect to
# | arg: -h, --host= - The host to connect to
# | arg: -P, --port= - The port to connect to
# | arg: -c, --command= - The command to evaluate
# | arg: -e, --eval - Evaluate instead of execute the command.
#
#
ynh_mongo_exec() {
# Declare an array to define the options of this helper.
local legacy_args=upadhPce
local -A args_array=( [u]=user= [p]=password= [a]=authenticationdatabase= [d]=database= [h]=host= [P]=port= [c]=command= [e]=eval )
local user
local password
local authenticationdatabase
local database
local host
local port
local command
local eval
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
user="${user:-}"
password="${password:-}"
authenticationdatabase="${authenticationdatabase:-}"
database="${database:-}"
host="${host:-}"
port="${port:-}"
eval=${eval:-0}
# Declare an array to define the options of this helper.
local legacy_args=upadhPce
local -A args_array=([u]=user= [p]=password= [a]=authenticationdatabase= [d]=database= [h]=host= [P]=port= [c]=command= [e]=eval)
local user
local password
local authenticationdatabase
local database
local host
local port
local command
local eval
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
user="${user:-}"
password="${password:-}"
authenticationdatabase="${authenticationdatabase:-}"
database="${database:-}"
host="${host:-}"
port="${port:-}"
eval=${eval:-0}
# If user is provided
if [ -n "$user" ]
then
user="--username=$user"
# If user is provided
if [ -n "$user" ]; then
user="--username=$user"
# If password is provided
if [ -n "$password" ]
then
password="--password=$password"
fi
# If password is provided
if [ -n "$password" ]; then
password="--password=$password"
fi
# If authenticationdatabase is provided
if [ -n "$authenticationdatabase" ]
then
authenticationdatabase="--authenticationDatabase=$authenticationdatabase"
else
authenticationdatabase="--authenticationDatabase=admin"
fi
else
password=""
authenticationdatabase=""
fi
# If authenticationdatabase is provided
if [ -n "$authenticationdatabase" ]; then
authenticationdatabase="--authenticationDatabase=$authenticationdatabase"
else
authenticationdatabase="--authenticationDatabase=admin"
fi
else
password=""
authenticationdatabase=""
fi
# If host is provided
if [ -n "$host" ]
then
host="--host=$host"
fi
# If host is provided
if [ -n "$host" ]; then
host="--host=$host"
fi
# If port is provided
if [ -n "$port" ]
then
port="--port=$port"
fi
# If port is provided
if [ -n "$port" ]; then
port="--port=$port"
fi
# If eval is not provided
if [ $eval -eq 0 ]
then
# If database is provided
if [ -n "$database" ]
then
database="use $database"
else
database=""
fi
# If eval is not provided
if [ $eval -eq 0 ]; then
# If database is provided
if [ -n "$database" ]; then
database="use $database"
else
database=""
fi
mongosh --quiet --username $user --password $password --authenticationDatabase $authenticationdatabase --host $host --port $port <<EOF
mongosh --quiet --username $user --password $password --authenticationDatabase $authenticationdatabase --host $host --port $port << EOF
$database
${command}
quit()
EOF
else
# If database is provided
if [ -n "$database" ]
then
database="$database"
else
database=""
fi
else
# If database is provided
if [ -n "$database" ]; then
database="$database"
else
database=""
fi
mongosh --quiet $database --username $user --password $password --authenticationDatabase $authenticationdatabase --host $host --port $port --eval="$command"
fi
mongosh --quiet $database --username $user --password $password --authenticationDatabase $authenticationdatabase --host $host --port $port --eval="$command"
fi
}
# Drop a database
@ -110,18 +102,18 @@ EOF
# consider using ynh_mongo_remove_db instead.
#
# usage: ynh_mongo_drop_db --database=database
# | arg: -d, --database= - The database name to drop
# | arg: -d, --database= - The database name to drop
#
#
ynh_mongo_drop_db() {
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=( [d]=database= )
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_mongo_exec --database="$database" --command='db.runCommand({dropDatabase: 1})'
ynh_mongo_exec --database="$database" --command='db.runCommand({dropDatabase: 1})'
}
# Dump a database
@ -129,19 +121,19 @@ ynh_mongo_drop_db() {
# example: ynh_mongo_dump_db --database=wekan > ./dump.bson
#
# usage: ynh_mongo_dump_db --database=database
# | arg: -d, --database= - The database name to dump
# | arg: -d, --database= - The database name to dump
# | ret: the mongodump output
#
#
ynh_mongo_dump_db() {
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=( [d]=database= )
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
mongodump --quiet --db="$database" --archive
mongodump --quiet --db="$database" --archive
}
# Create a user
@ -149,49 +141,48 @@ ynh_mongo_dump_db() {
# [internal]
#
# usage: ynh_mongo_create_user --db_user=user --db_pwd=pwd --db_name=name
# | arg: -u, --db_user= - The user name to create
# | arg: -p, --db_pwd= - The password to identify user by
# | arg: -n, --db_name= - Name of the database to grant privilegies
# | arg: -u, --db_user= - The user name to create
# | arg: -p, --db_pwd= - The password to identify user by
# | arg: -n, --db_name= - Name of the database to grant privilegies
#
#
ynh_mongo_create_user() {
# Declare an array to define the options of this helper.
local legacy_args=unp
local -A args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
local db_user
local db_name
local db_pwd
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=unp
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
local db_user
local db_name
local db_pwd
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Create the user and set the user as admin of the db
ynh_mongo_exec --database="$db_name" --command='db.createUser( { user: "'${db_user}'", pwd: "'${db_pwd}'", roles: [ { role: "readWrite", db: "'${db_name}'" } ] } );'
# Create the user and set the user as admin of the db
ynh_mongo_exec --database="$db_name" --command='db.createUser( { user: "'${db_user}'", pwd: "'${db_pwd}'", roles: [ { role: "readWrite", db: "'${db_name}'" } ] } );'
# Add clustermonitoring rights
ynh_mongo_exec --database="$db_name" --command='db.grantRolesToUser("'${db_user}'",[{ role: "clusterMonitor", db: "admin" }]);'
# Add clustermonitoring rights
ynh_mongo_exec --database="$db_name" --command='db.grantRolesToUser("'${db_user}'",[{ role: "clusterMonitor", db: "admin" }]);'
}
# Check if a mongo database exists
#
# usage: ynh_mongo_database_exists --database=database
# | arg: -d, --database= - The database for which to check existence
# | arg: -d, --database= - The database for which to check existence
# | exit: Return 1 if the database doesn't exist, 0 otherwise
#
#
ynh_mongo_database_exists() {
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")' --eval) -lt 0 ]
then
return 1
else
return 0
fi
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")' --eval) -lt 0 ]; then
return 1
else
return 0
fi
}
# Restore a database
@ -199,18 +190,18 @@ ynh_mongo_database_exists() {
# example: ynh_mongo_restore_db --database=wekan < ./dump.bson
#
# usage: ynh_mongo_restore_db --database=database
# | arg: -d, --database= - The database name to restore
# | arg: -d, --database= - The database name to restore
#
#
ynh_mongo_restore_db() {
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=( [d]=database= )
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=d
local -A args_array=([d]=database=)
local database
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
mongorestore --quiet --db="$database" --archive
mongorestore --quiet --db="$database" --archive
}
# Drop a user
@ -218,120 +209,120 @@ ynh_mongo_restore_db() {
# [internal]
#
# usage: ynh_mongo_drop_user --db_user=user --db_name=name
# | arg: -u, --db_user= - The user to drop
# | arg: -n, --db_name= - Name of the database
# | arg: -u, --db_user= - The user to drop
# | arg: -n, --db_name= - Name of the database
#
#
ynh_mongo_drop_user() {
# Declare an array to define the options of this helper.
local legacy_args=un
local -A args_array=( [u]=db_user= [n]=db_name= )
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=un
local -A args_array=([u]=db_user= [n]=db_name=)
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
ynh_mongo_exec --database="$db_name" --command='db.dropUser("'$db_user'", {w: "majority", wtimeout: 5000})'
ynh_mongo_exec --database="$db_name" --command='db.dropUser("'$db_user'", {w: "majority", wtimeout: 5000})'
}
# Create a database, an user and its password. Then store the password in the app's config
#
# usage: ynh_mongo_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
# | arg: -p, --db_pwd= - Password of the database. If not provided, a password will be generated
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
# | arg: -p, --db_pwd= - Password of the database. If not provided, a password will be generated
#
# After executing this helper, the password of the created database will be available in $db_pwd
# It will also be stored as "mongopwd" into the app settings.
#
#
ynh_mongo_setup_db() {
# Declare an array to define the options of this helper.
local legacy_args=unp
local -A args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=unp
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
local db_user
local db_name
db_pwd=""
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local new_db_pwd=$(ynh_string_random) # Generate a random password
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
local new_db_pwd=$(ynh_string_random) # Generate a random password
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
# Create the user and grant access to the database
ynh_mongo_create_user --db_user="$db_user" --db_pwd="$db_pwd" --db_name="$db_name"
# Create the user and grant access to the database
ynh_mongo_create_user --db_user="$db_user" --db_pwd="$db_pwd" --db_name="$db_name"
# Store the password in the app's config
ynh_app_setting_set --app=$app --key=db_pwd --value=$db_pwd
# Store the password in the app's config
ynh_app_setting_set --app=$app --key=db_pwd --value=$db_pwd
}
# Remove a database if it exists, and the associated user
#
# usage: ynh_mongo_remove_db --db_user=user --db_name=name
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
# | arg: -u, --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database
#
#
ynh_mongo_remove_db() {
# Declare an array to define the options of this helper.
local legacy_args=un
local -A args_array=( [u]=db_user= [n]=db_name= )
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Declare an array to define the options of this helper.
local legacy_args=un
local -A args_array=([u]=db_user= [n]=db_name=)
local db_user
local db_name
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if ynh_mongo_database_exists --database=$db_name; then # Check if the database exists
ynh_mongo_drop_db --database=$db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
if ynh_mongo_database_exists --database=$db_name; then # Check if the database exists
ynh_mongo_drop_db --database=$db_name # Remove the database
else
ynh_print_warn --message="Database $db_name not found"
fi
# Remove mongo user if it exists
ynh_mongo_drop_user --db_user=$db_user --db_name=$db_name
# Remove mongo user if it exists
ynh_mongo_drop_user --db_user=$db_user --db_name=$db_name
}
# Install MongoDB and integrate MongoDB service in YunoHost
#
# usage: ynh_install_mongo [--mongo_version=mongo_version]
# | arg: -m, --mongo_version= - Version of MongoDB to install
# | arg: -m, --mongo_version= - Version of MongoDB to install
#
#
ynh_install_mongo() {
# Declare an array to define the options of this helper.
local legacy_args=m
local -A args_array=([m]=mongo_version=)
local mongo_version
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
mongo_version="${mongo_version:-$YNH_MONGO_VERSION}"
# Declare an array to define the options of this helper.
local legacy_args=m
local -A args_array=([m]=mongo_version=)
local mongo_version
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
mongo_version="${mongo_version:-$YNH_MONGO_VERSION}"
ynh_print_info --message="Installing MongoDB Community Edition ..."
local mongo_debian_release=$(ynh_get_debian_release)
ynh_print_info --message="Installing MongoDB Community Edition ..."
local mongo_debian_release=$(ynh_get_debian_release)
if [[ "$(grep '^flags' /proc/cpuinfo | uniq)" != *"avx"* && "$mongo_version" != "4.4" ]]; then
ynh_print_warn --message="Installing Mongo 4.4 as $mongo_version is not compatible with your cpu (see https://docs.mongodb.com/manual/administration/production-notes/#x86_64)."
mongo_version="4.4"
fi
if [[ "$mongo_version" == "4.4" ]]; then
ynh_print_warn --message="Switched to buster install as Mongo 4.4 is not compatible with $mongo_debian_release."
mongo_debian_release=buster
fi
ynh_print_warn --message="Installing Mongo 4.4 as $mongo_version is not compatible with your cpu (see https://docs.mongodb.com/manual/administration/production-notes/#x86_64)."
mongo_version="4.4"
fi
if [[ "$mongo_version" == "4.4" ]]; then
ynh_print_warn --message="Switched to buster install as Mongo 4.4 is not compatible with $mongo_debian_release."
mongo_debian_release=buster
fi
ynh_install_extra_app_dependencies --repo="deb http://repo.mongodb.org/apt/debian $mongo_debian_release/mongodb-org/$mongo_version main" --package="mongodb-org mongodb-org-server mongodb-org-tools mongodb-mongosh" --key="https://www.mongodb.org/static/pgp/server-$mongo_version.asc"
mongodb_servicename=mongod
ynh_install_extra_app_dependencies --repo="deb http://repo.mongodb.org/apt/debian $mongo_debian_release/mongodb-org/$mongo_version main" --package="mongodb-org mongodb-org-server mongodb-org-tools mongodb-mongosh" --key="https://www.mongodb.org/static/pgp/server-$mongo_version.asc"
mongodb_servicename=mongod
# Make sure MongoDB is started and enabled
systemctl enable $mongodb_servicename --quiet
systemctl daemon-reload --quiet
ynh_systemd_action --service_name=$mongodb_servicename --action=restart --line_match="aiting for connections" --log_path="/var/log/mongodb/$mongodb_servicename.log"
# Make sure MongoDB is started and enabled
systemctl enable $mongodb_servicename --quiet
systemctl daemon-reload --quiet
ynh_systemd_action --service_name=$mongodb_servicename --action=restart --line_match="aiting for connections" --log_path="/var/log/mongodb/$mongodb_servicename.log"
# Integrate MongoDB service in YunoHost
yunohost service add $mongodb_servicename --description="MongoDB daemon" --log="/var/log/mongodb/$mongodb_servicename.log"
# Integrate MongoDB service in YunoHost
yunohost service add $mongodb_servicename --description="MongoDB daemon" --log="/var/log/mongodb/$mongodb_servicename.log"
# Store mongo_version into the config of this app
ynh_app_setting_set --app=$app --key=mongo_version --value=$mongo_version
# Store mongo_version into the config of this app
ynh_app_setting_set --app=$app --key=mongo_version --value=$mongo_version
}
# Remove MongoDB
@ -342,14 +333,13 @@ ynh_install_mongo() {
#
#
ynh_remove_mongo() {
# Only remove the mongodb service if it is not installed.
if ! ynh_package_is_installed --package="mongodb*"
then
ynh_print_info --message="Removing MongoDB service..."
mongodb_servicename=mongod
# Remove the mongodb service
yunohost service remove $mongodb_servicename
ynh_secure_remove --file="/var/lib/mongodb"
ynh_secure_remove --file="/var/log/mongodb"
fi
# Only remove the mongodb service if it is not installed.
if ! ynh_package_is_installed --package="mongodb*"; then
ynh_print_info --message="Removing MongoDB service..."
mongodb_servicename=mongod
# Remove the mongodb service
yunohost service remove $mongodb_servicename
ynh_secure_remove --file="/var/lib/mongodb"
ynh_secure_remove --file="/var/log/mongodb"
fi
}

View file

@ -47,7 +47,7 @@ ynh_mysql_execute_as_root() {
database="--database=$database"
fi
mysql -B "$database" <<<"$sql"
mysql -B "$database" <<< "$sql"
}
# Execute a command from a file as root user
@ -71,7 +71,7 @@ ynh_mysql_execute_file_as_root() {
database="--database=$database"
fi
mysql -B "$database" <"$file"
mysql -B "$database" < "$file"
}
# Create a database and grant optionnaly privilegies to a user
@ -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
}

View file

@ -79,7 +79,7 @@ ynh_validate_ip() {
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1
python3 /dev/stdin <<EOF
python3 /dev/stdin << EOF
import socket
import sys
family = { "4" : socket.AF_INET, "6" : socket.AF_INET6 }

View file

@ -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
@ -53,7 +52,7 @@ ynh_change_url_nginx_config() {
# Make a backup of the original NGINX config file if manually modified
# (nb: this is possibly different from the same instruction called by
# ynh_add_config inside ynh_add_nginx_config because the path may have
# ynh_add_config inside ynh_add_nginx_config because the path may have
# changed if we're changing the domain too...)
local old_nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf
ynh_backup_if_checksum_is_different --file="$old_nginx_conf_path"

View file

@ -174,7 +174,7 @@ ynh_permission_exists() {
ynh_handle_getopts_args "$@"
yunohost user permission list "$app" --output-as json --quiet \
| jq -e --arg perm "$app.$permission" '.permissions[$perm]' >/dev/null
| jq -e --arg perm "$app.$permission" '.permissions[$perm]' > /dev/null
}
# Redefine the url associated to a permission
@ -342,7 +342,7 @@ ynh_permission_has_user() {
# Check both allowed and corresponding_users sections in the json
for section in "allowed" "corresponding_users"; do
if yunohost user permission info "$app.$permission" --output-as json --quiet \
| jq -e --arg user $user --arg section $section '.[$section] | index($user)' >/dev/null; then
| jq -e --arg user $user --arg section $section '.[$section] | index($user)' > /dev/null; then
return 0
fi
done

View file

@ -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}
@ -11,19 +11,19 @@ YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
#
# Case 1 (recommended) : your provided a snippet conf/extra_php-fpm.conf
#
# The actual PHP configuration will be automatically generated,
# The actual PHP configuration will be automatically generated,
# and your extra_php-fpm.conf will be appended (typically contains PHP upload limits)
#
# The resulting configuration will be deployed to the appropriate place, /etc/php/$phpversion/fpm/pool.d/$app.conf
#
# Performance-related options in the PHP conf, such as :
# Performance-related options in the PHP conf, such as :
# pm.max_children, pm.start_servers, pm.min_spare_servers pm.max_spare_servers
# are computed from two parameters called "usage" and "footprint" which can be set to low/medium/high. (cf details below)
#
# If you wish to tweak those, please initialize the settings `fpm_usage` and `fpm_footprint`
# If you wish to tweak those, please initialize the settings `fpm_usage` and `fpm_footprint`
# *prior* to calling this helper. Otherwise, "low" will be used as a default for both values.
#
# Otherwise, if you want the user to have control over these, we encourage to create a config panel
# Otherwise, if you want the user to have control over these, we encourage to create a config panel
# (which should ultimately be standardized by the core ...)
#
# Case 2 (deprecate) : you provided an entire conf/php-fpm.conf
@ -33,7 +33,7 @@ YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
# The resulting configuration will be deployed to the appropriate place, /etc/php/$phpversion/fpm/pool.d/$app.conf
#
# ----------------------
#
#
# fpm_footprint: Memory footprint of the service (low/medium/high).
# low - Less than 20 MB of RAM by pool.
# medium - Between 20 MB and 40 MB of RAM by pool.
@ -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
local fpm_service="php${phpversion}-fpm"
local fpm_config_dir="/etc/php/$phpversion/fpm"
# 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"
@ -166,37 +197,80 @@ pm = __PHP_PM__
pm.max_children = __PHP_MAX_CHILDREN__
pm.max_requests = 500
request_terminate_timeout = 1d
" >"$phpfpm_path"
" > "$phpfpm_path"
if [ "$php_pm" = "dynamic" ]; then
echo "
pm.start_servers = __PHP_START_SERVERS__
pm.min_spare_servers = __PHP_MIN_SPARE_SERVERS__
pm.max_spare_servers = __PHP_MAX_SPARE_SERVERS__
" >>"$phpfpm_path"
" >> "$phpfpm_path"
elif [ "$php_pm" = "ondemand" ]; then
echo "
pm.process_idle_timeout = 10s
" >>"$phpfpm_path"
" >> "$phpfpm_path"
fi
# Concatene the extra config.
if [ -e $YNH_APP_BASEDIR/conf/extra_php-fpm.conf ]; then
cat $YNH_APP_BASEDIR/conf/extra_php-fpm.conf >>"$phpfpm_path"
cat $YNH_APP_BASEDIR/conf/extra_php-fpm.conf >> "$phpfpm_path"
fi
fi
local finalphpconf="$fpm_config_dir/pool.d/$app.conf"
ynh_add_config --template="$phpfpm_path" --destination="$finalphpconf"
# 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
ynh_secure_remove --file="$finalphpconf"
ynh_die --message="The new configuration broke php-fpm?"
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
ynh_secure_remove --file="$finalphpconf"
ynh_die --message="The new configuration broke php-fpm?"
fi
ynh_systemd_action --service_name=$fpm_service --action=reload
fi
ynh_systemd_action --service_name=$fpm_service --action=reload
}
# 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"
ynh_systemd_action --service_name=$fpm_service --action=reload
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

View file

@ -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
#
@ -51,7 +51,7 @@ ynh_psql_execute_as_root() {
fi
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
$database <<<"$sql"
$database <<< "$sql"
}
# Execute a command from a file as root user
@ -76,7 +76,7 @@ ynh_psql_execute_file_as_root() {
fi
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
$database <"$file"
$database < "$file"
}
# Create a database and grant optionnaly privilegies to a user
@ -199,10 +199,9 @@ ynh_psql_database_exists() {
# if psql is not there, we cannot check the db
# though it could exists.
if ! command -v psql
then
ynh_print_err -m "PostgreSQL is not installed, impossible to check for db existence."
return 1
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
return 1
else

View file

@ -5,27 +5,25 @@
# usage: ynh_redis_get_free_db
# | returns: the database number to use
ynh_redis_get_free_db() {
local result max db
result=$(redis-cli INFO keyspace)
local result max db
result=$(redis-cli INFO keyspace)
# get the num
max=$(cat /etc/redis/redis.conf | grep ^databases | grep -Eow "[0-9]+")
# get the num
max=$(cat /etc/redis/redis.conf | grep ^databases | grep -Eow "[0-9]+")
db=0
# default Debian setting is 15 databases
for i in $(seq 0 "$max")
do
if ! echo "$result" | grep -q "db$i"
then
db=$i
break 1
fi
db=-1
done
db=0
# default Debian setting is 15 databases
for i in $(seq 0 "$max"); do
if ! echo "$result" | grep -q "db$i"; then
db=$i
break 1
fi
db=-1
done
test "$db" -eq -1 && ynh_die --message="No available Redis databases..."
test "$db" -eq -1 && ynh_die --message="No available Redis databases..."
echo "$db"
echo "$db"
}
# Create a master password and set up global settings
@ -34,6 +32,6 @@ ynh_redis_get_free_db() {
# usage: ynh_redis_remove_db database
# | arg: database - the database to erase
ynh_redis_remove_db() {
local db=$1
redis-cli -n "$db" flushdb
local db=$1
redis-cli -n "$db" flushdb
}

View file

@ -8,8 +8,8 @@ export RBENV_ROOT="$rbenv_install_dir"
export rbenv_root="$rbenv_install_dir"
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
build_ruby_dependencies="libjemalloc-dev curl build-essential libreadline-dev zlib1g-dev libsqlite3-dev libssl-dev libxml2-dev libxslt-dev autoconf automake bison libtool"
build_pkg_dependencies="${build_pkg_dependencies:-} $build_ruby_dependencies"
build_ruby_dependencies="libjemalloc-dev curl build-essential libreadline-dev zlib1g-dev libsqlite3-dev libssl-dev libxml2-dev libxslt-dev autoconf automake bison libtool"
build_pkg_dependencies="${build_pkg_dependencies:-} $build_ruby_dependencies"
fi
# Load the version of Ruby for an app, and set variables.
@ -50,7 +50,7 @@ fi
# usage: ynh_use_ruby
#
# Requires YunoHost version 3.2.2 or higher.
ynh_use_ruby () {
ynh_use_ruby() {
ruby_version=$(ynh_app_setting_get --app=$app --key=ruby_version)
# Get the absolute path of this version of Ruby
@ -75,7 +75,7 @@ ynh_use_ruby () {
# Sets the local application-specific Ruby version
pushd ${install_dir:-$final_path}
$rbenv_install_dir/bin/rbenv local $ruby_version
$rbenv_install_dir/bin/rbenv local $ruby_version
popd
}
@ -95,10 +95,10 @@ ynh_use_ruby () {
# | arg: -v, --ruby_version= - Version of ruby to install.
#
# Requires YunoHost version 3.2.2 or higher.
ynh_install_ruby () {
ynh_install_ruby() {
# Declare an array to define the options of this helper.
local legacy_args=v
local -A args_array=( [v]=ruby_version= )
local -A args_array=([v]=ruby_version=)
local ruby_version
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
@ -117,31 +117,31 @@ ynh_install_ruby () {
rbenv="$(command -v rbenv $rbenv_install_dir/bin/rbenv | grep "$rbenv_install_dir/bin/rbenv" | head -1)"
if [ -n "$rbenv" ]; then
pushd "${rbenv%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/rbenv.git"; then
ynh_print_info --message="Updating rbenv..."
git pull -q --tags origin master
ynh_ruby_try_bash_extension
else
ynh_print_info --message="Reinstalling rbenv..."
cd ..
ynh_secure_remove --file=$rbenv_install_dir
mkdir -p $rbenv_install_dir
cd $rbenv_install_dir
git init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master
ynh_ruby_try_bash_extension
rbenv=$rbenv_install_dir/bin/rbenv
fi
popd
else
ynh_print_info --message="Installing rbenv..."
pushd $rbenv_install_dir
if git remote -v 2> /dev/null | grep "https://github.com/rbenv/rbenv.git"; then
ynh_print_info --message="Updating rbenv..."
git pull -q --tags origin master
ynh_ruby_try_bash_extension
else
ynh_print_info --message="Reinstalling rbenv..."
cd ..
ynh_secure_remove --file=$rbenv_install_dir
mkdir -p $rbenv_install_dir
cd $rbenv_install_dir
git init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master
ynh_ruby_try_bash_extension
rbenv=$rbenv_install_dir/bin/rbenv
fi
popd
else
ynh_print_info --message="Installing rbenv..."
pushd $rbenv_install_dir
git init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master
ynh_ruby_try_bash_extension
rbenv=$rbenv_install_dir/bin/rbenv
popd
fi
@ -150,10 +150,10 @@ ynh_install_ruby () {
ruby_build="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-install rbenv-install | head -1)"
if [ -n "$ruby_build" ]; then
pushd "${ruby_build%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/ruby-build.git"; then
ynh_print_info --message="Updating ruby-build..."
git pull -q origin master
fi
if git remote -v 2> /dev/null | grep "https://github.com/rbenv/ruby-build.git"; then
ynh_print_info --message="Updating ruby-build..."
git pull -q origin master
fi
popd
else
ynh_print_info --message="Installing ruby-build..."
@ -163,10 +163,10 @@ ynh_install_ruby () {
rbenv_alias="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-alias rbenv-alias | head -1)"
if [ -n "$rbenv_alias" ]; then
pushd "${rbenv_alias%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then
ynh_print_info --message="Updating rbenv-aliases..."
git pull -q origin master
fi
if git remote -v 2> /dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then
ynh_print_info --message="Updating rbenv-aliases..."
git pull -q origin master
fi
popd
else
ynh_print_info --message="Installing rbenv-aliases..."
@ -176,10 +176,10 @@ ynh_install_ruby () {
rbenv_latest="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-latest rbenv-latest | head -1)"
if [ -n "$rbenv_latest" ]; then
pushd "${rbenv_latest%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then
ynh_print_info --message="Updating xxenv-latest..."
git pull -q origin master
fi
if git remote -v 2> /dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then
ynh_print_info --message="Updating xxenv-latest..."
git pull -q origin master
fi
popd
else
ynh_print_info --message="Installing xxenv-latest..."
@ -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
@ -222,7 +221,7 @@ ynh_install_ruby () {
ynh_cleanup_ruby
# Set environment for Ruby users
echo "#rbenv
echo "#rbenv
export RBENV_ROOT=$rbenv_install_dir
export PATH=\"$rbenv_install_dir/bin:$PATH\"
eval \"\$(rbenv init -)\"
@ -237,7 +236,7 @@ eval \"\$(rbenv init -)\"
# This helper will also cleanup Ruby versions
#
# usage: ynh_remove_ruby
ynh_remove_ruby () {
ynh_remove_ruby() {
local ruby_version=$(ynh_app_setting_get --app=$app --key=ruby_version)
# Load rbenv path in PATH
@ -262,34 +261,29 @@ ynh_remove_ruby () {
# If no app uses Ruby, rbenv will be also removed.
#
# usage: ynh_cleanup_ruby
ynh_cleanup_ruby () {
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"
@ -298,9 +292,9 @@ ynh_cleanup_ruby () {
}
ynh_ruby_try_bash_extension() {
if [ -x src/configure ]; then
src/configure && make -C src || {
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
}
fi
if [ -x src/configure ]; then
src/configure && make -C src || {
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
}
fi
}

View file

@ -18,7 +18,11 @@ ynh_app_setting_get() {
ynh_handle_getopts_args "$@"
app="${app:-$_globalapp}"
ynh_app_setting "get" "$app" "$key"
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}"
ynh_app_setting "set" "$app" "$key" "$value"
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}"
ynh_app_setting "delete" "$app" "$key"
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
@ -108,7 +120,7 @@ ynh_app_setting_delete() {
#
ynh_app_setting() {
set +o xtrace # set +x
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python3 - <<EOF
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python3 - << EOF
import os, yaml, sys
app, action = os.environ['APP'], os.environ['ACTION'].lower()
key, value = os.environ['KEY'], os.environ.get('VALUE', None)

View file

@ -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
@ -263,11 +249,11 @@ ynh_setup_source() {
# Apply patches
if [ -d "$YNH_APP_BASEDIR/sources/patches/" ]; then
local patches_folder=$(realpath $YNH_APP_BASEDIR/sources/patches/)
if (($(find $patches_folder -type f -name "${source_id}-*.patch" 2>/dev/null | wc --lines) > "0")); then
if (($(find $patches_folder -type f -name "${source_id}-*.patch" 2> /dev/null | wc --lines) > "0")); then
pushd "$dest_dir"
for p in $patches_folder/${source_id}-*.patch; do
echo $p
patch --strip=1 <$p || ynh_print_warn --message="Packagers /!\\ patch $p failed to apply"
patch --strip=1 < $p || ynh_print_warn --message="Packagers /!\\ patch $p failed to apply"
done
popd
fi

View file

@ -21,7 +21,7 @@ ynh_string_random() {
length=${length:-24}
filter=${filter:-'A-Za-z0-9'}
dd if=/dev/urandom bs=1 count=1000 2>/dev/null \
dd if=/dev/urandom bs=1 count=1000 2> /dev/null \
| tr --complement --delete "$filter" \
| sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p'
}

View file

@ -94,12 +94,12 @@ ynh_systemd_action() {
# Following the starting of the app in its log
if [ "$log_path" == "systemd" ]; then
# Read the systemd journal
journalctl --unit=$service_name --follow --since=-0 --quiet >"$templog" &
journalctl --unit=$service_name --follow --since=-0 --quiet > "$templog" &
# Get the PID of the journalctl command
local pid_tail=$!
else
# Read the specified log file
tail --follow=name --retry --lines=0 "$log_path" >"$templog" 2>&1 &
tail --follow=name --retry --lines=0 "$log_path" > "$templog" 2>&1 &
# Get the PID of the tail command
local pid_tail=$!
fi
@ -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

View file

@ -17,7 +17,7 @@ ynh_system_user_exists() {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
getent passwd "$username" &>/dev/null
getent passwd "$username" &> /dev/null
}
# Check if a group exists on the system
@ -37,7 +37,7 @@ ynh_system_group_exists() {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
getent group "$group" &>/dev/null
getent group "$group" &> /dev/null
}
# Create a system user

View file

@ -39,11 +39,11 @@
# This option is meant for advanced use-cases where the "simple" templating
# mode ain't enough because you need conditional blocks or loops.
#
# For a full documentation of jinja's syntax you can refer to:
# For a full documentation of jinja's syntax you can refer to:
# https://jinja.palletsprojects.com/en/3.1.x/templates/
#
# Note that in YunoHost context, all variables are from shell variables and therefore are strings
#
#
# ##### Keeping track of manual changes by the admin
#
# The helper will verify the checksum and backup the destination file
@ -83,10 +83,9 @@ 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)
j2 "$template_path" -f env -o $destination
)
@ -267,7 +266,7 @@ ynh_read_var_in_file() {
var_part+='\s*'
# Extract the part after assignation sign
local expression_with_comment="$((tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
local expression_with_comment="$( (tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
echo YNH_NULL
@ -346,7 +345,7 @@ ynh_write_var_in_file() {
var_part+='\s*'
# Extract the part after assignation sign
local expression_with_comment="$((tail +$after_line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
local expression_with_comment="$( (tail +$after_line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
return 1
@ -403,5 +402,5 @@ ynh_render_template() {
# Taken from https://stackoverflow.com/a/35009576
python3 -c 'import os, sys, jinja2; sys.stdout.write(
jinja2.Template(sys.stdin.read()
).render(os.environ));' <$template_path >$output_path
).render(os.environ));' < $template_path > $output_path
}

View file

@ -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
@ -39,7 +38,7 @@ ynh_exit_properly() {
# Small tempo to avoid the next message being mixed up with other DEBUG messages
sleep 0.5
if type -t ynh_clean_setup >/dev/null; then # Check if the function exist in the app script.
if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script.
ynh_clean_setup # Call the function to do specific cleaning for the app.
fi
@ -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
chmod o-rwx $target
chmod g-w $target
chown -R root:root $target
if ynh_system_user_exists $app; then
chown $app:$app $target
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() {
@ -415,7 +412,7 @@ ynh_user_exists() {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
yunohost user list --output-as json --quiet | jq -e ".users.\"${username}\"" >/dev/null
yunohost user list --output-as json --quiet | jq -e ".users.\"${username}\"" > /dev/null
}
# Retrieve a YunoHost user information

View file

@ -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
@ -100,7 +95,7 @@ ynh_apt_install_dependencies() {
# For some reason, dpkg-deb insists for folder perm to be 755 and sometimes it's 777 o_O?
chmod -R 755 ${TMPDIR}/${app_ynh_deps}
cat >${TMPDIR}/${app_ynh_deps}/DEBIAN/control <<EOF
cat > ${TMPDIR}/${app_ynh_deps}/DEBIAN/control << EOF
Section: misc
Priority: optional
Package: ${app_ynh_deps}
@ -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,11 +198,13 @@ 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
if (("${#repo_parts[@]}" > 0)); then
component="${repo_parts[*]:$index}"
fi
@ -280,7 +274,7 @@ _ynh_wait_dpkg_free() {
# With seq 1 17, timeout will be almost 30 minutes
for try in $(seq 1 17); do
# Check if /var/lib/dpkg/lock is used by another process
if lsof /var/lib/dpkg/lock >/dev/null; then
if lsof /var/lib/dpkg/lock > /dev/null; then
echo "apt is already in use..."
# Sleep an exponential time at each round
sleep $((try * try))
@ -298,7 +292,7 @@ _ynh_wait_dpkg_free() {
set -o xtrace # set -x
return 1
fi
done 9<<<"$(ls -1 $dpkg_dir)"
done 9<<< "$(ls -1 $dpkg_dir)"
set -o xtrace # set -x
return 0
fi
@ -310,14 +304,14 @@ _ynh_wait_dpkg_free() {
# Check either a package is installed or not
_ynh_apt_package_is_installed() {
local package=$1
dpkg-query --show --showformat='${db:Status-Status}' "$package" 2>/dev/null \
| grep --quiet "^installed$" &>/dev/null
dpkg-query --show --showformat='${db:Status-Status}' "$package" 2> /dev/null \
| grep --quiet "^installed$" &> /dev/null
}
# Return the installed version of an apt package, if installed
_ynh_apt_package_version() {
if _ynh_apt_package_is_installed "$package"; then
dpkg-query --show --showformat='${Version}' "$package" 2>/dev/null
dpkg-query --show --showformat='${Version}' "$package" 2> /dev/null
else
echo ''
fi

View file

@ -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
@ -83,7 +81,7 @@ ynh_backup() {
# ==============================================================================
local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g')
local dest=$(echo "${dest_path}" | sed --regexp-extended 's/"/\"\"/g')
echo "\"${src}\",\"${dest}\"" >>"${YNH_BACKUP_CSV}"
echo "\"${src}\",\"${dest}\"" >> "${YNH_BACKUP_CSV}"
# ==============================================================================
@ -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

View file

@ -38,8 +38,8 @@ ynh_composer_exec() {
local workdir="${composer_workdir:-$install_dir}"
COMPOSER_HOME="$workdir/.composer" \
COMPOSER_MEMORY_LIMIT=-1 \
sudo -E -u "${composer_user:-$app}" \
php${php_version} "$workdir/composer.phar" $@ \
COMPOSER_MEMORY_LIMIT=-1 \
sudo -E -u "${composer_user:-$app}" \
php${php_version} "$workdir/composer.phar" $@ \
-d "$workdir" --no-interaction --no-ansi 2>&1
}

View file

@ -6,11 +6,11 @@ _ynh_app_config_get_one() {
local bind="$3"
local getter="get__${short_setting}"
# Get value from getter if exists
if type -t $getter 2>/dev/null | grep -q '^function$' 2>/dev/null; then
if type -t $getter 2> /dev/null | grep -q '^function$' 2> /dev/null; then
old[$short_setting]="$($getter)"
formats[${short_setting}]="yaml"
elif [[ "$bind" == *"("* ]] && type -t "get__${bind%%(*}" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
elif [[ "$bind" == *"("* ]] && type -t "get__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
old[$short_setting]="$("get__${bind%%(*}" $short_setting $type $bind)"
formats[${short_setting}]="yaml"
@ -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
@ -59,10 +59,10 @@ _ynh_app_config_apply_one() {
local type="${types[$short_setting]}"
if [ "${changed[$short_setting]}" == "true" ]; then
# Apply setter if exists
if type -t $setter 2>/dev/null | grep -q '^function$' 2>/dev/null; then
if type -t $setter 2> /dev/null | grep -q '^function$' 2> /dev/null; then
$setter
elif [[ "$bind" == *"("* ]] && type -t "set__${bind%%(*}" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
elif [[ "$bind" == *"("* ]] && type -t "set__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
"set__${bind%%(*}" $short_setting $type $bind
elif [[ "$bind" == "null" ]]; then
@ -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
echo "${!short_setting}" > "$bind_file"
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,69 +132,17 @@ _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"
IFS='|' read short_setting type bind <<< "$line"
binds[${short_setting}]="$bind"
types[${short_setting}]="$type"
file_hash[${short_setting}]=""
formats[${short_setting}]=""
ynh_app_config_get_one $short_setting $type $bind
done
}
_ynh_app_config_apply() {
@ -267,9 +212,9 @@ _ynh_app_config_validate() {
for short_setting in "${!old[@]}"; do
[[ "${changed[$short_setting]}" == "false" ]] && continue
local result=""
if type -t validate__$short_setting | grep -q '^function$' 2>/dev/null; then
if type -t validate__$short_setting | grep -q '^function$' 2> /dev/null; then
result="$(validate__$short_setting)"
elif [[ "$bind" == *"("* ]] && type -t "validate__${bind%%(*}" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
elif [[ "$bind" == *"("* ]] && type -t "validate__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
"validate__${bind%%(*}" $short_setting
fi
if [ -n "$result" ]; then
@ -324,7 +269,7 @@ ynh_app_config_apply() {
ynh_app_action_run() {
local runner="run__$1"
# Get value from getter if exists
if type -t "$runner" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
if type -t "$runner" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
$runner
#ynh_return "result:"
#ynh_return "$(echo "${result}" | sed 's/^/ /g')"
@ -342,22 +287,23 @@ ynh_app_config_run() {
declare -Ag formats=()
case $1 in
show)
ynh_app_config_get
ynh_app_config_show
;;
apply)
max_progression=4
ynh_script_progression "Reading config panel description and current configuration..."
ynh_app_config_get
show)
ynh_app_config_get
ynh_app_config_show
;;
apply)
max_progression=4
ynh_script_progression "Reading config panel description and current configuration..."
ynh_app_config_get
ynh_app_config_validate
ynh_app_config_validate
ynh_script_progression "Applying the new configuration..."
ynh_app_config_apply
ynh_script_progression "Configuration of $app completed"
;;
*)
ynh_app_action_run $1
ynh_script_progression "Applying the new configuration..."
ynh_app_config_apply
ynh_script_progression "Configuration of $app completed"
;;
*)
ynh_app_action_run $1
;;
esac
}

View file

@ -68,7 +68,7 @@ port = http,https
filter = __APP__
logpath = __LOGPATH__
maxretry = 5
" >"$YNH_APP_BASEDIR/conf/f2b_jail.conf"
" > "$YNH_APP_BASEDIR/conf/f2b_jail.conf"
echo "
[INCLUDES]
@ -76,7 +76,7 @@ before = common.conf
[Definition]
failregex = __FAILREGEX__
ignoreregex =
" >"$YNH_APP_BASEDIR/conf/f2b_filter.conf"
" > "$YNH_APP_BASEDIR/conf/f2b_filter.conf"
fi
ynh_config_add --template="f2b_jail.conf" --destination="/etc/fail2ban/jail.d/$app.conf"

View file

@ -20,7 +20,7 @@
# | arg: $@ - Simply "$@" to tranfert all the positionnal arguments to the function
#
# This helper need an array, named "args_array" with all the arguments used by the helper
# that want to use ynh_handle_getopts_args
# that want to use ynh_handle_getopts_args
# Be carreful, this array has to be an associative array, as the following example:
# local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
# Let's explain this array:
@ -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
@ -182,6 +181,6 @@ ynh_handle_getopts_args() {
# Call parse_arg and pass the modified list of args as an array of arguments.
parse_arg "${arguments[@]}"
eval "$xtrace_enable"
}

View file

@ -23,7 +23,7 @@ _ynh_load_go_in_path_and_other_tweaks() {
# Sets the local application-specific go version
pushd ${install_dir}
$GOENV_INSTALL_DIR/bin/goenv local $go_version
$GOENV_INSTALL_DIR/bin/goenv local $go_version
popd
}
@ -39,7 +39,7 @@ _ynh_load_go_in_path_and_other_tweaks() {
# - `$go_dir` (the directory containing the specific go version)
#
# This helper also creates a /etc/profile.d/goenv.sh that configures PATH environment for goenv
ynh_go_install () {
ynh_go_install() {
[[ -n "${go_version:-}" ]] || ynh_die "\$go_version should be defined prior to calling ynh_go_install"
@ -55,33 +55,33 @@ ynh_go_install () {
# Install or update goenv
mkdir -p $GOENV_INSTALL_DIR
pushd "$GOENV_INSTALL_DIR"
if ! [ -x "$GOENV_INSTALL_DIR/bin/goenv" ]; then
ynh_print_info "Downloading goenv..."
git init -q
git remote add origin https://github.com/syndbg/goenv.git
else
ynh_print_info "Updating goenv..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
_ynh_go_try_bash_extension
goenv=$GOENV_INSTALL_DIR/bin/goenv
if ! [ -x "$GOENV_INSTALL_DIR/bin/goenv" ]; then
ynh_print_info "Downloading goenv..."
git init -q
git remote add origin https://github.com/syndbg/goenv.git
else
ynh_print_info "Updating goenv..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
_ynh_go_try_bash_extension
goenv=$GOENV_INSTALL_DIR/bin/goenv
popd
# Install or update xxenv-latest
mkdir -p "$GOENV_INSTALL_DIR/plugins/xxenv-latest"
pushd "$GOENV_INSTALL_DIR/plugins/xxenv-latest"
if ! [ -x "$GOENV_INSTALL_DIR/plugins/xxenv-latest/bin/goenv-latest" ]; then
ynh_print_info "Downloading xxenv-latest..."
git init -q
git remote add origin https://github.com/momo-lab/xxenv-latest.git
else
ynh_print_info "Updating xxenv-latest..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
if ! [ -x "$GOENV_INSTALL_DIR/plugins/xxenv-latest/bin/goenv-latest" ]; then
ynh_print_info "Downloading xxenv-latest..."
git init -q
git remote add origin https://github.com/momo-lab/xxenv-latest.git
else
ynh_print_info "Updating xxenv-latest..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
popd
# Enable caching
@ -109,7 +109,7 @@ ynh_go_install () {
_ynh_go_cleanup
# Set environment for Go users
echo "#goenv
echo "#goenv
export GOENV_ROOT=$GOENV_INSTALL_DIR
export PATH=\"$GOENV_INSTALL_DIR/bin:$PATH\"
eval \"\$(goenv init -)\"
@ -126,7 +126,7 @@ eval \"\$(goenv init -)\"
# This helper will also cleanup Go versions
#
# usage: ynh_go_remove
ynh_go_remove () {
ynh_go_remove() {
local go_version=$(ynh_app_setting_get --key="go_version")
# Load goenv path in PATH
@ -151,34 +151,29 @@ ynh_go_remove () {
# If no app uses Go, goenv will be also removed.
#
# usage: _ynh_go_cleanup
_ynh_go_cleanup () {
_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"
@ -187,9 +182,9 @@ _ynh_go_cleanup () {
}
_ynh_go_try_bash_extension() {
if [ -x src/configure ]; then
src/configure && make -C src || {
ynh_print_info "Optional bash extension failed to build, but things will still work normally."
}
fi
if [ -x src/configure ]; then
src/configure && make -C src || {
ynh_print_info "Optional bash extension failed to build, but things will still work normally."
}
fi
}

View file

@ -5,11 +5,9 @@
# usage: ynh_die "Some message"
ynh_die() {
set +o xtrace # set +x
if [[ -n "${1:-}" ]]
then
if [[ -n "${YNH_STDRETURN:-}" ]]
then
python3 -c 'import yaml, sys; print(yaml.dump({"error": sys.stdin.read()}))' <<< "${1:-}" >>"$YNH_STDRETURN"
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
fi
@ -51,7 +49,7 @@ ynh_exec_and_print_stderr_only_if_error() {
rc=0
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
"$@" 2> "$logfile" || rc="$?"
if (( rc != 0 )); then
if ((rc != 0)); then
cat "$logfile" >&2
ynh_safe_rm "$logfile"
return "$rc"
@ -63,7 +61,7 @@ ynh_exec_and_print_stderr_only_if_error() {
#
# usage: ynh_return somedata
ynh_return() {
echo "$1" >>"$YNH_STDRETURN"
echo "$1" >> "$YNH_STDRETURN"
}
# Initial definitions for ynh_script_progression
@ -105,10 +103,9 @@ 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
effective_progression=$progress_scale
expected_progression=0
if grep -qw 'completed' <<< "$1"; then
effective_progression=$progress_scale
expected_progression=0
fi
# left_progression is the progression not yet done
local left_progression="$(($progress_scale - $effective_progression - $expected_progression))"

View file

@ -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
@ -32,7 +31,7 @@ ynh_config_add_logrotate() {
done
local tempconf="$(mktemp)"
cat << EOF >$tempconf
cat << EOF > $tempconf
$logfile {
# Rotate if the logfile exceeds 100Mo
size 100M
@ -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

View file

@ -12,16 +12,15 @@
#
ynh_mongo_exec() {
# ============ Argument parsing =============
local -A args_array=( [d]=database= [c]=command= )
local -A args_array=([d]=database= [c]=command=)
local database
local command
ynh_handle_getopts_args "$@"
database="${database:-}"
# ===========================================
if [ -n "$database" ]
then
mongosh --quiet <<EOF
if [ -n "$database" ]; then
mongosh --quiet << EOF
use $database
${command}
quit()
@ -44,7 +43,7 @@ EOF
#
ynh_mongo_drop_db() {
# ============ Argument parsing =============
local -A args_array=( [d]=database= )
local -A args_array=([d]=database=)
local database
ynh_handle_getopts_args "$@"
# ===========================================
@ -63,7 +62,7 @@ ynh_mongo_drop_db() {
#
ynh_mongo_dump_db() {
# ============ Argument parsing =============
local -A args_array=( [d]=database= )
local -A args_array=([d]=database=)
local database
ynh_handle_getopts_args "$@"
# ===========================================
@ -83,7 +82,7 @@ ynh_mongo_dump_db() {
#
ynh_mongo_create_user() {
# ============ Argument parsing =============
local -A args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
local db_user
local db_name
local db_pwd
@ -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
@ -129,7 +127,7 @@ ynh_mongo_database_exists() {
#
ynh_mongo_restore_db() {
# ============ Argument parsing =============
local -A args_array=( [d]=database= )
local -A args_array=([d]=database=)
local database
ynh_handle_getopts_args "$@"
# ===========================================
@ -148,7 +146,7 @@ ynh_mongo_restore_db() {
#
ynh_mongo_drop_user() {
# ============ Argument parsing =============
local -A args_array=( [u]=db_user= [n]=db_name= )
local -A args_array=([u]=db_user= [n]=db_name=)
local db_user
local db_name
ynh_handle_getopts_args "$@"
@ -170,7 +168,7 @@ ynh_mongo_drop_user() {
#
ynh_mongo_setup_db() {
# ============ Argument parsing =============
local -A args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
local db_user
local db_name
db_pwd=""
@ -197,14 +195,14 @@ ynh_mongo_setup_db() {
#
ynh_mongo_remove_db() {
# ============ Argument parsing =============
local -A args_array=( [u]=db_user= [n]=db_name= )
local -A args_array=([u]=db_user= [n]=db_name=)
local db_user
local db_name
ynh_handle_getopts_args "$@"
# ===========================================
if ynh_mongo_database_exists --database=$db_name; then # Check if the database exists
ynh_mongo_drop_db --database=$db_name # Remove the database
if ynh_mongo_database_exists --database=$db_name; then # Check if the database exists
ynh_mongo_drop_db --database=$db_name # Remove the database
else
ynh_print_warn "Database $db_name not found"
fi
@ -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

View file

@ -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
@ -47,7 +46,7 @@ ynh_config_change_url_nginx() {
# Make a backup of the original NGINX config file if manually modified
# (nb: this is possibly different from the same instruction called by
# ynh_config_add inside ynh_config_add_nginx because the path may have
# ynh_config_add inside ynh_config_add_nginx because the path may have
# changed if we're changing the domain too...)
local old_nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf
ynh_backup_if_checksum_is_different "$old_nginx_conf_path"

View file

@ -169,7 +169,7 @@ ynh_permission_exists() {
# ===========================================
yunohost user permission list "$app" --output-as json --quiet \
| jq -e --arg perm "$app.$permission" '.permissions[$perm]' >/dev/null
| jq -e --arg perm "$app.$permission" '.permissions[$perm]' > /dev/null
}
# Redefine the url associated to a permission
@ -301,7 +301,7 @@ ynh_permission_has_user() {
# Check both allowed and corresponding_users sections in the json
for section in "allowed" "corresponding_users"; do
if yunohost user permission info "$app.$permission" --output-as json --quiet \
| jq -e --arg user $user --arg section $section '.[$section] | index($user)' >/dev/null; then
| jq -e --arg user $user --arg section $section '.[$section] | index($user)' > /dev/null; then
return 0
fi
done

View file

@ -59,9 +59,9 @@ ynh_config_add_phpfpm() {
# Apps willing to tweak these should use ynh_setting_set_default_value (in install and upgrade?)
#
local php_upload_max_filesize=${php_upload_max_filesize:-50M}
local php_process_management=${php_process_management:-ondemand} # alternatively 'dynamic' or 'static'
local php_process_management=${php_process_management:-ondemand} # alternatively 'dynamic' or 'static'
local php_max_children=${php_max_children:-$(_default_php_max_children)}
local php_memory_limit=${php_memory_limit:-128M} # default value is from global php.ini
local php_memory_limit=${php_memory_limit:-128M} # default value is from global php.ini
local phpfpm_template=$(mktemp)
cat << EOF > $phpfpm_template
@ -102,7 +102,7 @@ EOF
# Concatene the extra config
if [ -e $YNH_APP_BASEDIR/conf/extra_php-fpm.conf ]; then
cat $YNH_APP_BASEDIR/conf/extra_php-fpm.conf >>"$phpfpm_template"
cat $YNH_APP_BASEDIR/conf/extra_php-fpm.conf >> "$phpfpm_template"
fi
# Make sure the fpm pool dir exists
@ -111,7 +111,7 @@ EOF
ynh_config_add --template="$phpfpm_template" --destination="/etc/php/$php_version/fpm/pool.d/$app.conf"
# Validate that the new php conf doesn't break php-fpm entirely
if ! php-fpm${php_version} --test 2>/dev/null; then
if ! php-fpm${php_version} --test 2> /dev/null; then
php-fpm${php_version} --test || true
ynh_safe_rm "/etc/php/$php_version/fpm/pool.d/$app.conf"
ynh_die "The new configuration broke php-fpm?"

View file

@ -5,27 +5,25 @@
# usage: ynh_redis_get_free_db
# | returns: the database number to use
ynh_redis_get_free_db() {
local result max db
result=$(redis-cli INFO keyspace)
local result max db
result=$(redis-cli INFO keyspace)
# get the num
max=$(cat /etc/redis/redis.conf | grep ^databases | grep -Eow "[0-9]+")
# get the num
max=$(cat /etc/redis/redis.conf | grep ^databases | grep -Eow "[0-9]+")
db=0
# default Debian setting is 15 databases
for i in $(seq 0 "$max")
do
if ! echo "$result" | grep -q "db$i"
then
db=$i
break 1
fi
db=-1
done
db=0
# default Debian setting is 15 databases
for i in $(seq 0 "$max"); do
if ! echo "$result" | grep -q "db$i"; then
db=$i
break 1
fi
db=-1
done
test "$db" -eq -1 && ynh_die "No available Redis databases..."
test "$db" -eq -1 && ynh_die "No available Redis databases..."
echo "$db"
echo "$db"
}
# Create a master password and set up global settings
@ -34,6 +32,6 @@ ynh_redis_get_free_db() {
# usage: ynh_redis_remove_db database
# | arg: database - the database to erase
ynh_redis_remove_db() {
local db=$1
redis-cli -n "$db" flushdb
local db=$1
redis-cli -n "$db" flushdb
}

View file

@ -25,7 +25,7 @@ _ynh_load_ruby_in_path_and_other_tweaks() {
# Sets the local application-specific Ruby version
pushd ${install_dir}
$RBENV_INSTALL_DIR/bin/rbenv local $ruby_version
$RBENV_INSTALL_DIR/bin/rbenv local $ruby_version
popd
}
@ -41,7 +41,7 @@ _ynh_load_ruby_in_path_and_other_tweaks() {
# - `$ruby_dir`, the directory containing the specific version of ruby, which may be used in the systemd config too (e.g. `ExecStart=__RUBY_DIR__/ruby foo bar`)
#
# This helper also creates a /etc/profile.d/rbenv.sh that configures PATH environment for rbenv
ynh_ruby_install () {
ynh_ruby_install() {
[[ -n "${ruby_version:-}" ]] || ynh_die "\$ruby_version should be defined prior to calling ynh_ruby_install"
@ -59,31 +59,31 @@ ynh_ruby_install () {
rbenv="$(command -v rbenv $RBENV_INSTALL_DIR/bin/rbenv | grep "$RBENV_INSTALL_DIR/bin/rbenv" | head -1)"
if [ -n "$rbenv" ]; then
pushd "${rbenv%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/rbenv.git"; then
echo "Updating rbenv..."
git pull -q --tags origin master
_ynh_ruby_try_bash_extension
else
echo "Reinstalling rbenv..."
cd ..
ynh_safe_rm $RBENV_INSTALL_DIR
mkdir -p $RBENV_INSTALL_DIR
cd $RBENV_INSTALL_DIR
git init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master
_ynh_ruby_try_bash_extension
rbenv=$RBENV_INSTALL_DIR/bin/rbenv
fi
popd
else
echo "Installing rbenv..."
pushd $RBENV_INSTALL_DIR
if git remote -v 2> /dev/null | grep "https://github.com/rbenv/rbenv.git"; then
echo "Updating rbenv..."
git pull -q --tags origin master
_ynh_ruby_try_bash_extension
else
echo "Reinstalling rbenv..."
cd ..
ynh_safe_rm $RBENV_INSTALL_DIR
mkdir -p $RBENV_INSTALL_DIR
cd $RBENV_INSTALL_DIR
git init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master
_ynh_ruby_try_bash_extension
rbenv=$RBENV_INSTALL_DIR/bin/rbenv
fi
popd
else
echo "Installing rbenv..."
pushd $RBENV_INSTALL_DIR
git init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master
_ynh_ruby_try_bash_extension
rbenv=$RBENV_INSTALL_DIR/bin/rbenv
popd
fi
@ -92,10 +92,10 @@ ynh_ruby_install () {
ruby_build="$(command -v "$RBENV_INSTALL_DIR"/plugins/*/bin/rbenv-install rbenv-install | head -1)"
if [ -n "$ruby_build" ]; then
pushd "${ruby_build%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/ruby-build.git"; then
echo "Updating ruby-build..."
git pull -q origin master
fi
if git remote -v 2> /dev/null | grep "https://github.com/rbenv/ruby-build.git"; then
echo "Updating ruby-build..."
git pull -q origin master
fi
popd
else
echo "Installing ruby-build..."
@ -105,10 +105,10 @@ ynh_ruby_install () {
rbenv_alias="$(command -v "$RBENV_INSTALL_DIR"/plugins/*/bin/rbenv-alias rbenv-alias | head -1)"
if [ -n "$rbenv_alias" ]; then
pushd "${rbenv_alias%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then
echo "Updating rbenv-aliases..."
git pull -q origin master
fi
if git remote -v 2> /dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then
echo "Updating rbenv-aliases..."
git pull -q origin master
fi
popd
else
echo "Installing rbenv-aliases..."
@ -118,10 +118,10 @@ ynh_ruby_install () {
rbenv_latest="$(command -v "$RBENV_INSTALL_DIR"/plugins/*/bin/rbenv-latest rbenv-latest | head -1)"
if [ -n "$rbenv_latest" ]; then
pushd "${rbenv_latest%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then
echo "Updating xxenv-latest..."
git pull -q origin master
fi
if git remote -v 2> /dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then
echo "Updating xxenv-latest..."
git pull -q origin master
fi
popd
else
echo "Installing xxenv-latest..."
@ -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
@ -165,7 +164,7 @@ ynh_ruby_install () {
_ynh_ruby_cleanup
# Set environment for Ruby users
echo "#rbenv
echo "#rbenv
export RBENV_ROOT=$RBENV_INSTALL_DIR
export PATH=\"$RBENV_INSTALL_DIR/bin:$PATH\"
eval \"\$(rbenv init -)\"
@ -182,7 +181,7 @@ eval \"\$(rbenv init -)\"
# This helper will also cleanup unused Ruby versions
#
# usage: ynh_ruby_remove
ynh_ruby_remove () {
ynh_ruby_remove() {
[[ -n "${ruby_version:-}" ]] || ynh_die "\$ruby_version should be defined prior to calling ynh_ruby_remove"
@ -208,34 +207,29 @@ ynh_ruby_remove () {
# This helper will check what Ruby version are no more required,
# and uninstall them
# If no app uses Ruby, rbenv will be also removed.
_ynh_ruby_cleanup () {
_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"
@ -244,9 +238,9 @@ _ynh_ruby_cleanup () {
}
_ynh_ruby_try_bash_extension() {
if [ -x src/configure ]; then
src/configure && make -C src 2>&1 || {
ynh_print_info "Optional bash extension failed to build, but things will still work normally."
}
fi
if [ -x src/configure ]; then
src/configure && make -C src 2>&1 || {
ynh_print_info "Optional bash extension failed to build, but things will still work normally."
}
fi
}

View file

@ -98,7 +98,7 @@ ynh_app_setting() {
# Trick to only re-enable debugging if it was set before
local xtrace_enable=$(set +o | grep xtrace)
set +o xtrace # set +x
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python3 - <<EOF
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python3 - << EOF
import os, yaml, sys
app, action = os.environ['APP'], os.environ['ACTION'].lower()
key, value = os.environ['KEY'], os.environ.get('VALUE', None)
@ -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

View file

@ -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
local patches_folder=$(realpath "$YNH_APP_BASEDIR/patches/$source_id")
if [ -d "$patches_folder" ]; then
if [ -d "$YNH_APP_BASEDIR/patches/" ]; then
local patches_folder=$(realpath "$YNH_APP_BASEDIR/patches/$source_id")
pushd "$dest_dir"
for patchfile in "$patches_folder/"*.patch; do
echo "Applying $patchfile"

View file

@ -18,7 +18,7 @@ ynh_string_random() {
filter=${filter:-'A-Za-z0-9'}
# ===========================================
dd if=/dev/urandom bs=1 count=1000 2>/dev/null \
dd if=/dev/urandom bs=1 count=1000 2> /dev/null \
| tr --complement --delete "$filter" \
| sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p'
}

View file

@ -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
@ -84,12 +83,12 @@ ynh_systemctl() {
# Following the starting of the app in its log
if [ "$log_path" == "systemd" ]; then
# Read the systemd journal
journalctl --unit=$service --follow --since=-0 --quiet >"$templog" &
journalctl --unit=$service --follow --since=-0 --quiet > "$templog" &
# Get the PID of the journalctl command
local pid_tail=$!
else
# Read the specified log file
tail --follow=name --retry --lines=0 "$log_path" >"$templog" 2>&1 &
tail --follow=name --retry --lines=0 "$log_path" > "$templog" 2>&1 &
# Get the PID of the tail command
local pid_tail=$!
fi
@ -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

View file

@ -12,7 +12,7 @@ ynh_system_user_exists() {
ynh_handle_getopts_args "$@"
# ===========================================
getent passwd "$username" &>/dev/null
getent passwd "$username" &> /dev/null
}
# Check if a group exists on the system
@ -27,7 +27,7 @@ ynh_system_group_exists() {
ynh_handle_getopts_args "$@"
# ===========================================
getent group "$group" &>/dev/null
getent group "$group" &> /dev/null
}
# Create a system user

View file

@ -29,7 +29,7 @@
# This option is meant for advanced use-cases where the "simple" templating
# mode ain't enough because you need conditional blocks or loops.
#
# For a full documentation of jinja's syntax you can refer to:
# For a full documentation of jinja's syntax you can refer to:
# https://jinja.palletsprojects.com/en/3.1.x/templates/
#
# Note that in YunoHost context, all variables are from shell variables and therefore are strings
@ -70,10 +70,9 @@ 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)
j2 "$template_path" -f env -o $destination
)
@ -216,7 +215,7 @@ ynh_read_var_in_file() {
var_part+='\s*'
# Extract the part after assignation sign
local expression_with_comment="$((tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
local expression_with_comment="$( (tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
echo YNH_NULL
@ -292,7 +291,7 @@ ynh_write_var_in_file() {
var_part+='\s*'
# Extract the part after assignation sign
local expression_with_comment="$((tail +$after_line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
local expression_with_comment="$( (tail +$after_line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
return 1

View file

@ -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
@ -223,31 +220,27 @@ _ynh_apply_default_permissions() {
is_in_dir() {
# Returns false if parent is empty
[ -n "$2" ] || return 1
local child=$(realpath "$1" 2>/dev/null)
local parent=$(realpath "$2" 2>/dev/null)
local child=$(realpath "$1" 2> /dev/null)
local parent=$(realpath "$2" 2> /dev/null)
[[ "${child}" =~ ^$parent ]]
}
# 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
@ -292,7 +285,7 @@ ynh_validate_ip() {
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1
# http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298
python3 /dev/stdin <<EOF
python3 /dev/stdin << EOF
import socket
import sys
family = { "4" : socket.AF_INET, "6" : socket.AF_INET6 }
@ -390,69 +383,201 @@ ynh_user_list() {
# from the app's service configuration file (defaults to $app.service, overridable by the packager with `service` setting).
# If the app relies on a specific PHP version, then `php` will be aliased that version. The PHP command will also be appended with the `phpflags` settings.
ynh_spawn_app_shell() {
local app=$1
local app=$1
# Force Bash to be used to run this helper
[[ $0 =~ \/?bash$ ]] || ynh_die "Please use Bash as shell"
# Force Bash to be used to run this helper
[[ $0 =~ \/?bash$ ]] || ynh_die "Please use Bash as shell"
# Make sure the app is installed
test -d /etc/yunohost/apps/$app || ynh_die "$app is not an installed app ?!"
# Make sure the app is installed
test -d /etc/yunohost/apps/$app || ynh_die "$app is not an installed app ?!"
# Make sure the app has its own user
id -u "$app" &>/dev/null || ynh_die "There is no \"$app\" system user"
# Make sure the app has its own user
id -u "$app" &> /dev/null || ynh_die "There is no \"$app\" system user"
# Make sure the app has an install_dir setting
local install_dir=$(ynh_app_setting_get --app=$app --key=install_dir)
[ -n "$install_dir" ] || ynh_die "$app has no install_dir setting (does it use packaging format >=2?)"
# Make sure the app has an install_dir setting
local install_dir=$(ynh_app_setting_get --app=$app --key=install_dir)
[ -n "$install_dir" ] || ynh_die "$app has no install_dir setting (does it use packaging format >=2?)"
# Load the app's service name, or default to $app
local service=$(ynh_app_setting_get --app=$app --key=service)
[ -z "$service" ] && service=$app;
# Load the app's service name, or default to $app
local service=$(ynh_app_setting_get --app=$app --key=service)
[ -z "$service" ] && service=$app
# Export HOME variable
export HOME=$install_dir;
# Export HOME variable
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;
# 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
# 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
eval "php() { php${phpversion} ${phpflags} \"\$@\"; }"
export -f php
fi
# 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
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
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
set -a
for file in ${env_files[*]}
do
[[ $file = /* ]] && source $file
done
set +a
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
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
set -a
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
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
set -a
source $install_dir/venv/bin/activate
set +a
fi
# Activate the Python environment, if it exists
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
set +a
fi
# 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;
cd $env_dir
# 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
cd $env_dir
# Spawn the app shell
su -s /bin/bash $app
# 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
View 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"

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