Compare commits

...

324 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
Alexandre Aubin
9f6f5f92fb Update changelog for 11.2.26 2024-08-01 18:06:23 +02:00
Alexandre Aubin
e88ba3428c Minor cosmetic / prevent double slashes 2024-08-01 18:05:02 +02:00
Alexandre Aubin
fe524dd866 Fix yunomprompt not being enable after ISO install 2024-07-31 15:50:45 +02:00
Alexandre Aubin
65ea34d7cb bullseye->bookworm: boring tweak to remove chattr +i from /etc/resolv.conf otherwise resolvconf will later explode and complain about it 2024-07-30 23:53:39 +02:00
Alexandre Aubin
d766f7cdda bullseye->bookworm: have a specific step dedicated to upgrade python3.9 to 3.11 because apt(itude) is derping about it sometimes... 2024-07-30 23:51:01 +02:00
Alexandre Aubin
423e79bd57
Update 0027_migrate_to_bookworm.py.disabled: encourage apt to remove luajit if it's installed because for some reason it's causing issues 2024-07-30 23:14:32 +02:00
Alexandre Aubin
44529b6d92 Update changelog for 11.2.25 2024-07-30 17:13:06 +02:00
Alexandre Aubin
f4727d3cb6 bullseye->bookworm: more stuff to try to prevent aptitude derping about python dependencies 2024-07-30 16:51:22 +02:00
Alexandre Aubin
8705dfcf5c debian: add rule that moulinette and ssowat must be < 12 to prevent situation in bullseye->bookworm transition where moulinette gets upgrade but yunohost doesnt and everything explodes 2024-07-30 16:21:08 +02:00
Alexandre Aubin
ad98a10fa8 bullseye->bookworm: make sure the non-free / non-free-firmware stuff is idempotent 2024-07-30 16:00:09 +02:00
Alexandre Aubin
d376677db6 diagnosis: be more robust when diagnosis DMARC records not containing '=' 2024-07-30 15:50:45 +02:00
Alexandre Aubin
8b56983171 bullseye->bookworm: explicitly validate that we're on yunohost 12.x at the end of the migration 2024-07-27 15:09:48 +02:00
Alexandre Aubin
2d3dddc51a bullseye->bookworm: explicitly import _strptime at the beginning to try to prevent "No module named '_strptime'" during migration 2024-07-27 15:06:48 +02:00
Alexandre Aubin
c861ef2ae6 Update changelog for 11.2.24 2024-07-26 21:09:15 +02:00
Alexandre Aubin
53427e8c14
Merge pull request #1920 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-07-26 20:18:42 +02:00
cjdw
e5d74d420d 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-07-26 20:10:39 +02:00
cjdw
cd30a2acc0 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-07-26 20:10:39 +02:00
Alexandre Aubin
9e1b0561e3 bullseye->bookworm: readd tweak about libluajit2 + be more robust about full-upgrade that may fail if python3.9-venv aint installed 2024-07-26 20:10:28 +02:00
Alexandre Aubin
843771ea05
Merge pull request #1921 from YunoHost/fix-install-from-equivs
Fix install from equivs
2024-07-25 16:06:40 +02:00
Kayou
ddf3e32c1c
fix the v2 too 2024-07-25 15:57:58 +02:00
Kayou
6d21e9fced
a better way to avoid the double commas 2024-07-25 15:56:56 +02:00
Kayou
d881d1a505
avoid double commas in control file, crash if there is an issue in the control file 2024-07-25 15:42:39 +02:00
Alexandre Aubin
ebaecfcbd6 ci: we don't care about mypy in tests/ folder 2024-07-23 19:26:28 +02:00
Alexandre Aubin
eeee096f3a Update changelog for 11.2.23 2024-07-23 19:08:45 +02:00
Alexandre Aubin
fc168c54a1
Merge pull request #1915 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-07-23 19:06:13 +02:00
cjdw
b010219814 Translated using Weblate (Indonesian)
Currently translated at 77.6% (625 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-07-23 19:05:44 +02:00
José M
67c5edc40e Translated using Weblate (Galician)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/gl/
2024-07-23 19:05:44 +02:00
cjdw
437189d8c1 Translated using Weblate (Indonesian)
Currently translated at 75.1% (605 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-07-23 19:05:44 +02:00
Alexandre Aubin
b2492ffc3d hmpf fix log list again 2024-07-23 19:05:34 +02:00
Alexandre Aubin
34861f906d
Merge pull request #1916 from YunoHost/fix_slapd_listen_ipv6
[Fix] Make slapd listen also on ipv6
2024-07-22 19:02:13 +02:00
Alexandre Aubin
a7edbc0cc7
Update helpers: go home aleks u drunk 2024-07-22 16:08:40 +02:00
Alexandre Aubin
b1d1f9f907
Merge pull request #1918 from milouse/fix-remove-senderscore
fix: Remove SenderScore from the dnsbl_list.yml file
2024-07-22 15:15:11 +02:00
Étienne Deparis
c90a691448 fix: Remove SenderScore from the dnsbl_list.yml file
Since march 1st this service is behind a fair-use paywall, which
generates lot of alert email confusing people whether their IP/domain is
actually blocked, when actually it’s just the service failing.

See: https://knowledge.validity.com/s/articles/Accessing-Validity-reputation-data-through-DNS?language=en_US
     https://forum.yunohost.org/t/senderscore-blacklist-blocklist-because-of-excessive-number-of-queries/30395
2024-07-22 12:54:45 +02:00
Josué Tille
f6c270e1d2
[Fix] Make slapd listen also on ipv6 2024-07-21 10:30:14 +02:00
Alexandre Aubin
3d53cf0467 helpers: force sourcing getopts before the other helpers to prevent stupid issues (in particular when renaming phpversion to php_version in helpers2.1) 2024-07-20 22:48:50 +02:00
Alexandre Aubin
7ee1734265
Merge pull request #1914 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-07-20 17:34:40 +02:00
Jose Riha
179daf68df Translated using Weblate (Slovak)
Currently translated at 30.5% (246 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/sk/
2024-07-20 11:54:47 +02:00
cjdw
57b4e240e1 Translated using Weblate (Indonesian)
Currently translated at 69.6% (561 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-07-20 11:54:47 +02:00
Alexandre Aubin
bfbc7035dd Update changelog for 11.2.22 2024-07-19 16:55:46 +02:00
Alexandre Aubin
239819b6da
Merge pull request #1910 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-07-19 16:54:26 +02:00
cjdw
357896cd55 Translated using Weblate (Indonesian)
Currently translated at 69.0% (556 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-07-18 20:54:48 +02:00
ppr
ded4892b9e Translated using Weblate (French)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/
2024-07-18 20:54:47 +02:00
xabirequejo
9721685001 Translated using Weblate (Basque)
Currently translated at 99.8% (804 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-07-17 17:56:40 +02:00
Anonymous
8395b066bc Translated using Weblate (French)
Currently translated at 99.8% (804 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/
2024-07-17 17:56:40 +02:00
cjdw
ac4ff0fc2d Translated using Weblate (Indonesian)
Currently translated at 62.7% (505 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-07-17 17:56:40 +02:00
xabirequejo
04101862ac Translated using Weblate (Basque)
Currently translated at 99.8% (804 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-07-17 17:56:40 +02:00
cjdw
0242ecd0e7 Translated using Weblate (Indonesian)
Currently translated at 60.3% (486 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-07-17 17:56:40 +02:00
Alexandre Aubin
6e5c555e37 flake8 etc 2024-07-17 17:56:32 +02:00
Kayou
ebcf3c79ff
Fix "log list" : use root_dir for iglob / make sure we use absolute paths (#1913)
* use root_dir for iglob, fix parent_symlink path and check if it exists

* fix log path

* do not try to read a yaml of a symlink to /dev/null

* use hidden files, needs python 3.11 (bookworm)

* don't worry, I'm an expert!

* Update log.py: log_file -> log_md_fullpath (otherwise it feel like log_file refers to the .log)

* Update log.py: remove debug statement

* Update log.py: revert unecessary if change

---------

Co-authored-by: Alexandre Aubin <4533074+alexAubin@users.noreply.github.com>
2024-07-17 16:45:43 +02:00
Alexandre Aubin
f11f11973b bullseye->bookworm: trigger the 'new' migration from inside the bullseye->bookworm migration 2024-07-17 16:36:46 +02:00
Alexandre Aubin
67d6baa151 bullseye->bookworm: forgot to remove the unhold for apps packages >_> 2024-07-17 16:17:46 +02:00
Alexandre Aubin
97bb6bde09 bullseye->bookworm: automatically add non-free-firmware if non-free is enabled 2024-07-17 15:31:25 +02:00
Alexandre Aubin
ca59886303 bullseye->bookworm: fix typo in message 2024-07-17 15:28:01 +02:00
Alexandre Aubin
a8fd6afeee bullseye->bookworm: try the yunohost upgrade without unholding the app-ynh-deps virtual packages, then after unholding if it didnt work for some reason 2024-07-17 15:24:04 +02:00
Alexandre Aubin
a5868733d7 bullseye->bookworm: uncessary comments / FIXME 2024-07-17 15:18:46 +02:00
Alexandre Aubin
079cdc2624 bullseye->bookworm: explicitly remove python3.9 and python3.9-venv which seems to confuse aptitude... 2024-07-17 15:06:05 +02:00
Alexandre Aubin
4232fc7c4b bullseye->bookworm: explicitly install yunohost-portal 2024-07-17 15:04:52 +02:00
Alexandre Aubin
845a14bfe1
Merge pull request #1912 from YunoHost/fix-venv-pre-bookworm
remove pkg_resources from pip freeze
2024-07-17 00:56:26 +02:00
Kay0u
73e0d6c271
remove pkg_resources from pip freeze 2024-07-16 23:26:35 +02:00
Alexandre Aubin
14312a9ec4 Update changelog for 11.2.21.2 2024-07-15 23:07:42 +02:00
Alexandre Aubin
8a65053a59 helpers/apt: zzzz did this break everything? 2024-07-15 23:06:05 +02:00
Alexandre Aubin
64c8d9e853 bullseye->bookworm migration: tweak message to reflect the fact that metronome and rspamd will be applications starting with bookworm 2024-07-15 22:29:30 +02:00
Alexandre Aubin
22201863a1 Update changelog for 11.2.21.1 2024-07-15 22:14:32 +02:00
Alexandre Aubin
bb20020c5a helpers2.1: forgot to patch ynh_remove_fpm_config -> ynh_config_remove_phpfpm 2024-07-15 22:13:20 +02:00
Alexandre Aubin
771a4b3446 Update changelog for 11.2.21 2024-07-15 16:31:44 +02:00
Alexandre Aubin
beeddc7819
Merge pull request #1909 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-07-15 16:16:50 +02:00
cjdw
0907411efc Translated using Weblate (Indonesian)
Currently translated at 53.0% (427 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-07-15 16:16:26 +02:00
José M
d71d8fe7b3 Translated using Weblate (Galician)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/gl/
2024-07-15 16:16:26 +02:00
Alexandre Aubin
9e8c7e704e
Merge pull request #1903 from YunoHost/repo_trusted
helpers/apt: Support apt repositories with [trusted=yes]
2024-07-15 16:16:22 +02:00
Alexandre Aubin
85c5c04b15
Merge pull request #1908 from YunoHost/actions/black
Format Python code with Black
2024-07-12 18:21:43 +02:00
alexAubin
a0bc7926c4 🎨 Format Python code with Black 2024-07-12 13:24:32 +00:00
Alexandre Aubin
27ccd2918e
Merge pull request #1907 from YunoHost/optimize-log-list-perf
log: optimize log list perf by creating a 'cache' symlink pointing to the log's parent
2024-07-12 15:24:13 +02:00
Alexandre Aubin
588742f31b log: optimize log list perf by creating a 'cache' symlink pointing to the log's parent 2024-07-11 17:35:37 +02:00
Alexandre Aubin
4112deda0c
Merge pull request #1906 from YunoHost/ci-autofix-translated-strings-dev
[CI] Reformat / remove stale translated strings
2024-07-11 17:14:16 +02:00
yunohost-bot
1e70577d23 [CI] Reformat / remove stale translated strings 2024-07-11 15:13:17 +00:00
OniriCorpe
623bd151d6 Translated using Weblate (French)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/
2024-07-11 17:00:40 +02:00
Anonymous
d87fe9fb4c Translated using Weblate (Japanese)
Currently translated at 65.3% (526 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/ja/
2024-07-11 17:00:40 +02:00
Anonymous
bf8271e383 Translated using Weblate (Ukrainian)
Currently translated at 90.1% (726 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/uk/
2024-07-11 17:00:40 +02:00
Anonymous
818fd78a3d Translated using Weblate (Basque)
Currently translated at 97.1% (782 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-07-11 17:00:40 +02:00
Anonymous
eb012de188 Translated using Weblate (Spanish)
Currently translated at 97.1% (782 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/es/
2024-07-11 17:00:40 +02:00
Anonymous
725b41d2a3 Translated using Weblate (Catalan)
Currently translated at 95.9% (772 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/ca/
2024-07-11 17:00:40 +02:00
OniriCorpe
85239f74f6 Translated using Weblate (French)
Currently translated at 100.0% (805 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/
2024-07-11 17:00:40 +02:00
OniriCorpe
0b438eab02 Translated using Weblate (French)
Currently translated at 99.5% (801 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/
2024-07-11 17:00:40 +02:00
cjdw
3c992c894a Translated using Weblate (Indonesian)
Currently translated at 50.8% (409 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-07-11 17:00:40 +02:00
cjdw
a97c82d1c2 Translated using Weblate (Indonesian)
Currently translated at 48.5% (391 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/id/
2024-07-11 17:00:40 +02:00
ppr
566213ecd5 Translated using Weblate (French)
Currently translated at 98.2% (791 of 805 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/
2024-07-11 17:00:40 +02:00
Zwiebel
5fb54936ba Translated using Weblate (German)
Currently translated at 97.0% (767 of 790 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/de/
2024-07-11 17:00:40 +02:00
José M
0b5c5a5f4d Translated using Weblate (Galician)
Currently translated at 100.0% (790 of 790 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/gl/
2024-07-11 17:00:40 +02:00
Alexandre Aubin
e8c171fd83 ci: add migration 0027 to expected strings 2024-07-11 15:53:34 +02:00
Alexandre Aubin
0bffcbae76
Merge pull request #1901 from YunoHost/actions/black
Format Python code with Black
2024-07-11 11:02:18 +02:00
alexAubin
fbe42f1867 🎨 Format Python code with Black 2024-07-11 08:55:48 +00:00
Alexandre Aubin
7121ed6836
Merge pull request #1904 from YunoHost/bookwork-migration-text-fix-some-typos
Bookworn migration text: fix some typos
2024-07-11 10:55:27 +02:00
OniriCorpe
e339006c69 revert migration description 2024-07-11 03:45:58 +02:00
OniriCorpe
a66890ddd8 Bookworn migration text: fix some typos 2024-07-11 01:21:28 +02:00
Kayou
e54e99bfb7
fix migration message 2024-07-11 00:18:06 +02:00
Alexandre Aubin
ab8e0e6619
Update system.py: forgot to add the corresponding stdin arg in some previous commit x_x 2024-07-10 23:37:41 +02:00
Alexandre Aubin
401ccf69c7 helpers2.1: forgot to keep ynh_spawn_app_shell /o\ 2024-07-10 21:09:31 +02:00
Alexandre Aubin
e5bc94b9cf Copypasta is the worst kind of pasta 2024-07-10 20:17:42 +02:00
Alexandre Aubin
9c22d36c6f backups: yunohost should not ask confirmation that 'YunoHost is already installed' when restoring only apps 2024-07-10 18:46:18 +02:00
Alexandre Aubin
b266e398ff Fix previous commit @_@ 2024-07-10 18:45:56 +02:00
Alexandre Aubin
c8a18129df backups: one should be able to restore a backup archive by providing a path to the archive without moving it to /home/yunohost.backup/archives/ 2024-07-10 18:30:12 +02:00
Alexandre Aubin
8be726b993 helpers: fix dpkg-deb --build complaining that the perm is sometimes 777 instead of 755 (not sure why in the first place x_x) 2024-07-10 18:15:36 +02:00
b96c530d2b Support trusted=yes repositories... 2024-07-09 23:57:19 +02:00
bb25c6b15d Fix: support repositories without component 2024-07-09 23:46:51 +02:00
Alexandre Aubin
a735a6d296
Merge pull request #1759 from YunoHost/migrate-to-bookworm
Draft: Bullseye->Bookworm migration
2024-07-08 23:21:33 +02:00
49961145ca Disable migration to bookworm until it is ready 2024-07-08 23:18:36 +02:00
b289de3eca Merge branch 'dev' into migrate-to-bookworm 2024-07-08 22:47:09 +02:00
26fba087d6 Add aptitude to deps for the migration to bookworm 2024-07-08 22:37:40 +02:00
Alexandre Aubin
f6fbd69c39 helpers/apt: rely on simpler dpkg-deb --build rather than equivs to create .deb for app virtual dependencies 2024-07-07 17:28:03 +02:00
Alexandre Aubin
1bb81e8f69 log: small hack when dumping log right after script failure, prevent a weird edge case where it'll dump the log of the resource provisioning instead of the script, guessing it's because it doesn't find 'ynh_exit_properly' near the end of the log ? 2024-07-07 16:38:46 +02:00
Alexandre Aubin
0f34d7e10f bullseye->bookworm: more tweaks for the 'assume yes' in aptitude call, can't use raw bash redirects, gotta use stdin= from subprocess ... and we want only a limited number of 'yes' and not an infinite yes like the -y option does resuling in conflict resolution loops 2024-07-06 16:55:47 +02:00
Alexandre Aubin
2763e04012 bullseye->bookworm: dirty hack to explicitly remove rspamd because it's causing too many issues in dependency resolution idk 2024-07-06 00:32:20 +02:00
90d4cd99b9 Add missing from time import sleep ; also restart nginx at the end of the migration 2024-07-04 21:26:38 +02:00
f344cb037b Fix missing import of moulinette.Moulinette 2024-07-04 21:02:32 +02:00
Alexandre Aubin
c694ea2cbc bullseye->bookworm: force-regen the nsswitch configuration because for some reason it gets reset? 2024-07-04 19:27:51 +02:00
Alexandre Aubin
772e772b24 bullseye->bookorm: delay the yunohost-api restart such that the migration doesnt appear as failed from the webamin 2024-07-04 19:13:43 +02:00
Alexandre Aubin
b5e6f02d7d
Merge pull request #1898 from YunoHost/ci-autofix-translated-strings-dev
[CI] Reformat / remove stale translated strings
2024-07-04 00:32:14 +02:00
yunohost-bot
30286bc811 [CI] Reformat / remove stale translated strings 2024-07-03 22:31:10 +00:00
Alexandre Aubin
62f7e022ff
Merge pull request #1897 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-07-04 00:22:39 +02:00
OniriCorpe
ffde5cbf87 Translated using Weblate (French)
Currently translated at 100.0% (790 of 790 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/fr/
2024-07-04 00:21:03 +02:00
Alexandre Aubin
c6aec680b9 Backport i18n string + code for bookworm migration 2024-07-04 00:17:32 +02:00
OniriCorpe
395dc6b843 Merge branch 'dev' of https://github.com/YunoHost/yunohost into dev 2024-07-04 00:16:44 +02:00
OniriCorpe
fe8fcaefef typo (menacing parenthesis) 2024-07-04 00:16:42 +02:00
Alexandre Aubin
d6aa310c21
Merge pull request #1896 from YunoHost/fix-dumb-typo
fix a dumb typo
2024-07-04 00:14:09 +02:00
OniriCorpe
5fcb1c6188 fix a dumb typo; i'd like commit amend but it was already merged thanks to our serial merger 2024-07-04 00:11:55 +02:00
Alexandre Aubin
22d8c0c70a
Merge pull request #1895 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-07-04 00:08:30 +02:00
Ivan Davydov
8de0a4cdcb Translated using Weblate (Russian)
Currently translated at 37.1% (291 of 783 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/ru/
2024-07-04 00:06:49 +02:00
Alexandre Aubin
6f73a82a2d
Merge pull request #1894 from YunoHost/translate-_diagnosis_ignore-function
translate _diagnosis_ignore function
2024-07-04 00:06:45 +02:00
OniriCorpe
ab742e55bb translate _diagnosis_ignore function 2024-07-04 00:04:17 +02:00
Alexandre Aubin
5d15c00d92 Update changelog for 11.2.20.2 2024-07-03 21:52:39 +02:00
Alexandre Aubin
9a5aff9715 Merge remote-tracking branch 'origin/dev' into migrate-to-bookworm 2024-07-03 17:24:15 +02:00
Alexandre Aubin
3e20cdd59e
Merge pull request #1893 from YunoHost/fix-#1886
trying to fix #1886
2024-07-02 22:24:29 +02:00
OniriCorpe
2edb6ad625
Merge branch 'dev' into fix-#1886 2024-07-02 21:52:10 +02:00
OniriCorpe
41ca422210 use of the intermediate functions with a more eloquent name for clarity 2024-07-02 21:47:54 +02:00
OniriCorpe
e55c914974 real working fix 2024-07-02 21:44:24 +02:00
Alexandre Aubin
7c7e763a74 Update changelog for 11.2.20.1 2024-07-01 23:39:34 +02:00
Alexandre Aubin
0f85ddbcff friskies³ 2024-07-01 22:24:36 +02:00
OniriCorpe
131760e30c trying to fix #1886 2024-07-01 22:04:28 +02:00
Alexandre Aubin
7e55a791b6
Merge pull request #1892 from YunoHost/better-help-message-for-diagnosis-unignore
cli: better help message for 'diagnosis unignore'
2024-07-01 22:00:18 +02:00
Alexandre Aubin
2640dd3171 friskies² 2024-07-01 21:59:45 +02:00
OniriCorpe
4e3f30ef82 better help message for 'diagnosis unignore' 2024-07-01 21:51:43 +02:00
Alexandre Aubin
bc3e36abb3 friskies 2024-07-01 21:39:59 +02:00
Alexandre Aubin
92807afb16 helpers: yolo add tests for helpersv2.1 2024-07-01 20:55:45 +02:00
Alexandre Aubin
1ed56952e6 What do we say about testing before releasing? Not today! 2024-07-01 20:25:10 +02:00
Alexandre Aubin
6b77e19bbd Update changelog for 11.2.20 2024-07-01 18:49:47 +02:00
Alexandre Aubin
50034aabdd helpers2.1: use the MEDIA_GROUP global var for consistency 2024-07-01 18:49:36 +02:00
Alexandre Aubin
ef622ffe4d helpers2.1: switch to posisional args for ynh_multimedia_addaccess because that's what 99% of apps already do 2024-07-01 18:25:14 +02:00
Alexandre Aubin
40a3205add
Merge pull request #1890 from YunoHost/actions/black
Format Python code with Black
2024-06-30 21:38:27 +02:00
alexAubin
7b0383f865 🎨 Format Python code with Black 2024-06-30 19:38:06 +00:00
Alexandre Aubin
0783af306d
Merge pull request #1886 from YunoHost/auto-disable
automatically ignore the service in diagnosis if it has been deactivated with the ynh cli
2024-06-30 21:37:49 +02:00
Alexandre Aubin
36b3b00166
Merge pull request #1889 from rndmh3ro/add_tar_support
add support for downloading tar-files
2024-06-30 20:25:06 +02:00
Sebastian Gumprich
e75b4b3b3b add support for downloading tar-files
this is needed for invoiceninja, see https://github.com/YunoHost-Apps/invoiceninja5_ynh/pull/280
2024-06-30 20:18:31 +02:00
Alexandre Aubin
1c62960e25 helpers2.1: remove the ynh_clean_setup mechanism underused/useless.. 2024-06-30 20:10:21 +02:00
Alexandre Aubin
1e1409c7d7 helpers2.1: logging tweak in ynh_die 2024-06-30 19:43:18 +02:00
Alexandre Aubin
fcaa366e91 helpers2.1: zzzz 2024-06-30 19:28:18 +02:00
Alexandre Aubin
f2b5f0f22c helpers2.1: when using ynh_die, also return the error via YNH_STDRETURN such that it can be obtained from the python and displayed in the main error message, to increase the chance that people may read it and have something more useful than "An error happened in the script" 2024-06-30 18:53:54 +02:00
Alexandre Aubin
4b43d8d99d
Update service.py: typo 2024-06-30 18:52:19 +02:00
Alexandre Aubin
636c9e563e
Update diagnosis.py: more messages improvement 2024-06-30 18:41:50 +02:00
Alexandre Aubin
c0bccc3ac9
Update diagnosis.py: gotta "return" now if the key doesn't exist, otherwise the next code fails 2024-06-30 18:40:23 +02:00
Alexandre Aubin
9727765ecf
Update diagnosis.py: improve warning to make it more explicit when called from another context 2024-06-30 18:39:11 +02:00
Alexandre Aubin
5ef0c84c0f
Update tools.py: use _run_service_command to enable+start yunohost-firewall during postinstall and prevent a warning about lack of diagnosis ignore rule 2024-06-30 18:34:38 +02:00
OniriCorpe
c965f13f50
Merge branch 'dev' into auto-disable 2024-06-30 18:29:06 +02:00
OniriCorpe
20741c63aa change an irrelevant error to a warning 2024-06-30 18:28:18 +02:00
Alexandre Aubin
a48bfa67de helpers2.1: change source patches location + raise an error instead of a warning when a patch fails to apply on CI
Co-authored-by: Félix Piédallu <felix@piedallu.me>
2024-06-30 17:46:52 +02:00
Alexandre Aubin
3f973669fc helpers2.1: fix automigration of phpversion to php_version 2024-06-30 01:37:56 +02:00
Alexandre Aubin
a18d5f26f2 helpers2.1: zgrblg 2024-06-30 00:21:40 +02:00
Alexandre Aubin
c2271ab731 Update changelog for 11.2.19 2024-06-29 23:57:26 +02:00
Alexandre Aubin
eee84c5f66 helpers2.1: also run _ynh_apply_default_permissions in ynh_restore to be consistent (also because the user uid on the new system may be different than in the archive etc) 2024-06-29 21:32:53 +02:00
OniriCorpe
6ed167bfaf automatically ignore the service in diagnosis if it has been deactivated with the ynh cli 2024-06-29 21:01:38 +02:00
OniriCorpe
eaf00103dd Revert "automatically ignore the service in diagnosis if it has been deactivated with the ynh cli"
This reverts commit ff78f3ada7.
2024-06-29 20:57:59 +02:00
OniriCorpe
ff78f3ada7 automatically ignore the service in diagnosis if it has been deactivated with the ynh cli 2024-06-29 20:57:21 +02:00
Alexandre Aubin
fcbb971792
Merge pull request #1885 from YunoHost/actions/black
Format Python code with Black
2024-06-29 20:33:05 +02:00
alexAubin
dbf579b7b4 🎨 Format Python code with Black 2024-06-29 18:31:51 +00:00
Alexandre Aubin
e5b575901a apps: be more robust when an app upgrade succeeds but for some reason is marked with 'broke the system' ... ending up in inconsistent state between the app settings vs the app scritpts (for example in v1->v2 transitions but not only) 2024-06-29 20:31:28 +02:00
Alexandre Aubin
d47c87e57d helpers2.1: wrmbgl 2024-06-29 20:16:52 +02:00
Alexandre Aubin
28603da4f1
Merge pull request #1884 from YunoHost/actions/black
Format Python code with Black
2024-06-29 20:05:21 +02:00
alexAubin
c2d69f7f84 🎨 Format Python code with Black 2024-06-29 18:05:02 +00:00
Alexandre Aubin
a349fc0334 apps: tweaks to be more robust and prevent the stupid flood of 'sh: 0: getcwd() failed: No such file or directory' when running an app upgrade/remove from /var/www/$app, sometimes making it look like the upgrade failed when it didnt 2024-06-29 20:04:27 +02:00
Alexandre Aubin
3e1c9ebaf7 Fix getopts error handling ... 2024-06-29 19:21:08 +02:00
Alexandre Aubin
1ab3a79d39 Update changelog for 11.2.18 2024-06-29 18:06:40 +02:00
Alexandre Aubin
44bbc34967
Merge pull request #1716 from Salamandar/ynh_secure_remove
Fix ynh_safe_rm: check if target is not a broken symlink before erorring out.
2024-06-29 17:23:50 +02:00
Alexandre Aubin
7b2959a3eb helpers2.1: forgot to rename the apt call in mongodb helpers 2024-06-29 17:18:20 +02:00
Alexandre Aubin
1dfc47d1d7 helpers2.1: in logrotate, make sure to also chown $app the log dir 2024-06-28 20:21:56 +02:00
Alexandre Aubin
9cd7c86641
Merge pull request #1883 from YunoHost/fix_default_permissions
[helpers v2.1] Rework _ynh_apply_default_permissions
2024-06-28 20:20:08 +02:00
Alexandre Aubin
ef68485c5f Use the group defined in the manifest by default 2024-06-28 19:24:07 +02:00
Alexandre Aubin
656ff823a9 Also handle files in /etc/$app 2024-06-28 18:56:18 +02:00
Alexandre Aubin
ae3018cdd0 Infer the necessity to use www-data as group from the presence of alias or root in nginx.conf 2024-06-28 18:39:12 +02:00
Alexandre Aubin
8b8768fd77 Only set www-data as group for webapps 2024-06-28 18:09:49 +02:00
Alexandre Aubin
75d7042974
Update helpers/helpers.v2.1.d/utils: use regex matching to check if path is child from a parent path 2024-06-28 16:56:28 +02:00
Alexandre Aubin
3b26ccc2a5 Properly handle case where $parent is empty to simplify condition 2024-06-28 16:55:39 +02:00
Alexandre Aubin
3608c5678c Proper 'if' cases to distinguish between $install_dir vs regular files in $install_dir and $data_dir 2024-06-28 16:45:43 +02:00
Alexandre Aubin
d9d404a5b2 ynh_setup_source: apply default perms *after* extracting files to hopefully remove the need to manually chown/chmod 2024-06-28 16:06:40 +02:00
8846381d47 Rework _ynh_apply_default_permissions, only check if target is a child of install_dir. 2024-06-28 16:03:17 +02:00
650481a58a ynh_safe_rm: Check if target is a symlink
When calling ynh_safe_rm to a broken symlink, the function was erroring out.
(test -e was following the symlink and returning false)
We need to also check if it is a symlink before exiting.
2024-06-28 15:01:59 +02:00
Alexandre Aubin
87eedc2a36 Update changelog for 11.2.17.1 2024-06-25 14:20:42 +02:00
Alexandre Aubin
feb9a095b3 helpers doc: fix detail block, cant use the HTML <details> because grav doesnt interpret markdown in it 2024-06-25 14:17:49 +02:00
Alexandre Aubin
997388dc79 helpers2.1: fix __PATH__/ handling 2024-06-25 14:16:04 +02:00
Alexandre Aubin
9982a77582
Merge pull request #1878 from YunoHost/actions/black
Format Python code with Black
2024-06-25 00:21:50 +02:00
Alexandre Aubin
2a7fefaecb helpers/doc: De-hide some helpers v1 in documentation now that the structure is less bloated sort of ? 2024-06-25 00:21:24 +02:00
Alexandre Aubin
7347b08e49 ci: Fix helpers 2.1 doc location 2024-06-25 00:18:38 +02:00
alexAubin
6851d740f7 🎨 Format Python code with Black 2024-06-24 20:38:46 +00:00
Alexandre Aubin
2d26935079 Update changelog for 11.2.17 2024-06-24 22:38:18 +02:00
Alexandre Aubin
094cd9ddd6 helpers: rework helper doc now that we have multiple versions of helpers in parallel + improve structure (group helper file in categories) 2024-06-24 22:34:36 +02:00
Alexandre Aubin
29ae71acad
Merge pull request #1877 from YunoHost/actions/black
Format Python code with Black
2024-06-24 22:28:31 +02:00
alexAubin
c9b76fde35 🎨 Format Python code with Black 2024-06-24 20:13:47 +00:00
Alexandre Aubin
e3bebeac98 helpers2.1: typo in getopts 2024-06-24 22:13:16 +02:00
Alexandre Aubin
ed426f05ba apps/helpers2.1: fix app env in resource upgrade context ending up in incorrect helper version being used 2024-06-24 22:13:01 +02:00
Alexandre Aubin
2af4c157d9 helpers/mongo: less noisy output when checking the avx flag is here in /proc/cpuinfo 2024-06-24 21:35:35 +02:00
Alexandre Aubin
0aad13cd2f helpers2.1: oopsies in apt helper 2024-06-24 19:11:28 +02:00
Alexandre Aubin
2895d4d99b helpers: Misc cleaning / reorganizing to prepare new doc 2024-06-24 17:42:37 +02:00
Alexandre Aubin
1fb80e5d24 helpers2.1: drop ynh_apps helper because only a single app is using it ... 2024-06-24 06:09:58 +02:00
Alexandre Aubin
30467f8bc3 helpers2.1: fix bad syntax in ynh_app_upstream_version 2024-06-23 20:04:17 +02:00
Alexandre Aubin
d8c3ff4c8a helpers2.1: forgot to propagate the 'goenv latest' fix from helpers v1 2024-06-23 16:35:58 +02:00
Alexandre Aubin
0e4495f11e Update changelog for 11.2.16 2024-06-23 15:32:47 +02:00
Alexandre Aubin
2b1f74268f helpers2.1: var rename / cosmetic etc for nodejs/ruby/go version and install directories 2024-06-23 15:21:25 +02:00
Alexandre Aubin
5f6df6a859 helpers2.1: for some reason sudo -E doesn't preserve PATH even though it's exported, so we gotta explicitly use --preserve-env=PATH 2024-06-23 14:49:11 +02:00
Alexandre Aubin
b3409729a6 helpers2.1: when using ynh_systemctl to reload/start/restart a service with a wait_until and it timesout, handle it as a filure rather than keep going 2024-06-23 14:36:55 +02:00
Alexandre Aubin
9298738d06 helpers2.1: display 100 lines instead of 20 in CI context when service fails to start 2024-06-23 14:30:57 +02:00
Alexandre Aubin
262453f132 helpers2.1: change default timeout of ynh_systemctl to 60s instead of 300s 2024-06-23 14:27:37 +02:00
Alexandre Aubin
d4857834f3 helpers2.1: sudo -u$app -> sudo -u $app 2024-06-23 14:13:17 +02:00
Alexandre Aubin
3942ea12ae helpers2.1: fix ynh_config_add_logrotate when no arg is passed 2024-06-23 14:08:31 +02:00
Alexandre Aubin
a2ac77fa91
Merge pull request #1867 from yunohost-bot/weblate-yunohost-core
Translations update from Weblate
2024-06-23 01:20:35 +02:00
Jose Riha
6ee40ac06a Translated using Weblate (Slovak)
Currently translated at 31.2% (245 of 783 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/sk/
2024-06-23 01:20:14 +02:00
xabirequejo
f26565d6de Translated using Weblate (Basque)
Currently translated at 100.0% (783 of 783 strings)

Translation: YunoHost/core
Translate-URL: https://translate.yunohost.org/projects/yunohost/core/eu/
2024-06-23 01:20:14 +02:00
Alexandre Aubin
2e05b0894b
Merge pull request #1876 from YunoHost/actions/black
Format Python code with Black
2024-06-23 01:20:11 +02:00
alexAubin
18092db1c8 🎨 Format Python code with Black 2024-06-22 23:15:07 +00:00
Alexandre Aubin
ecb82ec693 Oopsies 2024-06-23 01:14:41 +02:00
Alexandre Aubin
31ae5d1eaa Misc fixes for flake8/mypy 2024-06-23 01:05:39 +02:00
Alexandre Aubin
be3df69326
Merge pull request #1873 from YunoHost/ynh_app_setting_set_default
helpers: add a new ynh_app_setting_set_default to replace the unecessarily complex 'if [ -z ${foo:-} ]' trick
2024-06-23 00:59:26 +02:00
Alexandre Aubin
7caf7e8b3e
Merge pull request #1874 from YunoHost/rework_fpm_settings_madness
helpers2.1: rework the fpm usage/footprint madness
2024-06-23 00:59:00 +02:00
Alexandre Aubin
e558513609 helpers2.1: fix positional arg parsing in ynh_psql_create_user 2024-06-22 22:52:31 +02:00
Alexandre Aubin
3d728d90ce helpers2.1: rework the fpm usage/footprint madness 2024-06-22 01:59:18 +02:00
alexAubin
0bd69e5622 🎨 Format Python code with Black 2024-06-21 22:47:02 +02:00
Alexandre Aubin
1b5074d857 helpers: add a new ynh_app_setting_set_default to replace the unecessarily complex 'if [ ${foo:-} ]' trick 2024-06-21 18:30:05 +02:00
Alexandre Aubin
dd8db1883a helpers2.1: drop unused 'local source' mechanism from ynh_setup_source 2024-06-21 16:26:14 +02:00
Alexandre Aubin
06c8fbc881 logs: misc ad-hoc tweaks to limit the noise in log sharing 2024-06-21 16:26:07 +02:00
Alexandre Aubin
a25033bba5 apps/logs: fix some information not being redacted because of the packaging v2 flows 2024-06-21 14:20:56 +02:00
Alexandre Aubin
307ed10c41 Merge remote-tracking branch 'origin/dev' into migrate-to-bookworm 2024-06-10 12:38:54 +02:00
Alexandre Aubin
383fd6f5d4 First draft for migrate_to_bookworm 2024-04-10 21:13:55 +02:00
tituspijean
bc30805c7d
[enh] exclude .well-known subpaths from conflict checks 2023-04-17 13:18:10 +02:00
149 changed files with 6329 additions and 4069 deletions

View file

@ -38,12 +38,17 @@ workflow:
- if: $CI_COMMIT_TAG # For tags - if: $CI_COMMIT_TAG # For tags
- if: $CI_COMMIT_REF_NAME == "ci-format-$CI_DEFAULT_BRANCH" # Ignore black formatting branch created by the CI - if: $CI_COMMIT_REF_NAME == "ci-format-$CI_DEFAULT_BRANCH" # Ignore black formatting branch created by the CI
when: never 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 - 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: never
- when: always - when: always
variables: 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: include:
- template: Code-Quality.gitlab-ci.yml - template: Code-Quality.gitlab-ci.yml

View file

@ -1,21 +1,19 @@
.build-stage: .build-stage:
stage: build stage: build
image: "before-install" image: "build-and-lint"
variables: variables:
YNH_SOURCE: "https://github.com/yunohost" YNH_BUILD_DIR: "$GIT_CLONE_PATH/build"
before_script: before_script:
- mkdir -p $YNH_BUILD_DIR - mkdir -p $YNH_BUILD_DIR
- DEBIAN_FRONTEND=noninteractive apt update
artifacts: artifacts:
paths: paths:
- ./*.deb - ./*.deb
.build_script: &build_script .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 - cd $YNH_BUILD_DIR/$PACKAGE
- VERSION=$(dpkg-parsechangelog -S Version 2>/dev/null) - VERSION=$(dpkg-parsechangelog -S Version 2>/dev/null)
- VERSION_NIGHTLY="${VERSION}+$(date +%Y%m%d%H%M)" - VERSION_TIMESTAMPED="${VERSION}+$(date +%Y%m%d%H%M)"
- dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_NIGHTLY}" -D "unstable" --force-distribution "Daily build." - dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_TIMESTAMPED}" -D "unstable" --force-distribution "CI build."
- debuild --no-lintian -us -uc - debuild --no-lintian -us -uc
- cp $YNH_BUILD_DIR/*.deb ${CI_PROJECT_DIR}/ - cp $YNH_BUILD_DIR/*.deb ${CI_PROJECT_DIR}/
- cd ${CI_PROJECT_DIR} - cd ${CI_PROJECT_DIR}
@ -36,14 +34,12 @@ build-yunohost:
- DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $YNH_BUILD_DIR/$PACKAGE - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $YNH_BUILD_DIR/$PACKAGE
- *build_script - *build_script
build-ssowat: build-ssowat:
extends: .build-stage extends: .build-stage
variables: variables:
PACKAGE: "ssowat" PACKAGE: "ssowat"
script: script:
- DEBIAN_DEPENDS=$(cat debian/control | tr "," "\n" | grep -Po "ssowat \([>,=,<]+ .*\)" | grep -Po "[0-9\.]+") - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $YNH_DEBIAN $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
- git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $DEBIAN_DEPENDS $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
- DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $YNH_BUILD_DIR/$PACKAGE - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $YNH_BUILD_DIR/$PACKAGE
- *build_script - *build_script
@ -52,7 +48,6 @@ build-moulinette:
variables: variables:
PACKAGE: "moulinette" PACKAGE: "moulinette"
script: script:
- DEBIAN_DEPENDS=$(cat debian/control | tr "," "\n" | grep -Po "moulinette \([>,=,<]+ .*\)" | grep -Po "[0-9\.]+") - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $YNH_DEBIAN $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
- git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $DEBIAN_DEPENDS $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
- DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $YNH_BUILD_DIR/$PACKAGE - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $YNH_BUILD_DIR/$PACKAGE
- *build_script - *build_script

View file

@ -4,18 +4,19 @@
generate-helpers-doc: generate-helpers-doc:
stage: doc stage: doc
image: "before-install" image: "build-and-lint"
needs: [] needs: []
before_script: before_script:
- apt-get update -y && apt-get install git hub -y
- git config --global user.email "yunohost@yunohost.org" - git config --global user.email "yunohost@yunohost.org"
- git config --global user.name "$GITHUB_USER" - git config --global user.name "$GITHUB_USER"
script: script:
- cd doc - cd doc
- python3 generate_helper_doc.py - python3 generate_helper_doc.py 2
- python3 generate_helper_doc.py 2.1
- python3 generate_resource_doc.py > resources.md - python3 generate_resource_doc.py > resources.md
- hub clone https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/doc.git doc_repo - hub clone https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/doc.git doc_repo
- cp helpers.md doc_repo/pages/06.contribute/10.packaging_apps/20.scripts/10.helpers/packaging_app_scripts_helpers.md - 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 resources.md doc_repo/pages/06.contribute/10.packaging_apps/10.manifest/10.appresources/packaging_app_manifest_resources.md
- cd doc_repo - cd doc_repo
# replace ${CI_COMMIT_REF_NAME} with ${CI_COMMIT_TAG} ? # replace ${CI_COMMIT_REF_NAME} with ${CI_COMMIT_TAG} ?

View file

@ -14,9 +14,8 @@
upgrade: upgrade:
extends: .install-stage extends: .install-stage
image: "after-install" image: "core-tests"
script: script:
- apt-get update -o Acquire::Retries=3
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
@ -24,6 +23,5 @@ install-postinstall:
extends: .install-stage extends: .install-stage
image: "before-install" image: "before-install"
script: script:
- apt-get update -o Acquire::Retries=3
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
- yunohost tools postinstall -d domain.tld -u syssa -F 'Syssa Mine' -p the_password --ignore-dyndns --force-diskspace - yunohost tools postinstall -d domain.tld -u syssa -F 'Syssa Mine' -p the_password --ignore-dyndns --force-diskspace

View file

@ -5,7 +5,7 @@
lint39: lint39:
stage: lint stage: lint
image: "before-install" image: "build-and-lint"
needs: [] needs: []
allow_failure: true allow_failure: true
script: script:
@ -13,14 +13,14 @@ lint39:
invalidcode39: invalidcode39:
stage: lint stage: lint
image: "before-install" image: "build-and-lint"
needs: [] needs: []
script: script:
- tox -e py39-invalidcode - tox -e py39-invalidcode
mypy: mypy:
stage: lint stage: lint
image: "before-install" image: "build-and-lint"
needs: [] needs: []
script: script:
- tox -e py39-mypy - tox -e py39-mypy

View file

@ -1,11 +1,9 @@
.install_debs: &install_debs .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 - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
- pip3 install -U mock pip pytest pytest-cov pytest-mock pytest-sugar requests-mock tox ansi2html black jinja2 "packaging<22"
.test-stage: .test-stage:
stage: test stage: test
image: "after-install" image: "core-tests"
variables: variables:
PYTEST_ADDOPTS: "--color=yes" PYTEST_ADDOPTS: "--color=yes"
before_script: before_script:
@ -34,6 +32,7 @@ full-tests:
PYTEST_ADDOPTS: "--color=yes" PYTEST_ADDOPTS: "--color=yes"
before_script: before_script:
- *install_debs - *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 - yunohost tools postinstall -d domain.tld -u syssa -F 'Syssa Mine' -p the_password --ignore-dyndns --force-diskspace
script: script:
- python3 -m pytest --cov=yunohost tests/ src/tests/ --junitxml=report.xml - python3 -m pytest --cov=yunohost tests/ src/tests/ --junitxml=report.xml
@ -57,14 +56,17 @@ test-actionmap:
changes: changes:
- share/actionsmap.yml - share/actionsmap.yml
test-helpers: test-helpers2:
extends: .test-stage extends: .test-stage
script: script:
- cd tests - cd tests
- bash test_helpers.sh - bash test_helpers.sh
# only:
# changes: test-helpers2.1:
# - helpers/* extends: .test-stage
script:
- cd tests
- bash test_helpers.sh 2.1
test-domains: test-domains:
extends: .test-stage extends: .test-stage

View file

@ -13,10 +13,9 @@ test-i18n-keys:
autofix-translated-strings: autofix-translated-strings:
stage: translation stage: translation
image: "before-install" image: "build-and-lint"
needs: [] needs: []
before_script: before_script:
- apt-get update -y && apt-get install git hub -y
- git config --global user.email "yunohost@yunohost.org" - git config --global user.email "yunohost@yunohost.org"
- git config --global user.name "$GITHUB_USER" - 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 - hub clone --branch ${CI_COMMIT_REF_NAME} "https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/yunohost.git" github_repo

View file

@ -69,7 +69,7 @@ then
You should now proceed with YunoHost post-installation. This is where you will You should now proceed with YunoHost post-installation. This is where you will
be asked for: be asked for:
- the main domain of your server; - the main domain of your server;
- the administration password. - the username and password for the first admin
You can perform this step: You can perform this step:
- from your web browser, by accessing: https://yunohost.local/ or ${local_ip} - from your web browser, by accessing: https://yunohost.local/ or ${local_ip}

View file

@ -1,28 +1,28 @@
VirtualHost "{{ domain }}" VirtualHost "{{ domain }}"
enable = true enable = true
ssl = { ssl = {
key = "/etc/yunohost/certs/{{ domain }}/key.pem"; key = "/etc/yunohost/certs/{{ domain }}/key.pem";
certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem"; certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem";
} }
authentication = "ldap2" authentication = "ldap2"
ldap = { ldap = {
hostname = "localhost", hostname = "localhost",
user = { user = {
basedn = "ou=users,dc=yunohost,dc=org", basedn = "ou=users,dc=yunohost,dc=org",
filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }})(permission=cn=xmpp.main,ou=permission,dc=yunohost,dc=org))", filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }})(permission=cn=xmpp.main,ou=permission,dc=yunohost,dc=org))",
usernamefield = "mail", usernamefield = "mail",
namefield = "cn", namefield = "cn",
}, },
} }
-- Discovery items -- Discovery items
disco_items = { disco_items = {
{ "muc.{{ domain }}" }, { "muc.{{ domain }}" },
{ "pubsub.{{ domain }}" }, { "pubsub.{{ domain }}" },
{ "jabber.{{ domain }}" }, { "jabber.{{ domain }}" },
{ "vjud.{{ domain }}" }, { "vjud.{{ domain }}" },
{ "xmpp-upload.{{ domain }}" }, { "xmpp-upload.{{ domain }}" },
}; };
-- contact_info = { -- contact_info = {
-- abuse = { "mailto:abuse@{{ domain }}", "xmpp:admin@{{ domain }}" }; -- abuse = { "mailto:abuse@{{ domain }}", "xmpp:admin@{{ domain }}" };
@ -35,41 +35,41 @@ VirtualHost "{{ domain }}"
---Set up a MUC (multi-user chat) room server ---Set up a MUC (multi-user chat) room server
Component "muc.{{ domain }}" "muc" Component "muc.{{ domain }}" "muc"
name = "{{ domain }} Chatrooms" name = "{{ domain }} Chatrooms"
modules_enabled = { modules_enabled = {
"muc_limits"; "muc_limits";
"muc_log"; "muc_log";
"muc_log_mam"; "muc_log_mam";
"muc_log_http"; "muc_log_http";
"muc_vcard"; "muc_vcard";
} }
muc_event_rate = 0.5 muc_event_rate = 0.5
muc_burst_factor = 10 muc_burst_factor = 10
room_default_config = { room_default_config = {
logging = true, logging = true,
persistent = true persistent = true
}; };
---Set up a PubSub server ---Set up a PubSub server
Component "pubsub.{{ domain }}" "pubsub" Component "pubsub.{{ domain }}" "pubsub"
name = "{{ domain }} Publish/Subscribe" name = "{{ domain }} Publish/Subscribe"
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server) unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
---Set up a HTTP Upload service ---Set up a HTTP Upload service
Component "xmpp-upload.{{ domain }}" "http_upload" Component "xmpp-upload.{{ domain }}" "http_upload"
name = "{{ domain }} Sharing Service" name = "{{ domain }} Sharing Service"
http_file_path = "/var/xmpp-upload/{{ domain }}/upload" http_file_path = "/var/xmpp-upload/{{ domain }}/upload"
http_external_url = "https://xmpp-upload.{{ domain }}:443" http_external_url = "https://xmpp-upload.{{ domain }}:443"
http_file_base_path = "/upload" http_file_base_path = "/upload"
http_file_size_limit = 6*1024*1024 http_file_size_limit = 6*1024*1024
http_file_quota = 60*1024*1024 http_file_quota = 60*1024*1024
http_upload_file_size_limit = 100 * 1024 * 1024 -- bytes http_upload_file_size_limit = 100 * 1024 * 1024 -- bytes
http_upload_quota = 10 * 1024 * 1024 * 1024 -- bytes http_upload_quota = 10 * 1024 * 1024 * 1024 -- bytes
---Set up a VJUD service ---Set up a VJUD service
Component "vjud.{{ domain }}" "vjud" Component "vjud.{{ domain }}" "vjud"
vjud_disco_name = "{{ domain }} User Directory" vjud_disco_name = "{{ domain }} User Directory"

View file

@ -1,72 +1,72 @@
-- ** Metronome's config file example ** -- ** Metronome's config file example **
-- --
-- The format is exactly equal to Prosody's: -- The format is exactly equal to Prosody's:
-- --
-- Lists are written { "like", "this", "one" } -- Lists are written { "like", "this", "one" }
-- Lists can also be of { 1, 2, 3 } numbers, etc. -- Lists can also be of { 1, 2, 3 } numbers, etc.
-- Either commas, or semi-colons; may be used as seperators. -- Either commas, or semi-colons; may be used as seperators.
-- --
-- A table is a list of values, except each value has a name. An -- A table is a list of values, except each value has a name. An
-- example would be: -- example would be:
-- --
-- ssl = { key = "keyfile.key", certificate = "certificate.cert" } -- ssl = { key = "keyfile.key", certificate = "certificate.cert" }
-- --
-- Tip: You can check that the syntax of this file is correct when you have finished -- Tip: You can check that the syntax of this file is correct when you have finished
-- by running: luac -p metronome.cfg.lua -- by running: luac -p metronome.cfg.lua
-- If there are any errors, it will let you know what and where they are, otherwise it -- If there are any errors, it will let you know what and where they are, otherwise it
-- will keep quiet. -- will keep quiet.
-- Global settings go in this section -- Global settings go in this section
-- This is the list of modules Metronome will load on startup. -- 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. -- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
modules_enabled = { modules_enabled = {
-- Generally required -- Generally required
"roster"; -- Allow users to have a roster. Recommended. "roster"; -- Allow users to have a roster. Recommended.
"saslauth"; -- Authentication for clients. Recommended if you want to log in. "saslauth"; -- Authentication for clients. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections "tls"; -- Add support for secure TLS on c2s/s2s connections
"disco"; -- Service discovery "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 -- Not essential, but recommended
--"admin_telnet"; -- administration console, telnet to port 5582 "private"; -- Private XML storage (for room bookmarks, etc.)
--"admin_web"; -- administration web interface "vcard"; -- Allow users to set vCards
"bosh"; -- Enable support for BOSH clients, aka "XMPP over Bidirectional Streams over Synchronous HTTP" "pep"; -- Allows setting of mood, tune, etc.
--"compression"; -- Allow clients to enable Stream Compression "pubsub"; -- Publish-subscribe XEP-0060
--"spim_block"; -- Require authorization via OOB form for messages from non-contacts and block unsollicited messages "posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
--"gate_guard"; -- Enable config-based blacklisting and hit-based auto-banning features "bidi"; -- Enables Bidirectional Server-to-Server Streams.
--"incidents_handling"; -- Enable Incidents Handling support (can be administered via adhoc commands)
--"server_presence"; -- Enables Server Buddies extension support -- Nice to have
--"service_directory"; -- Enables Service Directories extension support "version"; -- Replies to server version requests
--"public_service"; -- Enables Server vCard support for public services in directories and advertises in features "uptime"; -- Report how long server has been running
--"register_api"; -- Provides secure API for both Out-Of-Band and In-Band registration for E-Mail verification "time"; -- Let others know the time here on this server
"websocket"; -- Enable support for WebSocket clients, aka "XMPP over WebSockets" "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 -- Server PID
@ -102,10 +102,10 @@ csi_config_queue_all_muc_messages_but_mentions = false;
-- Logging configuration -- Logging configuration
log = { log = {
info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/metronome/metronome.err"; error = "/var/log/metronome/metronome.err";
-- "*syslog"; -- Uncomment this for logging to syslog -- "*syslog"; -- Uncomment this for logging to syslog
-- "*console"; -- Log to the console, useful for debugging with daemonize=false -- "*console"; -- Log to the console, useful for debugging with daemonize=false
} }
------ Components ------ ------ Components ------
@ -114,7 +114,7 @@ log = {
---Set up a local BOSH service ---Set up a local BOSH service
Component "localhost" "http" Component "localhost" "http"
modules_enabled = { "bosh" } modules_enabled = { "bosh" }
----------- Virtual hosts ----------- ----------- Virtual hosts -----------
-- You need to add a VirtualHost entry for each domain you wish Metronome to serve. -- You need to add a VirtualHost entry for each domain you wish Metronome to serve.

View file

@ -23,68 +23,68 @@ if not ldap then
end end
function new_default_provider(host) function new_default_provider(host)
local provider = { name = "ldap2" }; local provider = { name = "ldap2" };
log("debug", "initializing ldap2 authentication provider for host '%s'", host); log("debug", "initializing ldap2 authentication provider for host '%s'", host);
function provider.test_password(username, password) function provider.test_password(username, password)
return ldap.bind(username, password); return ldap.bind(username, password);
end end
function provider.user_exists(username) function provider.user_exists(username)
local params = ldap.getparams() local params = ldap.getparams()
local filter = ldap.filter.combine_and(params.user.filter, params.user.usernamefield .. '=' .. username); local filter = ldap.filter.combine_and(params.user.filter, params.user.usernamefield .. '=' .. username);
if params.user.usernamefield == 'mail' then if params.user.usernamefield == 'mail' then
filter = ldap.filter.combine_and(params.user.filter, 'mail=' .. username .. '@*'); filter = ldap.filter.combine_and(params.user.filter, 'mail=' .. username .. '@*');
end end
return ldap.singlematch { return ldap.singlematch {
base = params.user.basedn, base = params.user.basedn,
filter = filter, filter = filter,
}; };
end end
function provider.get_password(username) function provider.get_password(username)
return nil, "Passwords unavailable for LDAP."; return nil, "Passwords unavailable for LDAP.";
end end
function provider.set_password(username, password) function provider.set_password(username, password)
return nil, "Passwords unavailable for LDAP."; return nil, "Passwords unavailable for LDAP.";
end end
function provider.create_user(username, password) function provider.create_user(username, password)
return nil, "Account creation/modification not available with LDAP."; return nil, "Account creation/modification not available with LDAP.";
end end
function provider.get_sasl_handler(session) function provider.get_sasl_handler(session)
local testpass_authentication_profile = { local testpass_authentication_profile = {
session = session, session = session,
plain_test = function(sasl, username, password, realm) plain_test = function(sasl, username, password, realm)
return provider.test_password(username, password), true; return provider.test_password(username, password), true;
end, end,
order = { "plain_test" }, order = { "plain_test" },
}; };
return new_sasl(module.host, testpass_authentication_profile); return new_sasl(module.host, testpass_authentication_profile);
end end
function provider.is_admin(jid) function provider.is_admin(jid)
local admin_config = ldap.getparams().admin; local admin_config = ldap.getparams().admin;
if not admin_config then if not admin_config then
return; return;
end end
local ld = ldap:getconnection(); local ld = ldap:getconnection();
local username = jsplit(jid); local username = jsplit(jid);
local filter = ldap.filter.combine_and(admin_config.filter, admin_config.namefield .. '=' .. username); local filter = ldap.filter.combine_and(admin_config.filter, admin_config.namefield .. '=' .. username);
return ldap.singlematch { return ldap.singlematch {
base = admin_config.basedn, base = admin_config.basedn,
filter = filter, filter = filter,
}; };
end end
return provider; return provider;
end end
module:add_item("auth-provider", new_default_provider(module.host)); module:add_item("auth-provider", new_default_provider(module.host));

View file

@ -1,7 +1,7 @@
-- Prosody IM -- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain -- Copyright (C) 2008-2010 Waqas Hussain
-- --
-- This project is MIT/X11 licensed. Please see the -- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information. -- COPYING file in the source package for more information.
-- --
@ -12,8 +12,8 @@ local st = require "util.stanza";
local t_concat = table.concat; local t_concat = table.concat;
local secure_auth_only = module:get_option("c2s_require_encryption") local secure_auth_only = module:get_option("c2s_require_encryption")
or module:get_option("require_encryption") or module:get_option("require_encryption")
or not(module:get_option("allow_unencrypted_plain_auth")); or not(module:get_option("allow_unencrypted_plain_auth"));
local sessionmanager = require "core.sessionmanager"; local sessionmanager = require "core.sessionmanager";
local usermanager = require "core.usermanager"; local usermanager = require "core.usermanager";
@ -22,66 +22,65 @@ local resourceprep = require "util.encodings".stringprep.resourceprep;
module:add_feature("jabber:iq:auth"); module:add_feature("jabber:iq:auth");
module:hook("stream-features", function(event) module:hook("stream-features", function(event)
local origin, features = event.origin, event.features; local origin, features = event.origin, event.features;
if secure_auth_only and not origin.secure then if secure_auth_only and not origin.secure then
-- Sorry, not offering to insecure streams! -- Sorry, not offering to insecure streams!
return; return;
elseif not origin.username then elseif not origin.username then
features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up(); features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up();
end end
end); end);
module:hook("stanza/iq/jabber:iq:auth:query", function(event) module:hook("stanza/iq/jabber:iq:auth:query", function(event)
local session, stanza = event.origin, event.stanza; local session, stanza = event.origin, event.stanza;
if session.type ~= "c2s_unauthed" then 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.")); (session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections."));
return true; return true;
end end
if secure_auth_only and not session.secure then 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")); session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server"));
return true; return true;
end end
local username = stanza.tags[1]:child_with_name("username"); local username = stanza.tags[1]:child_with_name("username");
local password = stanza.tags[1]:child_with_name("password"); local password = stanza.tags[1]:child_with_name("password");
local resource = stanza.tags[1]:child_with_name("resource"); local resource = stanza.tags[1]:child_with_name("resource");
if not (username and password and resource) then if not (username and password and resource) then
local reply = st.reply(stanza); local reply = st.reply(stanza);
session.send(reply:query("jabber:iq:auth") session.send(reply:query("jabber:iq:auth")
:tag("username"):up() :tag("username"):up()
:tag("password"):up() :tag("password"):up()
:tag("resource"):up()); :tag("resource"):up());
else else
username, password, resource = t_concat(username), t_concat(password), t_concat(resource); username, password, resource = t_concat(username), t_concat(password), t_concat(resource);
username = nodeprep(username); username = nodeprep(username);
resource = resourceprep(resource) resource = resourceprep(resource)
if not (username and resource) then if not (username and resource) then
session.send(st.error_reply(stanza, "modify", "bad-request")); session.send(st.error_reply(stanza, "modify", "bad-request"));
return true; return true;
end end
if usermanager.test_password(username, session.host, password) then if usermanager.test_password(username, session.host, password) then
-- Authentication successful! -- Authentication successful!
local success, err = sessionmanager.make_authenticated(session, username); local success, err = sessionmanager.make_authenticated(session, username);
if success then if success then
local err_type, err_msg; local err_type, err_msg;
success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource); success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource);
if not success then if not success then
session.send(st.error_reply(stanza, err_type, err, err_msg)); 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? session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager?
return true; return true;
elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth 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.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? session:close(); -- FIXME undo resource bind and auth instead of closing the session?
return true; return true;
end end
end end
session.send(st.reply(stanza)); session.send(st.reply(stanza));
else else
session.send(st.error_reply(stanza, "auth", "not-authorized")); session.send(st.error_reply(stanza, "auth", "not-authorized"));
end end
end end
return true; return true;
end); end);

View file

@ -43,35 +43,35 @@ end
local get_alias_for_user; local get_alias_for_user;
do do
local user_cache; local user_cache;
local last_fetch_time; local last_fetch_time;
local function populate_user_cache() local function populate_user_cache()
local user_c = get_config(module.host, 'ldap').user; local user_c = get_config(module.host, 'ldap').user;
if not user_c then return; end if not user_c then return; end
local ld = ldap.getconnection(); local ld = ldap.getconnection();
local usernamefield = user_c.usernamefield; local usernamefield = user_c.usernamefield;
local namefield = user_c.namefield; local namefield = user_c.namefield;
user_cache = {}; user_cache = {};
for _, attrs in ld:search { base = user_c.basedn, scope = 'onelevel', filter = user_c.filter } do for _, attrs in ld:search { base = user_c.basedn, scope = 'onelevel', filter = user_c.filter } do
user_cache[attrs[usernamefield]] = attrs[namefield]; user_cache[attrs[usernamefield]] = attrs[namefield];
end end
last_fetch_time = gettime(); last_fetch_time = gettime();
end end
function get_alias_for_user(user) function get_alias_for_user(user)
if last_fetch_time and last_fetch_time + CACHE_EXPIRY < gettime() then if last_fetch_time and last_fetch_time + CACHE_EXPIRY < gettime() then
user_cache = nil; user_cache = nil;
end end
if not user_cache then if not user_cache then
populate_user_cache(); populate_user_cache();
end end
return user_cache[user]; return user_cache[user];
end end
end end
---------------------------------------- ----------------------------------------
@ -79,18 +79,18 @@ end
---------------------------------------- ----------------------------------------
local function ldap_store(config) local function ldap_store(config)
local self = {}; local self = {};
local config = config; local config = config;
function self:get(username) function self:get(username)
return nil, "Data getting is not available for this storage backend"; return nil, "Data getting is not available for this storage backend";
end end
function self:set(username, data) function self:set(username, data)
return nil, "Data setting is not available for this storage backend"; return nil, "Data setting is not available for this storage backend";
end end
return self; return self;
end end
local adapters = {}; local adapters = {};
@ -100,60 +100,60 @@ local adapters = {};
---------------------------------------- ----------------------------------------
adapters.roster = function (config) adapters.roster = function (config)
-- Validate configuration requirements -- Validate configuration requirements
if not config.groups then return nil; end if not config.groups then return nil; end
local self = ldap_store(config) local self = ldap_store(config)
function self:get(username) function self:get(username)
local ld = ldap.getconnection(); local ld = ldap.getconnection();
local contacts = {}; local contacts = {};
local memberfield = config.groups.memberfield; local memberfield = config.groups.memberfield;
local namefield = config.groups.namefield; local namefield = config.groups.namefield;
local filter = memberfield .. '=' .. tostring(username); local filter = memberfield .. '=' .. tostring(username);
local groups = {}; local groups = {};
for _, config in ipairs(config.groups) do for _, config in ipairs(config.groups) do
groups[ config[namefield] ] = config.name; groups[ config[namefield] ] = config.name;
end end
log("debug", "Found %d group(s) for user %s", select('#', groups), username) 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 -- 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 for _, attrs in ld:search { base = config.groups.basedn, scope = 'onelevel', filter = filter } do
if groups[ attrs[namefield] ] then if groups[ attrs[namefield] ] then
local members = attrs[memberfield]; local members = attrs[memberfield];
for _, user in ipairs(members) do for _, user in ipairs(members) do
if user ~= username then if user ~= username then
local jid = user .. '@' .. module.host; local jid = user .. '@' .. module.host;
local record = contacts[jid]; local record = contacts[jid];
if not record then if not record then
record = { record = {
subscription = 'both', subscription = 'both',
groups = {}, groups = {},
name = get_alias_for_user(user), name = get_alias_for_user(user),
}; };
contacts[jid] = record; contacts[jid] = record;
end end
record.groups[ groups[ attrs[namefield] ] ] = true; record.groups[ groups[ attrs[namefield] ] ] = true;
end end
end end
end end
end end
return contacts; return contacts;
end end
function self:set(username, data) function self:set(username, data)
log("warn", "Setting data in Roster LDAP storage is not supported yet") log("warn", "Setting data in Roster LDAP storage is not supported yet")
return nil, "not supported"; return nil, "not supported";
end end
return self; return self;
end end
---------------------------------------- ----------------------------------------
@ -161,35 +161,35 @@ end
---------------------------------------- ----------------------------------------
adapters.vcard = function (config) adapters.vcard = function (config)
-- Validate configuration requirements -- Validate configuration requirements
if not config.vcard_format or not config.user then return nil; end if not config.vcard_format or not config.user then return nil; end
local self = ldap_store(config) local self = ldap_store(config)
function self:get(username) function self:get(username)
local ld = ldap.getconnection(); local ld = ldap.getconnection();
local filter = config.user.usernamefield .. '=' .. tostring(username); local filter = config.user.usernamefield .. '=' .. tostring(username);
log("debug", "Retrieving vCard for user '%s'", username); log("debug", "Retrieving vCard for user '%s'", username);
local match = ldap.singlematch { local match = ldap.singlematch {
base = config.user.basedn, base = config.user.basedn,
filter = filter, filter = filter,
}; };
if match then if match then
match.jid = username .. '@' .. module.host match.jid = username .. '@' .. module.host
return st.preserialize(ldap_record_to_vcard(match, config.vcard_format)); return st.preserialize(ldap_record_to_vcard(match, config.vcard_format));
else else
return nil, "username not found"; return nil, "username not found";
end end
end end
function self:set(username, data) function self:set(username, data)
log("warn", "Setting data in vCard LDAP storage is not supported yet") log("warn", "Setting data in vCard LDAP storage is not supported yet")
return nil, "not supported"; return nil, "not supported";
end end
return self; return self;
end end
---------------------------------------- ----------------------------------------

View file

@ -135,28 +135,28 @@ function builder_methods:build()
end end
local function new_builder(params) local function new_builder(params)
local vcard_tag = st.stanza('vCard', { xmlns = VCARD_NS }); local vcard_tag = st.stanza('vCard', { xmlns = VCARD_NS });
local object = { local object = {
vcard = vcard_tag, vcard = vcard_tag,
__index = builder_methods, __index = builder_methods,
}; };
for k, v in pairs(params) do for k, v in pairs(params) do
object[k] = v; object[k] = v;
end end
setmetatable(object, object); setmetatable(object, object);
return object; return object;
end end
local _M = {}; local _M = {};
function _M.create(params) function _M.create(params)
local builder = new_builder(params); local builder = new_builder(params);
return builder:build(); return builder:build();
end end
return _M; return _M;

View file

@ -211,3 +211,11 @@ smtp_sasl_security_options = noanonymous
# where to find sasl_passwd # where to find sasl_passwd
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
{% endif %} {% 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

@ -21,7 +21,7 @@ SLAPD_PIDFILE=
# sockets. # sockets.
# Example usage: # Example usage:
# SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///" # SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///"
SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///" SLAPD_SERVICES="ldap://localhost:389/ ldaps:/// ldapi:///"
# If SLAPD_NO_START is set, the init script will not start or restart # If SLAPD_NO_START is set, the init script will not start or restart
# slapd (but stop will still work). Uncomment this if you are # slapd (but stop will still work). Uncomment this if you are

View file

@ -84,7 +84,7 @@ Subsystem sftp internal-sftp
# Apply following instructions to user with sftp perm only # Apply following instructions to user with sftp perm only
Match Group sftp.main,!ssh.main 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 # We can't restrict to /home/%u because the chroot base must be owned by root
# So we chroot only on /home # So we chroot only on /home
# See https://serverfault.com/questions/584986/bad-ownership-or-modes-for-chroot-directory-component # 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 PermitUserRC no
Match Group sftp.app,!ssh.app Match Group sftp.app,!ssh.app
ForceCommand internal-sftp ForceCommand internal-sftp -u 0002
ChrootDirectory %h ChrootDirectory %h
AllowTcpForwarding no AllowTcpForwarding no
AllowStreamLocalForwarding no AllowStreamLocalForwarding no

228
debian/changelog vendored
View file

@ -1,3 +1,231 @@
yunohost (11.2.30) stable; urgency=low
- 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 ! (Félix Piédallu, Josué Tille, OniriCorpe, selfhoster1312)
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 31 Aug 2024 19:26:59 +0200
yunohost (11.2.29) stable; urgency=low
- 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
Thanks to all contributors <3 ! (cjdw, craftrac, José M, ppr, xabirequejo)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 27 Aug 2024 14:46:26 +0200
yunohost (11.2.28) stable; urgency=low
- 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
- bullseye->bookworm: encourage apt to remove luajit if it's installed because for some reason it's causing issues (423e79bd5)
- bullseye->bookworm: have a specific step dedicated to upgrade python3.9 to 3.11 because apt(itude) is derping about it sometimes... (d766f7cdd)
- bullseye->bookworm: boring tweak to remove chattr +i from /etc/resolv.conf otherwise resolvconf will later explode and complain about it (65ea34d7c)
- Fix yunomprompt not being enable after ISO install (fe524dd86)
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 01 Aug 2024 18:05:33 +0200
yunohost (11.2.25) stable; urgency=low
- diagnosis: be more robust when diagnosis DMARC records not containing '=' (d376677db)
- bullseye->bookworm: explicitly import _strptime at the beginning to try to prevent "No module named '_strptime'" during migration (2d3dddc51)
- bullseye->bookworm: explicitly validate that we're on yunohost 12.x at the end of the migration (8b5698317)
- bullseye->bookworm: make sure the non-free / non-free-firmware stuff is idempotent (ad98a10fa)
- bullseye->bookworm: in debian control, add rule that moulinette and ssowat must be < 12 to prevent situation in bullseye->bookworm transition where moulinette gets upgrade but yunohost doesnt and everything explodes (8705dfcf5)
- bullseye->bookworm: more stuff to try to prevent aptitude derping about python dependencies (f4727d3cb)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 30 Jul 2024 17:12:12 +0200
yunohost (11.2.24) stable; urgency=low
- ci: we don't care about mypy in tests/ folder (ebaecfcbd)
- helpers: fix install from equivs ([#1921](http://github.com/YunoHost/yunohost/pull/1921))
- bullseye->bookworm: re-add tweak about libluajit2 + be more robust about full-upgrade that may fail if python3.9-venv aint installed (9e1b0561e)
- i18n: Translations updated for Indonesian
Thanks to all contributors <3 ! (cjdw, Kayou)
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 26 Jul 2024 21:01:23 +0200
yunohost (11.2.23) stable; urgency=low
- helpers2.1: force sourcing getopts before the other helpers to prevent stupid issues (in particular when renaming phpversion to php_version) (3d53cf04)
- diagnosis: Remove SenderScore from the dnsbl_list.yml file ([#1918](http://github.com/YunoHost/yunohost/pull/1918))
- ldap: make slapd listen also on ipv6 ([#1916](http://github.com/YunoHost/yunohost/pull/1916))
- log: zzz fix log list again (b2492ffc)
- i18n: Translations updated for Galician, Indonesian, Slovak
Thanks to all contributors <3 ! (cjdw, Étienne Deparis, José M, Jose Riha, Josué Tille)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 23 Jul 2024 19:07:20 +0200
yunohost (11.2.22) stable; urgency=low
- logs: fix "log list" : use root_dir for iglob / make sure we use absolute paths ([#1913](http://github.com/YunoHost/yunohost/pull/1913))
- bullseye->bookworm: remove pkg_resources from pip freeze ([#1912](http://github.com/YunoHost/yunohost/pull/1912))
- bullseye->bookworm: explicitly install yunohost-portal (4232fc7c)
- bullseye->bookworm: explicitly remove python3.9 and python3.9-venv which seems to confuse aptitude... (079cdc26)
- bullseye->bookworm: try the yunohost upgrade without unholding the app-ynh-deps virtual packages, then after unholding if it didnt work for some reason (a8fd6afe)
- bullseye->bookworm: automatically add non-free-firmware if non-free is enabled (97bb6bde)
- bullseye->bookworm: trigger the 'new' migrations from inside the bullseye->bookworm migration (f11f1197)
- i18n: Translations updated for Basque, French, Indonesian
Thanks to all contributors <3 ! (Anonymous, cjdw, Kayou, ppr, xabirequejo)
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 19 Jul 2024 16:51:55 +0200
yunohost (11.2.21.2) stable; urgency=low
- bullseye->bookworm migration: tweak message to reflect the fact that metronome and rspamd will be applications starting with bookworm (64c8d9e8)
- helpers/apt: unbound variable (8a65053a)
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 15 Jul 2024 23:07:08 +0200
yunohost (11.2.21.1) stable; urgency=low
- helpers2.1: forgot to patch ynh_remove_fpm_config -> ynh_config_remove_phpfpm (bb20020c)
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 15 Jul 2024 22:13:39 +0200
yunohost (11.2.21) stable; urgency=low
- log: optimize log list perf by creating a 'cache' symlink pointing to the log's parent ([#1907](http://github.com/YunoHost/yunohost/pull/1907))
- log: small hack when dumping log right after script failure, prevent a weird edge case where it'll dump the log of the resource provisioning instead of the script (1bb81e8f)
- debian: Bullseye->Bookworm migration ('hidden' but easier to test) ([#1759](http://github.com/YunoHost/yunohost/pull/1759), ab8e0e66, e54e99bf)
- helpers/apt: rely on simpler dpkg-deb --build rather than equivs to create .deb for app virtual dependencies (f6fbd69c, 8be726b9)
- helpers/apt: Support apt repositories with [trusted=yes] ([#1903](http://github.com/YunoHost/yunohost/pull/1903))
- backups: one should be able to restore a backup archive by providing a path to the archive without moving it to /home/yunohost.backup/archives/ (c8a18129, b266e398)
- backups: yunohost should not ask confirmation that 'YunoHost is already installed' when restoring only apps (9c22d36c)
- i18n: translate _diagnosis_ignore function ([#1894](http://github.com/YunoHost/yunohost/pull/1894))
- i18n: Translations updated for Basque, Catalan, French, Galician, German, Indonesian, Japanese, Russian, Spanish, Ukrainian
Thanks to all contributors <3 ! (alexAubin, Anonymous, cjdw, Félix Piédallu, Ivan Davydov, José M, Kayou, OniriCorpe, ppr, Zwiebel)
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 15 Jul 2024 16:22:26 +0200
yunohost (11.2.20.2) stable; urgency=low
- Fix service enable/disable auto-ignoring diagnosis entries ([#1886](http://github.com/YunoHost/yunohost/pull/1886))
Thanks to all contributors <3 ! (OniriCorpe)
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 03 Jul 2024 21:51:50 +0200
yunohost (11.2.20.1) stable; urgency=low
- helpers2.1: typo (1ed56952e)
- helpers2.1: add unit tests (92807afb1)
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 01 Jul 2024 23:38:29 +0200
yunohost (11.2.20) stable; urgency=low
- helpers2.1: fix automigration of phpversion to php_version (3f973669)
- helpers2.1: change source patches location + raise an error instead of a warning when a patch fails to apply on CI (a48bfa67)
- helpers2.1: when using ynh_die, also return the error via YNH_STDRETURN such that it can be obtained from the python and displayed in the main error message, to increase the chance that people may read it and have something more useful than "An error happened in the script" (f2b5f0f2)
- helpers2.1: remove the ynh_clean_setup mechanism underused/useless.. (1c62960e)
- helpers2.1: switch to posisional args for ynh_multimedia_addaccess because that's what 99% of apps already do (ef622ffe)
- helpers2.1: add support for downloading .tar files ([#1889](http://github.com/YunoHost/yunohost/pull/1889))
- services/diagnosis: automatically ignore the service in diagnosis if it has been deactivated with the ynh cli ([#1886](http://github.com/YunoHost/yunohost/pull/1886))
Thanks to all contributors <3 ! (alexAubin, OniriCorpe, Sebastian Gumprich)
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 01 Jul 2024 18:46:52 +0200
yunohost (11.2.19) stable; urgency=low
- apps: tweaks to be more robust and prevent the stupid flood of 'sh: 0: getcwd() failed: No such file or directory' when running an app upgrade/remove from /var/www/$app, sometimes making it look like the upgrade failed when it didnt (a349fc03)
- apps: be more robust when an app upgrade succeeds but for some reason is marked with 'broke the system' ... ending up in inconsistent state between the app settings vs the app scritpts (for example in v1->v2 transitions but not only) (e5b57590)
- helpers2.1: Fix getopts error handling ... (3e1c9eba)
- helpers2.1: also run _ynh_apply_default_permissions in ynh_restore to be consistent (also because the user uid on the new system may be different than in the archive etc) (eee84c5f)
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 29 Jun 2024 23:55:52 +0200
yunohost (11.2.18) stable; urgency=low
- helpers2.1: Rework _ynh_apply_default_permissions to hopefully remove the necessity to chown/chmod in the app scripts ([#1883](http://github.com/YunoHost/yunohost/pull/1883))
- helpers2.1: in logrotate, make sure to also chown $app the log dir (1dfc47d1d)
- helpers2.1: forgot to rename the apt call in mongodb helpers (7b2959a3e)
- helpers2.1: in ynh_safe_rm, check if target is not a broken symlink before erorring out ([#1716](http://github.com/YunoHost/yunohost/pull/1716))
Thanks to all contributors <3 ! (Félix Piédallu)
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 29 Jun 2024 18:05:04 +0200
yunohost (11.2.17.1) stable; urgency=low
- helpers2.1: fix __PATH__/ handling (997388dc)
- ci: Fix helpers 2.1 doc location (7347b08e)
- helpers/doc: De-hide some helpers v1 in documentation now that the structure is less bloated sort of ? (2a7fefae)
- helpers/doc: fix detail block, cant use the HTML <details> because grav doesnt interpret markdown in it (feb9a095)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 25 Jun 2024 14:19:58 +0200
yunohost (11.2.17) stable; urgency=low
- helpers: Misc cleaning / reorganizing to prepare new doc (2895d4d9)
- helpers: rework helper doc now that we have multiple versions of helpers in parallel + improve structure (group helper file in categories) (094cd9dd)
- helpers/mongo: less noisy output when checking the avx flag is here in /proc/cpuinfo (2af4c157)
- apps/helpers2.1: fix app env in resource upgrade context ending up in incorrect helper version being used (ed426f05)
- helpers2.1: forgot to propagate the 'goenv latest' fix from helpers v1 (d8c3ff4c)
- helpers2.1: drop ynh_apps helper because only a single app is using it ... (1fb80e5d)
- helpers2.1: other typo fixes
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 24 Jun 2024 22:36:32 +0200
yunohost (11.2.16) stable; urgency=low
- apps/logs: fix some information not being redacted because of the packaging v2 flows (a25033bb)
- logs: misc ad-hoc tweaks to limit the noise in log sharing (06c8fbc8)
- helpers: (1/2/2.1) add a new ynh_app_setting_set_default to replace the unecessarily complex 'if [ -z ${foo:-} ]' trick ([#1873](http://github.com/YunoHost/yunohost/pull/1873))
- helpers2.1: drop unused 'local source' mechanism from ynh_setup_source (dd8db188)
- helpers2.1: fix positional arg parsing in ynh_psql_create_user (e5585136)
- helpers2.1: rework the fpm usage/footprint madness ([#1874](http://github.com/YunoHost/yunohost/pull/1874))
- helpers2.1: fix ynh_config_add_logrotate when no arg is passed (3942ea12)
- helpers2.1: sudo -u$app -> sudo -u $app (d4857834)
- helpers2.1: change default timeout of ynh_systemctl to 60s instead of 300s (262453f1)
- helpers2.1: display 100 lines instead of 20 in CI context when service fails to start (9298738d)
- helpers2.1: when using ynh_systemctl to reload/start/restart a service with a wait_until and it timesout, handle it as a failure rather than keep going (b3409729)
- helpers2.1: for some reason sudo -E doesn't preserve PATH even though it's exported, so we gotta explicitly use --preserve-env=PATH (5f6df6a8)
- helpers2.1: var rename / cosmetic etc for nodejs/ruby/go version and install directories (2b1f7426)
- i18n: Translations updated for Basque, Slovak
Thanks to all contributors <3 ! (alexAubin, Jose Riha, xabirequejo)
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 23 Jun 2024 15:30:22 +0200
yunohost (11.2.15) stable; urgency=low yunohost (11.2.15) stable; urgency=low
- apps: new experimentals "2.1" helpers ([#1855](http://github.com/YunoHost/yunohost/pull/1855)) - apps: new experimentals "2.1" helpers ([#1855](http://github.com/YunoHost/yunohost/pull/1855))

6
debian/control vendored
View file

@ -10,14 +10,14 @@ Package: yunohost
Essential: yes Essential: yes
Architecture: all Architecture: all
Depends: ${python3:Depends}, ${misc:Depends} Depends: ${python3:Depends}, ${misc:Depends}
, moulinette (>= 11.1), ssowat (>= 11.1) , moulinette (>= 11.1), moulinette (<< 12.0), ssowat (>= 11.1), ssowat (<< 12.0)
, python3-psutil, python3-requests, python3-dnspython, python3-openssl , python3-psutil, python3-requests, python3-dnspython, python3-openssl
, python3-miniupnpc, python3-dbus, python3-jinja2 , python3-miniupnpc, python3-dbus, python3-jinja2
, python3-toml, python3-packaging, python3-publicsuffix2 , python3-toml, python3-packaging, python3-publicsuffix2
, python3-ldap, python3-zeroconf (>= 0.36), python3-lexicon, , python3-ldap, python3-zeroconf (>= 0.36), python3-lexicon,
, python-is-python3 , python-is-python3
, nginx, nginx-extras (>=1.18) , nginx, nginx-extras (>=1.18)
, apt, apt-transport-https, apt-utils, dirmngr , apt, apt-transport-https, apt-utils, aptitude, dirmngr
, openssh-server, iptables, fail2ban, bind9-dnsutils , openssh-server, iptables, fail2ban, bind9-dnsutils
, openssl, ca-certificates, netcat-openbsd, iproute2 , openssl, ca-certificates, netcat-openbsd, iproute2
, slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd , slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd
@ -28,7 +28,7 @@ Depends: ${python3:Depends}, ${misc:Depends}
, redis-server , redis-server
, acl , acl
, git, curl, wget, cron, unzip, jq, bc, at, procps, j2cli , git, curl, wget, cron, unzip, jq, bc, at, procps, j2cli
, lsb-release, haveged, fake-hwclock, equivs, lsof, whois , lsb-release, haveged, fake-hwclock, lsof, whois
Recommends: yunohost-admin Recommends: yunohost-admin
, ntp, inetutils-ping | iputils-ping , ntp, inetutils-ping | iputils-ping
, bash-completion, rsyslog , bash-completion, rsyslog

2
debian/postinst vendored
View file

@ -27,7 +27,7 @@ do_configure() {
yunohost tools migrations run --auto yunohost tools migrations run --auto
echo "Re-diagnosing server health..." 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..." echo "Refreshing app catalog..."
yunohost tools update apps --output-as none || true yunohost tools update apps --output-as none || true

View file

@ -1,10 +1,55 @@
#!/usr/env/python3 #!/usr/env/python3
import sys
import os import os
import glob import glob
import datetime import datetime
import subprocess import subprocess
tree = {
"sources": {
"title": "Sources",
"notes": "This is coupled to the 'sources' resource in the manifest.toml",
"subsections": ["sources"],
},
"tech": {
"title": "App technologies",
"notes": "These allow to install specific version of the technology required to run some apps",
"subsections": ["nodejs", "ruby", "go", "composer"],
},
"db": {
"title": "Databases",
"notes": "This is coupled to the 'database' resource in the manifest.toml - at least for mysql/postgresql. Mongodb/redis may have better integration in the future.",
"subsections": ["mysql", "postgresql", "mongodb", "redis"],
},
"conf": {
"title": "Configurations / templating",
"subsections": [
"templating",
"nginx",
"php",
"systemd",
"fail2ban",
"logrotate",
],
},
"misc": {
"title": "Misc tools",
"subsections": [
"utils",
"setting",
"string",
"backup",
"logging",
"multimedia",
],
},
"meh": {
"title": "Deprecated or handled by the core / app resources since v2",
"subsections": ["permission", "apt", "systemuser"],
},
}
def get_current_commit(): def get_current_commit():
p = subprocess.Popen( p = subprocess.Popen(
@ -19,14 +64,7 @@ def get_current_commit():
return current_commit return current_commit
def render(helpers): def render(tree, helpers_version):
current_commit = get_current_commit()
data = {
"helpers": helpers,
"date": datetime.datetime.now().strftime("%d/%m/%Y"),
"version": open("../debian/changelog").readlines()[0].split()[1].strip("()"),
}
from jinja2 import Template from jinja2 import Template
from ansi2html import Ansi2HTMLConverter from ansi2html import Ansi2HTMLConverter
@ -42,12 +80,15 @@ def render(helpers):
t = Template(template) t = Template(template)
t.globals["now"] = datetime.datetime.utcnow t.globals["now"] = datetime.datetime.utcnow
result = t.render( result = t.render(
current_commit=current_commit, tree=tree,
data=data, date=datetime.datetime.now().strftime("%d/%m/%Y"),
version=open("../debian/changelog").readlines()[0].split()[1].strip("()"),
helpers_version=helpers_version,
current_commit=get_current_commit(),
convert=shell_to_html, convert=shell_to_html,
shell_css=shell_css, shell_css=shell_css,
) )
open("helpers.md", "w").write(result) open(f"helpers.v{helpers_version}.md", "w").write(result)
############################################################################## ##############################################################################
@ -87,7 +128,7 @@ class Parser:
# We're still in a comment bloc # We're still in a comment bloc
assert line.startswith("# ") or line == "#", malformed_error(i) assert line.startswith("# ") or line == "#", malformed_error(i)
current_block["comments"].append(line[2:]) current_block["comments"].append(line[2:])
elif line.strip() == "": elif line.strip() == "" or line.startswith("_ynh"):
# Well eh that was not an actual helper definition ... start over ? # Well eh that was not an actual helper definition ... start over ?
current_reading = "void" current_reading = "void"
current_block = { current_block = {
@ -121,7 +162,11 @@ class Parser:
# (we ignore helpers containing [internal] ...) # (we ignore helpers containing [internal] ...)
if ( if (
"[packagingv1]" not in current_block["comments"] "[packagingv1]" not in current_block["comments"]
and "[internal]" not in current_block["comments"] and not any(
line.startswith("[internal]")
for line in current_block["comments"]
)
and not current_block["name"].startswith("_")
): ):
self.blocks.append(current_block) self.blocks.append(current_block)
current_block = { current_block = {
@ -212,23 +257,27 @@ def malformed_error(line_number):
def main(): def main():
helper_files = sorted(glob.glob("../helpers/*"))
helpers = []
for helper_file in helper_files: if len(sys.argv) == 1:
if not os.path.isfile(helper_file): print("This script needs the helper version (1, 2, 2.1) as an argument")
continue sys.exit(1)
category_name = os.path.basename(helper_file) version = sys.argv[1]
print("Parsing %s ..." % category_name)
p = Parser(helper_file)
p.parse_blocks()
for b in p.blocks:
p.parse_block(b)
helpers.append((category_name, p.blocks)) for section in tree.values():
section["helpers"] = {}
for subsection in section["subsections"]:
print(f"Parsing {subsection} ...")
helper_file = f"../helpers/helpers.v{version}.d/{subsection}"
assert os.path.isfile(helper_file), f"Uhoh, {file} doesn't exists?"
p = Parser(helper_file)
p.parse_blocks()
for b in p.blocks:
p.parse_block(b)
render(helpers) section["helpers"][subsection] = p.blocks
render(tree, version)
main() main()

View file

@ -1,18 +1,26 @@
--- ---
title: App helpers title: App helpers (v{{ helpers_version }})
template: docs template: docs
taxonomy: taxonomy:
category: docs category: docs
routes: routes:
default: '/packaging_apps_helpers' default: '/packaging_apps_helpers{% if helpers_version not in ["1", "2"] %}_v{{ helpers_version }}{% endif %}'
--- ---
Doc auto-generated by [this script](https://github.com/YunoHost/yunohost/blob/{{ current_commit }}/doc/generate_helper_doc.py) on {{data.date}} (YunoHost version {{data.version}}) Doc auto-generated by [this script](https://github.com/YunoHost/yunohost/blob/{{ current_commit }}/doc/generate_helper_doc.py) on {{date}} (YunoHost version {{version}})
{% for section_id, section in tree.items() %}
## {{ section["title"].title() }}
{% if section['notes'] %}<p>{{ section['notes'] }}</p>{% endif %}
{% for subsection, helpers in section["helpers"].items() %}
### {{ subsection.upper() }}
{% for h in helpers %}
#### {{ h.name }}
{% for category, helpers in data.helpers %}
## {{ category.upper() }}
{% for h in helpers %}
### {{ h.name }}
[details summary="<i>{{ h.brief }}</i>" class="helper-card-subtitle text-muted"] [details summary="<i>{{ h.brief }}</i>" class="helper-card-subtitle text-muted"]
**Usage**: `{{ h.usage }}` **Usage**: `{{ h.usage }}`
@ -51,9 +59,9 @@ Doc auto-generated by [this script](https://github.com/YunoHost/yunohost/blob/{{
**Details**: **Details**:
{{ h.details }} {{ h.details }}
{%- endif %} {%- endif %}
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/{{ current_commit }}/helpers/{{ category }}#L{{ h.line + 1 }}) [Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/{{ current_commit }}/helpers/helpers.v{{ helpers_version if helpers_version != "2" else "1" }}.d/{{ subsection }}#L{{ h.line + 1 }})
[/details] [/details]
{% endfor %}
--- ---
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Entrypoint for the helpers scripts # 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. # Helpers version can be specified via an environment variable or default to 1.
YNH_HELPERS_VERSION=${YNH_HELPERS_VERSION:-1} YNH_HELPERS_VERSION=${YNH_HELPERS_VERSION:-1}
@ -13,6 +13,7 @@ YNH_HELPERS_DIR="$SCRIPT_DIR/helpers.v${YNH_HELPERS_VERSION}.d"
case "$YNH_HELPERS_VERSION" in case "$YNH_HELPERS_VERSION" in
"1" | "2" | "2.1") "1" | "2" | "2.1")
readarray -t HELPERS < <(find -L "$YNH_HELPERS_DIR" -mindepth 1 -maxdepth 1 -type f) readarray -t HELPERS < <(find -L "$YNH_HELPERS_DIR" -mindepth 1 -maxdepth 1 -type f)
source $YNH_HELPERS_DIR/getopts
for helper in "${HELPERS[@]}"; do for helper in "${HELPERS[@]}"; do
[ -r "$helper" ] && source "$helper" [ -r "$helper" ] && source "$helper"
done done
@ -20,6 +21,7 @@ case "$YNH_HELPERS_VERSION" in
*) *)
echo "Helpers are not available in version '$YNH_HELPERS_VERSION'." >&2 echo "Helpers are not available in version '$YNH_HELPERS_VERSION'." >&2
exit 1 exit 1
;;
esac esac
eval "$XTRACE_ENABLE" eval "$XTRACE_ENABLE"

View file

@ -7,52 +7,49 @@
# #
# Requires YunoHost version *.*.* or higher. # Requires YunoHost version *.*.* or higher.
ynh_install_apps() { ynh_install_apps() {
# Declare an array to define the options of this helper. # Declare an array to define the options of this helper.
local legacy_args=a local legacy_args=a
local -A args_array=([a]=apps=) local -A args_array=([a]=apps=)
local apps local apps
# Manage arguments with getopts # Manage arguments with getopts
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
# Split the list of apps in an array # Split the list of apps in an array
local apps_list=($(echo $apps | tr " " "\n")) local apps_list=($(echo $apps | tr " " "\n"))
local apps_dependencies="" 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"
yunohost tools update apps # For each app
for one_app_and_its_args in "${apps_list[@]}"; do
# Installing or upgrading the app depending if it's installed or not # Retrieve the name of the app (part before ?)
if ! yunohost app list --output-as json --quiet | jq -e --arg id $one_app '.apps[] | select(.id == $id)' >/dev/null local one_app=$(cut -d "?" -f1 <<< "$one_app_and_its_args")
then [ -z "$one_app" ] && ynh_die --message="You didn't provided a YunoHost app to install"
# 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" ] yunohost tools update apps
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" # 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 # Remove other YunoHost apps
@ -63,53 +60,47 @@ ynh_install_apps() {
# #
# Requires YunoHost version *.*.* or higher. # Requires YunoHost version *.*.* or higher.
ynh_remove_apps() { ynh_remove_apps() {
# Retrieve the apps dependencies of the app # Retrieve the apps dependencies of the app
local apps_dependencies=$(ynh_app_setting_get --app=$app --key=apps_dependencies) local apps_dependencies=$(ynh_app_setting_get --app=$app --key=apps_dependencies)
ynh_app_setting_delete --app=$app --key=apps_dependencies ynh_app_setting_delete --app=$app --key=apps_dependencies
if [ ! -z "$apps_dependencies" ] if [ ! -z "$apps_dependencies" ]; then
then # Split the list of apps dependencies in an array
# Split the list of apps dependencies in an array local apps_dependencies_list=($(echo $apps_dependencies | tr ", " "\n"))
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=""
# For each other installed app # For each apps dependencies
for one_installed_app in $installed_apps_list for one_app in "${apps_dependencies_list[@]}"; do
do # Retrieve the list of installed apps
# Retrieve the other apps dependencies local installed_apps_list=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
one_installed_apps_dependencies=$(ynh_app_setting_get --app=$one_installed_app --key=apps_dependencies) local required_by=""
if [ ! -z "$one_installed_apps_dependencies" ] local installed_app_required_by=""
then
one_installed_apps_dependencies_list=($(echo $one_installed_apps_dependencies | tr ", " "\n"))
# For each dependency of the other apps # For each other installed app
for one_installed_app_dependency in "${one_installed_apps_dependencies_list[@]}" for one_installed_app in $installed_apps_list; do
do # Retrieve the other apps dependencies
if [[ $one_installed_app_dependency == $one_app ]]; then one_installed_apps_dependencies=$(ynh_app_setting_get --app=$one_installed_app --key=apps_dependencies)
required_by="$required_by $one_installed_app" if [ ! -z "$one_installed_apps_dependencies" ]; then
fi one_installed_apps_dependencies_list=($(echo $one_installed_apps_dependencies | tr ", " "\n"))
done
fi
done
# If $one_app is no more required # For each dependency of the other apps
if [[ -z "$required_by" ]] for one_installed_app_dependency in "${one_installed_apps_dependencies_list[@]}"; do
then if [[ $one_installed_app_dependency == $one_app ]]; then
# Remove $one_app required_by="$required_by $one_installed_app"
ynh_print_info --message="Removing of $one_app" fi
yunohost app remove $one_app --purge done
else fi
ynh_print_info --message="$one_app was not removed because it's still required by${required_by}" done
fi
done # If $one_app is no more required
fi 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 # 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). # 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. # 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() { ynh_spawn_app_shell() {
# Declare an array to define the options of this helper. # Declare an array to define the options of this helper.
local legacy_args=a local legacy_args=a
local -A args_array=([a]=app=) local -A args_array=([a]=app=)
local app local app
# Manage arguments with getopts # Manage arguments with getopts
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
# Force Bash to be used to run this helper # Force Bash to be used to run this helper
if [[ ! $0 =~ \/?bash$ ]] if [[ ! $0 =~ \/?bash$ ]]; then
then ynh_print_err --message="Please use Bash as shell"
ynh_print_err --message="Please use Bash as shell" exit 1
exit 1 fi
fi
# Make sure the app is installed # Make sure the app is installed
local installed_apps_list=($(yunohost app list --output-as json --quiet | jq -r .apps[].id)) local installed_apps_list=($(yunohost app list --output-as json --quiet | jq -r .apps[].id))
if [[ " ${installed_apps_list[*]} " != *" ${app} "* ]] if [[ " ${installed_apps_list[*]} " != *" ${app} "* ]]; then
then ynh_print_err --message="$app is not in the apps list"
ynh_print_err --message="$app is not in the apps list" exit 1
exit 1 fi
fi
# Make sure the app has its own user # Make sure the app has its own user
if ! id -u "$app" &>/dev/null; then if ! id -u "$app" &> /dev/null; then
ynh_print_err --message="There is no \"$app\" system user" ynh_print_err --message="There is no \"$app\" system user"
exit 1 exit 1
fi fi
# Make sure the app has an install_dir setting # Make sure the app has an install_dir setting
local install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) local install_dir=$(ynh_app_setting_get --app=$app --key=install_dir)
if [ -z "$install_dir" ] if [ -z "$install_dir" ]; then
then ynh_print_err --message="$app has no install_dir setting (does it use packaging format >=2?)"
ynh_print_err --message="$app has no install_dir setting (does it use packaging format >=2?)" exit 1
exit 1 fi
fi
# Load the app's service name, or default to $app # Load the app's service name, or default to $app
local service=$(ynh_app_setting_get --app=$app --key=service) local service=$(ynh_app_setting_get --app=$app --key=service)
[ -z "$service" ] && service=$app; [ -z "$service" ] && service=$app
# Export HOME variable # Export HOME variable
export HOME=$install_dir; export HOME=$install_dir
# Load the Environment variables from the app's service # Load the Environment variables from the app's service
local env_var=$(systemctl show $service.service -p "Environment" --value) local env_var=$(systemctl show $service.service -p "Environment" --value)
[ -n "$env_var" ] && export $env_var; [ -n "$env_var" ] && export $env_var
# Force `php` to its intended version # Force `php` to its intended version
# We use `eval`+`export` since `alias` is not propagated to subshells, even with `export` # 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 phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
local phpflags=$(ynh_app_setting_get --app=$app --key=phpflags) local phpflags=$(ynh_app_setting_get --app=$app --key=phpflags)
if [ -n "$phpversion" ] if [ -n "$phpversion" ]; then
then eval "php() { php${phpversion} ${phpflags} \"\$@\"; }"
eval "php() { php${phpversion} ${phpflags} \"\$@\"; }" export -f php
export -f php fi
fi
# Source the EnvironmentFiles from the app's service # Source the EnvironmentFiles from the app's service
local env_files=($(systemctl show $service.service -p "EnvironmentFiles" --value)) local env_files=($(systemctl show $service.service -p "EnvironmentFiles" --value))
if [ ${#env_files[*]} -gt 0 ] if [ ${#env_files[*]} -gt 0 ]; then
then # set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`. set -a
set -a for file in ${env_files[*]}; do
for file in ${env_files[*]} [[ $file = /* ]] && source $file
do done
[[ $file = /* ]] && source $file set +a
done fi
set +a
fi
# Activate the Python environment, if it exists # Activate the Python environment, if it exists
if [ -f $install_dir/venv/bin/activate ] if [ -f $install_dir/venv/bin/activate ]; then
then # set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`. set -a
set -a source $install_dir/venv/bin/activate
source $install_dir/venv/bin/activate set +a
set +a fi
fi
# cd into the WorkingDirectory set in the service, or default to the install_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) local env_dir=$(systemctl show $service.service -p "WorkingDirectory" --value)
[ -z $env_dir ] && env_dir=$install_dir; [ -z $env_dir ] && env_dir=$install_dir
cd $env_dir cd $env_dir
# Spawn the app shell # Spawn the app shell
su -s /bin/bash $app 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 # With seq 1 17, timeout will be almost 30 minutes
for try in $(seq 1 17); do for try in $(seq 1 17); do
# Check if /var/lib/dpkg/lock is used by another process # 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..." echo "apt is already in use..."
# Sleep an exponential time at each round # Sleep an exponential time at each round
sleep $((try * try)) sleep $((try * try))
@ -32,7 +32,7 @@ ynh_wait_dpkg_free() {
set -o xtrace # set -x set -o xtrace # set -x
return 1 return 1
fi fi
done 9<<<"$(ls -1 $dpkg_dir)" done 9<<< "$(ls -1 $dpkg_dir)"
set -o xtrace # set -x set -o xtrace # set -x
return 0 return 0
fi fi
@ -58,8 +58,8 @@ ynh_package_is_installed() {
# Manage arguments with getopts # Manage arguments with getopts
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
dpkg-query --show --showformat='${Status}' "$package" 2>/dev/null \ dpkg-query --show --showformat='${Status}' "$package" 2> /dev/null \
| grep --count "ok installed" &>/dev/null | grep --count "ok installed" &> /dev/null
} }
# Get the version of an installed package # Get the version of an installed package
@ -82,7 +82,7 @@ ynh_package_version() {
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
if ynh_package_is_installed "$package"; then 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 else
echo '' echo ''
fi fi
@ -186,22 +186,25 @@ ynh_package_install_from_equivs() {
# Build and install the package # Build and install the package
local TMPDIR=$(mktemp --directory) local TMPDIR=$(mktemp --directory)
mkdir -p ${TMPDIR}/${pkgname}/DEBIAN/
# Make sure to delete the legacy compat file # For some reason, dpkg-deb insists for folder perm to be 755 and sometimes it's 777 o_O?
# It's now handle somewhat magically through the control file chmod -R 755 ${TMPDIR}/${pkgname}
rm -f /usr/share/equivs/template/debian/compat
# Note that the cd executes into a sub shell # Note that the cd executes into a sub shell
# Create a fake deb package with equivs-build and the given control file # Create a fake deb package with equivs-build and the given control file
# Install the fake package without its dependencies with dpkg # Install the fake package without its dependencies with dpkg
# Install missing dependencies with ynh_package_install # Install missing dependencies with ynh_package_install
ynh_wait_dpkg_free ynh_wait_dpkg_free
cp "$controlfile" "${TMPDIR}/control"
( cp "$controlfile" "${TMPDIR}/${pkgname}/DEBIAN/control"
cd "$TMPDIR"
LC_ALL=C equivs-build ./control 2>&1 # Install the fake package without its dependencies with dpkg --force-depends
LC_ALL=C dpkg --force-depends --install "./${pkgname}_${pkgversion}_all.deb" 2>&1 | tee ./dpkg_log if ! LC_ALL=C dpkg-deb --build "${TMPDIR}/${pkgname}" "${TMPDIR}/${pkgname}.deb" > "${TMPDIR}/dpkg_log" 2>&1; then
) cat "${TMPDIR}/dpkg_log" >&2
ynh_die --message="Unable to install dependencies"
fi
# Don't crash in case of error, because is nicely covered by the following line
LC_ALL=C dpkg --force-depends --install "${TMPDIR}/${pkgname}.deb" 2>&1 | tee "${TMPDIR}/dpkg_log" || true
ynh_package_install --fix-broken \ ynh_package_install --fix-broken \
|| { # If the installation failed || { # If the installation failed
@ -224,8 +227,6 @@ YNH_INSTALL_APP_DEPENDENCIES_REPLACE="true"
# Define and install dependencies with a equivs control file # Define and install dependencies with a equivs control file
# #
# [packagingv1]
#
# This helper can/should only be called once per app # This helper can/should only be called once per app
# #
# example : ynh_install_app_dependencies dep1 dep2 "dep3|dep4|dep5" # example : ynh_install_app_dependencies dep1 dep2 "dep3|dep4|dep5"
@ -265,8 +266,7 @@ ynh_install_app_dependencies() {
# The (?<=php) syntax corresponds to lookbehind ;) # The (?<=php) syntax corresponds to lookbehind ;)
local specific_php_version=$(echo $dependencies | grep -oP '(?<=php)[0-9.]+(?=-|\>|)' | sort -u) local specific_php_version=$(echo $dependencies | grep -oP '(?<=php)[0-9.]+(?=-|\>|)' | sort -u)
if [[ -n "$specific_php_version" ]] if [[ -n "$specific_php_version" ]]; then
then
# Cover a small edge case where a packager could have specified "php7.4-pwet php5-gni" which is confusing # 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 ]] \ [[ $(echo $specific_php_version | wc -l) -eq 1 ]] \
|| ynh_die --message="Inconsistent php versions in dependencies ... found : $specific_php_version" || ynh_die --message="Inconsistent php versions in dependencies ... found : $specific_php_version"
@ -280,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_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" local old_php_finalphpconf="$old_php_fpm_config_dir/pool.d/$app.conf"
if [[ -f "$old_php_finalphpconf" ]] if [[ -f "$old_php_finalphpconf" ]]; then
then
ynh_backup_if_checksum_is_different --file="$old_php_finalphpconf" ynh_backup_if_checksum_is_different --file="$old_php_finalphpconf"
ynh_remove_fpm_config ynh_remove_fpm_config
fi fi
@ -290,8 +289,7 @@ ynh_install_app_dependencies() {
ynh_app_setting_set --app=$app --key=phpversion --value=$specific_php_version 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. # Set the default php version back as the default version for php-cli.
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
then
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
fi fi
elif grep --quiet 'php' <<< "$dependencies"; then elif grep --quiet 'php' <<< "$dependencies"; then
@ -305,26 +303,25 @@ ynh_install_app_dependencies() {
# upgrade script where ynh_install_app_dependencies is called with this # upgrade script where ynh_install_app_dependencies is called with this
# expected effect) Otherwise, any subsequent call will add dependencies # expected effect) Otherwise, any subsequent call will add dependencies
# to those already present in the equivs control file. # to those already present in the equivs control file.
if [[ $YNH_INSTALL_APP_DEPENDENCIES_REPLACE == "true" ]] if [[ $YNH_INSTALL_APP_DEPENDENCIES_REPLACE == "true" ]]; then
then
YNH_INSTALL_APP_DEPENDENCIES_REPLACE="false" YNH_INSTALL_APP_DEPENDENCIES_REPLACE="false"
else else
local current_dependencies="" local current_dependencies=""
if ynh_package_is_installed --package="${dep_app}-ynh-deps" if ynh_package_is_installed --package="${dep_app}-ynh-deps"; then
then
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${dep_app}-ynh-deps) " current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${dep_app}-ynh-deps) "
current_dependencies=${current_dependencies// | /|} current_dependencies=${current_dependencies// | /|}
fi fi
dependencies="$current_dependencies, $dependencies" dependencies="$current_dependencies, $dependencies"
fi 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 Section: misc
Priority: optional Priority: optional
Package: ${dep_app}-ynh-deps Package: ${dep_app}-ynh-deps
Version: ${version} Version: ${version}
Depends: ${dependencies} Depends: ${dependencies//,,/,}
Architecture: all Architecture: all
Maintainer: root@localhost
Description: Fake package for ${app} (YunoHost app) dependencies Description: Fake package for ${app} (YunoHost app) dependencies
This meta-package is only responsible of installing its dependencies. This meta-package is only responsible of installing its dependencies.
EOF EOF
@ -335,8 +332,7 @@ EOF
# Trigger postgresql regenconf if we may have just installed postgresql # Trigger postgresql regenconf if we may have just installed postgresql
local psql_installed2="$(ynh_package_is_installed "postgresql-$PSQL_VERSION" && echo yes || echo no)" local psql_installed2="$(ynh_package_is_installed "postgresql-$PSQL_VERSION" && echo yes || echo no)"
if [[ "$psql_installed" != "$psql_installed2" ]] if [[ "$psql_installed" != "$psql_installed2" ]]; then
then
yunohost tools regen-conf postgresql yunohost tools regen-conf postgresql
fi fi
@ -364,15 +360,13 @@ ynh_add_app_dependencies() {
# Remove fake package and its dependencies # Remove fake package and its dependencies
# #
# [packagingv1]
#
# Dependencies will removed only if no other package need them. # Dependencies will removed only if no other package need them.
# #
# usage: ynh_remove_app_dependencies # usage: ynh_remove_app_dependencies
# #
# Requires YunoHost version 2.6.4 or higher. # Requires YunoHost version 2.6.4 or higher.
ynh_remove_app_dependencies() { ynh_remove_app_dependencies() {
local dep_app=${app//_/-} # Replace all '_' by '-' local dep_app=${app//_/-} # Replace all '_' by '-'
local current_dependencies="" 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
@ -382,24 +376,20 @@ ynh_remove_app_dependencies() {
# Edge case where the app dep may be on hold, # Edge case where the app dep may be on hold,
# cf https://forum.yunohost.org/t/migration-error-cause-of-ffsync/20675/4 # cf https://forum.yunohost.org/t/migration-error-cause-of-ffsync/20675/4
if apt-mark showhold | grep -q -w ${dep_app}-ynh-deps if apt-mark showhold | grep -q -w ${dep_app}-ynh-deps; then
then
apt-mark unhold ${dep_app}-ynh-deps apt-mark unhold ${dep_app}-ynh-deps
fi fi
# Remove the fake package and its dependencies if they not still used. # Remove the fake package and its dependencies if they not still used.
# (except if dpkg doesn't know anything about the package, # (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) # 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 if dpkg-query --show ${dep_app}-ynh-deps &> /dev/null; then
then
ynh_package_autopurge ${dep_app}-ynh-deps ynh_package_autopurge ${dep_app}-ynh-deps
fi fi
} }
# Install packages from an extra repository properly. # Install packages from an extra repository properly.
# #
# [packagingv1]
#
# usage: ynh_install_extra_app_dependencies --repo="repo" --package="dep1 dep2" [--key=key_url] [--name=name] # usage: ynh_install_extra_app_dependencies --repo="repo" --package="dep1 dep2" [--key=key_url] [--name=name]
# | arg: -r, --repo= - Complete url of the extra repository. # | arg: -r, --repo= - Complete url of the extra repository.
# | arg: -p, --package= - The packages to install from this extra repository # | arg: -p, --package= - The packages to install from this extra repository
@ -476,21 +466,31 @@ ynh_install_extra_repo() {
wget_append="tee" wget_append="tee"
fi fi
# Split the repository into uri, suite and components. if [[ "$key" == "trusted=yes" ]]; then
trusted="--trusted"
else
trusted=""
fi
IFS=', ' read -r -a repo_parts <<< "$repo"
index=0
# Remove "deb " at the beginning of the repo. # Remove "deb " at the beginning of the repo.
repo="${repo#deb }" if [[ "${repo_parts[0]}" == "deb" ]]; then
index=1
# Get the uri fi
local uri="$(echo "$repo" | awk '{ print $1 }')" uri="${repo_parts[$index]}"
index=$((index + 1))
# Get the suite suite="${repo_parts[$index]}"
local suite="$(echo "$repo" | awk '{ print $2 }')" index=$((index + 1))
# Get the components # Get the components
local component="${repo##$uri $suite }" if (("${#repo_parts[@]}" > 0)); then
component="${repo_parts[*]:$index}"
fi
# Add the repository into sources.list.d # Add the repository into sources.list.d
ynh_add_repo --uri="$uri" --suite="$suite" --component="$component" --name="$name" $append ynh_add_repo --uri="$uri" --suite="$suite" --component="$component" --name="$name" $append $trusted
# Pin the new repo with the default priority, so it won't be used for upgrades. # Pin the new repo with the default priority, so it won't be used for upgrades.
# Build $pin from the uri without http and any sub path # Build $pin from the uri without http and any sub path
@ -503,10 +503,10 @@ ynh_install_extra_repo() {
ynh_pin_repo --package="*" --pin="origin \"$pin\"" $priority --name="$name" $append ynh_pin_repo --package="*" --pin="origin \"$pin\"" $priority --name="$name" $append
# Get the public key for the repo # Get the public key for the repo
if [ -n "$key" ]; then if [ -n "$key" ] && [[ "$key" != "trusted=yes" ]]; then
mkdir --parents "/etc/apt/trusted.gpg.d" 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) # 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 fi
# Update the list of package with the new repo # Update the list of package with the new repo
@ -556,6 +556,7 @@ ynh_remove_extra_repo() {
# | arg: -c, --component= - Component of the repository. # | arg: -c, --component= - Component of the repository.
# | arg: -n, --name= - Name for the files for this repo, $app as default value. # | arg: -n, --name= - Name for the files for this repo, $app as default value.
# | arg: -a, --append - Do not overwrite existing files. # | arg: -a, --append - Do not overwrite existing files.
# | arg: -t, --trusted - Add trusted=yes to the repository (not recommended)
# #
# Example for a repo like deb http://forge.yunohost.org/debian/ stretch stable # Example for a repo like deb http://forge.yunohost.org/debian/ stretch stable
# uri suite component # uri suite component
@ -564,27 +565,34 @@ ynh_remove_extra_repo() {
# Requires YunoHost version 3.8.1 or higher. # Requires YunoHost version 3.8.1 or higher.
ynh_add_repo() { ynh_add_repo() {
# Declare an array to define the options of this helper. # Declare an array to define the options of this helper.
local legacy_args=uscna local legacy_args=uscnat
local -A args_array=([u]=uri= [s]=suite= [c]=component= [n]=name= [a]=append) local -A args_array=([u]=uri= [s]=suite= [c]=component= [n]=name= [a]=append [t]=trusted)
local uri local uri
local suite local suite
local component local component
local name local name
local append local append
local trusted
# Manage arguments with getopts # Manage arguments with getopts
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
name="${name:-$app}" name="${name:-$app}"
append=${append:-0} append=${append:-0}
trusted=${trusted:-0}
if [ $append -eq 1 ]; then if [ $append -eq 1 ]; then
append="tee --append" append="tee --append"
else else
append="tee" append="tee"
fi fi
if [[ "$trusted" -eq 1 ]]; then
trust="[trusted=yes]"
else
trust=""
fi
mkdir --parents "/etc/apt/sources.list.d" mkdir --parents "/etc/apt/sources.list.d"
# Add the new repo in sources.list.d # Add the new repo in sources.list.d
echo "deb $uri $suite $component" \ echo "deb $trust $uri $suite $component" \
| $append "/etc/apt/sources.list.d/$name.list" | $append "/etc/apt/sources.list.d/$name.list"
} }

View file

@ -162,7 +162,7 @@ ynh_backup() {
# ============================================================================== # ==============================================================================
local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g') local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g')
local dest=$(echo "${dest_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 # 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 # 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 # 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}" if [[ "${dest_path}" == "/etc/nginx/conf.d/"* ]] && grep 'php7.3.*sock' "${dest_path}"; then
then
sed -i 's/php7.3/php7.4/g' "${dest_path}" sed -i 's/php7.3/php7.4/g' "${dest_path}"
fi fi
} }
@ -376,8 +375,7 @@ ynh_backup_if_checksum_is_different() {
echo "$backup_file_checksum" # Return the name of the backup file echo "$backup_file_checksum" # Return the name of the backup file
if [ ${PACKAGE_CHECK_EXEC:-0} -eq 1 ]; then if [ ${PACKAGE_CHECK_EXEC:-0} -eq 1 ]; then
local file_path_base64=$(echo "$file" | base64 -w0) local file_path_base64=$(echo "$file" | base64 -w0)
if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64} if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64}; then
then
ynh_print_warn "Diff with the original file:" 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 diff --report-identical-files --unified --color=always /var/cache/yunohost/appconfbackup/original_${file_path_base64} $file >&2 || true
fi fi
@ -412,7 +410,7 @@ ynh_delete_file_checksum() {
# #
ynh_backup_archive_exists() { ynh_backup_archive_exists() {
yunohost backup list --output-as json --quiet \ 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 # 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 the backup succeeded, remove the previous backup
if ynh_backup_archive_exists "$app_bck-pre-upgrade$old_backup_number"; then if ynh_backup_archive_exists "$app_bck-pre-upgrade$old_backup_number"; then
# Remove the previous backup only if it exists # 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 fi
else else
ynh_die --message="Backup failed, the upgrade process was aborted." ynh_die --message="Backup failed, the upgrade process was aborted."
@ -494,8 +492,7 @@ ynh_restore_upgradebackup() {
yunohost app remove $app yunohost app remove $app
# Restore the backup # Restore the backup
yunohost backup restore $app_bck-pre-upgrade$backup_number --apps $app --force --debug yunohost backup restore $app_bck-pre-upgrade$backup_number --apps $app --force --debug
if [[ -d /etc/yunohost/apps/$app ]] if [[ -d /etc/yunohost/apps/$app ]]; then
then
ynh_die --message="The app was restored to the way it was before the failed upgrade." ynh_die --message="The app was restored to the way it was before the failed upgrade."
else else
ynh_die --message="Uhoh ... Yunohost failed to restore the app to the way it was before the failed upgrade :|" ynh_die --message="Uhoh ... Yunohost failed to restore the app to the way it was before the failed upgrade :|"

View file

@ -0,0 +1,82 @@
#!/bin/bash
readonly YNH_DEFAULT_COMPOSER_VERSION=1.10.17
# Declare the actual composer version to use.
# A packager willing to use another version of composer can override the variable into its _common.sh.
YNH_COMPOSER_VERSION=${YNH_COMPOSER_VERSION:-$YNH_DEFAULT_COMPOSER_VERSION}
# Execute a command with Composer
#
# usage: ynh_composer_exec [--phpversion=phpversion] [--workdir=$install_dir] --commands="commands"
# | arg: -v, --phpversion - PHP version to use with composer
# | arg: -w, --workdir - The directory from where the command will be executed. Default $install_dir or $final_path
# | arg: -c, --commands - Commands to execute.
#
# Requires YunoHost version 4.2 or higher.
ynh_composer_exec() {
local _globalphpversion=${phpversion-:}
# Declare an array to define the options of this helper.
local legacy_args=vwc
declare -Ar args_array=([v]=phpversion= [w]=workdir= [c]=commands=)
local phpversion
local workdir
local commands
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
workdir="${workdir:-${install_dir:-$final_path}}"
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
phpversion="${phpversion:-$YNH_PHP_VERSION}"
else
phpversion="${phpversion:-$_globalphpversion}"
fi
COMPOSER_HOME="$workdir/.composer" COMPOSER_MEMORY_LIMIT=-1 \
php${phpversion} "$workdir/composer.phar" $commands \
-d "$workdir" --no-interaction --no-ansi 2>&1
}
# Install and initialize Composer in the given directory
#
# usage: ynh_install_composer [--phpversion=phpversion] [--workdir=$install_dir] [--install_args="--optimize-autoloader"] [--composerversion=composerversion]
# | arg: -v, --phpversion - PHP version to use with composer
# | arg: -w, --workdir - The directory from where the command will be executed. Default $install_dir.
# | arg: -a, --install_args - Additional arguments provided to the composer install. Argument --no-dev already include
# | arg: -c, --composerversion - Composer version to install
#
# Requires YunoHost version 4.2 or higher.
ynh_install_composer() {
local _globalphpversion=${phpversion-:}
# Declare an array to define the options of this helper.
local legacy_args=vwac
declare -Ar args_array=([v]=phpversion= [w]=workdir= [a]=install_args= [c]=composerversion=)
local phpversion
local workdir
local install_args
local composerversion
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
workdir="${workdir:-$final_path}"
else
workdir="${workdir:-$install_dir}"
fi
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
phpversion="${phpversion:-$YNH_PHP_VERSION}"
else
phpversion="${phpversion:-$_globalphpversion}"
fi
install_args="${install_args:-}"
composerversion="${composerversion:-$YNH_COMPOSER_VERSION}"
curl -sS https://getcomposer.org/installer \
| COMPOSER_HOME="$workdir/.composer" \
php${phpversion} -- --quiet --install-dir="$workdir" --version=$composerversion \
|| ynh_die --message="Unable to install Composer."
# install dependencies
ynh_composer_exec --phpversion="${phpversion}" --workdir="$workdir" --commands="install --no-dev $install_args" \
|| ynh_die --message="Unable to install core dependencies with Composer."
}

View file

@ -6,11 +6,11 @@ _ynh_app_config_get_one() {
local bind="$3" local bind="$3"
local getter="get__${short_setting}" local getter="get__${short_setting}"
# Get value from getter if exists # 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)" old[$short_setting]="$($getter)"
formats[${short_setting}]="yaml" 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)" old[$short_setting]="$("get__${bind%%(*}" $short_setting $type $bind)"
formats[${short_setting}]="yaml" formats[${short_setting}]="yaml"
@ -22,7 +22,7 @@ _ynh_app_config_get_one() {
if [[ "$bind" == "settings" ]]; then if [[ "$bind" == "settings" ]]; then
ynh_die --message="File '${short_setting}' can't be stored in settings" ynh_die --message="File '${short_setting}' can't be stored in settings"
fi 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" file_hash[$short_setting]="true"
# Get multiline text from settings or from a full file # Get multiline text from settings or from a full file
@ -32,7 +32,7 @@ _ynh_app_config_get_one() {
elif [[ "$bind" == *":"* ]]; then 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" 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 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 fi
# Get value from a kind of key/value file # 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_after="$(echo "${bind_key_}" | cut -d'>' -f1)"
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)" bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
fi 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}")" old[$short_setting]="$(ynh_read_var_in_file --file="${bind_file}" --key="${bind_key_}" --after="${bind_after}")"
fi fi
@ -59,10 +59,10 @@ _ynh_app_config_apply_one() {
local type="${types[$short_setting]}" local type="${types[$short_setting]}"
if [ "${changed[$short_setting]}" == "true" ]; then if [ "${changed[$short_setting]}" == "true" ]; then
# Apply setter if exists # 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 $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 "set__${bind%%(*}" $short_setting $type $bind
elif [[ "$bind" == "null" ]]; then elif [[ "$bind" == "null" ]]; then
@ -73,7 +73,7 @@ _ynh_app_config_apply_one() {
if [[ "$bind" == "settings" ]]; then if [[ "$bind" == "settings" ]]; then
ynh_die --message="File '${short_setting}' can't be stored in settings" ynh_die --message="File '${short_setting}' can't be stored in settings"
fi 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 if [[ "${!short_setting}" == "" ]]; then
ynh_backup_if_checksum_is_different --file="$bind_file" ynh_backup_if_checksum_is_different --file="$bind_file"
ynh_secure_remove --file="$bind_file" ynh_secure_remove --file="$bind_file"
@ -98,9 +98,9 @@ _ynh_app_config_apply_one() {
if [[ "$bind" == *":"* ]]; then 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" 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 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" 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_store_file_checksum --file="$bind_file" --update_only
ynh_print_info --message="File '$bind_file' overwritten with the content provided in question '${short_setting}'" 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)" bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
fi fi
bind_key_=${bind_key_:-$short_setting} 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_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}" 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
fi fi
} }
_ynh_app_config_get() { _ynh_app_config_get() {
# From settings for line in $YNH_APP_CONFIG_PANEL_OPTIONS_TYPES_AND_BINDS; do
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
# Split line into short_setting, type and bind # 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" binds[${short_setting}]="$bind"
types[${short_setting}]="$type" types[${short_setting}]="$type"
file_hash[${short_setting}]="" file_hash[${short_setting}]=""
formats[${short_setting}]="" formats[${short_setting}]=""
ynh_app_config_get_one $short_setting $type $bind ynh_app_config_get_one $short_setting $type $bind
done done
} }
_ynh_app_config_apply() { _ynh_app_config_apply() {
@ -258,9 +206,9 @@ _ynh_app_config_validate() {
for short_setting in "${!old[@]}"; do for short_setting in "${!old[@]}"; do
[[ "${changed[$short_setting]}" == "false" ]] && continue [[ "${changed[$short_setting]}" == "false" ]] && continue
local result="" 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)" 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 "validate__${bind%%(*}" $short_setting
fi fi
if [ -n "$result" ]; then if [ -n "$result" ]; then
@ -315,7 +263,7 @@ ynh_app_config_apply() {
ynh_app_action_run() { ynh_app_action_run() {
local runner="run__$1" local runner="run__$1"
# Get value from getter if exists # 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 $runner
#ynh_return "result:" #ynh_return "result:"
#ynh_return "$(echo "${result}" | sed 's/^/ /g')" #ynh_return "$(echo "${result}" | sed 's/^/ /g')"
@ -333,22 +281,23 @@ ynh_app_config_run() {
declare -Ag formats=() declare -Ag formats=()
case $1 in case $1 in
show) show)
ynh_app_config_get ynh_app_config_get
ynh_app_config_show ynh_app_config_show
;; ;;
apply) apply)
max_progression=4 max_progression=4
ynh_script_progression --message="Reading config panel description and current configuration..." ynh_script_progression --message="Reading config panel description and current configuration..."
ynh_app_config_get ynh_app_config_get
ynh_app_config_validate ynh_app_config_validate
ynh_script_progression --message="Applying the new configuration..." ynh_script_progression --message="Applying the new configuration..."
ynh_app_config_apply ynh_app_config_apply
ynh_script_progression --message="Configuration of $app completed" --last ynh_script_progression --message="Configuration of $app completed" --last
;; ;;
*) *)
ynh_app_action_run $1 ynh_app_action_run $1
;;
esac esac
} }

View file

@ -40,9 +40,7 @@
# ignoreregex = # ignoreregex =
# ``` # ```
# #
# ----------------------------------------------------------------------------- # ##### Note about the "failregex" option:
#
# Note about the "failregex" option:
# #
# regex to match the password failure messages in the logfile. The host must be # 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 # matched by a group named "`host`". The tag "`<HOST>`" can be used for standard
@ -84,7 +82,7 @@ port = __PORTS__
filter = __APP__ filter = __APP__
logpath = __LOGPATH__ logpath = __LOGPATH__
maxretry = __MAX_RETRY__ maxretry = __MAX_RETRY__
" >"$YNH_APP_BASEDIR/conf/f2b_jail.conf" " > "$YNH_APP_BASEDIR/conf/f2b_jail.conf"
echo " echo "
[INCLUDES] [INCLUDES]
@ -92,7 +90,7 @@ before = common.conf
[Definition] [Definition]
failregex = __FAILREGEX__ failregex = __FAILREGEX__
ignoreregex = ignoreregex =
" >"$YNH_APP_BASEDIR/conf/f2b_filter.conf" " > "$YNH_APP_BASEDIR/conf/f2b_filter.conf"
fi fi
ynh_add_config --template="f2b_jail.conf" --destination="/etc/fail2ban/jail.d/$app.conf" ynh_add_config --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 # | 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 # 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: # Be carreful, this array has to be an associative array, as the following example:
# local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 ) # local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
# Let's explain this array: # 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.. # 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. # Dot not echo, to prevent to go through a helper output. But print only in the log.
set -x set -x
echo "! Helper used in legacy mode !" >/dev/null echo "! Helper used in legacy mode !" > /dev/null
set +x set +x
local i local i
for i in $(seq 0 $((${#arguments[@]} - 1))); do for i in $(seq 0 $((${#arguments[@]} - 1))); do

View file

@ -1,11 +1,11 @@
#!/bin/bash #!/bin/bash
ynh_go_try_bash_extension() { ynh_go_try_bash_extension() {
if [ -x src/configure ]; then if [ -x src/configure ]; then
src/configure && make -C src || { src/configure && make -C src || {
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally." ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
} }
fi fi
} }
goenv_install_dir="/opt/goenv" goenv_install_dir="/opt/goenv"
@ -51,7 +51,7 @@ export GOENV_ROOT="$goenv_install_dir"
# usage: ynh_use_go # usage: ynh_use_go
# #
# Requires YunoHost version 3.2.2 or higher. # 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) go_version=$(ynh_app_setting_get --app=$app --key=go_version)
# Get the absolute path of this version of Go # Get the absolute path of this version of Go
@ -73,7 +73,7 @@ ynh_use_go () {
# Sets the local application-specific Go version # Sets the local application-specific Go version
pushd $install_dir pushd $install_dir
$goenv_install_dir/bin/goenv local $go_version $goenv_install_dir/bin/goenv local $go_version
popd popd
} }
@ -93,10 +93,10 @@ ynh_use_go () {
# | arg: -v, --go_version= - Version of go to install. # | arg: -v, --go_version= - Version of go to install.
# #
# Requires YunoHost version 3.2.2 or higher. # Requires YunoHost version 3.2.2 or higher.
ynh_install_go () { ynh_install_go() {
# Declare an array to define the options of this helper. # Declare an array to define the options of this helper.
local legacy_args=v local legacy_args=v
local -A args_array=( [v]=go_version= ) local -A args_array=([v]=go_version=)
local go_version local go_version
# Manage arguments with getopts # Manage arguments with getopts
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
@ -113,34 +113,34 @@ ynh_install_go () {
# Install or update goenv # Install or update goenv
mkdir -p $goenv_install_dir mkdir -p $goenv_install_dir
pushd "$goenv_install_dir" pushd "$goenv_install_dir"
if ! [ -x "$goenv_install_dir/bin/goenv" ]; then if ! [ -x "$goenv_install_dir/bin/goenv" ]; then
ynh_print_info --message="Downloading goenv..." ynh_print_info --message="Downloading goenv..."
git init -q git init -q
git remote add origin https://github.com/syndbg/goenv.git git remote add origin https://github.com/syndbg/goenv.git
else else
ynh_print_info --message="Updating goenv..." ynh_print_info --message="Updating goenv..."
fi fi
git fetch -q --tags --prune origin git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)") local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag" git checkout -q "$git_latest_tag"
ynh_go_try_bash_extension ynh_go_try_bash_extension
goenv=$goenv_install_dir/bin/goenv goenv=$goenv_install_dir/bin/goenv
popd popd
# Install or update xxenv-latest # Install or update xxenv-latest
goenv_latest_dir="$goenv_install_dir/plugins/xxenv-latest" goenv_latest_dir="$goenv_install_dir/plugins/xxenv-latest"
mkdir -p "$goenv_latest_dir" mkdir -p "$goenv_latest_dir"
pushd "$goenv_latest_dir" pushd "$goenv_latest_dir"
if ! [ -x "$goenv_latest_dir/bin/goenv-latest" ]; then if ! [ -x "$goenv_latest_dir/bin/goenv-latest" ]; then
ynh_print_info --message="Downloading xxenv-latest..." ynh_print_info --message="Downloading xxenv-latest..."
git init -q git init -q
git remote add origin https://github.com/momo-lab/xxenv-latest.git git remote add origin https://github.com/momo-lab/xxenv-latest.git
else else
ynh_print_info --message="Updating xxenv-latest..." ynh_print_info --message="Updating xxenv-latest..."
fi fi
git fetch -q --tags --prune origin git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)") local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag" git checkout -q "$git_latest_tag"
popd popd
# Enable caching # Enable caching
@ -167,7 +167,7 @@ ynh_install_go () {
ynh_cleanup_go ynh_cleanup_go
# Set environment for Go users # Set environment for Go users
echo "#goenv echo "#goenv
export GOENV_ROOT=$goenv_install_dir export GOENV_ROOT=$goenv_install_dir
export PATH=\"$goenv_install_dir/bin:$PATH\" export PATH=\"$goenv_install_dir/bin:$PATH\"
eval \"\$(goenv init -)\" eval \"\$(goenv init -)\"
@ -182,7 +182,7 @@ eval \"\$(goenv init -)\"
# This helper will also cleanup Go versions # This helper will also cleanup Go versions
# #
# usage: ynh_remove_go # usage: ynh_remove_go
ynh_remove_go () { ynh_remove_go() {
local go_version=$(ynh_app_setting_get --app="$app" --key="go_version") local go_version=$(ynh_app_setting_get --app="$app" --key="go_version")
# Load goenv path in PATH # Load goenv path in PATH
@ -205,34 +205,29 @@ ynh_remove_go () {
# If no app uses Go, goenv will be also removed. # If no app uses Go, goenv will be also removed.
# #
# usage: ynh_cleanup_go # usage: ynh_cleanup_go
ynh_cleanup_go () { ynh_cleanup_go() {
# List required Go versions # List required Go versions
local installed_apps=$(yunohost app list --output-as json --quiet | jq -r .apps[].id) local installed_apps=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
local required_go_versions="" local required_go_versions=""
for installed_app in $installed_apps for installed_app in $installed_apps; do
do
local installed_app_go_version=$(ynh_app_setting_get --app=$installed_app --key="go_version") local installed_app_go_version=$(ynh_app_setting_get --app=$installed_app --key="go_version")
if [[ $installed_app_go_version ]] if [[ $installed_app_go_version ]]; then
then
required_go_versions="${installed_app_go_version}\n${required_go_versions}" required_go_versions="${installed_app_go_version}\n${required_go_versions}"
fi fi
done done
# Remove no more needed Go versions # Remove no more needed Go versions
local installed_go_versions=$(goenv versions --bare --skip-aliases | grep -Ev '/') local installed_go_versions=$(goenv versions --bare --skip-aliases | grep -Ev '/')
for installed_go_version in $installed_go_versions for installed_go_version in $installed_go_versions; do
do if ! $(echo ${required_go_versions} | grep "${installed_go_version}" 1> /dev/null 2>&1); then
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" ynh_print_info --message="Removing of Go-$installed_go_version"
$goenv_install_dir/bin/goenv uninstall --force "$installed_go_version" $goenv_install_dir/bin/goenv uninstall --force "$installed_go_version"
fi fi
done done
# If none Go version is required # If none Go version is required
if [[ ! $required_go_versions ]] if [[ ! $required_go_versions ]]; then
then
# Remove goenv environment configuration # Remove goenv environment configuration
ynh_print_info --message="Removing of goenv" ynh_print_info --message="Removing of goenv"
ynh_secure_remove --file="$goenv_install_dir" 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, # Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
# (because in the past eval was used) ... # (because in the past eval was used) ...
# we detect this by checking that there's no 2nd arg, and $1 contains a space # we detect this by checking that there's no 2nd arg, and $1 contains a space
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]] if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
then
ynh_print_err --message="$(eval $@)" ynh_print_err --message="$(eval $@)"
else else
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077 # 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, # Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
# (because in the past eval was used) ... # (because in the past eval was used) ...
# we detect this by checking that there's no 2nd arg, and $1 contains a space # we detect this by checking that there's no 2nd arg, and $1 contains a space
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]] if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
then
ynh_print_warn --message="$(eval $@)" ynh_print_warn --message="$(eval $@)"
else else
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077 # 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, # Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
# (because in the past eval was used) ... # (because in the past eval was used) ...
# we detect this by checking that there's no 2nd arg, and $1 contains a space # we detect this by checking that there's no 2nd arg, and $1 contains a space
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]] if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
then
eval $@ 2>&1 eval $@ 2>&1
else else
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077 # 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, # Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
# (because in the past eval was used) ... # (because in the past eval was used) ...
# we detect this by checking that there's no 2nd arg, and $1 contains a space # we detect this by checking that there's no 2nd arg, and $1 contains a space
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]] if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
then
eval $@ > /dev/null eval $@ > /dev/null
else else
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077 # 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, # Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
# (because in the past eval was used) ... # (because in the past eval was used) ...
# we detect this by checking that there's no 2nd arg, and $1 contains a space # we detect this by checking that there's no 2nd arg, and $1 contains a space
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]] if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
then
eval $@ > /dev/null 2>&1 eval $@ > /dev/null 2>&1
else else
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077 # 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 rc=0
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077 # Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
"$@" 2> "$logfile" || rc="$?" "$@" 2> "$logfile" || rc="$?"
if (( rc != 0 )); then if ((rc != 0)); then
ynh_exec_warn cat "$logfile" ynh_exec_warn cat "$logfile"
ynh_secure_remove "$logfile" ynh_secure_remove "$logfile"
return "$rc" return "$rc"
@ -216,7 +211,7 @@ ynh_exec_and_print_stderr_only_if_error() {
# #
# Requires YunoHost version 3.2.0 or higher. # Requires YunoHost version 3.2.0 or higher.
ynh_print_OFF() { ynh_print_OFF() {
exec {BASH_XTRACEFD}>/dev/null exec {BASH_XTRACEFD}> /dev/null
} }
# Restore the logging after ynh_print_OFF # Restore the logging after ynh_print_OFF
@ -229,7 +224,7 @@ ynh_print_OFF() {
ynh_print_ON() { ynh_print_ON() {
exec {BASH_XTRACEFD}>&1 exec {BASH_XTRACEFD}>&1
# Print an echo only for the log, to be able to know that ynh_print_ON has been called. # 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 # Initial definitions for ynh_script_progression
@ -271,9 +266,9 @@ ynh_script_progression() {
# Always activate time when running inside CI tests # Always activate time when running inside CI tests
if [ ${PACKAGE_CHECK_EXEC:-0} -eq 1 ]; then if [ ${PACKAGE_CHECK_EXEC:-0} -eq 1 ]; then
time=${time:-1} time=${time:-1}
else else
time=${time:-0} time=${time:-0}
fi fi
last=${last:-0} 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'))) 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. # max_progression is a total number of calls to this helper.
# Less the number of calls with a weight value. # Less the number of calls with a weight value.
# Plus the total of weight values # Plus the total of weight values
max_progression=$(($helper_calls - $weight_calls + $weight_values)) max_progression=$(($helper_calls - $weight_calls + $weight_values))
fi fi
@ -329,7 +324,7 @@ ynh_script_progression() {
local print_exec_time="" local print_exec_time=""
if [ $time -eq 1 ] && [ "$exec_time" -gt 10 ]; then 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 fi
ynh_print_info "[$progression_bar] > ${message}${print_exec_time}" ynh_print_info "[$progression_bar] > ${message}${print_exec_time}"
@ -343,5 +338,5 @@ ynh_script_progression() {
# #
# Requires YunoHost version 3.6.0 or higher. # Requires YunoHost version 3.6.0 or higher.
ynh_return() { 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 # Stupid patch to ignore legacy --non-append and --nonappend
# which was never properly understood and improperly used and kind of bullshit # which was never properly understood and improperly used and kind of bullshit
local all_args=( ${@} ) local all_args=(${@})
for I in $(seq 0 $(($# - 1))) for I in $(seq 0 $(($# - 1))); do
do if [[ "${all_args[$I]}" == "--non-append" ]] || [[ "${all_args[$I]}" == "--nonappend" ]]; then
if [[ "${all_args[$I]}" == "--non-append" ]] || [[ "${all_args[$I]}" == "--nonappend" ]]
then
unset all_args[$I] unset all_args[$I]
fi fi
done done
@ -43,8 +41,7 @@ ynh_use_logrotate() {
fi fi
set +o noglob set +o noglob
for stuff in $logfile for stuff in $logfile; do
do
mkdir --parents $(dirname "$stuff") mkdir --parents $(dirname "$stuff")
done done
@ -54,7 +51,7 @@ ynh_use_logrotate() {
fi fi
local tempconf="$(mktemp)" local tempconf="$(mktemp)"
cat << EOF >$tempconf cat << EOF > $tempconf
$logfile { $logfile {
# Rotate if the logfile exceeds 100Mo # Rotate if the logfile exceeds 100Mo
size 100M size 100M
@ -76,8 +73,7 @@ $logfile {
} }
EOF EOF
if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]] if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]]; then
then
cat $tempconf > /etc/logrotate.d/$app cat $tempconf > /etc/logrotate.d/$app
else else
cat $tempconf >> /etc/logrotate.d/$app cat $tempconf >> /etc/logrotate.d/$app

View file

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

View file

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

View file

@ -79,7 +79,7 @@ ynh_validate_ip() {
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1 [ "$family" == "4" ] || [ "$family" == "6" ] || return 1
python3 /dev/stdin <<EOF python3 /dev/stdin << EOF
import socket import socket
import sys import sys
family = { "4" : socket.AF_INET, "6" : socket.AF_INET6 } 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 ynh_systemd_action --service_name=nginx --action=reload
} }
# Regen the nginx config in a change url context # Regen the nginx config in a change url context
# #
# usage: ynh_change_url_nginx_config # 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 # Make a backup of the original NGINX config file if manually modified
# (nb: this is possibly different from the same instruction called by # (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...) # changed if we're changing the domain too...)
local old_nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf 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" ynh_backup_if_checksum_is_different --file="$old_nginx_conf_path"

View file

@ -36,8 +36,6 @@
# | arg: -t, --show_tile= - (optional) Define if a tile will be shown in the SSO. If yes the name of the tile will be the 'label' parameter. Defaults to false for the permission different than 'main'. # | arg: -t, --show_tile= - (optional) Define if a tile will be shown in the SSO. If yes the name of the tile will be the 'label' parameter. Defaults to false for the permission different than 'main'.
# | arg: -P, --protected= - (optional) Define if this permission is protected. If it is protected the administrator won't be able to add or remove the visitors group of this permission. Defaults to 'false'. # | arg: -P, --protected= - (optional) Define if this permission is protected. If it is protected the administrator won't be able to add or remove the visitors group of this permission. Defaults to 'false'.
# #
# [packagingv1]
#
# If provided, 'url' or 'additional_urls' is assumed to be relative to the app domain/path if they # If provided, 'url' or 'additional_urls' is assumed to be relative to the app domain/path if they
# start with '/'. For example: # start with '/'. For example:
# / -> domain.tld/app # / -> domain.tld/app
@ -145,8 +143,6 @@ ynh_permission_create() {
# Remove a permission for the app (note that when the app is removed all permission is automatically removed) # Remove a permission for the app (note that when the app is removed all permission is automatically removed)
# #
# [packagingv1]
#
# example: ynh_permission_delete --permission=editors # example: ynh_permission_delete --permission=editors
# #
# usage: ynh_permission_delete --permission="permission" # usage: ynh_permission_delete --permission="permission"
@ -165,8 +161,6 @@ ynh_permission_delete() {
# Check if a permission exists # Check if a permission exists
# #
# [packagingv1]
#
# usage: ynh_permission_exists --permission=permission # usage: ynh_permission_exists --permission=permission
# | arg: -p, --permission= - the permission to check # | arg: -p, --permission= - the permission to check
# | exit: Return 1 if the permission doesn't exist, 0 otherwise # | exit: Return 1 if the permission doesn't exist, 0 otherwise
@ -180,13 +174,11 @@ ynh_permission_exists() {
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
yunohost user permission list "$app" --output-as json --quiet \ 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 # Redefine the url associated to a permission
# #
# [packagingv1]
#
# usage: ynh_permission_url --permission "permission" [--url="url"] [--add_url="new-url" [ "other-new-url" ]] [--remove_url="old-url" [ "other-old-url" ]] # usage: ynh_permission_url --permission "permission" [--url="url"] [--add_url="new-url" [ "other-new-url" ]] [--remove_url="old-url" [ "other-old-url" ]]
# [--auth_header=true|false] [--clear_urls] # [--auth_header=true|false] [--clear_urls]
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed) # | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
@ -255,8 +247,6 @@ ynh_permission_url() {
# Update a permission for the app # Update a permission for the app
# #
# [packagingv1]
#
# usage: ynh_permission_update --permission "permission" [--add="group" ["group" ...]] [--remove="group" ["group" ...]] # usage: ynh_permission_update --permission "permission" [--add="group" ["group" ...]] [--remove="group" ["group" ...]]
# [--label="label"] [--show_tile=true|false] [--protected=true|false] # [--label="label"] [--show_tile=true|false] [--protected=true|false]
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" already exist) # | arg: -p, --permission= - the name for the permission (by default a permission named "main" already exist)
@ -352,7 +342,7 @@ ynh_permission_has_user() {
# Check both allowed and corresponding_users sections in the json # Check both allowed and corresponding_users sections in the json
for section in "allowed" "corresponding_users"; do for section in "allowed" "corresponding_users"; do
if yunohost user permission info "$app.$permission" --output-as json --quiet \ 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 return 0
fi fi
done done
@ -362,8 +352,6 @@ ynh_permission_has_user() {
# Check if a legacy permissions exist # Check if a legacy permissions exist
# #
# [packagingv1]
#
# usage: ynh_legacy_permissions_exists # usage: ynh_legacy_permissions_exists
# | exit: Return 1 if the permission doesn't exist, 0 otherwise # | exit: Return 1 if the permission doesn't exist, 0 otherwise
# #
@ -379,8 +367,6 @@ ynh_legacy_permissions_exists() {
# Remove all legacy permissions # Remove all legacy permissions
# #
# [packagingv1]
#
# usage: ynh_legacy_permissions_delete_all # usage: ynh_legacy_permissions_delete_all
# #
# example: # example:

View file

@ -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 # 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) # 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 # 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 # 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) # 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. # *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 ...) # (which should ultimately be standardized by the core ...)
# #
# Case 2 (deprecate) : you provided an entire conf/php-fpm.conf # 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 # 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). # fpm_footprint: Memory footprint of the service (low/medium/high).
# low - Less than 20 MB of RAM by pool. # low - Less than 20 MB of RAM by pool.
# medium - Between 20 MB and 40 MB of RAM by pool. # medium - Between 20 MB and 40 MB of RAM by pool.
@ -92,16 +92,14 @@ ynh_add_fpm_config() {
# If no usage provided, default to the value existing in setting ... or to low # 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) local fpm_usage_in_setting=$(ynh_app_setting_get --app=$app --key=fpm_usage)
if [ -z "$usage" ] if [ -z "$usage" ]; then
then
usage=${fpm_usage_in_setting:-low} usage=${fpm_usage_in_setting:-low}
ynh_app_setting_set --app=$app --key=fpm_usage --value=$usage ynh_app_setting_set --app=$app --key=fpm_usage --value=$usage
fi fi
# If no footprint provided, default to the value existing in setting ... or to low # 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) local fpm_footprint_in_setting=$(ynh_app_setting_get --app=$app --key=fpm_footprint)
if [ -z "$footprint" ] if [ -z "$footprint" ]; then
then
footprint=${fpm_footprint_in_setting:-low} footprint=${fpm_footprint_in_setting:-low}
ynh_app_setting_set --app=$app --key=fpm_footprint --value=$footprint ynh_app_setting_set --app=$app --key=fpm_footprint --value=$footprint
fi fi
@ -125,8 +123,7 @@ ynh_add_fpm_config() {
local old_php_fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir) 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" local old_php_finalphpconf="$old_php_fpm_config_dir/pool.d/$app.conf"
if [[ -f "$old_php_finalphpconf" ]] if [[ -f "$old_php_finalphpconf" ]]; then
then
ynh_backup_if_checksum_is_different --file="$old_php_finalphpconf" ynh_backup_if_checksum_is_different --file="$old_php_finalphpconf"
ynh_remove_fpm_config ynh_remove_fpm_config
fi fi
@ -200,24 +197,24 @@ pm = __PHP_PM__
pm.max_children = __PHP_MAX_CHILDREN__ pm.max_children = __PHP_MAX_CHILDREN__
pm.max_requests = 500 pm.max_requests = 500
request_terminate_timeout = 1d request_terminate_timeout = 1d
" >"$phpfpm_path" " > "$phpfpm_path"
if [ "$php_pm" = "dynamic" ]; then if [ "$php_pm" = "dynamic" ]; then
echo " echo "
pm.start_servers = __PHP_START_SERVERS__ pm.start_servers = __PHP_START_SERVERS__
pm.min_spare_servers = __PHP_MIN_SPARE_SERVERS__ pm.min_spare_servers = __PHP_MIN_SPARE_SERVERS__
pm.max_spare_servers = __PHP_MAX_SPARE_SERVERS__ pm.max_spare_servers = __PHP_MAX_SPARE_SERVERS__
" >>"$phpfpm_path" " >> "$phpfpm_path"
elif [ "$php_pm" = "ondemand" ]; then elif [ "$php_pm" = "ondemand" ]; then
echo " echo "
pm.process_idle_timeout = 10s pm.process_idle_timeout = 10s
" >>"$phpfpm_path" " >> "$phpfpm_path"
fi fi
# Concatene the extra config. # Concatene the extra config.
if [ -e $YNH_APP_BASEDIR/conf/extra_php-fpm.conf ]; then 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
fi fi
@ -238,7 +235,7 @@ pid = /run/php/php__PHPVERSION__-fpm-__APP__.pid
error_log = /var/log/php/fpm-php.__APP__.log error_log = /var/log/php/fpm-php.__APP__.log
syslog.ident = php-fpm-__APP__ syslog.ident = php-fpm-__APP__
include = __FINALPHPCONF__ include = __FINALPHPCONF__
" >$YNH_APP_BASEDIR/conf/php-fpm-$app.conf " > $YNH_APP_BASEDIR/conf/php-fpm-$app.conf
ynh_add_config --template="php-fpm-$app.conf" --destination="$globalphpconf" ynh_add_config --template="php-fpm-$app.conf" --destination="$globalphpconf"
@ -255,7 +252,7 @@ ExecReload=/bin/kill -USR2 \$MAINPID
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
" >$YNH_APP_BASEDIR/conf/$fpm_service " > $YNH_APP_BASEDIR/conf/$fpm_service
# Create this dedicated PHP-FPM service # Create this dedicated PHP-FPM service
ynh_add_systemd_config --service=$fpm_service --template=$fpm_service ynh_add_systemd_config --service=$fpm_service --template=$fpm_service
@ -267,7 +264,7 @@ WantedBy=multi-user.target
ynh_systemd_action --service_name=$fpm_service --action=restart ynh_systemd_action --service_name=$fpm_service --action=restart
else else
# Validate that the new php conf doesn't break php-fpm entirely # Validate that the new php conf doesn't break php-fpm entirely
if ! php-fpm${phpversion} --test 2>/dev/null; then if ! php-fpm${phpversion} --test 2> /dev/null; then
php-fpm${phpversion} --test || true php-fpm${phpversion} --test || true
ynh_secure_remove --file="$finalphpconf" ynh_secure_remove --file="$finalphpconf"
ynh_die --message="The new configuration broke php-fpm?" ynh_die --message="The new configuration broke php-fpm?"
@ -360,7 +357,7 @@ ynh_install_php() {
# usage: ynh_remove_php # usage: ynh_remove_php
# #
# Requires YunoHost version 3.8.1 or higher. # Requires YunoHost version 3.8.1 or higher.
ynh_remove_php () { ynh_remove_php() {
ynh_remove_app_dependencies ynh_remove_app_dependencies
} }
@ -500,84 +497,3 @@ ynh_get_scalable_phpfpm() {
fi fi
fi fi
} }
readonly YNH_DEFAULT_COMPOSER_VERSION=1.10.17
# Declare the actual composer version to use.
# A packager willing to use another version of composer can override the variable into its _common.sh.
YNH_COMPOSER_VERSION=${YNH_COMPOSER_VERSION:-$YNH_DEFAULT_COMPOSER_VERSION}
# Execute a command with Composer
#
# usage: ynh_composer_exec [--phpversion=phpversion] [--workdir=$install_dir] --commands="commands"
# | arg: -v, --phpversion - PHP version to use with composer
# | arg: -w, --workdir - The directory from where the command will be executed. Default $install_dir or $final_path
# | arg: -c, --commands - Commands to execute.
#
# Requires YunoHost version 4.2 or higher.
ynh_composer_exec() {
local _globalphpversion=${phpversion-:}
# Declare an array to define the options of this helper.
local legacy_args=vwc
declare -Ar args_array=([v]=phpversion= [w]=workdir= [c]=commands=)
local phpversion
local workdir
local commands
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
workdir="${workdir:-${install_dir:-$final_path}}"
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
phpversion="${phpversion:-$YNH_PHP_VERSION}"
else
phpversion="${phpversion:-$_globalphpversion}"
fi
COMPOSER_HOME="$workdir/.composer" COMPOSER_MEMORY_LIMIT=-1 \
php${phpversion} "$workdir/composer.phar" $commands \
-d "$workdir" --no-interaction --no-ansi 2>&1
}
# Install and initialize Composer in the given directory
#
# usage: ynh_install_composer [--phpversion=phpversion] [--workdir=$install_dir] [--install_args="--optimize-autoloader"] [--composerversion=composerversion]
# | arg: -v, --phpversion - PHP version to use with composer
# | arg: -w, --workdir - The directory from where the command will be executed. Default $install_dir.
# | arg: -a, --install_args - Additional arguments provided to the composer install. Argument --no-dev already include
# | arg: -c, --composerversion - Composer version to install
#
# Requires YunoHost version 4.2 or higher.
ynh_install_composer() {
local _globalphpversion=${phpversion-:}
# Declare an array to define the options of this helper.
local legacy_args=vwac
declare -Ar args_array=([v]=phpversion= [w]=workdir= [a]=install_args= [c]=composerversion=)
local phpversion
local workdir
local install_args
local composerversion
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
workdir="${workdir:-$final_path}"
else
workdir="${workdir:-$install_dir}"
fi
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
phpversion="${phpversion:-$YNH_PHP_VERSION}"
else
phpversion="${phpversion:-$_globalphpversion}"
fi
install_args="${install_args:-}"
composerversion="${composerversion:-$YNH_COMPOSER_VERSION}"
curl -sS https://getcomposer.org/installer \
| COMPOSER_HOME="$workdir/.composer" \
php${phpversion} -- --quiet --install-dir="$workdir" --version=$composerversion \
|| ynh_die --message="Unable to install Composer."
# install dependencies
ynh_composer_exec --phpversion="${phpversion}" --workdir="$workdir" --commands="install --no-dev $install_args" \
|| ynh_die --message="Unable to install core dependencies with Composer."
}

View file

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

View file

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

View file

@ -8,8 +8,8 @@ export RBENV_ROOT="$rbenv_install_dir"
export rbenv_root="$rbenv_install_dir" export rbenv_root="$rbenv_install_dir"
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then 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_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_pkg_dependencies="${build_pkg_dependencies:-} $build_ruby_dependencies"
fi fi
# Load the version of Ruby for an app, and set variables. # Load the version of Ruby for an app, and set variables.
@ -50,7 +50,7 @@ fi
# usage: ynh_use_ruby # usage: ynh_use_ruby
# #
# Requires YunoHost version 3.2.2 or higher. # 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) ruby_version=$(ynh_app_setting_get --app=$app --key=ruby_version)
# Get the absolute path of this version of Ruby # Get the absolute path of this version of Ruby
@ -75,7 +75,7 @@ ynh_use_ruby () {
# Sets the local application-specific Ruby version # Sets the local application-specific Ruby version
pushd ${install_dir:-$final_path} pushd ${install_dir:-$final_path}
$rbenv_install_dir/bin/rbenv local $ruby_version $rbenv_install_dir/bin/rbenv local $ruby_version
popd popd
} }
@ -95,10 +95,10 @@ ynh_use_ruby () {
# | arg: -v, --ruby_version= - Version of ruby to install. # | arg: -v, --ruby_version= - Version of ruby to install.
# #
# Requires YunoHost version 3.2.2 or higher. # Requires YunoHost version 3.2.2 or higher.
ynh_install_ruby () { ynh_install_ruby() {
# Declare an array to define the options of this helper. # Declare an array to define the options of this helper.
local legacy_args=v local legacy_args=v
local -A args_array=( [v]=ruby_version= ) local -A args_array=([v]=ruby_version=)
local ruby_version local ruby_version
# Manage arguments with getopts # Manage arguments with getopts
ynh_handle_getopts_args "$@" 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)" rbenv="$(command -v rbenv $rbenv_install_dir/bin/rbenv | grep "$rbenv_install_dir/bin/rbenv" | head -1)"
if [ -n "$rbenv" ]; then if [ -n "$rbenv" ]; then
pushd "${rbenv%/*/*}" pushd "${rbenv%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/rbenv.git"; then if git remote -v 2> /dev/null | grep "https://github.com/rbenv/rbenv.git"; then
ynh_print_info --message="Updating rbenv..." ynh_print_info --message="Updating rbenv..."
git pull -q --tags origin master git pull -q --tags origin master
ynh_ruby_try_bash_extension ynh_ruby_try_bash_extension
else else
ynh_print_info --message="Reinstalling rbenv..." ynh_print_info --message="Reinstalling rbenv..."
cd .. cd ..
ynh_secure_remove --file=$rbenv_install_dir ynh_secure_remove --file=$rbenv_install_dir
mkdir -p $rbenv_install_dir mkdir -p $rbenv_install_dir
cd $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 init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1 git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master git checkout -q -b master origin/master
ynh_ruby_try_bash_extension ynh_ruby_try_bash_extension
rbenv=$rbenv_install_dir/bin/rbenv 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 popd
fi fi
@ -150,10 +150,10 @@ ynh_install_ruby () {
ruby_build="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-install rbenv-install | head -1)" ruby_build="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-install rbenv-install | head -1)"
if [ -n "$ruby_build" ]; then if [ -n "$ruby_build" ]; then
pushd "${ruby_build%/*/*}" pushd "${ruby_build%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/ruby-build.git"; then if git remote -v 2> /dev/null | grep "https://github.com/rbenv/ruby-build.git"; then
ynh_print_info --message="Updating ruby-build..." ynh_print_info --message="Updating ruby-build..."
git pull -q origin master git pull -q origin master
fi fi
popd popd
else else
ynh_print_info --message="Installing ruby-build..." 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)" rbenv_alias="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-alias rbenv-alias | head -1)"
if [ -n "$rbenv_alias" ]; then if [ -n "$rbenv_alias" ]; then
pushd "${rbenv_alias%/*/*}" pushd "${rbenv_alias%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then if git remote -v 2> /dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then
ynh_print_info --message="Updating rbenv-aliases..." ynh_print_info --message="Updating rbenv-aliases..."
git pull -q origin master git pull -q origin master
fi fi
popd popd
else else
ynh_print_info --message="Installing rbenv-aliases..." 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)" rbenv_latest="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-latest rbenv-latest | head -1)"
if [ -n "$rbenv_latest" ]; then if [ -n "$rbenv_latest" ]; then
pushd "${rbenv_latest%/*/*}" pushd "${rbenv_latest%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then if git remote -v 2> /dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then
ynh_print_info --message="Updating xxenv-latest..." ynh_print_info --message="Updating xxenv-latest..."
git pull -q origin master git pull -q origin master
fi fi
popd popd
else else
ynh_print_info --message="Installing xxenv-latest..." 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 ynh_app_setting_set --app=$app --key=ruby_version --value=$final_ruby_version
# Remove app virtualenv # Remove app virtualenv
if rbenv alias --list | grep --quiet "$app " if rbenv alias --list | grep --quiet "$app "; then
then
rbenv alias $app --remove rbenv alias $app --remove
fi fi
@ -222,7 +221,7 @@ ynh_install_ruby () {
ynh_cleanup_ruby ynh_cleanup_ruby
# Set environment for Ruby users # Set environment for Ruby users
echo "#rbenv echo "#rbenv
export RBENV_ROOT=$rbenv_install_dir export RBENV_ROOT=$rbenv_install_dir
export PATH=\"$rbenv_install_dir/bin:$PATH\" export PATH=\"$rbenv_install_dir/bin:$PATH\"
eval \"\$(rbenv init -)\" eval \"\$(rbenv init -)\"
@ -237,7 +236,7 @@ eval \"\$(rbenv init -)\"
# This helper will also cleanup Ruby versions # This helper will also cleanup Ruby versions
# #
# usage: ynh_remove_ruby # usage: ynh_remove_ruby
ynh_remove_ruby () { ynh_remove_ruby() {
local ruby_version=$(ynh_app_setting_get --app=$app --key=ruby_version) local ruby_version=$(ynh_app_setting_get --app=$app --key=ruby_version)
# Load rbenv path in PATH # Load rbenv path in PATH
@ -262,34 +261,29 @@ ynh_remove_ruby () {
# If no app uses Ruby, rbenv will be also removed. # If no app uses Ruby, rbenv will be also removed.
# #
# usage: ynh_cleanup_ruby # usage: ynh_cleanup_ruby
ynh_cleanup_ruby () { ynh_cleanup_ruby() {
# List required Ruby versions # List required Ruby versions
local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$') local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$')
local required_ruby_versions="" local required_ruby_versions=""
for installed_app in $installed_apps for installed_app in $installed_apps; do
do
local installed_app_ruby_version=$(ynh_app_setting_get --app=$installed_app --key="ruby_version") local installed_app_ruby_version=$(ynh_app_setting_get --app=$installed_app --key="ruby_version")
if [[ -n "$installed_app_ruby_version" ]] if [[ -n "$installed_app_ruby_version" ]]; then
then
required_ruby_versions="${installed_app_ruby_version}\n${required_ruby_versions}" required_ruby_versions="${installed_app_ruby_version}\n${required_ruby_versions}"
fi fi
done done
# Remove no more needed Ruby versions # Remove no more needed Ruby versions
local installed_ruby_versions=$(rbenv versions --bare --skip-aliases | grep -Ev '/') local installed_ruby_versions=$(rbenv versions --bare --skip-aliases | grep -Ev '/')
for installed_ruby_version in $installed_ruby_versions for installed_ruby_version in $installed_ruby_versions; do
do if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"; then
if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"
then
ynh_print_info --message="Removing Ruby-$installed_ruby_version" ynh_print_info --message="Removing Ruby-$installed_ruby_version"
$rbenv_install_dir/bin/rbenv uninstall --force $installed_ruby_version $rbenv_install_dir/bin/rbenv uninstall --force $installed_ruby_version
fi fi
done done
# If none Ruby version is required # If none Ruby version is required
if [[ -z "$required_ruby_versions" ]] if [[ -z "$required_ruby_versions" ]]; then
then
# Remove rbenv environment configuration # Remove rbenv environment configuration
ynh_print_info --message="Removing rbenv" ynh_print_info --message="Removing rbenv"
ynh_secure_remove --file="$rbenv_install_dir" ynh_secure_remove --file="$rbenv_install_dir"
@ -298,9 +292,9 @@ ynh_cleanup_ruby () {
} }
ynh_ruby_try_bash_extension() { ynh_ruby_try_bash_extension() {
if [ -x src/configure ]; then if [ -x src/configure ]; then
src/configure && make -C src || { src/configure && make -C src || {
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally." ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
} }
fi fi
} }

View file

@ -52,6 +52,42 @@ ynh_app_setting_set() {
fi fi
} }
# Set an application setting but only if the "$key" variable ain't set yet
#
# Note that it doesn't just define the setting but ALSO define the $foobar variable
#
# Hence it's meant as a replacement for this legacy overly complex syntax:
#
# if [ -z "${foo:-}" ]
# then
# foo="bar"
# ynh_app_setting_set --key="foo" --value="$foo"
# fi
#
# usage: ynh_app_setting_set_default --app=app --key=key --value=value
# | arg: -a, --app= - the application id
# | arg: -k, --key= - the setting name to set
# | arg: -v, --value= - the default setting value to set
#
# Requires YunoHost version 11.1.16 or higher.
ynh_app_setting_set_default() {
local _globalapp=${app-:}
# Declare an array to define the options of this helper.
local legacy_args=akv
local -A args_array=([a]=app= [k]=key= [v]=value=)
local app
local key
local value
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
app="${app:-$_globalapp}"
if [ -z "${!key:-}" ]; then
eval $key=\$value
ynh_app_setting "set" "$app" "$key" "$value"
fi
}
# Delete an application setting # Delete an application setting
# #
# usage: ynh_app_setting_delete --app=app --key=key # usage: ynh_app_setting_delete --app=app --key=key
@ -84,7 +120,7 @@ ynh_app_setting_delete() {
# #
ynh_app_setting() { ynh_app_setting() {
set +o xtrace # set +x 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 import os, yaml, sys
app, action = os.environ['APP'], os.environ['ACTION'].lower() app, action = os.environ['APP'], os.environ['ACTION'].lower()
key, value = os.environ['KEY'], os.environ.get('VALUE', None) key, value = os.environ['KEY'], os.environ.get('VALUE', None)

View file

@ -0,0 +1,286 @@
#!/bin/bash
# Download, check integrity, uncompress and patch the source from app.src
#
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id] [--keep="file1 file2"] [--full_replace]
# | arg: -d, --dest_dir= - Directory where to setup sources
# | arg: -s, --source_id= - Name of the source, defaults to `main` (when the sources resource exists in manifest.toml) or (legacy) `app` otherwise
# | arg: -k, --keep= - Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs' (no trailing `/` for folders)
# | arg: -r, --full_replace= - Remove previous sources before installing new sources (can be 1 or 0, default to 0)
#
# ##### New 'sources' resources
#
# (See also the resources documentation which may be more complete?)
#
# This helper will read infos from the 'sources' resources in the manifest.toml of the app
# and expect a structure like:
#
# ```toml
# [resources.sources]
# [resources.sources.main]
# url = "https://some.address.to/download/the/app/archive"
# sha256 = "0123456789abcdef" # The sha256 sum of the asset obtained from the URL
# ```
#
# ##### Optional flags
#
# ```text
# format = "tar.gz"/xz/bz2 # automatically guessed from the extension of the URL, but can be set explicitly. Will use `tar` to extract
# "zip" # automatically guessed from the extension of the URL, but can be set explicitly. Will use `unzip` to extract
# "docker" # useful to extract files from an already-built docker image (instead of rebuilding them locally). Will use `docker-image-extract` to extract
# "whatever" # an arbitrary value, not really meaningful except to imply that the file won't be extracted
#
# in_subdir = true # default, there's an intermediate subdir in the archive before accessing the actual files
# false # sources are directly in the archive root
# n # (special cases) an integer representing a number of subdirs levels to get rid of
#
# extract = true # default if file is indeed an archive such as .zip, .tar.gz, .tar.bz2, ...
# = false # default if file 'format' is not set and the file is not to be extracted because it is not an archive but a script or binary or whatever asset.
# # in which case the file will only be `mv`ed to the location possibly renamed using the `rename` value
#
# rename = "whatever_your_want" # to be used for convenience when `extract` is false and the default name of the file is not practical
# platform = "linux/amd64" # (defaults to "linux/$YNH_ARCH") to be used in conjonction with `format = "docker"` to specify which architecture to extract for
# ```
#
# You may also define assets url and checksum per-architectures such as:
# ```toml
# [resources.sources]
# [resources.sources.main]
# amd64.url = "https://some.address.to/download/the/app/archive/when/amd64"
# amd64.sha256 = "0123456789abcdef"
# armhf.url = "https://some.address.to/download/the/app/archive/when/armhf"
# armhf.sha256 = "fedcba9876543210"
# ```
#
# In which case `ynh_setup_source --dest_dir="$install_dir"` will automatically pick the appropriate source depending on the arch
#
# The helper will:
# - Download the specific URL if there is no local archive
# - Check the integrity with the specific sha256 sum
# - Uncompress the archive to `$dest_dir`.
# - If `in_subdir` is true, the first level directory of the archive will be removed.
# - If `in_subdir` is a numeric value, the N first level directories will be removed.
# - Patches named `sources/patches/${src_id}-*.patch` will be applied to `$dest_dir`
# - Extra files in `sources/extra_files/$src_id` will be copied to dest_dir
#
# Requires YunoHost version 2.6.4 or higher.
ynh_setup_source() {
# Declare an array to define the options of this helper.
local legacy_args=dsk
local -A args_array=([d]=dest_dir= [s]=source_id= [k]=keep= [r]=full_replace=)
local dest_dir
local source_id
local keep
local full_replace
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
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
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
local arch_prefix=""
else
local arch_prefix=".$YNH_ARCH"
fi
local src_url="$(jq -r "$arch_prefix.url" <<< "$sources_json" | sed 's/^null$//')"
local src_sum="$(jq -r "$arch_prefix.sha256" <<< "$sources_json" | sed 's/^null$//')"
local src_sumprg="sha256sum"
local src_format="$(jq -r ".format" <<< "$sources_json" | sed 's/^null$//')"
local src_in_subdir="$(jq -r ".in_subdir" <<< "$sources_json" | sed 's/^null$//')"
local src_extract="$(jq -r ".extract" <<< "$sources_json" | sed 's/^null$//')"
local src_platform="$(jq -r ".platform" <<< "$sources_json" | sed 's/^null$//')"
local src_rename="$(jq -r ".rename" <<< "$sources_json" | sed 's/^null$//')"
[[ -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
src_format="zip"
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
src_format="tar.xz"
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]; then
src_format="tar.bz2"
elif [[ -z "$src_extract" ]]; then
src_extract="false"
fi
fi
else
source_id="${source_id:-app}"
local src_file_path="$YNH_APP_BASEDIR/conf/${source_id}.src"
# Load value from configuration file (see above for a small doc about this file
# format)
local src_url=$(grep 'SOURCE_URL=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_sum=$(grep 'SOURCE_SUM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_format=$(grep 'SOURCE_FORMAT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_rename=$(grep 'SOURCE_FILENAME=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_extract=$(grep 'SOURCE_EXTRACT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_platform=$(grep 'SOURCE_PLATFORM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
fi
# Default value
src_sumprg=${src_sumprg:-sha256sum}
src_in_subdir=${src_in_subdir:-true}
src_format=${src_format:-tar.gz}
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
src_extract=${src_extract:-true}
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}"
# Gotta use this trick with 'dirname' because source_id may contain slashes x_x
mkdir -p $(dirname /var/cache/yunohost/download/${YNH_APP_ID}/${source_id})
src_filename="/var/cache/yunohost/download/${YNH_APP_ID}/${source_id}"
if [ "$src_format" = "docker" ]; then
src_platform="${src_platform:-"linux/$YNH_ARCH"}"
else
if test -e "$local_src"; then
cp $local_src $src_filename
fi
[ -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
rm -f "$src_filename"
fi
# Only redownload the file if it wasnt prefetched
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 ...
local out
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
|| ynh_die --message="$out"
fi
# Check the control sum
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}
ynh_die --message="Corrupt source for ${src_url}: Expected sha256sum to be ${src_sum} but got ${actual_sum} (size: ${actual_size})."
fi
fi
# Keep files to be backup/restored at the end of the helper
# Assuming $dest_dir already exists
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
if [ -n "$keep" ] && [ -e "$dest_dir" ]; then
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
mkdir -p $keep_dir
local stuff_to_keep
for stuff_to_keep in $keep; do
if [ -e "$dest_dir/$stuff_to_keep" ]; then
mkdir --parents "$(dirname "$keep_dir/$stuff_to_keep")"
cp --archive "$dest_dir/$stuff_to_keep" "$keep_dir/$stuff_to_keep"
fi
done
fi
if [ "$full_replace" -eq 1 ]; then
ynh_secure_remove --file="$dest_dir"
fi
# Extract source into the app dir
mkdir --parents "$dest_dir"
if [ -n "${install_dir:-}" ] && [ "$dest_dir" == "$install_dir" ]; then
_ynh_apply_default_permissions $dest_dir
fi
if [ -n "${final_path:-}" ] && [ "$dest_dir" == "$final_path" ]; then
_ynh_apply_default_permissions $dest_dir
fi
if [[ "$src_extract" == "false" ]]; then
if [[ -z "$src_rename" ]]; then
mv $src_filename $dest_dir
else
mv $src_filename $dest_dir/$src_rename
fi
elif [[ "$src_format" == "docker" ]]; then
"$YNH_HELPERS_DIR/vendor/docker-image-extract/docker-image-extract" -p $src_platform -o $dest_dir $src_url 2>&1
elif [[ "$src_format" == "zip" ]]; then
# Zip format
# Using of a temp directory, because unzip doesn't manage --strip-components
if $src_in_subdir; then
local tmp_dir=$(mktemp --directory)
unzip -quo $src_filename -d "$tmp_dir"
cp --archive $tmp_dir/*/. "$dest_dir"
ynh_secure_remove --file="$tmp_dir"
else
unzip -quo $src_filename -d "$dest_dir"
fi
ynh_secure_remove --file="$src_filename"
else
local strip=""
if [ "$src_in_subdir" != "false" ]; then
if [ "$src_in_subdir" == "true" ]; then
local sub_dirs=1
else
local sub_dirs="$src_in_subdir"
fi
strip="--strip-components $sub_dirs"
fi
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]]; then
tar --extract --file=$src_filename --directory="$dest_dir" $strip
else
ynh_die --message="Archive format unrecognized."
fi
ynh_secure_remove --file="$src_filename"
fi
# 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
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"
done
popd
fi
fi
# Add supplementary files
if test -e "$YNH_APP_BASEDIR/sources/extra_files/${source_id}"; then
cp --archive $YNH_APP_BASEDIR/sources/extra_files/$source_id/. "$dest_dir"
fi
# Keep files to be backup/restored at the end of the helper
# Assuming $dest_dir already exists
if [ -n "$keep" ]; then
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
local stuff_to_keep
for stuff_to_keep in $keep; do
if [ -e "$keep_dir/$stuff_to_keep" ]; then
mkdir --parents "$(dirname "$dest_dir/$stuff_to_keep")"
# We add "--no-target-directory" (short option is -T) to handle the special case
# when we "keep" a folder, but then the new setup already contains the same dir (but possibly empty)
# in which case a regular "cp" will create a copy of the directory inside the directory ...
# resulting in something like /var/www/$app/data/data instead of /var/www/$app/data
# cf https://unix.stackexchange.com/q/94831 for a more elaborate explanation on the option
cp --archive --no-target-directory "$keep_dir/$stuff_to_keep" "$dest_dir/$stuff_to_keep"
fi
done
fi
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
}

View file

@ -21,7 +21,7 @@ ynh_string_random() {
length=${length:-24} length=${length:-24}
filter=${filter:-'A-Za-z0-9'} 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" \ | tr --complement --delete "$filter" \
| sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p' | sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p'
} }

View file

@ -94,12 +94,12 @@ ynh_systemd_action() {
# Following the starting of the app in its log # Following the starting of the app in its log
if [ "$log_path" == "systemd" ]; then if [ "$log_path" == "systemd" ]; then
# Read the systemd journal # 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 # Get the PID of the journalctl command
local pid_tail=$! local pid_tail=$!
else else
# Read the specified log file # 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 # Get the PID of the tail command
local pid_tail=$! local pid_tail=$!
fi fi
@ -149,8 +149,7 @@ ynh_systemd_action() {
# Also check the timeout using actual timestamp, because sometimes for some reason, # 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 # journalctl may take a huge time to run, and we end up waiting literally an entire hour
# instead of 5 min ... # instead of 5 min ...
if [[ "$(( $(date +%s) - $starttime))" -gt "$timeout" ]] if [[ "$(($(date +%s) - $starttime))" -gt "$timeout" ]]; then
then
i=$timeout i=$timeout
break break
fi fi

View file

@ -1,59 +1,5 @@
#!/bin/bash #!/bin/bash
# Check if a YunoHost user exists
#
# usage: ynh_user_exists --username=username
# | arg: -u, --username= - the username to check
# | ret: 0 if the user exists, 1 otherwise.
#
# example: ynh_user_exists 'toto' || echo "User does not exist"
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
local -A args_array=([u]=username=)
local username
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
yunohost user list --output-as json --quiet | jq -e ".users.\"${username}\"" >/dev/null
}
# Retrieve a YunoHost user information
#
# usage: ynh_user_get_info --username=username --key=key
# | arg: -u, --username= - the username to retrieve info from
# | arg: -k, --key= - the key to retrieve
# | ret: the value associate to that key
#
# example: mail=$(ynh_user_get_info --username="toto" --key=mail)
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_get_info() {
# Declare an array to define the options of this helper.
local legacy_args=uk
local -A args_array=([u]=username= [k]=key=)
local username
local key
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
yunohost user info "$username" --output-as json --quiet | jq -r ".$key"
}
# Get the list of YunoHost users
#
# usage: ynh_user_list
# | ret: one username per line as strings
#
# example: for u in $(ynh_user_list); do ... ; done
#
# Requires YunoHost version 2.4.0 or higher.
ynh_user_list() {
yunohost user list --output-as json --quiet | jq -r ".users | keys[]"
}
# Check if a user exists on the system # Check if a user exists on the system
# #
# [packagingv1] # [packagingv1]
@ -71,7 +17,7 @@ ynh_system_user_exists() {
# Manage arguments with getopts # Manage arguments with getopts
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
getent passwd "$username" &>/dev/null getent passwd "$username" &> /dev/null
} }
# Check if a group exists on the system # Check if a group exists on the system
@ -91,13 +37,11 @@ ynh_system_group_exists() {
# Manage arguments with getopts # Manage arguments with getopts
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
getent group "$group" &>/dev/null getent group "$group" &> /dev/null
} }
# Create a system user # Create a system user
# #
# [packagingv1]
#
# usage: ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell] [--groups="group1 group2"] # usage: ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell] [--groups="group1 group2"]
# | arg: -u, --username= - Name of the system user that will be create # | arg: -u, --username= - Name of the system user that will be create
# | arg: -h, --home_dir= - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home # | arg: -h, --home_dir= - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home
@ -152,8 +96,6 @@ ynh_system_user_create() {
# Delete a system user # Delete a system user
# #
# [packagingv1]
#
# usage: ynh_system_user_delete --username=user_name # usage: ynh_system_user_delete --username=user_name
# | arg: -u, --username= - Name of the system user that will be create # | arg: -u, --username= - Name of the system user that will be create
# #

View file

@ -0,0 +1,406 @@
#!/bin/bash
# Create a dedicated config file from a template
#
# usage: ynh_add_config --template="template" --destination="destination"
# | arg: -t, --template= - Template config file to use
# | arg: -d, --destination= - Destination of the config file
# | arg: -j, --jinja - Use jinja template instead of the simple `__MY_VAR__` templating format
#
# examples:
# ynh_add_config --template=".env" --destination="$install_dir/.env" # (use the template file "conf/.env" from the app's package)
# ynh_add_config --jinja --template="config.j2" --destination="$install_dir/config" # (use the template file "conf/config.j2" from the app's package)
#
# The template can be by default the name of a file in the conf directory
# of a YunoHost Package, a relative path or an absolute path.
#
# The helper will use the template `template` to generate a config file
# `destination` by replacing the following keywords with global variables
# that should be defined before calling this helper :
# ```
# __PATH__ by $path_url
# __NAME__ by $app
# __NAMETOCHANGE__ by $app
# __USER__ by $app
# __FINALPATH__ by $final_path
# __PHPVERSION__ by $YNH_PHP_VERSION (packaging v1 only, packaging v2 uses phpversion setting implicitly set by apt resource)
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH
# ```
# And any dynamic variables that should be defined before calling this helper like:
# ```
# __DOMAIN__ by $domain
# __APP__ by $app
# __VAR_1__ by $var_1
# __VAR_2__ by $var_2
# ```
#
# ##### When --jinja is enabled
#
# 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:
# 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
# if it's different before applying the new template.
#
# And it will calculate and store the destination file checksum
# into the app settings when configuration is done.
#
# Requires YunoHost version 4.1.0 or higher.
ynh_add_config() {
# Declare an array to define the options of this helper.
local legacy_args=tdj
local -A args_array=([t]=template= [d]=destination= [j]=jinja)
local template
local destination
local jinja
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local template_path
jinja="${jinja:-0}"
if [ -f "$YNH_APP_BASEDIR/conf/$template" ]; then
template_path="$YNH_APP_BASEDIR/conf/$template"
elif [ -f "$template" ]; then
template_path=$template
else
ynh_die --message="The provided template $template doesn't exist"
fi
ynh_backup_if_checksum_is_different --file="$destination"
# Make sure to set the permissions before we copy the file
# This is to cover a case where an attacker could have
# created a file beforehand to have control over it
# (cp won't overwrite ownership / modes by default...)
touch $destination
chmod 640 $destination
_ynh_apply_default_permissions $destination
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
)
else
cp -f "$template_path" "$destination"
ynh_replace_vars --file="$destination"
fi
ynh_store_file_checksum --file="$destination"
}
# Replace variables in a file
#
# [internal]
#
# usage: ynh_replace_vars --file="file"
# | arg: -f, --file= - File where to replace variables
#
# The helper will replace the following keywords with global variables
# that should be defined before calling this helper :
# __PATH__ by $path_url
# __NAME__ by $app
# __NAMETOCHANGE__ by $app
# __USER__ by $app
# __FINALPATH__ by $final_path
# __PHPVERSION__ by $YNH_PHP_VERSION (packaging v1 only, packaging v2 uses phpversion setting implicitly set by apt resource)
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH
#
# And any dynamic variables that should be defined before calling this helper like:
# __DOMAIN__ by $domain
# __APP__ by $app
# __VAR_1__ by $var_1
# __VAR_2__ by $var_2
#
# Requires YunoHost version 4.1.0 or higher.
ynh_replace_vars() {
# Declare an array to define the options of this helper.
local legacy_args=f
local -A args_array=([f]=file=)
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Replace specific YunoHost variables
if test -n "${path_url:-}"; then
# path_url_slash_less is path_url, or a blank value if path_url is only '/'
local path_url_slash_less=${path_url%/}
ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$file"
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$file"
fi
if test -n "${app:-}"; then
ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$file"
ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$file"
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$file"
fi
# Legacy
if test -n "${final_path:-}"; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$file"
ynh_replace_string --match_string="__INSTALL_DIR__" --replace_string="$final_path" --target_file="$file"
fi
# Legacy / Packaging v1 only
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2 && test -n "${YNH_PHP_VERSION:-}"; then
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$YNH_PHP_VERSION" --target_file="$file"
fi
if test -n "${ynh_node_load_PATH:-}"; then
ynh_replace_string --match_string="__YNH_NODE_LOAD_PATH__" --replace_string="$ynh_node_load_PATH" --target_file="$file"
fi
# Replace others variables
# List other unique (__ __) variables in $file
local uniques_vars=($(grep -oP '__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__' $file | sort --unique | sed "s@__\([^.]*\)__@\L\1@g"))
set +o xtrace # set +x
# Do the replacement
local delimit=@
for one_var in "${uniques_vars[@]}"; do
# Validate that one_var is indeed defined
# -v checks if the variable is defined, for example:
# -v FOO tests if $FOO is defined
# -v $FOO tests if ${!FOO} is defined
# More info: https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash/17538964#comment96392525_17538964
[[ -v "${one_var:-}" ]] || ynh_die --message="Variable \$$one_var wasn't initialized when trying to replace __${one_var^^}__ in $file"
# Escape delimiter in match/replace string
match_string="__${one_var^^}__"
match_string=${match_string//${delimit}/"\\${delimit}"}
replace_string="${!one_var}"
replace_string=${replace_string//\\/\\\\}
replace_string=${replace_string//${delimit}/"\\${delimit}"}
# Actually replace (sed is used instead of ynh_replace_string to avoid triggering an epic amount of debug logs)
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$file"
done
set -o xtrace # set -x
}
# Get a value from heterogeneous file (yaml, json, php, python...)
#
# usage: ynh_read_var_in_file --file=PATH --key=KEY
# | arg: -f, --file= - the path to the file
# | arg: -k, --key= - the key to get
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
#
# This helpers match several var affectation use case in several languages
# We don't use jq or equivalent to keep comments and blank space in files
# This helpers work line by line, it is not able to work correctly
# if you have several identical keys in your files
#
# Example of line this helpers can managed correctly
# .yml
# title: YunoHost documentation
# email: 'yunohost@yunohost.org'
# .json
# "theme": "colib'ris",
# "port": 8102
# "some_boolean": false,
# "user": null
# .ini
# some_boolean = On
# action = "Clear"
# port = 20
# .php
# $user=
# user => 20
# .py
# USER = 8102
# user = 'https://donate.local'
# CUSTOM['user'] = 'YunoHost'
#
# Requires YunoHost version 4.3 or higher.
ynh_read_var_in_file() {
# Declare an array to define the options of this helper.
local legacy_args=fka
local -A args_array=([f]=file= [k]=key= [a]=after=)
local file
local key
local after
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
after="${after:-}"
[[ -f $file ]] || ynh_die --message="File $file does not exists"
set +o xtrace # set +x
# Get the line number after which we search for the variable
local line_number=1
if [[ -n "$after" ]]; then
line_number=$(grep -m1 -n $after $file | cut -d: -f1)
if [[ -z "$line_number" ]]; then
set -o xtrace # set -x
return 1
fi
fi
local filename="$(basename -- "$file")"
local ext="${filename##*.}"
local endline=',;'
local assign="=>|:|="
local comments="#"
local string="\"'"
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
endline='#'
fi
if [[ "$ext" =~ ^ini|env$ ]]; then
comments="[;#]"
fi
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
comments="//"
fi
local list='\[\s*['$string']?\w+['$string']?\]'
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
var_part+="[$string]?${key}[$string]?"
var_part+='\s*\]?\s*'
var_part+="($assign)"
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)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
echo YNH_NULL
return 0
fi
# Remove comments if needed
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
local first_char="${expression:0:1}"
if [[ "$first_char" == '"' ]]; then
echo "$expression" | grep -m1 -o -P '"\K([^"](\\")?)*[^\\](?=")' | head -n1 | sed 's/\\"/"/g'
elif [[ "$first_char" == "'" ]]; then
echo "$expression" | grep -m1 -o -P "'\K([^'](\\\\')?)*[^\\\\](?=')" | head -n1 | sed "s/\\\\'/'/g"
else
echo "$expression"
fi
set -o xtrace # set -x
}
# Set a value into heterogeneous file (yaml, json, php, python...)
#
# usage: ynh_write_var_in_file --file=PATH --key=KEY --value=VALUE
# | arg: -f, --file= - the path to the file
# | arg: -k, --key= - the key to set
# | arg: -v, --value= - the value to set
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
#
# Requires YunoHost version 4.3 or higher.
ynh_write_var_in_file() {
# Declare an array to define the options of this helper.
local legacy_args=fkva
local -A args_array=([f]=file= [k]=key= [v]=value= [a]=after=)
local file
local key
local value
local after
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
after="${after:-}"
[[ -f $file ]] || ynh_die --message="File $file does not exists"
set +o xtrace # set +x
# Get the line number after which we search for the variable
local after_line_number=1
if [[ -n "$after" ]]; then
after_line_number=$(grep -m1 -n $after $file | cut -d: -f1)
if [[ -z "$after_line_number" ]]; then
set -o xtrace # set -x
return 1
fi
fi
local filename="$(basename -- "$file")"
local ext="${filename##*.}"
local endline=',;'
local assign="=>|:|="
local comments="#"
local string="\"'"
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
endline='#'
fi
if [[ "$ext" =~ ^ini|env$ ]]; then
comments="[;#]"
fi
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
comments="//"
fi
local list='\[\s*['$string']?\w+['$string']?\]'
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
var_part+="[$string]?${key}[$string]?"
var_part+='\s*\]?\s*'
var_part+="($assign)"
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)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
return 1
fi
local value_line_number="$(tail +$after_line_number ${file} | grep -m1 -n -i -P $var_part'\K.*$' | cut -d: -f1)"
value_line_number=$((after_line_number + value_line_number))
local range="${after_line_number},${value_line_number} "
# Remove comments if needed
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
endline=${expression_with_comment#"$expression"}
endline="$(echo "$endline" | sed 's/\\/\\\\/g')"
value="$(echo "$value" | sed 's/\\/\\\\/g')"
value=${value//&/"\&"}
local first_char="${expression:0:1}"
delimiter=$'\001'
if [[ "$first_char" == '"' ]]; then
# \ and sed is quite complex you need 2 \\ to get one in a sed
# So we need \\\\ to go through 2 sed
value="$(echo "$value" | sed 's/"/\\\\"/g')"
sed -ri "${range}s$delimiter"'(^'"${var_part}"'")([^"]|\\")*("[\s;,]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}"'"'"${endline}${delimiter}i" ${file}
elif [[ "$first_char" == "'" ]]; then
# \ and sed is quite complex you need 2 \\ to get one in a sed
# However double quotes implies to double \\ to
# So we need \\\\\\\\ to go through 2 sed and 1 double quotes str
value="$(echo "$value" | sed "s/'/\\\\\\\\'/g")"
sed -ri "${range}s$delimiter(^${var_part}')([^']|\\')*('"'[\s,;]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}'${endline}${delimiter}i" ${file}
else
if [[ "$value" == *"'"* ]] || [[ "$value" == *'"'* ]] || [[ "$ext" =~ ^php|py|json|js$ ]]; then
value='\"'"$(echo "$value" | sed 's/"/\\\\"/g')"'\"'
fi
if [[ "$ext" =~ ^yaml|yml$ ]]; then
value=" $value"
fi
sed -ri "${range}s$delimiter(^${var_part}).*\$$delimiter\1${value}${endline}${delimiter}i" ${file}
fi
set -o xtrace # set -x
}
# Render templates with Jinja2
#
# [internal]
#
# Attention : Variables should be exported before calling this helper to be
# accessible inside templates.
#
# usage: ynh_render_template some_template output_path
# | arg: some_template - Template file to be rendered
# | arg: output_path - The path where the output will be redirected to
ynh_render_template() {
local template_path=$1
local output_path=$2
mkdir -p "$(dirname $output_path)"
# Taken from https://stackoverflow.com/a/35009576
python3 -c 'import os, sys, jinja2; sys.stdout.write(
jinja2.Template(sys.stdin.read()
).render(os.environ));' < $template_path > $output_path
}

View file

@ -22,8 +22,7 @@ YNH_APP_BASEDIR=${YNH_APP_BASEDIR:-$(realpath ..)}
ynh_exit_properly() { ynh_exit_properly() {
local exit_code=$? local exit_code=$?
if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]] if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]]; then
then
rm -rf "/var/cache/yunohost/download/" rm -rf "/var/cache/yunohost/download/"
fi fi
@ -39,7 +38,7 @@ ynh_exit_properly() {
# Small tempo to avoid the next message being mixed up with other DEBUG messages # Small tempo to avoid the next message being mixed up with other DEBUG messages
sleep 0.5 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. ynh_clean_setup # Call the function to do specific cleaning for the app.
fi fi
@ -67,327 +66,10 @@ ynh_abort_if_errors() {
} }
# When running an app script with packaging format >= 2, auto-enable ynh_abort_if_errors except for remove script # 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" ]] if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} ge 2 && [[ ${YNH_APP_ACTION} != "remove" ]]; then
then
ynh_abort_if_errors ynh_abort_if_errors
fi fi
# Download, check integrity, uncompress and patch the source from app.src
#
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id] [--keep="file1 file2"] [--full_replace]
# | arg: -d, --dest_dir= - Directory where to setup sources
# | arg: -s, --source_id= - Name of the source, defaults to `main` (when the sources resource exists in manifest.toml) or (legacy) `app` otherwise
# | arg: -k, --keep= - Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs' (no trailing `/` for folders)
# | arg: -r, --full_replace= - Remove previous sources before installing new sources (can be 1 or 0, default to 0)
#
# #### New 'sources' resources
#
# (See also the resources documentation which may be more complete?)
#
# This helper will read infos from the 'sources' resources in the manifest.toml of the app
# and expect a structure like:
#
# ```toml
# [resources.sources]
# [resources.sources.main]
# url = "https://some.address.to/download/the/app/archive"
# sha256 = "0123456789abcdef" # The sha256 sum of the asset obtained from the URL
# ```
#
# ##### Optional flags
#
# ```text
# format = "tar.gz"/xz/bz2 # automatically guessed from the extension of the URL, but can be set explicitly. Will use `tar` to extract
# "zip" # automatically guessed from the extension of the URL, but can be set explicitly. Will use `unzip` to extract
# "docker" # useful to extract files from an already-built docker image (instead of rebuilding them locally). Will use `docker-image-extract` to extract
# "whatever" # an arbitrary value, not really meaningful except to imply that the file won't be extracted
#
# in_subdir = true # default, there's an intermediate subdir in the archive before accessing the actual files
# false # sources are directly in the archive root
# n # (special cases) an integer representing a number of subdirs levels to get rid of
#
# extract = true # default if file is indeed an archive such as .zip, .tar.gz, .tar.bz2, ...
# = false # default if file 'format' is not set and the file is not to be extracted because it is not an archive but a script or binary or whatever asset.
# # in which case the file will only be `mv`ed to the location possibly renamed using the `rename` value
#
# rename = "whatever_your_want" # to be used for convenience when `extract` is false and the default name of the file is not practical
# platform = "linux/amd64" # (defaults to "linux/$YNH_ARCH") to be used in conjonction with `format = "docker"` to specify which architecture to extract for
# ```
#
# You may also define assets url and checksum per-architectures such as:
# ```toml
# [resources.sources]
# [resources.sources.main]
# amd64.url = "https://some.address.to/download/the/app/archive/when/amd64"
# amd64.sha256 = "0123456789abcdef"
# armhf.url = "https://some.address.to/download/the/app/archive/when/armhf"
# armhf.sha256 = "fedcba9876543210"
# ```
#
# In which case ynh_setup_source --dest_dir="$install_dir" will automatically pick the appropriate source depending on the arch
#
#
#
# #### Legacy format '.src'
#
# This helper will read `conf/${source_id}.src`, download and install the sources.
#
# The src file need to contains:
# ```
# SOURCE_URL=Address to download the app archive
# SOURCE_SUM=Sha256 sum
# SOURCE_FORMAT=tar.gz
# SOURCE_IN_SUBDIR=false
# SOURCE_FILENAME=example.tar.gz
# SOURCE_EXTRACT=(true|false)
# SOURCE_PLATFORM=linux/arm64/v8
# ```
#
# The helper will:
# - Download the specific URL if there is no local archive
# - Check the integrity with the specific sha256 sum
# - Uncompress the archive to `$dest_dir`.
# - If `in_subdir` is true, the first level directory of the archive will be removed.
# - If `in_subdir` is a numeric value, the N first level directories will be removed.
# - Patches named `sources/patches/${src_id}-*.patch` will be applied to `$dest_dir`
# - Extra files in `sources/extra_files/$src_id` will be copied to dest_dir
#
# Requires YunoHost version 2.6.4 or higher.
ynh_setup_source() {
# Declare an array to define the options of this helper.
local legacy_args=dsk
local -A args_array=([d]=dest_dir= [s]=source_id= [k]=keep= [r]=full_replace=)
local dest_dir
local source_id
local keep
local full_replace
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
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
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
local arch_prefix=""
else
local arch_prefix=".$YNH_ARCH"
fi
local src_url="$(jq -r "$arch_prefix.url" <<< "$sources_json" | sed 's/^null$//')"
local src_sum="$(jq -r "$arch_prefix.sha256" <<< "$sources_json" | sed 's/^null$//')"
local src_sumprg="sha256sum"
local src_format="$(jq -r ".format" <<< "$sources_json" | sed 's/^null$//')"
local src_in_subdir="$(jq -r ".in_subdir" <<< "$sources_json" | sed 's/^null$//')"
local src_extract="$(jq -r ".extract" <<< "$sources_json" | sed 's/^null$//')"
local src_platform="$(jq -r ".platform" <<< "$sources_json" | sed 's/^null$//')"
local src_rename="$(jq -r ".rename" <<< "$sources_json" | sed 's/^null$//')"
[[ -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
src_format="zip"
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
src_format="tar.xz"
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]
then
src_format="tar.bz2"
elif [[ -z "$src_extract" ]]
then
src_extract="false"
fi
fi
else
source_id="${source_id:-app}"
local src_file_path="$YNH_APP_BASEDIR/conf/${source_id}.src"
# Load value from configuration file (see above for a small doc about this file
# format)
local src_url=$(grep 'SOURCE_URL=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_sum=$(grep 'SOURCE_SUM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_format=$(grep 'SOURCE_FORMAT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_rename=$(grep 'SOURCE_FILENAME=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_extract=$(grep 'SOURCE_EXTRACT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
local src_platform=$(grep 'SOURCE_PLATFORM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
fi
# Default value
src_sumprg=${src_sumprg:-sha256sum}
src_in_subdir=${src_in_subdir:-true}
src_format=${src_format:-tar.gz}
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
src_extract=${src_extract:-true}
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}"
# Gotta use this trick with 'dirname' because source_id may contain slashes x_x
mkdir -p $(dirname /var/cache/yunohost/download/${YNH_APP_ID}/${source_id})
src_filename="/var/cache/yunohost/download/${YNH_APP_ID}/${source_id}"
if [ "$src_format" = "docker" ]; then
src_platform="${src_platform:-"linux/$YNH_ARCH"}"
else
if test -e "$local_src"; then
cp $local_src $src_filename
fi
[ -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
rm -f "$src_filename"
fi
# Only redownload the file if it wasnt prefetched
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 ...
local out
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
|| ynh_die --message="$out"
fi
# Check the control sum
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}
ynh_die --message="Corrupt source for ${src_url}: Expected sha256sum to be ${src_sum} but got ${actual_sum} (size: ${actual_size})."
fi
fi
# Keep files to be backup/restored at the end of the helper
# Assuming $dest_dir already exists
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
if [ -n "$keep" ] && [ -e "$dest_dir" ]; then
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
mkdir -p $keep_dir
local stuff_to_keep
for stuff_to_keep in $keep; do
if [ -e "$dest_dir/$stuff_to_keep" ]; then
mkdir --parents "$(dirname "$keep_dir/$stuff_to_keep")"
cp --archive "$dest_dir/$stuff_to_keep" "$keep_dir/$stuff_to_keep"
fi
done
fi
if [ "$full_replace" -eq 1 ]; then
ynh_secure_remove --file="$dest_dir"
fi
# Extract source into the app dir
mkdir --parents "$dest_dir"
if [ -n "${install_dir:-}" ] && [ "$dest_dir" == "$install_dir" ]; then
_ynh_apply_default_permissions $dest_dir
fi
if [ -n "${final_path:-}" ] && [ "$dest_dir" == "$final_path" ]; then
_ynh_apply_default_permissions $dest_dir
fi
if [[ "$src_extract" == "false" ]]; then
if [[ -z "$src_rename" ]]
then
mv $src_filename $dest_dir
else
mv $src_filename $dest_dir/$src_rename
fi
elif [[ "$src_format" == "docker" ]]; then
"$YNH_HELPERS_DIR/vendor/docker-image-extract/docker-image-extract" -p $src_platform -o $dest_dir $src_url 2>&1
elif [[ "$src_format" == "zip" ]]; then
# Zip format
# Using of a temp directory, because unzip doesn't manage --strip-components
if $src_in_subdir; then
local tmp_dir=$(mktemp --directory)
unzip -quo $src_filename -d "$tmp_dir"
cp --archive $tmp_dir/*/. "$dest_dir"
ynh_secure_remove --file="$tmp_dir"
else
unzip -quo $src_filename -d "$dest_dir"
fi
ynh_secure_remove --file="$src_filename"
else
local strip=""
if [ "$src_in_subdir" != "false" ]; then
if [ "$src_in_subdir" == "true" ]; then
local sub_dirs=1
else
local sub_dirs="$src_in_subdir"
fi
strip="--strip-components $sub_dirs"
fi
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]]; then
tar --extract --file=$src_filename --directory="$dest_dir" $strip
else
ynh_die --message="Archive format unrecognized."
fi
ynh_secure_remove --file="$src_filename"
fi
# 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
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"
done
popd
fi
fi
# Add supplementary files
if test -e "$YNH_APP_BASEDIR/sources/extra_files/${source_id}"; then
cp --archive $YNH_APP_BASEDIR/sources/extra_files/$source_id/. "$dest_dir"
fi
# Keep files to be backup/restored at the end of the helper
# Assuming $dest_dir already exists
if [ -n "$keep" ]; then
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
local stuff_to_keep
for stuff_to_keep in $keep; do
if [ -e "$keep_dir/$stuff_to_keep" ]; then
mkdir --parents "$(dirname "$dest_dir/$stuff_to_keep")"
# We add "--no-target-directory" (short option is -T) to handle the special case
# when we "keep" a folder, but then the new setup already contains the same dir (but possibly empty)
# in which case a regular "cp" will create a copy of the directory inside the directory ...
# resulting in something like /var/www/$app/data/data instead of /var/www/$app/data
# cf https://unix.stackexchange.com/q/94831 for a more elaborate explanation on the option
cp --archive --no-target-directory "$keep_dir/$stuff_to_keep" "$dest_dir/$stuff_to_keep"
fi
done
fi
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
}
# Curl abstraction to help with POST requests to local pages (such as installation forms) # Curl abstraction to help with POST requests to local pages (such as installation forms)
# #
# usage: ynh_local_curl "page_uri" "key1=value1" "key2=value2" ... # usage: ynh_local_curl "page_uri" "key1=value1" "key2=value2" ...
@ -447,435 +129,6 @@ ynh_local_curl() {
fi fi
} }
# Create a dedicated config file from a template
#
# usage: ynh_add_config --template="template" --destination="destination"
# | arg: -t, --template= - Template config file to use
# | arg: -d, --destination= - Destination of the config file
# | arg: -j, --jinja - Use jinja template instead of legacy __MY_VAR__
#
# examples:
# ynh_add_config --template=".env" --destination="$install_dir/.env" use the template file "../conf/.env"
# ynh_add_config --jinja --template="config.j2" --destination="$install_dir/config" use the template file "../conf/config.j2"
# ynh_add_config --template="/etc/nginx/sites-available/default" --destination="etc/nginx/sites-available/mydomain.conf"
#
##
## How it works in "legacy" mode
##
# The template can be by default the name of a file in the conf directory
# of a YunoHost Package, a relative path or an absolute path.
#
# The helper will use the template `template` to generate a config file
# `destination` by replacing the following keywords with global variables
# that should be defined before calling this helper :
# ```
# __PATH__ by $path_url
# __NAME__ by $app
# __NAMETOCHANGE__ by $app
# __USER__ by $app
# __FINALPATH__ by $final_path
# __PHPVERSION__ by $YNH_PHP_VERSION (packaging v1 only, packaging v2 uses phpversion setting implicitly set by apt resource)
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH
# ```
# And any dynamic variables that should be defined before calling this helper like:
# ```
# __DOMAIN__ by $domain
# __APP__ by $app
# __VAR_1__ by $var_1
# __VAR_2__ by $var_2
# ```
#
##
## When --jinja is enabled
##
# For a full documentation of the template you can refer to: https://jinja.palletsprojects.com/en/3.1.x/templates/
# In Yunohost context there are no really some specificity except that all variable passed are of type string.
# So here are some example of recommended usage:
#
# If you need a conditional block
#
# {% if should_my_block_be_shown == 'true' %}
# ...
# {% endif %}
#
# or
#
# {% if should_my_block_be_shown == '1' %}
# ...
# {% endif %}
#
# If you need to iterate with loop:
#
# {% for yolo in var_with_multiline_value.splitlines() %}
# ...
# {% endfor %}
#
# or
#
# {% for jail in my_var_with_coma.split(',') %}
# ...
# {% endfor %}
#
# The helper will verify the checksum and backup the destination file
# if it's different before applying the new template.
#
# And it will calculate and store the destination file checksum
# into the app settings when configuration is done.
#
# Requires YunoHost version 4.1.0 or higher.
ynh_add_config() {
# Declare an array to define the options of this helper.
local legacy_args=tdj
local -A args_array=([t]=template= [d]=destination= [j]=jinja)
local template
local destination
local jinja
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local template_path
jinja="${jinja:-0}"
if [ -f "$YNH_APP_BASEDIR/conf/$template" ]; then
template_path="$YNH_APP_BASEDIR/conf/$template"
elif [ -f "$template" ]; then
template_path=$template
else
ynh_die --message="The provided template $template doesn't exist"
fi
ynh_backup_if_checksum_is_different --file="$destination"
# Make sure to set the permissions before we copy the file
# This is to cover a case where an attacker could have
# created a file beforehand to have control over it
# (cp won't overwrite ownership / modes by default...)
touch $destination
chmod 640 $destination
_ynh_apply_default_permissions $destination
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
)
else
cp -f "$template_path" "$destination"
ynh_replace_vars --file="$destination"
fi
ynh_store_file_checksum --file="$destination"
}
# Replace variables in a file
#
# [internal]
#
# usage: ynh_replace_vars --file="file"
# | arg: -f, --file= - File where to replace variables
#
# The helper will replace the following keywords with global variables
# that should be defined before calling this helper :
# __PATH__ by $path_url
# __NAME__ by $app
# __NAMETOCHANGE__ by $app
# __USER__ by $app
# __FINALPATH__ by $final_path
# __PHPVERSION__ by $YNH_PHP_VERSION (packaging v1 only, packaging v2 uses phpversion setting implicitly set by apt resource)
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH
#
# And any dynamic variables that should be defined before calling this helper like:
# __DOMAIN__ by $domain
# __APP__ by $app
# __VAR_1__ by $var_1
# __VAR_2__ by $var_2
#
# Requires YunoHost version 4.1.0 or higher.
ynh_replace_vars() {
# Declare an array to define the options of this helper.
local legacy_args=f
local -A args_array=([f]=file=)
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
# Replace specific YunoHost variables
if test -n "${path_url:-}"; then
# path_url_slash_less is path_url, or a blank value if path_url is only '/'
local path_url_slash_less=${path_url%/}
ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$file"
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$file"
fi
if test -n "${app:-}"; then
ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$file"
ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$file"
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$file"
fi
# Legacy
if test -n "${final_path:-}"; then
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$file"
ynh_replace_string --match_string="__INSTALL_DIR__" --replace_string="$final_path" --target_file="$file"
fi
# Legacy / Packaging v1 only
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2 && test -n "${YNH_PHP_VERSION:-}"; then
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$YNH_PHP_VERSION" --target_file="$file"
fi
if test -n "${ynh_node_load_PATH:-}"; then
ynh_replace_string --match_string="__YNH_NODE_LOAD_PATH__" --replace_string="$ynh_node_load_PATH" --target_file="$file"
fi
# Replace others variables
# List other unique (__ __) variables in $file
local uniques_vars=($(grep -oP '__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__' $file | sort --unique | sed "s@__\([^.]*\)__@\L\1@g"))
set +o xtrace # set +x
# Do the replacement
local delimit=@
for one_var in "${uniques_vars[@]}"; do
# Validate that one_var is indeed defined
# -v checks if the variable is defined, for example:
# -v FOO tests if $FOO is defined
# -v $FOO tests if ${!FOO} is defined
# More info: https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash/17538964#comment96392525_17538964
[[ -v "${one_var:-}" ]] || ynh_die --message="Variable \$$one_var wasn't initialized when trying to replace __${one_var^^}__ in $file"
# Escape delimiter in match/replace string
match_string="__${one_var^^}__"
match_string=${match_string//${delimit}/"\\${delimit}"}
replace_string="${!one_var}"
replace_string=${replace_string//\\/\\\\}
replace_string=${replace_string//${delimit}/"\\${delimit}"}
# Actually replace (sed is used instead of ynh_replace_string to avoid triggering an epic amount of debug logs)
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$file"
done
set -o xtrace # set -x
}
# Get a value from heterogeneous file (yaml, json, php, python...)
#
# usage: ynh_read_var_in_file --file=PATH --key=KEY
# | arg: -f, --file= - the path to the file
# | arg: -k, --key= - the key to get
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
#
# This helpers match several var affectation use case in several languages
# We don't use jq or equivalent to keep comments and blank space in files
# This helpers work line by line, it is not able to work correctly
# if you have several identical keys in your files
#
# Example of line this helpers can managed correctly
# .yml
# title: YunoHost documentation
# email: 'yunohost@yunohost.org'
# .json
# "theme": "colib'ris",
# "port": 8102
# "some_boolean": false,
# "user": null
# .ini
# some_boolean = On
# action = "Clear"
# port = 20
# .php
# $user=
# user => 20
# .py
# USER = 8102
# user = 'https://donate.local'
# CUSTOM['user'] = 'YunoHost'
#
# Requires YunoHost version 4.3 or higher.
ynh_read_var_in_file() {
# Declare an array to define the options of this helper.
local legacy_args=fka
local -A args_array=([f]=file= [k]=key= [a]=after=)
local file
local key
local after
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
after="${after:-}"
[[ -f $file ]] || ynh_die --message="File $file does not exists"
set +o xtrace # set +x
# Get the line number after which we search for the variable
local line_number=1
if [[ -n "$after" ]]; then
line_number=$(grep -m1 -n $after $file | cut -d: -f1)
if [[ -z "$line_number" ]]; then
set -o xtrace # set -x
return 1
fi
fi
local filename="$(basename -- "$file")"
local ext="${filename##*.}"
local endline=',;'
local assign="=>|:|="
local comments="#"
local string="\"'"
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
endline='#'
fi
if [[ "$ext" =~ ^ini|env$ ]]; then
comments="[;#]"
fi
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
comments="//"
fi
local list='\[\s*['$string']?\w+['$string']?\]'
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
var_part+="[$string]?${key}[$string]?"
var_part+='\s*\]?\s*'
var_part+="($assign)"
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)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
echo YNH_NULL
return 0
fi
# Remove comments if needed
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
local first_char="${expression:0:1}"
if [[ "$first_char" == '"' ]]; then
echo "$expression" | grep -m1 -o -P '"\K([^"](\\")?)*[^\\](?=")' | head -n1 | sed 's/\\"/"/g'
elif [[ "$first_char" == "'" ]]; then
echo "$expression" | grep -m1 -o -P "'\K([^'](\\\\')?)*[^\\\\](?=')" | head -n1 | sed "s/\\\\'/'/g"
else
echo "$expression"
fi
set -o xtrace # set -x
}
# Set a value into heterogeneous file (yaml, json, php, python...)
#
# usage: ynh_write_var_in_file --file=PATH --key=KEY --value=VALUE
# | arg: -f, --file= - the path to the file
# | arg: -k, --key= - the key to set
# | arg: -v, --value= - the value to set
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
#
# Requires YunoHost version 4.3 or higher.
ynh_write_var_in_file() {
# Declare an array to define the options of this helper.
local legacy_args=fkva
local -A args_array=([f]=file= [k]=key= [v]=value= [a]=after=)
local file
local key
local value
local after
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
after="${after:-}"
[[ -f $file ]] || ynh_die --message="File $file does not exists"
set +o xtrace # set +x
# Get the line number after which we search for the variable
local after_line_number=1
if [[ -n "$after" ]]; then
after_line_number=$(grep -m1 -n $after $file | cut -d: -f1)
if [[ -z "$after_line_number" ]]; then
set -o xtrace # set -x
return 1
fi
fi
local filename="$(basename -- "$file")"
local ext="${filename##*.}"
local endline=',;'
local assign="=>|:|="
local comments="#"
local string="\"'"
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
endline='#'
fi
if [[ "$ext" =~ ^ini|env$ ]]; then
comments="[;#]"
fi
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
comments="//"
fi
local list='\[\s*['$string']?\w+['$string']?\]'
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
var_part+="[$string]?${key}[$string]?"
var_part+='\s*\]?\s*'
var_part+="($assign)"
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)"
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x
return 1
fi
local value_line_number="$(tail +$after_line_number ${file} | grep -m1 -n -i -P $var_part'\K.*$' | cut -d: -f1)"
value_line_number=$((after_line_number + value_line_number))
local range="${after_line_number},${value_line_number} "
# Remove comments if needed
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
endline=${expression_with_comment#"$expression"}
endline="$(echo "$endline" | sed 's/\\/\\\\/g')"
value="$(echo "$value" | sed 's/\\/\\\\/g')"
value=${value//&/"\&"}
local first_char="${expression:0:1}"
delimiter=$'\001'
if [[ "$first_char" == '"' ]]; then
# \ and sed is quite complex you need 2 \\ to get one in a sed
# So we need \\\\ to go through 2 sed
value="$(echo "$value" | sed 's/"/\\\\"/g')"
sed -ri "${range}s$delimiter"'(^'"${var_part}"'")([^"]|\\")*("[\s;,]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}"'"'"${endline}${delimiter}i" ${file}
elif [[ "$first_char" == "'" ]]; then
# \ and sed is quite complex you need 2 \\ to get one in a sed
# However double quotes implies to double \\ to
# So we need \\\\\\\\ to go through 2 sed and 1 double quotes str
value="$(echo "$value" | sed "s/'/\\\\\\\\'/g")"
sed -ri "${range}s$delimiter(^${var_part}')([^']|\\')*('"'[\s,;]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}'${endline}${delimiter}i" ${file}
else
if [[ "$value" == *"'"* ]] || [[ "$value" == *'"'* ]] || [[ "$ext" =~ ^php|py|json|js$ ]]; then
value='\"'"$(echo "$value" | sed 's/"/\\\\"/g')"'\"'
fi
if [[ "$ext" =~ ^yaml|yml$ ]]; then
value=" $value"
fi
sed -ri "${range}s$delimiter(^${var_part}).*\$$delimiter\1${value}${endline}${delimiter}i" ${file}
fi
set -o xtrace # set -x
}
# Render templates with Jinja2
#
# [internal]
#
# Attention : Variables should be exported before calling this helper to be
# accessible inside templates.
#
# usage: ynh_render_template some_template output_path
# | arg: some_template - Template file to be rendered
# | arg: output_path - The path where the output will be redirected to
ynh_render_template() {
local template_path=$1
local output_path=$2
mkdir -p "$(dirname $output_path)"
# Taken from https://stackoverflow.com/a/35009576
python3 -c 'import os, sys, jinja2; sys.stdout.write(
jinja2.Template(sys.stdin.read()
).render(os.environ));' <$template_path >$output_path
}
# Fetch the Debian release codename # Fetch the Debian release codename
# #
# [packagingv1] # [packagingv1]
@ -894,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) 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 ... # Legacy : A couple apps still have data in /home/$app ...
if [[ -n "${app:-}" ]] if [[ -n "${app:-}" ]]; then
then
forbidden_paths=$(echo "$forbidden_paths" | grep -v "/home/$app") forbidden_paths=$(echo "$forbidden_paths" | grep -v "/home/$app")
fi fi
@ -960,19 +212,16 @@ ynh_read_manifest() {
if [ ! -e "${manifest:-}" ]; then if [ ! -e "${manifest:-}" ]; then
# If the manifest isn't found, try the common place for backup and restore script. # If the manifest isn't found, try the common place for backup and restore script.
if [ -e "$YNH_APP_BASEDIR/manifest.json" ] if [ -e "$YNH_APP_BASEDIR/manifest.json" ]; then
then
manifest="$YNH_APP_BASEDIR/manifest.json" manifest="$YNH_APP_BASEDIR/manifest.json"
elif [ -e "$YNH_APP_BASEDIR/manifest.toml" ] elif [ -e "$YNH_APP_BASEDIR/manifest.toml" ]; then
then
manifest="$YNH_APP_BASEDIR/manifest.toml" manifest="$YNH_APP_BASEDIR/manifest.toml"
else else
ynh_die --message "No manifest found !?" ynh_die --message "No manifest found !?"
fi fi
fi fi
if echo "$manifest" | grep -q '\.json$' if echo "$manifest" | grep -q '\.json$'; then
then
jq ".$manifest_key" "$manifest" --raw-output jq ".$manifest_key" "$manifest" --raw-output
else else
cat "$manifest" | python3 -c 'import json, toml, sys; print(json.dumps(toml.load(sys.stdin)))' | jq ".$manifest_key" --raw-output cat "$manifest" | python3 -c 'import json, toml, sys; print(json.dumps(toml.load(sys.stdin)))' | jq ".$manifest_key" --raw-output
@ -1132,8 +381,7 @@ _ynh_apply_default_permissions() {
# Crons should be owned by root # Crons should be owned by root
# Also we don't want systemd conf, nginx conf or others stuff to be owned by the app, # 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 # 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" if grep -qE '^(/etc/cron|/etc/php|/etc/nginx/conf.d|/etc/fail2ban|/etc/systemd/system)' <<< "$target"; then
then
chmod 400 $target chmod 400 $target
chown root:root $target chown root:root $target
fi fi
@ -1146,3 +394,57 @@ int_to_bool() {
toml_to_json() { toml_to_json() {
python3 -c 'import toml, json, sys; print(json.dumps(toml.load(sys.stdin)))' python3 -c 'import toml, json, sys; print(json.dumps(toml.load(sys.stdin)))'
} }
# Check if a YunoHost user exists
#
# usage: ynh_user_exists --username=username
# | arg: -u, --username= - the username to check
# | ret: 0 if the user exists, 1 otherwise.
#
# example: ynh_user_exists 'toto' || echo "User does not exist"
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
local -A args_array=([u]=username=)
local username
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
yunohost user list --output-as json --quiet | jq -e ".users.\"${username}\"" > /dev/null
}
# Retrieve a YunoHost user information
#
# usage: ynh_user_get_info --username=username --key=key
# | arg: -u, --username= - the username to retrieve info from
# | arg: -k, --key= - the key to retrieve
# | ret: the value associate to that key
#
# example: mail=$(ynh_user_get_info --username="toto" --key=mail)
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_get_info() {
# Declare an array to define the options of this helper.
local legacy_args=uk
local -A args_array=([u]=username= [k]=key=)
local username
local key
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
yunohost user info "$username" --output-as json --quiet | jq -r ".$key"
}
# Get the list of YunoHost users
#
# usage: ynh_user_list
# | ret: one username per line as strings
#
# example: for u in $(ynh_user_list); do ... ; done
#
# Requires YunoHost version 2.4.0 or higher.
ynh_user_list() {
yunohost user list --output-as json --quiet | jq -r ".users | keys[]"
}

View file

@ -1,213 +0,0 @@
#!/bin/bash
# Install others YunoHost apps
#
# usage: ynh_install_apps --apps="appfoo?domain=domain.foo&path=/foo appbar?domain=domain.bar&path=/bar&admin=USER&language=fr&is_public=1&pass?word=pass&port=666"
# | arg: -a, --apps= - apps to install
#
# Requires YunoHost version *.*.* or higher.
ynh_install_apps() {
# ============ Argument parsing =============
local -A args_array=([a]=apps=)
local apps
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 "You didn't provided a YunoHost app to install"
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
if [ ! -z "$apps_dependencies" ]
then
apps_dependencies="$apps_dependencies, $one_app"
else
apps_dependencies="$one_app"
fi
done
ynh_app_setting_set --key=apps_dependencies --value="$apps_dependencies"
}
# Remove other YunoHost apps
#
# Other YunoHost apps will be removed only if no other apps need them.
#
# usage: ynh_remove_apps
#
# Requires YunoHost version *.*.* or higher.
ynh_remove_apps() {
# Retrieve the apps dependencies of the app
local apps_dependencies=$(ynh_app_setting_get --key=apps_dependencies)
ynh_app_setting_delete --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=""
# 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 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 "Removing of $one_app"
yunohost app remove $one_app --purge
else
ynh_print_info "$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
#
# usage: ynh_spawn_app_shell --app="app"
# | arg: -a, --app= - the app ID
#
# examples:
# ynh_spawn_app_shell --app="APP" <<< 'echo "$USER"'
# ynh_spawn_app_shell --app="APP" < /tmp/some_script.bash
#
# Requires YunoHost version 11.0.* or higher, and that the app relies on packaging v2 or higher.
# The spawned shell will have environment variables loaded and environment files sourced
# 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() {
# ============ Argument parsing =============
local -A args_array=([a]=app=)
local app
ynh_handle_getopts_args "$@"
# ===========================================
# Force Bash to be used to run this helper
if [[ ! $0 =~ \/?bash$ ]]
then
ynh_print_warn "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_warn "$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_warn "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 --key=install_dir)
if [ -z "$install_dir" ]
then
ynh_print_warn "$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 --key=service)
[ -z "$service" ] && service=$app;
# 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;
# Force `php` to its intended version
# We use `eval`+`export` since `alias` is not propagated to subshells, even with `export`
local php_version=$(ynh_app_setting_get --key=php_version)
local phpflags=$(ynh_app_setting_get --key=phpflags)
if [ -n "$php_version" ]
then
eval "php() { php${php_version} ${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
# 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
# Spawn the app shell
su -s /bin/bash $app
}

View file

@ -4,27 +4,21 @@ YNH_APT_INSTALL_DEPENDENCIES_REPLACE="true"
# Define and install dependencies with a equivs control file # Define and install dependencies with a equivs control file
# #
# [packagingv1] # example : ynh_apt_install_dependencies dep1 dep2 "dep3|dep4|dep5"
# #
# This helper can/should only be called once per app # usage: ynh_apt_install_dependencies dep [dep [...]]
#
# example : ynh_install_app_dependencies dep1 dep2 "dep3|dep4|dep5"
#
# usage: ynh_install_app_dependencies dep [dep [...]]
# | arg: dep - the package name to install in dependence. # | 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). # | arg: "dep1|dep2|…" - You can specify alternatives. It will require to install (dep1 or dep2, etc).
# #
# Requires YunoHost version 2.6.4 or higher.
ynh_apt_install_dependencies() { ynh_apt_install_dependencies() {
local dependencies=$@
# Add a comma for each space between packages. But not add a comma if the space separate a version specification. (See below) # Add a comma for each space between packages. But not add a comma if the space separate a version specification. (See below)
dependencies="$(echo "$dependencies" | sed 's/\([^\<=\>]\)\ \([^(]\)/\1, \2/g')" local dependencies="$(sed 's/\([^\<=\>]\)\ \([^(]\)/\1, \2/g' <<< "$@" | sed 's/|/ | /')"
local dependencies=${dependencies//|/ | }
local version=$(ynh_read_manifest "version") local version=$(ynh_read_manifest "version")
local app_ynh_deps="${app//_/-}-ynh-deps" # Replace all '_' by '-', and append -ynh-deps local app_ynh_deps="${app//_/-}-ynh-deps" # Replace all '_' by '-', and append -ynh-deps
# Handle specific versions # Handle specific versions
if [[ "$dependencies" =~ [\<=\>] ]]; then if grep '[<=>]' <<< "$dependencies"; then
# Replace version specifications by relationships syntax # Replace version specifications by relationships syntax
# https://www.debian.org/doc/debian-policy/ch-relationships.html # https://www.debian.org/doc/debian-policy/ch-relationships.html
# Sed clarification # Sed clarification
@ -33,7 +27,7 @@ ynh_apt_install_dependencies() {
# \+ matches one or more occurence of the previous characters, for >= or >>. # \+ matches one or more occurence of the previous characters, for >= or >>.
# [^,]\+ matches all characters except ',' # [^,]\+ matches all characters except ','
# Ex: 'package>=1.0' will be replaced by 'package (>= 1.0)' # Ex: 'package>=1.0' will be replaced by 'package (>= 1.0)'
dependencies="$(echo "$dependencies" | sed 's/\([^(\<=\>]\)\([\<=\>]\+\)\([^,]\+\)/\1 (\2 \3)/g')" dependencies="$(sed 's/\([^(\<=\>]\)\([\<=\>]\+\)\([^,]\+\)/\1 (\2 \3)/g' <<< "$dependencies")"
fi fi
# ############################## # # ############################## #
@ -43,10 +37,9 @@ ynh_apt_install_dependencies() {
# Check for specific php dependencies which requires sury # Check for specific php dependencies which requires sury
# This grep will for example return "7.4" if dependencies is "foo bar php7.4-pwet php-gni" # This grep will for example return "7.4" if dependencies is "foo bar php7.4-pwet php-gni"
# The (?<=php) syntax corresponds to lookbehind ;) # The (?<=php) syntax corresponds to lookbehind ;)
local specific_php_version=$(echo $dependencies | grep -oP '(?<=php)[0-9.]+(?=-|\>|)' | sort -u) local specific_php_version=$(grep -oP '(?<=php)[0-9.]+(?=-|\>|)' <<< "$dependencies" | sort -u)
if [[ -n "$specific_php_version" ]] if [[ -n "$specific_php_version" ]]; then
then
# Cover a small edge case where a packager could have specified "php7.4-pwet php5-gni" which is confusing # 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 ]] \ [[ $(echo $specific_php_version | wc -l) -eq 1 ]] \
|| ynh_die "Inconsistent php versions in dependencies ... found : $specific_php_version" || ynh_die "Inconsistent php versions in dependencies ... found : $specific_php_version"
@ -57,21 +50,16 @@ ynh_apt_install_dependencies() {
# If the PHP version changed, remove the old fpm conf # If the PHP version changed, remove the old fpm conf
if [ -n "$old_php_version" ] && [ "$old_php_version" != "$specific_php_version" ]; then if [ -n "$old_php_version" ] && [ "$old_php_version" != "$specific_php_version" ]; then
local old_php_fpm_config_dir=$(ynh_app_setting_get --key=fpm_config_dir) if [[ -f "/etc/php/$php_version/fpm/pool.d/$app.conf" ]]; then
local old_php_finalphpconf="$old_php_fpm_config_dir/pool.d/$app.conf" ynh_backup_if_checksum_is_different "/etc/php/$php_version/fpm/pool.d/$app.conf"
ynh_config_remove_phpfpm
if [[ -f "$old_php_finalphpconf" ]]
then
ynh_backup_if_checksum_is_different "$old_php_finalphpconf"
ynh_remove_fpm_config
fi fi
fi fi
# Store php_version into the config of this app # Store php_version into the config of this app
ynh_app_setting_set --key=php_version --value=$specific_php_version ynh_app_setting_set --key=php_version --value=$specific_php_version
# Set the default php version back as the default version for php-cli. # Set the default php version back as the default version for php-cli.
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
then
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
fi fi
elif grep --quiet 'php' <<< "$dependencies"; then elif grep --quiet 'php' <<< "$dependencies"; then
@ -81,79 +69,78 @@ ynh_apt_install_dependencies() {
# Specific tweak related to Postgresql (cf end of the helper) # 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)" 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 # 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 # expected effect) Otherwise, any subsequent call will add dependencies
# to those already present in the equivs control file. # to those already present in the equivs control file.
if [[ $YNH_APT_INSTALL_DEPENDENCIES_REPLACE == "true" ]] if [[ $YNH_APT_INSTALL_DEPENDENCIES_REPLACE == "true" ]]; then
then
YNH_APT_INSTALL_DEPENDENCIES_REPLACE="false" YNH_APT_INSTALL_DEPENDENCIES_REPLACE="false"
else else
local current_dependencies="" local current_dependencies=""
if _ynh_apt_package_is_installed "${app_ynh_deps}" if _ynh_apt_package_is_installed "${app_ynh_deps}"; then
then
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${app_ynh_deps}) " current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${app_ynh_deps}) "
current_dependencies=${current_dependencies// | /|} current_dependencies=${current_dependencies// | /|}
fi fi
dependencies="$current_dependencies, $dependencies" dependencies="$current_dependencies, $dependencies"
fi fi
# ############################# # ################
# Actual install using equivs # # Actual install #
# ############################# # ################
# Prepare the virtual-dependency control file for equivs # Prepare the virtual-dependency control file for dpkg-deb --build
local TMPDIR=$(mktemp --directory) local TMPDIR=$(mktemp --directory)
cat >${TMPDIR}/control <<EOF # Make a control file for equivs-build mkdir -p ${TMPDIR}/${app_ynh_deps}/DEBIAN
# 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
Section: misc Section: misc
Priority: optional Priority: optional
Package: ${app_ynh_deps} Package: ${app_ynh_deps}
Version: ${version} Version: ${version}
Depends: ${dependencies} Depends: ${dependencies//,,/,}
Architecture: all Architecture: all
Maintainer: root@localhost
Description: Fake package for ${app} (YunoHost app) dependencies Description: Fake package for ${app} (YunoHost app) dependencies
This meta-package is only responsible of installing its dependencies. This meta-package is only responsible of installing its dependencies.
EOF EOF
# Make sure to delete equivs' legacy compat file
# It's now handle somewhat magically through the control file
rm -f /usr/share/equivs/template/debian/compat
_ynh_apt update _ynh_apt update
_ynh_wait_dpkg_free _ynh_wait_dpkg_free
( # Install the fake package without its dependencies with dpkg --force-depends
# NB: this is in a subshell (though not sure why exactly not just use pushd/popd...) if ! LC_ALL=C dpkg-deb --build "${TMPDIR}/${app_ynh_deps}" "${TMPDIR}/${app_ynh_deps}.deb" > "${TMPDIR}/dpkg_log" 2>&1; then
cd "$TMPDIR" cat "${TMPDIR}/dpkg_log" >&2
# Install the fake package without its dependencies with dpkg --force-depends ynh_die --message="Unable to install dependencies"
LC_ALL=C equivs-build ./control 2>&1 fi
LC_ALL=C dpkg --force-depends --install "./${app_ynh_deps}_${version}_all.deb" 2>&1 | tee ./dpkg_log # Don't crash in case of error, because is nicely covered by the following line
) LC_ALL=C dpkg --force-depends --install "${TMPDIR}/${app_ynh_deps}.deb" 2>&1 | tee "${TMPDIR}/dpkg_log" || true
# Then install the missing dependencies with apt install # Then install the missing dependencies with apt install
_ynh_apt_install --fix-broken \ _ynh_apt_install --fix-broken || {
|| { # If the installation failed # If the installation failed
# (the following is ran inside { } to not start a subshell otherwise ynh_die wouldnt exit the original process) # (the following is ran inside { } to not start a subshell otherwise ynh_die wouldnt exit the original process)
# Parse the list of problematic dependencies from dpkg's log ... # Parse the list of problematic dependencies from dpkg's log ...
# (relevant lines look like: "foo-ynh-deps depends on bar; however:") # (relevant lines look like: "foo-ynh-deps depends on bar; however:")
local problematic_dependencies="$(cat $TMPDIR/dpkg_log | grep -oP '(?<=-ynh-deps depends on ).*(?=; however)' | tr '\n' ' ')" cat $TMPDIR/dpkg_log
# Fake an install of those dependencies to see the errors local problematic_dependencies="$(grep -oP '(?<=-ynh-deps depends on ).*(?=; however)' $TMPDIR/dpkg_log | tr '\n' ' ')"
# The sed command here is, Print only from 'Reading state info' to the end. # Fake an install of those dependencies to see the errors
[[ -n "$problematic_dependencies" ]] && _ynh_apt_install $problematic_dependencies --dry-run 2>&1 | sed --quiet '/Reading state info/,$p' | grep -v "fix-broken\|Reading state info" >&2 # The sed command here is, Print only from 'Reading state info' to the end.
ynh_die "Unable to install dependencies" [[ -n "$problematic_dependencies" ]] && _ynh_apt_install $problematic_dependencies --dry-run 2>&1 | sed --quiet '/Reading state info/,$p' | grep -v "fix-broken\|Reading state info" >&2
ynh_die "Unable to install apt dependencies"
} }
rm --recursive --force "$TMPDIR" # Remove the temp dir. rm --recursive --force "$TMPDIR" # Remove the temp dir.
# check if the package is actually installed # check if the package is actually installed
_ynh_apt_package_is_installed "${app_ynh_deps}" || ynh_die "Unable to install dependencies" _ynh_apt_package_is_installed "${app_ynh_deps}" || ynh_die "Unable to install apt dependencies"
# Specific tweak related to Postgresql # Specific tweak related to Postgresql
# -> trigger postgresql regenconf if we may have just installed 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)" local psql_installed2="$(_ynh_apt_package_is_installed "postgresql-$PSQL_VERSION" && echo yes || echo no)"
if [[ "$psql_installed" != "$psql_installed2" ]] if [[ "$psql_installed" != "$psql_installed2" ]]; then
then
yunohost tools regen-conf postgresql yunohost tools regen-conf postgresql
fi fi
@ -161,13 +148,9 @@ EOF
# Remove fake package and its dependencies # Remove fake package and its dependencies
# #
# [packagingv1]
#
# Dependencies will removed only if no other package need them. # Dependencies will removed only if no other package need them.
# #
# usage: ynh_apt_remove_dependencies # usage: ynh_apt_remove_dependencies
#
# Requires YunoHost version 2.6.4 or higher.
ynh_apt_remove_dependencies() { ynh_apt_remove_dependencies() {
local app_ynh_deps="${app//_/-}-ynh-deps" # Replace all '_' by '-', and append -ynh-deps local app_ynh_deps="${app//_/-}-ynh-deps" # Replace all '_' by '-', and append -ynh-deps
@ -179,30 +162,25 @@ ynh_apt_remove_dependencies() {
# Edge case where the app dep may be on hold, # Edge case where the app dep may be on hold,
# cf https://forum.yunohost.org/t/migration-error-cause-of-ffsync/20675/4 # cf https://forum.yunohost.org/t/migration-error-cause-of-ffsync/20675/4
if apt-mark showhold | grep -q -w ${app_ynh_deps} if apt-mark showhold | grep -q -w ${app_ynh_deps}; then
then
apt-mark unhold ${app_ynh_deps} apt-mark unhold ${app_ynh_deps}
fi fi
# Remove the fake package and its dependencies if they not still used. # Remove the fake package and its dependencies if they not still used.
# (except if dpkg doesn't know anything about the package, # (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) # 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 if dpkg-query --show ${app_ynh_deps} &> /dev/null; then
then
_ynh_apt autoremove --purge ${app_ynh_deps} _ynh_apt autoremove --purge ${app_ynh_deps}
fi fi
} }
# Install packages from an extra repository properly. # Install packages from an extra repository properly.
# #
# [packagingv1]
#
# usage: ynh_apt_install_dependencies_from_extra_repository --repo="repo" --package="dep1 dep2" --key=key_url # usage: ynh_apt_install_dependencies_from_extra_repository --repo="repo" --package="dep1 dep2" --key=key_url
# | arg: -r, --repo= - Complete url of the extra repository. # | arg: --repo= - Complete url of the extra repository.
# | arg: -p, --package= - The packages to install from this extra repository # | arg: --package= - The packages to install from this extra repository
# | arg: -k, --key= - url to get the public key. # | arg: --key= - url to get the public key.
# #
# Requires YunoHost version 3.8.1 or higher.
ynh_apt_install_dependencies_from_extra_repository() { ynh_apt_install_dependencies_from_extra_repository() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([r]=repo= [p]=package= [k]=key=) local -A args_array=([r]=repo= [p]=package= [k]=key=)
@ -213,14 +191,32 @@ ynh_apt_install_dependencies_from_extra_repository() {
# =========================================== # ===========================================
# Split the repository into uri, suite and components. # Split the repository into uri, suite and components.
repo="${repo#deb }" IFS=', ' read -r -a repo_parts <<< "$repo"
local uri="$(echo "$repo" | awk '{ print $1 }')" index=0
local suite="$(echo "$repo" | awk '{ print $2 }')"
local component="${repo##$uri $suite }" # Remove "deb " at the beginning of the repo.
if [[ "${repo_parts[0]}" == "deb" ]]; then
index=1
fi
uri="${repo_parts[$index]}"
index=$((index + 1))
suite="${repo_parts[$index]}"
index=$((index + 1))
# Get the components
if (("${#repo_parts[@]}" > 0)); then
component="${repo_parts[*]:$index}"
fi
if [[ "$key" == "trusted=yes" ]]; then
trust="[trusted=yes]"
else
trust=""
fi
# Add the new repo in sources.list.d # Add the new repo in sources.list.d
mkdir --parents "/etc/apt/sources.list.d" mkdir --parents "/etc/apt/sources.list.d"
echo "deb $uri $suite $component" > "/etc/apt/sources.list.d/$app.list" echo "deb $trust $uri $suite $component" > "/etc/apt/sources.list.d/$app.list"
# Pin the new repo with the default priority, so it won't be used for upgrades. # Pin the new repo with the default priority, so it won't be used for upgrades.
# Build $pin from the uri without http and any sub path # Build $pin from the uri without http and any sub path
@ -235,9 +231,11 @@ Pin: origin $pin
Pin-Priority: 995 Pin-Priority: 995
EOF EOF
mkdir --parents "/etc/apt/trusted.gpg.d" if [ -n "$key" ] && [[ "$key" != "trusted=yes" ]]; then
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget) mkdir --parents "/etc/apt/trusted.gpg.d"
wget --timeout 900 --quiet "$key" --output-document=- | gpg --dearmor | tee /etc/apt/trusted.gpg.d/$name.gpg >/dev/null # Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
wget --timeout 900 --quiet "$key" --output-document=- | gpg --dearmor > /etc/apt/trusted.gpg.d/$app.gpg
fi
# Update the list of package with the new repo NB: we use -o # Update the list of package with the new repo NB: we use -o
# Dir::Etc::sourcelist to only refresh this repo, because # Dir::Etc::sourcelist to only refresh this repo, because
@ -262,13 +260,12 @@ EOF
ynh_safe_rm "/etc/apt/sources.list.d/$app.list" ynh_safe_rm "/etc/apt/sources.list.d/$app.list"
ynh_safe_rm "/etc/apt/preferences.d/$app" ynh_safe_rm "/etc/apt/preferences.d/$app"
ynh_safe_rm "/etc/apt/trusted.gpg.d/$app.gpg" ynh_safe_rm "/etc/apt/trusted.gpg.d/$app.gpg"
ynh_apt_update _ynh_apt update
} }
# #####################
#######################
# Internal misc utils # # Internal misc utils #
####################### # #####################
# Check if apt is free to use, or wait, until timeout. # Check if apt is free to use, or wait, until timeout.
_ynh_wait_dpkg_free() { _ynh_wait_dpkg_free() {
@ -277,7 +274,7 @@ _ynh_wait_dpkg_free() {
# With seq 1 17, timeout will be almost 30 minutes # With seq 1 17, timeout will be almost 30 minutes
for try in $(seq 1 17); do for try in $(seq 1 17); do
# Check if /var/lib/dpkg/lock is used by another process # 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..." echo "apt is already in use..."
# Sleep an exponential time at each round # Sleep an exponential time at each round
sleep $((try * try)) sleep $((try * try))
@ -295,7 +292,7 @@ _ynh_wait_dpkg_free() {
set -o xtrace # set -x set -o xtrace # set -x
return 1 return 1
fi fi
done 9<<<"$(ls -1 $dpkg_dir)" done 9<<< "$(ls -1 $dpkg_dir)"
set -o xtrace # set -x set -o xtrace # set -x
return 0 return 0
fi fi
@ -307,14 +304,14 @@ _ynh_wait_dpkg_free() {
# Check either a package is installed or not # Check either a package is installed or not
_ynh_apt_package_is_installed() { _ynh_apt_package_is_installed() {
local package=$1 local package=$1
dpkg-query --show --showformat='${db:Status-Status}' "$package" 2>/dev/null \ dpkg-query --show --showformat='${db:Status-Status}' "$package" 2> /dev/null \
| grep --quiet "^installed$" &>/dev/null | grep --quiet "^installed$" &> /dev/null
} }
# Return the installed version of an apt package, if installed # Return the installed version of an apt package, if installed
_ynh_apt_package_version() { _ynh_apt_package_version() {
if _ynh_apt_package_is_installed "$package"; then 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 else
echo '' echo ''
fi fi

View file

@ -27,13 +27,11 @@ ynh_backup() {
local is_data=false local is_data=false
# If the path starts with /var/log/$app or $data_dir # If the path starts with /var/log/$app or $data_dir
if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]) if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]); then
then
is_data=true is_data=true
fi fi
if [[ -n "${app:-}" ]] if [[ -n "${app:-}" ]]; then
then
local do_not_backup_data=$(ynh_app_setting_get --key=do_not_backup_data) local do_not_backup_data=$(ynh_app_setting_get --key=do_not_backup_data)
fi fi
@ -83,7 +81,7 @@ ynh_backup() {
# ============================================================================== # ==============================================================================
local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g') local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g')
local dest=$(echo "${dest_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}"
# ============================================================================== # ==============================================================================
@ -128,8 +126,6 @@ with open(sys.argv[1], 'r') as backup_file:
# `/etc/nginx/conf.d/$domain.d/$app.conf` # `/etc/nginx/conf.d/$domain.d/$app.conf`
# otheriwse, search for a match in the csv (eg: conf/nginx.conf) and restore it into # otheriwse, search for a match in the csv (eg: conf/nginx.conf) and restore it into
# `/etc/nginx/conf.d/$domain.d/$app.conf` # `/etc/nginx/conf.d/$domain.d/$app.conf`
#
# Requires YunoHost version 2.6.4 or higher.
ynh_restore() { ynh_restore() {
target="$1" target="$1"
@ -137,15 +133,13 @@ ynh_restore() {
# If the path starts with /var/log/$app or $data_dir # If the path starts with /var/log/$app or $data_dir
local is_data=false local is_data=false
if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]) if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]); then
then
is_data=true is_data=true
fi fi
# If archive_path doesn't exist, search for a corresponding path in CSV # If archive_path doesn't exist, search for a corresponding path in CSV
if [ ! -d "$archive_path" ] && [ ! -f "$archive_path" ] && [ ! -L "$archive_path" ]; then if [ ! -d "$archive_path" ] && [ ! -f "$archive_path" ] && [ ! -L "$archive_path" ]; then
if [[ "$is_data" == true ]] if [[ "$is_data" == true ]]; then
then
ynh_print_info "Skipping $target which doesn't exists in the archive, probably because restoring from a safety-backup-before-upgrade" 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 # Assume it's not a big deal, we may be restoring a safety-backup-before-upgrade which doesnt contain those
return 0 return 0
@ -181,13 +175,13 @@ ynh_restore() {
else else
mv "$archive_path" "${target}" mv "$archive_path" "${target}"
fi fi
_ynh_apply_default_permissions "$target"
} }
# Restore all files that were previously backuped in an app backup script # Restore all files that were previously backuped in an app backup script
# #
# usage: ynh_restore_everything # usage: ynh_restore_everything
#
# Requires YunoHost version 2.6.4 or higher.
ynh_restore_everything() { ynh_restore_everything() {
# Deduce the relative path of $YNH_CWD # Deduce the relative path of $YNH_CWD
local REL_DIR="${YNH_CWD#$YNH_BACKUP_DIR/}" local REL_DIR="${YNH_CWD#$YNH_BACKUP_DIR/}"
@ -196,7 +190,7 @@ ynh_restore_everything() {
# For each destination path begining by $REL_DIR # For each destination path begining by $REL_DIR
cat ${YNH_BACKUP_CSV} | tr --delete $'\r' | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR.*\"$" \ cat ${YNH_BACKUP_CSV} | tr --delete $'\r' | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR.*\"$" \
| while read line; do | 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" ynh_restore "$ARCHIVE_PATH"
done done
} }
@ -211,6 +205,7 @@ _ynh_file_checksum_exists() {
# #
# usage: ynh_store_file_checksum /path/to/file # usage: ynh_store_file_checksum /path/to/file
ynh_store_file_checksum() { ynh_store_file_checksum() {
set +o xtrace # set +x
local file=$1 local file=$1
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_' local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
@ -231,6 +226,7 @@ ynh_store_file_checksum() {
fi fi
# Unset the variable, so it wouldn't trig a ynh_store_file_checksum without a ynh_backup_if_checksum_is_different before it. # Unset the variable, so it wouldn't trig a ynh_store_file_checksum without a ynh_backup_if_checksum_is_different before it.
unset backup_file_checksum unset backup_file_checksum
set -o xtrace # set -x
} }
# Verify the checksum and backup the file if it's different # Verify the checksum and backup the file if it's different
@ -240,6 +236,7 @@ ynh_store_file_checksum() {
# This helper is primarily meant to allow to easily backup personalised/manually # This helper is primarily meant to allow to easily backup personalised/manually
# modified config files. # modified config files.
ynh_backup_if_checksum_is_different() { ynh_backup_if_checksum_is_different() {
set +o xtrace # set +x
local file=$1 local file=$1
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_' local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
local checksum_value=$(ynh_app_setting_get --key=$checksum_setting_name) local checksum_value=$(ynh_app_setting_get --key=$checksum_setting_name)
@ -255,14 +252,14 @@ ynh_backup_if_checksum_is_different() {
echo "$backup_file_checksum" # Return the name of the backup file echo "$backup_file_checksum" # Return the name of the backup file
if ynh_in_ci_tests; then if ynh_in_ci_tests; then
local file_path_base64=$(echo "$file" | base64 -w0) local file_path_base64=$(echo "$file" | base64 -w0)
if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64} if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64}; then
then
ynh_print_warn "Diff with the original file:" 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 diff --report-identical-files --unified --color=always /var/cache/yunohost/appconfbackup/original_${file_path_base64} $file >&2 || true
fi fi
fi fi
fi fi
fi fi
set -o xtrace # set -x
} }
# Delete a file checksum from the app settings # Delete a file checksum from the app settings

View file

@ -0,0 +1,45 @@
#!/bin/bash
# Install and initialize Composer in the given directory
#
# The installed version is defined by `$composer_version` which should be defined
# as global prior to calling this helper.
#
# Will use `$install_dir` as workdir unless `$composer_workdir` exists (but that shouldnt be necessary)
#
# usage: ynh_composer_install
ynh_composer_install() {
local workdir="${composer_workdir:-$install_dir}"
[[ -n "${composer_version}" ]] || ynh_die "\$composer_version should be defined before calling ynh_composer_install. (In the past, this was called \$YNH_COMPOSER_VERSION)"
[[ ! -e "$workdir/composer.phar" ]] || ynh_safe_rm $workdir/composer.phar
local composer_url="https://getcomposer.org/download/$composer_version/composer.phar"
# NB. we have to declare the var as local first,
# otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
# because local always return 0 ...
local out
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$workdir/composer.phar $composer_url 2>&1) \
|| ynh_die "$out"
}
# Execute a command with Composer
#
# Will use `$install_dir` as workdir unless `$composer_workdir` exists (but that shouldnt be necessary)
#
# You may also define `composer_user=root` prior to call this helper if you
# absolutely need composer to run as root, but this is discouraged...
#
# usage: ynh_composer_exec commands
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" $@ \
-d "$workdir" --no-interaction --no-ansi 2>&1
}

View file

@ -6,11 +6,11 @@ _ynh_app_config_get_one() {
local bind="$3" local bind="$3"
local getter="get__${short_setting}" local getter="get__${short_setting}"
# Get value from getter if exists # 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)" old[$short_setting]="$($getter)"
formats[${short_setting}]="yaml" 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)" old[$short_setting]="$("get__${bind%%(*}" $short_setting $type $bind)"
formats[${short_setting}]="yaml" formats[${short_setting}]="yaml"
@ -22,7 +22,7 @@ _ynh_app_config_get_one() {
if [[ "$bind" == "settings" ]]; then if [[ "$bind" == "settings" ]]; then
ynh_die "File '${short_setting}' can't be stored in settings" ynh_die "File '${short_setting}' can't be stored in settings"
fi 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" file_hash[$short_setting]="true"
# Get multiline text from settings or from a full file # Get multiline text from settings or from a full file
@ -32,7 +32,7 @@ _ynh_app_config_get_one() {
elif [[ "$bind" == *":"* ]]; then 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" 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 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 fi
# Get value from a kind of key/value file # 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_after="$(echo "${bind_key_}" | cut -d'>' -f1)"
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)" bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
fi 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}")" old[$short_setting]="$(ynh_read_var_in_file --file="${bind_file}" --key="${bind_key_}" --after="${bind_after}")"
fi fi
@ -59,10 +59,10 @@ _ynh_app_config_apply_one() {
local type="${types[$short_setting]}" local type="${types[$short_setting]}"
if [ "${changed[$short_setting]}" == "true" ]; then if [ "${changed[$short_setting]}" == "true" ]; then
# Apply setter if exists # 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 $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 "set__${bind%%(*}" $short_setting $type $bind
elif [[ "$bind" == "null" ]]; then elif [[ "$bind" == "null" ]]; then
@ -73,7 +73,7 @@ _ynh_app_config_apply_one() {
if [[ "$bind" == "settings" ]]; then if [[ "$bind" == "settings" ]]; then
ynh_die "File '${short_setting}' can't be stored in settings" ynh_die "File '${short_setting}' can't be stored in settings"
fi fi
local bind_file="$(echo "$bind" | sed s@__INSTALL_DIR__@${install_dir:-}@ | sed s/__APP__/$app/)" local bind_file="$bind"
if [[ "${!short_setting}" == "" ]]; then if [[ "${!short_setting}" == "" ]]; then
ynh_backup_if_checksum_is_different "$bind_file" ynh_backup_if_checksum_is_different "$bind_file"
ynh_safe_rm "$bind_file" ynh_safe_rm "$bind_file"
@ -84,8 +84,7 @@ _ynh_app_config_apply_one() {
if [[ "${!short_setting}" != "$bind_file" ]]; then if [[ "${!short_setting}" != "$bind_file" ]]; then
cp "${!short_setting}" "$bind_file" cp "${!short_setting}" "$bind_file"
fi fi
if _ynh_file_checksum_exists "$bind_file" if _ynh_file_checksum_exists "$bind_file"; then
then
ynh_store_file_checksum "$bind_file" ynh_store_file_checksum "$bind_file"
fi fi
ynh_print_info "File '$bind_file' overwritten with ${!short_setting}" ynh_print_info "File '$bind_file' overwritten with ${!short_setting}"
@ -101,11 +100,10 @@ _ynh_app_config_apply_one() {
if [[ "$bind" == *":"* ]]; then 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" 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 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" ynh_backup_if_checksum_is_different "$bind_file"
echo "${!short_setting}" >"$bind_file" echo "${!short_setting}" > "$bind_file"
if _ynh_file_checksum_exists "$bind_file" if _ynh_file_checksum_exists "$bind_file"; then
then
ynh_store_file_checksum "$bind_file" ynh_store_file_checksum "$bind_file"
fi fi
ynh_print_info "File '$bind_file' overwritten with the content provided in question '${short_setting}'" 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)" bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
fi fi
bind_key_=${bind_key_:-$short_setting} 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_backup_if_checksum_is_different "$bind_file"
ynh_write_var_in_file --file="${bind_file}" --key="${bind_key_}" --value="${!short_setting}" --after="${bind_after}" ynh_write_var_in_file --file="${bind_file}" --key="${bind_key_}" --value="${!short_setting}" --after="${bind_after}"
if _ynh_file_checksum_exists "$bind_file" if _ynh_file_checksum_exists "$bind_file"; then
then
ynh_store_file_checksum "$bind_file" ynh_store_file_checksum "$bind_file"
fi fi
@ -135,69 +132,17 @@ _ynh_app_config_apply_one() {
fi fi
fi fi
} }
_ynh_app_config_get() { _ynh_app_config_get() {
# From settings for line in $YNH_APP_CONFIG_PANEL_OPTIONS_TYPES_AND_BINDS; do
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
# Split line into short_setting, type and bind # 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" binds[${short_setting}]="$bind"
types[${short_setting}]="$type" types[${short_setting}]="$type"
file_hash[${short_setting}]="" file_hash[${short_setting}]=""
formats[${short_setting}]="" formats[${short_setting}]=""
ynh_app_config_get_one $short_setting $type $bind ynh_app_config_get_one $short_setting $type $bind
done done
} }
_ynh_app_config_apply() { _ynh_app_config_apply() {
@ -267,9 +212,9 @@ _ynh_app_config_validate() {
for short_setting in "${!old[@]}"; do for short_setting in "${!old[@]}"; do
[[ "${changed[$short_setting]}" == "false" ]] && continue [[ "${changed[$short_setting]}" == "false" ]] && continue
local result="" 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)" 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 "validate__${bind%%(*}" $short_setting
fi fi
if [ -n "$result" ]; then if [ -n "$result" ]; then
@ -324,7 +269,7 @@ ynh_app_config_apply() {
ynh_app_action_run() { ynh_app_action_run() {
local runner="run__$1" local runner="run__$1"
# Get value from getter if exists # 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 $runner
#ynh_return "result:" #ynh_return "result:"
#ynh_return "$(echo "${result}" | sed 's/^/ /g')" #ynh_return "$(echo "${result}" | sed 's/^/ /g')"
@ -342,22 +287,23 @@ ynh_app_config_run() {
declare -Ag formats=() declare -Ag formats=()
case $1 in case $1 in
show) show)
ynh_app_config_get ynh_app_config_get
ynh_app_config_show ynh_app_config_show
;; ;;
apply) apply)
max_progression=4 max_progression=4
ynh_script_progression "Reading config panel description and current configuration..." ynh_script_progression "Reading config panel description and current configuration..."
ynh_app_config_get ynh_app_config_get
ynh_app_config_validate ynh_app_config_validate
ynh_script_progression "Applying the new configuration..." ynh_script_progression "Applying the new configuration..."
ynh_app_config_apply ynh_app_config_apply
ynh_script_progression "Configuration of $app completed" ynh_script_progression "Configuration of $app completed"
;; ;;
*) *)
ynh_app_action_run $1 ynh_app_action_run $1
;;
esac esac
} }

View file

@ -2,18 +2,16 @@
# Create a dedicated fail2ban config (jail and filter conf files) # Create a dedicated fail2ban config (jail and filter conf files)
# #
# usage 1: ynh_config_add_fail2ban --logpath=log_file --failregex=filter # usage: ynh_config_add_fail2ban --logpath=log_file --failregex=filter
# | arg: -l, --logpath= - Log file to be checked by fail2ban # | arg: --logpath= - Log file to be checked by fail2ban
# | arg: -r, --failregex= - Failregex to be looked for by fail2ban # | arg: --failregex= - Failregex to be looked for by fail2ban
# #
# usage 2: ynh_config_add_fail2ban # If --logpath / --failregex are provided, the helper will generate the appropriate conf using these.
# | arg: -t, --use_template - Use this helper in template mode
# #
# This will use a template in `../conf/f2b_jail.conf` and `../conf/f2b_filter.conf` # Otherwise, it will assume that the app provided templates, namely
# See the documentation of `ynh_config_add` for a description of the template # `../conf/f2b_jail.conf` and `../conf/f2b_filter.conf`
# format and how placeholders are replaced with actual variables.
# #
# Generally your template will look like that by example (for synapse): # They will typically look like (for example here for synapse):
# ``` # ```
# f2b_jail.conf: # f2b_jail.conf:
# [__APP__] # [__APP__]
@ -38,9 +36,7 @@
# ignoreregex = # ignoreregex =
# ``` # ```
# #
# ----------------------------------------------------------------------------- # ##### Regarding the the `failregex` option:
#
# Note about the "failregex" option:
# #
# regex to match the password failure messages in the logfile. The host must be # 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 # matched by a group named "`host`". The tag "`<HOST>`" can be used for standard
@ -53,8 +49,6 @@
# ``` # ```
# fail2ban-regex /var/log/YOUR_LOG_FILE_PATH /etc/fail2ban/filter.d/YOUR_APP.conf # fail2ban-regex /var/log/YOUR_LOG_FILE_PATH /etc/fail2ban/filter.d/YOUR_APP.conf
# ``` # ```
#
# Requires YunoHost version 4.1.0 or higher.
ynh_config_add_fail2ban() { ynh_config_add_fail2ban() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([l]=logpath= [r]=failregex=) local -A args_array=([l]=logpath= [r]=failregex=)
@ -74,7 +68,7 @@ port = http,https
filter = __APP__ filter = __APP__
logpath = __LOGPATH__ logpath = __LOGPATH__
maxretry = 5 maxretry = 5
" >"$YNH_APP_BASEDIR/conf/f2b_jail.conf" " > "$YNH_APP_BASEDIR/conf/f2b_jail.conf"
echo " echo "
[INCLUDES] [INCLUDES]
@ -82,7 +76,7 @@ before = common.conf
[Definition] [Definition]
failregex = __FAILREGEX__ failregex = __FAILREGEX__
ignoreregex = ignoreregex =
" >"$YNH_APP_BASEDIR/conf/f2b_filter.conf" " > "$YNH_APP_BASEDIR/conf/f2b_filter.conf"
fi fi
ynh_config_add --template="f2b_jail.conf" --destination="/etc/fail2ban/jail.d/$app.conf" ynh_config_add --template="f2b_jail.conf" --destination="/etc/fail2ban/jail.d/$app.conf"
@ -117,8 +111,6 @@ ignoreregex =
# Remove the dedicated fail2ban config (jail and filter conf files) # Remove the dedicated fail2ban config (jail and filter conf files)
# #
# usage: ynh_config_remove_fail2ban # usage: ynh_config_remove_fail2ban
#
# Requires YunoHost version 3.5.0 or higher.
ynh_config_remove_fail2ban() { ynh_config_remove_fail2ban() {
ynh_safe_rm "/etc/fail2ban/jail.d/$app.conf" ynh_safe_rm "/etc/fail2ban/jail.d/$app.conf"
ynh_safe_rm "/etc/fail2ban/filter.d/$app.conf" ynh_safe_rm "/etc/fail2ban/filter.d/$app.conf"

View file

@ -20,7 +20,7 @@
# | arg: $@ - Simply "$@" to tranfert all the positionnal arguments to the function # | 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 # 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: # Be carreful, this array has to be an associative array, as the following example:
# local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 ) # local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
# Let's explain this array: # Let's explain this array:
@ -40,17 +40,18 @@
# If there's many values for an option, -f /final /path, the value will be separated by a ';' $finalpath=/final;/path # If there's many values for an option, -f /final /path, the value will be separated by a ';' $finalpath=/final;/path
# For an option without value, like --user in the example, the helper can be called only with --user or -u. $user will then get the value 1. # For an option without value, like --user in the example, the helper can be called only with --user or -u. $user will then get the value 1.
# #
# To keep a retrocompatibility, a package can still call a helper, using getopts, with positional arguments.
# The "legacy mode" will manage the positional arguments and fill the variable in the same order than they are given in $args_array.
# e.g. for `my_helper "val1" val2`, arg1 will be filled with val1, and arg2 with val2.
#
# Requires YunoHost version 3.2.2 or higher.
ynh_handle_getopts_args() { ynh_handle_getopts_args() {
# Trick to only re-enable debugging if it was set before
local xtrace_enable=$(set +o | grep xtrace)
# Manage arguments only if there's some provided # Manage arguments only if there's some provided
set +o xtrace # set +x set +o xtrace # set +x
if [ $# -eq 0 ]; then if [ $# -eq 0 ]; then
set -o xtrace # set -x eval "$xtrace_enable"
return return
# Validate that the first char is - because it should be something like --option=value or -o ...
elif [[ "${1:0:1}" != "-" ]]; then
ynh_die "It looks like you called the helper using positional arguments instead of keyword arguments ?"
fi fi
# Store arguments in an array to keep each argument separated # Store arguments in an array to keep each argument separated
@ -100,9 +101,9 @@ ynh_handle_getopts_args() {
getopts ":$getopts_parameters" parameter || true getopts ":$getopts_parameters" parameter || true
if [ "$parameter" = "?" ]; then if [ "$parameter" = "?" ]; then
ynh_die "Invalid argument: -${OPTARG:-}" ynh_die "Invalid argument: ${1:-}"
elif [ "$parameter" = ":" ]; then elif [ "$parameter" = ":" ]; then
ynh_die "-$OPTARG parameter requires an argument." ynh_die "${1:-} parameter requires an argument."
else else
local shift_value=1 local shift_value=1
# Use the long option, corresponding to the short option read by getopts, as a variable # Use the long option, corresponding to the short option read by getopts, as a variable
@ -180,6 +181,6 @@ ynh_handle_getopts_args() {
# Call parse_arg and pass the modified list of args as an array of arguments. # Call parse_arg and pass the modified list of args as an array of arguments.
parse_arg "${arguments[@]}" parse_arg "${arguments[@]}"
set -o xtrace # set -x eval "$xtrace_enable"
} }

View file

@ -1,26 +1,17 @@
#!/bin/bash #!/bin/bash
ynh_go_try_bash_extension() { readonly GOENV_INSTALL_DIR="/opt/goenv"
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
}
goenv_install_dir="/opt/goenv"
go_version_path="$goenv_install_dir/versions"
# goenv_ROOT is the directory of goenv, it needs to be loaded as a environment variable. # goenv_ROOT is the directory of goenv, it needs to be loaded as a environment variable.
export GOENV_ROOT="$goenv_install_dir" export GOENV_ROOT="$GOENV_INSTALL_DIR"
_ynh_load_go_in_path_and_other_tweaks() { _ynh_load_go_in_path_and_other_tweaks() {
# Get the absolute path of this version of go # Get the absolute path of this version of go
local go_path="$go_version_path/$app/bin" go_dir="$GOENV_INSTALL_DIR/versions/$app/bin"
# Load the path of this version of go in $PATH # Load the path of this version of go in $PATH
if [[ :$PATH: != *":$go_path"* ]]; then if [[ :$PATH: != *":$go_dir"* ]]; then
PATH="$go_path:$PATH" PATH="$go_dir:$PATH"
fi fi
# Export PATH such that it's available through sudo -E / ynh_exec_as $app # Export PATH such that it's available through sudo -E / ynh_exec_as $app
@ -32,31 +23,28 @@ _ynh_load_go_in_path_and_other_tweaks() {
# Sets the local application-specific go version # Sets the local application-specific go version
pushd ${install_dir} pushd ${install_dir}
$goenv_install_dir/bin/goenv local $go_version $GOENV_INSTALL_DIR/bin/goenv local $go_version
popd popd
} }
# Install a specific version of Go using goenv # Install a specific version of Go using goenv
# #
# The installed version is defined by $nodejs_version which should be defined as global prior to calling this helper # The installed version is defined by `$go_version` which should be defined as global prior to calling this helper
#
# This helper creates a /etc/profile.d/goenv.sh that configures PATH environment for goenv
# for every LOGIN user, hence your user must have a defined shell (as opposed to /usr/sbin/nologin)
#
# Don't forget to execute go-dependent command in a login environment
# (e.g. sudo --login option)
# When not possible (e.g. in systemd service definition), please use direct path
# to goenv shims (e.g. $goenv_ROOT/shims/bundle)
# #
# usage: ynh_go_install # usage: ynh_go_install
# #
# Requires YunoHost version 3.2.2 or higher. # The helper adds the appropriate, specific version of go to the `$PATH` variable (which
ynh_go_install () { # is preserved when calling `ynh_exec_as_app`). Also defines:
# - `$path_with_go` (the value of the modified `$PATH`, but you dont really need it?)
# - `$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() {
[[ -n "${go_version:-}" ]] || ynh_die "\$go_version should be defined prior to calling ynh_go_install" [[ -n "${go_version:-}" ]] || ynh_die "\$go_version should be defined prior to calling ynh_go_install"
# Load goenv path in PATH # Load goenv path in PATH
local CLEAR_PATH="$goenv_install_dir/bin:$PATH" local CLEAR_PATH="$GOENV_INSTALL_DIR/bin:$PATH"
# Remove /usr/local/bin in PATH in case of Go prior installation # Remove /usr/local/bin in PATH in case of Go prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@') PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
@ -65,42 +53,42 @@ ynh_go_install () {
test -x /usr/bin/go && mv /usr/bin/go /usr/bin/go_goenv test -x /usr/bin/go && mv /usr/bin/go /usr/bin/go_goenv
# Install or update goenv # Install or update goenv
mkdir -p $goenv_install_dir mkdir -p $GOENV_INSTALL_DIR
pushd "$goenv_install_dir" pushd "$GOENV_INSTALL_DIR"
if ! [ -x "$goenv_install_dir/bin/goenv" ]; then if ! [ -x "$GOENV_INSTALL_DIR/bin/goenv" ]; then
ynh_print_info "Downloading goenv..." ynh_print_info "Downloading goenv..."
git init -q git init -q
git remote add origin https://github.com/syndbg/goenv.git git remote add origin https://github.com/syndbg/goenv.git
else else
ynh_print_info "Updating goenv..." ynh_print_info "Updating goenv..."
fi fi
git fetch -q --tags --prune origin git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)") local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag" git checkout -q "$git_latest_tag"
ynh_go_try_bash_extension _ynh_go_try_bash_extension
goenv=$goenv_install_dir/bin/goenv goenv=$GOENV_INSTALL_DIR/bin/goenv
popd popd
# Install or update xxenv-latest # Install or update xxenv-latest
mkdir -p "$goenv_install_dir/plugins/xxenv-latest" mkdir -p "$GOENV_INSTALL_DIR/plugins/xxenv-latest"
pushd "$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 if ! [ -x "$GOENV_INSTALL_DIR/plugins/xxenv-latest/bin/goenv-latest" ]; then
ynh_print_info "Downloading xxenv-latest..." ynh_print_info "Downloading xxenv-latest..."
git init -q git init -q
git remote add origin https://github.com/momo-lab/xxenv-latest.git git remote add origin https://github.com/momo-lab/xxenv-latest.git
else else
ynh_print_info "Updating xxenv-latest..." ynh_print_info "Updating xxenv-latest..."
fi fi
git fetch -q --tags --prune origin git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)") local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag" git checkout -q "$git_latest_tag"
popd popd
# Enable caching # Enable caching
mkdir -p "${goenv_install_dir}/cache" mkdir -p "${GOENV_INSTALL_DIR}/cache"
# Create shims directory if needed # Create shims directory if needed
mkdir -p "${goenv_install_dir}/shims" mkdir -p "${GOENV_INSTALL_DIR}/shims"
# Restore /usr/local/bin in PATH # Restore /usr/local/bin in PATH
PATH=$CLEAR_PATH PATH=$CLEAR_PATH
@ -109,7 +97,7 @@ ynh_go_install () {
test -x /usr/bin/go_goenv && mv /usr/bin/go_goenv /usr/bin/go test -x /usr/bin/go_goenv && mv /usr/bin/go_goenv /usr/bin/go
# Install the requested version of Go # Install the requested version of Go
local final_go_version=$(goenv latest --print "$go_version") local final_go_version=$("$GOENV_INSTALL_DIR/plugins/xxenv-latest/bin/goenv-latest" --print "$go_version")
ynh_print_info "Installation of Go-$final_go_version" ynh_print_info "Installation of Go-$final_go_version"
goenv install --quiet --skip-existing "$final_go_version" 2>&1 goenv install --quiet --skip-existing "$final_go_version" 2>&1
@ -121,9 +109,9 @@ ynh_go_install () {
_ynh_go_cleanup _ynh_go_cleanup
# Set environment for Go users # Set environment for Go users
echo "#goenv echo "#goenv
export GOENV_ROOT=$goenv_install_dir export GOENV_ROOT=$GOENV_INSTALL_DIR
export PATH=\"$goenv_install_dir/bin:$PATH\" export PATH=\"$GOENV_INSTALL_DIR/bin:$PATH\"
eval \"\$(goenv init -)\" eval \"\$(goenv init -)\"
#goenv" > /etc/profile.d/goenv.sh #goenv" > /etc/profile.d/goenv.sh
@ -138,11 +126,11 @@ eval \"\$(goenv init -)\"
# This helper will also cleanup Go versions # This helper will also cleanup Go versions
# #
# usage: ynh_go_remove # usage: ynh_go_remove
ynh_go_remove () { ynh_go_remove() {
local go_version=$(ynh_app_setting_get --key="go_version") local go_version=$(ynh_app_setting_get --key="go_version")
# Load goenv path in PATH # Load goenv path in PATH
local CLEAR_PATH="$goenv_install_dir/bin:$PATH" local CLEAR_PATH="$GOENV_INSTALL_DIR/bin:$PATH"
# Remove /usr/local/bin in PATH in case of Go prior installation # Remove /usr/local/bin in PATH in case of Go prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@') PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
@ -156,42 +144,47 @@ ynh_go_remove () {
# Remove no more needed versions of Go used by the app. # Remove no more needed versions of Go used by the app.
# #
# [internal]
#
# This helper will check what Go version are no more required, # This helper will check what Go version are no more required,
# and uninstall them # and uninstall them
# If no app uses Go, goenv will be also removed. # If no app uses Go, goenv will be also removed.
# #
# usage: _ynh_go_cleanup # usage: _ynh_go_cleanup
_ynh_go_cleanup () { _ynh_go_cleanup() {
# List required Go versions # List required Go versions
local installed_apps=$(yunohost app list --output-as json --quiet | jq -r .apps[].id) local installed_apps=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
local required_go_versions="" local required_go_versions=""
for installed_app in $installed_apps for installed_app in $installed_apps; do
do
local installed_app_go_version=$(ynh_app_setting_get --app=$installed_app --key="go_version") local installed_app_go_version=$(ynh_app_setting_get --app=$installed_app --key="go_version")
if [[ $installed_app_go_version ]] if [[ $installed_app_go_version ]]; then
then
required_go_versions="${installed_app_go_version}\n${required_go_versions}" required_go_versions="${installed_app_go_version}\n${required_go_versions}"
fi fi
done done
# Remove no more needed Go versions # Remove no more needed Go versions
local installed_go_versions=$(goenv versions --bare --skip-aliases | grep -Ev '/') local installed_go_versions=$(goenv versions --bare --skip-aliases | grep -Ev '/')
for installed_go_version in $installed_go_versions for installed_go_version in $installed_go_versions; do
do if ! $(echo ${required_go_versions} | grep "${installed_go_version}" 1> /dev/null 2>&1); then
if ! `echo ${required_go_versions} | grep "${installed_go_version}" 1>/dev/null 2>&1`
then
ynh_print_info "Removing of Go-$installed_go_version" ynh_print_info "Removing of Go-$installed_go_version"
$goenv_install_dir/bin/goenv uninstall --force "$installed_go_version" $GOENV_INSTALL_DIR/bin/goenv uninstall --force "$installed_go_version"
fi fi
done done
# If none Go version is required # If none Go version is required
if [[ ! $required_go_versions ]] if [[ ! $required_go_versions ]]; then
then
# Remove goenv environment configuration # Remove goenv environment configuration
ynh_print_info "Removing of goenv" ynh_print_info "Removing of goenv"
ynh_safe_rm "$goenv_install_dir" ynh_safe_rm "$GOENV_INSTALL_DIR"
ynh_safe_rm "/etc/profile.d/goenv.sh" ynh_safe_rm "/etc/profile.d/goenv.sh"
fi fi
} }
_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
}

View file

@ -4,7 +4,13 @@
# #
# usage: ynh_die "Some message" # usage: ynh_die "Some message"
ynh_die() { ynh_die() {
echo "$1" 1>&2 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"
fi
echo "${1:-}" 1>&2
fi
exit 1 exit 1
} }
@ -38,14 +44,12 @@ ynh_hide_warnings() {
# | arg: command - command to execute # | arg: command - command to execute
# #
# Note that you should NOT quote the command but only prefix it with ynh_exec_and_print_stderr_only_if_error # Note that you should NOT quote the command but only prefix it with ynh_exec_and_print_stderr_only_if_error
#
# Requires YunoHost version 11.2 or higher.
ynh_exec_and_print_stderr_only_if_error() { ynh_exec_and_print_stderr_only_if_error() {
logfile="$(mktemp)" logfile="$(mktemp)"
rc=0 rc=0
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077 # Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
"$@" 2> "$logfile" || rc="$?" "$@" 2> "$logfile" || rc="$?"
if (( rc != 0 )); then if ((rc != 0)); then
cat "$logfile" >&2 cat "$logfile" >&2
ynh_safe_rm "$logfile" ynh_safe_rm "$logfile"
return "$rc" return "$rc"
@ -56,10 +60,8 @@ ynh_exec_and_print_stderr_only_if_error() {
# (to be used by special hooks like app config panel and core diagnosis) # (to be used by special hooks like app config panel and core diagnosis)
# #
# usage: ynh_return somedata # usage: ynh_return somedata
#
# Requires YunoHost version 3.6.0 or higher.
ynh_return() { ynh_return() {
echo "$1" >>"$YNH_STDRETURN" echo "$1" >> "$YNH_STDRETURN"
} }
# Initial definitions for ynh_script_progression # Initial definitions for ynh_script_progression
@ -76,8 +78,6 @@ progress_string0="...................."
# Print a progress bar showing the progression of an app script # Print a progress bar showing the progression of an app script
# #
# usage: ynh_script_progression "Some message" # usage: ynh_script_progression "Some message"
#
# Requires YunoHost version 3.5.0 or higher.
ynh_script_progression() { ynh_script_progression() {
set +o xtrace # set +x set +o xtrace # set +x
@ -103,10 +103,9 @@ ynh_script_progression() {
local expected_progression="$((($increment_progression + 1) * $progress_scale / $max_progression - $effective_progression))" local expected_progression="$((($increment_progression + 1) * $progress_scale / $max_progression - $effective_progression))"
# Hack for the "--last" message # Hack for the "--last" message
if grep -qw 'completed' <<< "$1"; if grep -qw 'completed' <<< "$1"; then
then effective_progression=$progress_scale
effective_progression=$progress_scale expected_progression=0
expected_progression=0
fi fi
# left_progression is the progression not yet done # left_progression is the progression not yet done
local left_progression="$(($progress_scale - $effective_progression - $expected_progression))" local left_progression="$(($progress_scale - $effective_progression - $expected_progression))"

View file

@ -10,11 +10,9 @@ FIRST_CALL_TO_LOGROTATE="true"
# #
# The configuration is autogenerated by YunoHost # The configuration is autogenerated by YunoHost
# (ie it doesnt come from a specific app template like nginx or systemd conf) # (ie it doesnt come from a specific app template like nginx or systemd conf)
#
# Requires YunoHost version 2.6.4 or higher.
ynh_config_add_logrotate() { ynh_config_add_logrotate() {
logfile="$1" local logfile="${1:-}"
set -o noglob set -o noglob
if [[ -z "$logfile" ]]; then if [[ -z "$logfile" ]]; then
@ -24,15 +22,16 @@ ynh_config_add_logrotate() {
fi fi
set +o noglob set +o noglob
for stuff in $logfile for stuff in $logfile; do
do
mkdir --parents $(dirname "$stuff")
# Make sure the permissions of the parent dir are correct (otherwise the config file could be ignored and the corresponding logs never rotated) # Make sure the permissions of the parent dir are correct (otherwise the config file could be ignored and the corresponding logs never rotated)
chmod 750 $(dirname "$stuff") local dir=$(dirname "$stuff")
mkdir --parents $dir
chmod 750 $dir
chown $app:$app $dir
done done
local tempconf="$(mktemp)" local tempconf="$(mktemp)"
cat << EOF >$tempconf cat << EOF > $tempconf
$logfile { $logfile {
# Rotate if the logfile exceeds 100Mo # Rotate if the logfile exceeds 100Mo
size 100M size 100M
@ -53,8 +52,7 @@ $logfile {
} }
EOF EOF
if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]] if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]]; then
then
cat $tempconf > /etc/logrotate.d/$app cat $tempconf > /etc/logrotate.d/$app
else else
cat $tempconf >> /etc/logrotate.d/$app cat $tempconf >> /etc/logrotate.d/$app
@ -67,9 +65,7 @@ EOF
# Remove the app's logrotate config. # Remove the app's logrotate config.
# #
# usage: ynh_remove_logrotate # usage:ynh_config_remove_logrotate
#
# Requires YunoHost version 2.6.4 or higher.
ynh_config_remove_logrotate() { ynh_config_remove_logrotate() {
if [ -e "/etc/logrotate.d/$app" ]; then if [ -e "/etc/logrotate.d/$app" ]; then
rm "/etc/logrotate.d/$app" rm "/etc/logrotate.d/$app"

View file

@ -6,22 +6,21 @@
# example: ynh_mongo_exec --command="db.getMongo().getDBNames().indexOf(\"wekan\")" # example: ynh_mongo_exec --command="db.getMongo().getDBNames().indexOf(\"wekan\")"
# #
# usage: ynh_mongo_exec [--database=database] --command="command" # usage: ynh_mongo_exec [--database=database] --command="command"
# | arg: -d, --database= - The database to connect to # | arg: --database= - The database to connect to
# | arg: -c, --command= - The command to evaluate # | arg: --command= - The command to evaluate
# #
# #
ynh_mongo_exec() { ynh_mongo_exec() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=( [d]=database= [c]=command= ) local -A args_array=([d]=database= [c]=command=)
local database local database
local command local command
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
database="${database:-}" database="${database:-}"
# =========================================== # ===========================================
if [ -n "$database" ] if [ -n "$database" ]; then
then mongosh --quiet << EOF
mongosh --quiet <<EOF
use $database use $database
${command} ${command}
quit() quit()
@ -39,12 +38,12 @@ EOF
# consider using ynh_mongo_remove_db instead. # consider using ynh_mongo_remove_db instead.
# #
# usage: ynh_mongo_drop_db --database=database # usage: ynh_mongo_drop_db --database=database
# | arg: -d, --database= - The database name to drop # | arg: --database= - The database name to drop
# #
# #
ynh_mongo_drop_db() { ynh_mongo_drop_db() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=( [d]=database= ) local -A args_array=([d]=database=)
local database local database
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
# =========================================== # ===========================================
@ -57,13 +56,13 @@ ynh_mongo_drop_db() {
# example: ynh_mongo_dump_db --database=wekan > ./dump.bson # example: ynh_mongo_dump_db --database=wekan > ./dump.bson
# #
# usage: ynh_mongo_dump_db --database=database # usage: ynh_mongo_dump_db --database=database
# | arg: -d, --database= - The database name to dump # | arg: --database= - The database name to dump
# | ret: the mongodump output # | ret: the mongodump output
# #
# #
ynh_mongo_dump_db() { ynh_mongo_dump_db() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=( [d]=database= ) local -A args_array=([d]=database=)
local database local database
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
# =========================================== # ===========================================
@ -76,14 +75,14 @@ ynh_mongo_dump_db() {
# [internal] # [internal]
# #
# usage: ynh_mongo_create_user --db_user=user --db_pwd=pwd --db_name=name # usage: ynh_mongo_create_user --db_user=user --db_pwd=pwd --db_name=name
# | arg: -u, --db_user= - The user name to create # | arg: --db_user= - The user name to create
# | arg: -p, --db_pwd= - The password to identify user by # | arg: --db_pwd= - The password to identify user by
# | arg: -n, --db_name= - Name of the database to grant privilegies # | arg: --db_name= - Name of the database to grant privilegies
# #
# #
ynh_mongo_create_user() { ynh_mongo_create_user() {
# ============ Argument parsing ============= # ============ 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_user
local db_name local db_name
local db_pwd local db_pwd
@ -100,7 +99,7 @@ ynh_mongo_create_user() {
# Check if a mongo database exists # Check if a mongo database exists
# #
# usage: ynh_mongo_database_exists --database=database # usage: ynh_mongo_database_exists --database=database
# | arg: -d, --database= - The database for which to check existence # | arg: --database= - The database for which to check existence
# | exit: Return 1 if the database doesn't exist, 0 otherwise # | exit: Return 1 if the database doesn't exist, 0 otherwise
# #
# #
@ -111,8 +110,7 @@ ynh_mongo_database_exists() {
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
# =========================================== # ===========================================
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")') -lt 0 ] if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")') -lt 0 ]; then
then
return 1 return 1
else else
return 0 return 0
@ -124,12 +122,12 @@ ynh_mongo_database_exists() {
# example: ynh_mongo_restore_db --database=wekan < ./dump.bson # example: ynh_mongo_restore_db --database=wekan < ./dump.bson
# #
# usage: ynh_mongo_restore_db --database=database # usage: ynh_mongo_restore_db --database=database
# | arg: -d, --database= - The database name to restore # | arg: --database= - The database name to restore
# #
# #
ynh_mongo_restore_db() { ynh_mongo_restore_db() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=( [d]=database= ) local -A args_array=([d]=database=)
local database local database
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
# =========================================== # ===========================================
@ -142,13 +140,13 @@ ynh_mongo_restore_db() {
# [internal] # [internal]
# #
# usage: ynh_mongo_drop_user --db_user=user --db_name=name # usage: ynh_mongo_drop_user --db_user=user --db_name=name
# | arg: -u, --db_user= - The user to drop # | arg: --db_user= - The user to drop
# | arg: -n, --db_name= - Name of the database # | arg: --db_name= - Name of the database
# #
# #
ynh_mongo_drop_user() { ynh_mongo_drop_user() {
# ============ Argument parsing ============= # ============ 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_user
local db_name local db_name
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
@ -160,9 +158,9 @@ ynh_mongo_drop_user() {
# Create a database, an user and its password. Then store the password in the app's config # 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] # usage: ynh_mongo_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
# | arg: -u, --db_user= - Owner of the database # | arg: --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database # | arg: --db_name= - Name of the database
# | arg: -p, --db_pwd= - Password of the database. If not provided, a password will be generated # | arg: --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 # 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. # It will also be stored as "mongopwd" into the app settings.
@ -170,7 +168,7 @@ ynh_mongo_drop_user() {
# #
ynh_mongo_setup_db() { ynh_mongo_setup_db() {
# ============ Argument parsing ============= # ============ 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_user
local db_name local db_name
db_pwd="" db_pwd=""
@ -191,20 +189,20 @@ ynh_mongo_setup_db() {
# Remove a database if it exists, and the associated user # Remove a database if it exists, and the associated user
# #
# usage: ynh_mongo_remove_db --db_user=user --db_name=name # usage: ynh_mongo_remove_db --db_user=user --db_name=name
# | arg: -u, --db_user= - Owner of the database # | arg: --db_user= - Owner of the database
# | arg: -n, --db_name= - Name of the database # | arg: --db_name= - Name of the database
# #
# #
ynh_mongo_remove_db() { ynh_mongo_remove_db() {
# ============ Argument parsing ============= # ============ 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_user
local db_name local db_name
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
# =========================================== # ===========================================
if ynh_mongo_database_exists --database=$db_name; then # Check if the database exists if ynh_mongo_database_exists --database=$db_name; then # Check if the database exists
ynh_mongo_drop_db --database=$db_name # Remove the database ynh_mongo_drop_db --database=$db_name # Remove the database
else else
ynh_print_warn "Database $db_name not found" ynh_print_warn "Database $db_name not found"
fi fi
@ -226,7 +224,7 @@ ynh_install_mongo() {
ynh_print_info "Installing MongoDB Community Edition ..." ynh_print_info "Installing MongoDB Community Edition ..."
local mongo_debian_release=$YNH_DEBIAN_VERSION local mongo_debian_release=$YNH_DEBIAN_VERSION
if [[ $(cat /proc/cpuinfo) != *"avx"* && "$mongo_version" != "4.4" ]]; then if [[ "$(grep '^flags' /proc/cpuinfo | uniq)" != *"avx"* && "$mongo_version" != "4.4" ]]; then
ynh_print_warn "Installing Mongo 4.4 as $mongo_version is not compatible with your cpu (see https://docs.mongodb.com/manual/administration/production-notes/#x86_64)." ynh_print_warn "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" mongo_version="4.4"
fi fi
@ -235,7 +233,10 @@ ynh_install_mongo() {
mongo_debian_release=buster mongo_debian_release=buster
fi 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" ynh_apt_install_dependencies_from_extra_repository \
--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 mongodb_servicename=mongod
# Make sure MongoDB is started and enabled # Make sure MongoDB is started and enabled
@ -259,8 +260,7 @@ ynh_install_mongo() {
# #
ynh_remove_mongo() { ynh_remove_mongo() {
# Only remove the mongodb service if it is not installed. # Only remove the mongodb service if it is not installed.
if ! _ynh_apt_package_is_installed "mongodb*" if ! _ynh_apt_package_is_installed "mongodb*"; then
then
ynh_print_info "Removing MongoDB service..." ynh_print_info "Removing MongoDB service..."
mongodb_servicename=mongod mongodb_servicename=mongod
# Remove the mongodb service # Remove the mongodb service

View file

@ -6,8 +6,6 @@ readonly MEDIA_DIRECTORY=/home/yunohost.multimedia
# Initialize the multimedia directory system # Initialize the multimedia directory system
# #
# usage: ynh_multimedia_build_main_dir # usage: ynh_multimedia_build_main_dir
#
# Requires YunoHost version 4.2 or higher.
ynh_multimedia_build_main_dir() { ynh_multimedia_build_main_dir() {
## Création du groupe multimedia ## Création du groupe multimedia
@ -55,12 +53,10 @@ ynh_multimedia_build_main_dir() {
# #
# usage: ynh_multimedia_addfolder --source_dir="source_dir" --dest_dir="dest_dir" # usage: ynh_multimedia_addfolder --source_dir="source_dir" --dest_dir="dest_dir"
# #
# | arg: -s, --source_dir= - Source directory - The real directory which contains your medias. # | arg: --source_dir= - Source directory - The real directory which contains your medias.
# | arg: -d, --dest_dir= - Destination directory - The name and the place of the symbolic link, relative to "/home/yunohost.multimedia" # | arg: --dest_dir= - Destination directory - The name and the place of the symbolic link, relative to "/home/yunohost.multimedia"
# #
# This "directory" will be a symbolic link to a existing directory. # This "directory" will be a symbolic link to a existing directory.
#
# Requires YunoHost version 4.2 or higher.
ynh_multimedia_addfolder() { ynh_multimedia_addfolder() {
# ============ Argument parsing ============= # ============ Argument parsing =============
@ -82,21 +78,12 @@ ynh_multimedia_addfolder() {
setfacl -RL -m m::rwx "$source_dir" setfacl -RL -m m::rwx "$source_dir"
} }
# Allow an user to have an write authorisation in multimedia directories # Add an user to the multimedia group, in turn having write permission in multimedia directories
# #
# usage: ynh_multimedia_addaccess user_name # usage: ynh_multimedia_addaccess user_name
# #
# | arg: -u, --user_name= - The name of the user which gain this access. # | arg: user_name - The name of the user which gain this access.
#
# Requires YunoHost version 4.2 or higher.
ynh_multimedia_addaccess() { ynh_multimedia_addaccess() {
groupadd -f $MEDIA_GROUP
# ============ Argument parsing ============= usermod -a -G $MEDIA_GROUP $1
local -A args_array=([u]=user_name=)
local user_name
ynh_handle_getopts_args "$@"
# ===========================================
groupadd -f multimedia
usermod -a -G multimedia $user_name
} }

View file

@ -16,7 +16,7 @@ ynh_mysql_db_shell() {
# Create a database and grant optionnaly privilegies to a user # Create a database and grant optionnaly privilegies to a user
# #
# [internal] # [internal] ... handled by the core / "database resource"
# #
# usage: ynh_mysql_create_db db [user [pwd]] # usage: ynh_mysql_create_db db [user [pwd]]
# | arg: db - the database name to create # | arg: db - the database name to create
@ -42,7 +42,7 @@ ynh_mysql_create_db() {
# Drop a database # Drop a database
# #
# [internal] # [internal] ... handled by the core / "database resource"
# #
# If you intend to drop the database *and* the associated user, # If you intend to drop the database *and* the associated user,
# consider using ynh_mysql_remove_db instead. # consider using ynh_mysql_remove_db instead.
@ -57,7 +57,7 @@ ynh_mysql_drop_db() {
# Dump a database # Dump a database
# #
# usage: ynh_mysql_dump_db database # usage: ynh_mysql_dump_db database
# | arg: -d, --database= - the database name to dump (by default, $db_name) # | arg: database - the database name to dump (by default, $db_name)
# | ret: The mysqldump output # | ret: The mysqldump output
# #
# example: ynh_mysql_dump_db "roundcube" > ./dump.sql # example: ynh_mysql_dump_db "roundcube" > ./dump.sql
@ -69,7 +69,7 @@ ynh_mysql_dump_db() {
# Create a user # Create a user
# #
# [internal] # [internal] ... handled by the core / "database resource"
# #
# usage: ynh_mysql_create_user user pwd [host] # usage: ynh_mysql_create_user user pwd [host]
# | arg: user - the user name to create # | arg: user - the user name to create
@ -84,7 +84,7 @@ ynh_mysql_create_user() {
# [internal] # [internal]
# #
# usage: ynh_mysql_user_exists user # usage: ynh_mysql_user_exists user
# | arg: user= - the user for which to check existence # | arg: user - the user for which to check existence
# | ret: 0 if the user exists, 1 otherwise. # | ret: 0 if the user exists, 1 otherwise.
ynh_mysql_user_exists() { ynh_mysql_user_exists() {
local user=$1 local user=$1
@ -93,6 +93,8 @@ ynh_mysql_user_exists() {
# Check if a mysql database exists # Check if a mysql database exists
# #
# [internal]
#
# usage: ynh_mysql_database_exists database # usage: ynh_mysql_database_exists database
# | arg: database - the database for which to check existence # | arg: database - the database for which to check existence
# | exit: Return 1 if the database doesn't exist, 0 otherwise # | exit: Return 1 if the database doesn't exist, 0 otherwise
@ -104,7 +106,7 @@ ynh_mysql_database_exists() {
# Drop a user # Drop a user
# #
# [internal] # [internal] ... handled by the core / "database resource"
# #
# usage: ynh_mysql_drop_user user # usage: ynh_mysql_drop_user user
# | arg: user - the user name to drop # | arg: user - the user name to drop

View file

@ -14,8 +14,6 @@
# #
# This allows to enable/disable specific behaviors dependenging on the install # This allows to enable/disable specific behaviors dependenging on the install
# location # location
#
# Requires YunoHost version 4.1.0 or higher.
ynh_config_add_nginx() { ynh_config_add_nginx() {
local finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf" local finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf"
@ -36,24 +34,19 @@ ynh_config_add_nginx() {
# Remove the dedicated nginx config # Remove the dedicated nginx config
# #
# usage: ynh_config_remove_nginx # usage: ynh_config_remove_nginx
#
# Requires YunoHost version 2.7.2 or higher.
ynh_config_remove_nginx() { ynh_config_remove_nginx() {
ynh_safe_rm "/etc/nginx/conf.d/$domain.d/$app.conf" ynh_safe_rm "/etc/nginx/conf.d/$domain.d/$app.conf"
ynh_systemctl --service=nginx --action=reload ynh_systemctl --service=nginx --action=reload
} }
# Regen the nginx config in a change url context # Regen the nginx config in a change url context
# #
# usage: ynh_config_change_url_nginx # usage: ynh_config_change_url_nginx
#
# Requires YunoHost version 11.1.9 or higher.
ynh_config_change_url_nginx() { ynh_config_change_url_nginx() {
# Make a backup of the original NGINX config file if manually modified # Make a backup of the original NGINX config file if manually modified
# (nb: this is possibly different from the same instruction called by # (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...) # changed if we're changing the domain too...)
local old_nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf local old_nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf
ynh_backup_if_checksum_is_different "$old_nginx_conf_path" ynh_backup_if_checksum_is_different "$old_nginx_conf_path"

View file

@ -1,18 +1,18 @@
#!/bin/bash #!/bin/bash
n_install_dir="/opt/node_n" readonly N_INSTALL_DIR="/opt/node_n"
node_version_path="$n_install_dir/n/versions/node"
# N_PREFIX is the directory of n, it needs to be loaded as a environment variable. # N_PREFIX is the directory of n, it needs to be loaded as a environment variable.
export N_PREFIX="$n_install_dir" export N_PREFIX="$N_INSTALL_DIR"
# [internal]
_ynh_load_nodejs_in_path_and_other_tweaks() { _ynh_load_nodejs_in_path_and_other_tweaks() {
# Get the absolute path of this version of node # Get the absolute path of this version of node
local nodejs_path="$node_version_path/$nodejs_version/bin" nodejs_dir="$N_INSTALL_DIR/n/versions/node/$nodejs_version/bin"
# Load the path of this version of node in $PATH # Load the path of this version of node in $PATH
if [[ :$PATH: != *":$nodejs_path"* ]]; then if [[ :$PATH: != *":$nodejs_dir"* ]]; then
PATH="$nodejs_path:$PATH" PATH="$nodejs_dir:$PATH"
fi fi
# Export PATH such that it's available through sudo -E / ynh_exec_as $app # Export PATH such that it's available through sudo -E / ynh_exec_as $app
@ -28,29 +28,27 @@ _ynh_load_nodejs_in_path_and_other_tweaks() {
# Install a specific version of nodejs, using 'n' # Install a specific version of nodejs, using 'n'
# #
# The installed version is defined by $nodejs_version which should be defined as global prior to calling this helper # The installed version is defined by `$nodejs_version` which should be defined as global prior to calling this helper
# #
# usage: ynh_nodejs_install # usage: ynh_nodejs_install
# #
# `n` (Node version management) uses the `PATH` variable to store the path of the version of node it is going to use. # `n` (Node version management) uses the `PATH` variable to store the path of the version of node it is going to use.
# That's how it changes the version # That's how it changes the version
# #
# Adds the appropriate, specific version of nodejs to the PATH variable (which # The helper adds the appropriate, specific version of nodejs to the `$PATH` variable (which
# is also exported, to ease the use of ynh_exec_as_app). Also define variable # is preserved when calling ynh_exec_as_app). Also defines:
# PATH_with_nodejs to be used in the systemd config # - `$path_with_nodejs` to be used in the systemd config (`Environment="PATH=__PATH_WITH_NODEJS__"`)
# (Environment="PATH=__PATH_WITH_NODEJS__") # - `$nodejs_dir`, the directory containing the specific version of nodejs, which may be used in the systemd config too (e.g. `ExecStart=__NODEJS_DIR__/node foo bar`)
#
# Requires YunoHost version 2.7.12 or higher.
ynh_nodejs_install() { ynh_nodejs_install() {
# Use n, https://github.com/tj/n to manage the nodejs versions # Use n, https://github.com/tj/n to manage the nodejs versions
[[ -n "${nodejs_version:-}" ]] || ynh_die "\$nodejs_version should be defined prior to calling ynh_nodejs_install" [[ -n "${nodejs_version:-}" ]] || ynh_die "\$nodejs_version should be defined prior to calling ynh_nodejs_install"
# Create $n_install_dir # Create $N_INSTALL_DIR
mkdir --parents "$n_install_dir" mkdir --parents "$N_INSTALL_DIR"
# Load n path in PATH # Load n path in PATH
CLEAR_PATH="$n_install_dir/bin:$PATH" CLEAR_PATH="$N_INSTALL_DIR/bin:$PATH"
# Remove /usr/local/bin in PATH in case of node prior installation # Remove /usr/local/bin in PATH in case of node prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@') PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
@ -59,10 +57,10 @@ ynh_nodejs_install() {
test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n
# Install (or update if YunoHost vendor/ folder updated since last install) n # Install (or update if YunoHost vendor/ folder updated since last install) n
mkdir -p $n_install_dir/bin/ mkdir -p $N_INSTALL_DIR/bin/
cp "$YNH_HELPERS_DIR/vendor/n/n" $n_install_dir/bin/n cp "$YNH_HELPERS_DIR/vendor/n/n" $N_INSTALL_DIR/bin/n
# Tweak for n to understand it's installed in $N_PREFIX # Tweak for n to understand it's installed in $N_PREFIX
ynh_replace --match="^N_PREFIX=\${N_PREFIX-.*}$" --replace="N_PREFIX=\${N_PREFIX-$N_PREFIX}" --file="$n_install_dir/bin/n" ynh_replace --match="^N_PREFIX=\${N_PREFIX-.*}$" --replace="N_PREFIX=\${N_PREFIX-$N_PREFIX}" --file="$N_INSTALL_DIR/bin/n"
# Restore /usr/local/bin in PATH # Restore /usr/local/bin in PATH
PATH=$CLEAR_PATH PATH=$CLEAR_PATH
@ -80,16 +78,18 @@ ynh_nodejs_install() {
fi fi
# Find the last "real" version for this major version of node. # Find the last "real" version for this major version of node.
real_nodejs_version=$(find $node_version_path/$nodejs_version* -maxdepth 0 | sort --version-sort | tail --lines=1) real_nodejs_version=$(find $N_INSTALL_DIR/n/versions/node/$nodejs_version* -maxdepth 0 | sort --version-sort | tail --lines=1)
real_nodejs_version=$(basename $real_nodejs_version) real_nodejs_version=$(basename $real_nodejs_version)
# Create a symbolic link for this major version if the file doesn't already exist # Create a symbolic link for this major version if the file doesn't already exist
if [ ! -e "$node_version_path/$nodejs_version" ]; then if [ ! -e "$N_INSTALL_DIR/n/versions/node/$nodejs_version" ]; then
ln --symbolic --force --no-target-directory $node_version_path/$real_nodejs_version $node_version_path/$nodejs_version ln --symbolic --force --no-target-directory \
$N_INSTALL_DIR/n/versions/node/$real_nodejs_version \
$N_INSTALL_DIR/n/versions/node/$nodejs_version
fi fi
# Store the ID of this app and the version of node requested for it # Store the ID of this app and the version of node requested for it
echo "$YNH_APP_INSTANCE_NAME:$nodejs_version" | tee --append "$n_install_dir/ynh_app_version" echo "$YNH_APP_INSTANCE_NAME:$nodejs_version" | tee --append "$N_INSTALL_DIR/ynh_app_version"
# Store nodejs_version into the config of this app # Store nodejs_version into the config of this app
ynh_app_setting_set --key=nodejs_version --value=$nodejs_version ynh_app_setting_set --key=nodejs_version --value=$nodejs_version
@ -104,24 +104,21 @@ ynh_nodejs_install() {
# This helper will check if another app uses the same version of node. # This helper will check if another app uses the same version of node.
# - If not, this version of node will be removed. # - If not, this version of node will be removed.
# - If no other app uses node, n will be also removed. # - If no other app uses node, n will be also removed.
#
# Requires YunoHost version 2.7.12 or higher.
ynh_nodejs_remove() { ynh_nodejs_remove() {
[[ -n "${nodejs_version:-}" ]] || ynh_die "\$nodejs_version should be defined prior to calling ynh_nodejs_remove" [[ -n "${nodejs_version:-}" ]] || ynh_die "\$nodejs_version should be defined prior to calling ynh_nodejs_remove"
# Remove the line for this app # Remove the line for this app
sed --in-place "/$YNH_APP_INSTANCE_NAME:$nodejs_version/d" "$n_install_dir/ynh_app_version" sed --in-place "/$YNH_APP_INSTANCE_NAME:$nodejs_version/d" "$N_INSTALL_DIR/ynh_app_version"
# If no other app uses this version of nodejs, remove it. # If no other app uses this version of nodejs, remove it.
if ! grep --quiet "$nodejs_version" "$n_install_dir/ynh_app_version"; then if ! grep --quiet "$nodejs_version" "$N_INSTALL_DIR/ynh_app_version"; then
$n_install_dir/bin/n rm $nodejs_version $N_INSTALL_DIR/bin/n rm $nodejs_version
fi fi
# If no other app uses n, remove n # If no other app uses n, remove n
if [ ! -s "$n_install_dir/ynh_app_version" ]; then if [ ! -s "$N_INSTALL_DIR/ynh_app_version" ]; then
ynh_safe_rm "$n_install_dir" ynh_safe_rm "$N_INSTALL_DIR"
ynh_safe_rm "/usr/local/n"
sed --in-place "/N_PREFIX/d" /root/.bashrc sed --in-place "/N_PREFIX/d" /root/.bashrc
fi fi
} }

View file

@ -27,14 +27,14 @@
# usage: ynh_permission_create --permission="permission" [--url="url"] [--additional_urls="second-url" [ "third-url" ]] [--auth_header=true|false] # usage: ynh_permission_create --permission="permission" [--url="url"] [--additional_urls="second-url" [ "third-url" ]] [--auth_header=true|false]
# [--allowed=group1 [ group2 ]] [--label="label"] [--show_tile=true|false] # [--allowed=group1 [ group2 ]] [--label="label"] [--show_tile=true|false]
# [--protected=true|false] # [--protected=true|false]
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" already exist) # | arg: --permission= - the name for the permission (by default a permission named "main" already exist)
# | arg: -u, --url= - (optional) URL for which access will be allowed/forbidden. Note that if 'show_tile' is enabled, this URL will be the URL of the tile. # | arg: --url= - (optional) URL for which access will be allowed/forbidden. Note that if 'show_tile' is enabled, this URL will be the URL of the tile.
# | arg: -A, --additional_urls= - (optional) List of additional URL for which access will be allowed/forbidden # | arg: --additional_urls= - (optional) List of additional URL for which access will be allowed/forbidden
# | arg: -h, --auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application. Default is true # | arg: --auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application. Default is true
# | arg: -a, --allowed= - (optional) A list of group/user to allow for the permission # | arg: --allowed= - (optional) A list of group/user to allow for the permission
# | arg: -l, --label= - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin. Default is "APP_LABEL (permission name)". # | arg: --label= - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin. Default is "APP_LABEL (permission name)".
# | arg: -t, --show_tile= - (optional) Define if a tile will be shown in the SSO. If yes the name of the tile will be the 'label' parameter. Defaults to false for the permission different than 'main'. # | arg: --show_tile= - (optional) Define if a tile will be shown in the SSO. If yes the name of the tile will be the 'label' parameter. Defaults to false for the permission different than 'main'.
# | arg: -P, --protected= - (optional) Define if this permission is protected. If it is protected the administrator won't be able to add or remove the visitors group of this permission. Defaults to 'false'. # | arg: --protected= - (optional) Define if this permission is protected. If it is protected the administrator won't be able to add or remove the visitors group of this permission. Defaults to 'false'.
# #
# [packagingv1] # [packagingv1]
# #
@ -62,9 +62,6 @@
# #
# Generally this feature is usefull to authenticate automatically the user in the application but in some case the application don't work with theses header and theses header need to be disabled to have the application to work correctly. # Generally this feature is usefull to authenticate automatically the user in the application but in some case the application don't work with theses header and theses header need to be disabled to have the application to work correctly.
# See https://github.com/YunoHost/issues/issues/1420 for more informations # See https://github.com/YunoHost/issues/issues/1420 for more informations
#
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_create() { ynh_permission_create() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([p]=permission= [u]=url= [A]=additional_urls= [h]=auth_header= [a]=allowed= [l]=label= [t]=show_tile= [P]=protected=) local -A args_array=([p]=permission= [u]=url= [A]=additional_urls= [h]=auth_header= [a]=allowed= [l]=label= [t]=show_tile= [P]=protected=)
@ -145,14 +142,10 @@ ynh_permission_create() {
# Remove a permission for the app (note that when the app is removed all permission is automatically removed) # Remove a permission for the app (note that when the app is removed all permission is automatically removed)
# #
# [packagingv1]
#
# example: ynh_permission_delete --permission=editors # example: ynh_permission_delete --permission=editors
# #
# usage: ynh_permission_delete --permission="permission" # usage: ynh_permission_delete --permission="permission"
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed) # | arg: --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_delete() { ynh_permission_delete() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([p]=permission=) local -A args_array=([p]=permission=)
@ -165,13 +158,9 @@ ynh_permission_delete() {
# Check if a permission exists # Check if a permission exists
# #
# [packagingv1]
#
# usage: ynh_permission_exists --permission=permission # usage: ynh_permission_exists --permission=permission
# | arg: -p, --permission= - the permission to check # | arg: --permission= - the permission to check
# | exit: Return 1 if the permission doesn't exist, 0 otherwise # | exit: Return 1 if the permission doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_exists() { ynh_permission_exists() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([p]=permission=) local -A args_array=([p]=permission=)
@ -180,23 +169,19 @@ ynh_permission_exists() {
# =========================================== # ===========================================
yunohost user permission list "$app" --output-as json --quiet \ 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 # Redefine the url associated to a permission
# #
# [packagingv1]
#
# usage: ynh_permission_url --permission "permission" [--url="url"] [--add_url="new-url" [ "other-new-url" ]] [--remove_url="old-url" [ "other-old-url" ]] # usage: ynh_permission_url --permission "permission" [--url="url"] [--add_url="new-url" [ "other-new-url" ]] [--remove_url="old-url" [ "other-old-url" ]]
# [--auth_header=true|false] [--clear_urls] # [--auth_header=true|false] [--clear_urls]
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed) # | arg: --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
# | arg: -u, --url= - (optional) URL for which access will be allowed/forbidden. Note that if you want to remove url you can pass an empty sting as arguments (""). # | arg: --url= - (optional) URL for which access will be allowed/forbidden. Note that if you want to remove url you can pass an empty sting as arguments ("").
# | arg: -a, --add_url= - (optional) List of additional url to add for which access will be allowed/forbidden. # | arg: --add_url= - (optional) List of additional url to add for which access will be allowed/forbidden.
# | arg: -r, --remove_url= - (optional) List of additional url to remove for which access will be allowed/forbidden # | arg: --remove_url= - (optional) List of additional url to remove for which access will be allowed/forbidden
# | arg: -h, --auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application # | arg: --auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application
# | arg: -c, --clear_urls - (optional) Clean all urls (url and additional_urls) # | arg: --clear_urls - (optional) Clean all urls (url and additional_urls)
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_url() { ynh_permission_url() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([p]=permission= [u]=url= [a]=add_url= [r]=remove_url= [h]=auth_header= [c]=clear_urls) local -A args_array=([p]=permission= [u]=url= [a]=add_url= [r]=remove_url= [h]=auth_header= [c]=clear_urls)
@ -255,15 +240,11 @@ ynh_permission_url() {
# Update a permission for the app # Update a permission for the app
# #
# [packagingv1]
#
# usage: ynh_permission_update --permission "permission" [--add="group" ["group" ...]] [--remove="group" ["group" ...]] # usage: ynh_permission_update --permission "permission" [--add="group" ["group" ...]] [--remove="group" ["group" ...]]
# #
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" already exist) # | arg: --permission= - the name for the permission (by default a permission named "main" already exist)
# | arg: -a, --add= - the list of group or users to enable add to the permission # | arg: --add= - the list of group or users to enable add to the permission
# | arg: -r, --remove= - the list of group or users to remove from the permission # | arg: --remove= - the list of group or users to remove from the permission
#
# Requires YunoHost version 3.7.0 or higher.
ynh_permission_update() { ynh_permission_update() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([p]=permission= [a]=add= [r]=remove=) local -A args_array=([p]=permission= [a]=add= [r]=remove=)
@ -302,11 +283,9 @@ ynh_permission_update() {
# example: ynh_permission_has_user --permission=main --user=visitors # example: ynh_permission_has_user --permission=main --user=visitors
# #
# usage: ynh_permission_has_user --permission=permission --user=user # usage: ynh_permission_has_user --permission=permission --user=user
# | arg: -p, --permission= - the permission to check # | arg: --permission= - the permission to check
# | arg: -u, --user= - the user seek in the permission # | arg: --user= - the user seek in the permission
# | exit: Return 1 if the permission doesn't have that user or doesn't exist, 0 otherwise # | exit: Return 1 if the permission doesn't have that user or doesn't exist, 0 otherwise
#
# Requires YunoHost version 3.7.1 or higher.
ynh_permission_has_user() { ynh_permission_has_user() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([p]=permission= [u]=user=) local -A args_array=([p]=permission= [u]=user=)
@ -322,7 +301,7 @@ ynh_permission_has_user() {
# Check both allowed and corresponding_users sections in the json # Check both allowed and corresponding_users sections in the json
for section in "allowed" "corresponding_users"; do for section in "allowed" "corresponding_users"; do
if yunohost user permission info "$app.$permission" --output-as json --quiet \ 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 return 0
fi fi
done done

View file

@ -3,105 +3,72 @@
# (this is used in the apt helpers, big meh ...) # (this is used in the apt helpers, big meh ...)
readonly YNH_DEFAULT_PHP_VERSION=7.4 readonly YNH_DEFAULT_PHP_VERSION=7.4
# Legacy: auto-convert phpversion to php_version (for consistency with nodejs_version, ruby_version, ...)
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
# Create a dedicated PHP-FPM config # Create a dedicated PHP-FPM config
# #
# usage: ynh_config_add_phpfpm # usage: ynh_config_add_phpfpm
# #
# This helper assumes the app has an conf/extra_php-fpm.conf snippet # This will automatically generate an appropriate PHP-FPM configuration for this app.
# #
# The actual PHP configuration will be automatically generated, # The resulting configuration will be deployed to the appropriate place:
# and your extra_php-fpm.conf will be appended (typically contains PHP upload limits) # `/etc/php/$php_version/fpm/pool.d/$app.conf`
# #
# The resulting configuration will be deployed to the appropriate place, /etc/php/$php_version/fpm/pool.d/$app.conf # If the app provides a `conf/extra_php-fpm.conf` template, it will be appended
# to the generated configuration. (In the vast majority of cases, this shouldnt
# be necessary)
# #
# Performance-related options in the PHP conf, such as : # $php_version should be defined prior to calling this helper, but there should
# pm.max_children, pm.start_servers, pm.min_spare_servers pm.max_spare_servers # be no reason to manually set it, as it is automatically set by the apt
# are computed from two parameters called "usage" and "footprint" which can be set to low/medium/high. (cf details below) # helpers/resources when installing phpX.Y dependencies (PHP apps should at
# least install phpX.Y-fpm using the `apt` helper/resource)
# #
# If you wish to tweak those, please initialize the settings `fpm_usage` and `fpm_footprint` # `$php_group` can be defined as a global (from `_common.sh`) if the worker
# *prior* to calling this helper. Otherwise, "low" will be used as a default for both values. # processes should run with a different group than `$app`
# #
# Otherwise, if you want the user to have control over these, we encourage to create a config panel # Additional "pm" and "php_admin_value" settings which are meant to be possibly
# (which should ultimately be standardized by the core ...) # configurable by admins from a future standard config panel at some point,
# related to performance and availability of the app, for which tweaking may be
# required if the app is used by "plenty" of users and other memory/CPU load
# considerations....
# #
# The footprint of the service will be used to defined the maximum footprint we can allow, which is half the maximum RAM. # If you have good reasons to be willing to use different
# So it will be used to defined 'pm.max_children' # defaults than the one set by this helper (while still allowing admin to
# A lower value for the footprint will allow more children for 'pm.max_children'. And so for # override it) you should use `ynh_app_setting_set_default`
# 'pm.start_servers', 'pm.min_spare_servers' and 'pm.max_spare_servers' which are defined from the
# value of 'pm.max_children'
# NOTE: 'pm.max_children' can't exceed 4 times the number of processor's cores.
# #
# The usage value will defined the way php will handle the children for the pool. # - `$php_upload_max_filezise`: corresponds upload_max_filesize and post_max_size. Defaults to 50M
# A value set as 'low' will set the process manager to 'ondemand'. Children will start only if the # - `$php_process_management`: corresponds to "pm" (ondemand, dynamic, static). Defaults to ondemand
# service is used, otherwise no child will stay alive. This config gives the lower footprint when the # - `$php_max_children`: by default, computed from "total RAM" divided by 40, cf `_default_php_max_children`
# service is idle. But will use more proc since it has to start a child as soon it's used. # - `$php_memory_limit`: by default, 128M (from global php.ini)
# Set as 'medium', the process manager will be at dynamic. If the service is idle, a number of children #
# equal to pm.min_spare_servers will stay alive. So the service can be quick to answer to any request. # Note that if $php_process_management is set to "dynamic", then these
# The number of children can grow if needed. The footprint can stay low if the service is idle, but # variables MUST be defined prior to calling the helper (no default value) ...
# not null. The impact on the proc is a little bit less than 'ondemand' as there's always a few # Check PHP-FPM's manual for more info on what these are (: ...
# children already available. #
# Set as 'high', the process manager will be set at 'static'. There will be always as many children as # - `$php_start_servers`
# 'pm.max_children', the footprint is important (but will be set as maximum a quarter of the maximum # - `$php_min_spare_servers`
# RAM) but the impact on the proc is lower. The service will be quick to answer as there's always many # - `$php_max_spare_servers`
# children ready to answer.
# #
# Requires YunoHost version 4.1.0 or higher.
ynh_config_add_phpfpm() { ynh_config_add_phpfpm() {
# ============ Argument parsing =============
local -A args_array=([g]=group=)
local group
ynh_handle_getopts_args "$@"
group=${group:-}
# ===========================================
# If the PHP version changed, remove the old fpm conf [[ -n "${php_version:-}" ]] || ynh_die "\$php_version should be defined prior to calling ynh_config_add_phpfpm. You should not need to define it manually, it is automatically set by the apt helper when installing the phpX.Y- depenencies"
# (NB: This stuff is also handled by the apt helper, which is usually triggered before this helper)
# FIXME: so is this still needed @_@
local old_php_version=$(ynh_app_setting_get --key=php_version)
if [ -n "$old_php_version" ] && [ "$old_php_version" != "$php_version" ]; then
local old_php_fpm_config_dir=$(ynh_app_setting_get --key=fpm_config_dir)
local old_php_finalphpconf="$old_php_fpm_config_dir/pool.d/$app.conf"
if [[ -f "$old_php_finalphpconf" ]] # Apps may define $php_group as a global (e.g. from _common.sh) to change this
then # (this is not meant to be overridable by users)
ynh_backup_if_checksum_is_different "$old_php_finalphpconf" local php_group=${php_group:-$app}
ynh_remove_fpm_config
fi
fi
local fpm_service="php${php_version}-fpm" # Meant to be overridable by users from a standard config panel at some point ...
local fpm_config_dir="/etc/php/$php_version/fpm" # 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_max_children=${php_max_children:-$(_default_php_max_children)}
local php_memory_limit=${php_memory_limit:-128M} # default value is from global php.ini
# Create the directory for FPM pools local phpfpm_template=$(mktemp)
mkdir --parents "$fpm_config_dir/pool.d" cat << EOF > $phpfpm_template
# FIXME: zzzz do we really need those ...
ynh_app_setting_set --key=fpm_config_dir --value="$fpm_config_dir"
ynh_app_setting_set --key=fpm_service --value="$fpm_service"
ynh_app_setting_set --key=php_version --value=$php_version
# Define the values to use for the configuration of PHP.
_ynh_get_scalable_phpfpm
local phpfpm_group=$([[ -n "$group" ]] && echo "$group" || echo "$app")
local phpfpm_path="$YNH_APP_BASEDIR/conf/php-fpm.conf"
echo "
[__APP__] [__APP__]
user = __APP__ user = __APP__
group = __PHPFPM_GROUP__ group = __PHP_GROUP__
chdir = __INSTALL_DIR__ chdir = __INSTALL_DIR__
@ -109,209 +76,74 @@ listen = /var/run/php/php__PHP_VERSION__-fpm-__APP__.sock
listen.owner = www-data listen.owner = www-data
listen.group = www-data listen.group = www-data
pm = __PHP_PM__ pm = __PHP_PROCESS_MANAGEMENT__
pm.max_children = __PHP_MAX_CHILDREN__ pm.max_children = __PHP_MAX_CHILDREN__
pm.max_requests = 500 pm.max_requests = 500
request_terminate_timeout = 1d request_terminate_timeout = 1d
" >"$phpfpm_path"
if [ "$php_pm" = "dynamic" ]; then EOF
echo " if [ "$php_process_management" = "dynamic" ]; then
cat << EOF >> $phpfpm_template
pm.start_servers = __PHP_START_SERVERS__ pm.start_servers = __PHP_START_SERVERS__
pm.min_spare_servers = __PHP_MIN_SPARE_SERVERS__ pm.min_spare_servers = __PHP_MIN_SPARE_SERVERS__
pm.max_spare_servers = __PHP_MAX_SPARE_SERVERS__ pm.max_spare_servers = __PHP_MAX_SPARE_SERVERS__
" >>"$phpfpm_path" EOF
elif [ "$php_process_management" = "ondemand" ]; then
elif [ "$php_pm" = "ondemand" ]; then cat << EOF >> $phpfpm_template
echo "
pm.process_idle_timeout = 10s pm.process_idle_timeout = 10s
" >>"$phpfpm_path" EOF
fi fi
# Concatene the extra config. cat << EOF >> $phpfpm_template
php_admin_value[upload_max_filesize] = __PHP_UPLOAD_MAX_FILESIZE__
php_admin_value[post_max_size] = __PHP_UPLOAD_MAX_FILESIZE__
php_admin_value[memory_limit] = __PHP_MEMORY_LIMIT__
EOF
# Concatene the extra config
if [ -e $YNH_APP_BASEDIR/conf/extra_php-fpm.conf ]; then 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_template"
fi fi
ynh_config_add --template="$phpfpm_path" --destination="$fpm_config_dir/pool.d/$app.conf" # Make sure the fpm pool dir exists
mkdir --parents "/etc/php/$php_version/fpm/pool.d"
# And hydrate configuration
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 # 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 php-fpm${php_version} --test || true
ynh_safe_rm "$fpm_config_dir/pool.d/$app.conf" ynh_safe_rm "/etc/php/$php_version/fpm/pool.d/$app.conf"
ynh_die "The new configuration broke php-fpm?" ynh_die "The new configuration broke php-fpm?"
fi fi
ynh_systemctl --service=$fpm_service --action=reload
ynh_systemctl --service=php${php_version}-fpm --action=reload
} }
# Remove the dedicated PHP-FPM config # Remove the dedicated PHP-FPM config
# #
# usage: ynh_config_remove_phpfpm # usage: ynh_config_remove_phpfpm
#
# Requires YunoHost version 2.7.2 or higher.
ynh_config_remove_phpfpm() { ynh_config_remove_phpfpm() {
local fpm_config_dir=$(ynh_app_setting_get --key=fpm_config_dir) ynh_safe_rm "/etc/php/$php_version/fpm/pool.d/$app.conf"
ynh_safe_rm "$fpm_config_dir/pool.d/$app.conf"
ynh_systemctl --service="php${php_version}-fpm" --action=reload ynh_systemctl --service="php${php_version}-fpm" --action=reload
} }
# Define the values to configure PHP-FPM _default_php_max_children() {
# # Get the total of RAM available
# [internal] local total_ram=$(ynh_get_ram --total)
#
# usage: _ynh_get_scalable_phpfpm
# Footprint can be defined via the "fpm_footprint", to be set prior to calling this helper
# low - Less than 20 MB of RAM by pool.
# medium - Between 20 MB and 40 MB of RAM by pool.
# high - More than 40 MB of RAM by pool.
# Or specify exactly the footprint, the load of the service as MB by pool instead of having a standard value.
# To have this value, use the following command and stress the service.
# watch -n0.5 ps -o user,cmd,%cpu,rss -u APP
#
# Usage can be defined via the "fpm_usage", to be set prior to calling this helper
# low - Personal usage, behind the SSO.
# medium - Low usage, few people or/and publicly accessible.
# high - High usage, frequently visited website.
#
_ynh_get_scalable_phpfpm() {
# If no usage provided, default to the value existing in setting ... or to low
local fpm_usage_in_setting=$(ynh_app_setting_get --key=fpm_usage)
local usage=${fpm_usage_in_setting:-low}
ynh_app_setting_set --key=fpm_usage --value=$usage
# If no footprint provided, default to the value existing in setting ... or to low
local fpm_footprint_in_setting=$(ynh_app_setting_get --key=fpm_footprint)
local footprint=${fpm_footprint_in_setting:-low}
ynh_app_setting_set --key=fpm_footprint --value=$footprint
# Set all characters as lowercase
if [ "$footprint" = "low" ]; then
footprint=20
elif [ "$footprint" = "medium" ]; then
footprint=35
elif [ "$footprint" = "high" ]; then
footprint=50
fi
# Define the factor to determine min_spare_servers
# to avoid having too few children ready to start for heavy apps
if [ $footprint -le 20 ]; then
min_spare_servers_factor=8
elif [ $footprint -le 35 ]; then
min_spare_servers_factor=5
else
min_spare_servers_factor=3
fi
# Define the way the process manager handle child processes.
if [ "$usage" = "low" ]; then
php_pm=ondemand
elif [ "$usage" = "medium" ]; then
php_pm=dynamic
elif [ "$usage" = "high" ]; then
php_pm=static
else
ynh_die "Does not recognize '$usage' as an usage value."
fi
# Get the total of RAM available, except swap.
local max_ram=$(ynh_get_ram --total)
at_least_one() {
# Do not allow value below 1
if [ $1 -le 0 ]; then
echo 1
else
echo $1
fi
}
# Define pm.max_children
# The value of pm.max_children is the total amount of ram divide by 2 and divide again by the footprint of a pool for this app.
# So if PHP-FPM start the maximum of children, it won't exceed half of the ram.
php_max_children=$(($max_ram / 2 / $footprint))
# If process manager is set as static, use half less children.
# Used as static, there's always as many children as the value of pm.max_children
if [ "$php_pm" = "static" ]; then
php_max_children=$(($php_max_children / 2))
fi
php_max_children=$(at_least_one $php_max_children)
# The value of pm.max_children is the total amount of ram divide by 2,
# divide again by 20MB (= a default, classic worker footprint) This is
# designed such that if PHP-FPM start the maximum of children, it won't
# exceed half of the ram.
local php_max_children="$(($total_ram / 40))"
# Make sure we get at least max_children = 1
if [ $php_max_children -le 0 ]; then
php_max_children=1
# To not overload the proc, limit the number of children to 4 times the number of cores. # To not overload the proc, limit the number of children to 4 times the number of cores.
local core_number=$(nproc) elif [ $php_max_children -gt "$(($(nproc) * 4))" ]; then
local max_proc=$(($core_number * 4)) php_max_children="$(($(nproc) * 4))"
if [ $php_max_children -gt $max_proc ]; then
php_max_children=$max_proc
fi fi
# Get a potential forced value for php_max_children echo "$php_max_children"
local php_forced_max_children=$(ynh_app_setting_get --key=php_forced_max_children)
if [ -n "$php_forced_max_children" ]; then
php_max_children=$php_forced_max_children
fi
if [ "$php_pm" = "dynamic" ]; then
# Define pm.start_servers, pm.min_spare_servers and pm.max_spare_servers for a dynamic process manager
php_min_spare_servers=$(($php_max_children / $min_spare_servers_factor))
php_min_spare_servers=$(at_least_one $php_min_spare_servers)
php_max_spare_servers=$(($php_max_children / 2))
php_max_spare_servers=$(at_least_one $php_max_spare_servers)
php_start_servers=$(($php_min_spare_servers + ($php_max_spare_servers - $php_min_spare_servers) / 2))
php_start_servers=$(at_least_one $php_start_servers)
else
php_min_spare_servers=0
php_max_spare_servers=0
php_start_servers=0
fi
}
# Execute a command with Composer
#
# Will use $install_dir as workdir unless $composer_workdir exists (but that shouldnt be necessary)
#
# You may also define composer_user=root prior to call this helper if you absolutely need composer to run as root, but this is discouraged...
#
# usage: ynh_composer_exec commands
#
# Requires YunoHost version 4.2 or higher.
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" $@ \
-d "$workdir" --no-interaction --no-ansi 2>&1
}
# Install and initialize Composer in the given directory
#
# The installed version is defined by $composer_version which should be defined
# as global prior to calling this helper.
#
# Will use $install_dir as workdir unless $composer_workdir exists (but that shouldnt be necessary)
#
# usage: ynh_composer_install
#
# Requires YunoHost version 4.2 or higher.
ynh_composer_install() {
local workdir="${composer_workdir:-$install_dir}"
[[ -n "${composer_version}" ]] || ynh_die "\$composer_version should be defined before calling ynh_composer_install. (In the past, this was called \$YNH_COMPOSER_VERSION)"
[[ ! -e "$workdir/composer.phar" ]] || ynh_safe_rm $workdir/composer.phar
local composer_url="https://getcomposer.org/download/$composer_version/composer.phar"
# NB. we have to declare the var as local first,
# otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
# because local always return 0 ...
local out
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$workdir/composer.phar $composer_url 2>&1) \
|| ynh_die "$out"
} }

View file

@ -19,7 +19,7 @@ ynh_psql_db_shell() {
# Create a database and grant optionnaly privilegies to a user # Create a database and grant optionnaly privilegies to a user
# #
# [internal] # [internal] ... handled by the core / "database resource"
# #
# usage: ynh_psql_create_db db [user] # usage: ynh_psql_create_db db [user]
# | arg: db - the database name to create # | arg: db - the database name to create
@ -42,7 +42,7 @@ ynh_psql_create_db() {
# Drop a database # Drop a database
# #
# [internal] # [internal] ... handled by the core / "database resource"
# #
# If you intend to drop the database *and* the associated user, # If you intend to drop the database *and* the associated user,
# consider using ynh_psql_remove_db instead. # consider using ynh_psql_remove_db instead.
@ -74,19 +74,21 @@ ynh_psql_dump_db() {
# Create a user # Create a user
# #
# [internal] # [internal] ... handled by the core / "database resource"
# #
# usage: ynh_psql_create_user user pwd # usage: ynh_psql_create_user user pwd
# | arg: user - the user name to create # | arg: user - the user name to create
# | arg: pwd - the password to identify user by # | arg: pwd - the password to identify user by
# #
ynh_psql_create_user() { ynh_psql_create_user() {
local user=$1
local pwd=$2
sudo --login --user=postgres psql <<< "CREATE USER $user WITH ENCRYPTED PASSWORD '$pwd'" sudo --login --user=postgres psql <<< "CREATE USER $user WITH ENCRYPTED PASSWORD '$pwd'"
} }
# Check if a psql user exists # Check if a psql user exists
# #
# [packagingv1] # [internal]
# #
# usage: ynh_psql_user_exists user # usage: ynh_psql_user_exists user
# | arg: user= - the user for which to check existence # | arg: user= - the user for which to check existence
@ -99,6 +101,8 @@ ynh_psql_user_exists() {
# Check if a psql database exists # Check if a psql database exists
# #
# [internal]
#
# usage: ynh_psql_database_exists database # usage: ynh_psql_database_exists database
# | arg: database - the database for which to check existence # | arg: database - the database for which to check existence
# | exit: Return 1 if the database doesn't exist, 0 otherwise # | exit: Return 1 if the database doesn't exist, 0 otherwise
@ -110,7 +114,7 @@ ynh_psql_database_exists() {
# Drop a user # Drop a user
# #
# [internal] # [internal] ... handled by the core / "database resource"
# #
# usage: ynh_psql_drop_user user # usage: ynh_psql_drop_user user
# | arg: user - the user name to drop # | arg: user - the user name to drop

View file

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

View file

@ -1,20 +1,19 @@
#!/bin/bash #!/bin/bash
rbenv_install_dir="/opt/rbenv" readonly RBENV_INSTALL_DIR="/opt/rbenv"
ruby_version_path="$rbenv_install_dir/versions"
# RBENV_ROOT is the directory of rbenv, it needs to be loaded as a environment variable. # RBENV_ROOT is the directory of rbenv, it needs to be loaded as a environment variable.
export RBENV_ROOT="$rbenv_install_dir" export RBENV_ROOT="$RBENV_INSTALL_DIR"
export rbenv_root="$rbenv_install_dir" export rbenv_root="$RBENV_INSTALL_DIR"
_ynh_load_ruby_in_path_and_other_tweaks() { _ynh_load_ruby_in_path_and_other_tweaks() {
# Get the absolute path of this version of Ruby # Get the absolute path of this version of Ruby
local ruby_path="$ruby_version_path/$app/bin" ruby_dir="$RBENV_INSTALL_DIR/versions/$app/bin"
# Load the path of this version of ruby in $PATH # Load the path of this version of ruby in $PATH
if [[ :$PATH: != *":$ruby_path"* ]]; then if [[ :$PATH: != *":$ruby_dir"* ]]; then
PATH="$ruby_path:$PATH" PATH="$ruby_dir:$PATH"
fi fi
# Export PATH such that it's available through sudo -E / ynh_exec_as $app # Export PATH such that it's available through sudo -E / ynh_exec_as $app
@ -26,36 +25,28 @@ _ynh_load_ruby_in_path_and_other_tweaks() {
# Sets the local application-specific Ruby version # Sets the local application-specific Ruby version
pushd ${install_dir} pushd ${install_dir}
$rbenv_install_dir/bin/rbenv local $ruby_version $RBENV_INSTALL_DIR/bin/rbenv local $ruby_version
popd popd
} }
# Install a specific version of Ruby using rbenv # Install a specific version of Ruby using rbenv
# #
# The installed version is defined by $ruby_version which should be defined as global prior to calling this helper # The installed version is defined by `$ruby_version` which should be defined as global prior to calling this helper
#
# This helper creates a /etc/profile.d/rbenv.sh that configures PATH environment for rbenv
# for every LOGIN user, hence your user must have a defined shell (as opposed to /usr/sbin/nologin)
#
# Don't forget to execute ruby-dependent command in a login environment
# (e.g. sudo --login option)
# When not possible (e.g. in systemd service definition), please use direct path
# to rbenv shims (e.g. $RBENV_ROOT/shims/bundle)
# #
# usage: ynh_ruby_install # usage: ynh_ruby_install
# #
# Adds the appropriate, specific version of ruby to the PATH variable (which # The helper adds the appropriate, specific version of ruby to the `$PATH` variable (which
# is also exported, to ease the use of ynh_exec_as_app). Also define variable # is preserved when calling ynh_exec_as_app). Also defines:
# PATH_with_ruby to be used in the systemd config # - `$path_with_ruby` to be used in the systemd config (`Environment="PATH=__PATH_WITH_RUBY__"`)
# (Environment="PATH=__PATH_WITH_RUBY__") # - `$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`)
# #
# Requires YunoHost version 3.2.2 or higher. # 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" [[ -n "${ruby_version:-}" ]] || ynh_die "\$ruby_version should be defined prior to calling ynh_ruby_install"
# Load rbenv path in PATH # Load rbenv path in PATH
local CLEAR_PATH="$rbenv_install_dir/bin:$PATH" local CLEAR_PATH="$RBENV_INSTALL_DIR/bin:$PATH"
# Remove /usr/local/bin in PATH in case of Ruby prior installation # Remove /usr/local/bin in PATH in case of Ruby prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@') PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
@ -64,84 +55,84 @@ ynh_ruby_install () {
test -x /usr/bin/ruby && mv /usr/bin/ruby /usr/bin/ruby_rbenv test -x /usr/bin/ruby && mv /usr/bin/ruby /usr/bin/ruby_rbenv
# Install or update rbenv # Install or update rbenv
mkdir -p $rbenv_install_dir mkdir -p $RBENV_INSTALL_DIR
rbenv="$(command -v rbenv $rbenv_install_dir/bin/rbenv | grep "$rbenv_install_dir/bin/rbenv" | head -1)" rbenv="$(command -v rbenv $RBENV_INSTALL_DIR/bin/rbenv | grep "$RBENV_INSTALL_DIR/bin/rbenv" | head -1)"
if [ -n "$rbenv" ]; then if [ -n "$rbenv" ]; then
pushd "${rbenv%/*/*}" pushd "${rbenv%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/rbenv.git"; then if git remote -v 2> /dev/null | grep "https://github.com/rbenv/rbenv.git"; then
echo "Updating rbenv..." echo "Updating rbenv..."
git pull -q --tags origin master git pull -q --tags origin master
ynh_ruby_try_bash_extension _ynh_ruby_try_bash_extension
else else
echo "Reinstalling rbenv..." echo "Reinstalling rbenv..."
cd .. cd ..
ynh_safe_rm $rbenv_install_dir ynh_safe_rm $RBENV_INSTALL_DIR
mkdir -p $rbenv_install_dir mkdir -p $RBENV_INSTALL_DIR
cd $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 init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1 git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master git checkout -q -b master origin/master
ynh_ruby_try_bash_extension _ynh_ruby_try_bash_extension
rbenv=$rbenv_install_dir/bin/rbenv 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 popd
fi fi
mkdir -p "${rbenv_install_dir}/plugins" mkdir -p "${RBENV_INSTALL_DIR}/plugins"
ruby_build="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-install rbenv-install | head -1)" ruby_build="$(command -v "$RBENV_INSTALL_DIR"/plugins/*/bin/rbenv-install rbenv-install | head -1)"
if [ -n "$ruby_build" ]; then if [ -n "$ruby_build" ]; then
pushd "${ruby_build%/*/*}" pushd "${ruby_build%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/ruby-build.git"; then if git remote -v 2> /dev/null | grep "https://github.com/rbenv/ruby-build.git"; then
echo "Updating ruby-build..." echo "Updating ruby-build..."
git pull -q origin master git pull -q origin master
fi fi
popd popd
else else
echo "Installing ruby-build..." echo "Installing ruby-build..."
git clone -q https://github.com/rbenv/ruby-build.git "${rbenv_install_dir}/plugins/ruby-build" git clone -q https://github.com/rbenv/ruby-build.git "${RBENV_INSTALL_DIR}/plugins/ruby-build"
fi fi
rbenv_alias="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-alias rbenv-alias | head -1)" rbenv_alias="$(command -v "$RBENV_INSTALL_DIR"/plugins/*/bin/rbenv-alias rbenv-alias | head -1)"
if [ -n "$rbenv_alias" ]; then if [ -n "$rbenv_alias" ]; then
pushd "${rbenv_alias%/*/*}" pushd "${rbenv_alias%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then if git remote -v 2> /dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then
echo "Updating rbenv-aliases..." echo "Updating rbenv-aliases..."
git pull -q origin master git pull -q origin master
fi fi
popd popd
else else
echo "Installing rbenv-aliases..." echo "Installing rbenv-aliases..."
git clone -q https://github.com/tpope/rbenv-aliases.git "${rbenv_install_dir}/plugins/rbenv-aliase" git clone -q https://github.com/tpope/rbenv-aliases.git "${RBENV_INSTALL_DIR}/plugins/rbenv-aliase"
fi fi
rbenv_latest="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-latest rbenv-latest | head -1)" rbenv_latest="$(command -v "$RBENV_INSTALL_DIR"/plugins/*/bin/rbenv-latest rbenv-latest | head -1)"
if [ -n "$rbenv_latest" ]; then if [ -n "$rbenv_latest" ]; then
pushd "${rbenv_latest%/*/*}" pushd "${rbenv_latest%/*/*}"
if git remote -v 2>/dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then if git remote -v 2> /dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then
echo "Updating xxenv-latest..." echo "Updating xxenv-latest..."
git pull -q origin master git pull -q origin master
fi fi
popd popd
else else
echo "Installing xxenv-latest..." echo "Installing xxenv-latest..."
git clone -q https://github.com/momo-lab/xxenv-latest.git "${rbenv_install_dir}/plugins/xxenv-latest" git clone -q https://github.com/momo-lab/xxenv-latest.git "${RBENV_INSTALL_DIR}/plugins/xxenv-latest"
fi fi
# Enable caching # Enable caching
mkdir -p "${rbenv_install_dir}/cache" mkdir -p "${RBENV_INSTALL_DIR}/cache"
# Create shims directory if needed # Create shims directory if needed
mkdir -p "${rbenv_install_dir}/shims" mkdir -p "${RBENV_INSTALL_DIR}/shims"
# Restore /usr/local/bin in PATH # Restore /usr/local/bin in PATH
PATH=$CLEAR_PATH PATH=$CLEAR_PATH
@ -162,8 +153,7 @@ ynh_ruby_install () {
ruby_version=$final_ruby_version ruby_version=$final_ruby_version
# Remove app virtualenv # Remove app virtualenv
if rbenv alias --list | grep --quiet "$app " if rbenv alias --list | grep --quiet "$app "; then
then
rbenv alias $app --remove rbenv alias $app --remove
fi fi
@ -174,9 +164,9 @@ ynh_ruby_install () {
_ynh_ruby_cleanup _ynh_ruby_cleanup
# Set environment for Ruby users # Set environment for Ruby users
echo "#rbenv echo "#rbenv
export RBENV_ROOT=$rbenv_install_dir export RBENV_ROOT=$RBENV_INSTALL_DIR
export PATH=\"$rbenv_install_dir/bin:$PATH\" export PATH=\"$RBENV_INSTALL_DIR/bin:$PATH\"
eval \"\$(rbenv init -)\" eval \"\$(rbenv init -)\"
#rbenv" > /etc/profile.d/rbenv.sh #rbenv" > /etc/profile.d/rbenv.sh
@ -188,14 +178,15 @@ eval \"\$(rbenv init -)\"
# Remove the version of Ruby used by the app. # Remove the version of Ruby used by the app.
# #
# This helper will also cleanup Ruby versions # This helper will also cleanup unused Ruby versions
# #
# usage: ynh_ruby_remove # usage: ynh_ruby_remove
ynh_ruby_remove () { ynh_ruby_remove() {
local ruby_version=$(ynh_app_setting_get --key=ruby_version)
[[ -n "${ruby_version:-}" ]] || ynh_die "\$ruby_version should be defined prior to calling ynh_ruby_remove"
# Load rbenv path in PATH # Load rbenv path in PATH
local CLEAR_PATH="$rbenv_install_dir/bin:$PATH" local CLEAR_PATH="$RBENV_INSTALL_DIR/bin:$PATH"
# Remove /usr/local/bin in PATH in case of Ruby prior installation # Remove /usr/local/bin in PATH in case of Ruby prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@') PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
@ -211,48 +202,45 @@ ynh_ruby_remove () {
# Remove no more needed versions of Ruby used by the app. # Remove no more needed versions of Ruby used by the app.
# #
# [internal]
#
# This helper will check what Ruby version are no more required, # This helper will check what Ruby version are no more required,
# and uninstall them # and uninstall them
# If no app uses Ruby, rbenv will be also removed. # If no app uses Ruby, rbenv will be also removed.
_ynh_ruby_cleanup () { _ynh_ruby_cleanup() {
# List required Ruby versions # List required Ruby versions
local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$') local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$')
local required_ruby_versions="" local required_ruby_versions=""
for installed_app in $installed_apps for installed_app in $installed_apps; do
do
local installed_app_ruby_version=$(ynh_app_setting_get --app=$installed_app --key="ruby_version") local installed_app_ruby_version=$(ynh_app_setting_get --app=$installed_app --key="ruby_version")
if [[ -n "$installed_app_ruby_version" ]] if [[ -n "$installed_app_ruby_version" ]]; then
then
required_ruby_versions="${installed_app_ruby_version}\n${required_ruby_versions}" required_ruby_versions="${installed_app_ruby_version}\n${required_ruby_versions}"
fi fi
done done
# Remove no more needed Ruby versions # Remove no more needed Ruby versions
local installed_ruby_versions=$(rbenv versions --bare --skip-aliases | grep -Ev '/') local installed_ruby_versions=$(rbenv versions --bare --skip-aliases | grep -Ev '/')
for installed_ruby_version in $installed_ruby_versions for installed_ruby_version in $installed_ruby_versions; do
do if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"; then
if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"
then
echo "Removing Ruby-$installed_ruby_version" echo "Removing Ruby-$installed_ruby_version"
$rbenv_install_dir/bin/rbenv uninstall --force $installed_ruby_version $RBENV_INSTALL_DIR/bin/rbenv uninstall --force $installed_ruby_version
fi fi
done done
# If none Ruby version is required # If none Ruby version is required
if [[ -z "$required_ruby_versions" ]] if [[ -z "$required_ruby_versions" ]]; then
then
# Remove rbenv environment configuration # Remove rbenv environment configuration
echo "Removing rbenv" echo "Removing rbenv"
ynh_safe_rm "$rbenv_install_dir" ynh_safe_rm "$RBENV_INSTALL_DIR"
ynh_safe_rm "/etc/profile.d/rbenv.sh" ynh_safe_rm "/etc/profile.d/rbenv.sh"
fi fi
} }
ynh_ruby_try_bash_extension() { _ynh_ruby_try_bash_extension() {
if [ -x src/configure ]; then if [ -x src/configure ]; then
src/configure && make -C src 2>&1 || { src/configure && make -C src 2>&1 || {
ynh_print_info "Optional bash extension failed to build, but things will still work normally." ynh_print_info "Optional bash extension failed to build, but things will still work normally."
} }
fi fi
} }

View file

@ -2,11 +2,9 @@
# Get an application setting # Get an application setting
# #
# usage: ynh_app_setting_get --app=app --key=key # usage: ynh_app_setting_get --key=key
# | arg: -a, --app= - the application id # | arg: --app= - the application id (global $app by default)
# | arg: -k, --key= - the setting to get # | arg: --key= - the setting to get
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_get() { ynh_app_setting_get() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local _globalapp=${app-:} local _globalapp=${app-:}
@ -22,12 +20,10 @@ ynh_app_setting_get() {
# Set an application setting # Set an application setting
# #
# usage: ynh_app_setting_set --app=app --key=key --value=value # usage: ynh_app_setting_set --key=key --value=value
# | arg: -a, --app= - the application id # | arg: --app= - the application id (global $app by default)
# | arg: -k, --key= - the setting name to set # | arg: --key= - the setting name to set
# | arg: -v, --value= - the setting value to set # | arg: --value= - the setting value to set
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_set() { ynh_app_setting_set() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local _globalapp=${app-:} local _globalapp=${app-:}
@ -42,13 +38,44 @@ ynh_app_setting_set() {
ynh_app_setting "set" "$app" "$key" "$value" ynh_app_setting "set" "$app" "$key" "$value"
} }
# Set an application setting but only if the "$key" variable ain't set yet
#
# Note that it doesn't just define the setting but ALSO define the $foobar variable
#
# Hence it's meant as a replacement for this legacy overly complex syntax:
#
# if [ -z "${foo:-}" ]
# then
# foo="bar"
# ynh_app_setting_set --key="foo" --value="$foo"
# fi
#
# usage: ynh_app_setting_set_default --key=key --value=value
# | arg: --app= - the application id (global $app by default)
# | arg: --key= - the setting name to set
# | arg: --value= - the default setting value to set
ynh_app_setting_set_default() {
# ============ Argument parsing =============
local _globalapp=${app-:}
local -A args_array=([a]=app= [k]=key= [v]=value=)
local app
local key
local value
ynh_handle_getopts_args "$@"
app="${app:-$_globalapp}"
# ===========================================
if [ -z "${!key:-}" ]; then
eval $key=\$value
ynh_app_setting "set" "$app" "$key" "$value"
fi
}
# Delete an application setting # Delete an application setting
# #
# usage: ynh_app_setting_delete --app=app --key=key # usage: ynh_app_setting_delete --key=key
# | arg: -a, --app= - the application id # | arg: --app= - the application id (global $app by default)
# | arg: -k, --key= - the setting to delete # | arg: --key= - the setting to delete
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_delete() { ynh_app_setting_delete() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local _globalapp=${app-:} local _globalapp=${app-:}
@ -68,8 +95,10 @@ ynh_app_setting_delete() {
# [internal] # [internal]
# #
ynh_app_setting() { 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 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 import os, yaml, sys
app, action = os.environ['APP'], os.environ['ACTION'].lower() app, action = os.environ['APP'], os.environ['ACTION'].lower()
key, value = os.environ['KEY'], os.environ.get('VALUE', None) key, value = os.environ['KEY'], os.environ.get('VALUE', None)
@ -91,5 +120,16 @@ else:
with open(setting_file, "w") as f: with open(setting_file, "w") as f:
yaml.safe_dump(settings, f, default_flow_style=False) yaml.safe_dump(settings, f, default_flow_style=False)
EOF EOF
set -o xtrace # set -x eval "$xtrace_enable"
} }
# 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
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

@ -0,0 +1,253 @@
#!/bin/bash
# Download, check integrity, uncompress and patch upstream sources
#
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id] [--keep="file1 file2"] [--full_replace]
# | arg: --dest_dir= - Directory where to setup sources
# | arg: --source_id= - Name of the source, defaults to `main` (when the sources resource exists in manifest.toml) or (legacy) `app` otherwise
# | arg: --keep= - Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs' (no trailing `/` for folders)
# | arg: --full_replace= - Remove previous sources before installing new sources (can be 1 or 0, default to 0)
#
# This helper will read infos from the 'sources' resources in the `manifest.toml` of the app
# and expect a structure like:
#
# ```toml
# [resources.sources]
# [resources.sources.main]
# url = "https://some.address.to/download/the/app/archive"
# sha256 = "0123456789abcdef" # The sha256 sum of the asset obtained from the URL
# ```
#
# (See also the resources documentation which may be more complete?)
#
# ##### Optional flags in the 'sources' resource
#
# ```text
# format = "tar.gz"/xz/bz2/tar # automatically guessed from the extension of the URL, but can be set explicitly. Will use `tar` to extract
# "zip" # automatically guessed from the extension of the URL, but can be set explicitly. Will use `unzip` to extract
# "docker" # useful to extract files from an already-built docker image (instead of rebuilding them locally). Will use `docker-image-extract` to extract
# "whatever" # an arbitrary value, not really meaningful except to imply that the file won't be extracted
#
# in_subdir = true # default, there's an intermediate subdir in the archive before accessing the actual files
# false # sources are directly in the archive root
# n # (special cases) an integer representing a number of subdirs levels to get rid of
#
# extract = true # default if file is indeed an archive such as .zip, .tar.gz, .tar.bz2, ...
# = false # default if file 'format' is not set and the file is not to be extracted because it is not an archive but a script or binary or whatever asset.
# # in which case the file will only be `mv`ed to the location possibly renamed using the `rename` value
#
# rename = "whatever_your_want" # to be used for convenience when `extract` is false and the default name of the file is not practical
# platform = "linux/amd64" # (defaults to "linux/$YNH_ARCH") to be used in conjonction with `format = "docker"` to specify which architecture to extract for
# ```
#
# You may also define assets url and checksum per-architectures such as:
# ```toml
# [resources.sources]
# [resources.sources.main]
# amd64.url = "https://some.address.to/download/the/app/archive/when/amd64"
# amd64.sha256 = "0123456789abcdef"
# armhf.url = "https://some.address.to/download/the/app/archive/when/armhf"
# armhf.sha256 = "fedcba9876543210"
# ```
#
# In which case `ynh_setup_source --dest_dir="$install_dir"` will automatically pick the appropriate source depending on the arch
#
# The helper will:
# - Download the specific URL if there is no local archive
# - Check the integrity with the specific sha256 sum
# - Uncompress the archive to `$dest_dir`.
# - If `in_subdir` is true, the first level directory of the archive will be removed.
# - If `in_subdir` is a numeric value, the N first level directories will be removed.
# - Patches named `patches/${src_id}/*.patch` will be applied to `$dest_dir`
# - Apply sane default permissions (see _ynh_apply_default_permissions)
ynh_setup_source() {
# ============ Argument parsing =============
local -A args_array=([d]=dest_dir= [s]=source_id= [k]=keep= [r]=full_replace)
local dest_dir
local source_id
local keep
local full_replace
ynh_handle_getopts_args "$@"
keep="${keep:-}"
full_replace="${full_replace:-0}"
source_id="${source_id:-main}"
# ===========================================
local sources_json=$(ynh_read_manifest "resources.sources[\"$source_id\"]")
if jq -re ".url" <<< "$sources_json"; then
local arch_prefix=""
else
local arch_prefix=".$YNH_ARCH"
fi
local src_url="$(jq -r "$arch_prefix.url" <<< "$sources_json" | sed 's/^null$//')"
local src_sum="$(jq -r "$arch_prefix.sha256" <<< "$sources_json" | sed 's/^null$//')"
local src_format="$(jq -r ".format" <<< "$sources_json" | sed 's/^null$//')"
local src_in_subdir="$(jq -r ".in_subdir" <<< "$sources_json" | sed 's/^null$//')"
src_in_subdir=${src_in_subdir:-true}
local src_extract="$(jq -r ".extract" <<< "$sources_json" | sed 's/^null$//')"
local src_platform="$(jq -r ".platform" <<< "$sources_json" | sed 's/^null$//')"
local src_rename="$(jq -r ".rename" <<< "$sources_json" | sed 's/^null$//')"
[[ -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
src_format="zip"
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
src_format="tar.xz"
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]; then
src_format="tar.bz2"
elif [[ "$src_url" =~ ^.*\.tar$ ]]; then
src_format="tar"
elif [[ -z "$src_extract" ]]; then
src_extract="false"
fi
fi
src_format=${src_format:-tar.gz}
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
src_extract=${src_extract:-true}
if [[ "$src_extract" != "true" ]] && [[ "$src_extract" != "false" ]]; then
ynh_die "For source $source_id, expected either 'true' or 'false' for the extract parameter"
fi
# Gotta use this trick with 'dirname' because source_id may contain slashes x_x
mkdir -p $(dirname /var/cache/yunohost/download/${YNH_APP_ID}/${source_id})
src_filename="/var/cache/yunohost/download/${YNH_APP_ID}/${source_id}"
if [ "$src_format" = "docker" ]; then
src_platform="${src_platform:-"linux/$YNH_ARCH"}"
else
[ -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
rm -f "$src_filename"
fi
# Only redownload the file if it wasnt prefetched
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 ...
local out
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
|| ynh_die "$out"
fi
# Check the control sum
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}
ynh_die "Corrupt source for ${src_url}: Expected sha256sum to be ${src_sum} but got ${actual_sum} (size: ${actual_size})."
fi
fi
# Keep files to be backup/restored at the end of the helper
# Assuming $dest_dir already exists
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
if [ -n "$keep" ] && [ -e "$dest_dir" ]; then
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
mkdir -p $keep_dir
local stuff_to_keep
for stuff_to_keep in $keep; do
if [ -e "$dest_dir/$stuff_to_keep" ]; then
mkdir --parents "$(dirname "$keep_dir/$stuff_to_keep")"
cp --archive "$dest_dir/$stuff_to_keep" "$keep_dir/$stuff_to_keep"
fi
done
fi
if [ "$full_replace" -eq 1 ]; then
ynh_safe_rm "$dest_dir"
fi
# Extract source into the app dir
mkdir --parents "$dest_dir"
if [[ "$src_extract" == "false" ]]; then
if [[ -z "$src_rename" ]]; then
mv $src_filename $dest_dir
else
mv $src_filename $dest_dir/$src_rename
fi
elif [[ "$src_format" == "docker" ]]; then
"$YNH_HELPERS_DIR/vendor/docker-image-extract/docker-image-extract" -p $src_platform -o $dest_dir $src_url 2>&1
elif [[ "$src_format" == "zip" ]]; then
# Zip format
# Using of a temp directory, because unzip doesn't manage --strip-components
if $src_in_subdir; then
local tmp_dir=$(mktemp --directory)
unzip -quo $src_filename -d "$tmp_dir"
cp --archive $tmp_dir/*/. "$dest_dir"
ynh_safe_rm "$tmp_dir"
else
unzip -quo $src_filename -d "$dest_dir"
fi
ynh_safe_rm "$src_filename"
else
local strip=""
if [ "$src_in_subdir" != "false" ]; then
if [ "$src_in_subdir" == "true" ]; then
local sub_dirs=1
else
local sub_dirs="$src_in_subdir"
fi
strip="--strip-components $sub_dirs"
fi
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz|tar$ ]]; then
tar --extract --file=$src_filename --directory="$dest_dir" $strip
else
ynh_die "Archive format unrecognized."
fi
ynh_safe_rm "$src_filename"
fi
# Apply patches
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"
if ! patch --strip=1 < "$patchfile"; then
if ynh_in_ci_tests; then
ynh_die "Patch $patchfile failed to apply!"
else
ynh_print_warn "Warn your packagers /!\\ Patch $patchfile failed to apply"
fi
fi
done
popd
fi
# Keep files to be backup/restored at the end of the helper
# Assuming $dest_dir already exists
if [ -n "$keep" ]; then
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
local stuff_to_keep
for stuff_to_keep in $keep; do
if [ -e "$keep_dir/$stuff_to_keep" ]; then
mkdir --parents "$(dirname "$dest_dir/$stuff_to_keep")"
# We add "--no-target-directory" (short option is -T) to handle the special case
# when we "keep" a folder, but then the new setup already contains the same dir (but possibly empty)
# in which case a regular "cp" will create a copy of the directory inside the directory ...
# resulting in something like /var/www/$app/data/data instead of /var/www/$app/data
# cf https://unix.stackexchange.com/q/94831 for a more elaborate explanation on the option
cp --archive --no-target-directory "$keep_dir/$stuff_to_keep" "$dest_dir/$stuff_to_keep"
fi
done
fi
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
if [ -n "${install_dir:-}" ] && [ "$dest_dir" == "$install_dir" ]; then
_ynh_apply_default_permissions $dest_dir
fi
}

View file

@ -3,13 +3,11 @@
# Generate a random string # Generate a random string
# #
# usage: ynh_string_random [--length=string_length] # usage: ynh_string_random [--length=string_length]
# | arg: -l, --length= - the string length to generate (default: 24) # | arg: --length= - the string length to generate (default: 24)
# | arg: -f, --filter= - the kind of characters accepted in the output (default: 'A-Za-z0-9') # | arg: --filter= - the kind of characters accepted in the output (default: 'A-Za-z0-9')
# | ret: the generated string # | ret: the generated string
# #
# example: pwd=$(ynh_string_random --length=8) # example: pwd=$(ynh_string_random --length=8)
#
# Requires YunoHost version 2.2.4 or higher.
ynh_string_random() { ynh_string_random() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([l]=length= [f]=filter=) local -A args_array=([l]=length= [f]=filter=)
@ -20,7 +18,7 @@ ynh_string_random() {
filter=${filter:-'A-Za-z0-9'} 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" \ | tr --complement --delete "$filter" \
| sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p' | sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p'
} }
@ -28,14 +26,12 @@ ynh_string_random() {
# Substitute/replace a string (or expression) by another in a file # Substitute/replace a string (or expression) by another in a file
# #
# usage: ynh_replace --match=match --replace=replace --file=file # usage: ynh_replace --match=match --replace=replace --file=file
# | arg: -m, --match= - String to be searched and replaced in the file # | arg: --match= - String to be searched and replaced in the file
# | arg: -r, --replace= - String that will replace matches # | arg: --replace= - String that will replace matches
# | arg: -f, --file= - File in which the string will be replaced. # | arg: --file= - File in which the string will be replaced.
# #
# As this helper is based on sed command, regular expressions and references to # As this helper is based on sed command, regular expressions and references to
# sub-expressions can be used (see sed manual page for more information) # sub-expressions can be used (see sed manual page for more information)
#
# Requires YunoHost version 2.6.4 or higher.
ynh_replace() { ynh_replace() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([m]=match= [r]=replace= [f]=file=) local -A args_array=([m]=match= [r]=replace= [f]=file=)
@ -55,18 +51,16 @@ ynh_replace() {
sed --in-place "s${delimit}${match}${delimit}${replace}${delimit}g" "$file" sed --in-place "s${delimit}${match}${delimit}${replace}${delimit}g" "$file"
} }
# Substitute/replace a special string by another in a file # Substitute/replace a regex in a file
# #
# usage: ynh_replace_special_string --match=match --replace=replace --file=file # usage: ynh_replace_regex --match=match --replace=replace --file=file
# | arg: -m, --match= - String to be searched and replaced in the file # | arg: --match= - String to be searched and replaced in the file
# | arg: -r, --replace= - String that will replace matches # | arg: --replace= - String that will replace matches
# | arg: -f, --file= - File in which the string will be replaced. # | arg: --file= - File in which the string will be replaced.
# #
# This helper will use ynh_replace, but as you can use special # This helper will use ynh_replace, but as you can use special
# characters, you can't use some regular expressions and sub-expressions. # characters, you can't use some regular expressions and sub-expressions.
# ynh_replace_regex() {
# Requires YunoHost version 2.7.7 or higher.
ynh_replace_special_string() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([m]=match= [r]=replace= [f]=file=) local -A args_array=([m]=match= [r]=replace= [f]=file=)
local match local match
@ -91,14 +85,12 @@ ynh_replace_special_string() {
# [packagingv1] # [packagingv1]
# #
# usage: ynh_sanitize_dbid --db_name=name # usage: ynh_sanitize_dbid --db_name=name
# | arg: -n, --db_name= - name to correct/sanitize # | arg: --db_name= - name to correct/sanitize
# | ret: the corrected name # | ret: the corrected name
# #
# example: dbname=$(ynh_sanitize_dbid $app) # example: dbname=$(ynh_sanitize_dbid $app)
# #
# Underscorify the string (replace - and . by _) # Underscorify the string (replace - and . by _)
#
# Requires YunoHost version 2.2.4 or higher.
ynh_sanitize_dbid() { ynh_sanitize_dbid() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([n]=db_name=) local -A args_array=([n]=db_name=)
@ -123,8 +115,6 @@ ynh_sanitize_dbid() {
# ynh_normalize_url_path / # -> / # ynh_normalize_url_path / # -> /
# #
# usage: ynh_normalize_url_path path_to_normalize # usage: ynh_normalize_url_path path_to_normalize
#
# Requires YunoHost version 2.6.4 or higher.
ynh_normalize_url_path() { ynh_normalize_url_path() {
local path_url=$1 local path_url=$1

View file

@ -3,15 +3,13 @@
# Create a dedicated systemd config # Create a dedicated systemd config
# #
# usage: ynh_config_add_systemd [--service=service] [--template=template] # usage: ynh_config_add_systemd [--service=service] [--template=template]
# | arg: -s, --service= - Service name (optionnal, `$app` by default) # | arg: --service= - Service name (optionnal, `$app` by default)
# | arg: -t, --template= - Name of template file (optionnal, this is 'systemd' by default, meaning `../conf/systemd.service` will be used as template) # | arg: --template= - Name of template file (optionnal, this is 'systemd' by default, meaning `../conf/systemd.service` will be used as template)
# #
# This will use the template `../conf/<templatename>.service`. # This will use the template `../conf/<templatename>.service`.
# #
# See the documentation of `ynh_config_add` for a description of the template # See the documentation of `ynh_config_add` for a description of the template
# format and how placeholders are replaced with actual variables. # format and how placeholders are replaced with actual variables.
#
# Requires YunoHost version 4.1.0 or higher.
ynh_config_add_systemd() { ynh_config_add_systemd() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([s]=service= [t]=template=) local -A args_array=([s]=service= [t]=template=)
@ -45,14 +43,12 @@ ynh_config_remove_systemd() {
# Start (or other actions) a service, print a log in case of failure and optionnaly wait until the service is completely started # Start (or other actions) a service, print a log in case of failure and optionnaly wait until the service is completely started
# #
# usage: ynh_systemctl [--service=service] [--action=action] [ [--wait_until="line to match"] [--log_path=log_path] [--timeout=300] [--length=20] ] # usage: ynh_systemctl [--service=service] [--action=action] [ [--wait_until="line to match"] [--log_path=log_path] [--timeout=300] [--length=20] ]
# | arg: -n, --service= - Name of the service to start. Default : `$app` # | arg: --service= - Name of the service to start. Default : `$app`
# | arg: -a, --action= - Action to perform with systemctl. Default: start # | arg: --action= - Action to perform with systemctl. Default: start
# | arg: -w, --wait_until= - The pattern to find in the log to attest the service is effectively fully started. # | arg: --wait_until= - The pattern to find in the log to attest the service is effectively fully started.
# | arg: -p, --log_path= - Log file - Path to the log file. Default : `/var/log/$app/$app.log` # | arg: --log_path= - Log file - Path to the log file. Default : `/var/log/$app/$app.log`
# | arg: -t, --timeout= - Timeout - The maximum time to wait before ending the watching. Default : 300 seconds. # | arg: --timeout= - Timeout - The maximum time to wait before ending the watching. Default : 60 seconds.
# | arg: -e, --length= - Length of the error log displayed for debugging : Default : 20 # | arg: --length= - Length of the error log displayed for debugging : Default : 20
#
# Requires YunoHost version 3.5.0 or higher.
ynh_systemctl() { ynh_systemctl() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([n]=service= [a]=action= [w]=wait_until= [p]=log_path= [t]=timeout= [e]=length=) local -A args_array=([n]=service= [a]=action= [w]=wait_until= [p]=log_path= [t]=timeout= [e]=length=)
@ -68,9 +64,14 @@ ynh_systemctl() {
wait_until=${wait_until:-} wait_until=${wait_until:-}
length=${length:-20} length=${length:-20}
log_path="${log_path:-/var/log/$service/$service.log}" log_path="${log_path:-/var/log/$service/$service.log}"
timeout=${timeout:-300} timeout=${timeout:-60}
# =========================================== # ===========================================
# 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
length=100
fi
# Manage case of service already stopped # Manage case of service already stopped
if [ "$action" == "stop" ] && ! systemctl is-active --quiet $service; then if [ "$action" == "stop" ] && ! systemctl is-active --quiet $service; then
return 0 return 0
@ -82,12 +83,12 @@ ynh_systemctl() {
# Following the starting of the app in its log # Following the starting of the app in its log
if [ "$log_path" == "systemd" ]; then if [ "$log_path" == "systemd" ]; then
# Read the systemd journal # 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 # Get the PID of the journalctl command
local pid_tail=$! local pid_tail=$!
else else
# Read the specified log file # 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 # Get the PID of the tail command
local pid_tail=$! local pid_tail=$!
fi fi
@ -114,7 +115,7 @@ ynh_systemctl() {
# Start the timeout and try to find wait_until # Start the timeout and try to find wait_until
if [[ -n "${wait_until:-}" ]]; then if [[ -n "${wait_until:-}" ]]; then
set +x set +o xtrace # set +x
local i=0 local i=0
local starttime=$(date +%s) local starttime=$(date +%s)
for i in $(seq 1 $timeout); do for i in $(seq 1 $timeout); do
@ -137,14 +138,13 @@ ynh_systemctl() {
# Also check the timeout using actual timestamp, because sometimes for some reason, # 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 # journalctl may take a huge time to run, and we end up waiting literally an entire hour
# instead of 5 min ... # instead of 5 min ...
if [[ "$(( $(date +%s) - $starttime))" -gt "$timeout" ]] if [[ "$(($(date +%s) - $starttime))" -gt "$timeout" ]]; then
then
i=$timeout i=$timeout
break break
fi fi
sleep 1 sleep 1
done done
set -x set -o xtrace # set -x
if [ $i -ge 3 ]; then if [ $i -ge 3 ]; then
echo "" >&2 echo "" >&2
fi fi
@ -156,6 +156,12 @@ ynh_systemctl() {
ynh_print_warn "===" ynh_print_warn "==="
tail --lines=$length "$log_path" >&2 tail --lines=$length "$log_path" >&2
fi 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
_ynh_clean_check_starting
return 1
fi
fi fi
_ynh_clean_check_starting _ynh_clean_check_starting
fi fi

View file

@ -1,66 +1,10 @@
#!/bin/bash #!/bin/bash
# Check if a YunoHost user exists
#
# usage: ynh_user_exists --username=username
# | arg: -u, --username= - the username to check
# | ret: 0 if the user exists, 1 otherwise.
#
# example: ynh_user_exists 'toto' || echo "User does not exist"
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_exists() {
# ============ Argument parsing =============
local -A args_array=([u]=username=)
local username
ynh_handle_getopts_args "$@"
# ===========================================
yunohost user list --output-as json --quiet | jq -e ".users.\"${username}\"" >/dev/null
}
# Retrieve a YunoHost user information
#
# usage: ynh_user_get_info --username=username --key=key
# | arg: -u, --username= - the username to retrieve info from
# | arg: -k, --key= - the key to retrieve
# | ret: the value associate to that key
#
# example: mail=$(ynh_user_get_info --username="toto" --key=mail)
#
# Requires YunoHost version 2.2.4 or higher.
ynh_user_get_info() {
# ============ Argument parsing =============
local -A args_array=([u]=username= [k]=key=)
local username
local key
ynh_handle_getopts_args "$@"
# ===========================================
yunohost user info "$username" --output-as json --quiet | jq -r ".$key"
}
# Get the list of YunoHost users
#
# usage: ynh_user_list
# | ret: one username per line as strings
#
# example: for u in $(ynh_user_list); do ... ; done
#
# Requires YunoHost version 2.4.0 or higher.
ynh_user_list() {
yunohost user list --output-as json --quiet | jq -r ".users | keys[]"
}
# Check if a user exists on the system # Check if a user exists on the system
# #
# [packagingv1]
#
# usage: ynh_system_user_exists --username=username # usage: ynh_system_user_exists --username=username
# | arg: -u, --username= - the username to check # | arg: --username= - the username to check
# | ret: 0 if the user exists, 1 otherwise. # | ret: 0 if the user exists, 1 otherwise.
#
# Requires YunoHost version 2.2.4 or higher.
ynh_system_user_exists() { ynh_system_user_exists() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([u]=username=) local -A args_array=([u]=username=)
@ -68,18 +12,14 @@ ynh_system_user_exists() {
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
# =========================================== # ===========================================
getent passwd "$username" &>/dev/null getent passwd "$username" &> /dev/null
} }
# Check if a group exists on the system # Check if a group exists on the system
# #
# [packagingv1]
#
# usage: ynh_system_group_exists --group=group # usage: ynh_system_group_exists --group=group
# | arg: -g, --group= - the group to check # | arg: --group= - the group to check
# | ret: 0 if the group exists, 1 otherwise. # | ret: 0 if the group exists, 1 otherwise.
#
# Requires YunoHost version 3.5.0.2 or higher.
ynh_system_group_exists() { ynh_system_group_exists() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([g]=group=) local -A args_array=([g]=group=)
@ -87,18 +27,16 @@ ynh_system_group_exists() {
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
# =========================================== # ===========================================
getent group "$group" &>/dev/null getent group "$group" &> /dev/null
} }
# Create a system user # Create a system user
# #
# [packagingv1]
#
# usage: ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell] [--groups="group1 group2"] # usage: ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell] [--groups="group1 group2"]
# | arg: -u, --username= - Name of the system user that will be create # | arg: --username= - Name of the system user that will be create
# | arg: -h, --home_dir= - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home # | arg: --home_dir= - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home
# | arg: -s, --use_shell - Create a user using the default login shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell # | arg: --use_shell - Create a user using the default login shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell
# | arg: -g, --groups - Add the user to system groups. Typically meant to add the user to the ssh.app / sftp.app group (e.g. for borgserver, my_webapp) # | arg: --groups - Add the user to system groups. Typically meant to add the user to the ssh.app / sftp.app group (e.g. for borgserver, my_webapp)
# #
# Create a nextcloud user with no home directory and /usr/sbin/nologin login shell (hence no login capability) : # Create a nextcloud user with no home directory and /usr/sbin/nologin login shell (hence no login capability) :
# ``` # ```
@ -108,8 +46,6 @@ ynh_system_group_exists() {
# ``` # ```
# ynh_system_user_create --username=discourse --home_dir=/var/www/discourse --use_shell # ynh_system_user_create --username=discourse --home_dir=/var/www/discourse --use_shell
# ``` # ```
#
# Requires YunoHost version 2.6.4 or higher.
ynh_system_user_create() { ynh_system_user_create() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([u]=username= [h]=home_dir= [s]=use_shell [g]=groups=) local -A args_array=([u]=username= [h]=home_dir= [s]=use_shell [g]=groups=)
@ -146,12 +82,8 @@ ynh_system_user_create() {
# Delete a system user # Delete a system user
# #
# [packagingv1]
#
# usage: ynh_system_user_delete --username=user_name # usage: ynh_system_user_delete --username=user_name
# | arg: -u, --username= - Name of the system user that will be create # | arg: --username= - Name of the system user that will be create
#
# Requires YunoHost version 2.6.4 or higher.
ynh_system_user_delete() { ynh_system_user_delete() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([u]=username=) local -A args_array=([u]=username=)
@ -171,12 +103,3 @@ ynh_system_user_delete() {
delgroup $username delgroup $username
fi fi
} }
# Execute a command after sudoing as $app
#
# Note that exported bash env variables are kept (using -E option of sudo)
#
# usage: ynh_exec_as_app COMMAND [ARG ...]
ynh_exec_as_app() {
sudo -E -u"$app" "$@"
}

View file

@ -3,75 +3,44 @@
# Create a dedicated config file from a template # Create a dedicated config file from a template
# #
# usage: ynh_config_add --template="template" --destination="destination" # usage: ynh_config_add --template="template" --destination="destination"
# | arg: -t, --template= - Template config file to use # | arg: --template= - Template config file to use
# | arg: -d, --destination= - Destination of the config file # | arg: --destination= - Destination of the config file
# | arg: -j, --jinja - Use jinja template instead of legacy __MY_VAR__ # | arg: --jinja - Use jinja template instead of the simple `__MY_VAR__` templating format
# #
# examples: # examples:
# ynh_config_add --template=".env" --destination="$install_dir/.env" use the template file "../conf/.env" # ynh_add_config --template=".env" --destination="$install_dir/.env" # (use the template file "conf/.env" from the app's package)
# ynh_config_add --jinja --template="config.j2" --destination="$install_dir/config" use the template file "../conf/config.j2" # ynh_add_config --jinja --template="config.j2" --destination="$install_dir/config" # (use the template file "conf/config.j2" from the app's package)
# ynh_config_add --template="/etc/nginx/sites-available/default" --destination="etc/nginx/sites-available/mydomain.conf"
# #
## # The template can be 1) the name of a file in the `conf` directory of
## How it works in "legacy" mode # the app, 2) a relative path or 3) an absolute path.
##
# The template can be by default the name of a file in the conf directory
# of a YunoHost Package, a relative path or an absolute path.
# #
# The helper will use the template `template` to generate a config file # This applies a simple templating format which covers a good 95% of cases,
# `destination` by replacing the following keywords with global variables # where patterns like `__FOO__` are replaced by the bash variable `$foo`, for example:
# that should be defined before calling this helper : # `__DOMAIN__` by `$domain`
# ``` # `__PATH__` by `$path`
# __USER__ by $app # `__APP__` by `$app`
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH # `__VAR_1__` by `$var_1`
# ``` # `__VAR_2__` by `$var_2`
# And any dynamic variables that should be defined before calling this helper like:
# ```
# __DOMAIN__ by $domain
# __PATH__ by $path
# __APP__ by $app
# __VAR_1__ by $var_1
# __VAR_2__ by $var_2
# ```
# #
## # Special case for `__PATH__/` which is replaced by `/` instead of `//` if `$path` is `/`
## When --jinja is enabled
##
# For a full documentation of the template you can refer to: https://jinja.palletsprojects.com/en/3.1.x/templates/
# In Yunohost context there are no really some specificity except that all variable passed are of type string.
# So here are some example of recommended usage:
# #
# If you need a conditional block # ##### When --jinja is enabled
# #
# {% if should_my_block_be_shown == 'true' %} # This option is meant for advanced use-cases where the "simple" templating
# ... # mode ain't enough because you need conditional blocks or loops.
# {% endif %}
# #
# or # For a full documentation of jinja's syntax you can refer to:
# https://jinja.palletsprojects.com/en/3.1.x/templates/
# #
# {% if should_my_block_be_shown == '1' %} # Note that in YunoHost context, all variables are from shell variables and therefore are strings
# ...
# {% endif %}
# #
# If you need to iterate with loop: # ##### Keeping track of manual changes by the admin
#
# {% for yolo in var_with_multiline_value.splitlines() %}
# ...
# {% endfor %}
#
# or
#
# {% for jail in my_var_with_coma.split(',') %}
# ...
# {% endfor %}
# #
# The helper will verify the checksum and backup the destination file # The helper will verify the checksum and backup the destination file
# if it's different before applying the new template. # if it's different before applying the new template.
# #
# And it will calculate and store the destination file checksum # And it will calculate and store the destination file checksum
# into the app settings when configuration is done. # into the app settings when configuration is done.
#
# Requires YunoHost version 4.1.0 or higher.
ynh_config_add() { ynh_config_add() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([t]=template= [d]=destination= [j]=jinja) local -A args_array=([t]=template= [d]=destination= [j]=jinja)
@ -101,70 +70,49 @@ ynh_config_add() {
chmod 640 $destination chmod 640 $destination
_ynh_apply_default_permissions $destination _ynh_apply_default_permissions $destination
if [[ "$jinja" == 1 ]] if [[ "$jinja" == 1 ]]; then
then
# This is ran in a subshell such that the "export" does not "contaminate" the main process # This is ran in a subshell such that the "export" does not "contaminate" the main process
( (
export $(compgen -v) export $(compgen -v)
j2 "$template_path" -f env -o $destination j2 "$template_path" -f env -o $destination
) )
else else
cp -f "$template_path" "$destination" cp -f "$template_path" "$destination"
ynh_replace_vars --file="$destination" _ynh_replace_vars "$destination"
fi fi
ynh_store_file_checksum "$destination" ynh_store_file_checksum "$destination"
} }
# Replace variables in a file # Replace `__FOO__` patterns in file with bash variable `$foo`
# #
# [internal] # [internal]
# #
# usage: ynh_replace_vars --file="file" # usage: ynh_replace_vars "/path/to/file"
# | arg: -f, --file= - File where to replace variables # | arg: /path/to/file - File where to replace variables
# #
# The helper will replace the following keywords with global variables # This applies a simple templating format which covers a good 95% of cases,
# that should be defined before calling this helper : # where patterns like `__FOO__` are replaced by the bash variable `$foo`, for example:
# __PATH__ by $path # `__DOMAIN__` by `$domain`
# __PATH__/ by $path/ if $path != /, or just / otherwise (instead of //) # `__PATH__` by `$path`
# __USER__ by $app # `__APP__` by `$app`
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH # `__VAR_1__` by `$var_1`
# `__VAR_2__` by `$var_2`
# #
# And any dynamic variables that should be defined before calling this helper like: # Special case for `__PATH__/` which is replaced by `/` instead of `//` if `$path` is `/`
# __DOMAIN__ by $domain _ynh_replace_vars() {
# __APP__ by $app local file=$1
# __VAR_1__ by $var_1
# __VAR_2__ by $var_2
#
# Requires YunoHost version 4.1.0 or higher.
ynh_replace_vars() {
# ============ Argument parsing =============
local -A args_array=([f]=file=)
local file
ynh_handle_getopts_args "$@"
# ===========================================
# Replace specific YunoHost variables # List unique (__ __) variables in $file
if test -n "${path:-}"; then
# path_slash_less is path, or a blank value if path is only '/'
local path_slash_less=${path%/}
ynh_replace --match="__PATH__/" --replace="$path_slash_less/" --file="$file"
ynh_replace --match="__PATH__" --replace="$path" --file="$file"
fi
if test -n "${app:-}"; then
ynh_replace --match="__USER__" --replace="$app" --file="$file"
fi
if test -n "${ynh_node_load_PATH:-}"; then
ynh_replace --match="__YNH_NODE_LOAD_PATH__" --replace="$ynh_node_load_PATH" --file="$file"
fi
# Replace others variables
# List other unique (__ __) variables in $file
local uniques_vars=($(grep -oP '__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__' $file | sort --unique | sed "s@__\([^.]*\)__@\L\1@g")) local uniques_vars=($(grep -oP '__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__' $file | sort --unique | sed "s@__\([^.]*\)__@\L\1@g"))
set +o xtrace # set +x set +o xtrace # set +x
# Specific trick to make sure that __PATH__/ doesn't end up in "//" if $path=/
if [[ "${path:-}" == "/" ]] && grep -q '__PATH__/' $file; then
sed --in-place "s@__PATH__/@/@g" "$file"
fi
# Do the replacement # Do the replacement
local delimit=@ local delimit=@
for one_var in "${uniques_vars[@]}"; do for one_var in "${uniques_vars[@]}"; do
@ -191,9 +139,9 @@ ynh_replace_vars() {
# Get a value from heterogeneous file (yaml, json, php, python...) # Get a value from heterogeneous file (yaml, json, php, python...)
# #
# usage: ynh_read_var_in_file --file=PATH --key=KEY # usage: ynh_read_var_in_file --file=PATH --key=KEY
# | arg: -f, --file= - the path to the file # | arg: --file= - the path to the file
# | arg: -k, --key= - the key to get # | arg: --key= - the key to get
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file) # | arg: --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
# #
# This helpers match several var affectation use case in several languages # This helpers match several var affectation use case in several languages
# We don't use jq or equivalent to keep comments and blank space in files # We don't use jq or equivalent to keep comments and blank space in files
@ -220,8 +168,6 @@ ynh_replace_vars() {
# USER = 8102 # USER = 8102
# user = 'https://donate.local' # user = 'https://donate.local'
# CUSTOM['user'] = 'YunoHost' # CUSTOM['user'] = 'YunoHost'
#
# Requires YunoHost version 4.3 or higher.
ynh_read_var_in_file() { ynh_read_var_in_file() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([f]=file= [k]=key= [a]=after=) local -A args_array=([f]=file= [k]=key= [a]=after=)
@ -269,7 +215,7 @@ ynh_read_var_in_file() {
var_part+='\s*' var_part+='\s*'
# Extract the part after assignation sign # 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 if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x set -o xtrace # set -x
echo YNH_NULL echo YNH_NULL
@ -293,12 +239,10 @@ ynh_read_var_in_file() {
# Set a value into heterogeneous file (yaml, json, php, python...) # Set a value into heterogeneous file (yaml, json, php, python...)
# #
# usage: ynh_write_var_in_file --file=PATH --key=KEY --value=VALUE # usage: ynh_write_var_in_file --file=PATH --key=KEY --value=VALUE
# | arg: -f, --file= - the path to the file # | arg: --file= - the path to the file
# | arg: -k, --key= - the key to set # | arg: --key= - the key to set
# | arg: -v, --value= - the value to set # | arg: --value= - the value to set
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file) # | arg: --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
#
# Requires YunoHost version 4.3 or higher.
ynh_write_var_in_file() { ynh_write_var_in_file() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([f]=file= [k]=key= [v]=value= [a]=after=) local -A args_array=([f]=file= [k]=key= [v]=value= [a]=after=)
@ -347,7 +291,7 @@ ynh_write_var_in_file() {
var_part+='\s*' var_part+='\s*'
# Extract the part after assignation sign # 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 if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
set -o xtrace # set -x set -o xtrace # set -x
return 1 return 1

View file

@ -6,24 +6,10 @@ YNH_APP_BASEDIR=${YNH_APP_BASEDIR:-$(realpath ..)}
# #
# [internal] # [internal]
# #
# usage:
# ynh_exit_properly is used only by the helper ynh_abort_if_errors.
# You should not use it directly.
# Instead, add to your script:
# ynh_clean_setup () {
# instructions...
# }
#
# This function provide a way to clean some residual of installation that not managed by remove script.
#
# It prints a warning to inform that the script was failed, and execute the ynh_clean_setup function if used in the app script
#
# Requires YunoHost version 2.6.4 or higher.
ynh_exit_properly() { ynh_exit_properly() {
local exit_code=$? local exit_code=$?
if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]] if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]]; then
then
rm -rf "/var/cache/yunohost/download/" rm -rf "/var/cache/yunohost/download/"
fi fi
@ -39,10 +25,6 @@ ynh_exit_properly() {
# Small tempo to avoid the next message being mixed up with other DEBUG messages # Small tempo to avoid the next message being mixed up with other DEBUG messages
sleep 0.5 sleep 0.5
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
# Exit with error status # Exit with error status
# We don't call ynh_die basically to avoid unecessary 10-ish # We don't call ynh_die basically to avoid unecessary 10-ish
# debug lines about parsing args and stuff just to exit 1.. # debug lines about parsing args and stuff just to exit 1..
@ -57,9 +39,6 @@ ynh_exit_properly() {
# #
# This configure the rest of the script execution such that, if an error occurs # This configure the rest of the script execution such that, if an error occurs
# or if an empty variable is used, the execution of the script stops immediately # or if an empty variable is used, the execution of the script stops immediately
# and a call to `ynh_clean_setup` is triggered if it has been defined by your script.
#
# Requires YunoHost version 2.6.4 or higher.
ynh_abort_if_errors() { ynh_abort_if_errors() {
set -o errexit # set -e; Exit if a command fail set -o errexit # set -e; Exit if a command fail
set -o nounset # set -u; And if a variable is used unset set -o nounset # set -u; And if a variable is used unset
@ -67,279 +46,17 @@ ynh_abort_if_errors() {
} }
# When running an app script, auto-enable ynh_abort_if_errors except for remove script # When running an app script, auto-enable ynh_abort_if_errors except for remove script
if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && [[ "${YNH_APP_ACTION}" != "remove" ]] if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && [[ "${YNH_APP_ACTION}" != "remove" ]]; then
then
ynh_abort_if_errors ynh_abort_if_errors
fi fi
# Download, check integrity, uncompress and patch upstream sources # Execute a command after sudoing as $app
# #
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id] [--keep="file1 file2"] [--full_replace] # Note that the $PATH variable is preserved (using --preserve-env=PATH)
# | arg: -d, --dest_dir= - Directory where to setup sources
# | arg: -s, --source_id= - Name of the source, defaults to `main` (when the sources resource exists in manifest.toml) or (legacy) `app` otherwise
# | arg: -k, --keep= - Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs' (no trailing `/` for folders)
# | arg: -r, --full_replace= - Remove previous sources before installing new sources (can be 1 or 0, default to 0)
# #
# #### New 'sources' resources # usage: ynh_exec_as_app COMMAND [ARG ...]
# ynh_exec_as_app() {
# (See also the resources documentation which may be more complete?) sudo --preserve-env=PATH -u "$app" "$@"
#
# This helper will read infos from the 'sources' resources in the manifest.toml of the app
# and expect a structure like:
#
# ```toml
# [resources.sources]
# [resources.sources.main]
# url = "https://some.address.to/download/the/app/archive"
# sha256 = "0123456789abcdef" # The sha256 sum of the asset obtained from the URL
# ```
#
# ##### Optional flags
#
# ```text
# format = "tar.gz"/xz/bz2 # automatically guessed from the extension of the URL, but can be set explicitly. Will use `tar` to extract
# "zip" # automatically guessed from the extension of the URL, but can be set explicitly. Will use `unzip` to extract
# "docker" # useful to extract files from an already-built docker image (instead of rebuilding them locally). Will use `docker-image-extract` to extract
# "whatever" # an arbitrary value, not really meaningful except to imply that the file won't be extracted
#
# in_subdir = true # default, there's an intermediate subdir in the archive before accessing the actual files
# false # sources are directly in the archive root
# n # (special cases) an integer representing a number of subdirs levels to get rid of
#
# extract = true # default if file is indeed an archive such as .zip, .tar.gz, .tar.bz2, ...
# = false # default if file 'format' is not set and the file is not to be extracted because it is not an archive but a script or binary or whatever asset.
# # in which case the file will only be `mv`ed to the location possibly renamed using the `rename` value
#
# rename = "whatever_your_want" # to be used for convenience when `extract` is false and the default name of the file is not practical
# platform = "linux/amd64" # (defaults to "linux/$YNH_ARCH") to be used in conjonction with `format = "docker"` to specify which architecture to extract for
# ```
#
# You may also define assets url and checksum per-architectures such as:
# ```toml
# [resources.sources]
# [resources.sources.main]
# amd64.url = "https://some.address.to/download/the/app/archive/when/amd64"
# amd64.sha256 = "0123456789abcdef"
# armhf.url = "https://some.address.to/download/the/app/archive/when/armhf"
# armhf.sha256 = "fedcba9876543210"
# ```
#
# In which case ynh_setup_source --dest_dir="$install_dir" will automatically pick the appropriate source depending on the arch
#
# The helper will:
# - Download the specific URL if there is no local archive
# - Check the integrity with the specific sha256 sum
# - Uncompress the archive to `$dest_dir`.
# - If `in_subdir` is true, the first level directory of the archive will be removed.
# - If `in_subdir` is a numeric value, the N first level directories will be removed.
# - Patches named `patches/${src_id}-*.patch` will be applied to `$dest_dir`
#
# Requires YunoHost version 2.6.4 or higher.
ynh_setup_source() {
# ============ Argument parsing =============
local -A args_array=([d]=dest_dir= [s]=source_id= [k]=keep= [r]=full_replace)
local dest_dir
local source_id
local keep
local full_replace
ynh_handle_getopts_args "$@"
keep="${keep:-}"
full_replace="${full_replace:-0}"
source_id="${source_id:-main}"
# ===========================================
local sources_json=$(ynh_read_manifest "resources.sources[\"$source_id\"]")
if jq -re ".url" <<< "$sources_json"
then
local arch_prefix=""
else
local arch_prefix=".$YNH_ARCH"
fi
local src_url="$(jq -r "$arch_prefix.url" <<< "$sources_json" | sed 's/^null$//')"
local src_sum="$(jq -r "$arch_prefix.sha256" <<< "$sources_json" | sed 's/^null$//')"
local src_sumprg="sha256sum"
local src_format="$(jq -r ".format" <<< "$sources_json" | sed 's/^null$//')"
local src_in_subdir="$(jq -r ".in_subdir" <<< "$sources_json" | sed 's/^null$//')"
src_in_subdir=${src_in_subdir:-true}
local src_extract="$(jq -r ".extract" <<< "$sources_json" | sed 's/^null$//')"
local src_platform="$(jq -r ".platform" <<< "$sources_json" | sed 's/^null$//')"
local src_rename="$(jq -r ".rename" <<< "$sources_json" | sed 's/^null$//')"
[[ -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
src_format="zip"
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
src_format="tar.xz"
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]
then
src_format="tar.bz2"
elif [[ -z "$src_extract" ]]
then
src_extract="false"
fi
fi
src_format=${src_format:-tar.gz}
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
src_extract=${src_extract:-true}
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}"
# Gotta use this trick with 'dirname' because source_id may contain slashes x_x
mkdir -p $(dirname /var/cache/yunohost/download/${YNH_APP_ID}/${source_id})
src_filename="/var/cache/yunohost/download/${YNH_APP_ID}/${source_id}"
if [ "$src_format" = "docker" ]; then
src_platform="${src_platform:-"linux/$YNH_ARCH"}"
else
if test -e "$local_src"; then
cp $local_src $src_filename
fi
[ -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
rm -f "$src_filename"
fi
# Only redownload the file if it wasnt prefetched
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 ...
local out
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
|| ynh_die "$out"
fi
# Check the control sum
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}
ynh_die "Corrupt source for ${src_url}: Expected sha256sum to be ${src_sum} but got ${actual_sum} (size: ${actual_size})."
fi
fi
# Keep files to be backup/restored at the end of the helper
# Assuming $dest_dir already exists
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
if [ -n "$keep" ] && [ -e "$dest_dir" ]; then
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
mkdir -p $keep_dir
local stuff_to_keep
for stuff_to_keep in $keep; do
if [ -e "$dest_dir/$stuff_to_keep" ]; then
mkdir --parents "$(dirname "$keep_dir/$stuff_to_keep")"
cp --archive "$dest_dir/$stuff_to_keep" "$keep_dir/$stuff_to_keep"
fi
done
fi
if [ "$full_replace" -eq 1 ]; then
ynh_safe_rm "$dest_dir"
fi
# Extract source into the app dir
mkdir --parents "$dest_dir"
if [ -n "${install_dir:-}" ] && [ "$dest_dir" == "$install_dir" ]; then
_ynh_apply_default_permissions $dest_dir
fi
if [[ "$src_extract" == "false" ]]; then
if [[ -z "$src_rename" ]]
then
mv $src_filename $dest_dir
else
mv $src_filename $dest_dir/$src_rename
fi
elif [[ "$src_format" == "docker" ]]; then
"$YNH_HELPERS_DIR/vendor/docker-image-extract/docker-image-extract" -p $src_platform -o $dest_dir $src_url 2>&1
elif [[ "$src_format" == "zip" ]]; then
# Zip format
# Using of a temp directory, because unzip doesn't manage --strip-components
if $src_in_subdir; then
local tmp_dir=$(mktemp --directory)
unzip -quo $src_filename -d "$tmp_dir"
cp --archive $tmp_dir/*/. "$dest_dir"
ynh_safe_rm "$tmp_dir"
else
unzip -quo $src_filename -d "$dest_dir"
fi
ynh_safe_rm "$src_filename"
else
local strip=""
if [ "$src_in_subdir" != "false" ]; then
if [ "$src_in_subdir" == "true" ]; then
local sub_dirs=1
else
local sub_dirs="$src_in_subdir"
fi
strip="--strip-components $sub_dirs"
fi
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]]; then
tar --extract --file=$src_filename --directory="$dest_dir" $strip
else
ynh_die "Archive format unrecognized."
fi
ynh_safe_rm "$src_filename"
fi
# Apply patches
if [ -d "$YNH_APP_BASEDIR/patches/" ]; then
local patches_folder=$(realpath $YNH_APP_BASEDIR/patches/)
# Check if any file matching the pattern exists, cf https://stackoverflow.com/a/34195247
if compgen -G "$patches_folder/${source_id}-*.patch" >/dev/null; then
pushd "$dest_dir"
for p in $patches_folder/${source_id}-*.patch; do
echo $p
patch --strip=1 <$p || ynh_print_warn "Packagers /!\\ patch $p failed to apply"
done
popd
fi
fi
# Keep files to be backup/restored at the end of the helper
# Assuming $dest_dir already exists
if [ -n "$keep" ]; then
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
local stuff_to_keep
for stuff_to_keep in $keep; do
if [ -e "$keep_dir/$stuff_to_keep" ]; then
mkdir --parents "$(dirname "$dest_dir/$stuff_to_keep")"
# We add "--no-target-directory" (short option is -T) to handle the special case
# when we "keep" a folder, but then the new setup already contains the same dir (but possibly empty)
# in which case a regular "cp" will create a copy of the directory inside the directory ...
# resulting in something like /var/www/$app/data/data instead of /var/www/$app/data
# cf https://unix.stackexchange.com/q/94831 for a more elaborate explanation on the option
cp --archive --no-target-directory "$keep_dir/$stuff_to_keep" "$dest_dir/$stuff_to_keep"
fi
done
fi
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
} }
# Curl abstraction to help with POST requests to local pages (such as installation forms) # Curl abstraction to help with POST requests to local pages (such as installation forms)
@ -355,8 +72,6 @@ ynh_setup_source() {
# For multiple calls, cookies are persisted between each call for the same app # For multiple calls, cookies are persisted between each call for the same app
# #
# `$domain` and `$path` should be defined externally (and correspond to the domain.tld and the /path (of the app?)) # `$domain` and `$path` should be defined externally (and correspond to the domain.tld and the /path (of the app?))
#
# Requires YunoHost version 2.6.4 or higher.
ynh_local_curl() { ynh_local_curl() {
# Define url of page to curl # Define url of page to curl
local local_page=$(ynh_normalize_url_path $1) local local_page=$(ynh_normalize_url_path $1)
@ -407,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) 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 ... # Legacy : A couple apps still have data in /home/$app ...
if [[ -n "${app:-}" ]] if [[ -n "${app:-}" ]]; then
then
forbidden_paths=$(echo "$forbidden_paths" | grep -v "/home/$app") forbidden_paths=$(echo "$forbidden_paths" | grep -v "/home/$app")
fi fi
@ -425,8 +139,6 @@ _acceptable_path_to_delete() {
# Remove a file or a directory, checking beforehand that it's not a disastrous location to rm such as entire /var or /home # Remove a file or a directory, checking beforehand that it's not a disastrous location to rm such as entire /var or /home
# #
# usage: ynh_safe_rm path_to_remove # usage: ynh_safe_rm path_to_remove
#
# Requires YunoHost version 2.6.4 or higher.
ynh_safe_rm() { ynh_safe_rm() {
local target="$1" local target="$1"
set +o xtrace # set +x set +o xtrace # set +x
@ -437,7 +149,7 @@ ynh_safe_rm() {
if [[ -z "$target" ]]; then if [[ -z "$target" ]]; then
ynh_print_warn "ynh_safe_rm called with empty argument, ignoring." ynh_print_warn "ynh_safe_rm called with empty argument, ignoring."
elif [[ ! -e $target ]]; then elif [[ ! -e "$target" ]] && [[ ! -L "$target" ]]; then
ynh_print_info "'$target' wasn't deleted because it doesn't exist." ynh_print_info "'$target' wasn't deleted because it doesn't exist."
elif ! _acceptable_path_to_delete "$target"; then elif ! _acceptable_path_to_delete "$target"; then
ynh_print_warn "Not deleting '$target' because it is not an acceptable path to delete." ynh_print_warn "Not deleting '$target' because it is not an acceptable path to delete."
@ -453,8 +165,6 @@ ynh_safe_rm() {
# usage: ynh_read_manifest "key" # usage: ynh_read_manifest "key"
# | arg: key - Name of the key to find # | arg: key - Name of the key to find
# | ret: the value associate to that key # | ret: the value associate to that key
#
# Requires YunoHost version 3.5.0 or higher.
ynh_read_manifest() { ynh_read_manifest() {
cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq ".$1" --raw-output cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq ".$1" --raw-output
} }
@ -465,10 +175,8 @@ ynh_read_manifest() {
# | ret: the version number of the upstream app # | ret: the version number of the upstream app
# #
# For example, if the manifest contains `4.3-2~ynh3` the function will return `4.3-2` # For example, if the manifest contains `4.3-2~ynh3` the function will return `4.3-2`
#
# Requires YunoHost version 3.5.0 or higher.
ynh_app_upstream_version() { ynh_app_upstream_version() {
echo "${$YNH_APP_MANIFEST_VERSION/~ynh*/}" echo "${YNH_APP_MANIFEST_VERSION/~ynh*/}"
} }
# Return 0 if the "upstream" part of the version changed, or 1 otherwise (ie only the ~ynh suffix changed) # Return 0 if the "upstream" part of the version changed, or 1 otherwise (ie only the ~ynh suffix changed)
@ -482,8 +190,6 @@ ynh_app_upstream_version_changed() {
# Compare the current package version is strictly lower than another version given as an argument # Compare the current package version is strictly lower than another version given as an argument
# #
# example: if ynh_app_upgrading_from_version_before 2.3.2~ynh1; then ... # example: if ynh_app_upgrading_from_version_before 2.3.2~ynh1; then ...
#
# Requires YunoHost version 11.2 or higher.
ynh_app_upgrading_from_version_before() { ynh_app_upgrading_from_version_before() {
local version=$1 local version=$1
[[ $version =~ '~ynh' ]] || ynh_die "Invalid argument for version, should include the ~ynhX prefix" [[ $version =~ '~ynh' ]] || ynh_die "Invalid argument for version, should include the ~ynhX prefix"
@ -494,8 +200,6 @@ ynh_app_upgrading_from_version_before() {
# Compare the current package version is lower or equal to another version given as an argument # Compare the current package version is lower or equal to another version given as an argument
# #
# example: if ynh_app_upgrading_from_version_before_or_equal_to 2.3.2~ynh1; then ... # example: if ynh_app_upgrading_from_version_before_or_equal_to 2.3.2~ynh1; then ...
#
# Requires YunoHost version 11.2 or higher.
ynh_app_upgrading_from_version_before_or_equal_to() { ynh_app_upgrading_from_version_before_or_equal_to() {
local version=$1 local version=$1
[[ $version =~ '~ynh' ]] || ynh_die "Invalid argument for version, should include the ~ynhX prefix" [[ $version =~ '~ynh' ]] || ynh_die "Invalid argument for version, should include the ~ynhX prefix"
@ -503,41 +207,57 @@ ynh_app_upgrading_from_version_before_or_equal_to() {
dpkg --compare-versions $YNH_APP_CURRENT_VERSION le $version dpkg --compare-versions $YNH_APP_CURRENT_VERSION le $version
} }
# Check if we should enforce sane default permissions (= disable rwx for 'others') # Apply sane permissions for files installed by ynh_setup_source and ynh_config_add.
# on file/folders handled with ynh_setup_source and ynh_config_add
# #
# [internal] # [internal]
# #
# Having a file others-readable or a folder others-executable(=enterable) # * Anything below $install_dir is chown $app:$app and chmod o-rwx,g-w
# is a security risk comparable to "chmod 777" # * The rest is considered as system configuration and chown root, chmod 400
#
# Configuration files may contain secrets. Or even just being able to enter a
# folder may allow an attacker to do nasty stuff (maybe a file or subfolder has
# some write permission enabled for 'other' and the attacker may edit the
# content or create files as leverage for priviledge escalation ...)
#
# The sane default should be to set ownership to $app:$app.
# In specific case, you may want to set the ownership to $app:www-data
# for example if nginx needs access to static files.
# #
_ynh_apply_default_permissions() { _ynh_apply_default_permissions() {
local target=$1 local target=$1
chmod o-rwx $target is_in_dir() {
chmod g-w $target # Returns false if parent is empty
chown -R root:root $target [ -n "$2" ] || return 1
if ynh_system_user_exists --username=$app; then local child=$(realpath "$1" 2> /dev/null)
chown $app:$app $target 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
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
# 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
# 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
group="www-data"
# Or default to "$app"
else
group="$app"
fi
fi
# Files inside should be owned by $app with rw-r----- (+x for folders or files that already have +x)
# The group needs read/dirtraversal (in particular if it's www-data)
chmod -R u=rwX,g=rX,o=--- "$target"
chown -R "$app:$group" "$target"
return
fi
fi fi
# Crons should be owned by root # Other files are considered system
# Also we don't want systemd conf, nginx conf or others stuff to be owned by the app, chmod 400 "$target"
# otherwise they could self-edit their own systemd conf and escalate privilege chown root:root "$target"
if echo "$target" | grep -q '^/etc/cron\|/etc/php\|/etc/nginx/conf.d\|/etc/fail2ban\|/etc/systemd/system'
then
chmod 400 $target
chown root:root $target
fi
} }
int_to_bool() { int_to_bool() {
@ -554,8 +274,6 @@ toml_to_json() {
# | ret: 0 for valid ip addresses, 1 otherwise # | ret: 0 for valid ip addresses, 1 otherwise
# #
# example: ynh_validate_ip 4 111.222.333.444 # example: ynh_validate_ip 4 111.222.333.444
#
# Requires YunoHost version 2.2.4 or higher.
ynh_validate_ip() { ynh_validate_ip() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([f]=family= [i]=ip_address=) local -A args_array=([f]=family= [i]=ip_address=)
@ -567,7 +285,7 @@ ynh_validate_ip() {
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1 [ "$family" == "4" ] || [ "$family" == "6" ] || return 1
# http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298 # http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298
python3 /dev/stdin <<EOF python3 /dev/stdin << EOF
import socket import socket
import sys import sys
family = { "4" : socket.AF_INET, "6" : socket.AF_INET6 } family = { "4" : socket.AF_INET, "6" : socket.AF_INET6 }
@ -584,11 +302,9 @@ EOF
# [packagingv1] # [packagingv1]
# #
# usage: ynh_get_ram [--free|--total] # usage: ynh_get_ram [--free|--total]
# | arg: -f, --free - Count free RAM+swap # | arg: --free - Count free RAM+swap
# | arg: -t, --total - Count total RAM+swap # | arg: --total - Count total RAM+swap
# | ret: the amount of free ram, in MB (MegaBytes) # | ret: the amount of free ram, in MB (MegaBytes)
#
# Requires YunoHost version 3.8.1 or higher.
ynh_get_ram() { ynh_get_ram() {
# ============ Argument parsing ============= # ============ Argument parsing =============
local -A args_array=([f]=free [t]=total) local -A args_array=([f]=free [t]=total)
@ -622,8 +338,246 @@ ynh_get_ram() {
# usage: ynh_in_ci_tests # usage: ynh_in_ci_tests
# #
# Return 0 if in CI, 1 otherwise # Return 0 if in CI, 1 otherwise
#
# Requires YunoHost version 11.3 or higher.
ynh_in_ci_tests() { ynh_in_ci_tests() {
[ "${PACKAGE_CHECK_EXEC:-0}" -eq 1 ] [ "${PACKAGE_CHECK_EXEC:-0}" -eq 1 ]
} }
# Retrieve a YunoHost user information
#
# usage: ynh_user_get_info --username=username --key=key
# | arg: --username= - the username to retrieve info from
# | arg: --key= - the key to retrieve
# | ret: the value associate to that key
#
# example: mail=$(ynh_user_get_info --username="toto" --key=mail)
ynh_user_get_info() {
# ============ Argument parsing =============
local -A args_array=([u]=username= [k]=key=)
local username
local key
ynh_handle_getopts_args "$@"
# ===========================================
yunohost user info "$username" --output-as json --quiet | jq -r ".$key"
}
# Get the list of YunoHost users
#
# usage: ynh_user_list
# | ret: one username per line as strings
#
# example: for u in $(ynh_user_list); do ... ; done
ynh_user_list() {
yunohost user list --output-as json --quiet | jq -r ".users | keys[]"
}
# Spawn a Bash shell with the app environment loaded
#
# usage: ynh_spawn_app_shell "appname"
#
# examples:
# ynh_spawn_app_shell "foobar" <<< 'echo "$USER"'
# ynh_spawn_app_shell "foobar" < /tmp/some_script.bash
#
# The spawned shell will have environment variables loaded and environment files sourced
# 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
# 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 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?)"
# 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
# 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
# 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
# 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
}
# 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")"
}

View file

@ -6,7 +6,7 @@ YNH_CWD="${YNH_BACKUP_DIR%/}/conf/manually_modified_files"
mkdir -p "$YNH_CWD" mkdir -p "$YNH_CWD"
cd "$YNH_CWD" cd "$YNH_CWD"
yunohost tools shell -c "from yunohost.regenconf import manually_modified_files; print('\n'.join(manually_modified_files()))" >./manually_modified_files_list yunohost tools shell -c "from yunohost.regenconf import manually_modified_files; print('\n'.join(manually_modified_files()))" > ./manually_modified_files_list
ynh_backup --src_path="./manually_modified_files_list" ynh_backup --src_path="./manually_modified_files_list"

View file

@ -14,7 +14,7 @@ do_init_regen() {
# set default current_host # set default current_host
[[ -f /etc/yunohost/current_host ]] \ [[ -f /etc/yunohost/current_host ]] \
|| echo "yunohost.org" >/etc/yunohost/current_host || echo "yunohost.org" > /etc/yunohost/current_host
# copy default services and firewall # copy default services and firewall
[[ -f /etc/yunohost/firewall.yml ]] \ [[ -f /etc/yunohost/firewall.yml ]] \
@ -45,7 +45,7 @@ do_init_regen() {
chown root:root /home/yunohost.backup/archives # This is later changed to root:admins once the admins group exists chown root:root /home/yunohost.backup/archives # This is later changed to root:admins once the admins group exists
# Empty ssowat json persistent conf # Empty ssowat json persistent conf
echo "{}" >'/etc/ssowat/conf.json.persistent' echo "{}" > '/etc/ssowat/conf.json.persistent'
chmod 644 /etc/ssowat/conf.json.persistent chmod 644 /etc/ssowat/conf.json.persistent
chown root:root /etc/ssowat/conf.json.persistent chown root:root /etc/ssowat/conf.json.persistent
@ -64,14 +64,17 @@ do_init_regen() {
systemctl enable yunohost-api.service --quiet systemctl enable yunohost-api.service --quiet
systemctl start yunohost-api.service systemctl start yunohost-api.service
# Enable yunoprompt (in particular for installs from ISO where we want this to show on first boot instead of asking for a login/password)
systemctl enable yunoprompt --quiet
# Yunohost-firewall is enabled only during postinstall, not init, not 100% sure why # Yunohost-firewall is enabled only during postinstall, not init, not 100% sure why
cp dpkg-origins /etc/dpkg/origins/yunohost cp dpkg-origins /etc/dpkg/origins/yunohost
# Change dpkg vendor # Change dpkg vendor
# see https://wiki.debian.org/Derivatives/Guidelines#Vendor # see https://wiki.debian.org/Derivatives/Guidelines#Vendor
if readlink -f /etc/dpkg/origins/default | grep -q debian; if readlink -f /etc/dpkg/origins/default | grep -q debian; then
then
rm -f /etc/dpkg/origins/default rm -f /etc/dpkg/origins/default
ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default
fi fi
@ -89,19 +92,19 @@ do_pre_regen() {
# add cron job for diagnosis to be ran at 7h and 19h + a random delay between # add cron job for diagnosis to be ran at 7h and 19h + a random delay between
# 0 and 20min, meant to avoid every instances running their diagnosis at # 0 and 20min, meant to avoid every instances running their diagnosis at
# exactly the same time, which may overload the diagnosis server. # exactly the same time, which may overload the diagnosis server.
cat >$pending_dir/etc/cron.d/yunohost-diagnosis <<EOF cat > $pending_dir/etc/cron.d/yunohost-diagnosis << EOF
SHELL=/bin/bash SHELL=/bin/bash
0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably" 0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably"
EOF EOF
# Cron job that upgrade the app list everyday # Cron job that upgrade the app list everyday
cat >$pending_dir/etc/cron.daily/yunohost-fetch-apps-catalog <<EOF cat > $pending_dir/etc/cron.daily/yunohost-fetch-apps-catalog << EOF
#!/bin/bash #!/bin/bash
sleep \$((RANDOM%3600)); yunohost tools update apps > /dev/null sleep \$((RANDOM%3600)); yunohost tools update apps > /dev/null
EOF EOF
# Cron job that renew lets encrypt certificates if there's any that needs renewal # Cron job that renew lets encrypt certificates if there's any that needs renewal
cat >$pending_dir/etc/cron.daily/yunohost-certificate-renew <<EOF cat > $pending_dir/etc/cron.daily/yunohost-certificate-renew << EOF
#!/bin/bash #!/bin/bash
yunohost domain cert renew --email yunohost domain cert renew --email
EOF EOF
@ -109,8 +112,8 @@ EOF
# If we subscribed to a dyndns domain, add the corresponding cron # If we subscribed to a dyndns domain, add the corresponding cron
# - delay between 0 and 60 secs to spread the check over a 1 min window # - delay between 0 and 60 secs to spread the check over a 1 min window
# - do not run the command if some process already has the lock, to avoid queuing hundreds of commands... # - do not run the command if some process already has the lock, to avoid queuing hundreds of commands...
if ls -l /etc/yunohost/dyndns/K*.key 2>/dev/null; then if ls -l /etc/yunohost/dyndns/K*.key 2> /dev/null; then
cat >$pending_dir/etc/cron.d/yunohost-dyndns <<EOF cat > $pending_dir/etc/cron.d/yunohost-dyndns << EOF
SHELL=/bin/bash SHELL=/bin/bash
# Every 10 minutes, # Every 10 minutes,
# - (sleep random 60 is here to spread requests over a 1-min window) # - (sleep random 60 is here to spread requests over a 1-min window)
@ -125,10 +128,9 @@ EOF
fi fi
# Skip ntp if inside a container (inspired from the conf of systemd-timesyncd) # Skip ntp if inside a container (inspired from the conf of systemd-timesyncd)
if systemctl | grep -q 'ntp.service' if systemctl | grep -q 'ntp.service'; then
then
mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/ mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/
cat >${pending_dir}/etc/systemd/system/ntp.service.d/ynh-override.conf <<EOF cat > ${pending_dir}/etc/systemd/system/ntp.service.d/ynh-override.conf << EOF
[Unit] [Unit]
ConditionCapability=CAP_SYS_TIME ConditionCapability=CAP_SYS_TIME
ConditionVirtualization=!container ConditionVirtualization=!container
@ -137,7 +139,7 @@ EOF
# Make nftable conflict with yunohost-firewall # Make nftable conflict with yunohost-firewall
mkdir -p ${pending_dir}/etc/systemd/system/nftables.service.d/ mkdir -p ${pending_dir}/etc/systemd/system/nftables.service.d/
cat >${pending_dir}/etc/systemd/system/nftables.service.d/ynh-override.conf <<EOF cat > ${pending_dir}/etc/systemd/system/nftables.service.d/ynh-override.conf << EOF
[Unit] [Unit]
# yunohost-firewall and nftables conflict with each other # yunohost-firewall and nftables conflict with each other
Conflicts=yunohost-firewall.service Conflicts=yunohost-firewall.service
@ -147,7 +149,7 @@ EOF
# Don't suspend computer on LidSwitch # Don't suspend computer on LidSwitch
mkdir -p ${pending_dir}/etc/systemd/logind.conf.d/ mkdir -p ${pending_dir}/etc/systemd/logind.conf.d/
cat >${pending_dir}/etc/systemd/logind.conf.d/ynh-override.conf <<EOF cat > ${pending_dir}/etc/systemd/logind.conf.d/ynh-override.conf << EOF
[Login] [Login]
HandleLidSwitch=ignore HandleLidSwitch=ignore
HandleLidSwitchDocked=ignore HandleLidSwitchDocked=ignore
@ -188,8 +190,7 @@ do_post_regen() {
find /etc/systemd/system/*.service -type f | xargs -r chown root:root find /etc/systemd/system/*.service -type f | xargs -r chown root:root
find /etc/systemd/system/*.service -type f | xargs -r chmod 0644 find /etc/systemd/system/*.service -type f | xargs -r chmod 0644
if ls -l /etc/php/*/fpm/pool.d/*.conf if ls -l /etc/php/*/fpm/pool.d/*.conf; then
then
chown root:root /etc/php/*/fpm/pool.d/*.conf chown root:root /etc/php/*/fpm/pool.d/*.conf
chmod 644 /etc/php/*/fpm/pool.d/*.conf chmod 644 /etc/php/*/fpm/pool.d/*.conf
fi fi
@ -218,8 +219,8 @@ do_post_regen() {
mkdir -p /etc/yunohost/domains mkdir -p /etc/yunohost/domains
# Misc configuration / state files # Misc configuration / state files
chown root:root $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null | grep -vw mdns.yml) chown root:root $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2> /dev/null | grep -vw mdns.yml)
chmod 600 $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null) chmod 600 $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2> /dev/null)
# Apps folder, custom hooks folder # Apps folder, custom hooks folder
[[ ! -e /etc/yunohost/hooks.d ]] || (chown root /etc/yunohost/hooks.d && chmod 700 /etc/yunohost/hooks.d) [[ ! -e /etc/yunohost/hooks.d ]] || (chown root /etc/yunohost/hooks.d && chmod 700 /etc/yunohost/hooks.d)
@ -231,15 +232,14 @@ do_post_regen() {
grep -q '^sftp.app:' /etc/group || groupadd sftp.app grep -q '^sftp.app:' /etc/group || groupadd sftp.app
# Propagates changes in systemd service config overrides # Propagates changes in systemd service config overrides
if systemctl | grep -q 'ntp.service' if systemctl | grep -q 'ntp.service'; then
then
[[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || { [[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || {
systemctl daemon-reload systemctl daemon-reload
systemctl restart ntp systemctl restart ntp
} }
fi fi
[[ ! "$regen_conf_files" =~ "nftables.service.d/ynh-override.conf" ]] || systemctl daemon-reload [[ ! "$regen_conf_files" =~ "nftables.service.d/ynh-override.conf" ]] || systemctl daemon-reload
[[ ! "$regen_conf_files" =~ "login.conf.d/ynh-override.conf" ]] || { [[ ! "$regen_conf_files" =~ "login.conf.d/ynh-override.conf" ]] || {
systemctl daemon-reload systemctl daemon-reload
systemctl restart systemd-logind systemctl restart systemd-logind
} }
@ -259,14 +259,12 @@ do_post_regen() {
# Change dpkg vendor # Change dpkg vendor
# see https://wiki.debian.org/Derivatives/Guidelines#Vendor # see https://wiki.debian.org/Derivatives/Guidelines#Vendor
if readlink -f /etc/dpkg/origins/default | grep -q debian; if readlink -f /etc/dpkg/origins/default | grep -q debian; then
then
rm -f /etc/dpkg/origins/default rm -f /etc/dpkg/origins/default
ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default
fi fi
if test -e /etc/yunohost/installed && test -e /etc/profile.d/check_yunohost_is_installed.sh if test -e /etc/yunohost/installed && test -e /etc/profile.d/check_yunohost_is_installed.sh; then
then
rm /etc/profile.d/check_yunohost_is_installed.sh rm /etc/profile.d/check_yunohost_is_installed.sh
fi fi
} }

View file

@ -3,7 +3,7 @@
set -e set -e
ssl_dir="/usr/share/yunohost/ssl" ssl_dir="/usr/share/yunohost/ssl"
template_dir="/usr/share/yunohost/conf/ssl/" template_dir="/usr/share/yunohost/conf/ssl"
ynh_ca="/etc/yunohost/certs/yunohost.org/ca.pem" ynh_ca="/etc/yunohost/certs/yunohost.org/ca.pem"
ynh_crt="/etc/yunohost/certs/yunohost.org/crt.pem" ynh_crt="/etc/yunohost/certs/yunohost.org/crt.pem"
ynh_key="/etc/yunohost/certs/yunohost.org/key.pem" ynh_key="/etc/yunohost/certs/yunohost.org/key.pem"
@ -23,7 +23,7 @@ regen_local_ca() {
# (Update the serial so that it's specific to this very instance) # (Update the serial so that it's specific to this very instance)
# N.B. : the weird RANDFILE thing comes from: # N.B. : the weird RANDFILE thing comes from:
# https://stackoverflow.com/questions/94445/using-openssl-what-does-unable-to-write-random-state-mean # https://stackoverflow.com/questions/94445/using-openssl-what-does-unable-to-write-random-state-mean
RANDFILE=.rnd openssl rand -hex 19 >serial RANDFILE=.rnd openssl rand -hex 19 > serial
rm -f index.txt rm -f index.txt
touch index.txt touch index.txt
cp ${template_dir}/openssl.cnf openssl.ca.cnf cp ${template_dir}/openssl.cnf openssl.ca.cnf
@ -51,7 +51,7 @@ regen_local_ca() {
do_init_regen() { do_init_regen() {
LOGFILE=/tmp/yunohost-ssl-init LOGFILE=/tmp/yunohost-ssl-init
echo "" >$LOGFILE echo "" > $LOGFILE
chown root:root $LOGFILE chown root:root $LOGFILE
chmod 640 $LOGFILE chmod 640 $LOGFILE
@ -61,24 +61,24 @@ do_init_regen() {
# create default certificates # create default certificates
if [[ ! -f "$ynh_ca" ]]; then if [[ ! -f "$ynh_ca" ]]; then
regen_local_ca yunohost.org >>$LOGFILE regen_local_ca yunohost.org >> $LOGFILE
fi fi
if [[ ! -f "$ynh_crt" ]]; then if [[ ! -f "$ynh_crt" ]]; then
echo -e "\n# Creating initial key and certificate \n" >>$LOGFILE echo -e "\n# Creating initial key and certificate \n" >> $LOGFILE
openssl req -new \ openssl req -new \
-config "${ssl_dir}/openssl.cnf" \ -config "${ssl_dir}/openssl.cnf" \
-out "${ssl_dir}/certs/yunohost_csr.pem" \ -out "${ssl_dir}/certs/yunohost_csr.pem" \
-keyout "${ssl_dir}/certs/yunohost_key.pem" \ -keyout "${ssl_dir}/certs/yunohost_key.pem" \
-nodes -batch &>>$LOGFILE -nodes -batch &>> $LOGFILE
openssl ca \ openssl ca \
-config "${ssl_dir}/openssl.cnf" \ -config "${ssl_dir}/openssl.cnf" \
-days 730 \ -days 730 \
-in "${ssl_dir}/certs/yunohost_csr.pem" \ -in "${ssl_dir}/certs/yunohost_csr.pem" \
-out "${ssl_dir}/certs/yunohost_crt.pem" \ -out "${ssl_dir}/certs/yunohost_crt.pem" \
-batch &>>$LOGFILE -batch &>> $LOGFILE
chmod 640 "${ssl_dir}/certs/yunohost_key.pem" chmod 640 "${ssl_dir}/certs/yunohost_key.pem"
chmod 640 "${ssl_dir}/certs/yunohost_crt.pem" chmod 640 "${ssl_dir}/certs/yunohost_crt.pem"
@ -104,10 +104,9 @@ do_post_regen() {
current_local_ca_domain=$(openssl x509 -in $ynh_ca -text | tr ',' '\n' | grep Issuer | awk '{print $4}') current_local_ca_domain=$(openssl x509 -in $ynh_ca -text | tr ',' '\n' | grep Issuer | awk '{print $4}')
main_domain=$(cat /etc/yunohost/current_host) main_domain=$(cat /etc/yunohost/current_host)
# Automigrate legacy folder # Automigrate legacy folder
if [ -e /usr/share/yunohost/yunohost-config/ssl/yunoCA ] if [ -e /usr/share/yunohost/yunohost-config/ssl/yunoCA ]; then
then
mv /usr/share/yunohost/yunohost-config/ssl/yunoCA/* ${ssl_dir} mv /usr/share/yunohost/yunohost-config/ssl/yunoCA/* ${ssl_dir}
rm -rf /usr/share/yunohost/yunohost-config rm -rf /usr/share/yunohost/yunohost-config
# Overwrite openssl.cnf because it may still contain references to the old yunoCA dir # Overwrite openssl.cnf because it may still contain references to the old yunoCA dir
@ -120,7 +119,7 @@ do_post_regen() {
chown root:root ${ssl_dir} chown root:root ${ssl_dir}
chmod 750 ${ssl_dir} chmod 750 ${ssl_dir}
chmod -R o-rwx ${ssl_dir} chmod -R o-rwx ${ssl_dir}
chmod o+x ${ssl_dir}/certs chmod o+x ${ssl_dir}/certs
chmod o+r ${ssl_dir}/certs/yunohost_crt.pem chmod o+r ${ssl_dir}/certs/yunohost_crt.pem
if [[ "$current_local_ca_domain" != "$main_domain" ]]; then if [[ "$current_local_ca_domain" != "$main_domain" ]]; then

View file

@ -12,7 +12,7 @@ do_pre_regen() {
# do not listen to IPv6 if unavailable # do not listen to IPv6 if unavailable
[[ -f /proc/net/if_inet6 ]] && ipv6_enabled=true || ipv6_enabled=false [[ -f /proc/net/if_inet6 ]] && ipv6_enabled=true || ipv6_enabled=false
ssh_keys=$(ls /etc/ssh/ssh_host_{ed25519,rsa,ecdsa}_key 2>/dev/null || true) ssh_keys=$(ls /etc/ssh/ssh_host_{ed25519,rsa,ecdsa}_key 2> /dev/null || true)
# Support different strategy for security configurations # Support different strategy for security configurations
export compatibility="$(yunohost settings get 'security.ssh.ssh_compatibility')" export compatibility="$(yunohost settings get 'security.ssh.ssh_compatibility')"

View file

@ -20,7 +20,7 @@ do_init_regen() {
rm -rf /var/backups/*.ldapdb rm -rf /var/backups/*.ldapdb
rm -rf /var/backups/slapd-* rm -rf /var/backups/slapd-*
debconf-set-selections <<EOF debconf-set-selections << EOF
slapd slapd/password1 password yunohost slapd slapd/password1 password yunohost
slapd slapd/password2 password yunohost slapd slapd/password2 password yunohost
slapd slapd/domain string yunohost.org slapd slapd/domain string yunohost.org
@ -87,13 +87,13 @@ do_pre_regen() {
rm -f "$tmp_backup_dir_file" rm -f "$tmp_backup_dir_file"
# Define if we need to migrate from hdb to mdb # Define if we need to migrate from hdb to mdb
curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2>/dev/null | awk '{print $2}') curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2> /dev/null | awk '{print $2}')
if [ -e /etc/ldap/slapd.conf ] && [ -n "$curr_backend" ] \ if [ -e /etc/ldap/slapd.conf ] && [ -n "$curr_backend" ] \
&& [ $curr_backend != 'mdb' ]; then && [ $curr_backend != 'mdb' ]; then
backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)" backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)"
mkdir -p "$backup_dir" mkdir -p "$backup_dir"
slapcat -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif" slapcat -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif"
echo "$backup_dir" >"$tmp_backup_dir_file" echo "$backup_dir" > "$tmp_backup_dir_file"
fi fi
# create needed directories # create needed directories
@ -155,7 +155,7 @@ objectClass: top"
_regenerate_slapd_conf _regenerate_slapd_conf
# If there's a backup, re-import its data # If there's a backup, re-import its data
backup_dir=$(cat "$tmp_backup_dir_file" 2>/dev/null || true) backup_dir=$(cat "$tmp_backup_dir_file" 2> /dev/null || true)
if [[ -n "$backup_dir" && -f "${backup_dir}/dc=yunohost-dc=org.ldif" ]]; then if [[ -n "$backup_dir" && -f "${backup_dir}/dc=yunohost-dc=org.ldif" ]]; then
# regenerate LDAP config directory and import database as root # regenerate LDAP config directory and import database as root
echo "Import the database using slapadd" echo "Import the database using slapadd"

View file

@ -17,14 +17,14 @@ do_pre_regen() {
echo " echo "
Package: php-common Package: php-common
Pin: origin \"packages.sury.org\" Pin: origin \"packages.sury.org\"
Pin-Priority: 500" >>"${pending_dir}/etc/apt/preferences.d/extra_php_version" Pin-Priority: 500" >> "${pending_dir}/etc/apt/preferences.d/extra_php_version"
packages_to_refuse_from_sury="php php-* openssl libssl1.1 libssl-dev" packages_to_refuse_from_sury="php php-* openssl libssl1.1 libssl-dev"
for package in $packages_to_refuse_from_sury; do for package in $packages_to_refuse_from_sury; do
echo " echo "
Package: $package Package: $package
Pin: origin \"packages.sury.org\" Pin: origin \"packages.sury.org\"
Pin-Priority: -1" >>"${pending_dir}/etc/apt/preferences.d/extra_php_version" Pin-Priority: -1" >> "${pending_dir}/etc/apt/preferences.d/extra_php_version"
done done
echo " echo "
@ -54,8 +54,7 @@ Pin-Priority: -1
Package: bind9 Package: bind9
Pin: release * Pin: release *
Pin-Priority: -1 Pin-Priority: -1
" >>"${pending_dir}/etc/apt/preferences.d/ban_packages" " >> "${pending_dir}/etc/apt/preferences.d/ban_packages"
} }
@ -63,19 +62,17 @@ do_post_regen() {
regen_conf_files=$1 regen_conf_files=$1
# Purge expired keys (such as sury 95BD4743) # Purge expired keys (such as sury 95BD4743)
EXPIRED_KEYS="$(LC_ALL='en_US.UTF-8' apt-key list 2>/dev/null | grep -A1 'expired:' | grep -v 'expired\|^-' | sed 's/\s//g')" EXPIRED_KEYS="$(LC_ALL='en_US.UTF-8' apt-key list 2> /dev/null | grep -A1 'expired:' | grep -v 'expired\|^-' | sed 's/\s//g')"
for KEY in $EXPIRED_KEYS; do apt-key del $KEY 2>/dev/null; done for KEY in $EXPIRED_KEYS; do apt-key del $KEY 2> /dev/null; done
# Add sury key # Add sury key
# We do this only at the post regen and if the key doesn't already exists, because we don't want the regenconf to fuck everything up if the regenconf runs while the network is down # We do this only at the post regen and if the key doesn't already exists, because we don't want the regenconf to fuck everything up if the regenconf runs while the network is down
if [[ ! -s /etc/apt/trusted.gpg.d/extra_php_version.gpg ]] if [[ ! -s /etc/apt/trusted.gpg.d/extra_php_version.gpg ]]; then
then wget --timeout 900 --quiet "https://packages.sury.org/php/apt.gpg" --output-document=- | gpg --dearmor > "/etc/apt/trusted.gpg.d/extra_php_version.gpg"
wget --timeout 900 --quiet "https://packages.sury.org/php/apt.gpg" --output-document=- | gpg --dearmor >"/etc/apt/trusted.gpg.d/extra_php_version.gpg"
fi fi
# Make sure php7.4 is the default version when using php in cli # Make sure php7.4 is the default version when using php in cli
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
then
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
fi fi
} }

View file

@ -2,8 +2,7 @@
set -e set -e
if ! dpkg --list | grep -q 'ii *metronome ' if ! dpkg --list | grep -q 'ii *metronome '; then
then
echo 'metronome is not installed, skipping' echo 'metronome is not installed, skipping'
exit 0 exit 0
fi fi
@ -24,7 +23,7 @@ do_pre_regen() {
# install main conf file # install main conf file
cat metronome.cfg.lua \ cat metronome.cfg.lua \
| sed "s/{{ main_domain }}/${main_domain}/g" \ | sed "s/{{ main_domain }}/${main_domain}/g" \
>"${metronome_dir}/metronome.cfg.lua" > "${metronome_dir}/metronome.cfg.lua"
# Trick such that old conf files are flagged as to remove # Trick such that old conf files are flagged as to remove
for domain in $YNH_DOMAINS; do for domain in $YNH_DOMAINS; do
@ -36,7 +35,7 @@ do_pre_regen() {
for domain in $domain_list; do for domain in $domain_list; do
cat domain.tpl.cfg.lua \ cat domain.tpl.cfg.lua \
| sed "s/{{ domain }}/${domain}/g" \ | sed "s/{{ domain }}/${domain}/g" \
>"${metronome_conf_dir}/${domain}.cfg.lua" > "${metronome_conf_dir}/${domain}.cfg.lua"
done done
# remove old domain conf files # remove old domain conf files
@ -74,16 +73,13 @@ do_post_regen() {
chown -R metronome: /var/lib/metronome/ chown -R metronome: /var/lib/metronome/
chown -R metronome: /etc/metronome/conf.d/ chown -R metronome: /etc/metronome/conf.d/
if [[ -z "$(ls /etc/metronome/conf.d/*.cfg.lua 2>/dev/null)" ]] if [[ -z "$(ls /etc/metronome/conf.d/*.cfg.lua 2> /dev/null)" ]]; then
then if systemctl is-enabled metronome &> /dev/null; then
if systemctl is-enabled metronome &>/dev/null systemctl disable metronome --now 2> /dev/null
then
systemctl disable metronome --now 2>/dev/null
fi fi
else else
if ! systemctl is-enabled metronome &>/dev/null if ! systemctl is-enabled metronome &> /dev/null; then
then systemctl enable metronome --now 2> /dev/null
systemctl enable metronome --now 2>/dev/null
sleep 3 sleep 3
fi fi

View file

@ -32,7 +32,7 @@ do_init_regen() {
cp "redirect_to_admin.conf" $nginx_conf_dir/default.d/ cp "redirect_to_admin.conf" $nginx_conf_dir/default.d/
# Restart nginx if conf looks good, otherwise display error and exit unhappy # Restart nginx if conf looks good, otherwise display error and exit unhappy
nginx -t 2>/dev/null || { nginx -t 2> /dev/null || {
nginx -t nginx -t
exit 1 exit 1
} }
@ -58,7 +58,7 @@ do_pre_regen() {
# remove the panel overlay if this is specified in settings # remove the panel overlay if this is specified in settings
panel_overlay=$(yunohost settings get 'misc.portal.ssowat_panel_overlay_enabled' | int_to_bool) panel_overlay=$(yunohost settings get 'misc.portal.ssowat_panel_overlay_enabled' | int_to_bool)
if [ "$panel_overlay" == "False" ]; then if [ "$panel_overlay" == "False" ]; then
echo "#" >"${nginx_conf_dir}/yunohost_panel.conf.inc" echo "#" > "${nginx_conf_dir}/yunohost_panel.conf.inc"
fi fi
# retrieve variables # retrieve variables
@ -86,22 +86,19 @@ do_pre_regen() {
export domain_cert_ca=$(echo $cert_status \ export domain_cert_ca=$(echo $cert_status \
| jq ".certificates.\"$domain\".CA_type" \ | jq ".certificates.\"$domain\".CA_type" \
| tr -d '"') | tr -d '"')
if echo "$xmpp_domain_list" | grep -q "^$domain$" if echo "$xmpp_domain_list" | grep -q "^$domain$"; then
then
export xmpp_enabled="True" export xmpp_enabled="True"
else else
export xmpp_enabled="False" export xmpp_enabled="False"
fi fi
if echo "$mail_domain_list" | grep -q "^$domain$" if echo "$mail_domain_list" | grep -q "^$domain$"; then
then
export mail_enabled="True" export mail_enabled="True"
else else
export mail_enabled="False" export mail_enabled="False"
fi fi
ynh_render_template "server.tpl.conf" "${nginx_conf_dir}/${domain}.conf" ynh_render_template "server.tpl.conf" "${nginx_conf_dir}/${domain}.conf"
if [ $mail_enabled == "True" ] if [ $mail_enabled == "True" ]; then
then
ynh_render_template "autoconfig.tpl.xml" "${mail_autoconfig_dir}/config-v1.1.xml" ynh_render_template "autoconfig.tpl.xml" "${mail_autoconfig_dir}/config-v1.1.xml"
fi fi
@ -129,7 +126,7 @@ do_pre_regen() {
done done
# remove old mail-autoconfig files # remove old mail-autoconfig files
autoconfig_files=$(ls -1 /var/www/.well-known/*/autoconfig/mail/config-v1.1.xml 2>/dev/null || true) autoconfig_files=$(ls -1 /var/www/.well-known/*/autoconfig/mail/config-v1.1.xml 2> /dev/null || true)
for file in $autoconfig_files; do for file in $autoconfig_files; do
domain=$(basename $(readlink -f $(dirname $file)/../..)) domain=$(basename $(readlink -f $(dirname $file)/../..))
[[ $YNH_DOMAINS =~ $domain ]] \ [[ $YNH_DOMAINS =~ $domain ]] \
@ -144,8 +141,7 @@ do_pre_regen() {
do_post_regen() { do_post_regen() {
regen_conf_files=$1 regen_conf_files=$1
if ls -l /etc/nginx/conf.d/*.d/*.conf if ls -l /etc/nginx/conf.d/*.d/*.conf; then
then
chown root:root /etc/nginx/conf.d/*.d/*.conf chown root:root /etc/nginx/conf.d/*.d/*.conf
chmod 644 /etc/nginx/conf.d/*.d/*.conf chmod 644 /etc/nginx/conf.d/*.d/*.conf
fi fi
@ -158,7 +154,7 @@ do_post_regen() {
done done
# Reload nginx if conf looks good, otherwise display error and exit unhappy # Reload nginx if conf looks good, otherwise display error and exit unhappy
nginx -t 2>/dev/null || { nginx -t 2> /dev/null || {
nginx -t nginx -t
exit 1 exit 1
} }

View file

@ -43,8 +43,21 @@ do_pre_regen() {
chown postfix ${pending_dir}/etc/postfix chown postfix ${pending_dir}/etc/postfix
chown postfix ${pending_dir}/etc/postfix/sasl_passwd chown postfix ${pending_dir}/etc/postfix/sasl_passwd
cat <<<"[${relay_host}]:${relay_port} ${relay_user}:${relay_password}" >${postfix_dir}/sasl_passwd cat <<< "[${relay_host}]:${relay_port} ${relay_user}:${relay_password}" > ${postfix_dir}/sasl_passwd
fi fi
# Use this postfix server as a backup MX
export backup_mx_domains="$(yunohost settings get 'email.smtp.smtp_backup_mx_domains' | sed "s/,/ /g")"
export backup_mx_emails="$(yunohost settings get 'email.smtp.smtp_backup_mx_emails_whitelisted' | sed "s/,/ /g")"
rm -f ${postfix_dir}/relay_recipients
touch ${postfix_dir}/relay_recipients
if [ -n "${backup_mx_domains}" ] && [ -n "${backup_mx_emails}" ]; then
for mail in ${backup_mx_emails}; do
echo "$mail OK" >> ${postfix_dir}/relay_recipients
done
postmap ${postfix_dir}/relay_recipients
fi
export main_domain export main_domain
export domain_list="$(yunohost domain list --features mail_in mail_out --output-as json | jq -r ".domains[]" | tr '\n' ' ')" export domain_list="$(yunohost domain list --features mail_in mail_out --output-as json | jq -r ".domains[]" | tr '\n' ' ')"
ynh_render_template "main.cf" "${postfix_dir}/main.cf" ynh_render_template "main.cf" "${postfix_dir}/main.cf"
@ -53,7 +66,7 @@ do_pre_regen() {
cat postsrsd \ cat postsrsd \
| sed "s/{{ main_domain }}/${main_domain}/g" \ | sed "s/{{ main_domain }}/${main_domain}/g" \
| sed "s/{{ domain_list }}/${domain_list}/g" \ | sed "s/{{ domain_list }}/${domain_list}/g" \
>"${default_dir}/postsrsd" > "${default_dir}/postsrsd"
# adapt it for IPv4-only hosts # adapt it for IPv4-only hosts
ipv6="$(yunohost settings get 'email.smtp.smtp_allow_ipv6' | int_to_bool)" ipv6="$(yunohost settings get 'email.smtp.smtp_allow_ipv6' | int_to_bool)"
@ -78,6 +91,11 @@ do_post_regen() {
postmap /etc/postfix/sasl_passwd postmap /etc/postfix/sasl_passwd
fi fi
if [ -e /etc/postfix/relay_recipients ]; then
chmod 750 /etc/postfix/relay_recipients*
chown postfix:root /etc/postfix/relay_recipients*
fi
postmap -F hash:/etc/postfix/sni postmap -F hash:/etc/postfix/sni
python3 -c 'from yunohost.app import regen_mail_app_user_config_for_dovecot_and_postfix as r; r(only="postfix")' python3 -c 'from yunohost.app import regen_mail_app_user_config_for_dovecot_and_postfix as r; r(only="postfix")'

View file

@ -41,7 +41,7 @@ do_post_regen() {
mkdir -p "/etc/dovecot/yunohost.d/post-ext.d" mkdir -p "/etc/dovecot/yunohost.d/post-ext.d"
# create vmail user # create vmail user
id vmail >/dev/null 2>&1 \ id vmail > /dev/null 2>&1 \
|| adduser --system --ingroup mail --uid 500 vmail --home /var/vmail --no-create-home || adduser --system --ingroup mail --uid 500 vmail --home /var/vmail --no-create-home
# Delete legacy home for vmail that existed in the past but was empty, poluting /home/ # Delete legacy home for vmail that existed in the past but was empty, poluting /home/

View file

@ -13,8 +13,8 @@ do_pre_regen() {
"${pending_dir}/etc/rspamd/local.d/dkim_signing.conf" "${pending_dir}/etc/rspamd/local.d/dkim_signing.conf"
install -D -m 644 rspamd.sieve \ install -D -m 644 rspamd.sieve \
"${pending_dir}/etc/dovecot/global_script/rspamd.sieve" "${pending_dir}/etc/dovecot/global_script/rspamd.sieve"
install -D -m 644 redis.conf \ install -D -m 644 redis.conf \
"${pending_dir}/etc/rspamd/local.d/redis.conf" "${pending_dir}/etc/rspamd/local.d/redis.conf"
} }
do_post_regen() { do_post_regen() {

View file

@ -3,8 +3,7 @@
set -e set -e
. /usr/share/yunohost/helpers . /usr/share/yunohost/helpers
if ! dpkg --list | grep -q 'ii *mariadb-server ' if ! dpkg --list | grep -q 'ii *mariadb-server '; then
then
echo 'mysql/mariadb is not installed, skipping' echo 'mysql/mariadb is not installed, skipping'
exit 0 exit 0
fi fi

View file

@ -3,42 +3,42 @@
set -e set -e
. /usr/share/yunohost/helpers . /usr/share/yunohost/helpers
if ! dpkg --list | grep -q "ii *postgresql-$PSQL_VERSION " if ! dpkg --list | grep -q "ii *postgresql-$PSQL_VERSION "; then
then
echo 'postgresql is not installed, skipping' echo 'postgresql is not installed, skipping'
exit 0 exit 0
fi fi
if [ ! -e "/etc/postgresql/$PSQL_VERSION" ] if [ ! -e "/etc/postgresql/$PSQL_VERSION" ]; then
then
ynh_die --message="It looks like postgresql was not properly configured ? /etc/postgresql/$PSQL_VERSION is missing ... Could be due to a locale issue, c.f.https://serverfault.com/questions/426989/postgresql-etc-postgresql-doesnt-exist" ynh_die --message="It looks like postgresql was not properly configured ? /etc/postgresql/$PSQL_VERSION is missing ... Could be due to a locale issue, c.f.https://serverfault.com/questions/426989/postgresql-etc-postgresql-doesnt-exist"
fi fi
do_pre_regen() { do_pre_regen() {
return 0 return 0
} }
do_post_regen() { do_post_regen() {
#regen_conf_files=$1 #regen_conf_files=$1
# Make sure postgresql is started and enabled # Make sure postgresql is started and enabled
# (N.B. : to check the active state, we check the cluster state because # (N.B. : to check the active state, we check the cluster state because
# postgresql could be flagged as active even though the cluster is in # postgresql could be flagged as active even though the cluster is in
# failed state because of how the service is configured..) # failed state because of how the service is configured..)
systemctl is-active postgresql@$PSQL_VERSION-main -q || ynh_systemd_action --service_name=postgresql --action=restart systemctl is-active postgresql@$PSQL_VERSION-main -q || ynh_systemd_action --service_name=postgresql --action=restart
systemctl is-enabled postgresql -q || systemctl enable postgresql --quiet systemctl is-enabled postgresql -q || systemctl enable postgresql --quiet
# If this is the very first time, we define the root password # If this is the very first time, we define the root password
# and configure a few things # and configure a few things
if [ ! -f "$PSQL_ROOT_PWD_FILE" ] || [ -z "$(cat $PSQL_ROOT_PWD_FILE)" ]; then if [ ! -f "$PSQL_ROOT_PWD_FILE" ] || [ -z "$(cat $PSQL_ROOT_PWD_FILE)" ]; then
ynh_string_random >$PSQL_ROOT_PWD_FILE ynh_string_random > $PSQL_ROOT_PWD_FILE
fi fi
[ ! -e $PSQL_ROOT_PWD_FILE ] || { chown root:postgres $PSQL_ROOT_PWD_FILE; chmod 440 $PSQL_ROOT_PWD_FILE; } [ ! -e $PSQL_ROOT_PWD_FILE ] || {
chown root:postgres $PSQL_ROOT_PWD_FILE
chmod 440 $PSQL_ROOT_PWD_FILE
}
sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$(cat $PSQL_ROOT_PWD_FILE)'" postgres sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$(cat $PSQL_ROOT_PWD_FILE)'" postgres
# force all user to connect to local databases using hashed passwords # force all user to connect to local databases using hashed passwords
# https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF # https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF
# Note: we can't use peer since YunoHost create users with nologin # Note: we can't use peer since YunoHost create users with nologin

View file

@ -5,8 +5,7 @@ set -e
_generate_config() { _generate_config() {
echo "domains:" echo "domains:"
# Add yunohost.local (only if yunohost.local ain't already in ynh_domains) # Add yunohost.local (only if yunohost.local ain't already in ynh_domains)
if ! echo "$YNH_DOMAINS" | tr ' ' '\n' | grep -q --line-regexp 'yunohost.local' if ! echo "$YNH_DOMAINS" | tr ' ' '\n' | grep -q --line-regexp 'yunohost.local'; then
then
echo " - yunohost.local" echo " - yunohost.local"
fi fi
for domain in $YNH_DOMAINS; do for domain in $YNH_DOMAINS; do
@ -15,10 +14,8 @@ _generate_config() {
[[ "$domain" =~ ^[^.]+\.local$ ]] || continue [[ "$domain" =~ ^[^.]+\.local$ ]] || continue
echo " - $domain" echo " - $domain"
done done
if [[ -e /etc/yunohost/mdns.aliases ]] if [[ -e /etc/yunohost/mdns.aliases ]]; then
then for localalias in $(cat /etc/yunohost/mdns.aliases | grep -v "^ *$"); do
for localalias in $(cat /etc/yunohost/mdns.aliases | grep -v "^ *$")
do
echo " - $localalias.local" echo " - $localalias.local"
done done
fi fi
@ -37,10 +34,10 @@ do_pre_regen() {
mkdir -p ${pending_dir}/etc/systemd/system/ mkdir -p ${pending_dir}/etc/systemd/system/
cp yunomdns.service ${pending_dir}/etc/systemd/system/ cp yunomdns.service ${pending_dir}/etc/systemd/system/
getent passwd mdns &>/dev/null || useradd --no-create-home --shell /usr/sbin/nologin --system --user-group mdns getent passwd mdns &> /dev/null || useradd --no-create-home --shell /usr/sbin/nologin --system --user-group mdns
mkdir -p ${pending_dir}/etc/yunohost mkdir -p ${pending_dir}/etc/yunohost
_generate_config >${pending_dir}/etc/yunohost/mdns.yml _generate_config > ${pending_dir}/etc/yunohost/mdns.yml
} }
do_post_regen() { do_post_regen() {

View file

@ -18,12 +18,12 @@ do_pre_regen() {
cp plain/etcdefault ${pending_dir}/etc/default/dnsmasq cp plain/etcdefault ${pending_dir}/etc/default/dnsmasq
# add resolver file # add resolver file
cat plain/resolv.dnsmasq.conf | grep "^nameserver" | shuf >${pending_dir}/etc/resolv.dnsmasq.conf cat plain/resolv.dnsmasq.conf | grep "^nameserver" | shuf > ${pending_dir}/etc/resolv.dnsmasq.conf
# retrieve variables # retrieve variables
ipv4=$(curl --max-time 10 -s -4 https://ip.yunohost.org 2>/dev/null || true) ipv4=$(curl --max-time 10 -s -4 https://ip.yunohost.org 2> /dev/null || true)
ynh_validate_ip4 "$ipv4" || ipv4='127.0.0.1' ynh_validate_ip4 "$ipv4" || ipv4='127.0.0.1'
ipv6=$(curl --max-time 10 -s -6 https://ip6.yunohost.org 2>/dev/null || true) ipv6=$(curl --max-time 10 -s -6 https://ip6.yunohost.org 2> /dev/null || true)
ynh_validate_ip6 "$ipv6" || ipv6='' ynh_validate_ip6 "$ipv6" || ipv6=''
interfaces="$(ip -j addr show | jq -r '[.[].ifname]|join(" ")')" interfaces="$(ip -j addr show | jq -r '[.[].ifname]|join(" ")')"
wireless_interfaces="lo" wireless_interfaces="lo"
@ -51,8 +51,7 @@ do_pre_regen() {
conf_files=$(ls -1 /etc/dnsmasq.d \ conf_files=$(ls -1 /etc/dnsmasq.d \
| awk '/^[^\.]+\.[^\.]+.*$/ { print $1 }') | awk '/^[^\.]+\.[^\.]+.*$/ { print $1 }')
for domain in $conf_files; do for domain in $conf_files; do
if [[ ! $YNH_DOMAINS =~ $domain ]] && [[ ! $domain =~ \.local$ ]] if [[ ! $YNH_DOMAINS =~ $domain ]] && [[ ! $domain =~ \.local$ ]]; then
then
touch "${dnsmasq_dir}/${domain}" touch "${dnsmasq_dir}/${domain}"
fi fi
done done
@ -68,27 +67,27 @@ do_post_regen() {
# Fuck it, those domain/search entries from dhclient are usually annoying # Fuck it, those domain/search entries from dhclient are usually annoying
# lying shit from the ISP trying to MiTM # lying shit from the ISP trying to MiTM
if grep -q -E "^ *(domain|search)" /run/resolvconf/resolv.conf; then if grep -q -E "^ *(domain|search)" /run/resolvconf/resolv.conf; then
if grep -q -E "^ *(domain|search)" /run/resolvconf/interface/*.dhclient 2>/dev/null; then if grep -q -E "^ *(domain|search)" /run/resolvconf/interface/*.dhclient 2> /dev/null; then
sed -E "s/^(domain|search)/#\1/g" -i /run/resolvconf/interface/*.dhclient sed -E "s/^(domain|search)/#\1/g" -i /run/resolvconf/interface/*.dhclient
fi fi
grep -q '^supersede domain-name "";' /etc/dhcp/dhclient.conf 2>/dev/null || echo 'supersede domain-name "";' >>/etc/dhcp/dhclient.conf grep -q '^supersede domain-name "";' /etc/dhcp/dhclient.conf 2> /dev/null || echo 'supersede domain-name "";' >> /etc/dhcp/dhclient.conf
grep -q '^supersede domain-search "";' /etc/dhcp/dhclient.conf 2>/dev/null || echo 'supersede domain-search "";' >>/etc/dhcp/dhclient.conf grep -q '^supersede domain-search "";' /etc/dhcp/dhclient.conf 2> /dev/null || echo 'supersede domain-search "";' >> /etc/dhcp/dhclient.conf
grep -q '^supersede search "";' /etc/dhcp/dhclient.conf 2>/dev/null || echo 'supersede search "";' >>/etc/dhcp/dhclient.conf grep -q '^supersede search "";' /etc/dhcp/dhclient.conf 2> /dev/null || echo 'supersede search "";' >> /etc/dhcp/dhclient.conf
systemctl restart resolvconf systemctl restart resolvconf
fi fi
# Some stupid things like rabbitmq-server used by onlyoffice won't work if # Some stupid things like rabbitmq-server used by onlyoffice won't work if
# the *short* hostname doesn't exists in /etc/hosts -_- # the *short* hostname doesn't exists in /etc/hosts -_-
short_hostname=$(hostname -s) short_hostname=$(hostname -s)
grep -q "127.0.0.1.*$short_hostname" /etc/hosts || echo -e "\n127.0.0.1\t$short_hostname" >>/etc/hosts grep -q "127.0.0.1.*$short_hostname" /etc/hosts || echo -e "\n127.0.0.1\t$short_hostname" >> /etc/hosts
[[ -n "$regen_conf_files" ]] || return 0 [[ -n "$regen_conf_files" ]] || return 0
# Remove / disable services likely to conflict with dnsmasq # Remove / disable services likely to conflict with dnsmasq
for SERVICE in systemd-resolved bind9; do for SERVICE in systemd-resolved bind9; do
systemctl is-enabled $SERVICE &>/dev/null && systemctl disable $SERVICE 2>/dev/null systemctl is-enabled $SERVICE &> /dev/null && systemctl disable $SERVICE 2> /dev/null
systemctl is-active $SERVICE &>/dev/null && systemctl stop $SERVICE systemctl is-active $SERVICE &> /dev/null && systemctl stop $SERVICE
done done
systemctl restart dnsmasq systemctl restart dnsmasq

View file

@ -24,8 +24,7 @@ do_pre_regen() {
do_post_regen() { do_post_regen() {
regen_conf_files=$1 regen_conf_files=$1
if ls -l /etc/fail2ban/jail.d/*.conf if ls -l /etc/fail2ban/jail.d/*.conf; then
then
chown root:root /etc/fail2ban/jail.d/*.conf chown root:root /etc/fail2ban/jail.d/*.conf
chmod 644 /etc/fail2ban/jail.d/*.conf chmod 644 /etc/fail2ban/jail.d/*.conf
fi fi

View file

@ -782,4 +782,4 @@
"user_import_partial_failed": "L'operació d'importació dels usuaris ha fallat parcialment", "user_import_partial_failed": "L'operació d'importació dels usuaris ha fallat parcialment",
"domain_dns_push_record_failed": "No s'ha pogut {action} el registre {type}/{name}: {error}", "domain_dns_push_record_failed": "No s'ha pogut {action} el registre {type}/{name}: {error}",
"registrar_infos": "Informació del registrador" "registrar_infos": "Informació del registrador"
} }

View file

@ -63,7 +63,7 @@
"mail_forward_remove_failed": "Die Weiterleitungs-E-Mail '{mail}' konnte nicht gelöscht werden", "mail_forward_remove_failed": "Die Weiterleitungs-E-Mail '{mail}' konnte nicht gelöscht werden",
"main_domain_change_failed": "Die Hauptdomain konnte nicht geändert werden", "main_domain_change_failed": "Die Hauptdomain konnte nicht geändert werden",
"main_domain_changed": "Die Hauptdomain wurde geändert", "main_domain_changed": "Die Hauptdomain wurde geändert",
"pattern_backup_archive_name": "Muss ein gültiger Dateiname mit maximal 30 Zeichen sein, ausschliesslich alphanumerische Zeichen und -_.", "pattern_backup_archive_name": "Muss ein gültiger Dateiname mit maximal 30 Zeichen sein, ausschließlich alphanumerische Zeichen und -_.",
"pattern_domain": "Muss ein gültiger Domainname sein (z.B. meine-domain.org)", "pattern_domain": "Muss ein gültiger Domainname sein (z.B. meine-domain.org)",
"pattern_email": "Es muss sich um eine gültige E-Mail-Adresse handeln, ohne '+'-Symbol (z. B. name@domäne.de)", "pattern_email": "Es muss sich um eine gültige E-Mail-Adresse handeln, ohne '+'-Symbol (z. B. name@domäne.de)",
"pattern_firstname": "Muss ein gültiger Vorname sein (mindestens 3 Zeichen)", "pattern_firstname": "Muss ein gültiger Vorname sein (mindestens 3 Zeichen)",
@ -782,4 +782,4 @@
"dyndns_set_recovery_password_failed": "Konnte Wiederherstellungspasswort nicht einstellen: {error}", "dyndns_set_recovery_password_failed": "Konnte Wiederherstellungspasswort nicht einstellen: {error}",
"dyndns_set_recovery_password_success": "Wiederherstellungspasswort eingestellt!", "dyndns_set_recovery_password_success": "Wiederherstellungspasswort eingestellt!",
"global_settings_setting_ssh_port_help": "Ein Port unter 1024 wird bevorzugt, um Kaperversuche durch Nicht-Administratordienste auf dem Remote-Computer zu verhindern. Sie sollten auch vermeiden, einen bereits verwendeten Port zu verwenden, z. B. 80 oder 443." "global_settings_setting_ssh_port_help": "Ein Port unter 1024 wird bevorzugt, um Kaperversuche durch Nicht-Administratordienste auf dem Remote-Computer zu verhindern. Sie sollten auch vermeiden, einen bereits verwendeten Port zu verwenden, z. B. 80 oder 443."
} }

View file

@ -1,4 +1,12 @@
{ {
"password_too_simple_1": "Ο κωδικός πρόσβασης πρέπει να έχει τουλάχιστον 8 χαρακτήρες", "password_too_simple_1": "Ο κωδικός πρόσβασης πρέπει να έχει τουλάχιστον 8 χαρακτήρες",
"aborting": "Ματαίωση." "aborting": "Ματαίωση.",
} "action_invalid": "Μη έγκυρη ενέργεια '{action}'",
"app_action_broke_system": "Αυτή η ενέργεια φαίνεται να έχει προκαλέσει προβλήματα σε αυτές τις σημαντικές υπηρεσίες: {services}",
"app_already_installed": "Η φαρμογή {app} είναι ήδη εγκατεστημένη",
"admin_password": "Κωδικός διαχείρισης",
"all_users": "Όλοι οι χρήστες YunoHost",
"admins": "Διαχειριστές",
"app_action_failed": "Αποτυχία εκτέλεσης ενέργειας {action} για την εφαρμογή {app}",
"already_up_to_date": "Δεν υπάρχει τίποτα να γίνει. Όλα είναι επικαιροποιημένα."
}

View file

@ -248,6 +248,13 @@
"diagnosis_http_special_use_tld": "Domain {domain} is based on a special-use top-level domain (TLD) such as .local or .test and is therefore not expected to be exposed outside the local network.", "diagnosis_http_special_use_tld": "Domain {domain} is based on a special-use top-level domain (TLD) such as .local or .test and is therefore not expected to be exposed outside the local network.",
"diagnosis_http_timeout": "Timed-out while trying to contact your server from the outside. It appears to be unreachable.<br>1. The most common cause for this issue is that port 80 (and 443) <a href='https://yunohost.org/isp_box_config'>are not correctly forwarded to your server</a>.<br>2. You should also make sure that the service nginx is running<br>3. On more complex setups: make sure that no firewall or reverse-proxy is interfering.", "diagnosis_http_timeout": "Timed-out while trying to contact your server from the outside. It appears to be unreachable.<br>1. The most common cause for this issue is that port 80 (and 443) <a href='https://yunohost.org/isp_box_config'>are not correctly forwarded to your server</a>.<br>2. You should also make sure that the service nginx is running<br>3. On more complex setups: make sure that no firewall or reverse-proxy is interfering.",
"diagnosis_http_unreachable": "Domain {domain} appears unreachable through HTTP from outside the local network.", "diagnosis_http_unreachable": "Domain {domain} appears unreachable through HTTP from outside the local network.",
"diagnosis_ignore_already_filtered": "(There is already a diagnosis {category} filter with these criterias)",
"diagnosis_ignore_criteria_error": "Criterias should be of the form key=value (e.g. domain=yolo.test)",
"diagnosis_ignore_filter_added": "Added a {category} diagnosis filter",
"diagnosis_ignore_filter_removed": "Removed a {category} diagnosis filter",
"diagnosis_ignore_missing_criteria": "You should provide at least one criteria being the diagnosis category to ignore",
"diagnosis_ignore_no_filter_found": "(There is no such diagnosis {category} filter with these criterias to remove)",
"diagnosis_ignore_no_issue_found": "No issues was found matching the given criteria.",
"diagnosis_ignored_issues": "(+ {nb_ignored} ignored issue(s))", "diagnosis_ignored_issues": "(+ {nb_ignored} ignored issue(s))",
"diagnosis_ip_broken_dnsresolution": "Domain name resolution seems to be broken for some reason… Is a firewall blocking DNS requests?", "diagnosis_ip_broken_dnsresolution": "Domain name resolution seems to be broken for some reason… Is a firewall blocking DNS requests?",
"diagnosis_ip_broken_resolvconf": "Domain name resolution seems to be broken on your server, which seems related to <code>/etc/resolv.conf</code> not pointing to <code>127.0.0.1</code>.", "diagnosis_ip_broken_resolvconf": "Domain name resolution seems to be broken on your server, which seems related to <code>/etc/resolv.conf</code> not pointing to <code>127.0.0.1</code>.",
@ -309,6 +316,8 @@
"diagnosis_regenconf_allgood": "All configuration files are in line with the recommended configuration!", "diagnosis_regenconf_allgood": "All configuration files are in line with the recommended configuration!",
"diagnosis_regenconf_manually_modified": "Configuration file <code>{file}</code> appears to have been manually modified.", "diagnosis_regenconf_manually_modified": "Configuration file <code>{file}</code> appears to have been manually modified.",
"diagnosis_regenconf_manually_modified_details": "This is probably OK if you know what you're doing! YunoHost will stop updating this file automatically… But beware that YunoHost upgrades could contain important recommended changes. If you want to, you can inspect the differences with <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> and force the reset to the recommended configuration with <cmd>yunohost tools regen-conf {category} --force</cmd>", "diagnosis_regenconf_manually_modified_details": "This is probably OK if you know what you're doing! YunoHost will stop updating this file automatically… But beware that YunoHost upgrades could contain important recommended changes. If you want to, you can inspect the differences with <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> and force the reset to the recommended configuration with <cmd>yunohost tools regen-conf {category} --force</cmd>",
"diagnosis_rfkill_wifi": "The Wi-Fi card is disabled and a system warning might prevent app installations",
"diagnosis_rfkill_wifi_details": "This warning sneaks in many command outputs, breaking some apps. It is usually required to specify your country code with the command <code>sudo raspi-config</code>. Here is the error:<br>{rfkill_wifi_error}",
"diagnosis_rootfstotalspace_critical": "The root filesystem only has a total of {space} which is quite worrisome! You will likely run out of disk space very quickly! It's recommended to have at least 16 GB for the root filesystem.", "diagnosis_rootfstotalspace_critical": "The root filesystem only has a total of {space} which is quite worrisome! You will likely run out of disk space very quickly! It's recommended to have at least 16 GB for the root filesystem.",
"diagnosis_rootfstotalspace_warning": "The root filesystem only has a total of {space}. This may be okay, but be careful because ultimately you may run out of disk space quickly… It's recommended to have at least 16 GB for the root filesystem.", "diagnosis_rootfstotalspace_warning": "The root filesystem only has a total of {space}. This may be okay, but be careful because ultimately you may run out of disk space quickly… It's recommended to have at least 16 GB for the root filesystem.",
"diagnosis_security_vulnerable_to_meltdown": "You appear vulnerable to the Meltdown critical security vulnerability", "diagnosis_security_vulnerable_to_meltdown": "You appear vulnerable to the Meltdown critical security vulnerability",
@ -449,6 +458,10 @@
"global_settings_setting_security_experimental_enabled_help": "Enable experimental security features (don't enable this if you don't know what you're doing!)", "global_settings_setting_security_experimental_enabled_help": "Enable experimental security features (don't enable this if you don't know what you're doing!)",
"global_settings_setting_smtp_allow_ipv6": "Allow IPv6", "global_settings_setting_smtp_allow_ipv6": "Allow IPv6",
"global_settings_setting_smtp_allow_ipv6_help": "Allow the use of IPv6 to receive and send mail", "global_settings_setting_smtp_allow_ipv6_help": "Allow the use of IPv6 to receive and send mail",
"global_settings_setting_smtp_backup_mx_domains": "Domains to act as secondary MX for",
"global_settings_setting_smtp_backup_mx_domains_help": "Allow this server to act as a backup *secondary* MX domain for the listed domain. This means that if the main MX for the domain is not reachable (for example because of an outage), mails will still be sent to this server, which will keep them during a maximum of 20 days and try to relay them to the real destination once it goes back up. Several domains can be provided, separated by commas.",
"global_settings_setting_smtp_backup_mx_emails_whitelisted": "SMTP backup MX emails whitelist",
"global_settings_setting_smtp_backup_mx_emails_whitelisted_help": "When acting as a secondary MX, the exhaustive list of allowed recipient's email addresses must be provided (otherwise mails will be refused and discarded). Several entries can be provided, separated by commas.",
"global_settings_setting_smtp_relay_enabled": "Enable SMTP relay", "global_settings_setting_smtp_relay_enabled": "Enable SMTP relay",
"global_settings_setting_smtp_relay_enabled_help": "Enable the SMTP relay to use in order to send mail instead of this yunohost instance. Useful if you are in one of this situation: your 25 port is blocked by your ISP or VPS provider, you have a residential IP listed on DUHL, you are not able to configure reverse DNS or this server is not directly exposed on the internet and you want use an other one to send mails.", "global_settings_setting_smtp_relay_enabled_help": "Enable the SMTP relay to use in order to send mail instead of this yunohost instance. Useful if you are in one of this situation: your 25 port is blocked by your ISP or VPS provider, you have a residential IP listed on DUHL, you are not able to configure reverse DNS or this server is not directly exposed on the internet and you want use an other one to send mails.",
"global_settings_setting_smtp_relay_host": "SMTP relay host", "global_settings_setting_smtp_relay_host": "SMTP relay host",
@ -573,7 +586,7 @@
"migration_0021_general_warning": "Please note that this migration is a delicate operation. The YunoHost team did its best to review and test it, but the migration might still break parts of the system or its apps.\n\nTherefore, it is recommended to:\n - Perform a backup of any critical data or app. More info on https://yunohost.org/backup;\n - Be patient after launching the migration: Depending on your Internet connection and hardware, it might take up to a few hours for everything to upgrade.", "migration_0021_general_warning": "Please note that this migration is a delicate operation. The YunoHost team did its best to review and test it, but the migration might still break parts of the system or its apps.\n\nTherefore, it is recommended to:\n - Perform a backup of any critical data or app. More info on https://yunohost.org/backup;\n - Be patient after launching the migration: Depending on your Internet connection and hardware, it might take up to a few hours for everything to upgrade.",
"migration_0021_main_upgrade": "Starting main upgrade…", "migration_0021_main_upgrade": "Starting main upgrade…",
"migration_0021_modified_files": "Please note that the following files were found to be manually modified and might be overwritten following the upgrade: {manually_modified_files}", "migration_0021_modified_files": "Please note that the following files were found to be manually modified and might be overwritten following the upgrade: {manually_modified_files}",
"migration_0021_not_buster2": "The current Debian distribution is not Buster! If you already ran the Buster->Bullseye migration, then this error is symptomatic of the fact that the migration procedure was not 100% succesful (otherwise YunoHost would have flagged it as completed). It is recommended to investigate what happened with the support team, who will need the **full** log of the `migration, which can be found in Tools > Logs in the webadmin.", "migration_0021_not_buster2": "The current Debian distribution is not Buster! If you already ran the Buster -> Bullseye migration, then this error is symptomatic of the fact that the migration procedure was not 100% succesful (otherwise YunoHost would have flagged it as completed). It is recommended to investigate what happened with the support team, who will need the **full** log of the migration, which can be found in Tools > Logs in the webadmin.",
"migration_0021_not_enough_free_space": "Free space is pretty low in /var/! You should have at least 1GB free to run this migration.", "migration_0021_not_enough_free_space": "Free space is pretty low in /var/! You should have at least 1GB free to run this migration.",
"migration_0021_patch_yunohost_conflicts": "Applying patch to workaround conflict issue…", "migration_0021_patch_yunohost_conflicts": "Applying patch to workaround conflict issue…",
"migration_0021_patching_sources_list": "Patching the sources.lists…", "migration_0021_patching_sources_list": "Patching the sources.lists…",
@ -591,12 +604,27 @@
"migration_0024_rebuild_python_venv_disclaimer_rebuild": "Rebuilding the virtualenv will be attempted for the following apps (NB: the operation may take some time!): {rebuild_apps}", "migration_0024_rebuild_python_venv_disclaimer_rebuild": "Rebuilding the virtualenv will be attempted for the following apps (NB: the operation may take some time!): {rebuild_apps}",
"migration_0024_rebuild_python_venv_failed": "Failed to rebuild the Python virtualenv for {app}. The app may not work as long as this is not resolved. You should fix the situation by forcing the upgrade of this app using `yunohost app upgrade --force {app}`.", "migration_0024_rebuild_python_venv_failed": "Failed to rebuild the Python virtualenv for {app}. The app may not work as long as this is not resolved. You should fix the situation by forcing the upgrade of this app using `yunohost app upgrade --force {app}`.",
"migration_0024_rebuild_python_venv_in_progress": "Now attempting to rebuild the Python virtualenv for `{app}`", "migration_0024_rebuild_python_venv_in_progress": "Now attempting to rebuild the Python virtualenv for `{app}`",
"migration_0027_cleaning_up": "Cleaning up cache and packages not useful anymore…",
"migration_0027_delayed_api_restart": "The YunoHost API will automatically be restarted in 15 seconds. It may be unavailable for a few seconds, and then you will have to login again.",
"migration_0027_general_warning": "Please note that this migration is a delicate operation. The YunoHost team did its best to review and test it, but the migration might still break parts of the system or its apps.\n\nTherefore, it is recommended to:\n - Perform a backup of any critical data or app. More info on https://yunohost.org/backup;\n - Be patient after launching the migration: Depending on your Internet connection and hardware, it might take up to a few hours for everything to upgrade properly.",
"migration_0027_main_upgrade": "Starting main upgrade…",
"migration_0027_modified_files": "Please note that the following files were found to be manually modified and might be overwritten following the upgrade: {manually_modified_files}",
"migration_0027_not_bullseye": "The current Debian distribution is not Bullseye! If you already ran the Bullseye -> Bookworm migration, then this error is symptomatic of the fact that the migration procedure was not 100% succesful (otherwise YunoHost would have flagged it as completed). It is recommended to investigate what happened with the support team, who will need the **full** log of the migration, which can be found in Tools > Logs in the webadmin.",
"migration_0027_not_enough_free_space": "Free space is pretty low in /var/! You should have at least 1GB free to run this migration.",
"migration_0027_patch_yunohost_conflicts": "Applying patch to workaround conflict issue…",
"migration_0027_patching_sources_list": "Patching the sources.lists file…",
"migration_0027_problematic_apps_warning": "Please note that the following possibly problematic installed apps were detected. It looks like those were not installed from the YunoHost app catalog, or are not flagged as 'working'. Consequently, it cannot be guaranteed that they will still work after the upgrade: {problematic_apps}",
"migration_0027_start": "Starting migration to Bookworm…",
"migration_0027_still_on_bullseye_after_main_upgrade": "Something went wrong during the main upgrade, the system appears to still be on Debian Bullseye.",
"migration_0027_system_not_fully_up_to_date": "Your system is not fully up-to-date. Please perform a regular upgrade before running the migration to Bookworm.",
"migration_0027_yunohost_upgrade": "Starting YunoHost core upgrade…",
"migration_description_0021_migrate_to_bullseye": "Upgrade the system to Debian Bullseye and YunoHost 11.x", "migration_description_0021_migrate_to_bullseye": "Upgrade the system to Debian Bullseye and YunoHost 11.x",
"migration_description_0022_php73_to_php74_pools": "Migrate php7.3-fpm 'pool' conf files to php7.4", "migration_description_0022_php73_to_php74_pools": "Migrate php7.3-fpm 'pool' conf files to php7.4",
"migration_description_0023_postgresql_11_to_13": "Migrate databases from PostgreSQL 11 to 13", "migration_description_0023_postgresql_11_to_13": "Migrate databases from PostgreSQL 11 to 13",
"migration_description_0024_rebuild_python_venv": "Repair Python app after bullseye migration", "migration_description_0024_rebuild_python_venv": "Repair Python app after bullseye migration",
"migration_description_0025_global_settings_to_configpanel": "Migrate legacy global settings nomenclature to the new, modern nomenclature", "migration_description_0025_global_settings_to_configpanel": "Migrate legacy global settings nomenclature to the new, modern nomenclature",
"migration_description_0026_new_admins_group": "Migrate to the new 'multiple admins' system", "migration_description_0026_new_admins_group": "Migrate to the new 'multiple admins' system",
"migration_description_0027_migrate_to_bookworm": "Upgrade the system to Debian Bookworm and YunoHost 12",
"migration_ldap_backup_before_migration": "Creating a backup of LDAP database and apps settings prior to the actual migration.", "migration_ldap_backup_before_migration": "Creating a backup of LDAP database and apps settings prior to the actual migration.",
"migration_ldap_can_not_backup_before_migration": "The backup of the system could not be completed before the migration failed. Error: {error}", "migration_ldap_can_not_backup_before_migration": "The backup of the system could not be completed before the migration failed. Error: {error}",
"migration_ldap_migration_failed_trying_to_rollback": "Could not migrate… trying to roll back the system.", "migration_ldap_migration_failed_trying_to_rollback": "Could not migrate… trying to roll back the system.",

View file

@ -507,4 +507,4 @@
"global_settings_setting_postfix_compatibility_help": "Kongruo vs sekureca kompromiso por la Postfix-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)", "global_settings_setting_postfix_compatibility_help": "Kongruo vs sekureca kompromiso por la Postfix-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
"global_settings_setting_ssh_compatibility_help": "Kongruo vs sekureca kompromiso por la SSH-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)", "global_settings_setting_ssh_compatibility_help": "Kongruo vs sekureca kompromiso por la SSH-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
"global_settings_setting_smtp_allow_ipv6_help": "Permesu la uzon de IPv6 por ricevi kaj sendi poŝton" "global_settings_setting_smtp_allow_ipv6_help": "Permesu la uzon de IPv6 por ricevi kaj sendi poŝton"
} }

View file

@ -782,4 +782,4 @@
"dyndns_set_recovery_password_success": "¡Password de recuperación establecida!", "dyndns_set_recovery_password_success": "¡Password de recuperación establecida!",
"global_settings_setting_dns_exposure_help": "NB: Esto afecta únicamente a la configuración recomentada de DNS y en las pruebas de diagnóstico. No afecta a la configuración del sistema.", "global_settings_setting_dns_exposure_help": "NB: Esto afecta únicamente a la configuración recomentada de DNS y en las pruebas de diagnóstico. No afecta a la configuración del sistema.",
"global_settings_setting_ssh_port_help": "Un puerto menor a 1024 es preferible para evitar intentos de usurpación por servicios no administrativos en la máquina remota. También debe de evitar usar un puerto ya en uso, como el 80 o 443." "global_settings_setting_ssh_port_help": "Un puerto menor a 1024 es preferible para evitar intentos de usurpación por servicios no administrativos en la máquina remota. También debe de evitar usar un puerto ya en uso, como el 80 o 443."
} }

View file

@ -36,7 +36,7 @@
"diagnosis_http_bad_status_code": "Zerbitzari hau ez den beste gailu batek erantzun omen dio eskaerari (agian routerrak).<br>1. Honen arrazoi ohikoena 80 (eta 443) ataka <a href='https://yunohost.org/isp_box_config'>zerbitzarira ondo birbidaltzen ez dela</a> da.<br>2. Konfigurazio konplexua badarabilzu, egiaztatu suebakiak edo reverse-proxyk oztopatzen ez dutela.", "diagnosis_http_bad_status_code": "Zerbitzari hau ez den beste gailu batek erantzun omen dio eskaerari (agian routerrak).<br>1. Honen arrazoi ohikoena 80 (eta 443) ataka <a href='https://yunohost.org/isp_box_config'>zerbitzarira ondo birbidaltzen ez dela</a> da.<br>2. Konfigurazio konplexua badarabilzu, egiaztatu suebakiak edo reverse-proxyk oztopatzen ez dutela.",
"diagnosis_http_timeout": "Denbora agortu da sare lokaletik kanpo zure zerbitzarira konektatzeko ahaleginean. Eskuragarri ez dagoela dirudi.<br>1. 80 (eta 443) ataka <a href='https://yunohost.org/isp_box_config'>zerbitzarira modu egokian birzuzentzen ez direla da</a> ohiko zergatia.<br>2. Badaezpada egiaztatu nginx martxan dagoela.<br>3. Konfigurazio konplexuetan, egiaztatu suebakiak edo reverse-proxyk konexioa oztopatzen ez dutela.", "diagnosis_http_timeout": "Denbora agortu da sare lokaletik kanpo zure zerbitzarira konektatzeko ahaleginean. Eskuragarri ez dagoela dirudi.<br>1. 80 (eta 443) ataka <a href='https://yunohost.org/isp_box_config'>zerbitzarira modu egokian birzuzentzen ez direla da</a> ohiko zergatia.<br>2. Badaezpada egiaztatu nginx martxan dagoela.<br>3. Konfigurazio konplexuetan, egiaztatu suebakiak edo reverse-proxyk konexioa oztopatzen ez dutela.",
"app_sources_fetch_failed": "Ezinezkoa izan da fitxategiak eskuratzea, zuzena al da URLa?", "app_sources_fetch_failed": "Ezinezkoa izan da fitxategiak eskuratzea, zuzena al da URLa?",
"app_make_default_location_already_used": "Ezinezkoa izan da '{app}' '{domain}' domeinuan lehenestea, '{other_app}'(e)k lehendik ere erabiltzen duelako", "app_make_default_location_already_used": "Ezin da '{app}' '{domain}' domeinuan lehenetsi, '{other_app}'(e)k lehendik ere erabiltzen duelako",
"app_already_installed_cant_change_url": "Aplikazio hau instalatuta dago dagoeneko. URLa ezin da aldatu aukera honekin. Markatu 'app changeurl' markatzeko moduan badago.", "app_already_installed_cant_change_url": "Aplikazio hau instalatuta dago dagoeneko. URLa ezin da aldatu aukera honekin. Markatu 'app changeurl' markatzeko moduan badago.",
"diagnosis_ip_not_connected_at_all": "Badirudi zerbitzaria ez dagoela internetera konektatuta!?", "diagnosis_ip_not_connected_at_all": "Badirudi zerbitzaria ez dagoela internetera konektatuta!?",
"app_already_up_to_date": "{app} egunean da dagoeneko", "app_already_up_to_date": "{app} egunean da dagoeneko",
@ -51,7 +51,7 @@
"config_validate_url": "Benetazko URL bat izan behar da", "config_validate_url": "Benetazko URL bat izan behar da",
"app_restore_script_failed": "Errorea gertatu da aplikazioa lehengoratzeko aginduan", "app_restore_script_failed": "Errorea gertatu da aplikazioa lehengoratzeko aginduan",
"app_upgrade_some_app_failed": "Ezinezkoa izan da aplikazio batzuk eguneratzea", "app_upgrade_some_app_failed": "Ezinezkoa izan da aplikazio batzuk eguneratzea",
"app_install_failed": "Ezinezkoa izan da {app} instalatzea: {error}", "app_install_failed": "Ezin da {app} instalatu: {error}",
"diagnosis_basesystem_kernel": "Zerbitzariak Linuxen {kernel_version} kernela darabil", "diagnosis_basesystem_kernel": "Zerbitzariak Linuxen {kernel_version} kernela darabil",
"app_argument_invalid": "Aukeratu balio egoki bat '{name}' argumenturako: {error}", "app_argument_invalid": "Aukeratu balio egoki bat '{name}' argumenturako: {error}",
"app_already_installed": "{app} instalatuta dago dagoeneko", "app_already_installed": "{app} instalatuta dago dagoeneko",
@ -132,7 +132,7 @@
"diagnosis_http_could_not_diagnose": "Ezinezkoa izan da domeinuak IPv{ipversion} kanpotik eskuragarri dauden egiaztatzea.", "diagnosis_http_could_not_diagnose": "Ezinezkoa izan da domeinuak IPv{ipversion} kanpotik eskuragarri dauden egiaztatzea.",
"diagnosis_http_ok": "{domain} domeinua HTTP bidez bisitatu daiteke sare lokaletik kanpo.", "diagnosis_http_ok": "{domain} domeinua HTTP bidez bisitatu daiteke sare lokaletik kanpo.",
"diagnosis_http_unreachable": "Badirudi {domain} domeinua ez dagoela eskuragarri HTTP bidez sare lokaletik kanpo.", "diagnosis_http_unreachable": "Badirudi {domain} domeinua ez dagoela eskuragarri HTTP bidez sare lokaletik kanpo.",
"apps_catalog_failed_to_download": "Ezinezkoa izan da {apps_catalog} aplikazioen zerrenda eskuratzea: {error}", "apps_catalog_failed_to_download": "Ezin da {apps_catalog} aplikazioen zerrenda eskuratu: {error}",
"apps_catalog_init_success": "Abiarazi da aplikazioen katalogo sistema!", "apps_catalog_init_success": "Abiarazi da aplikazioen katalogo sistema!",
"apps_catalog_obsolete_cache": "Aplikazioen katalogoaren katxea hutsik edo zaharkituta dago.", "apps_catalog_obsolete_cache": "Aplikazioen katalogoaren katxea hutsik edo zaharkituta dago.",
"diagnosis_description_mail": "Posta elektronikoa", "diagnosis_description_mail": "Posta elektronikoa",
@ -148,18 +148,18 @@
"diagnosis_http_hairpinning_issue": "Dirudienez zure sareak ez du hairpinninga gaituta.", "diagnosis_http_hairpinning_issue": "Dirudienez zure sareak ez du hairpinninga gaituta.",
"diagnosis_http_partially_unreachable": "Badirudi {domain} domeinua ezin dela bisitatu HTTP bidez IPv{failed} sare lokaletik kanpo, bai ordea IPv{passed} erabiliz.", "diagnosis_http_partially_unreachable": "Badirudi {domain} domeinua ezin dela bisitatu HTTP bidez IPv{failed} sare lokaletik kanpo, bai ordea IPv{passed} erabiliz.",
"backup_archive_cant_retrieve_info_json": "Ezinezkoa izan da '{archive}' fitxategiko informazioa eskuratzea… info.json fitxategia ezin izan da eskuratu (edo ez da baliozko json-a).", "backup_archive_cant_retrieve_info_json": "Ezinezkoa izan da '{archive}' fitxategiko informazioa eskuratzea… info.json fitxategia ezin izan da eskuratu (edo ez da baliozko json-a).",
"diagnosis_domain_expiration_not_found": "Ezinezkoa izan da domeinu batzuen iraungitze data egiaztatzea", "diagnosis_domain_expiration_not_found": "Ezin da domeinu batzuen iraungitze data egiaztatu",
"diagnosis_domain_expiration_not_found_details": "Badirudi {domain} domeinuari buruzko WHOIS informazioak ez duela zehazten noiz iraungiko den?", "diagnosis_domain_expiration_not_found_details": "Badirudi {domain} domeinuari buruzko WHOIS informazioak ez duela zehazten noiz iraungiko den?",
"certmanager_domain_not_diagnosed_yet": "Oraindik ez dago {domain} domeinurako diagnostikorik. Berrabiarazi diagnostikoak 'DNS balioak' eta 'Web' ataletarako diagnostikoen gunean Let's Encrypt ziurtagirirako prest ote dagoen egiaztatzeko. (Edo zertan ari zaren baldin badakizu, erabili '--no-checks' egiaztatzea desgaitzeko.)", "certmanager_domain_not_diagnosed_yet": "Oraindik ez dago {domain} domeinurako diagnostikorik. Berrabiarazi diagnostikoak 'DNS balioak' eta 'Web' ataletarako diagnostikoen gunean Let's Encrypt ziurtagirirako prest ote dagoen egiaztatzeko. (Edo zertan ari zaren baldin badakizu, erabili '--no-checks' egiaztatzea desgaitzeko.)",
"diagnosis_domain_expiration_warning": "Domeinu batzuk iraungitzear daude!", "diagnosis_domain_expiration_warning": "Domeinu batzuk iraungitzear daude!",
"app_packaging_format_not_supported": "Aplikazio hau ezin da instalatu YunoHostek ez duelako paketea ezagutzen. Sistema eguneratzea hausnartu beharko zenuke ziur asko.", "app_packaging_format_not_supported": "Aplikazio hau ezin da instalatu YunoHostek ez duelako paketea ezagutzen. Sistema eguneratzea hausnartu beharko zenuke ziur asko.",
"diagnosis_dns_try_dyndns_update_force": "Domeinu honen DNS konfigurazioa YunoHostek kudeatu beharko luke automatikoki. Gertatuko ez balitz, eguneratzera behartu zenezake <cmd>yunohost dyndns update --force</cmd> erabiliz.", "diagnosis_dns_try_dyndns_update_force": "Domeinu honen DNS konfigurazioa YunoHostek kudeatu beharko luke automatikoki. Gertatuko ez balitz, eguneratzera behartu zenezake <cmd>yunohost dyndns update --force</cmd> erabiliz.",
"app_manifest_install_ask_path": "Aukeratu aplikazio hau instalatzeko URLaren bidea (domeinuaren atzeko aldean)", "app_manifest_install_ask_path": "Aukeratu aplikazio hau instalatzeko URLaren bidea (domeinuaren atzeko aldean)",
"app_manifest_install_ask_admin": "Aukeratu administrari bat aplikazio honetarako", "app_manifest_install_ask_admin": "Aukeratu administratzaile bat aplikazio honetarako",
"app_manifest_install_ask_password": "Aukeratu administrazio-pasahitz bat aplikazio honetarako", "app_manifest_install_ask_password": "Aukeratu administrazio-pasahitz bat aplikazio honetarako",
"ask_user_domain": "Erabiltzailearen posta elektroniko eta XMPP konturako erabiliko den domeinua", "ask_user_domain": "Erabiltzailearen posta elektroniko eta XMPP konturako erabiliko den domeinua",
"app_action_cannot_be_ran_because_required_services_down": "{services} zerbitzuak martxan egon beharko lirateke eragiketa hau exekutatu ahal izateko. Saia zaitez zerbitzuok berrabiarazten (eta ikertu zergatik ez diren abiarazi).", "app_action_cannot_be_ran_because_required_services_down": "{services} zerbitzuak martxan egon beharko lirateke eragiketa hau exekutatu ahal izateko. Saia zaitez zerbitzuok berrabiarazten (eta ikertu zergatik ez diren abiarazi).",
"apps_already_up_to_date": "Egunean daude dagoeneko aplikazio guztiak", "apps_already_up_to_date": "Aplikazio guztiak egunean daude dagoeneko",
"app_full_domain_unavailable": "Aplikazio honek bere domeinu propioa behar du, baina beste aplikazio batzuk daude dagoeneko instalatuta '{domain}' domeinuan. Azpidomeinu bat erabil zenezake instalatu nahi duzun aplikaziorako.", "app_full_domain_unavailable": "Aplikazio honek bere domeinu propioa behar du, baina beste aplikazio batzuk daude dagoeneko instalatuta '{domain}' domeinuan. Azpidomeinu bat erabil zenezake instalatu nahi duzun aplikaziorako.",
"app_install_script_failed": "Errore bat gertatu da aplikazioaren instalatzailearen aginduetan", "app_install_script_failed": "Errore bat gertatu da aplikazioaren instalatzailearen aginduetan",
"diagnosis_basesystem_host": "Zerbitzariak Debian {debian_version} darabil", "diagnosis_basesystem_host": "Zerbitzariak Debian {debian_version} darabil",
@ -263,14 +263,14 @@
"log_user_import": "Inportatu erabiltzaileak", "log_user_import": "Inportatu erabiltzaileak",
"diagnosis_mail_fcrdns_ok": "Alderantzizko DNSa zuzen konfiguratuta dago!", "diagnosis_mail_fcrdns_ok": "Alderantzizko DNSa zuzen konfiguratuta dago!",
"diagnosis_mail_queue_unavailable_details": "Errorea: {error}", "diagnosis_mail_queue_unavailable_details": "Errorea: {error}",
"dyndns_provider_unreachable": "Ezinezkoa izan da DynDNS {provider} enpresarekin konektatzea: agian zure YunoHost zerbitzaria ez dago internetera konektatuta edo dynette zerbitzaria ez dago martxan.", "dyndns_provider_unreachable": "Ezin da DynDNS {provider} enpresarekin konektatu: agian zure YunoHost zerbitzaria ez dago internetera konektatuta edo dynette zerbitzaria ez dago martxan.",
"extracting": "Ateratzen…", "extracting": "Ateratzen…",
"diagnosis_ports_unreachable": "{port}. ataka ez dago eskuragarri kanpotik.", "diagnosis_ports_unreachable": "{port}. ataka ez dago eskuragarri kanpotik.",
"diagnosis_regenconf_manually_modified_details": "Ez dago arazorik zertan ari zaren baldin badakizu! YunoHostek fitxategi hau automatikoki eguneratzeari utziko dio… Baina kontuan izan YunoHosten eguneraketek aldaketa garrantzitsuak izan ditzaketela. Nahi izatekotan, desberdintasunak aztertu ditzakezu <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> komandoa exekutatuz, eta gomendatutako konfiguraziora bueltatu <cmd>yunohost tools regen-conf {category} --force</cmd> erabiliz", "diagnosis_regenconf_manually_modified_details": "Ez dago arazorik zertan ari zaren baldin badakizu! YunoHostek fitxategi hau automatikoki eguneratzeari utziko dio… Baina kontuan izan YunoHosten eguneraketek aldaketa garrantzitsuak izan ditzaketela. Nahi izatekotan, desberdintasunak aztertu ditzakezu <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> komandoa exekutatuz, eta gomendatutako konfiguraziora bueltatu <cmd>yunohost tools regen-conf {category} --force</cmd> erabiliz",
"dyndns_domain_not_provided": "{provider} DynDNS enpresak ezin du {domain} domeinua eskaini.", "dyndns_domain_not_provided": "{provider} DynDNS enpresak ezin du {domain} domeinua eskaini.",
"firewall_reload_failed": "Ezinezkoa izan da suebakia birkargatzea", "firewall_reload_failed": "Ezinezkoa izan da suebakia birkargatzea",
"hook_name_unknown": "'{name}' 'hook' izen ezezaguna", "hook_name_unknown": "'{name}' 'hook' izen ezezaguna",
"domain_deletion_failed": "Ezinezkoa izan da {domain} ezabatzea: {error}", "domain_deletion_failed": "Ezin da {domain} ezabatu: {error}",
"log_regen_conf": "Berregin '{}' sistemaren konfigurazioa", "log_regen_conf": "Berregin '{}' sistemaren konfigurazioa",
"dpkg_lock_not_available": "Ezin da komando hau une honetan exekutatu beste aplikazio batek dpkg (sistemaren paketeen kudeatzailea) blokeatuta duelako, erabiltzen ari baita", "dpkg_lock_not_available": "Ezin da komando hau une honetan exekutatu beste aplikazio batek dpkg (sistemaren paketeen kudeatzailea) blokeatuta duelako, erabiltzen ari baita",
"group_created": "'{group}' taldea sortu da", "group_created": "'{group}' taldea sortu da",
@ -351,7 +351,7 @@
"diagnosis_mail_queue_unavailable": "Ezinezkoa da ilaran zenbat posta elektroniko dauden kontsultatzea", "diagnosis_mail_queue_unavailable": "Ezinezkoa da ilaran zenbat posta elektroniko dauden kontsultatzea",
"log_user_create": "Gehitu '{}' erabiltzailea", "log_user_create": "Gehitu '{}' erabiltzailea",
"group_cannot_edit_visitors": "'bisitariak' taldea ezin da eskuz moldatu. Saiorik hasi gabeko bisitariak barne hartzen dituen talde berezia da", "group_cannot_edit_visitors": "'bisitariak' taldea ezin da eskuz moldatu. Saiorik hasi gabeko bisitariak barne hartzen dituen talde berezia da",
"diagnosis_ram_verylow": "Sistemak RAM memoriaren {available} baino ez ditu erabilgarri; memoria guztiaren ({total}) %{available_percent}a bakarrik!", "diagnosis_ram_verylow": "Sistemak RAM memoriaren {available} baino ez ditu erabilgarri; memoria guztiaren ({total}) %{available_percent}a.",
"diagnosis_ram_low": "Sistemak RAM memoriaren {available} ditu erabilgarri; memoria guztiaren ({total}) %{available_percent}a. Adi ibili.", "diagnosis_ram_low": "Sistemak RAM memoriaren {available} ditu erabilgarri; memoria guztiaren ({total}) %{available_percent}a. Adi ibili.",
"diagnosis_ram_ok": "Sistemak RAM memoriaren {available} ditu oraindik erabilgarri; memoria guztiaren ({total}) %{available_percent}a.", "diagnosis_ram_ok": "Sistemak RAM memoriaren {available} ditu oraindik erabilgarri; memoria guztiaren ({total}) %{available_percent}a.",
"diagnosis_swap_none": "Sistemak ez du swap-ik. Gutxienez {recommended} izaten saiatu beharko zinateke, sistema memoriarik gabe gera ez dadin.", "diagnosis_swap_none": "Sistemak ez du swap-ik. Gutxienez {recommended} izaten saiatu beharko zinateke, sistema memoriarik gabe gera ez dadin.",
@ -387,7 +387,7 @@
"diagnosis_mail_outgoing_port_25_ok": "SMTP posta zerbitzaria posta elektronikoa bidaltzeko gai da (25. atakaren irteera ez dago blokeatuta).", "diagnosis_mail_outgoing_port_25_ok": "SMTP posta zerbitzaria posta elektronikoa bidaltzeko gai da (25. atakaren irteera ez dago blokeatuta).",
"diagnosis_ports_partially_unreachable": "{port}. ataka ez dago eskuragarri kanpotik IPv{failed} erabiliz.", "diagnosis_ports_partially_unreachable": "{port}. ataka ez dago eskuragarri kanpotik IPv{failed} erabiliz.",
"diagnosis_ports_forwarding_tip": "Arazoa konpontzeko, litekeena da operadorearen routerrean ataken birbideraketa konfiguratu behar izatea, <a href='https://yunohost.org/isp_box_config'>https://yunohost.org/isp_box_config</a>-n agertzen den bezala", "diagnosis_ports_forwarding_tip": "Arazoa konpontzeko, litekeena da operadorearen routerrean ataken birbideraketa konfiguratu behar izatea, <a href='https://yunohost.org/isp_box_config'>https://yunohost.org/isp_box_config</a>-n agertzen den bezala",
"domain_creation_failed": "Ezinezkoa izan da {domain} domeinua sortzea: {error}", "domain_creation_failed": "Ezin da {domain} domeinua sortu: {error}",
"domains_available": "Erabilgarri dauden domeinuak:", "domains_available": "Erabilgarri dauden domeinuak:",
"group_already_exist_on_system": "{group} taldea existitzen da dagoeneko sistemaren taldeetan", "group_already_exist_on_system": "{group} taldea existitzen da dagoeneko sistemaren taldeetan",
"diagnosis_processes_killed_by_oom_reaper": "Memoria agortu eta sistemak prozesu batzuk amaituarazi behar izan ditu. Honek esan nahi du sistemak ez duela memoria nahikoa edo prozesuren batek memoria gehiegi behar duela. Amaituarazi d(ir)en prozesua(k):\n{kills_summary}", "diagnosis_processes_killed_by_oom_reaper": "Memoria agortu eta sistemak prozesu batzuk amaituarazi behar izan ditu. Honek esan nahi du sistemak ez duela memoria nahikoa edo prozesuren batek memoria gehiegi behar duela. Amaituarazi d(ir)en prozesua(k):\n{kills_summary}",
@ -400,7 +400,7 @@
"domain_cannot_remove_main": "Ezin duzu '{domain}' ezabatu domeinu nagusia delako. Beste domeinu bat ezarri beharko duzu nagusi bezala 'yunohost domain main-domain -n <another-domain>' erabiliz; honako hauek dituzu aukeran: {other_domains}", "domain_cannot_remove_main": "Ezin duzu '{domain}' ezabatu domeinu nagusia delako. Beste domeinu bat ezarri beharko duzu nagusi bezala 'yunohost domain main-domain -n <another-domain>' erabiliz; honako hauek dituzu aukeran: {other_domains}",
"domain_created": "Sortu da domeinua", "domain_created": "Sortu da domeinua",
"domain_dyndns_already_subscribed": "Dagoeneko izena eman duzu DynDNS domeinu batean", "domain_dyndns_already_subscribed": "Dagoeneko izena eman duzu DynDNS domeinu batean",
"domain_hostname_failed": "Ezinezkoa izan da hostname berria ezartzea. Honek arazoak ekar litzake etorkizunean (litekeena da ondo egotea).", "domain_hostname_failed": "Ezin da hostname berria ezarri. Honek arazoak ekar litzake etorkizunean (litekeena da ondo egotea).",
"domain_uninstall_app_first": "Honako aplikazio hauek domeinuan instalatuta daude:\n{apps}\n\nDesinstalatu 'yunohost app remove the_app_id' exekutatuz edo alda itzazu beste domeinu batera 'yunohost app change-url the_app_id' erabiliz domeinua ezabatu baino lehen", "domain_uninstall_app_first": "Honako aplikazio hauek domeinuan instalatuta daude:\n{apps}\n\nDesinstalatu 'yunohost app remove the_app_id' exekutatuz edo alda itzazu beste domeinu batera 'yunohost app change-url the_app_id' erabiliz domeinua ezabatu baino lehen",
"file_does_not_exist": "{path} fitxategia ez da existitzen.", "file_does_not_exist": "{path} fitxategia ez da existitzen.",
"firewall_rules_cmd_failed": "Suebakiko arau batzuen exekuzioak huts egin du. Informazio gehiago erregistroetan.", "firewall_rules_cmd_failed": "Suebakiko arau batzuen exekuzioak huts egin du. Informazio gehiago erregistroetan.",
@ -423,7 +423,7 @@
"domain_cert_gen_failed": "Ezinezkoa izan da ziurtagiria sortzea", "domain_cert_gen_failed": "Ezinezkoa izan da ziurtagiria sortzea",
"field_invalid": "'{}' ez da baliogarria", "field_invalid": "'{}' ez da baliogarria",
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn": "Operadore batzuei bost axola zaie internetaren neutraltasuna (Net Neutrality) eta ez dute 25. ataka desblokeatzen uzten.<br>- Operadore batzuek <a href='https://yunohost.org/email_configure_relay'>relay posta zerbitzari bat</a> eskaini dezakete, baina kasu horretan zure posta elektronikoa zelatatu dezakete.<br>- Pribatutasuna bermatzeko *IP publikoa* duen VPN bat erabiltzea izan daiteke irtenbidea. Ikus <a href='https://yunohost.org/vpn_advantage'>https://yunohost.org/vpn_advantage</a><br>- Edo <a href='https://yunohost.org/isp'>operadore desberdin batera aldatu</a>", "diagnosis_mail_outgoing_port_25_blocked_relay_vpn": "Operadore batzuei bost axola zaie internetaren neutraltasuna (Net Neutrality) eta ez dute 25. ataka desblokeatzen uzten.<br>- Operadore batzuek <a href='https://yunohost.org/email_configure_relay'>relay posta zerbitzari bat</a> eskaini dezakete, baina kasu horretan zure posta elektronikoa zelatatu dezakete.<br>- Pribatutasuna bermatzeko *IP publikoa* duen VPN bat erabiltzea izan daiteke irtenbidea. Ikus <a href='https://yunohost.org/vpn_advantage'>https://yunohost.org/vpn_advantage</a><br>- Edo <a href='https://yunohost.org/isp'>operadore desberdin batera aldatu</a>",
"ldap_server_down": "Ezin izan da LDAP zerbitzarira konektatu", "ldap_server_down": "Ezin da LDAP zerbitzarira konektatu",
"ldap_server_is_down_restart_it": "LDAP zerbitzaria ez dago martxan, saia zaitez berrabiarazten…", "ldap_server_is_down_restart_it": "LDAP zerbitzaria ez dago martxan, saia zaitez berrabiarazten…",
"log_app_upgrade": "'{}' aplikazioa eguneratu", "log_app_upgrade": "'{}' aplikazioa eguneratu",
"log_tools_shutdown": "Itzali zerbitzaria", "log_tools_shutdown": "Itzali zerbitzaria",
@ -461,7 +461,7 @@
"user_import_success": "Erabiltzaileak arazorik gabe inportatu dira", "user_import_success": "Erabiltzaileak arazorik gabe inportatu dira",
"yunohost_already_installed": "YunoHost instalatuta dago dagoeneko", "yunohost_already_installed": "YunoHost instalatuta dago dagoeneko",
"migrations_success_forward": "{id} migrazioak amaitu du", "migrations_success_forward": "{id} migrazioak amaitu du",
"migrations_to_be_ran_manually": "{id} migrazioa eskuz abiarazi behar da. Joan Tresnak → Migrazioak atalera administrazio-atarian edo bestela exekutatu 'yunohost tools migrations run'.", "migrations_to_be_ran_manually": "{id} migrazioa eskuz abiarazi behar da. Joan Tresnak → Migrazioak atalera administrazio-gunean edo bestela exekutatu 'yunohost tools migrations run'.",
"permission_currently_allowed_for_all_users": "Baimen hau erabiltzaile guztiei esleitzen zaie eta baita beste talde batzuei ere. Litekeena da 'all users' baimena edo esleituta duten taldeei baimena kendu nahi izatea.", "permission_currently_allowed_for_all_users": "Baimen hau erabiltzaile guztiei esleitzen zaie eta baita beste talde batzuei ere. Litekeena da 'all users' baimena edo esleituta duten taldeei baimena kendu nahi izatea.",
"permission_require_account": "'{permission}' baimena zerbitzarian kontua duten erabiltzaileentzat da eta, beraz, ezin da gaitu bisitarientzat.", "permission_require_account": "'{permission}' baimena zerbitzarian kontua duten erabiltzaileentzat da eta, beraz, ezin da gaitu bisitarientzat.",
"postinstall_low_rootfsspace": "'root' fitxategi-sistemak 10 GB edo espazio gutxiago dauka, kezkatzekoa dena! Litekeena da espaziorik gabe geratzea aurki! Gomendagarria da 'root' fitxategi-sistemak gutxienez 16 GB libre izatea. Jakinarazpen honen ondoren YunoHost instalatzen jarraitu nahi baduzu, berrabiarazi agindua '--force-diskspace' gehituz", "postinstall_low_rootfsspace": "'root' fitxategi-sistemak 10 GB edo espazio gutxiago dauka, kezkatzekoa dena! Litekeena da espaziorik gabe geratzea aurki! Gomendagarria da 'root' fitxategi-sistemak gutxienez 16 GB libre izatea. Jakinarazpen honen ondoren YunoHost instalatzen jarraitu nahi baduzu, berrabiarazi agindua '--force-diskspace' gehituz",
@ -515,7 +515,7 @@
"service_disable_failed": "Ezin izan da '{service}' zerbitzua geldiarazi zerbitzaria abiaraztean.\n\nZerbitzuen erregistro berrienak: {logs}", "service_disable_failed": "Ezin izan da '{service}' zerbitzua geldiarazi zerbitzaria abiaraztean.\n\nZerbitzuen erregistro berrienak: {logs}",
"migrations_skip_migration": "{id} migrazioa saihesten…", "migrations_skip_migration": "{id} migrazioa saihesten…",
"upnp_disabled": "UPnP itzalita dago", "upnp_disabled": "UPnP itzalita dago",
"main_domain_change_failed": "Ezinezkoa izan da domeinu nagusia aldatzea", "main_domain_change_failed": "Ezin da domeinu nagusia aldatu",
"regenconf_failed": "Ezinezkoa izan da ondorengo atal(ar)en konfigurazioa berregitea: {categories}", "regenconf_failed": "Ezinezkoa izan da ondorengo atal(ar)en konfigurazioa berregitea: {categories}",
"pattern_email_forward": "Helbide elektroniko baliagarri bat izan behar da, '+' karakterea onartzen da (adibidez: izena+urtea@domeinua.eus)", "pattern_email_forward": "Helbide elektroniko baliagarri bat izan behar da, '+' karakterea onartzen da (adibidez: izena+urtea@domeinua.eus)",
"regenconf_file_manually_removed": "'{conf}' konfigurazio fitxategia eskuz ezabatu da eta ez da berriro sortuko", "regenconf_file_manually_removed": "'{conf}' konfigurazio fitxategia eskuz ezabatu da eta ez da berriro sortuko",
@ -579,7 +579,7 @@
"port_already_opened": "{port}. ataka dagoeneko irekita dago {ip_version} konexioetarako", "port_already_opened": "{port}. ataka dagoeneko irekita dago {ip_version} konexioetarako",
"user_home_creation_failed": "Ezin izan da erabiltzailearentzat '{home}' direktorioa sortu", "user_home_creation_failed": "Ezin izan da erabiltzailearentzat '{home}' direktorioa sortu",
"user_unknown": "Erabiltzaile ezezaguna: {user}", "user_unknown": "Erabiltzaile ezezaguna: {user}",
"yunohost_postinstall_end_tip": "Instalazio ondorengo prozesua amaitu da! Sistemaren konfigurazioa bukatzeko:\n- erabili 'Diagnostikoak' gunea ohiko arazoei aurre hartzeko. Administrazio-atarian abiarazi edo 'yunohost diagnosis run' exekutatu;\n- irakurri 'Finalizing your setup' eta 'Getting to know YunoHost' atalak. Dokumentazioan aurki ditzakezu: https://yunohost.org/admindoc.", "yunohost_postinstall_end_tip": "Instalazio ondorengo prozesua amaitu da! Sistemaren konfigurazioa bukatzeko:\n- erabili 'Diagnostikoak' gunea ohiko arazoei aurre hartzeko. Abiarazi administrazio-gunean edo exekutatu 'yunohost diagnosis run';\n- irakurri 'Finalizing your setup' eta 'Getting to know YunoHost' atalak. Dokumentazioan aurki ditzakezu: https://yunohost.org/admindoc.",
"yunohost_not_installed": "YunoHost ez da zuzen instalatu. Exekutatu 'yunohost tools postinstall'", "yunohost_not_installed": "YunoHost ez da zuzen instalatu. Exekutatu 'yunohost tools postinstall'",
"unlimit": "Mugarik ez", "unlimit": "Mugarik ez",
"restore_already_installed_apps": "Ondorengo aplikazioak ezin dira lehengoratu dagoeneko instalatuta daudelako: {apps}", "restore_already_installed_apps": "Ondorengo aplikazioak ezin dira lehengoratu dagoeneko instalatuta daudelako: {apps}",
@ -590,9 +590,9 @@
"migration_ldap_rollback_success": "Sistema lehengoratu da.", "migration_ldap_rollback_success": "Sistema lehengoratu da.",
"regenconf_need_to_explicitly_specify_ssh": "SSH ezarpenak eskuz aldatu dira, baina aldaketak erabiltzeko '--force' zehaztu behar duzu 'ssh' atalean.", "regenconf_need_to_explicitly_specify_ssh": "SSH ezarpenak eskuz aldatu dira, baina aldaketak erabiltzeko '--force' zehaztu behar duzu 'ssh' atalean.",
"regex_incompatible_with_tile": "/!\\ Pakete-arduradunak! {permission}' baimenak show_tile aukera 'true' bezala dauka eta horregatik ezin duzue regex URLa URL nagusi bezala ezarri", "regex_incompatible_with_tile": "/!\\ Pakete-arduradunak! {permission}' baimenak show_tile aukera 'true' bezala dauka eta horregatik ezin duzue regex URLa URL nagusi bezala ezarri",
"root_password_desynchronized": "Administrariaren pasahitza aldatu da baina YunoHostek ezin izan du aldaketa root pasahitzera hedatu!", "root_password_desynchronized": "Administratzailearen pasahitza aldatu da baina YunoHostek ezin izan du aldaketa root pasahitzera hedatu!",
"server_shutdown": "Zerbitzaria itzaliko da", "server_shutdown": "Zerbitzaria itzaliko da",
"service_stop_failed": "Ezin izan da '{service}' zerbitzua geldiarazi\n\nZerbitzuen azken erregistroak: {logs}", "service_stop_failed": "Ezin da '{service}' zerbitzua geldiarazi\n\nZerbitzuaren azken erregistroak: {logs}",
"service_unknown": "'{service}' zerbitzu ezezaguna", "service_unknown": "'{service}' zerbitzu ezezaguna",
"show_tile_cant_be_enabled_for_url_not_defined": "Ezin duzu 'show_tile' gaitu une honetan, '{permission}' baimenerako URL bat zehaztu behar duzulako", "show_tile_cant_be_enabled_for_url_not_defined": "Ezin duzu 'show_tile' gaitu une honetan, '{permission}' baimenerako URL bat zehaztu behar duzulako",
"upnp_enabled": "UPnP piztuta dago", "upnp_enabled": "UPnP piztuta dago",
@ -601,8 +601,8 @@
"restore_hook_unavailable": "'{part}'-(e)rako lehengoratze agindua ez dago erabilgarri ez sisteman ezta fitxategian ere", "restore_hook_unavailable": "'{part}'-(e)rako lehengoratze agindua ez dago erabilgarri ez sisteman ezta fitxategian ere",
"restore_cleaning_failed": "Ezin izan dira lehengoratzeko behin-behineko fitxategiak ezabatu", "restore_cleaning_failed": "Ezin izan dira lehengoratzeko behin-behineko fitxategiak ezabatu",
"restore_confirm_yunohost_installed": "Ziur al zaude dagoeneko instalatuta dagoen sistema lehengoratu nahi duzula? [{answers}]", "restore_confirm_yunohost_installed": "Ziur al zaude dagoeneko instalatuta dagoen sistema lehengoratu nahi duzula? [{answers}]",
"restore_may_be_not_enough_disk_space": "Badirudi zure sistemak ez duela nahikoa espazio (erabilgarri: {free_space} B, beharrezkoa {needed_space} B, segurtasuneko tartea: {margin} B)", "restore_may_be_not_enough_disk_space": "Badirudi zure sistemak ez duela nahikoa espazio (erabilgarri: {free_space} B, beharrezkoa {needed_space} B, segurtasun-tartea: {margin} B)",
"restore_not_enough_disk_space": "Ez dago nahikoa espazio (erabilgarri: {free_space} B, beharrezkoa {needed_space} B, segurtasuneko tartea: {margin} B)", "restore_not_enough_disk_space": "Ez dago nahikoa espazio (erabilgarri: {free_space} B, beharrezkoa {needed_space} B, segurtasun-tartea: {margin} B)",
"restore_running_hooks": "Lehengoratzeko 'hook'ak exekutatzen…", "restore_running_hooks": "Lehengoratzeko 'hook'ak exekutatzen…",
"restore_system_part_failed": "Ezinezkoa izan da sistemaren '{part}' atala lehengoratzea", "restore_system_part_failed": "Ezinezkoa izan da sistemaren '{part}' atala lehengoratzea",
"server_reboot": "Zerbitzaria berrabiaraziko da", "server_reboot": "Zerbitzaria berrabiaraziko da",
@ -620,24 +620,24 @@
"service_description_redis-server": "Datuak bizkor atzitzeko, zereginak lerratzeko eta programen arteko komunikaziorako datubase berezi bat da", "service_description_redis-server": "Datuak bizkor atzitzeko, zereginak lerratzeko eta programen arteko komunikaziorako datubase berezi bat da",
"service_description_rspamd": "Spama bahetu eta posta elektronikoarekin zerikusia duten bestelako futzioen ardura dauka", "service_description_rspamd": "Spama bahetu eta posta elektronikoarekin zerikusia duten bestelako futzioen ardura dauka",
"service_description_slapd": "Erabiltzaileak, domeinuak eta hauei lotutako informazioa gordetzen du", "service_description_slapd": "Erabiltzaileak, domeinuak eta hauei lotutako informazioa gordetzen du",
"service_description_yunohost-api": "YunoHosten web-atariaren eta sistemaren arteko hartuemana kudeatzen du", "service_description_yunohost-api": "YunoHosten web-interfazearen eta sistemaren arteko hartuemana kudeatzen du",
"domain_config_default_app": "Lehenetsitako aplikazioa", "domain_config_default_app": "Lehenetsitako aplikazioa",
"tools_upgrade": "Sistemaren paketeak eguneratzen", "tools_upgrade": "Sistemaren paketeak eguneratzen",
"tools_upgrade_failed": "Ezin izan dira paketeak eguneratu: {packages_list}", "tools_upgrade_failed": "Ezin izan dira paketeak eguneratu: {packages_list}",
"service_description_postgresql": "Aplikazioen datuak gordetzen ditu (SQL datubasea)", "service_description_postgresql": "Aplikazioen datuak gordetzen ditu (SQL datubasea)",
"migration_0021_start": "Bullseye (e)rako migrazioa abiarazten", "migration_0021_start": "Bullseye-rako migrazioa abiarazten",
"migration_0021_patching_sources_list": "sources.lists petatxatzen…", "migration_0021_patching_sources_list": "sources.lists petatxatzen…",
"migration_0021_main_upgrade": "Eguneraketa nagusia abiarazten…", "migration_0021_main_upgrade": "Eguneraketa nagusia abiarazten…",
"migration_0021_still_on_buster_after_main_upgrade": "Zerbaitek huts egin du eguneraketa nagusian, badirudi sistemak oraindik darabilela Debian Buster", "migration_0021_still_on_buster_after_main_upgrade": "Zerbaitek huts egin du eguneraketa nagusian, badirudi sistemak oraindik darabilela Debian Buster",
"migration_0021_yunohost_upgrade": "YunoHosten muineko eguneraketa abiarazten…", "migration_0021_yunohost_upgrade": "YunoHosten muineko bertsio-berriztea abiarazten…",
"migration_0021_not_enough_free_space": "/var/-enerabilgarri dagoen espazioa oso txikia da! Guxtienez GB 1 izan beharko zenuke erabilgarri migrazioari ekiteko.", "migration_0021_not_enough_free_space": "/var/-en erabilgarri dagoen espazioa oso txikia da! Gutxienez GB 1 izan beharko zenuke erabilgarri migrazioari ekiteko.",
"migration_0021_system_not_fully_up_to_date": "Sistema ez dago erabat egunean. Egizu eguneraketa arrunt bat Bullseye-(e)rako migrazioa abiarazi baino lehen.", "migration_0021_system_not_fully_up_to_date": "Sistema ez dago erabat egunean. Egizu eguneraketa arrunt bat Bullseye-rako migrazioa abiarazi baino lehen.",
"migration_0021_general_warning": "Kontuan hartu migrazio hau konplexua dela. YunoHost taldeak ahalegin handia egin du probatzeko, baina hala ere migrazioak sistemaren zatiren bat edo aplikazioak apurt litzake.\n\nHorregatik, gomendagarria da:\n\t- Datu edo aplikazio garrantzitsuen babeskopia egitea. Informazio gehiago: https://yunohost.org/backup;\n\t- Ez izan presarik migrazioa abiaraztean: zure internet eta hardwarearen arabera ordu batzuk ere iraun lezake eguneraketa prozesuak.", "migration_0021_general_warning": "Kontuan hartu migrazio hau konplexua dela. YunoHost taldeak ahalegin handia egin du probatzeko, baina hala ere migrazioak sistemaren zatiren bat edo aplikazioak apurt litzake.\n\nHorregatik, gomendagarria da:\n\t- Datu edo aplikazio garrantzitsuen babeskopia egitea. Informazio gehiago: https://yunohost.org/backup;\n\t- Ez izan presarik migrazioa abiaraztean: zure internet eta hardwarearen arabera ordu batzuk ere iraun lezake eguneraketa prozesuak.",
"migration_0021_modified_files": "Kontuan hartu ondorengo fitxategiak eskuz moldatu omen direla eta eguneraketak berridatziko dituela: {manually_modified_files}", "migration_0021_modified_files": "Kontuan hartu ondorengo fitxategiak eskuz moldatu omen direla eta eguneraketak berridatziko dituela: {manually_modified_files}",
"migration_0021_cleaning_up": "Katxea eta erabilgarriak ez diren paketeak garbitzen…", "migration_0021_cleaning_up": "Katxea eta erabilgarriak ez diren paketeak garbitzen…",
"migration_0021_patch_yunohost_conflicts": "Arazo gatazkatsu bati adabakia jartzen…", "migration_0021_patch_yunohost_conflicts": "Arazo gatazkatsu bati adabakia jartzen…",
"migration_description_0021_migrate_to_bullseye": "Eguneratu sistema Debian Bullseye eta Yunohost 11.x-ra", "migration_description_0021_migrate_to_bullseye": "Bertsio-berritu sistema Debian Bullseye eta YunoHost 11.x-ra",
"migration_0021_problematic_apps_warning": "Kontuan izan ziur asko gatazkatsuak izango diren odorengo aplikazioak aurkitu direla. Badirudi ez zirela YunoHost aplikazioen katalogotik instalatu, edo ez daude 'badabiltza' bezala etiketatuak. Ondorioz, ezin da bermatu eguneratu ondoren funtzionatzen jarraituko dutenik: {problematic_apps}", "migration_0021_problematic_apps_warning": "Kontuan izan ziur asko gatazkatsuak izango diren ondorengo aplikazioak aurkitu direla. Badirudi ez zirela YunoHost aplikazioen katalogotik instalatu, edo ez daude 'badabiltza' bezala etiketatuak. Ondorioz, ezin da bermatu eguneratu ondoren funtzionatzen jarraituko dutenik: {problematic_apps}",
"migration_0023_not_enough_space": "{path}-en ez dago toki nahikorik migrazioa abiarazteko.", "migration_0023_not_enough_space": "{path}-en ez dago toki nahikorik migrazioa abiarazteko.",
"migration_0023_postgresql_11_not_installed": "PostgreSQL ez zegoen zure isteman instalatuta. Ez dago egitekorik.", "migration_0023_postgresql_11_not_installed": "PostgreSQL ez zegoen zure isteman instalatuta. Ez dago egitekorik.",
"migration_0023_postgresql_13_not_installed": "PostgreSQL 11 dago instalatuta baina PostgreSQL 13 ez!? Zerbait arraroa gertatu omen zaio zure sistemari :(…", "migration_0023_postgresql_13_not_installed": "PostgreSQL 11 dago instalatuta baina PostgreSQL 13 ez!? Zerbait arraroa gertatu omen zaio zure sistemari :(…",
@ -654,8 +654,8 @@
"global_settings_setting_ssh_password_authentication_help": "Baimendu pasahitz bidezko autentikazioa SSHrako", "global_settings_setting_ssh_password_authentication_help": "Baimendu pasahitz bidezko autentikazioa SSHrako",
"global_settings_setting_ssh_port": "SSH ataka", "global_settings_setting_ssh_port": "SSH ataka",
"global_settings_setting_webadmin_allowlist_help": "Administrazio-atarira sar daitezken IP helbideak. CIDR notazioa ahalbidetzen da.", "global_settings_setting_webadmin_allowlist_help": "Administrazio-atarira sar daitezken IP helbideak. CIDR notazioa ahalbidetzen da.",
"global_settings_setting_webadmin_allowlist_enabled_help": "Baimendu IP zehatz batzuk bakarrik administrazio-atarian.", "global_settings_setting_webadmin_allowlist_enabled_help": "Baimendu IP zehatz batzuk bakarrik administrazio-gunerako.",
"global_settings_setting_smtp_allow_ipv6_help": "Baimendu IPv6 posta elektronikoa jaso eta bidaltzeko", "global_settings_setting_smtp_allow_ipv6_help": "Gaitu IPv6 posta elektronikoa jaso eta bidaltzeko",
"global_settings_setting_smtp_relay_enabled_help": "YunoHosten ordez posta elektronikoa bidaltzeko SMTP relay helbidea. Erabilgarri izan daiteke egoera hauetan: operadore edo VPS enpresak 25. ataka blokeatzen badu, DUHLen zure etxeko IPa ageri bada, ezin baduzu alderantzizko DNSa ezarri edo zerbitzari hau ez badago zuzenean internetera konektatuta baina posta elektronikoa bidali nahi baduzu.", "global_settings_setting_smtp_relay_enabled_help": "YunoHosten ordez posta elektronikoa bidaltzeko SMTP relay helbidea. Erabilgarri izan daiteke egoera hauetan: operadore edo VPS enpresak 25. ataka blokeatzen badu, DUHLen zure etxeko IPa ageri bada, ezin baduzu alderantzizko DNSa ezarri edo zerbitzari hau ez badago zuzenean internetera konektatuta baina posta elektronikoa bidali nahi baduzu.",
"migration_0024_rebuild_python_venv_broken_app": "{app} aplikazioari ez ikusiarena egin zaio ezin delako ingurune birtuala modu errazean birsortu. Horren ordez, aplikazioaren eguneraketa behartzen saia zaitezke `yunohost app upgrade --force {app}` arazoa konpontzeko.", "migration_0024_rebuild_python_venv_broken_app": "{app} aplikazioari ez ikusiarena egin zaio ezin delako ingurune birtuala modu errazean birsortu. Horren ordez, aplikazioaren eguneraketa behartzen saia zaitezke `yunohost app upgrade --force {app}` arazoa konpontzeko.",
"migration_0024_rebuild_python_venv_disclaimer_rebuild": "Ondorengo aplikazioen virtualenv-a birsortzeko saiakera egingo da (eragiketak luze jo dezake!): {rebuild_apps}", "migration_0024_rebuild_python_venv_disclaimer_rebuild": "Ondorengo aplikazioen virtualenv-a birsortzeko saiakera egingo da (eragiketak luze jo dezake!): {rebuild_apps}",
@ -664,12 +664,12 @@
"migration_0024_rebuild_python_venv_failed": "{app} aplikazioaren Python virtualenv-aren birsorkuntza saiakerak huts egin du. Litekeena da aplikazioak ez funtzionatzea arazoa konpondu arte. Aplikazioaren eguneraketa behartu beharko zenuke ondorengo komandoarekin: `yunohost app upgrade --force {app}`.", "migration_0024_rebuild_python_venv_failed": "{app} aplikazioaren Python virtualenv-aren birsorkuntza saiakerak huts egin du. Litekeena da aplikazioak ez funtzionatzea arazoa konpondu arte. Aplikazioaren eguneraketa behartu beharko zenuke ondorengo komandoarekin: `yunohost app upgrade --force {app}`.",
"migration_description_0024_rebuild_python_venv": "Konpondu Python aplikazioa Bullseye eguneraketa eta gero", "migration_description_0024_rebuild_python_venv": "Konpondu Python aplikazioa Bullseye eguneraketa eta gero",
"migration_0024_rebuild_python_venv_disclaimer_base": "Debian Bullseye eguneraketa dela-eta, Python aplikazio batzuk birsortu behar dira Debianekin datorren Pythonen bertsiora egokitzeko (teknikoki 'virtualenv' deritzaiona birsortu behar da). Egin artean, litekeena da Python aplikazio horiek ez funtzionatzea. YunoHost saia daiteke beherago ageri diren aplikazioen virtualenv edo ingurune birtualak birsortzen. Beste aplikazio batzuen kasuan, edo birsortze saiakerak kale egingo balu, aplikazio horien eguneraketa behartu beharko duzu.", "migration_0024_rebuild_python_venv_disclaimer_base": "Debian Bullseye eguneraketa dela-eta, Python aplikazio batzuk birsortu behar dira Debianekin datorren Pythonen bertsiora egokitzeko (teknikoki 'virtualenv' deritzaiona birsortu behar da). Egin artean, litekeena da Python aplikazio horiek ez funtzionatzea. YunoHost saia daiteke beherago ageri diren aplikazioen virtualenv edo ingurune birtualak birsortzen. Beste aplikazio batzuen kasuan, edo birsortze saiakerak kale egingo balu, aplikazio horien eguneraketa behartu beharko duzu.",
"migration_0021_not_buster2": "Zerbitzariak darabilen Debian bertsioa ez da Buster! Dagoeneko Buster -> Bullseye migrazioa exekutatu baduzu, errore honek migrazioa erabat arrakastatsua izan ez zela esan nahi du (bestela YunoHostek amaitutzat markatuko luke). Komenigarria izango litzateke, laguntza taldearekin batera, zer gertatu zen aztertzea. Horretarako `migrazioaren erregistro **osoa** beharko duzue, Tresnak > Erregistroak atalean eskuragarri dagoena.", "migration_0021_not_buster2": "Zerbitzariak darabilen Debian bertsioa ez da Buster! Dagoeneko Buster -> Bullseye migrazioa exekutatu baduzu, errore honek migrazioa erabat arrakastatsua izan ez zela esan nahi du (bestela YunoHostek amaitutzat markatuko luke). Komenigarria izango litzateke, laguntza taldearekin batera, zer gertatu zen aztertzea. Horretarako migrazioaren erregistro **osoa** beharko duzue, Tresnak > Erregistroak atalean eskuragarri dagoena.",
"admins": "Administratzaileek", "admins": "Administratzaileek",
"app_action_failed": "{app} aplikaziorako {action} eragiketak huts egin du", "app_action_failed": "{app} aplikaziorako {action} eragiketak huts egin du",
"config_action_disabled": "Ezin izan da '{action}' eragiketa exekutatu ezgaituta dagoelako, egiaztatu bere mugak betetzen dituzula. Laguntza: {help}", "config_action_disabled": "Ezin izan da '{action}' eragiketa exekutatu ezgaituta dagoelako, egiaztatu bere mugak betetzen dituzula. Laguntza: {help}",
"all_users": "YunoHosten erabiltzaile guztiek", "all_users": "YunoHosten erabiltzaile guztiek",
"app_manifest_install_ask_init_admin_permission": "Nork izan beharko luke aplikazio honetako administrazio aukeretara sarbidea? (Aldatzea dago)", "app_manifest_install_ask_init_admin_permission": "Nork izan beharko luke aplikazio honetako administrazio-aukeretara sarbidea? (Aldatzea dago)",
"app_manifest_install_ask_init_main_permission": "Nork izan beharko luke aplikazio honetara sarbidea? (Aldatzea dago)", "app_manifest_install_ask_init_main_permission": "Nork izan beharko luke aplikazio honetara sarbidea? (Aldatzea dago)",
"ask_admin_fullname": "Administratzailearen izen osoa", "ask_admin_fullname": "Administratzailearen izen osoa",
"ask_admin_username": "Administratzailearen erabiltzaile-izena", "ask_admin_username": "Administratzailearen erabiltzaile-izena",
@ -681,7 +681,7 @@
"domain_config_cert_summary_expired": "LARRIA: Uneko ziurtagiria ez da baliozkoa! HTTPS ezin da erabili!", "domain_config_cert_summary_expired": "LARRIA: Uneko ziurtagiria ez da baliozkoa! HTTPS ezin da erabili!",
"domain_config_cert_summary_selfsigned": "ADI: Uneko zirutagiria norberak sinatutakoa da. Web-nabigatzaileek bisitariak izutuko dituen mezu bat erakutsiko dute!", "domain_config_cert_summary_selfsigned": "ADI: Uneko zirutagiria norberak sinatutakoa da. Web-nabigatzaileek bisitariak izutuko dituen mezu bat erakutsiko dute!",
"global_settings_setting_postfix_compatibility": "Postfixekin bateragarritasuna", "global_settings_setting_postfix_compatibility": "Postfixekin bateragarritasuna",
"global_settings_setting_root_access_explain": "Linux sistemetan 'root' administratzaile gorena da. YunoHosten testuinguruan, zuzeneko 'root' SSH saioa ezgaituta dago defektuz, zerbitzariaren sare lokaletik ez bada. 'administrariak' taldeko kideek sudo komandoa erabili dezakete root bailitzan jarduteko terminalaren bidez. Hala ere lagungarri izan liteke root pasahitz (sendo) bat izatea sistema arazteko egoeraren batean administratzaile arruntek saiorik hasi ezin balute.", "global_settings_setting_root_access_explain": "Linux sistemetan 'root' administratzaile gorena da. YunoHosten testuinguruan, zuzeneko 'root' SSH saioa ezgaituta dago defektuz, zerbitzariaren sare lokaletik ez bada. 'administratzaileak' taldeko kideek sudo komandoa erabili dezakete root bailitzan jarduteko terminalaren bidez. Hala ere lagungarri izan liteke root pasahitz (sendo) bat izatea sistema arazteko egoeraren batean administratzaile arruntek saiorik hasi ezin balute.",
"log_settings_reset": "Berrezarri ezarpenak", "log_settings_reset": "Berrezarri ezarpenak",
"log_settings_reset_all": "Berrezarri ezarpen guztiak", "log_settings_reset_all": "Berrezarri ezarpen guztiak",
"root_password_changed": "root pasahitza aldatu da", "root_password_changed": "root pasahitza aldatu da",
@ -695,7 +695,7 @@
"diagnosis_using_stable_codename": "<cmd>apt</cmd> (sistemaren pakete kudeatzailea) 'stable' (egonkorra) izen kodea duten paketeak instalatzeko ezarrita dago une honetan, eta ez uneko Debianen bertsioaren (bullseye) izen kodea.", "diagnosis_using_stable_codename": "<cmd>apt</cmd> (sistemaren pakete kudeatzailea) 'stable' (egonkorra) izen kodea duten paketeak instalatzeko ezarrita dago une honetan, eta ez uneko Debianen bertsioaren (bullseye) izen kodea.",
"diagnosis_using_yunohost_testing": "<cmd>apt</cmd> (sistemaren pakete kudeatzailea) YunoHosten muinerako 'testing' (proba) izen kodea duten paketeak instalatzeko ezarrita dago une honetan.", "diagnosis_using_yunohost_testing": "<cmd>apt</cmd> (sistemaren pakete kudeatzailea) YunoHosten muinerako 'testing' (proba) izen kodea duten paketeak instalatzeko ezarrita dago une honetan.",
"diagnosis_using_yunohost_testing_details": "Ez dago arazorik zertan ari zaren baldin badakizu, baina arretaz irakurri oharrak YunoHosten eguneraketak instalatu baino lehen! 'testing' (proba) bertsioak ezgaitu nahi badituzu, kendu <cmd>testing</cmd> gakoa <cmd>/etc/apt/sources.list.d/yunohost.list</cmd> fitxategitik.", "diagnosis_using_yunohost_testing_details": "Ez dago arazorik zertan ari zaren baldin badakizu, baina arretaz irakurri oharrak YunoHosten eguneraketak instalatu baino lehen! 'testing' (proba) bertsioak ezgaitu nahi badituzu, kendu <cmd>testing</cmd> gakoa <cmd>/etc/apt/sources.list.d/yunohost.list</cmd> fitxategitik.",
"global_settings_setting_smtp_allow_ipv6": "Baimendu IPv6", "global_settings_setting_smtp_allow_ipv6": "Gaitu IPv6",
"global_settings_setting_smtp_relay_host": "SMTP errele-ostatatzailea", "global_settings_setting_smtp_relay_host": "SMTP errele-ostatatzailea",
"domain_config_acme_eligible": "ACME hautagarritasuna", "domain_config_acme_eligible": "ACME hautagarritasuna",
"domain_config_acme_eligible_explain": "Ez dirudi domeinu hau Let's Encrypt ziurtagirirako prest dagoenik. Egiaztatu DNS ezarpenak eta zerbitzariaren HTTP irisgarritasuna. <a href='#/diagnosis'>Diagnostikoen guneko</a> 'DNS erregistroak' eta 'Web' atalek zer dagoen gaizki ulertzen lagun zaitzakete.", "domain_config_acme_eligible_explain": "Ez dirudi domeinu hau Let's Encrypt ziurtagirirako prest dagoenik. Egiaztatu DNS ezarpenak eta zerbitzariaren HTTP irisgarritasuna. <a href='#/diagnosis'>Diagnostikoen guneko</a> 'DNS erregistroak' eta 'Web' atalek zer dagoen gaizki ulertzen lagun zaitzakete.",
@ -720,12 +720,12 @@
"global_settings_setting_ssh_password_authentication": "Pasahitz bidezko autentifikazioa", "global_settings_setting_ssh_password_authentication": "Pasahitz bidezko autentifikazioa",
"global_settings_setting_user_strength_help": "Betekizun hauek lehenbizikoz sortzerakoan edo pasahitza aldatzerakoan bete behar dira soilik", "global_settings_setting_user_strength_help": "Betekizun hauek lehenbizikoz sortzerakoan edo pasahitza aldatzerakoan bete behar dira soilik",
"global_settings_setting_webadmin_allowlist": "Administrazio-atarira sartzeko baimendutako IPak", "global_settings_setting_webadmin_allowlist": "Administrazio-atarira sartzeko baimendutako IPak",
"global_settings_setting_webadmin_allowlist_enabled": "Gaitu administrazio-ataria sartzeko baimendutako IPak", "global_settings_setting_webadmin_allowlist_enabled": "Gaitu administrazio-gunera sartzeko baimendutako IPak",
"invalid_credentials": "Pasahitz edo erabiltzaile-izen baliogabea", "invalid_credentials": "Pasahitz edo erabiltzaile-izen baliogabea",
"log_resource_snippet": "Baliabide bat eguneratzen / eskuratzen / eskuragarritasuna uzten", "log_resource_snippet": "Baliabide bat eguneratzen / eskuratzen / eskuragarritasuna uzten",
"log_settings_set": "Aplikatu ezarpenak", "log_settings_set": "Aplikatu ezarpenak",
"migration_description_0025_global_settings_to_configpanel": "Migratu ezarpen globalen nomenklatura zaharra izendegi berri eta modernora", "migration_description_0025_global_settings_to_configpanel": "Migratu ezarpen globalen nomenklatura zaharra izendegi berri eta modernora",
"migration_description_0026_new_admins_group": "Migratu 'administrari bat baino gehiago' sistema berrira", "migration_description_0026_new_admins_group": "Migratu 'administratzaile bat baino gehiago' sistema berrira",
"password_confirmation_not_the_same": "Pasahitzak ez datoz bat", "password_confirmation_not_the_same": "Pasahitzak ez datoz bat",
"password_too_long": "Aukeratu 127 karaktere baino laburragoa den pasahitz bat", "password_too_long": "Aukeratu 127 karaktere baino laburragoa den pasahitz bat",
"diagnosis_using_stable_codename_details": "Ostatatzaileak zerbait oker ezarri duenean gertatu ohi da hau. Arriskutsua da, Debianen datorren bertsioa 'estable' (egonkorra) bilakatzen denean, <cmd>apt</cmd>-k sistemaren pakete guztiak bertsio-berritzen saiatuko da, beharrezko migrazio-prozedurarik burutu gabe. Debianen gordailuan apt iturria editatzen konpontzea da gomendioa, <cmd>stable</cmd> gakoa <cmd>bullseye</cmd> gakoarekin ordezkatuz. Ezarpen-fitxategia <cmd>/etc/apt/sources.list</cmd> izan beharko litzateke, edo <cmd>/etc/apt/sources.list.d/</cmd> direktorioko fitxategiren bat.", "diagnosis_using_stable_codename_details": "Ostatatzaileak zerbait oker ezarri duenean gertatu ohi da hau. Arriskutsua da, Debianen datorren bertsioa 'estable' (egonkorra) bilakatzen denean, <cmd>apt</cmd>-k sistemaren pakete guztiak bertsio-berritzen saiatuko da, beharrezko migrazio-prozedurarik burutu gabe. Debianen gordailuan apt iturria editatzen konpontzea da gomendioa, <cmd>stable</cmd> gakoa <cmd>bullseye</cmd> gakoarekin ordezkatuz. Ezarpen-fitxategia <cmd>/etc/apt/sources.list</cmd> izan beharko litzateke, edo <cmd>/etc/apt/sources.list.d/</cmd> direktorioko fitxategiren bat.",
@ -739,7 +739,7 @@
"app_resource_failed": "{app} aplikaziorako baliabideen eguneraketak / prestaketak / askapenak huts egin du: {error}", "app_resource_failed": "{app} aplikaziorako baliabideen eguneraketak / prestaketak / askapenak huts egin du: {error}",
"app_not_enough_disk": "Aplikazio honek {required} espazio libre behar ditu.", "app_not_enough_disk": "Aplikazio honek {required} espazio libre behar ditu.",
"app_yunohost_version_not_supported": "Aplikazio honek YunoHost >= {required} behar du baina unean instalatutako bertsioa {current} da", "app_yunohost_version_not_supported": "Aplikazio honek YunoHost >= {required} behar du baina unean instalatutako bertsioa {current} da",
"global_settings_setting_passwordless_sudo": "Baimendu administrariek 'sudo' erabiltzea pasahitzak berriro idatzi beharrik gabe", "global_settings_setting_passwordless_sudo": "Baimendu administratzaileek 'sudo' erabiltzea pasahitzak berriro idatzi beharrik gabe",
"global_settings_setting_portal_theme": "Atariko gaia", "global_settings_setting_portal_theme": "Atariko gaia",
"global_settings_setting_portal_theme_help": "Atariko gai propioak sortzeari buruzko informazio gehiago: https://yunohost.org/theming", "global_settings_setting_portal_theme_help": "Atariko gai propioak sortzeari buruzko informazio gehiago: https://yunohost.org/theming",
"invalid_shell": "Shell baliogabea: {shell}", "invalid_shell": "Shell baliogabea: {shell}",
@ -765,7 +765,7 @@
"group_user_add": "'{user}' erabiltzailea '{group}' taldera gehituko da", "group_user_add": "'{user}' erabiltzailea '{group}' taldera gehituko da",
"ask_dyndns_recovery_password_explain": "Aukeratu DynDNS domeinurako berreskuratze-pasahitza, etorkizunean berrezarri beharko bazenu.", "ask_dyndns_recovery_password_explain": "Aukeratu DynDNS domeinurako berreskuratze-pasahitza, etorkizunean berrezarri beharko bazenu.",
"ask_dyndns_recovery_password_explain_during_unsubscribe": "Sartu DynDNS domeinuaren berreskuratze-pasahitza.", "ask_dyndns_recovery_password_explain_during_unsubscribe": "Sartu DynDNS domeinuaren berreskuratze-pasahitza.",
"dyndns_no_recovery_password": "Ez da berreskuratze-pasahitzik zehaztu! Domeinuaren gaineko kontrola galduz gero, YunoHost taldeko administrariarekin jarri beharko zara harremanetan!", "dyndns_no_recovery_password": "Ez da berreskuratze-pasahitzik zehaztu! Domeinuaren gaineko kontrola galduz gero, YunoHost taldeko administratzailearekin jarri beharko zara harremanetan!",
"ask_dyndns_recovery_password": "DynDNS berreskuratze-pasahitza", "ask_dyndns_recovery_password": "DynDNS berreskuratze-pasahitza",
"dyndns_subscribed": "DynDNS domeinua harpidetu da", "dyndns_subscribed": "DynDNS domeinua harpidetu da",
"dyndns_subscribe_failed": "Ezin izan da DynDNS domeinua harpidetu: {error}", "dyndns_subscribe_failed": "Ezin izan da DynDNS domeinua harpidetu: {error}",
@ -781,5 +781,33 @@
"dyndns_set_recovery_password_invalid_password": "Berreskuratze-pasahitza ezartzeak huts egin du: pasahitza ez da nahikoa sendoa", "dyndns_set_recovery_password_invalid_password": "Berreskuratze-pasahitza ezartzeak huts egin du: pasahitza ez da nahikoa sendoa",
"dyndns_set_recovery_password_failed": "Berreskuratze-pasahitza ezartzeak huts egin du: {error}", "dyndns_set_recovery_password_failed": "Berreskuratze-pasahitza ezartzeak huts egin du: {error}",
"dyndns_set_recovery_password_success": "Berreskuratze-pasahitza ezarri da!", "dyndns_set_recovery_password_success": "Berreskuratze-pasahitza ezarri da!",
"global_settings_setting_ssh_port_help": "1024 baino ataka txikiago bat izan beharko litzateke, zerbitzu ez-administratzaileek urruneko makinan usurpazio-saiorik egin ez dezaten. Lehendik ere erabiltzen ari diren atakak ere ekidin beharko zenituzke, 80 edo 443 kasu." "global_settings_setting_ssh_port_help": "1024 baino ataka txikiago bat izan beharko litzateke, zerbitzu ez-administratzaileek urruneko makinan usurpazio-saiorik egin ez dezaten. Lehendik ere erabiltzen ari diren atakak ere ekidin beharko zenituzke, 80 edo 443 kasu.",
"migration_0027_start": "Bookworm-erako migrazioa abiarazten…",
"migration_0027_still_on_bullseye_after_main_upgrade": "Zerbaitek kale egin du bertsio-berritze nagusian; sistemak oraindik Debian Bullseye darabilela dirudi.",
"migration_0027_general_warning": "Migrazioa tentuz ibiltzeko prozedura da. YunoHosten taldeak ahal izan duen guztia egin du berrikusi eta probatzeko, baina hala ere sistemaren atalak edo aplikazioak honda litzake.\n\nBeraz, gomendagarria da:\n - Datu edo aplikazio garrantzitsuen babeskopia egitea. Informazio gehiagorako: https://yunohost.org/backup;\n - Ez izan presarik migrazioa abiaraztean: internet konexioaren eta hardwarearen arabera, litekeena da ordu apur batzuk ere behar izatea guztia dagokion bezala bertsio-berritzeko.",
"migration_description_0027_migrate_to_bookworm": "Bertsio-berritu sistema Debian Bookworm eta YunoHost 12-ra",
"migration_0027_system_not_fully_up_to_date": "Sistema ez dago erabat egunean. Egizu eguneraketa arrunt bat Bookworm-erako migrazioa abiarazi baino lehen.",
"diagnosis_ignore_filter_added": "{category} atalaren diagnostikorako iragazkia gehitu da",
"migration_0027_problematic_apps_warning": "Kontuan izan ziur asko gatazkatsuak izango diren ondorengo aplikazioak aurkitu direla. Badirudi ez zirela YunoHost aplikazioen katalogotik instalatu, edo ez daude 'badabiltza' bezala etiketatuak. Ondorioz, ezin da bermatu eguneratu ondoren funtzionatzen jarraituko dutenik: {problematic_apps}",
"diagnosis_ignore_missing_criteria": "Gutxienez irizpide bat gehitu behar duzu atalaren diagnostikoak kontuan har ez dezan",
"migration_0027_not_bullseye": "Zerbitzariak darabilen Debian bertsioa ez da Bullseye! Dagoeneko Bullseye -> Bookworm migrazioa exekutatu baduzu, errore honek migrazioa erabat arrakastatsua izan ez zela esan nahi du (bestela YunoHostek amaitutzat markatuko luke). Komenigarria izango litzateke, laguntza taldearekin batera, zer gertatu zen aztertzea. Horretarako migrazioaren erregistro **osoa** beharko duzue, Tresnak > Erregistroak atalean eskuragarri dagoena.",
"diagnosis_ignore_criteria_error": "Irizpideek forma hau izan behar dute: gakoa=balorea (adib. domain=yolo.test)",
"diagnosis_ignore_already_filtered": "(Badago lehendik ere irizpide horiek dituen {category} atalaren diagnostikorako iragazkia)",
"diagnosis_ignore_filter_removed": "{category} atalaren diagnostikorako iragazkia kendu da",
"diagnosis_ignore_no_filter_found": "(Ez dago irizpide horiek dituen {category} atalaren diagnostikorako iragazkirik)",
"diagnosis_ignore_no_issue_found": "Ez da arazorik aurkitu emandako irizpideekin.",
"migration_0027_delayed_api_restart": "YunoHosten APIa 15 segundu barru berrabiaraziko da automatikoki. Litekeena da tarte batez erabilgarri egoteari uztea eta ondoren berriro hasi beharko duzu saioa.",
"migration_0027_main_upgrade": "Bertsio-berritze nagusia abiarazten…",
"migration_0027_cleaning_up": "Erabilgarri izateari utzi dioten katxe eta paketeak garbitzen…",
"migration_0027_yunohost_upgrade": "YunoHosten muineko bertsio-berriztea abiarazten…",
"migration_0027_patch_yunohost_conflicts": "Arazo gatazkatsu bati adabakia jartzen…",
"migration_0027_modified_files": "Ondorengo fitxategiak eskuz moldatu direla antzeman da eta litekeena da bertsio-berritzeak gainean idaztea: {manually_modified_files}",
"migration_0027_not_enough_free_space": "/var/-en erabilgarri dagoen espazioa oso txikia da! Gutxienez GB 1 izan beharko zenuke erabilgarri migrazioari ekiteko.",
"migration_0027_patching_sources_list": "sources.lists fitxategia petatxatzen…",
"global_settings_setting_smtp_backup_mx_emails_whitelisted": "Baimendutako posta elektronikoen MXren SMTP babeskopia",
"global_settings_setting_smtp_backup_mx_domains": "Bigarren mailako MX gisa jarduteko domeinuak",
"global_settings_setting_smtp_backup_mx_domains_help": "Zerbitzari honek zerrendan agertzen den domeinurako *bigarren mailako* MX domeinu gisa jardun dezake. Domeinurako lehenetsitako MX lortu ezin denean (adibidez, itzalaldi baten ondorioz), mezuak bigarren zerbitzari horretara bidaliko dira —gehienez 20 egunez mantenduko dituena— eta berriro eskuragarri dagoenean benetako helburura helarazten saiatuko da. Hainbat domeinu zehaztu daitezke, komaz bereizita.",
"global_settings_setting_smtp_backup_mx_emails_whitelisted_help": "Bigarren mailako MX gisa jarduten duenean, baimendutako hartzaileen posta elektronikoko helbideen zerrenda zehatza eman beharko da (bestela, mezuak ukatu eta baztertuko dira). Hainbat sarrera eman daitezke, komaz bereizita.",
"diagnosis_rfkill_wifi_details": "Ohartarazpena komando askotan ageri da, aplikazio batzuk hautsiz. Herrialdearen kodea zehaztuz konpon daiteke <code>sudo raspi-config</code> komandoaren bidez. Hau da errorea:<br>{rfkill_wifi_error}",
"diagnosis_rfkill_wifi": "Wi-Fi txartela ezgaituta dago eta sistemaren ohartarazpen batek aplikazioen instalazioak eragotzi ditzake"
} }

View file

@ -565,4 +565,4 @@
"global_settings_setting_webadmin_allowlist_enabled_help": "فقط به برخی از IP ها اجازه دسترسی به مدیریت وب را بدهید.", "global_settings_setting_webadmin_allowlist_enabled_help": "فقط به برخی از IP ها اجازه دسترسی به مدیریت وب را بدهید.",
"global_settings_setting_smtp_allow_ipv6_help": "اجازه دهید از IPv6 برای دریافت و ارسال نامه استفاده شود", "global_settings_setting_smtp_allow_ipv6_help": "اجازه دهید از IPv6 برای دریافت و ارسال نامه استفاده شود",
"global_settings_setting_smtp_relay_enabled_help": "میزبان رله SMTP برای ارسال نامه به جای این نمونه yunohost استفاده می شود. اگر در یکی از این شرایط قرار دارید مفید است: پورت 25 شما توسط ارائه دهنده ISP یا VPS شما مسدود شده است، شما یک IP مسکونی دارید که در DUHL ذکر شده است، نمی توانید DNS معکوس را پیکربندی کنید یا این سرور مستقیماً در اینترنت نمایش داده نمی شود و می خواهید از یکی دیگر برای ارسال ایمیل استفاده کنید." "global_settings_setting_smtp_relay_enabled_help": "میزبان رله SMTP برای ارسال نامه به جای این نمونه yunohost استفاده می شود. اگر در یکی از این شرایط قرار دارید مفید است: پورت 25 شما توسط ارائه دهنده ISP یا VPS شما مسدود شده است، شما یک IP مسکونی دارید که در DUHL ذکر شده است، نمی توانید DNS معکوس را پیکربندی کنید یا این سرور مستقیماً در اینترنت نمایش داده نمی شود و می خواهید از یکی دیگر برای ارسال ایمیل استفاده کنید."
} }

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