From c273bc44e7b4d1bedb9ae2c7e72d17b273dbc4f8 Mon Sep 17 00:00:00 2001 From: bencharp Date: Sat, 18 Dec 2021 18:10:41 +0100 Subject: [PATCH] wip : rewrite of a new version from the updated of example_ynh package's --- README.md | 71 ++++++--------- README_fr.md | 68 +++++++-------- check_process | 24 ++--- conf/server.js | 10 ++- conf/systemd.service | 10 ++- config_panel.toml | 78 +++++++++++++++++ doc/screenshots/armadietto.png | Bin 0 -> 73405 bytes doc/screenshots/example.jpg | Bin 35451 -> 0 bytes manifest.json | 31 ++----- scripts/_common.sh | 4 +- scripts/backup | 34 +------- scripts/change_url | 22 +++-- scripts/config | 102 ---------------------- scripts/install | 154 +++++++++------------------------ scripts/remove | 55 ++++-------- scripts/restore | 77 +++++------------ scripts/upgrade | 80 ++++++----------- 17 files changed, 294 insertions(+), 526 deletions(-) create mode 100644 config_panel.toml create mode 100644 doc/screenshots/armadietto.png delete mode 100644 doc/screenshots/example.jpg delete mode 100644 scripts/config diff --git a/README.md b/README.md index d58287b..4bd7c81 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,67 @@ - -# Packaging your an app, starting from this example - -- Copy this app before working on it, using the ['Use this template'](https://github.com/YunoHost/example_ynh/generate) button on the Github repo. -- Edit the `manifest.json` with app specific info. -- Edit the `install`, `upgrade`, `remove`, `backup`, and `restore` scripts, and any relevant conf files in `conf/`. - - Using the [script helpers documentation.](https://yunohost.org/packaging_apps_helpers) -- Add a `LICENSE` file for the package. -- Edit `doc/DISCLAIMER*.md` -- The `README.md` files are to be automatically generated by https://github.com/YunoHost/apps/tree/master/tools/README-generator - - ---- - -# Example app for YunoHost +# Armadietto package for Yunohost -[![Integration level](https://dash.yunohost.org/integration/example.svg)](https://dash.yunohost.org/appci/app/example) ![](https://ci-apps.yunohost.org/ci/badges/example.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/example.maintain.svg) -[![Install example with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=example) +[![Integration level](https://dash.yunohost.org/integration/armadietto.svg)](https://dash.yunohost.org/appci/app/armadietto) ![](https://ci-apps.yunohost.org/ci/badges/armadietto.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/armadietto.maintain.svg) + +[![Install Armadietto with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=armadietto) *[Lire ce readme en français.](./README_fr.md)* > *This package allows you to install example quickly and simply on a YunoHost server. If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* -## Overview +## Armadietto overview -Explain in *a few (10~15) words* the purpose of the app or what it actually does (it is meant to give a rough idea to users browsing a catalog of 100+ apps) +[Armadietto](https://github.com/remotestorage/armadietto/) is a [remoteStorage](https://remotestorage.io) server written for Node.js. -**Shipped version:** 1.0~ynh1 +Armadietto is maintained by remoteStorage Team [IRC](https://kiwiirc.com/client/irc.freenode.net/#remotestorage) -**Demo:** https://demo.example.com +> ### :warning: WARNING +> Please do not consider `armadietto` production ready, this project is still +> considered experimental. As with any alpha-stage storage technology, you +> MUST expect that it will eat your data and take precautions against this. You +> SHOULD expect that its APIs and storage schemas will change before it is +> labelled stable. +**Shipped version:** 0.1.5 ## Screenshots - ![](./doc/screenshots/example.jpg) + ![](./doc/screenshots/armadietto.png) ## Disclaimers / important information -* Any known limitations, constrains or stuff not working, such as (but not limited to): - * requiring a full dedicated domain ? - * architectures not supported ? - * not-working single-sign on or LDAP integration ? - * the app requires an important amount of RAM / disk / .. to install or to work properly - * etc... +### Important Notes +RemoteStorage requires a dedicated domain, so obtain one and add it using the YunoHost admin panel. **Domains -> Add domain**. As RemoteStorage uses the full domain and is installed on the root, you can create a subdomain such as remote.domain.tld. Don't forget to update your DNS if you manage them manually. -* Other infos that people should be aware of, such as: - * any specific step to perform after installing (such as manually finishing the install, specific admin credentials, ...) - * how to configure / administrate the application if it ain't obvious - * upgrade process / specificities / things to be aware of ? - * security considerations ? +RemoteStorage requires browser-approved SSL certificates. If you have certificates not issued by [Let's Encrypt](https://letsencrypt.org/), install them manually as usual. +### Application for remoteStorage +[Click here](https://remotestorage.io/apps/) to see the list of applications that can be used with RemoteStorage. + ## Documentation and resources -* Official app website: https://example.com -* Official user documentation: https://yunohost.org/apps -* Official admin documentation: https://yunohost.org/packaging_apps -* Upstream app code repository: https://some.forge.com/example/example -* YunoHost documentation for this app: https://yunohost.org/app_example -* Report a bug: https://github.com/YunoHost-Apps/example_ynh/issues +* Official app website: https://remotestorage.io/ +* Upstream app code repository: https://github.com/remotestorage/armadietto/ +* Report a bug: https://github.com/bencharp/armadietto_ynh/issues ## Developer info -Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/example_ynh/tree/testing). +Please send your pull request to the [testing branch](https://github.com/bencharp/armadietto_ynh/tree/testing). To try the testing branch, please proceed like that. ``` -sudo yunohost app install https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app install https://github.com/bencharp/armadietto_ynh/tree/testing --debug or -sudo yunohost app upgrade example -u https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app upgrade armadietto_ynh -u https://github.com/bencharp/armadietto_ynh/tree/testing --debug ``` - -**More info regarding app packaging:** https://yunohost.org/packaging_apps \ No newline at end of file diff --git a/README_fr.md b/README_fr.md index d856bf9..38aef6f 100644 --- a/README_fr.md +++ b/README_fr.md @@ -1,66 +1,64 @@ -# Example app pour YunoHost +# Armadietto package pour Yunohost -[![Niveau d'intégration](https://dash.yunohost.org/integration/example.svg)](https://dash.yunohost.org/appci/app/example) ![](https://ci-apps.yunohost.org/ci/badges/example.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/example.maintain.svg) -[![Installer example avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=example) +[![Integration level](https://dash.yunohost.org/integration/armadietto.svg)](https://dash.yunohost.org/appci/app/armadietto) ![](https://ci-apps.yunohost.org/ci/badges/armadietto.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/armadietto.maintain.svg) + +[![Install Armadietto with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=armadietto) *[Read this readme in english.](./README.md)* -*[Lire ce readme en français.](./README_fr.md)* -> *This package allows you to install example quickly and simply on a YunoHost server. -If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* -## Vue d'ensemble +> *Ce paquetage vous permet d'installer Armadietto rapidement et simplement sur un serveur YunoHost. +Si vous n'avez pas YunoHost, veuillez consulter [le guide](https://yunohost.org/#/install) pour savoir comment l'installer.* -Expliquez en *quelques* (10~15) mots l'utilité de l'app ou ce qu'elle fait (l'objectif est de donner une idée grossière pour des utilisateurs qui naviguent dans un catalogue de 100+ apps) +## Aperçu d'Armadietto -**Version incluse:** 1.0~ynh1 +[Armadietto](https://github.com/remotestorage/armadietto/) est un serveur [remoteStorage](https://remotestorage.io) écrit pour Node.js. -**Démo:** https://demo.example.com +Armadietto est maintenu par l'équipe remoteStorage [IRC](https://kiwiirc.com/client/irc.freenode.net/#remotestorage). + +> ### :warning : WARNING +> Veuillez ne pas considérer `armadietto` comme prêt pour la production, ce projet est toujours +> comme expérimental. Comme avec toute technologie de stockage en phase alpha, vous +> devez vous attendre à ce qu'elle mange vos données et prendre des précautions contre cela. Vous +> Vous devez vous attendre à ce que ses API et ses schémas de stockage changent avant qu'il ne soit +> étiqueté comme stable. + +**Version livrée:** 0.1.5 ## Captures d'écran - ![](./doc/screenshots/example.jpg) + ![](./doc/screenshots/armadietto.png) ## Avertissements / informations importantes -* Any known limitations, constrains or stuff not working, such as (but not limited to): - * requiring a full dedicated domain ? - * architectures not supported ? - * not-working single-sign on or LDAP integration ? - * the app requires an important amount of RAM / disk / .. to install or to work properly - * etc... +### Notes importantes +RemoteStorage nécessite un domaine dédié, il faut donc en obtenir un et l'ajouter en utilisant le panneau d'administration de YunoHost. **Domaines -> Ajouter un domaine**. Comme RemoteStorage utilise le domaine complet et est installé à la racine, vous pouvez créer un sous-domaine tel que remote.domain.tld. N'oubliez pas de mettre à jour vos DNS si vous les gérez manuellement. -* Other infos that people should be aware of, such as: - * any specific step to perform after installing (such as manually finishing the install, specific admin credentials, ...) - * how to configure / administrate the application if it ain't obvious - * upgrade process / specificities / things to be aware of ? - * security considerations ? +RemoteStorage nécessite des certificats SSL approuvés par le navigateur. Si vous disposez de certificats qui ne sont pas émis par [Let's Encrypt](https://letsencrypt.org/), installez-les manuellement comme d'habitude. +### Application pour remoteStorage +[Cliquez ici](https://remotestorage.io/apps/) pour voir la liste des applications qui peuvent être utilisées avec RemoteStorage. + ## Documentations et ressources -* Site official de l'app : https://example.com -* Documentation officielle utilisateur: https://yunohost.org/apps -* Documentation officielle de l'admin: https://yunohost.org/packaging_apps -* Dépôt de code officiel de l'app: https://some.forge.com/example/example -* Documentation YunoHost pour cette app: https://yunohost.org/app_example -* Signaler un bug: https://github.com/YunoHost-Apps/example_ynh/issues +* Site Web officiel de l'application : https://remotestorage.io/ +* Dépôt de code de l'application en amont : https://github.com/remotestorage/armadietto/ +* Signalez un bogue : https://github.com/bencharp/armadietto_ynh/issues ## Informations pour les développeurs -Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/example_ynh/tree/testing). +Veuillez envoyer votre demande à la [branche de test] (https://github.com/bencharp/armadietto_ynh/tree/testing). -Pour essayer la branche testing, procédez comme suit. +Pour essayer la branche testing, veuillez procéder comme suit. ``` -sudo yunohost app install https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug -or -sudo yunohost app upgrade example -u https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app install https://github.com/bencharp/armadietto_ynh/tree/testing --debug +ou +sudo yunohost app upgrade armadietto_ynh -u https://github.com/bencharp/armadietto_ynh/tree/testing --debug ``` - -**Plus d'infos sur le packaging d'applications:** https://yunohost.org/packaging_apps \ No newline at end of file diff --git a/check_process b/check_process index fefa192..83fe458 100644 --- a/check_process +++ b/check_process @@ -6,23 +6,23 @@ ;; Test complet ; Manifest domain="domain.tld" - path="/path" - admin="john" + path="/" + admin="armadietto" language="fr" is_public=1 - password="1Strong-Password" - port="666" + is_signup=0 + port="8008" ; Checks pkg_linter=1 - setup_sub_dir=1 + setup_sub_dir=0 setup_root=1 setup_nourl=0 - setup_private=1 - setup_public=1 - upgrade=1 - upgrade=1 from_commit=CommitHash - backup_restore=1 - multi_instance=1 + setup_private=0 + setup_public=0 + upgrade=0 + upgrade=0 from_commit=CommitHash + backup_restore=0 + multi_instance=0 port_already_use=0 change_url=1 ;;; Options @@ -31,4 +31,4 @@ Notification=none ;;; Upgrade options ; commit=CommitHash name=Name and date of the commit. - manifest_arg=domain=DOMAIN&path=PATH&admin=USER&language=fr&is_public=1&password=pass&port=666& + manifest_arg=domain=DOMAIN&path=PATH&admin=USER&language=fr&is_public=1&is_signup=0&port=8008& diff --git a/conf/server.js b/conf/server.js index 6c8c026..5531073 100644 --- a/conf/server.js +++ b/conf/server.js @@ -3,13 +3,15 @@ const Armadietto = require('__MODULE_PATH__/armadietto'); let store; let server; -const type = process.argv[2]; +// const type = process.argv[2]; store = new Armadietto.FileTree({path: '__DATADIR__'}); server = new Armadietto({ store: store, - http: {port: __PORT__}, + http: { + port: __PORT__ + }, https: { force: true, port: __PORT__, @@ -19,9 +21,9 @@ server = new Armadietto({ allow: { signup: __SIGNUP__ }, - cacheViews: false, - basePath: "" + cacheViews: false }); console.log('LISTENING ON PORT __PORT__'); server.boot(); + diff --git a/conf/systemd.service b/conf/systemd.service index 2003f0a..51aa374 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -1,5 +1,5 @@ [Unit] -Description=Armadietto remoteStorage server written in nodejs +Description=Armadietto is a remoteStorage server written in nodejs After=network.target [Service] @@ -7,9 +7,10 @@ Type=simple User=__APP__ Group=__APP__ WorkingDirectory=__FINALPATH__/ -ExecStart=__FINALPATH__/script -StandardOutput=append:/var/log/__APP__/__APP__.log -StandardError=inherit +ExecStart=__NODEJS_PATH__/node __FINALPATH__/server.js +Restart=always +Environment=PATH=/usr/bin:/usr/local/bin:__NODEJS_PATH__ +Environment=NODE_ENV=production # Sandboxing options to harden security # Depending on specificities of your service/app, you may need to tweak these @@ -29,6 +30,7 @@ ProtectKernelTunables=yes LockPersonality=yes SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap + # Denying access to capabilities that should not be relevant for webapps # Doc: https://man7.org/linux/man-pages/man7/capabilities.7.html CapabilityBoundingSet=~CAP_RAWIO CAP_MKNOD diff --git a/config_panel.toml b/config_panel.toml new file mode 100644 index 0000000..e1bf587 --- /dev/null +++ b/config_panel.toml @@ -0,0 +1,78 @@ + +## Config panel are available from webadmin > Apps > YOUR_APP > Config Panel Button +## Those panels let user configure some params on their apps using a friendly interface, +## and remove the need to manually edit files from the command line. + +## From a packager perspective, this .toml is coupled to the scripts/config script, +## which may be used to define custom getters/setters. However, most use cases +## should be covered automagically by the core, thus it may not be necessary +## to define a scripts/config at all! + +## ----------------------------------------------------------------------------- +## IMPORTANT: In accordance with YunoHost's spirit, please keep things simple and +## do not overwhelm the admin with tons of misunderstandable or advanced settings. +## ----------------------------------------------------------------------------- + +## The top level describe the entire config panels screen. + +## The version is a required property. +## Here a small reminder to associate config panel version with YunoHost version +## | Config | YNH | Config panel small change log | +## | ------ | --- | ------------------------------------------------------- | +## | 0.1 | 3.x | 0.1 config script not compatible with YNH >= 4.3 | +## | 1.0 | 4.3.x | The new config panel system with 'bind' property | +version = "1.0" + +## (optional) i18n property let you internationalize questions, however this feature +## is only available in core configuration panel (like yunohost domain config). +## So in app config panel this key is ignored for now, but you can internationalize +## by using a lang dictionary (see property name bellow) +# i18n = "prefix_translation_key" + +################################################################################ +#### ABOUT PANELS +################################################################################ + +## The next level describes web admin panels +## You have to choose an ID for each panel, in this example the ID is "main" +## Keep in mind this ID will be used in CLI to refer to your question, so choose +## something short and meaningfull. +## In the webadmin, each panel corresponds to a distinct tab / form +[main] + +## Define the label for your panel +## Internationalization works similarly to the 'description' and 'ask' questions in the manifest +# name.en = "Main configuration" +# name.fr = "Configuration principale" + +## (optional) If you need to trigger a service reload-or-restart after the user +## change a question in this panel, you can add your service in the list. +services = ["__APP__"] +# or services = ["nginx", "__APP__"] to also reload-or-restart nginx + +## (optional) This help properties is a short help displayed on the same line +## than the panel title but not displayed in the tab. +# help = "" + + ############################################################################ + #### ABOUT SECTIONS + ############################################################################ + + ## A panel is composed of one or several sections. + ## + ## Sections are meant to group questions together when they correspond to + ## a same subtopic. This impacts the rendering in terms of CLI prompts + ## and HTML forms + ## + ## You should choose an ID for your section, and prefix it with the panel ID + ## (Be sure to not make a typo in the panel ID, which would implicitly create + ## an other entire panel) + ## + ## We use the context of pepettes_ynh as an example, + ## which is a simple donation form app written in python, + ## and for which the admin will want to edit the configuration + [main.customization] + + ## (optional) Defining a proper title for sections is not mandatory + ## and depends on the exact rendering you're aiming for the CLI / webadmin + name = "PLOP" \ No newline at end of file diff --git a/doc/screenshots/armadietto.png b/doc/screenshots/armadietto.png new file mode 100644 index 0000000000000000000000000000000000000000..fa87b65abceec2c6d1c79f5dafce0e14ad9e4705 GIT binary patch literal 73405 zcmeFZcU)6<`#*dT1uG(@sDP|iR8#~+M0V2FK^1{pQBhV@L_}my36NN;po~-$5E;=@ zKtzbh21BBZC<~f-A?x{^(EI+r?(gs4=da)M@Mm8K0kJ=#_b=eXig31^aU2##395Z(V=vz5CV;LBIUV@4c5|jmm4#q7qmUZL%#Ju75)yLy+2P%6?#ajbjoA@HTKX4W zC!R05(8Op;@a%d0?JG(0yuIIAxWITzr4I~fnq2>UK)~5b&+q;7r=y-j?^>@;b>x-a z?0$8zHq^&0{F|^BBe}aX-S^=r4u64NgO3Tn&Gh85kbAFxeyX0Z-A1$MLh-{?edp%E z2)c?>{%Lz_=9d?`r?kE2`YPC6PL32IU*YP)u zwe+1!65-GPbzF&(;obh*yL7#r$W!_F4Zs7iHm$(?YbpRAJJ_6Pu^;|7*_`pxeB=)m z&rd0ot89j?rBoe}lP`{ESLq)P9($2pb*V1gZy2Xr5>}Z;+e-eDgEQ=6N;mQMJpN=QhjEDN3+-Xx|@AiRq=BygFz!CqIZ|+IaR`Jfc z9d6AV2nphkJ3o2XF0T{4HwQh>kDSQxR=MjR$DxuAULbg=IJ*UT!KO~O2@n39VPXcZ zsi|J>o3RX_8AAm`TP>sl97O0G88ry&@A`JEwDI7#D=kk7zXG#2#NiU%43YEsigow4 zAGoN-8;rob_8?krG5^t`GAF!mDRTIZJS<U<$o)qI&LN_sCsBAAy)qNjgo1_V??e_71-5#P-P;)kzk#u=xIAI64|4A`P!y# z{*XuQ(u3-y4nkT?37SPTDyf^l|8ac35;=tF;dTg$(A+i%LMd|blUHfrNcRI46;Jwc zyFpa-Y={necC6hgN&_ncBwO7hm8|mGC(od-$59V}r-bdWSo{L}+i1HLYyO=(1#*k5 z+j6g}2E;NPqU;L7;8#BPm%Gb2IB;K{$yJeE$i*2xs0lGL6!bMGX-K|qwAs(*-joew zQ=NpC34_4Vfp!&w+DvK93Z{>1Uk8qN(X;_ z91m9_`>@VX{9w=O<-jl<+Mlu;2gmgTiVkYW(fga{-VOe~LBT1222@(+jrwvs6E?<) zMDtz1QM8WU*Ho) z&%k5%1(A+!u{iK7GjkN+&2dB8*2jD7_gUQJPZi*kGfW<{#%cB8-i#muN!+}4xccP^ zE40YuJ8-@?ghP-l^u-U3dWG!=5{*5Rrw@Czbip>4#(2L0z$ERc8)q2dTKBhTeO)_g za7{jpL_yPq-p9ZLX(-H5rcVYq>25piqR90N;8e$ex|oFtR_8RZ37DKMcje|#T+t*Q z^RGk=GX(5tjgu~W{UF2wdE`6}%CQmrez9`4P%2<&0d+Du##S@v+-W>Q*CTS|-c!pk z-ikGVk;wTPW-idy$MMCx+z_gbjhTT>8<$rl^)lC1Q}U5%EN8?R=7k1O)Q~y z`q@Jolw;!UZ_W8^vKvKUnqnQT*-zf;F4^z~G-&P-F`sCy?y@Tn^m1NDDh}7N>I*oc z!cfKGO#fO7|LT$Eb|i9jGUbN9e{y#bE%c_pzeASXYM(D*#=6C_4YtT9XrLc&1B8Q8 zq(0_a^FDOC>oJ4R#IuAU#j*=8&!Cde7kR|{bUHi)e%E(9^MlMvyl(PC7+HXELC%cR zj=BgtL)eXCCS>i`_o?)1Q%l#37_s!_FMz%qcB72UAnG$ys~n7&Z$A4*_biG7e9Lp7 zn*FHtyf&6eMSWj27>*tbwh!vPVhh{sGr0N$PP=pJby<5dfT4EY;>+A*{$xA@AR}us zSFaJ^yEKxmYaFwB$v9Tn_|%g7clCVjjOTbuYS71@;!+0+2A}}|TGia1 ze$S?dsX^~Igk1e6A3a54egO$!4;$gU18YQFDhi^<@N9wq0=Uxz9AZ{zv$cNS8}F_S zyvm+Qn`kGR!&!*KG>V6*M&koY(?E?XWpTXK2?sf#ao~)5S8L=^s{?P}7 z(~gM*e1`JPn<`B~N6gF$TuQHcG5t2l4_kyx#2!AZJ;<+M$e07x@#!%RXT^G_f1$)p zz32k*`vg_w4`tW0Rb}NiJH)hg%MAw;I1`xx_CzX3zoTzkCn#^dS{e6LJ>tDu)0*1M z=sV(cVy{ilwJMTp++x=wU zme1oBxn&i+cb>G*ZX5PMN!# z!48W~0|%Aw<%`%_b*ts4duhP<-P{`On5EJ#=578si@PfLvwLw| zzqKB9>87u5LRy+V8(68yte)LgEn2p^`r(gHL~#h5AHSgCc~kR0^ff4?GGSs5_X;#Q9J;>VP?)KW7gvY(${Y1mBV=}N!;?Q?T; z+vu#y%F3qzXgwqr-{uMna*_k0M_se;D{6e3A;8Jt#sRs@phn5>gQ6uOrEr18{%rB> z039qUh8t%}Qq{FhPA;S7Y@;ITto!=Gc*eDNwmm&H*2nneo`2_#bWG@2gV-U z>}OA7kXim^<|7;E>+8#uhyhgz6IeWSl(?;|2>KwmTZ?0(o}yL7-K4v|1mX)C=E9;B zR(^Ig`R9WRRrTDtMtp&TO`$85{ZSWpAzB!78wQiB6Q93<&#|JJO&*db0z&kLQ+ni9ubSCFV3|zyM*!EEkpo&*;Y+L3Q!sgi zph+L;;rD=K3#dzPZI~+)4_MyaNm{_=bZyDsj~(o-mq&3(Wts>2F1W?RZJ#Jf8)-80 zy8m11JMvp_07M?G^qthp?#rW~-kINCWp+Ab`a=$-H@-4b=nVkcOZY)sY?j`bGqXZQ z7h6>ulgx%R)7`_5f6lV7+JY2*tR<-eqLDP!>D~C@9<9;dZ14wgEbW5qBR0>TEf+=6 zzf;*mxu@Em2og^IQ#01$Q*(AToMWpzI;z z$9Ur8fCIdX)#2F_0%^nLLB!AonBN68D4I3xPXC->LbbMnbG<&^8z|;^z(J`!#^r`D zm8H<~V#XfrHbsVum#8|Sh~`zU##J)*eTLky*-)fzP$r+F+9ebMW{+YRd)ywEAB-hM z`9rbQW4t#KvAkC--l*Q6OHK+nz%IjQ=jK;<0%bH$Jj*|CQZq5a`@ug zF?MgMr|mT7R__~Q0Pr~}%qeiN18$M_!dY*mkzfZsYG$r_EakQ-31h2$I~3&UvQnSU ziMKeSUwbpiU8-cGhMsR%>J;zdRRtwx$_mqg<=}-P>%vb0Qi09#CRtOY=a@K@tfHw^*73Mx|yMdJL8(12w9Pvwk+kWC7P32&37Q`qD~1;|7O@ zv>g%rbKi7-pRs_bz)gY_XAi{8xYCoAb+>#Qm23y%Lqv)+2%czQLu&F@R%v+qXc4GJ zUQU(j#I8JQ6ggV?MU4f2lN$y#z;6Fe5XTmKt{Vg9@Ib)otI&tRV2)Q*AUDh#LL=GL zAlCnyj@e`X><0}q|Id~Cw^x9i^UC(ab|o@grU1}0wW0P^v>As^#;@Qd{Gc`h`-1}W zLUatsUWWX{o{orm&eiF#v>8(f6*cAcwWp^ikGA|6|89FjT!e(P30Aq*n#ut@&X#%a zt{)0oAFzGgL6X(#B|SytXcB(6f5cQCs!b@wAyzLk>OtXJ*ed7-HNyr~w{weD<}geS zF+m;mo6R5_z=?L%P!u{VX8E-_yU~dOYB}8T1np#iSLp+ld3kw^j~C4$5~tnjfs+~m zFoJwXyt3{I%^&2o&8>lnw&RfEW93y<>DE*Mi=|y<7BHk)H4yBo8S=R_h%D1^wdWDy#=<+~mm#J$}nJPD&pD+4BcNAF8%68!9Lmb&a6IZr{+*EMK-(QS7O|=2E z=^`oiD5IWRTX~ZxKfKQ=KXr4>rDU-IB0Csh^MQ+j=i!XRU6$88cpxWgdMbs^1xR;h z*X=;XNH zqIMZDh?kL1RzVRqT7Znn9kY0)<>MwqXa@hbO8s(WW#P#i>(4ss=7u)hNmoKBQ(=TH&cw_1A=W zYX*|vyrRbRTw?B;r**vD2l&|8bY79R>;kCO8#BCfv>a`?q2-l(Y(K;4qBnpft3M>s zN7Wn-!Y?l`KeY%6&u4l7xM_^(@9SeMG*I$~j`%@v6;Xts@alP@6oKDBwJ`weg@-(S zaf~X)f73QxlYv1dV=@<4yxMmnX*KwrV7~5wpq@7**hUC&pMiv9j~#dWldd#0zhwoz z`042Vv_vvcmxDW^3LNlf`gLjAex*om@|;$2JkYvSeXl@dU@ZzUOplSWWpAY5HltG2 zJv6ABX;^P~%b=j7BtH`J2TTLFj#pZ^%W%9fz7C|5(?_`gVGah-<#pVi@VQEw=DT8r zqxfC(7*1PN-cV)aig3!2z8C#R&vJ`iL_cuYO&_c_Y;N_T(6 zx7jN`ZF}r90LMH}mH~ zP~pjMR?{>vFvzC+`h44JZ!b6>{khO7!BHZNWC$uYlOqPh92u2>RF9@5v_~mO@yY4AhjCO5 z|LT36qts_%9*kH(Z;V54Ooat^Mgt6V7~uV`V7R}g?XHsHseuVVTt6Q^tr`W0+HUR9 z8s>#mqMre1C3p)`on!yS@xBE*YAQHDlW|>h9Jq(HWdCpOlhtb41WaNVP3riX0?POU zE=z%o<)#95u@{6`?j8G@(_a-phctp$zMl7hxJ3kZV?y2_dn$J7} zNrvSmsnu;-5d-Hr=s^DXC*N(Dh4=Da0j{l(FexBfKd4`y@b1+F?Fe|x1Io%*oVcz8 ze+3-iIctq?U6LDS{KA?lAbGHj>1ZRsJQy=YJ%`{>Vsr4$NQ1yQQ{SF&wC3x-0m{e6 z13-Ri#Y=feB}Ih=|LFea`SKlOP?V&5tok#8I+~e`k&uDv?=rOORyd1;tokf|7%0o+ zw`l%g6|u*$G@9|Cpi9VsbIWd)N}=9;?HX*7=9niYyC+A>=`iYiwon;4x)W^jcPIf5P&z*ufgC!8h@etFSg*Zdx& z#9E+dHYA)bLcX37gZz>Vz_bZ~>D8u(9mX{k6{dR}tV?D^FfnMHgL{p6cu*HIf53(C z#}!WbJ6T63YoSl)Qw+7SsAzWHXF?HRx}ZUHYN)I{H@&R)t(P4m$iar2*wyc)g|)?L zJ1zFfDfW@<2!5hfu6q;t!Z>+)Nz-;Nyx-(7X>}}Vr&ZEd7{EaUYgwp zVrP1a3mf{p(%T#dO7v-{;`}< z%+>o(gIeZl@0&+q7*f<#2q9WBv5S>=D#&pQt^@VcLBZ9Fo<0TB^9kVeo^Y;qkEO$A zYxGPND9ODAB4&pJ~mE)CxnSnFGIO981{UORs$zebC>Q6Y~p0poFO2%N7OG z&ds$z)}S@r7~|q{qzQ0j1#Ql1BTqm3M2!_J#4z?shCB(xMB|)c%{33uf6DDowwUNm zVNSzxV6J`X=;#>diENRptVYka3{I-lS3rqk5md*WG3y$SFo{`BR0I7wo5kC5y{_5l zSyfNYT^&2oPyaBLyJt;K|dR;ksbrtg?$BCIn{$LsZ_msROBi%Y^EnKM{JQk z(+9dFrcIdv^{Lf#m@<%f!1GT>6C$%p(sR^ceg`vTMi8^D&YBxOLkswAz#p`}ZI-`H zCde*S2aT%G1AKk$h}xmsVLLKP+bw6ZPP2{zY6~LzLH}HDX)Yz!3=&wv?c1bgX&f+c&Rb%B~p3;n#Z3$g2v8AT?!y=YpJ(G7eJvR z8HDv|YyTRVl{lmjbPmUpU5ev?hqFkMU%n0v0iXT*B!wm{(+d6a{>%X22_{4(P+rJx zQM<6%r&*)$#ROK);T^DCVNR`5J;0RM@{7#^`RD@zKDcGdODDHTb^+W+Z@wy4bRVvI z24V$T4+zNR-VSXvX}Jrsj+ozFSf!6pjL3UIOo74Ty}V9eA&PWochwXyCkPQ3enD8& zPWL^-h%-#Q^|U=f_Icp+&^bz{1@5Of36}~2cKM@0hyP}*AKa1=`bRNbdLVS2i`=lT ztt#&5kE*haN3E>osc9mkZ z6dYD_SNOEpeM7_<)zP6#q<;RzyK+l7!F7@UyW13_rdl*oyG z#T8q~aQ2WU(_}DZ9E#x$wiC`<0^&g9f^L$&jp7pUC+&cD?6O8$zP(iqWr#4OjU_Fn z+No5zl44`pY^_u!?Ph*`S*wC+pg}O*00~E*AbdW-LwCPYJw$2-2V>AGuebF*L-miR z8~tVt`q7fFo_KF8@jL~xelEfOkYKb@+%8jHh>@(YGLc&P6ES=CfK>DpF>f@gR~5T| z9?6T?nck{IX3;qb?9_dj?I^?~el)`lp)oTrii{SeP@6{@#1<2pJZ35XJ+A5RuNYOJ z?E%a@t1+TPOb=oxV^ma>M0FRJQ>o1wRhUC^X51MrZ#_WZf9PQtG!F`-XpkPWs|HIw zy|ZFhGad+>t@c+~$u1CiL-=YIk0d$8pau}R;kbH~jVVL`teah}u-z>+st%03w1KVd z29_V{Z|_-h1MS^w3^6)(K#!m@=>`7OO{p40IK=E0I^-5^jYc>Kv(%3 zbV0IcrdK#jx!M~m8RA!%`Ae>4nTQjNZ;>##Bp&9#7L8?UHeKTj0VAAUc5F`c6u+g> zRUl~De~qW~NLz=;6SnL5qoU8vf6@b!OYxvOR?pEPN3OQoYQDP2mQKjofu-Npvp6&q zLXGhXs0;N8CJ%xv2UG5h946qX36+&&D;8j8SXebzBpV11@`|g590ulL{<&Gp@~`Pp zCGF^+;e!2HHLIuC)$`+@FT7Z5F`26QNZg5wB>b&m8)5Sz3Ep0fF|Gv#h?CAR154HJ~;* zZv_Ve5!TIqb;%~H#gDn@CDG%AeM=CuwhJ&_D6`V-jCsnpu@EklmWKH*?v<9hdrm)f zV_SfLv2by5`GJQXO)@)6kYu)U2c?R(Gt6*atiz0_>NEn9(~4LI17JobU3lS>$e$!i zen==>iFvtZ>xRjEVq783(Klw z-RWY^w^UsAh5Lf+(G$nuanrYcR8SL`nO9X-Hg)7VHpBHNXbwDpha0fO@LbZXHOEk0 z71TOcr@IzucJr-LAf&G}o7oNBO-oDrck{9oaDgU(sA{9lNjN~fEf6ci4JrMSg*fCx za6jj0`+$1>bq2x_DLSngz3>8_y2CAu%{$65pJFbQL>qD|V&;4!ngK?Ghc|cvj$wSW zD}D4G$1qV96%<^$SW-d{}v(`oNeue`^suB6kE!~G9T(5+FwNqB& zcpCUdJ4;dhX~KkltUG!|q!xab+S`79O#Y5)RT`%!f&&xo|jcTH|+mS-qocHeJI(wgEnQ8wa8C*jD0xT8Ed;?kmPWl)o-< z0NK-2no17TEQGLgGh;0rkkbT4?@48SC;%1SjHeo!_ZW z&jUwDO@0hhwkr+$@mH&~(+tp-mHvZ0Q+et2uIUslo2b*b25U{(y`a2G0A0ZnhSWE2 z_}OcJb1eo{Bi!68;@iyo0*j|3i#c{iF;)3^0CO;#fhkLdN9ViS>CVxwgKf{Ss_1u0 z!~H_q2y*}tlEEnV1qIm(q00ap1&PyBNldwDBB5O!BcG8opSi)oPLTGvn82IBfSB(BEnSnyF2}}xiT~iMNWF|$R6*YM!W8Mt3lKv8C zd2nW87e5vJko#@A+c!!?oHc+OP64qTSHK`Vf-VjK#J3hL(M+_s&p@&Tt=1jz+_0P; zD}TL~{^p9V3a`lPv-NT>=xk{N_XIZvbO3JApVxAxV=oH)%K5Hx^fx-+FjQHg0Kk2Ij}u61Z#h#?ckb zqOL-*pp{7!KLf8r&x>HjHCqO{NTBAQJ-wOSnSZ`sP9J`6$qP<7%a=e$5OY-+1G)-P zB2&Qop`Rn*;ZLvLW*x+#`${_MAb)RGKXkaHezorgAfB7aU`%?HKyrX@GPy-6)gQMx zhPe26_qy=oE^zdN>&s~CkWogwH)(SQXE{~-@hd08az&}6V zh1DVb`Tt-1e_0{%C@}lpvZh>UITm&y_y;R@1+>1TKR3SrpBLE*Kb=h3_0K;y<2RH4 z^OuyaAJwtD|MO{KJXVU8)epGr_cK_IBNu$3B&rZy5`NYq?yJnTY5o?zS!ZXc| z9k4dMx?+_2%;N7QUt8hz#+VSa;QT-KDwNu>oE0u{-kB_PYm9fy&$Rek$lD{i)QGVj z>POyLv(J-{uoeG~A+U;Dl&a-1uijn~c-OVn5qQgv|5)(&A5y6VXIb^yLGv;jWakU? zGsAvP?ccijeN}s4%s;l}MoFz~8k=c0Cf`@C95H5;9x;C>m4p&r^u$;(*uH2%L8|ng z9f&oBBn>`9FE-q&DUIlo>}L(g>SIU)KSuYFPP}{fstOal<}-75rAO&{N_@8;*?2)C zT8W>!cwNarLcDo*;XOXN`r7G6s}iL(U;Nu9T`Fu+w-tdIM+?pkn0_vhU^G7$;j|`~;*+(fIP*|hIu1@0`d=ee1CyCYmSg#}om&Ll zzny!Y#2U=SjyDg#KDrQuQD!IQ5k>8%q@OO7kw&-=Yf{5b-;HV3u;A)9YcosJ-6BZ> zAKWF$3db|fRQH{E?{jqFBWfrnW*8q`RYmvt$2LuCwy8q%xWa=`3k9t>((Z4@7JH?FD02OC&6PaXlpI5#5R%jcu6d&Y zX}Pfpar9HU0VBPxlkxP=g7k zww96D_ z+J=%t>y#vU@lN7>jBzGfV75uk0swGmBujQSYY2*vMG*?Kb1^wKq?1~U!%#d>ErA%H8`1+7ew*6@f#lRyf3=i zvLYya!sa=*;7C3N(S{b&RX0`)tX9STw~;qW7DT|on|`XkuN(>RKHpP=nP4g?vDmCwki;y2X>u18Fc@;m*l49fpO(Z^C%aD6%Vg~J!k zf8LHGjVFue)G#Wx67lr>FXgi*0=Z>Yp5vH0yrG0BrpX#R_}gYJ)o`aui#SI;*((>PCg~3gVoQRA_EytX9Sg43 z)5(&CzwK}zC2mb99ZB3axe=Sg>uACICx4}g&os7Dc|+dE){bwpX0^eYab^UHX~tP` zotUJ5U{@`4QB9M8)T^TC;1vVyFg+pu@7uN$n0f}maRoU}89s0{aAe;LC);8AZ|Zl7 z+?C9|AVaft5pFswgETbDM0d?;wOgfGY(8uy;MnPvUz215o1Ksm$t2R5+d$aykTifS z1ELT9oMv$A4+Q&_Un`Bx{Wg|_t)H)+2%6?%FyMQV0 zt^P^__lp#U?ArqRqjk~Uf%8_V1N$FikDNY-)v?g9dF)7&76U^g1pP&H*fX+xe^^dPETfZh}~bQ z0{!`*TGq7J9hCGfL@s^H`|)P_Ok(5d4yoWSLOW>rc?!xa0&LUi4#1jPDxGeXT>u@e zx+RnDj(q#fY0GOs9mJ5=g-u`{Ws+neH~g+-GrUD*iYte=AB1jbFxu+tbK&?7zPWOA zcA%zgg7+>5PqWWFGWYeTY9i5wEkys7Z57cYWZBx;*`R7S)mCg=gkbs%A5U2DRgqMGP;)!HzCcSc z%Y1iehH~U*Z~a8_J=mLmiAW@xWk0e$&(l`JT1jgk*xZy?MoMHL?`uBcWbt{8U*1-N z^$|lwQWJ?Z*I(rvlVigbv|J5P$5sW72aeWy<)?@ z4Yvv>m@EgYi22jj0ggG3o)d}0emuS{(~P!MXDsF6Tq))Ldp)sgh;n)P;SWFk=nIy;JizXa{oNDAUbn>u&RZpg+F&riE}%mV&XPWW0m7Gh zQj$|BK7M{lV4tfIn9fe_ZIXuBaxb%Vfpx_hH$mtDFRCD^z!$9?OS6^{u;uz$M@N_y zX`OpPtE?FwM1k1aT`)DjV%70ja^%<(v6cHAvVHO(1c9p;jJ9TeD+Zd8dLp03F=Xoua6qv&pL#05 z6@;JP`jYW;UpB}tj3IFsgCZJnsE1E2c8M&>L~F=-hqA)V49MNKCN!76NB6otLar1S z7u&4H<|+OHEPDVnGg$>ive(%011gd;zdC|Z6F#FvoV`C*=k4ZH?hdTge#EmnecJAJ zmpp0|aleqX0SrA^i$3{vi|VHT<&)>ZE+6|-d?{%g;FroQ@nOcRQIkZH7jR8Y3`ll2 zM*}{cAsufB7$NtMR3mZK!ly!N!~mYTjlPHTy<6a^$+x`Web{_Jc~oUVc71@}~=H<~^9Fy#u}dc1khrqKoXu4wRKQJs;trT+{RjD4EXCnjtNclNLgYej5Eq;x3w(J-SRB3- zz+4dsQYrLu028)!(r?ceo8t3m(aBftnwo8&9xnc&%x?kzxPBO z9h{>i!zD^<7+{|(NNcnbcP~GX%{sZhWr<#3Y5FE1Z+nxMmWgl8p6fji33@ILHE**J zwWFebcxW2a3s#424ZX84CZ9WN?onA)6){Dm9$JbR4^p7;ffEuDcHQ?se|YrP1CRf3 z#$v`au&f6(+DDl0JOFYORupNypu>NE1X*`p?eA z{5M9PpMeH~R+&?xogQcli5eZH6*ThR9mx%;U{|fYq%%e$T2$?}Z6W*6sfX9o4z5#G zB9EUKo^fbVVk#?B2UUYUGwlc)vb@&Me}J;MJF-D!XWajI3g_&nHaox1Q$H0<#2(zy zn^}2wp-0!fNGqearzdTS=ZqUE2|Q@$gmdx(uC;uuiID42Fy|K#;Arh{gFDT70FZ*) z!&z#&XZ!4e<^D=|Eo6*75+%OXgd0@x3~^NK1y6cF^O!QZDebmQuaUgLqBI%vxjs@v zmPYA#uEdt3@4M4bGlM-zr?Rv$R`SF9M+0g`cq^m>=glEi459CPAbLr-%`ih|W%aS{ z5L#FAYzW}T2Hg~}Mtf8?(Dt6^>Eed|p@Z<8uB3#vch%pRaF`ZTJef$r@|?{w-@w{0z{XK_P(^B(A&K(w5%rDxMe>_$EFe{};q>jB6CZT5tiOQ@ku(vSK=V(j}I{D7d@pSzYkhO_C!uIpZJQ?G%!wa zbkZr8s2FjDThOg3UPtrr0o{c^jGn09agrNOR*r1{Nf~*uPC&dAdPyw4M_X5NcpZ-c zx%mwgh3@JdIt0-;miUS+gjMl}PKAQPu*sG~dm|zsdOG0SvKO8A3*Eapp=29lNOj8y z7m*Y-!Yu4y67}SVb5{AA9Jzz+fS{2_t6X#UkP*^PTrlgky~nc4qrQ|Au2uR1bV#S+$w$e%rAnmAgtDzyGMD zo;JQ8aX#SLeDX0t2jE?TVy4eC-6;Prv%r%UHhzmz8o5M}9e6Ao=x7t(CrIPQGhc7Z zsdzEu74yGHmx>p^YvdRO>pFG4jW=tNw%*&oNPRCJz=;Dt5_fG@G$m#(mR`7+fxv@i27s{lWu{R=m9&2|^E z;T}e>C5BkUz4w23M7Fpl5HftX%+ggzp;mc$HtIT0$oB@@O7h(~RkLSE8%F2LNrQ8r zG&t0V@v$*lLfr68U68el4z82n<6)e-cy86i!@`Fbh6Pd;Xl)o!kPWQ3Qa14AjhP~u zYtFqn!o32L!2I-cr#X|agD-BN)UoKOz{Fm(-0+9o7W7}`x?TzW04RyE&8KWvuk&x0 z^{66pr7l~DSnJdfZ)#!7GyxTcbhvfO1rpcA@{h{OEXe^zk9xPGDC>xLyAHeGcs^$( zq7HUloL#Jq-^TVs>r}Up0rQfm*_E8~;F#}Z%v6oD=s^azk>eF!V2;;$|_>0SNN6G zL|ko)=a1S^=wMC2&I=UZH-LmXoV39#%)6pwx~QTY4*hxa!BEOZVZ|l>o!YUASY5_v z89v@ysB>NIPF;}JFv1ctYf+YpxG;&34fNbX2AK=J#Gg);srC)C4!3b2oARIjdlx_n zKVGptIp5tz<9&`AwoF>2rTkBFn~`X*lImi?0;Npk2h~O0Sx?&Eq!OK2ea6G@j)NFV z0@RVUPx6G@GT5=6kMNc79F;z<&!22zdz;2&_ncEIy1$8kA?|p*+oY{>3ki=iK+wz&MK1$DrtG(yZ9y(?+*I z%SnAbTj6B?6jdUoatiWugx-9btF;t|Qh`sF%2fAp{aS4%hRmS|ugHCx8x+Y&HX!p; zzUP{oF64ZK+|XP#PX+yGQcLzwjW!Y|&6qb|{{!V<19)Yb^?)Km*2NZ5~sZ zB0ApqS)}XXc1FxaM4%cI^Z#O3U0$)_qINn6XyD7momCT(0XDH*dF6NI@i=-sOjlXx z0X*#pq^b=d9hx`a1eXWhB>}Gf=lV3{hf5Np?s>+^RF}#RGiIQ44L!kGx#2#2AJn4e?={kBOmom)xrKHIcS zJ?7~21IUQHH3H?i)}iF>*TlBEOU(SB_Fxe`S;o9|3ZEc9JSy4GNOWs#LAR2Yi!&Ds zA`#xCu@&?x={P8}7OQTrRt}j8_p`N-SGotdsH9!Xhm< znS+Ib#dNeEH1zIvNP1iqF$@|49DagX7#?*?HgHrC4)Oj>%7~_kt zK;k8B9jrp!pCyTL=o!eZ6@6}QsaI~eSp%zk3Nzs%&b?!kEn|*u8Wp!^Th)o4f;Gv> z=yzb-^kJ2O&@F77ZYveB>*D_;Mkla@bO`dU5eI;|IH;CJAnUmRT?b)ZyqDQ|@ueQ3 z7F?9-#({E{KnJt1JN%!jI~MA~oEqCYIaHIm01nlP8<3(Km?l%r**kndcES6t5?LN| z6F4Z?B{`*8ap7d%2v~$3=;-(XyznZa9RH%I;a1Q4L#=y#prH_HDRjw^?;0H{Ofzt; z6@@GxlN+AhCa!bFb)r>c{mXRo*ZpX^i@(UG$}?~8SP{+k*}M zX#|uG=r|VMw0Tz1_wyM5Bn6CG6Hq8Pi+&@<$Ai|78a9`;nan-gTH%}^X$Kw4W3H~Q zRhXfu>rndz_H%lw@4|Lx(2VV&U0lg{#r+5F|Kk-DE(Uxf{~k?Jd>B#%asy^NwMx?4 z3Rv|h>!buO2u@@zIx6E1yhhAkm|-FltFPY_vmL~gMA-#f;H&Cb@W05oCA)Bilq2ms z_ydA;Zf-{^ngeBx-)Mhrd(u0mO>TIR+bsjP3b`R~ZgVCOChIk@`cwa@D<{^RqtPx4O~RP+eH6#&77!F z|7tZQ7oA^OxrB7SXRAoFJjQF1i3HMw?LH|%q9e5ToX_qRNO0fuKAldlgFL)ne{55?cbzRZ35^2d)ouYce8d;H-a zD94e>{b@g;32%@R1 zgV!~JL(a<&V}1jB`Ctk+ipncEQEt!AYJU)s7l&@dGq+=Hg^ehvo=*^M7?z>W1j_U} zcGafI2G;VP;zZu7-;}Y0&lOMRx=4?HYYf@Jy?T!?zLRT z8v--))9tsYnb_F)s}ZJh!_fiY*<|h?U^yDX4ut*zMKeiuqYv|V^iv`aXB%bAY_{YC zfIW`JqY^HZb#wJRK^b48X(H3xU-3QG9=L4IPt_$QhNC_)A;+QRD*h#&mC7>fc>Yf` z?SFZeK4meL!43_CO}@AG1h;M(^R}&DE4pN4@Y-*qVQxo2q9H1v7v7oWQxwrVn2 zhG!2Si9*?V+@Z4S2a_|P**TX@PSH z2@>>9PfvGvTyRE1%MU}Ae;jLeOe~kzBvDR7%i#ucmj$KrcYmSjY#0k6UNWK`h1$n< zB%jFL6xXn6{km60Mf$zoS20Q%4ic?R_g*uv|6oIaH_ZVDL$ALK{xg<8mLOgi$O~9i zAdBi}kPv;zS-kE|%+@zxnKjK$ekim)oi@=_@Vi4O!`53M85WIMJ_1&M!PoXT21KaIZJ(!2I z%0<1x&uPPZGDEUHS(M^OZSP(H<0$6c%5B+_QI>RiH#(K0_{CxA56D ztJ4Pa#`#&)(P$e~h{3Rx#AZ$Mx|lioJtZq%m{7~-*9;R#iThM+aUQC4lw=)&F#Qu|Mf-}ZEN$?azusv<$WTTdM=lHQs7WkAMoS%KSCQ=}b{yvKu=7|N5JB#H^XQ1~T@84wlZ zP$25u!wr|6YTtPKdpsI**+^clI6^!k*b5e&72_J#Utagd=z+5N)=lFg(~V?t(^X>% z?$<+?Ftm2rdnZ^28F=*&MPH_prGSRcOCL$;Wp3=y>Bd^-y=TX1uG{lIeA|1r2*n z2-T~rP<374^;ud-B|gpuyQ)RZ{3sR+#e;@j7Nxq<1vlp{Yi@gTGkId~Ws*$qjt#SB zkY3`tqS5+C%C z*r3BmQPPPl*hKaRa&96&n2}T-h0>k`V+xmV8?3*4(uZbKspDO{FSm{I1NJ*|#v9b# zZw~6S_n<5b0rSz63wc>5bu4(UpSG7*mwZqv*W|@D*GzJTj@Zfw04D<+^)RHDyiS|z znEazZzkK@+wbE|RXUV}&aEE~Wl)gO!tvNPU&Dr?_ZT+ z*fwZZZ(W_-Fec~$N%BM!6DJ~6axoZ_SAJU;@8R+&{tH{k8LuTXJFvtai60%B_0D!P zqn(15%X)&qD6}K0*gsR1>C6y=%j*IsW(CVut36vcuJ7wwN@i`$qkD9BDKf zH-q<80N)FwX=CH|ycP*Q^j01e&Chf^m1F{ieJ5i+xJvSusa~>UQ)f4A7`}BiAE@jy zQWq_I=jRi;FTRt?hPm;G%94{YxB6CZD=1}#D6C)SgUb9bJpn{#w?#k>nj5l?LiKYx zd2{F4qty$ghgssW3ZN)3=F8-L%w?#Ji;5AN^d>lcZcxn9?GuCqMP z^PEFnmQ44*7>GNd_Bv(0sdgR@QiWa_5$6eJ)RmxBQ1rLMihXvRhMNb%4g@E)rWKvd zEbH>9<{o714*sNXY#dGF$*GgNy;pxbqI%CYs3V%=oNF&)-`vl#$afwe_#TuTzN_9k zAiz+$P9%pdjw?9mf=$3SD`wW5N^@mBFQ#uWm(+oOrKY>9W|)ZESFWY$Q@@DwN%AD% zJveJH1m-bR>PyGq1?e9OQQx#tQ@$)qP9f;GM^Fc*c=q<-YCqeYmTYM4?jEJf=e$P0 zTtBJ*m@(}G>#_d9U^j-jBdK5sJ=J&o`EvNu{CByv8s1HFfH=Le zJs1^@HUH;pvO~E+46-I&`#`hSJ^!(fTZ6U?aHL{IQ1(Y-QD~u==&{#JRt0_xC?~l8 zFHwDxZ~@gU#OmH##1||bQiQp^_f_uycPZaxP;_3lIG*4GS3W0>& zr`-28-zP7%S#-<5m|VqUYut>S6sjVdLGK+!5Nzw14(Y|Q#6H$MUhMW7vD^D>Vq;>U zJTOF`)qZZ}Az!+AT134FtNYsS;GqeY8Ss^8L*De*H#_O{`8l~cr&5iL!@>MVT8^9T zk>_OT=4T6JN)EOzetEm3Sm}ypQDV(&Fle!A|A(_Ed`oftfH4McR5+*hE*u6wU54Y^=@USykUgNw&Am7dCKmD6^26WY^rbFY@+uN{9mqdJ)rjXGIm zDdgqlT@b3=J0I>S~;Es@f>KX_6<+kVdHEH~Y!Tl`5Z`*Qqr!1KMx#S30N zgy^b6a+pndWWAcJ;h~T5#`X=HoCeKmtUzgn)TFCVx8S0?R3~90=XHhP=DB60CswiM zDKO^J5-&Z@_^7}2z*O(YF(%HMyhYq)!a1r2qAVs#&MsFkkL+iSD;J z(zk|pX+H-FoJ;?o)X*BW*(Wu{y8|g??RHmB&~!nx=~%;69qAQ9D2}#(6&l|kUgK8D zk98Gc>6TdA8?681Y|SI}_o18eNKY!&*+#EuCJ<}&-hUZe;0m79JKd-C^GXk{qD;5Z z#rO%zBF*;Is^-^B36%YrOLF>eLr)bmcW!@N>!-4dJ~BnCJ+N=xEPmts>tTdH?YXi^ zWfcF>3tu-xePG!K7ekI+zR$k~PFZ?0gsd)kb1EYJZmM{8oa$iiNC%$m!&&2sW~!=O z&rmq7!ffo-U~VjO#V;2#Xm@y1Az3U|IO2(LU8&2mN#?viTnnmkj=sHU!PdIKM-?EB z^o4lpg6pK3nHD#1ZVJjdvASwEnrc^2ok!M+-H8*%{m;FLy~64~czi(AElOA5ManKu z>mA(^sMI)iqUL5@?)yy=QYg`W>be|yCSmDo`2nc2saUI(wD~pjwoM;553qhaTXShF z^#;vD^;1xg8U;lU2?t_8b-$)+N=8)zYaXL&SUQlHs*;nP-Q<*QFZpm=O$fnJHI=W} zx+GnFsgo;sN6^Vg>5PaLWPpZ~i^XVz(O#H$#WNLpQWUco`&XB=XU zJuENAN>a}&1DL0d-u{TpF_a5;BLvOdwIV(CimYY6|I(&4nNLe37FPH3=O37vo6i*- z`*94^|5*jgb4`C17&+%HtgUmwcOM?MD=IEN!Ns0lR@Sp8r(n7Fj91a-fk4a4W6dEd zu7Aog1?lPOVyRSz6Yv0$bI=P;riDh;DW?oOvDZ9|+e>=+y`!1-Bq0~wu_oBgSi1MW z3Y+6u`Vn^=^%6Sa<^HQ-4OdHwg7u%X(qh;Z4L29(Zl5^ICoi^zskO3jXe6L;E4gl( zBDYqaO^>}hJ|e@?9k;gJg^N0iJK9vaP|jYn+`ISBUYm9{9W@r&Xu{%LZ=myXj3CWv zd(ASjjZK=)xp{Vv;662KV6KpP8p@g33y#X%8TM{L%XUU~c?_$23Wd#HIO-edsX3|Z zD*K-)d~hv)yJ_8-JNF-biep)d=x=KbuS>n^ZN8&>Pw=NWc14%Xy8G@oP39krqe@9F z5tH0*E-i3lagaA=09|mV;yZ;ICLWeZ)>9Kk*_Xmz*Ib%ih)Mr)DJR!WXph+wiNtme zYd02ozUOvawbw)HZ-y0N=c?>74N6fb6$lc|UY8c@7INF!{$z@w=(DZU zg^bChaLV}j8NOqjV3Ge5gMw!#ID3BVk9M1Y+MLynZv1hZ-1K*h3j@hw?=98yRJM`V zBweV~QPNZ^@Lm>TXv_5NGjjDE_%RJ;c{W3-ELf8fWgB+m`@Q;jpVJ z;i31?BK7ghRq}mjY}$(@TP`)M(*N#iNvX+fy>DTh>V1n9{y+A6?`7{^ zjTTJ0=W*EAeEYDJJv4Q@=@XE?{ z<&)e;SVzv>>}*;9Aa7)p&=@_GVpc|`V{A-MEe=cXr0^D<)P7d#TxUQE&59P6%b ztKqHdu-N2Wz8H7PX;>I_d1jjhxLPH1FR4r7mN*vqJDYPEO8eO#Lf}5${pD9)OiWCq zDqj7ob^0`m$=$?)%KZFRMb2URGmRuC7Z=0Jm!I(+JQ#%;xMpolRk~&+!P33fzhj0` z@F{naVsB<&f-WpBHhTX2xs#(Kuog3AJH3zYMgF1w{so0&+uPNW2mf0b9^&bXM*+w zw}0&j+-y=(I(oNE%MDkVra6epI7X?CB_C9U9u*TgVCHxInjJ0!$% z*0B4sT$^Mf2rIr$%(UGFd;>P2SH3D+ZS;@s{eHZlv$J!V@AF$u;}fXMQ~HXjBtAaA z0>u&I^Qf@;n|@Wz?fFRp9pAvZtHlGi}?% z{`*lk-PL!W73ljT7+CeiO?AkvJUx*Sy0$Cg8 z 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 UE-)&$xd9C0IsX9d#{5|Pe`qLcKmY&$ diff --git a/manifest.json b/manifest.json index eaf16df..7213d9a 100644 --- a/manifest.json +++ b/manifest.json @@ -6,16 +6,14 @@ "en": "Armadietto is a remoteStorage server written for Node.js.", "fr": "Armadietto est un serveur remoteStorage écrit pour node.js." }, - "version": "0.2.0", + "version": "1.0.1~ynh2", "url": "https://github.com/remotestorage/armadietto", "upstream": { - "license": "WTFPL", - "website": "https://example.com", - "demo": "https://demo.example.com", - "admindoc": "https://yunohost.org/packaging_apps", - "userdoc": "https://yunohost.org/apps", - "code": "https://some.forge.com/example/example" + "license": "MIT", + "website": "https://remotestorage.io/", + "code": "https://github.com/remotestorage/armadietto" }, + "license": "WTFPL", "maintainer": { "name": "bencharp", "email": "contact@bencharp.com", @@ -32,35 +30,22 @@ "install" : [ { "name": "domain", - "type": "domain", - "ask": { - "en": "Choose a domain name for your armadietto remoteStorage server", - "fr": "Choisissez un nom de domaine pour votre serveur remoteStorage armadietto" - }, - "example": "store.yunohost.packaging" + "type": "domain" }, { "name": "path", "type": "path", - "ask": { - "en": "Choose a path for armadietto", - "fr": "Choisissez un chemin pour armadietto" - }, "example": "/", "default": "/" }, { "name": "is_public", "type": "boolean", + "default": true, "help": { "en": "Would you like to restrein the access to this web site?", "fr": "Souhaitez-vous limiter l'accès à ce site web ?" - }, - "ask": { - "en": "Is it a public site?", - "fr": "Est-ce un site publique ?" - }, - "default": true + } }, { "name": "is_signup", diff --git a/scripts/_common.sh b/scripts/_common.sh index 013b3c1..2a28ffc 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -5,7 +5,9 @@ #================================================= # dependencies used by the app -# pkg_dependencies="deb1 deb2 php$YNH_DEFAULT_PHP_VERSION-deb1 php$YNH_DEFAULT_PHP_VERSION-deb2" +# pkg_dependencies="" + +NODEJS_VERSION=14 #================================================= # PERSONAL HELPERS diff --git a/scripts/backup b/scripts/backup index f99225d..f8732d8 100755 --- a/scripts/backup +++ b/scripts/backup @@ -30,8 +30,6 @@ app=$YNH_APP_INSTANCE_NAME final_path=$(ynh_app_setting_get --app=$app --key=final_path) domain=$(ynh_app_setting_get --app=$app --key=domain) -db_name=$(ynh_app_setting_get --app=$app --key=db_name) -phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) datadir=$(ynh_app_setting_get --app=$app --key=datadir) #================================================= @@ -62,26 +60,12 @@ ynh_backup --src_path="$datadir" --is_big ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" -#================================================= -# BACKUP THE PHP-FPM CONFIGURATION -#================================================= - -ynh_backup --src_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" - #================================================= # BACKUP FAIL2BAN CONFIGURATION #================================================= -ynh_backup --src_path="/etc/fail2ban/jail.d/$app.conf" -ynh_backup --src_path="/etc/fail2ban/filter.d/$app.conf" - -#================================================= -# SPECIFIC BACKUP -#================================================= -# BACKUP LOGROTATE -#================================================= - -ynh_backup --src_path="/etc/logrotate.d/$app" +# ynh_backup --src_path="/etc/fail2ban/jail.d/$app.conf" +# ynh_backup --src_path="/etc/fail2ban/filter.d/$app.conf" #================================================= # BACKUP SYSTEMD @@ -93,22 +77,12 @@ ynh_backup --src_path="/etc/systemd/system/$app.service" # BACKUP VARIOUS FILES #================================================= -ynh_backup --src_path="/etc/cron.d/$app" +# ynh_backup --src_path="/etc/cron.d/$app" -ynh_backup --src_path="/etc/$app/" +# ynh_backup --src_path="/etc/$app/" -#================================================= -# BACKUP THE MYSQL DATABASE -#================================================= -ynh_print_info --message="Backing up the MySQL database..." - -### (However, things like MySQL dumps *do* take some time to run, though the -### copy of the generated dump to the archive still happens later) - -ynh_mysql_dump_db --database="$db_name" > db.sql #================================================= # END OF SCRIPT #================================================= - ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." diff --git a/scripts/change_url b/scripts/change_url index 495b7eb..e025f6d 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -24,7 +24,7 @@ app=$YNH_APP_INSTANCE_NAME #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --time --weight=1 +ynh_script_progression --message="Loading installation settings..." --weight=1 # Needed for helper "ynh_add_nginx_config" final_path=$(ynh_app_setting_get --app=$app --key=final_path) @@ -37,7 +37,7 @@ final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= # BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP #================================================= -ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." --time --weight=1 +ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." --weight=1 # Backup the current version of the app ynh_backup_before_upgrade @@ -72,14 +72,14 @@ fi #================================================= # STOP SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 +ynh_script_progression --message="Stopping a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" #================================================= # MODIFY URL IN NGINX CONF #================================================= -ynh_script_progression --message="Updating NGINX web server configuration..." --time --weight=1 +ynh_script_progression --message="Updating NGINX web server configuration..." --weight=1 nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf @@ -116,19 +116,27 @@ fi #================================================= # START SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Starting a systemd service..." --time --weight=1 +ynh_script_progression --message="Starting a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" #================================================= # RELOAD NGINX #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --time --weight=1 +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 ynh_systemd_action --service_name=nginx --action=reload +#================================================= +# RESTART ARMADIETTO +#================================================= +ynh_script_progression --message="Start armadietto web server..." --weight=1 + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" + #================================================= # END OF SCRIPT #================================================= -ynh_script_progression --message="Change of URL completed for $app" --time --last +ynh_script_progression --message="Change of URL completed for $app" --last diff --git a/scripts/config b/scripts/config deleted file mode 100644 index b9e79f8..0000000 --- a/scripts/config +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash -# In simple cases, you don't need a config script. - -# With a simple config_panel.toml, you can write in the app settings, in the -# upstream config file or replace complete files (logo ...) and restart services. - -# The config scripts allows you to go further, to handle specific cases -# (validation of several interdependent fields, specific getter/setter for a value, -# display dynamic informations or choices, pre-loading of config type .cube... ). - -#================================================= -# GENERIC STARTING -#================================================= -# IMPORT GENERIC HELPERS -#================================================= - -source /usr/share/yunohost/helpers - -ynh_abort_if_errors - -#================================================= -# RETRIEVE ARGUMENTS -#================================================= - -final_path=$(ynh_app_setting_get $app final_path) - -#================================================= -# SPECIFIC GETTERS FOR TOML SHORT KEY -#================================================= - -get__amount() { - # Here we can imagine to have an API call to stripe to know the amount of donation during a month - local amount = 200 - - # It's possible to change some properties of the question by overriding it: - if [ $amount -gt 100 ] - then - cat << EOF -style: success -value: $amount -ask: - en: A lot of donation this month: **$amount €** -EOF - else - cat << EOF -style: danger -value: $amount -ask: - en: Not so much donation this month: $amount € -EOF - fi -} - -get__prices() { - local prices = "$(grep "DONATION\['" "$final_path/settings.py" | sed -r "s@^DONATION\['([^']*)'\]\['([^']*)'\] = '([^']*)'@\1/\2/\3@g" | sed -z 's/\n/,/g;s/,$/\n/')" - if [ "$prices" == "," ]; - then - # Return YNH_NULL if you prefer to not return a value at all. - echo YNH_NULL - else - echo $prices - fi -} - - -#================================================= -# SPECIFIC VALIDATORS FOR TOML SHORT KEYS -#================================================= -validate__publishable_key() { - - # We can imagine here we test if the key is really a publisheable key - (is_secret_key $publishable_key) && - echo 'This key seems to be a secret key' -} - -#================================================= -# SPECIFIC SETTERS FOR TOML SHORT KEYS -#================================================= -set__prices() { - - #--------------------------------------------- - # IMPORTANT: setter are trigger only if a change is detected - #--------------------------------------------- - for price in $(echo $prices | sed "s/,/ /"); do - frequency=$(echo $price | cut -d/ -f1) - currency=$(echo $price | cut -d/ -f2) - price_id=$(echo $price | cut -d/ -f3) - sed "d/DONATION\['$frequency'\]\['$currency'\]" "$final_path/settings.py" - - echo "DONATION['$frequency']['$currency'] = '$price_id'" >> "$final_path/settings.py" - done - - #--------------------------------------------- - # IMPORTANT: to be able to upgrade properly, you have to saved the value in settings too - #--------------------------------------------- - ynh_app_setting_set $app prices $prices -} - -#================================================= -# GENERIC FINALIZATION -#================================================= -ynh_app_config_run $1 diff --git a/scripts/install b/scripts/install index 32dfb3e..a414b4e 100755 --- a/scripts/install +++ b/scripts/install @@ -26,65 +26,44 @@ ynh_abort_if_errors domain=$YNH_APP_ARG_DOMAIN path_url=$YNH_APP_ARG_PATH -admin=$YNH_APP_ARG_ADMIN is_public=$YNH_APP_ARG_IS_PUBLIC -language=$YNH_APP_ARG_LANGUAGE -password=$YNH_APP_ARG_PASSWORD +is_signup=$YNH_APP_ARG_IS_SIGNUP -### If it's a multi-instance app, meaning it can be installed several times independently -### The id of the app as stated in the manifest is available as $YNH_APP_ID -### The instance number is available as $YNH_APP_INSTANCE_NUMBER (equals "1", "2"...) -### The app instance name is available as $YNH_APP_INSTANCE_NAME -### - the first time the app is installed, YNH_APP_INSTANCE_NAME = ynhexample -### - the second time the app is installed, YNH_APP_INSTANCE_NAME = ynhexample__2 -### - ynhexample__{N} for the subsequent installations, with N=3,4... -### The app instance name is probably what interests you most, since this is -### guaranteed to be unique. This is a good unique identifier to define installation path, -### db names... app=$YNH_APP_INSTANCE_NAME #================================================= # CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS #================================================= -### About --weight and --time -### ynh_script_progression will show to your final users the progression of each scripts. -### In order to do that, --weight will represent the relative time of execution compared to the other steps in the script. -### --time is a packager option, it will show you the execution time since the previous call. -### This option should be removed before releasing your app. -### Use the execution time, given by --time, to estimate the weight of a step. -### A common way to do it is to set a weight equal to the execution time in second +1. -### The execution time is given for the duration since the previous call. So the weight should be applied to this previous call. -ynh_script_progression --message="Validating installation parameters..." --time --weight=1 +ynh_script_progression --message="Validating installation parameters..." --weight=1 ### If the app uses NGINX as web server (written in HTML/PHP in most cases), the final path should be "/var/www/$app". ### If the app provides an internal web server (or uses another application server such as uWSGI), the final path should be "/opt/yunohost/$app" final_path=/opt/yunohost/$app test ! -e "$final_path" || ynh_die --message="This path already contains a folder" +# Only on / directory +if [ "$path_url" != "/" ]; then + ynh_die "Only / is allowed" +fi + # Register (book) web path ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url #================================================= # STORE SETTINGS FROM MANIFEST #================================================= -ynh_script_progression --message="Storing installation settings..." --time --weight=1 +ynh_script_progression --message="Storing installation settings..." --weight=1 ynh_app_setting_set --app=$app --key=domain --value=$domain ynh_app_setting_set --app=$app --key=path --value=$path_url -ynh_app_setting_set --app=$app --key=admin --value=$admin -ynh_app_setting_set --app=$app --key=language --value=$language +ynh_app_setting_set --app=$app --key=is_signup --value=$is_signup #================================================= # STANDARD MODIFICATIONS #================================================= # FIND AND OPEN A PORT #================================================= -ynh_script_progression --message="Finding an available port..." --time --weight=1 - -### Use these lines if you have to open a port for the application -### `ynh_find_port` will find the first available port starting from the given port. -### If you're not using these lines: -### - Remove the section "CLOSE A PORT" in the remove script +ynh_script_progression --message="Finding an available port..." --weight=1 # Find an available port port=$(ynh_find_port --port=8008) @@ -95,22 +74,21 @@ ynh_app_setting_set --app=$app --key=port --value=$port # If you do this and the app doesn't actually need you are CREATING SECURITY HOLES IN THE SERVER !) # Open the port -# ynh_script_progression --message="Configuring firewall..." --time --weight=1 +# ynh_script_progression --message="Configuring firewall..." --weight=1 # ynh_exec_warn_less yunohost firewall allow --no-upnp TCP $port #================================================= -# INSTALL NODEJS +# INSTALL DEPENDENCIES #================================================= -ynh_script_progression --message="Installing dependencies..." --time --weight=1 +ynh_script_progression --message="Installing dependencies..." --weight=4 -nodejs_version=10 - -ynh_install_nodejs -n $nodejs_version +ynh_install_nodejs --nodejs_version=$NODEJS_VERSION +ynh_use_nodejs #================================================= # CHECK AND CREATE FINAL_PATH #================================================= -ynh_script_progression --message="Setting up and create final app path..." --time --weight=1 +ynh_script_progression --message="Setting up and create final app path..." --weight=1 ynh_app_setting_set $app final_path $final_path # Download, check integrity, uncompress and patch the source from app.src @@ -119,40 +97,28 @@ ynh_app_setting_set $app final_path $final_path # Create final_path mkdir -p "$final_path" -#================================================= -# CREATE DEDICATED USER -#================================================= -ynh_script_progression --message="Configuring system user..." --time --weight=1 - -# Create a system user -ynh_system_user_create --username=$app --home_dir="$final_path" - #================================================= # NGINX CONFIGURATION #================================================= -ynh_script_progression --message="Configuring NGINX web server..." --time --weight=1 +ynh_script_progression --message="Configuring NGINX web server..." --weight=1 ### `ynh_add_nginx_config` will use the file conf/nginx.conf # Create a dedicated NGINX config ynh_add_nginx_config +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Configuring system user..." --weight=1 + +# Create a system user +ynh_system_user_create --username=$app --home_dir="$final_path" + #================================================= # SETUP SYSTEMD #================================================= -ynh_script_progression --message="Configuring a systemd service..." --time --weight=1 - -### `ynh_systemd_config` is used to configure a systemd script for an app. -### It can be used for apps that use sysvinit (with adaptation) or systemd. -### Have a look at the app to be sure this app needs a systemd script. -### `ynh_systemd_config` will use the file conf/systemd.service -### If you're not using these lines: -### - You can remove those files in conf/. -### - Remove the section "BACKUP SYSTEMD" in the backup script -### - Remove also the section "STOP AND REMOVE SERVICE" in the remove script -### - As well as the section "RESTORE SYSTEMD" in the restore script -### - And the section "SETUP SYSTEMD" in the upgrade script - +ynh_script_progression --message="Configuring a systemd service..." --weight=1 ynh_replace_string --match_string="__NODEJS_PATH__" --replace_string="$nodejs_path" --target_file="../conf/systemd.service" ynh_replace_string --match_string="__ENV_PATH__" --replace_string="$PATH" --target_file="../conf/systemd.service" @@ -161,12 +127,10 @@ ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" # Create a dedicated systemd config ynh_add_systemd_config -# PATH=$nodejs_path:$PATH - #================================================= # DEFINE ARMADIETTO OPTIONS & CREATE DIRECTORY FOR DATA #================================================= -ynh_script_progression --message="Configuring armadietto options..." --time --weight=1 +ynh_script_progression --message="Configuring armadietto options..." --weight=1 # Define armadietto module path modulepath="$node_version_path/$nodejs_version/lib/node_modules/armadietto/lib" @@ -185,33 +149,22 @@ ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$final_path/server.js" ynh_replace_string --match_string="__SIGNUP__" --replace_string="$is_signup" --target_file="$final_path/server.js" - - #================================================= # INSTALL ARMADIETTO #================================================= -ynh_script_progression --message="Install armadietto with npm..." --time --weight=1 +ynh_script_progression --message="Install armadietto with npm..." --weight=1 -ynh_use_nodejs cd $final_path npm -g i armadietto -ynh_script_progression --message="Armadietto installed..." --time --weight=1 +ynh_script_progression --message="Armadietto installed..." --weight=1 #================================================= # GENERIC FINALIZATION #================================================= # SETUP LOGROTATE #================================================= -ynh_script_progression --message="Configuring log rotation..." --time --weight=1 - -### `ynh_use_logrotate` is used to configure a logrotate configuration for the logs of this app. -### Use this helper only if there is effectively a log file for this app. -### If you're not using this helper: -### - Remove the section "BACKUP LOGROTATE" in the backup script -### - Remove also the section "REMOVE LOGROTATE CONFIGURATION" in the remove script -### - As well as the section "RESTORE THE LOGROTATE CONFIGURATION" in the restore script -### - And the section "SETUP LOGROTATE" in the upgrade script +ynh_script_progression --message="Configuring log rotation..." --weight=1 # Use logrotate to manage application logfile(s) ynh_use_logrotate @@ -219,7 +172,7 @@ ynh_use_logrotate #================================================= # SECURE FILES AND DIRECTORIES #================================================= -ynh_script_progression --message="Secure files and directories" --time --weight=1 +ynh_script_progression --message="Secure files and directories" --weight=1 # Set permissions to app files chown -R $app:$app "$final_path" @@ -228,48 +181,22 @@ chmod 0700 $datadir && chown $app:$app $datadir #================================================= # INTEGRATE SERVICE IN YUNOHOST #================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --time --weight=1 - -### `yunohost service add` integrates a service in YunoHost. It then gets -### displayed in the admin interface and through the others `yunohost service` commands. -### (N.B.: this line only makes sense if the app adds a service to the system!) -### If you're not using these lines: -### - You can remove these files in conf/. -### - Remove the section "REMOVE SERVICE INTEGRATION IN YUNOHOST" in the remove script -### - As well as the section "INTEGRATE SERVICE IN YUNOHOST" in the restore script -### - And the section "INTEGRATE SERVICE IN YUNOHOST" in the upgrade script +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" -### Additional options starting with 3.8: -### -### --needs_exposed_ports "$port" a list of ports that needs to be publicly exposed -### which will then be checked by YunoHost's diagnosis system -### (N.B. DO NOT USE THIS is the port is only internal!!!) -### -### --test_status "some command" a custom command to check the status of the service -### (only relevant if 'systemctl status' doesn't do a good job) -### -### --test_conf "some command" some command similar to "nginx -t" that validates the conf of the service -### -### Re-calling 'yunohost service add' during the upgrade script is the right way -### to proceed if you later realize that you need to enable some flags that -### weren't enabled on old installs (be careful it'll override the existing -### service though so you should re-provide all relevant flags when doing so) - - #================================================= # SETUP FAIL2BAN #================================================= -ynh_script_progression --message="Configuring Fail2Ban..." --time --weight=1 +# ynh_script_progression --message="Configuring Fail2Ban..." --weight=1 # Create a dedicated Fail2Ban config -ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" +# ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" #================================================= # SETUP SSOWAT #================================================= -ynh_script_progression --message="Configuring permissions..." --time --weight=1 +ynh_script_progression --message="Configuring permissions..." --weight=1 # Make app public if necessary if [ $is_public -eq 1 ] @@ -283,24 +210,24 @@ fi ### does have for example an admin interface or an API. # Only the admin can access the admin panel of the app (if the app has an admin panel) -ynh_permission_create --permission="admin" --url="/admin" --allowed=$admin +# ynh_permission_create --permission="admin" --url="/admin" --allowed=$admin # Everyone can access the API part # We don't want to display the tile in the SSO so we put --show_tile="false" # And we don't want the YunoHost admin to be able to remove visitors group to this permission, so we put --protected="true" -ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --show_tile="false" --protected="true" +# ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --show_tile="false" --protected="true" #================================================= # RELOAD NGINX #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --time --weight=1 +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 ynh_systemd_action --service_name=nginx --action=reload #================================================= # START ARMADIETTO #================================================= -ynh_script_progression --message="Start armadietto web server..." --time --weight=1 +ynh_script_progression --message="Start armadietto web server..." --weight=1 # Start a systemd service ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" @@ -308,5 +235,4 @@ ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$ap #================================================= # END OF SCRIPT #================================================= - -ynh_script_progression --message="Installation of $app completed" --time --last +ynh_script_progression --message="Installation of $app completed" --last diff --git a/scripts/remove b/scripts/remove index 07723e9..475bcdf 100755 --- a/scripts/remove +++ b/scripts/remove @@ -12,14 +12,12 @@ source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --time --weight=1 +ynh_script_progression --message="Loading installation settings..." --weight=1 app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) port=$(ynh_app_setting_get --app=$app --key=port) -db_name=$(ynh_app_setting_get --app=$app --key=db_name) -db_user=$db_name final_path=$(ynh_app_setting_get --app=$app --key=final_path) datadir=$(ynh_app_setting_get --app=$app --key=datadir) @@ -32,14 +30,14 @@ datadir=$(ynh_app_setting_get --app=$app --key=datadir) # Remove the service from the list of services known by YunoHost (added from `yunohost service add`) if ynh_exec_warn_less yunohost service status $app >/dev/null then - ynh_script_progression --message="Removing $app service integration..." --time --weight=1 + ynh_script_progression --message="Removing $app service integration..." --weight=1 yunohost service remove $app fi #================================================= # STOP AND REMOVE SERVICE #================================================= -ynh_script_progression --message="Stopping and removing the systemd service..." --time --weight=1 +ynh_script_progression --message="Stopping and removing the systemd service..." --weight=1 # Remove the dedicated systemd config ynh_remove_systemd_config @@ -52,18 +50,10 @@ ynh_script_progression --message="Removing logrotate configuration..." --time -- # Remove the app-specific logrotate config ynh_remove_logrotate -#================================================= -# REMOVE THE MYSQL DATABASE -#================================================= -ynh_script_progression --message="Removing the MySQL database..." --time --weight=1 - -# Remove a database if it exists, along with the associated user -ynh_mysql_remove_db --db_user=$db_user --db_name=$db_name - #================================================= # REMOVE APP MAIN DIR #================================================= -ynh_script_progression --message="Removing app main directory..." --time --weight=1 +ynh_script_progression --message="Removing app main directory..." --weight=1 # Remove the app directory securely ynh_secure_remove --file="$final_path" @@ -75,33 +65,25 @@ ynh_secure_remove --file="$final_path" # Remove the data directory if --purge option is used if [ "${YNH_APP_PURGE:-0}" -eq 1 ] then - ynh_script_progression --message="Removing app data directory..." --time --weight=1 + ynh_script_progression --message="Removing app data directory..." --weight=1 ynh_secure_remove --file="$datadir" fi #================================================= # REMOVE NGINX CONFIGURATION #================================================= -ynh_script_progression --message="Removing NGINX web server configuration..." --time --weight=1 +ynh_script_progression --message="Removing NGINX web server configuration..." --weight=1 # Remove the dedicated NGINX config ynh_remove_nginx_config -#================================================= -# REMOVE PHP-FPM CONFIGURATION -#================================================= -ynh_script_progression --message="Removing PHP-FPM configuration..." --time --weight=1 - -# Remove the dedicated PHP-FPM config -ynh_remove_fpm_config #================================================= # REMOVE DEPENDENCIES #================================================= -ynh_script_progression --message="Removing dependencies..." --time --weight=1 +ynh_script_progression --message="Removing dependencies..." --weight=1 -# Remove metapackage and its dependencies -ynh_remove_app_dependencies +ynh_remove_nodejs --nodejs_version=$NODEJS_VERSION #================================================= # CLOSE A PORT @@ -109,40 +91,34 @@ ynh_remove_app_dependencies if yunohost firewall list | grep -q "\- $port$" then - ynh_script_progression --message="Closing port $port..." --time --weight=1 + ynh_script_progression --message="Closing port $port..." --weight=1 ynh_exec_warn_less yunohost firewall disallow TCP $port fi #================================================= # REMOVE FAIL2BAN CONFIGURATION #================================================= -ynh_script_progression --message="Removing Fail2ban configuration..." --time --weight=1 +# ynh_script_progression --message="Removing Fail2ban configuration..." --weight=1 # Remove the dedicated Fail2Ban config -ynh_remove_fail2ban_config +# ynh_remove_fail2ban_config #================================================= # SPECIFIC REMOVE #================================================= # REMOVE VARIOUS FILES #================================================= -ynh_script_progression --message="Removing various files..." --time --weight=1 +ynh_script_progression --message="Removing various files..." --weight=1 # Remove a cron file -ynh_secure_remove --file="/etc/cron.d/$app" - -# Remove a directory securely -ynh_secure_remove --file="/etc/$app" - -# Remove the log files -ynh_secure_remove --file="/var/log/$app" +# ynh_secure_remove --file="" #================================================= # GENERIC FINALIZATION #================================================= # REMOVE DEDICATED USER #================================================= -ynh_script_progression --message="Removing the dedicated system user..." --time --weight=1 +ynh_script_progression --message="Removing the dedicated system user..." --weight=1 # Delete a system user ynh_system_user_delete --username=$app @@ -150,5 +126,4 @@ ynh_system_user_delete --username=$app #================================================= # END OF SCRIPT #================================================= - -ynh_script_progression --message="Removal of $app completed" --time --last +ynh_script_progression --message="Removal of $app completed" --last diff --git a/scripts/restore b/scripts/restore index f9a46dc..80aa975 100755 --- a/scripts/restore +++ b/scripts/restore @@ -24,22 +24,19 @@ ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --time --weight=1 +ynh_script_progression --message="Loading installation settings..." --weight=1 app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) path_url=$(ynh_app_setting_get --app=$app --key=path) final_path=$(ynh_app_setting_get --app=$app --key=final_path) -db_name=$(ynh_app_setting_get --app=$app --key=db_name) -db_user=$db_name -phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) datadir=$(ynh_app_setting_get --app=$app --key=datadir) #================================================= # CHECK IF THE APP CAN BE RESTORED #================================================= -ynh_script_progression --message="Validating restoration parameters..." --time --weight=1 +ynh_script_progression --message="Validating restoration parameters..." --weight=1 test ! -d $final_path \ || ynh_die --message="There is already a directory: $final_path " @@ -49,14 +46,14 @@ test ! -d $final_path \ #================================================= # RESTORE THE NGINX CONFIGURATION #================================================= -ynh_script_progression --message="Restoring the NGINX configuration..." --time --weight=1 +ynh_script_progression --message="Restoring the NGINX configuration..." --weight=1 ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" #================================================= # RECREATE THE DEDICATED USER #================================================= -ynh_script_progression --message="Recreating the dedicated system user..." --time --weight=1 +ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 # Create the dedicated user (if not existing) ynh_system_user_create --username=$app --home_dir="$final_path" @@ -64,7 +61,7 @@ ynh_system_user_create --username=$app --home_dir="$final_path" #================================================= # RESTORE THE APP MAIN DIR #================================================= -ynh_script_progression --message="Restoring the app main directory..." --time --weight=1 +ynh_script_progression --message="Restoring the app main directory..." --weight=1 ynh_restore_file --origin_path="$final_path" @@ -76,12 +73,12 @@ ynh_restore_file --origin_path="$final_path" # this will be treated as a security issue. chmod 750 "$final_path" chmod -R o-rwx "$final_path" -chown -R $app:www-data "$final_path" +chown -R $app:$app "$final_path" #================================================= # RESTORE THE DATA DIRECTORY #================================================= -ynh_script_progression --message="Restoring the data directory..." --time --weight=1 +ynh_script_progression --message="Restoring the data directory..." --weight=1 ynh_restore_file --origin_path="$datadir" --not_mandatory @@ -93,80 +90,48 @@ mkdir -p $datadir # files in some cases. # But FOR THE LOVE OF GOD, do not allow r/x for "others" on the entire folder - # this will be treated as a security issue. -chmod 750 "$datadir" +chmod 700 "$datadir" chmod -R o-rwx "$datadir" -chown -R $app:www-data "$datadir" - -#================================================= -# RESTORE THE PHP-FPM CONFIGURATION -#================================================= -ynh_script_progression --message="Restoring the PHP-FPM configuration..." --time --weight=1 - -ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" +chown -R $app:$app "$datadir" #================================================= # RESTORE FAIL2BAN CONFIGURATION #================================================= -ynh_script_progression --message="Restoring the Fail2Ban configuration..." --time --weight=1 +# ynh_script_progression --message="Restoring the Fail2Ban configuration..." --weight=1 -ynh_restore_file "/etc/fail2ban/jail.d/$app.conf" -ynh_restore_file "/etc/fail2ban/filter.d/$app.conf" -ynh_systemd_action --action=restart --service_name=fail2ban +# ynh_restore_file "/etc/fail2ban/jail.d/$app.conf" +# ynh_restore_file "/etc/fail2ban/filter.d/$app.conf" +# ynh_systemd_action --action=restart --service_name=fail2ban #================================================= # SPECIFIC RESTORATION #================================================= # REINSTALL DEPENDENCIES #================================================= -ynh_script_progression --message="Reinstalling dependencies..." --time --weight=1 +ynh_script_progression --message="Reinstalling dependencies..." --weight=1 -# Define and install dependencies -ynh_install_app_dependencies $pkg_dependencies - -#================================================= -# RESTORE THE MYSQL DATABASE -#================================================= -ynh_script_progression --message="Restoring the MySQL database..." --time --weight=1 - -db_pwd=$(ynh_app_setting_get --app=$app --key=mysqlpwd) -ynh_mysql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd -ynh_mysql_connect_as --user=$db_user --password=$db_pwd --database=$db_name < ./db.sql - -#================================================= -# RESTORE VARIOUS FILES -#================================================= -ynh_script_progression --message="Restoring various files..." --time --weight=1 - -ynh_restore_file --origin_path="/etc/cron.d/$app" - -ynh_restore_file --origin_path="/etc/$app/" +ynh_install_nodejs --nodejs_version=$NODEJS_VERSION +ynh_use_nodejs #================================================= # RESTORE SYSTEMD #================================================= -ynh_script_progression --message="Restoring the systemd configuration..." --time --weight=1 +ynh_script_progression --message="Restoring the systemd configuration..." --weight=1 ynh_restore_file --origin_path="/etc/systemd/system/$app.service" systemctl enable $app.service --quiet -#================================================= -# RESTORE THE LOGROTATE CONFIGURATION -#================================================= -ynh_script_progression --message="Restoring the logrotate configuration..." --time --weight=1 - -ynh_restore_file --origin_path="/etc/logrotate.d/$app" - #================================================= # INTEGRATE SERVICE IN YUNOHOST #================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --time --weight=1 +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" #================================================= # START SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Starting a systemd service..." --time --weight=1 +ynh_script_progression --message="Starting a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" @@ -175,7 +140,7 @@ ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$ap #================================================= # RELOAD NGINX AND PHP-FPM #================================================= -ynh_script_progression --message="Reloading NGINX web server and PHP-FPM..." --time --weight=1 +ynh_script_progression --message="Reloading NGINX web server and PHP-FPM..." --weight=1 ynh_systemd_action --service_name=php$phpversion-fpm --action=reload ynh_systemd_action --service_name=nginx --action=reload @@ -184,4 +149,4 @@ ynh_systemd_action --service_name=nginx --action=reload # END OF SCRIPT #================================================= -ynh_script_progression --message="Restoration completed for $app" --time --last +ynh_script_progression --message="Restoration completed for $app" --last diff --git a/scripts/upgrade b/scripts/upgrade index 855b543..d4a4bb0 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -12,16 +12,14 @@ source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --time --weight=1 +ynh_script_progression --message="Loading installation settings..." --weight=1 app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) -path_url=$(ynh_app_setting_get --app=$app --key=path) -admin=$(ynh_app_setting_get --app=$app --key=admin) +port=$(ynh_app_setting_get --app=$app --key=port) final_path=$(ynh_app_setting_get --app=$app --key=final_path) -language=$(ynh_app_setting_get --app=$app --key=language) -db_name=$(ynh_app_setting_get --app=$app --key=db_name) +datadir=$(ynh_app_setting_get --app=$app --key=datadir) #================================================= # CHECK VERSION @@ -38,7 +36,7 @@ upgrade_type=$(ynh_check_app_version_changed) #================================================= # BACKUP BEFORE UPGRADE THEN ACTIVE TRAP #================================================= -ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --time --weight=1 +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=1 # Backup the current version of the app ynh_backup_before_upgrade @@ -54,14 +52,14 @@ ynh_abort_if_errors #================================================= # STOP SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 +ynh_script_progression --message="Stopping a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" #================================================= # ENSURE DOWNWARD COMPATIBILITY #================================================= -ynh_script_progression --message="Ensuring downward compatibility..." --time --weight=1 +# ynh_script_progression --message="Ensuring downward compatibility..." --weight=1 # # N.B. : the followings setting migrations snippets are provided as *EXAMPLES* @@ -81,30 +79,12 @@ ynh_script_progression --message="Ensuring downward compatibility..." --time --w # ynh_app_setting_set --app=$app --key=final_path --value=$final_path #fi -### If nobody installed your app before 4.1, -### then you may safely remove these lines -# Cleaning legacy permissions -if ynh_legacy_permissions_exists; then - ynh_legacy_permissions_delete_all - - ynh_app_setting_delete --app=$app --key=is_public -fi - -if ! ynh_permission_exists --permission="admin"; then - # Create the required permissions - ynh_permission_create --permission="admin" --url="/admin" --allowed=$admin -fi - -# Create a permission if needed -if ! ynh_permission_exists --permission="api"; then - ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --show_tile="false" --protected="true" -fi #================================================= # CREATE DEDICATED USER #================================================= -ynh_script_progression --message="Making sure dedicated system user exists..." --time --weight=1 +ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 # Create a dedicated user (if not existing) ynh_system_user_create --username=$app --home_dir="$final_path" @@ -115,7 +95,7 @@ ynh_system_user_create --username=$app --home_dir="$final_path" if [ "$upgrade_type" == "UPGRADE_APP" ] then - ynh_script_progression --message="Upgrading source files..." --time --weight=1 + ynh_script_progression --message="Upgrading source files..." --weight=1 # Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$final_path" @@ -134,7 +114,7 @@ chown -R $app:www-data "$final_path" #================================================= # NGINX CONFIGURATION #================================================= -ynh_script_progression --message="Upgrading NGINX web server configuration..." --time --weight=1 +ynh_script_progression --message="Upgrading NGINX web server configuration..." --weight=1 # Create a dedicated NGINX config ynh_add_nginx_config @@ -142,18 +122,10 @@ ynh_add_nginx_config #================================================= # UPGRADE DEPENDENCIES #================================================= -ynh_script_progression --message="Upgrading dependencies..." --time --weight=1 +ynh_script_progression --message="Upgrading dependencies..." --weight=1 ynh_install_app_dependencies $pkg_dependencies -#================================================= -# PHP-FPM CONFIGURATION -#================================================= -ynh_script_progression --message="Upgrading PHP-FPM configuration..." --time --weight=1 - -# Create a dedicated PHP-FPM config -ynh_add_fpm_config - #================================================= # SPECIFIC UPGRADE #================================================= @@ -163,7 +135,7 @@ ynh_add_fpm_config #================================================= # UPDATE A CONFIG FILE #================================================= -ynh_script_progression --message="Updating a configuration file..." --time --weight=1 +ynh_script_progression --message="Updating a configuration file..." --weight=1 ### Same as during install ### @@ -188,52 +160,52 @@ chown $app:$app "$final_path/some_config_file" #================================================= # SETUP SYSTEMD #================================================= -ynh_script_progression --message="Upgrading systemd configuration..." --time --weight=1 +ynh_script_progression --message="Upgrading systemd configuration..." --weight=1 # Create a dedicated systemd config ynh_add_systemd_config #================================================= # GENERIC FINALIZATION -#================================================= -# SETUP LOGROTATE -#================================================= -ynh_script_progression --message="Upgrading logrotate configuration..." --time --weight=1 - -# Use logrotate to manage app-specific logfile(s) -ynh_use_logrotate --non-append - #================================================= # INTEGRATE SERVICE IN YUNOHOST #================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --time --weight=1 +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" #================================================= # START SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Starting a systemd service..." --time --weight=1 +ynh_script_progression --message="Starting a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" #================================================= # UPGRADE FAIL2BAN #================================================= -ynh_script_progression --message="Reconfiguring Fail2Ban..." --time --weight=1 +# ynh_script_progression --message="Reconfiguring Fail2Ban..." --weight=1 # Create a dedicated Fail2Ban config -ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" +# ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" #================================================= # RELOAD NGINX #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --time --weight=1 +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 ynh_systemd_action --service_name=nginx --action=reload +#================================================= +# RESTART ARMADIETTO +#================================================= +ynh_script_progression --message="Start armadietto web server..." --weight=1 + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" + #================================================= # END OF SCRIPT #================================================= -ynh_script_progression --message="Upgrade of $app completed" --time --last +ynh_script_progression --message="Upgrade of $app completed" --last