diff --git a/LICENSE b/LICENSE index dbbe355..94a9ed0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies @@ -7,15 +7,17 @@ Preamble - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. + The GNU General Public License is a free, copyleft license for +software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to +the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free -software for all its users. +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you @@ -24,34 +26,44 @@ them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. @@ -60,7 +72,7 @@ modification follow. 0. Definitions. - "This License" refers to version 3 of the GNU Affero General Public License. + "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. @@ -537,45 +549,35 @@ to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. + 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single +under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General +Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published +GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's +versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. @@ -633,29 +635,40 @@ the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. + GNU General Public License for more details. - You should have received a copy of the GNU Affero General Public License + You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see +For more information on this, and how to apply and follow the GNU GPL, see . + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index 9fb4c2f..9562d62 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,72 @@ # Lufi for YunoHost -[![Latest Version](https://img.shields.io/badge/version-_--_-green.svg?style=flat)](https://github.com/YunoHost-Apps/lufi_ynh/releases) -[![Status](https://img.shields.io/badge/status-working-yellow.svg?style=flat)](https://github.com/YunoHost-Apps/lufi_ynh/milestones) -[![Dependencies](https://img.shields.io/badge/dependencies-includes-lightgrey.svg?style=flat)](https://github.com/YunoHost-Apps/lufi_ynh#dependencies) -[![GitHub license](https://img.shields.io/badge/license-GPLv3-blue.svg?style=flat)](https://raw.githubusercontent.com/YunoHost-Apps/lufi_ynh/master/LICENSE) -[![Yunohost version](https://img.shields.io/badge/yunohost-2.4.2_tested-orange.svg?style=flat)](https://github.com/YunoHost/yunohost) -[![GitHub issues](https://img.shields.io/github/issues/YunoHost-Apps/lufi_ynh.svg?style=flat)](https://github.com/YunoHost-Apps/lufi_ynh/issues) +[![Integration level](https://dash.yunohost.org/integration/lufi.svg)](https://dash.yunohost.org/appci/app/lufi) +[![Install lufi with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=lufi) -## Lufi c'est quoi ? +*[Lire ce readme en français.](./README_fr.md)* -Il stocke vos fichiers et vous permet de les télécharger. - -Est-ce tout? Non. Tous les fichiers sont cryptés par le navigateur! Non chiffré. Ça ne marche pas. L'administrateur de l'instance Lufi ne pourra pas voir quel est votre administrateur réseau ou votre FAI. - -La clé de cryptage est une ancre (voir Fragment Identifier), ce qui signifie que cette partie n'est traitée que par le client et n'atteint pas le serveur. :-) - -Source: [Documentation de Lufi](https://framagit.org/luc/lufi/wikis/home) - -### Installation - -`$ sudo yunohost app install https://github.com/YunoHost-Apps/lufi_ynh --debug` - -### Mise à jour - -`$ sudo yunohost app upgrade lufi -u https://github.com/YunoHost-Apps/lufi_ynh --debug` - -## What is Lufi? +> *This package allow you to install lufi quickly and simply on a YunoHost server. +If you don't have YunoHost, please see [here](https://yunohost.org/#/install) to know how to install and enjoy it.* +## Overview It stores files and allows you to download them. -Is that all? No. All the files are encrypted by the browser! It means that your files never leave your computer unencrypted. The administrator of the Lufi instance you use will not be able to see what is in your file, neither will your network administrator, or your ISP. +Is that all? No. All the files are encrypted **by the browser**! It means that your files **never** leave your computer unencrypted. +The administrator of the Lufi instance you use will not be able to see what is in your file, neither will your network administrator, or your ISP. -The encryption key part of the URL is a anchor (Cf. Fragment Identifier), that means this part is only processed client-side and does not reach the server. :-) +The encryption key part of the URL is a anchor (Cf. [Fragment Identifier](https://en.wikipedia.org/wiki/Fragment_identifier)), that means this part is only processed client-side and does not reach the server. :-) -Source: [Lufi documentation](https://framagit.org/luc/lufi/wikis/home) +**Shipped version:** 0.03.5 -### Install +## Screenshots -`$ sudo yunohost app install https://github.com/YunoHost-Apps/lufi_ynh --debug` +![](https://framalibre.org/sites/default/files/screenshot_lufi_1.png) -### Update +## Demo -`$ sudo yunohost app upgrade lufi -u https://github.com/YunoHost-Apps/lufi_ynh --debug` +* [Official demo](https://demo.lufi.io/) + +## Configuration + +How to configure this app: a plain file with SSH. + +## Documentation + + * Official documentation: https://framagit.org/luc/lufi/wikis/home + +## YunoHost specific features + +#### Multi-users support + +Are LDAP and HTTP auth supported? **Yes** +Can the app be used by multiple users? **Yes** + +#### Supported architectures + +* x86-64b - [![Build Status](https://ci-apps.yunohost.org/ci/logs/lufi%20%28Community%29.svg)](https://ci-apps.yunohost.org/ci/apps/lufi/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/lufi%20%28Community%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/lufi/) +* Jessie x86-64b - [![Build Status](https://ci-stretch.nohost.me/ci/logs/lufi%20%28Community%29.svg)](https://ci-stretch.nohost.me/ci/apps/lufi/) + +## Links + + * Report a bug: https://github.com/YunoHost-Apps/lufi_ynh/issues + * App website: https://framagit.org/fiat-tux/hat-softwares/lufi + * YunoHost website: https://yunohost.org/ + +--- + +Developers info +---------------- + +**Only if you want to use a testing branch for coding, instead of merging directly into master.** +Please do your pull request to the [testing branch](https://github.com/YunoHost-Apps/lufi_ynh/tree/testing). + +To try the testing branch, please proceed like that. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/lufi_ynh/tree/testing --debug +or +sudo yunohost app upgrade lufi -u https://github.com/YunoHost-Apps/lufi_ynh/tree/testing --debug +``` + +**More information on the documentation page:** +https://yunohost.org/packaging_apps diff --git a/README_fr.md b/README_fr.md new file mode 100644 index 0000000..978f621 --- /dev/null +++ b/README_fr.md @@ -0,0 +1,116 @@ +# Lufi pour YunoHost + +[![Integration level](https://dash.yunohost.org/integration/lufi.svg)](https://dash.yunohost.org/appci/app/lufi) +[![Install lufi with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=lufi) + +*[Read this readme in english.](./README.md)* + +> *Ce package vous permet d'installer lufi rapidement et simplement sur un serveur Yunohost. +Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l'installer et en profiter.* + +## Vue d'ensemble +Il stocke vos fichiers et vous permet de les télécharger. + +Est-ce tout? Non. Tous les fichiers sont cryptés par le navigateur! Non chiffré. Ça ne marche pas. L'administrateur de l'instance Lufi ne pourra pas voir quel est votre administrateur réseau ou votre FAI. + +La clé de cryptage est une ancre (voir [Fragment Identifier](https://en.wikipedia.org/wiki/Fragment_identifier)), ce qui signifie que cette partie n'est traitée que par le client et n'atteint pas le serveur. :-) + +**Version incluse:** 0.03.5 + +## Captures d'écran + +![](https://framalibre.org/sites/default/files/screenshot_lufi_1.png) + +## Démo + +* [Démo officielle](https://demo.lufi.io/) + +## Configuration + +Comment configurer cette application: un fichier brut en SSH. + +## Documentation + + * Documentation officielle: https://framagit.org/luc/lufi/wikis/home + +## Caractéristiques spécifiques YunoHost + +#### Support multi-utilisateurs + +L'authentification LDAP et HTTP est-elle prise en charge? **Oui** +L'application peut-elle être utilisée par plusieurs utilisateurs? **Oui** + +#### Supported architectures + +* x86-64b - [![Build Status](https://ci-apps.yunohost.org/ci/logs/lufi%20%28Community%29.svg)](https://ci-apps.yunohost.org/ci/apps/lufi/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/lufi%20%28Community%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/lufi/) +* Jessie x86-64b - [![Build Status](https://ci-stretch.nohost.me/ci/logs/lufi%20%28Community%29.svg)](https://ci-stretch.nohost.me/ci/apps/lufi/) + +## Links + + * Signaler un bug: https://github.com/YunoHost-Apps/lufi_ynh/issues + * Site de l'application: https://framagit.org/fiat-tux/hat-softwares/lufi + * Site web YunoHost: https://yunohost.org/ + +--- + +Informations pour les développeurs +---------------- + +**Seulement si vous voulez utiliser une branche de test pour le codage, au lieu de fusionner directement dans la banche principale.** +Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/lufi_ynh/tree/testing). + +Pour essayer la branche testing, procédez comme suit. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/lufi_ynh/tree/testing --debug +ou +sudo yunohost app upgrade lufi -u https://github.com/YunoHost-Apps/lufi_ynh/tree/testing --debug +``` + +**Plus d'informations sur la page de documentation:** +https://yunohost.org/packaging_apps + +# Lufi for YunoHost + +[![Latest Version](https://img.shields.io/badge/version-_--_-green.svg?style=flat)](https://github.com/YunoHost-Apps/lufi_ynh/releases) +[![Status](https://img.shields.io/badge/status-working-yellow.svg?style=flat)](https://github.com/YunoHost-Apps/lufi_ynh/milestones) +[![Dependencies](https://img.shields.io/badge/dependencies-includes-lightgrey.svg?style=flat)](https://github.com/YunoHost-Apps/lufi_ynh#dependencies) +[![GitHub license](https://img.shields.io/badge/license-GPLv3-blue.svg?style=flat)](https://raw.githubusercontent.com/YunoHost-Apps/lufi_ynh/master/LICENSE) +[![Yunohost version](https://img.shields.io/badge/yunohost-2.4.2_tested-orange.svg?style=flat)](https://github.com/YunoHost/yunohost) +[![GitHub issues](https://img.shields.io/github/issues/YunoHost-Apps/lufi_ynh.svg?style=flat)](https://github.com/YunoHost-Apps/lufi_ynh/issues) + +## Lufi c'est quoi ? + +Il stocke vos fichiers et vous permet de les télécharger. + +Est-ce tout? Non. Tous les fichiers sont cryptés par le navigateur! Non chiffré. Ça ne marche pas. L'administrateur de l'instance Lufi ne pourra pas voir quel est votre administrateur réseau ou votre FAI. + +La clé de cryptage est une ancre (voir Fragment Identifier), ce qui signifie que cette partie n'est traitée que par le client et n'atteint pas le serveur. :-) + +Source: [Documentation de Lufi](https://framagit.org/luc/lufi/wikis/home) + +### Installation + +`$ sudo yunohost app install https://github.com/YunoHost-Apps/lufi_ynh.git` + +### Mise à jour + +`$ sudo yunohost app upgrade --verbose lufi -u https://github.com/YunoHost-Apps/lufi_ynh.git` + +## What is Lufi? + +It stores files and allows you to download them. + +Is that all? No. All the files are encrypted by the browser! It means that your files never leave your computer unencrypted. The administrator of the Lufi instance you use will not be able to see what is in your file, neither will your network administrator, or your ISP. + +The encryption key part of the URL is a anchor (Cf. Fragment Identifier), that means this part is only processed client-side and does not reach the server. :-) + +Source: [Lufi documentation](https://framagit.org/luc/lufi/wikis/home) + +### Install + +`$ sudo yunohost app install https://github.com/YunoHost-Apps/lufi_ynh.git` + +### Update + +`$ sudo yunohost app upgrade --verbose lufi -u https://github.com/YunoHost-Apps/lufi_ynh.git` diff --git a/check_process b/check_process index db2a351..7b9b7ae 100644 --- a/check_process +++ b/check_process @@ -4,8 +4,8 @@ domain="domain.tld" (DOMAIN) path="/path" (PATH) is_public="Yes" (PUBLIC|public=Yes|private=No) - admin="john" (USER) - + max_file_size=100 + admin="john" (USER) ; Checks pkg_linter=1 setup_sub_dir=1 @@ -14,24 +14,20 @@ setup_private=1 setup_public=1 upgrade=1 + upgrade=1 from_commit=1d53901957efcf8861b10efc8d3f081cadd2ba9e backup_restore=1 - multi_instance=0 - wrong_user=1 - wrong_path=1 + multi_instance=1 incorrect_path=1 - corrupt_source=1 - fail_download_source=1 - port_already_use=1 - final_path_already_use=1 + port_already_use=1 (8095) + change_url=1 ;;; Levels Level 1=auto Level 2=auto Level 3=auto - Level 4=na - Level 5=1 -# level 5: le test ne semble pas tout à fait savoir ce qu'est vraiment un "exit". + Level 4=1 + Level 5=auto Level 6=auto Level 7=auto Level 8=0 Level 9=0 - Level 10=0 + Level 10=0 diff --git a/conf/app.src b/conf/app.src new file mode 100644 index 0000000..50cce5a --- /dev/null +++ b/conf/app.src @@ -0,0 +1,5 @@ +SOURCE_URL=https://framagit.org/fiat-tux/hat-softwares/lufi/-/archive/0.03.5/lufi-0.03.5.tar.gz +SOURCE_SUM=aeb4bb4e7b4d5a7a12a7b8a49578e98c4ef8b6cb606b266b4531767a6ea6debe +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=tar.gz +SOURCE_IN_SUBDIR=true diff --git a/conf/lufi.conf.template b/conf/lufi.conf.template index 7052d31..4fc1e86 100644 --- a/conf/lufi.conf.template +++ b/conf/lufi.conf.template @@ -6,19 +6,31 @@ # see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings hypnotoad => { # array of IP addresses and ports you want to listen to + # you can specify a unix socket too, like 'http+unix://%2Ftmp%2Flufi.sock' listen => ['http://127.0.0.1:__PORT__'], - # if you use Lufi behind a reverse proxy like Nginx, you want ro set proxy to 1 + # if you use Lufi behind a reverse proxy like Nginx, you want to set proxy to 1 # if you use Lufi directly, let it commented - proxy => 1, + proxy => 1, + + # Please read http://mojolicious.org/perldoc/Mojo/Server/Hypnotoad#workers + # to adjust this to your server + workers => 30, + clients => 1, }, # put a way to contact you here and uncomment it + # you can put some HTML in it # MANDATORY - contact => 'webmaster@__DOMAIN__', + contact => 'Contact page', + + # put an URL or an email address to receive file reports and uncomment it + # it's for make reporting illegal files easy for users + # MANDATORY + report => 'webmaster@__DOMAIN__', # array of random strings used to encrypt cookies # optional, default is ['fdjsofjoihrei'], PLEASE, CHANGE IT - secrets => ['__SECRET__'], + secrets => ['__SECRET__'], # choose a theme. See the available themes in `themes` directory # optional, default is 'default' @@ -43,7 +55,7 @@ # max file size, in octets # you can write it 100*1024*1024 # optional, no default - #max_file_size => 104857600, + max_file_size => __MAX_FILE_SIZE__*1024*1024, # if you want to have piwik statistics, provide a piwik image tracker # only the image tracker is allowed, no javascript @@ -78,7 +90,7 @@ # example: you want to have Lufi under https://example.org/lufi/ # => set prefix to '/lufi' or to '/lufi/', it doesn't matter # optional, defaut is / - prefix => '__PATH__', + prefix => '__PATH__', # array of authorized domains for API calls. # if you want to authorize everyone to use the API: ['*'] @@ -102,12 +114,48 @@ # Optional, default to no-reply@lufi.io #mail_sender => 'no-reply@lufi.io', + # choose what database you want to use + # valid choices are sqlite, postgresql and mysql (all lowercase) + # optional, default is sqlite + dbtype => 'postgresql', + + # SQLite ONLY - only used if dbtype is set to sqlite # define a path to the SQLite database # you can define it relative to lufi directory or set an absolute path # remember that it has to be in a directory writable by Lufi user # optional, default is lufi.db #db_path => 'lufi.db', + # PostgreSQL ONLY - only used if dbtype is set to postgresql + # these are the credentials to access the PostgreSQL database + # mandatory if you choosed postgresql as dbtype + pgdb => { + database => '__DB_NAME__', + host => 'localhost', + # optional, default is 5432 + #port => 5432, + user => '__DB_USER__', + pwd => '__DB_PWD__', + # https://mojolicious.org/perldoc/Mojo/Pg#max_connections + # optional, default is 1 + #max_connections => 1, + }, + + # MySQL ONLY - only used if dbtype is set to mysql + # these are the credentials to access the MySQL database + # mandatory if you choosed mysql as dbtype + #mysqldb => { + # database => 'lufi', + # host => 'localhost', + # # optional, default is 3306 + # #port => 3306, + # user => 'DBUSER', + # pwd => 'DBPASSWORD', + # # https://metacpan.org/pod/Mojo::mysql#max_connections + # # optional, default is 5 (set to 0 to disable persistent connections) + # #max_connections => 5, + #}, + # define a path to the upload directory, where the uploaded files will be stored # you can define it relative to lufi directory or set an absolute path # remember that it has to be in a directory writable by Lufi user @@ -118,20 +166,79 @@ # set `ldap` if you want that only authenticated users can upload files # please note that everybody can still download files # optional, no default - #ldap => { - # uri => 'ldaps://ldap.example.org', - # user_tree => 'ou=users,dc=example,dc=org', - # bind_dn => ',ou=users,dc=example,dc=org', - # bind_user => 'uid=ldap_user', - # bind_pwd => 'secr3t', - # user_filter => '!(uid=ldap_user)' - #}, + __IS_PUBLIC__ldap => { + __IS_PUBLIC__ uri => 'ldap://localhost:389', # server URI + __IS_PUBLIC__ user_tree => 'dc=yunohost,dc=org', # search base DN + __IS_PUBLIC__ bind_dn => 'ou=users,dc=yunohost,dc=org', # search bind DN + __IS_PUBLIC__ #bind_pwd => 'secr3t', # search bind password + __IS_PUBLIC__ user_attr => 'uid', # user attribute (uid, mail, sAMAccountName, etc.) + __IS_PUBLIC__ #user_filter => '(!(uid=ldap_user))', # user filter (to exclude some users, etc.) + __IS_PUBLIC__ # optional start_tls configuration. See https://metacpan.org/pod/distribution/perl-ldap/lib/Net/LDAP.pod#start_tls + __IS_PUBLIC__ # don't set or uncomment if you don't want to configure it + __IS_PUBLIC__ #start_tls => { + __IS_PUBLIC__ # verify => 'optional', + __IS_PUBLIC__ # clientcert => '/etc/ssl/certs/ca-bundle.pem' + __IS_PUBLIC__ #} + __IS_PUBLIC__}, + + # set `htpasswd` if you want to use an htpasswd file instead of ldap + # see 'man htpasswd' to know how to create such file + #htpasswd => 'lufi.passwd', # if you've set ldap above, the session will last `session_duration` seconds before # the user needs to reauthenticate # optional, default is 3600 #session_duration => 3600, + # allow to add a password on files, asked before allowing to download files + # optional, default is 0 + allow_pwd_on_files => 1, + + # force all files to be in "Burn after reading mode" + # optional, default is 0 + #force_burn_after_reading => 0, + + # if set, the files' URLs will always use this domain + # optional, no default + #fixed_domain => 'example.org', + + # abuse reasons + # set an integer in the abuse field of a file in the database and it will not be downloadable anymore + # the reason will be displayed to the downloader, according to the reasons you will configure here. + # optional, no default + #abuse => { + # 0 => 'Copyright infringment', + # 1 => 'Illegal content', + #}, + + # Content-Security-Policy header that will be sent by Lufi + # Set to '' to disable CSP header + # https://content-security-policy.com/ provides a good documentation about CSP. + # https://report-uri.com/home/generate provides a tool to generate a CSP header. + # optional, default is "base-uri 'self'; connect-src 'self' ws://YOUR_HOST; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' blob:; media-src blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'" + #csp => "", + + # X-Frame-Options header that will be sent by Lufi + # Valid values are: 'DENY', 'SAMEORIGIN', 'ALLOW-FROM https://example.com/' + # Set to '' to disable X-Frame-Options header + # See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options + # Please note that this will add a "frame-ancestors" directive to the CSP header (see above) accordingly + # to the chosen setting (See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors) + # optional, default is 'DENY' + #x_frame_options => 'DENY', + + # X-Content-Type-Options that will be sent by Lufi + # See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options + # Set to '' to disable X-Content-Type-Options header + # optional, default is 'nosniff' + #x_content_type_options => 'nosniff', + + # X-XSS-Protection that will be sent by Lufi + # See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection + # Set to '' to disable X-XSS-Protection header + # optional, default is '1; mode=block' + #x_xss_protection => '1; mode=block', + ######################### # Lufi cron jobs settings ######################### @@ -144,13 +251,13 @@ # max size of the files directory, in octets # used by script/lufi cron watch to trigger an action # optional, no default - max_total_size => 1024*1024*1024, + #max_total_size => 10*1024*1024*1024, # default action when files directory is over max_total_size (used with script/lufi cron watch) # valid values are 'warn', 'stop-upload' and 'delete' # please, see readme # optional, default is 'warn' - policy_when_full => 'stop-upload', + #policy_when_full => 'warn', # images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task # if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted diff --git a/conf/lufi.service b/conf/lufi.service deleted file mode 100644 index 5f2f072..0000000 --- a/conf/lufi.service +++ /dev/null @@ -1,18 +0,0 @@ -[Unit] -Description=Image hosting and sharing service -Documentation=https://framagit.org/luc/lufi/wikis/home -Requires=network.target -After=network.target - -[Service] -Type=forking -User=www-data -RemainAfterExit=yes -WorkingDirectory=__FINALPATH__ -PIDFile=__FINALPATH__script/hypnotoad.pid -ExecStart=/usr/local/bin/carton exec hypnotoad script/lufi >> /var/log/lufi/production.log 2>&1 -ExecStop=/usr/local/bin/carton exec hypnotoad -s script/lufi >> /var/log/lufi/production.log 2>&1 -ExecReload=/usr/local/bin/carton exec hypnotoad script/lufi >> /var/log/lufi/production.log 2>&1 - -[Install] -WantedBy=multi-user.target diff --git a/conf/nginx.conf b/conf/nginx.conf index d761ca3..aed2041 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,4 +1,5 @@ -location __PATH__ { +#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; +location __PATH__/ { if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; } @@ -8,11 +9,11 @@ location __PATH__ { error_log /var/log/nginx/lufi.error.log; # This is important ! Make it OK with your Lutim configuration - client_max_body_size 40M; + client_max_body_size __MAX_FILE_SIZE__M; if ($request_uri ~* ^/(img|css|font|js)/) { - add_header Expires "Thu, 31 Dec 2037 23:55:55 GMT"; - add_header Cache-Control "public, max-age=315360000"; + more_set_headers Expires "Thu, 31 Dec 2037 23:55:55 GMT"; + more_set_headers Cache-Control "public, max-age=315360000"; } proxy_pass http://127.0.0.1:__PORT____PATH__; @@ -25,15 +26,12 @@ location __PATH__ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - # If you want to log the remote port of the file senders, you'll need that proxy_set_header X-Remote-Port $remote_port; - proxy_set_header X-Forwarded-Proto $scheme; # We expect the downsteam servers to redirect to the right hostname, so don't do any rewrite$ proxy_redirect off; - #--PRIVATE--# Include SSOWAT user panel. - #--PRIVATE--include conf.d/yunohost_panel.conf.inc; + # Include SSOWAT user panel. + include conf.d/yunohost_panel.conf.inc; } diff --git a/conf/systemd.service b/conf/systemd.service new file mode 100644 index 0000000..a8b2a68 --- /dev/null +++ b/conf/systemd.service @@ -0,0 +1,19 @@ +[Unit] +Description=Image hosting and sharing service +Documentation=https://framagit.org/luc/lufi/wikis/home +Requires=network.target +After=network.target + +[Service] +Type=simple +User=__APP__ +Group=__APP__ +RemainAfterExit=yes +WorkingDirectory=__FINALPATH__ +PIDFile=__FINALPATH__script/hypnotoad.pid +ExecStart=/usr/local/bin/carton exec hypnotoad script/lufi +ExecStop=/usr/local/bin/carton exec hypnotoad -s script/lufi +ExecReload=/usr/local/bin/carton exec hypnotoad script/lufi + +[Install] +WantedBy=multi-user.target diff --git a/manifest.json b/manifest.json index f49bf2f..b9dff0c 100644 --- a/manifest.json +++ b/manifest.json @@ -3,25 +3,25 @@ "id": "lufi", "packaging_format": 1, "requirements": { - "yunohost": ">= 2.7.2" + "yunohost": ">= 3.2.2" }, "description": { "en": "Self hosting files and sharing anonymous application", "fr": "Application d'hébergement et de partage de fichiers anonyme" }, - "version": "0.9.2-1", + "version": "0.03.5~ynh1", "url": "https://git.framasoft.org/luc/lufi", - "license": "AGPL", + "license": "AGPL-3.0-or-later", "maintainer": { "name": "frju365, cyp", "email": "win10@tutanota.com, cyp@rouquin.me" }, - "multi_instance": false, + "multi_instance": true, "services": [ "nginx" ], "arguments": { - "install" : [ + "install": [ { "name": "domain", "type": "domain", @@ -42,23 +42,24 @@ "default": "/lufi" }, { - "name": "admin", - "type": "user", + "name": "max_file_size", + "type": "string", "ask": { - "en": "Choose the Lufi administrator (must be an existing YunoHost user)", - "fr": "Choisissez un administrateur Lufi (doit être un utilisateur YunoHost)" + "en": "Choose a max file size, in Mo (0 = no limit)", + "fr": "Choisissez une taille de fichier maximum chemin, en Mo (0 = pas de limite)" }, - "example": "john" + "example": "100", + "default": "100" }, { "name": "is_public", + "type": "boolean", "ask": { - "en": "Uploading files is it public?", - "fr": "L'upload de fichiers est-il public ?" + "en": "Is it a public application?", + "fr": "Est-ce une application publique ?" }, - "choices": ["Yes", "No"], - "default": "No" + "default": true } ] } -} +} \ No newline at end of file diff --git a/scripts/.fonctions b/scripts/.fonctions deleted file mode 100644 index bdce6c5..0000000 --- a/scripts/.fonctions +++ /dev/null @@ -1,225 +0,0 @@ -#!/bin/bash - -ynh_version="2.5" - -YNH_VERSION () { # Returns the version number of the Yunohost moulinette - ynh_version=$(sudo yunohost -v | grep "moulinette:" | cut -d' ' -f2 | cut -d'.' -f1,2) -} - -CHECK_VAR () { # Verifies that the variable is not empty. - # $1 = Variable to be checked - # $2 = Display text on error - test -n "$1" || (echo "$2" >&2 && false) -} - -EXIT_PROPERLY () { # Causes the script to stop in the event of an error. And clean the residue. - trap '' ERR - echo -e "\e[91m \e[1m" # Shell in light red bold - echo -e "!!\n $app install's script has encountered an error. Installation was cancelled.\n!!" >&2 - - if type -t CLEAN_SETUP > /dev/null; then # Checks the existence of the function before executing it. - CLEAN_SETUP # Call the specific cleanup function of the install script. - fi - - # Compensates the ssowat bug that does not remove the app's input in case of installation error. - sudo sed -i "\@\"$domain$path/\":@d" /etc/ssowat/conf.json - - if [ "$ynh_version" = "2.2" ]; then - /bin/bash $script_dir/remove - fi - - ynh_die -} - -TRAP_ON () { # Activate signal capture - trap EXIT_PROPERLY ERR # Capturing exit signals on error -} - -TRAP_OFF () { # Ignoring signal capture until TRAP_ON - trap '' ERR # Ignoring exit signals -} - -CHECK_USER () { # Check the validity of the user admin - # $1 = User admin variable - ynh_user_exists "$1" || (echo "Wrong admin" >&2 && false) -} - -CHECK_PATH () { # Checks / at the beginning of the path. And his absence at the end. - if [ "${path:0:1}" != "/" ]; then # If the first character is not / - path="/$path" # Add / at the beginning of path - fi - if [ "${path:${#path}-1}" == "/" ] && [ ${#path} -gt 1 ]; then # If the last character is a / and it is not the only character. - path="${path:0:${#path}-1}" # Delete last character - fi -} - -CHECK_DOMAINPATH () { # Checks the availability of the path and domain. - sudo yunohost app checkurl $domain$path -a $app -} - -CHECK_FINALPATH () { # Checks that the destination folder is not already in use. - final_path=/var/www/$app - if [ -e "$final_path" ] - then - echo "This path already contains a folder" >&2 - false - fi -} - -SETUP_SOURCE () { # Download source, decompress and copu into $final_path - src=$(cat ../sources/source_md5 | awk -F' ' {'print $2'}) - sudo wget -nv -i ../sources/source_url -O $src - # Checks the checksum of the downloaded source. - md5sum -c ../sources/source_md5 --status || ynh_die "Corrupt source" - # Decompress source - if [ "$(echo ${src##*.})" == "tgz" ]; then - tar -x -f $src - elif [ "$(echo ${src##*.})" == "zip" ]; then - unzip -q $src - else - false # Unsupported archive format. - fi - # Copy file source - sudo cp -a $(cat ../sources/source_dir)/. "$final_path" - # Copy additional file and modified - if test -e "../sources/ajouts"; then - sudo cp -a ../sources/ajouts/. "$final_path" - fi -} - -ADD_SYS_USER () { # Créer un utilisateur système dédié à l'app - if ! ynh_system_user_exists "$app" # Test l'existence de l'utilisateur - then - sudo useradd -d /var/www/$app --system --user-group $app --shell /usr/sbin/nologin || (echo "Unable to create $app system account" >&2 && false) - fi -} - -STORE_MD5_CONFIG () { # Saves the checksum of the config file - # $1 = Name of the conf file for storage in settings.yml - # $2 = Full name and path of the conf file. - ynh_app_setting_set $app $1_file_md5 $(sudo md5sum "$2" | cut -d' ' -f1) -} - -CHECK_MD5_CONFIG () { # Created a backup of the config file if it was changed. - # $1 = Name of the conf file for storage in settings.yml - # $2 = Full name and path of the conf file.onf. - if [ "$(ynh_app_setting_get $app $1_file_md5)" != $(sudo md5sum "$2" | cut -d' ' -f1) ]; then - sudo cp -a "$2" "$2.backup.$(date '+%d.%m.%y_%Hh%M,%Ss')" # Si le fichier de config a été modifié, créer un backup. - fi -} - -### REMOVE SCRIPT - -REMOVE_NGINX_CONF () { # Delete nginx configuration - if [ -e "/etc/nginx/conf.d/$domain.d/$app.conf" ]; then # Delete nginx config - echo "Delete nginx config" - sudo rm "/etc/nginx/conf.d/$domain.d/$app.conf" - sudo service nginx reload - fi -} - -REMOVE_LOGROTATE_CONF () { # Delete logrotate configuration - if [ -e "/etc/logrotate.d/$app" ]; then - echo "Delete logrotate config" - sudo rm "/etc/logrotate.d/$app" - fi -} - -SECURE_REMOVE () { # Deleting a folder with variable verification - chaine="$1" # The argument must be given between simple quotes '', to avoid interpreting the variables. - no_var=0 - while (echo "$chaine" | grep -q '\$') # Loop as long as there are $ in the string - do - no_var=1 - global_var=$(echo "$chaine" | cut -d '$' -f 2) # Isole the first variable found. - only_var=\$$(expr "$global_var" : '\([A-Za-z0-9_]*\)') # Isole completely the variable by adding the $ at the beginning and keeping only the name of the variable. Mostly gets rid of / and a possible path behind. - real_var=$(eval "echo ${only_var}") # `eval "echo ${var}` Allows to interpret a variable contained in a variable. - if test -z "$real_var" || [ "$real_var" = "/" ]; then - echo "Variable $only_var is empty, suppression of $chaine cancelled." >&2 - return 1 - fi - chaine=$(echo "$chaine" | sed "s@$only_var@$real_var@") # Replaces variable with its value in the string. - done - if [ "$no_var" -eq 1 ] - then - if [ -e "$chaine" ]; then - echo "Delete directory $chaine" - sudo rm -r "$chaine" - fi - return 0 - else - echo "No detected variable." >&2 - return 1 - fi -} - -REMOVE_SYS_USER () { # Delete user - if ynh_system_user_exists "$app" # Test user exist - then - sudo userdel $app - fi -} - -# Find a free port and return it -# -# example: port=$(ynh_find_port 8080) -# -# usage: ynh_find_port begin_port -# | arg: begin_port - port to start to search -ynh_find_port () { - port=$1 - test -n "$port" || ynh_die "The argument of ynh_find_port must be a valid port." - while netcat -z 127.0.0.1 $port # Check if the port is free - do - port=$((port+1)) # Else, pass to next port - done - echo $port -} - -#================================================= -# BACKUP -#================================================= - -# Manage a fail of the script -# -# Print a warning to inform that the script was failed -# Execute the ynh_clean_setup function if used in the app script -# -# usage of ynh_clean_setup function -# This function provide a way to clean some residual of installation that not managed by remove script. -# To use it, simply add in your script: -# ynh_clean_setup () { -# instructions... -# } -# This function is optionnal. -# -# Usage: ynh_exit_properly is used only by the helper ynh_check_error. -# You must not use it directly. -ynh_exit_properly () { - exit_code=$? - if [ "$exit_code" -eq 0 ]; then - ynh_die # Exit without error if the script ended correctly - fi - - trap '' EXIT # Ignore new exit signals - set +eu # Do not exit anymore if a command fail or if a variable is empty - - echo -e "!!\n $app's script has encountered an error. Its execution was cancelled.\n!!" >&2 - - 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 - - ynh_die # Exit with error status -} - -# Exit if an error occurs during the execution of the script. -# -# Stop immediatly the execution if an error occured or if a empty variable is used. -# The execution of the script is derivate to ynh_exit_properly function before exit. -# -# Usage: ynh_abort_if_errors -ynh_abort_if_errors () { - set -eu # Exit if a command fail, and if a variable is used unset. - trap ynh_exit_properly EXIT # Capturing exit signals on shell script -} diff --git a/scripts/_common.sh b/scripts/_common.sh new file mode 100644 index 0000000..d572836 --- /dev/null +++ b/scripts/_common.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +#================================================= +# COMMON VARIABLES +#================================================= + +# dependencies used by the app +pkg_dependencies="build-essential libssl-dev libio-socket-ssl-perl liblwp-protocol-https-perl libpq-dev postgresql cpanminus" + +#================================================= +# FUTURE OFFICIAL HELPERS +#================================================= + +# Start (or other actions) a service, print a log in case of failure and optionnaly wait until the service is completely started +# +# usage: ynh_systemd_action [-n service_name] [-a action] [ [-l "line to match"] [-p log_path] [-t timeout] [-e length] ] +# | arg: -n, --service_name= - Name of the service to start. Default : $app +# | arg: -a, --action= - Action to perform with systemctl. Default: start +# | arg: -l, --line_match= - Line to match - The line to find in the log to attest the service have finished to boot. +# If not defined it don't wait until the service is completely started. +# WARNING: When using --line_match, you should always add `ynh_clean_check_starting` into your +# `ynh_clean_setup` at the beginning of the script. Otherwise, tail will not stop in case of failure +# of the script. The script will then hang forever. +# | arg: -p, --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: -e, --length= - Length of the error log : Default : 20 +ynh_systemd_action() { + # Declare an array to define the options of this helper. + declare -Ar args_array=( [n]=service_name= [a]=action= [l]=line_match= [p]=log_path= [t]=timeout= [e]=length= ) + local service_name + local action + local line_match + local length + local log_path + local timeout + + # Manage arguments with getopts + ynh_handle_getopts_args "$@" + + local service_name="${service_name:-$app}" + local action=${action:-start} + local log_path="${log_path:-/var/log/$service_name/$service_name.log}" + local length=${length:-20} + local timeout=${timeout:-300} + + # Start to read the log + if [[ -n "${line_match:-}" ]] + then + local templog="$(mktemp)" + # Following the starting of the app in its log + if [ "$log_path" == "systemd" ] ; then + # Read the systemd journal + journalctl --unit=$service_name --follow --since=-0 --quiet > "$templog" & + # Get the PID of the journalctl command + local pid_tail=$! + else + # Read the specified log file + tail -F -n0 "$log_path" > "$templog" 2>&1 & + # Get the PID of the tail command + local pid_tail=$! + fi + fi + + ynh_print_info --message="${action^} the service $service_name" + + # Use reload-or-restart instead of reload. So it wouldn't fail if the service isn't running. + if [ "$action" == "reload" ]; then + action="reload-or-restart" + fi + + systemctl $action $service_name \ + || ( journalctl --no-pager --lines=$length -u $service_name >&2 \ + ; test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2 \ + ; false ) + + # Start the timeout and try to find line_match + if [[ -n "${line_match:-}" ]] + then + local i=0 + for i in $(seq 1 $timeout) + do + # Read the log until the sentence is found, that means the app finished to start. Or run until the timeout + if grep --quiet "$line_match" "$templog" + then + ynh_print_info --message="The service $service_name has correctly started." + break + fi + if [ $i -eq 3 ]; then + echo -n "Please wait, the service $service_name is ${action}ing" >&2 + fi + if [ $i -ge 3 ]; then + echo -n "." >&2 + fi + sleep 1 + done + if [ $i -ge 3 ]; then + echo "" >&2 + fi + if [ $i -eq $timeout ] + then + ynh_print_warn --message="The service $service_name didn't fully started before the timeout." + ynh_print_warn --message="Please find here an extract of the end of the log of the service $service_name:" + journalctl --no-pager --lines=$length -u $service_name >&2 + test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2 + fi + ynh_clean_check_starting + fi +} + +# Clean temporary process and file used by ynh_check_starting +# (usually used in ynh_clean_setup scripts) +# +# usage: ynh_clean_check_starting +ynh_clean_check_starting () { + # Stop the execution of tail. + kill -s 15 $pid_tail 2>&1 + ynh_secure_remove "$templog" 2>&1 +} \ No newline at end of file diff --git a/scripts/backup b/scripts/backup index 719e11f..15c84e6 100644 --- a/scripts/backup +++ b/scripts/backup @@ -1,27 +1,84 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Source app helpers +source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -# Get multi-instances specific variables +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ### Remove this function if there's nothing to clean before calling the remove script. + true +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info "Loading installation settings..." + app=$YNH_APP_INSTANCE_NAME -# Retrieve app settings -domain=$(ynh_app_setting_get "$app" domain) +final_path=$(ynh_app_setting_get $app final_path) +domain=$(ynh_app_setting_get $app domain) +db_name=$(ynh_app_setting_get $app db_name) -# Copy the app files -final_path="/var/www/${app}" -ynh_backup "${final_path}" "sources" 1 +#================================================= +# STANDARD BACKUP STEPS +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= +ynh_print_info "Backing up the main app directory..." -# Copy the nginx conf files -ynh_backup "/etc/nginx/conf.d/${domain}.d/${app}.conf" "nginx.conf" +ynh_backup "$final_path" -# Copy the lufi conf file -ynh_backup "${final_path}/lufi.conf" "lufi.conf" -ynh_backup "/etc/systemd/system/lufi.service" "systemd_lufi.service" -ynh_backup "/etc/cron.d/${app}" "cron_lufi" -ynh_backup "/etc/logrotate.d/${app}" "logrotate_lufi" -ynh_backup "/var/log/${app}/production.log" "production.log" \ No newline at end of file +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= +ynh_print_info "Backing up nginx web server configuration..." + +ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# BACKUP THE POSTGRESQL DATABASE +#================================================= +ynh_print_info "Backing up the PostgreSQL database..." + +ynh_psql_dump_db "$db_name" > db.sql + +#================================================= +# SPECIFIC BACKUP +#================================================= +# BACKUP LOGROTATE +#================================================= +ynh_print_info "Backing up logrotate configuration..." + +ynh_backup "/etc/logrotate.d/$app" + +#================================================= +# BACKUP SYSTEMD +#================================================= +ynh_print_info "Backing up systemd configuration..." + +ynh_backup "/etc/systemd/system/$app.service" + +#================================================= +# BACKUP CRON +#================================================= +ynh_print_info "Backing up cron configuration..." + +ynh_backup "/etc/cron.d/${app}" + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info "Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." \ No newline at end of file diff --git a/scripts/change_url b/scripts/change_url new file mode 100644 index 0000000..23da1c3 --- /dev/null +++ b/scripts/change_url @@ -0,0 +1,164 @@ +#!/bin/bash + +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +old_domain=$YNH_APP_OLD_DOMAIN +old_path=$YNH_APP_OLD_PATH + +new_domain=$YNH_APP_NEW_DOMAIN +new_path=$YNH_APP_NEW_PATH + +app=$YNH_APP_INSTANCE_NAME + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info "Loading installation settings..." + +# Needed for helper "ynh_add_nginx_config" +final_path=$(ynh_app_setting_get $app final_path) + +# Needed for lufi conf +port=$(ynh_app_setting_get $app port) +is_public=$(ynh_app_setting_get $app is_public) +db_name=$(ynh_app_setting_get "$app" db_name) +db_pwd=$(ynh_app_setting_get $app psqlpwd) +db_user=$db_name +secret=$(ynh_app_setting_get $app secret) +max_file_size=$(ynh_app_setting_get $app max_file_size) + +#================================================= +# CHECK THE SYNTAX OF THE PATHS +#================================================= + +test -n "$old_path" || old_path="/" +test -n "$new_path" || new_path="/" +new_path=$(ynh_normalize_url_path $new_path) +old_path=$(ynh_normalize_url_path $old_path) + +#================================================= +# CHECK WHICH PARTS SHOULD BE CHANGED +#================================================= + +change_domain=0 +if [ "$old_domain" != "$new_domain" ] +then + change_domain=1 +fi + +change_path=0 +if [ "$old_path" != "$new_path" ] +then + change_path=1 +fi + +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# MODIFY URL IN NGINX CONF +#================================================= +ynh_print_info "Updating nginx web server configuration..." + +nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf + +# Change the path in the nginx config file +if [ $change_path -eq 1 ] +then + # Make a backup of the original nginx config file if modified + ynh_backup_if_checksum_is_different "$nginx_conf_path" + # Set global variables for nginx helper + domain="$old_domain" + path_url="$new_path" + # Create a dedicated nginx config + ynh_add_nginx_config max_file_size +fi + +# Change the domain for nginx +if [ $change_domain -eq 1 ] +then + # Delete file checksum for the old conf file location + ynh_delete_file_checksum "$nginx_conf_path" + mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf + # Store file checksum for the new config file location + ynh_store_file_checksum "/etc/nginx/conf.d/$new_domain.d/$app.conf" +fi + +#================================================= +# SPECIFIC MODIFICATIONS +#================================================= +# SETUP LUFI +#================================================= +ynh_print_info "Configuring lufi..." + +domain="$new_domain" +path_url="$new_path" + +cp ../conf/lufi.conf.template "${final_path}/lufi.conf" +ynh_replace_string "__DOMAIN__" "$domain" "${final_path}/lufi.conf" +ynh_replace_string "__PATH__" "$path_url" "${final_path}/lufi.conf" +ynh_replace_string "__PORT__" "$port" "${final_path}/lufi.conf" +ynh_replace_string "__DB_NAME__" "$db_name" "${final_path}/lufi.conf" +ynh_replace_string "__DB_USER__" "$db_user" "${final_path}/lufi.conf" +ynh_replace_string "__DB_PWD__" "$db_pwd" "${final_path}/lufi.conf" +ynh_replace_string "__MAX_FILE_SIZE__" "$max_file_size" "${final_path}/lufi.conf" +if [ $max_file_size -eq 0 ]; then # Comment the limitation line if no limit + ynh_replace_string "max_file_size" "#max_file_size" "${final_path}/lufi.conf" +fi + +ynh_replace_string "__SECRET__" "$secret" "${final_path}/lufi.conf" +if [ $is_public -eq 0 ]; +then + ynh_replace_string "__IS_PUBLIC__" "" "${final_path}/lufi.conf" +else + ynh_replace_string "__IS_PUBLIC__" "#" "${final_path}/lufi.conf" +fi +ynh_store_file_checksum "${final_path}/lufi.conf" + +#================================================= +# GENERIC FINALISATION +#================================================= +# UPDATE SSOWAT +#================================================= +ynh_print_info "Reconfigure SSOwat" + +ynh_app_setting_set $app unprotected_uris "/" +if [ $is_public -eq 0 ] +then + if [ "$path_url" == "/" ]; then + # If the path is /, clear it to prevent any error with the regex. + path_url="" + fi + # Modify the domain to be used in a regex + domain_regex=$(echo "$domain" | sed 's@-@.@g') + ynh_app_setting_set $app protected_regex "$domain_regex$path_url/stats$","$domain_regex$path_url/manifest.webapp$","$domain_regex$path_url/$","$domain_regex$path_url/d/.*$","$domain_regex$path_url/m/.*$" +fi + +#================================================= +# RESTART LUFI +#================================================= + +ynh_systemd_action -n $app -a reload -l "Creating process id file" -p "$final_path/log/production.log" + +#================================================= +# RELOAD NGINX +#================================================= +ynh_print_info "Reloading nginx web server..." + +systemctl reload nginx + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info "Change of URL completed for $app" diff --git a/scripts/install b/scripts/install index 3b189bd..d55e7a7 100644 --- a/scripts/install +++ b/scripts/install @@ -1,145 +1,237 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -source .fonctions # Loads the generic functions usually used in the script -source /usr/share/yunohost/helpers # Source app helpers +source _common.sh +source /usr/share/yunohost/helpers -CLEAN_SETUP () { - # Clean installation residues that are not supported by the remove script. - # Clean hosts - echo "" +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ynh_clean_check_starting + + true } -TRAP_ON # Active trap to stop the script if an error is detected. +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# RETRIEVE ARGUMENTS FROM THE MANIFEST +#================================================= -# Retrieve arguments domain=$YNH_APP_ARG_DOMAIN -path=$YNH_APP_ARG_PATH -admin=$YNH_APP_ARG_ADMIN +path_url=$YNH_APP_ARG_PATH is_public=$YNH_APP_ARG_IS_PUBLIC +max_file_size=$YNH_APP_ARG_MAX_FILE_SIZE app=$YNH_APP_INSTANCE_NAME -script_dir=$PWD +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= +ynh_print_info "Validating installation parameters..." -# Check variable is not empty -CHECK_VAR "$app" "app name not set" -CHECK_VAR "$script_dir" "script_dir not set" +final_path=/var/www/$app +test ! -e "$final_path" || ynh_die "This path already contains a folder" -CHECK_USER "$admin" # Check username +# Normalize the url path syntax +path_url=$(ynh_normalize_url_path $path_url) -CHECK_PATH # Check and fix path syntax -CHECK_DOMAINPATH # Check and fix domain disponibility +# Check if max_file_size is a number +if ! [[ $max_file_size =~ "^[\-0-9]+$" ]] && [ $max_file_size -lt 0 ]; then + ynh_die "Max file must be a number positive or zero" +fi -CHECK_FINALPATH # Check final path +# Check web path availability +ynh_webpath_available $domain $path_url +# Register (book) web path +ynh_webpath_register $app $domain $path_url -# Check domain with regex -domain_regex=$(echo "$domain" | sed 's@-@.@g') -CHECK_VAR "$domain_regex" "domain_regex empty" +#================================================= +# FIND AND OPEN A PORT +#================================================= +ynh_print_info "Configuring firewall..." -port=$(ynh_find_port 8096) # Check port availability +# Find a free port +port=$(ynh_find_port 8095) +# Open this port +yunohost firewall allow --no-upnp TCP $port 2>&1 + +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= +ynh_print_info "Storing installation settings..." -# Save app settings -ynh_app_setting_set $app admin $admin ynh_app_setting_set $app domain $domain ynh_app_setting_set $app is_public $is_public ynh_app_setting_set $app port $port +ynh_app_setting_set $app path $path_url +ynh_app_setting_set $app max_file_size $max_file_size -# Install build-essential -ynh_package_update -ynh_package_install build-essential +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_print_info "Installing dependencies..." + +ynh_install_app_dependencies $pkg_dependencies +# Install Carton +echo yes | cpanm Carton + +#================================================= +# CREATE A POSTGRESQL DATABASE +#================================================= +ynh_print_info "Creating a PostgreSQL database..." + +# Create postgresql database +ynh_psql_test_if_first_run +db_name=$(ynh_sanitize_dbid "$app") +db_user=$db_name +ynh_app_setting_set "$app" db_name "$db_name" +# Initialize database and store postgres password for upgrade +ynh_psql_setup_db "$db_name" "$db_user" +db_pwd=$(ynh_app_setting_get $app psqlpwd) # Password created in ynh_psql_setup_db function + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= +ynh_print_info "Setting up source files..." -# Copy files to the right place -sudo mkdir "${final_path}" ynh_app_setting_set $app final_path $final_path +# Download, check integrity, uncompress and patch the source from app.src +ynh_setup_source "$final_path" -# Get source -SETUP_SOURCE +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_print_info "Configuring nginx web server..." -# Copy it to Nginx conf directory -sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf +# Create a dedicated nginx config +ynh_add_nginx_config max_file_size -if [ "$is_public" = "Yes" ]; -then - sudo sed -i "s@#--PRIVATE--@@g" /etc/nginx/conf.d/$domain.d/$app.conf +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_print_info "Configuring system user..." + +# Create a system user +ynh_system_user_create $app + +#================================================= +# Copy and fix variable into lufi config +#================================================= +ynh_print_info "Configuring lufi..." + +cp ../conf/lufi.conf.template "${final_path}/lufi.conf" +ynh_replace_string "__DOMAIN__" "$domain" "${final_path}/lufi.conf" +ynh_replace_string "__PATH__" "$path_url" "${final_path}/lufi.conf" +ynh_replace_string "__PORT__" "$port" "${final_path}/lufi.conf" +ynh_replace_string "__DB_NAME__" "$db_name" "${final_path}/lufi.conf" +ynh_replace_string "__DB_USER__" "$db_user" "${final_path}/lufi.conf" +ynh_replace_string "__DB_PWD__" "$db_pwd" "${final_path}/lufi.conf" +ynh_replace_string "__MAX_FILE_SIZE__" "$max_file_size" "${final_path}/lufi.conf" +if [ $max_file_size -eq 0 ]; then # Comment the limitation line if no limit + ynh_replace_string "max_file_size" "#max_file_size" "${final_path}/lufi.conf" fi -## Copy and fix variable into lufi config -sudo cp ../conf/lufi.conf.template "${final_path}/lufi.conf" -sudo sed -i "s@__DOMAIN__@$domain@g" "${final_path}/lufi.conf" -sudo sed -i "s@__PATH__@$path@g" "${final_path}/lufi.conf" -sudo sed -i "s@__PORT__@$port@g" "${final_path}/lufi.conf" - secret=$(ynh_string_random 24) -CHECK_VAR "$secret" "secret empty" -sudo sed -i "s@__SECRET__@$secret@g" "${final_path}/lufi.conf" -STORE_MD5_CONFIG "lufi.conf" "${final_path}/lufi.conf" - -# Install systemd script -sudo cp ../conf/lufi.service /etc/systemd/system/lufi.service -sudo chown root: /etc/systemd/system/lufi.service -sudo sed -i "s@__FINALPATH__@$final_path/@g" /etc/systemd/system/lufi.service -## Start service auto -sudo systemctl enable lufi.service - -## Install cron -sudo cp ../conf/cron_lufi /etc/cron.d/$app -sudo sed -i "s@__FINALPATH__@$final_path/@g" /etc/cron.d/$app -sudo chmod +x $final_path/script/lufi - -# Install logrotate -sed -i "s@__FINALPATH__@$final_path@g" ../conf/logrotate -sudo cp ../conf/logrotate /etc/logrotate.d/$app - -# Install Carton -sudo apt-get install cpanminus -y -echo yes | sudo cpanm Carton - -# Install lufi via carton -sudo mkdir -p /var/log/$app/ -cd $final_path -sudo carton install 2>&1 | sudo tee -a "/var/log/$app/setup_carton.log" - -# Change variables in nginx configuration -sudo sed -i "s@__PATH__@$path@g" /etc/nginx/conf.d/$domain.d/$app.conf -sudo sed -i "s@__PORT__@$port@g" /etc/nginx/conf.d/$domain.d/$app.conf - -# Make app public or private -ynh_app_setting_set $app skipped_uris "/" -if [ "$is_public" = "No" ]; +ynh_app_setting_set $app secret $secret +ynh_replace_string "__SECRET__" "$secret" "${final_path}/lufi.conf" +if [ $is_public -eq 0 ]; then - if [ "$path" == "/" ]; then - path="" + ynh_replace_string "__IS_PUBLIC__" "" "${final_path}/lufi.conf" +else + ynh_replace_string "__IS_PUBLIC__" "#" "${final_path}/lufi.conf" +fi +ynh_store_file_checksum "${final_path}/lufi.conf" + +#================================================= +# SETUP CRON +#================================================= + +cp ../conf/cron_lufi /etc/cron.d/$app +ynh_replace_string "__FINALPATH__" "$final_path/" "/etc/cron.d/$app" +chmod +x $final_path/script/lufi + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_print_info "Configuring a systemd service..." + +# Create a dedicated systemd config +ynh_add_systemd_config + +#================================================= +# Install lufi's dependencies via carton +#================================================= +ynh_print_info "Installing lufi..." + +pushd $final_path +carton install --deployment --without=sqlite --without=mysql --without=htpasswd --without=test +popd + +#================================================= +# SETUP LOGROTATE +#================================================= +ynh_print_info "Configuring log rotation..." + +# Use logrotate to manage application logfile(s) +ynh_use_logrotate + +#================================================= +# ADVERTISE SERVICE IN ADMIN PANEL +#================================================= + +yunohost service add $app --log "$final_path/log/production.log" + +#================================================= +# SETUP SSOWAT +#================================================= +ynh_print_info "Configuring SSOwat..." + +ynh_app_setting_set $app unprotected_uris "/" +if [ $is_public -eq 0 ] +then + if [ "$path_url" == "/" ]; then + # If the path is /, clear it to prevent any error with the regex. + path_url="" fi - ynh_app_setting_set $app protected_regex "$domain_regex$path/stats$","$domain_regex$path/manifest.webapp$","$domain_regex$path/$","$domain_regex$path/d/.*$","$domain_regex$path/m/.*$" + # Modify the domain to be used in a regex + domain_regex=$(echo "$domain" | sed 's@-@.@g') + ynh_app_setting_set $app protected_regex "$domain_regex$path_url/stats$","$domain_regex$path_url/manifest.webapp$","$domain_regex$path_url/$","$domain_regex$path_url/d/.*$","$domain_regex$path_url/m/.*$" fi -# Making log symbolic link to /var/log -sudo touch /var/log/$app/production.log -sudo chown www-data: /var/log/$app/production.log -sudo ln -s /var/log/$app/production.log "$final_path/log/production.log" - +#================================================= # Configure owner -sudo chown -R www-data: $final_path +#================================================= +chown -R $app:$app "$final_path" + +#================================================= # Start lufi -sudo systemctl daemon-reload -sudo systemctl start lufi.service -sudo systemctl enable lufi.service +#================================================= -# Set right permissions on new files created at first start -sudo chown -R www-data: "$final_path" +systemctl enable $app.service +ynh_systemd_action -n $app -a start -l "Creating process id file" -p "$final_path/log/production.log" -# Add lufi as a service -sudo yunohost service add lufi -l $final_path/log/production.log - -if [ "$is_public" = "No" ]; -then - # Delete public access - ynh_app_setting_delete $app unprotected_uris - sudo yunohost app ssowatconf -fi +#================================================= +# RELOAD NGINX +#================================================= +ynh_print_info "Reloading nginx web server..." # Reload Nginx -sudo service nginx reload +systemctl reload nginx +yunohost app ssowatconf + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info "Installation of $app completed" diff --git a/scripts/remove b/scripts/remove index eef6b33..b7eb829 100644 --- a/scripts/remove +++ b/scripts/remove @@ -1,53 +1,124 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -u +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -if [ ! -e .fonctions ]; then - # Get file fonction if not been to the current directory - sudo cp ../settings/scripts/.fonctions ./.fonctions - sudo chmod a+rx .fonctions -fi -source .fonctions # Loads the generic functions usually used in the script -source /usr/share/yunohost/helpers # Source app helpers +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info "Loading installation settings..." -# Get multi-instances specific variables app=$YNH_APP_INSTANCE_NAME +final_path=$(ynh_app_setting_get $app final_path) domain=$(ynh_app_setting_get $app domain) +port=$(ynh_app_setting_get $app port) +db_name=$(ynh_app_setting_get $app db_name) +db_user=$db_name -# Stop lufi service -if [ -e "/etc/systemd/system/lufi.service" ]; then - echo "Delete systemd script" - sudo service lufi stop - sudo rm "/etc/systemd/system/lufi.service" - sudo systemctl disable lufi.service -fi +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE SERVICE FROM ADMIN PANEL +#================================================= -# Remove monitoring service Yunohost. -if sudo yunohost service status | grep -q lufi # Test l'existence du service dans Yunohost +# Remove a service from the admin panel, added by `yunohost service add` +if yunohost service status | grep -q $app then - echo "Remove lufi service" - sudo yunohost service remove lufi + echo "Remove $app service" + yunohost service remove $app fi -SECURE_REMOVE '/var/www/$app' # Delete directory application +#================================================= +# STOP AND REMOVE SERVICE +#================================================= +ynh_print_info "Stopping and removing the systemd service" -REMOVE_NGINX_CONF # Delete nginx configuration +# Remove the dedicated systemd config +ynh_remove_systemd_config -# Delete cron -if [ -e "/etc/cron.d/$app" ]; then - echo "Delete cron" - sudo rm "/etc/cron.d/$app" +#================================================= +# REMOVE APP MAIN DIR +#================================================= +ynh_print_info "Removing app main directory" + +# Remove the app directory securely +ynh_secure_remove "$final_path" + +#================================================= +# REMOVE NGINX CONFIGURATION +#================================================= +ynh_print_info "Removing nginx web server configuration" + +# Remove the dedicated nginx config +ynh_remove_nginx_config + +#================================================= +# DELETE LOG +#================================================= + +ynh_secure_remove "/var/log/$app" + +#================================================= +# REMOVE LOGROTATE CONFIGURATION +#================================================= +ynh_print_info "Removing logrotate configuration" + +# Remove the app-specific logrotate config +ynh_remove_logrotate + +#================================================= +# CLOSE A PORT +#================================================= + +if yunohost firewall list | grep -q "\- $port$" +then + echo "Close port $port" + yunohost firewall disallow TCP $port 2>&1 fi -SECURE_REMOVE '/var/log/$app/' # Delete log +#================================================= +# REMOVE THE POSTGRESQL DATABASE +#================================================= +ynh_print_info "Removing the PostgreSQL database" -REMOVE_LOGROTATE_CONF # Delete logrotate configuration +ynh_psql_remove_db $db_name $db_user -ynh_package_remove build-essential || echo "build-essential already uninstalled" +#================================================= +# REMOVE DEPENDENCIES +#================================================= +ynh_print_info "Removing dependencies" -# Reload SSOwat configuration -sudo yunohost app ssowatconf +# Remove metapackage and its dependencies +ynh_remove_app_dependencies -echo -e "\e[0m" # Restore normal color +#================================================= +# GENERIC FINALIZATION +#================================================= +# REMOVE DEDICATED USER +#================================================= +ynh_print_info "Removing the dedicated system user" + +# Delete a system user +ynh_system_user_delete $app + +#================================================= +# SPECIFIC REMOVE +#================================================= +# REMOVE THE CRON FILE +#================================================= + +# Remove a cron file +ynh_secure_remove "/etc/cron.d/$app" + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info "Removal of $app completed" diff --git a/scripts/restore b/scripts/restore index 63933bd..e16363a 100644 --- a/scripts/restore +++ b/scripts/restore @@ -1,101 +1,139 @@ #!/bin/bash -# This restore script is adapted to Yunohost >=2.4 -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Source app helpers +source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -# The parameter $app is the id of the app instance ex: ynhexample__2 +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ynh_clean_check_starting + + true +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info "Loading settings..." + app=$YNH_APP_INSTANCE_NAME -# Get old parameter of the app domain=$(ynh_app_setting_get $app domain) -path=$(ynh_app_setting_get $app path) -is_public=$(ynh_app_setting_get $app is_public) +path_url=$(ynh_app_setting_get $app path) +final_path=$(ynh_app_setting_get $app final_path) +db_name=$(ynh_app_setting_get $app db_name) -ynh_package_update -ynh_package_install carton +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= +ynh_print_info "Validating restoration parameters..." -# Check domain/path availability -sudo yunohost app checkurl "${domain}${path}" -a "${app}" \ - || ynh_die "Path not available: ${domain}${path}" +ynh_webpath_available $domain $path_url \ + || ynh_die "Path not available: ${domain}${path_url}" +test ! -d $final_path \ + || ynh_die "There is already a directory: $final_path " -# Check $final_path -final_path="/var/www/${app}" -if [ -d "${final_path}" ]; then - ynh_die "There is already a directory: ${final_path}" -fi +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_print_info "Reinstalling dependencies..." -# Check configuration files nginx -nginx_conf="/etc/nginx/conf.d/${domain}.d/${app}.conf" -if [ -f "${nginx_conf}" ]; then - ynh_die "The NGINX configuration already exists at '${nginx_conf}'. You should safely delete it before restoring this app." -fi +# Define and install dependencies +ynh_install_app_dependencies $pkg_dependencies +# Install Carton +echo yes | cpanm Carton -# Check configuration files lufi -lufi_conf="${final_path}/${app}.conf" -if [ -f "${lufi_conf}" ]; then - ynh_die "The LUFI CONF configuration already exists at '${lufi_conf}'. You should safely delete it before restoring this app." -fi +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= -lufi_systemd="/etc/systemd/system/${app}.service" -if [ -f "${lufi_systemd}" ]; then - ynh_die "The LUFI SYSTEMD configuration already exists at '${lufi_systemd}'. You should safely delete it before restoring this app." -fi +ynh_restore_file "/etc/nginx/conf.d/$domain.d/$app.conf" -lufi_cron="/etc/cron.d/${app}" -if [ -f "${lufi_cron}" ]; then - ynh_die "The LUFI CRONTAB configuration already exists at '${lufi_cron}'. You should safely delete it before restoring this app." -fi +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= +ynh_print_info "Restoring the app main directory..." -lufi_logrotate="/etc/logrotate.d/${app}" -if [ -f "${lufi_logrotate}" ]; then - ynh_die "The LUFI LOGROTATE configuration already exists at '${lufi_logrotate}'. You should safely delete it before restoring this app." -fi +ynh_restore_file "$final_path" -lufi_log="/var/log/${app}/production.log" -if [ -f "${lufi_log}" ]; then - ynh_die "The LUFI LOG configuration already exists at '${lufi_log}'. You should safely delete it before restoring this app." -fi +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_print_info "Recreating the dedicated system user..." - # Restore sources & data -sudo cp -a ./sources "${final_path}" +# Create the dedicated user (if not existing) +ynh_system_user_create $app -# Set permissions -sudo chown -R www-data: "${final_path}" +#================================================= +# RESTORE THE POSTGRESQL DATABASE +#================================================= +ynh_print_info "Restoring the PostregSQL database..." -# Restore nginx configuration files -sudo cp -a ./nginx.conf "${nginx_conf}" +db_pwd=$(ynh_app_setting_get $app psqlpwd) +ynh_psql_test_if_first_run +ynh_psql_setup_db $db_name $db_name $db_pwd +ynh_psql_connect_as $db_name $db_pwd $db_name < ./db.sql -# Restore lufi configuration files -sudo cp -a ./lufi.conf "${lufi_conf}" +#================================================= +# RESTORE USER RIGHTS +#================================================= -# Restore service -sudo cp -a ./systemd_lufi.service "${lufi_systemd}" +# Restore permissions on app files +chown -R $app:$app "$final_path" -sudo cp -a ./cron_lufi "${lufi_cron}" -sudo cp -a ./logrotate_lufi "${lufi_logrotate}" +#================================================= +# SPECIFIC RESTORATION +#================================================= +# RESTORE SYSTEMD +#================================================= +ynh_print_info "Restoring the systemd configuration..." -# Create log production -sudo mkdir "/var/log/${app}/" -sudo cp -a ./production.log "${lufi_log}" -# Delete symbolic link and restore -sudo rm -fr "${final_path}/log/production.log" -sudo ln -s "/var/log/${app}/production.log" "${final_path}/log/production.log" +ynh_restore_file "/etc/systemd/system/$app.service" +systemctl enable $app.service +ynh_systemd_action -n $app -a start -l "Creating process id file" -p "$final_path/log/production.log" -# Reload lufi service -sudo systemctl daemon-reload -sudo systemctl start lufi.service -sudo systemctl enable lufi.service +#================================================= +# ADVERTISE SERVICE IN ADMIN PANEL +#================================================= -# Set ssowat config -if [ "$is_public" = "No" ]; -then - ynh_app_setting_delete $app skipped_uris -fi +yunohost service add $app --log "$final_path/log/production.log" -# Reload services -sudo systemctl reload nginx -sudo yunohost app ssowatconf \ No newline at end of file +#================================================= +# RESTORE THE LOGROTATE CONFIGURATION +#================================================= + +ynh_restore_file "/etc/logrotate.d/$app" + +#================================================= +# RESTORE THE CRON CONFIGURATION +#================================================= + +ynh_restore_file "/etc/cron.d/$app" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX +#================================================= +ynh_print_info "Reloading nginx web server..." + +systemctl reload nginx +yunohost app ssowatconf + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info "Restoration completed for $app" diff --git a/scripts/upgrade b/scripts/upgrade index adcf977..0699122 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,28 +1,31 @@ #!/bin/bash -set -eu - #================================================= -# GENERIC STARTING +# GENERIC START #================================================= # IMPORT GENERIC HELPERS #================================================= -source .fonctions +source _common.sh source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= +ynh_print_info "Loading installation settings..." app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get $app domain) -path=$(ynh_app_setting_get $app path) +path_url=$(ynh_app_setting_get $app path) is_public=$(ynh_app_setting_get $app is_public) port=$(ynh_app_setting_get $app port) final_path=$(ynh_app_setting_get $app final_path) secret=$(ynh_app_setting_get $app secret) +db_name=$(ynh_app_setting_get $app db_name) +db_user=$db_name +db_pwd=$(ynh_app_setting_get $app psqlpwd) +max_file_size=$(ynh_app_setting_get $app max_file_size) #================================================= # FIX OLD THINGS @@ -41,95 +44,198 @@ then # Si final_path n'est pas renseigné dans la config yunohost, cas d'ancien final_path=/var/www/$app fi -CHECK_PATH # Checks and corrects the syntax of the path. +if [ -z "$db_pwd" ]; then + # Need to install new dependencies before creating the new database + need_migration_from_sqlite_to_psql=1 +else + need_migration_from_sqlite_to_psql=0 +fi -# Get source -SETUP_SOURCE +if [ -z "$max_file_size" ]; then + max_file_size=100 # 100 Mo +fi + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_print_info "Backing up the app before upgrading (may take a while)..." + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + ynh_clean_check_starting + # restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# STANDARD UPGRADE STEPS +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= +ynh_print_info "Upgrading source files..." + +ynh_install_app_dependencies $pkg_dependencies + +ynh_setup_source "$final_path" + +#================================================= +# CREATE A POSTGRESQL DATABASE IF NEEDED +#================================================= + +if [ $need_migration_from_sqlite_to_psql -eq 1 ]; then + ynh_print_info "Creating a PostgreSQL database..." + # Create postgresql database + ynh_psql_test_if_first_run + db_name=$(ynh_sanitize_dbid "$app") + db_user=$db_name + ynh_app_setting_set "$app" db_name "$db_name" + # Initialize database and store postgres password for upgrade + ynh_psql_setup_db "$db_name" "$db_user" + db_pwd=$(ynh_app_setting_get $app psqlpwd) # Password created in ynh_psql_setup_db function +fi #================================================= # NGINX CONFIGURATION #================================================= +ynh_print_info "Upgrading nginx web server configuration..." -# Et copie le fichier de config nginx -sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf -# Modify Nginx configuration file and copy it to Nginx conf directory -sudo sed -i "s@__PATH__@$path@g" /etc/nginx/conf.d/$domain.d/$app.conf -sudo sed -i "s@__PORT__@$port@g" /etc/nginx/conf.d/$domain.d/$app.conf +# Create a dedicated nginx config +ynh_add_nginx_config max_file_size +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_print_info "Making sure dedicated system user exists..." -if [ "$is_public" = "Yes" ]; -then - sudo sed -i "s@#--PRIVATE--@@g" /etc/nginx/conf.d/$domain.d/$app.conf -fi +# Create a dedicated user (if not existing) +ynh_system_user_create $app #================================================= # SPECIFIC UPGRADE #================================================= # SETUP LUFI #================================================= +ynh_print_info "Configuring lufi..." -## Copie et configuration du fichier de conf. -CHECK_MD5_CONFIG "lufi.conf" "$final_path/lufi.conf" # Créé un backup du fichier de config si il a été modifié. -sudo cp ../conf/lufi.conf.template "$final_path/lufi.conf" -sudo sed -i "s@__DOMAIN__@$domain@g" "$final_path/lufi.conf" -sudo sed -i "s@__PATH__@$path@g" "$final_path/lufi.conf" -sudo sed -i "s@__PORT__@$port@g" "$final_path/lufi.conf" -sudo sed -i "s@__SECRET__@$secret@g" "${final_path}/lufi.conf" -STORE_MD5_CONFIG "lufi.conf" "$final_path/lufi.conf" # Réenregistre la somme de contrôle du fichier de config +cp ../conf/lufi.conf.template "${final_path}/lufi.conf" +ynh_replace_string "__DOMAIN__" "$domain" "${final_path}/lufi.conf" +ynh_replace_string "__PATH__" "$path_url" "${final_path}/lufi.conf" +ynh_replace_string "__PORT__" "$port" "${final_path}/lufi.conf" +ynh_replace_string "__DB_NAME__" "$db_name" "${final_path}/lufi.conf" +ynh_replace_string "__DB_USER__" "$db_user" "${final_path}/lufi.conf" +ynh_replace_string "__DB_PWD__" "$db_pwd" "${final_path}/lufi.conf" +ynh_replace_string "__MAX_FILE_SIZE__" "$max_file_size" "${final_path}/lufi.conf" +if [ $max_file_size -eq 0 ]; then # Comment the limitation line if no limit + ynh_replace_string "max_file_size" "#max_file_size" "${final_path}/lufi.conf" +fi -#================================================= -# SETUP SYSTEMD -#================================================= - -# Mise en place du script systemd -sudo systemctl stop $app -sudo cp ../conf/lufi.service /etc/systemd/system/$app.service -sudo chown root: /etc/systemd/system/$app.service -sudo sed -i "s@__FINALPATH__@$final_path/@g" /etc/systemd/system/$app.service -sudo sed -i "s@__APP__@$app@g" /etc/systemd/system/$app.service -## Démarrage auto du service -sudo systemctl enable $app +ynh_replace_string "__SECRET__" "$secret" "${final_path}/lufi.conf" +if [ $is_public -eq 0 ]; +then + ynh_replace_string "__IS_PUBLIC__" "" "${final_path}/lufi.conf" +else + ynh_replace_string "__IS_PUBLIC__" "#" "${final_path}/lufi.conf" +fi +ynh_store_file_checksum "${final_path}/lufi.conf" #================================================= # SETUP CRON #================================================= -sudo cp ../conf/cron_lufi /etc/cron.d/$app -sudo sed -i "s@__FINALPATH__@$final_path/@g" /etc/cron.d/$app - -#================================================= -# UPDATE LUFI WITH CARTON -#================================================= - -pushd $final_path # cd avec une stack pour revenir en arrière -echo yes | sudo carton install 2>&1 | sudo tee -a "/var/log/$app/setup_carton.log" -popd # Revient au dossier courant avant pushd +cp ../conf/cron_lufi /etc/cron.d/$app +ynh_replace_string "__FINALPATH__" "$final_path/" "/etc/cron.d/$app" +chmod +x $final_path/script/lufi #================================================= # SECURING FILES AND DIRECTORIES #================================================= -sudo chown -R www-data: $final_path +chown -R $app: "$final_path" + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_print_info "Upgrading systemd configuration..." + +# Create a dedicated systemd config +ynh_add_systemd_config + +#================================================= +# Install lufi's dependencies via carton +#================================================= + +pushd $final_path +# Migrate from SQLite to PostgreSQL +if [ $need_migration_from_sqlite_to_psql -eq 1 ]; then + # Preinstall with sqlite + carton install --deployment --without=mysql --without=htpasswd --without=test + + # if /var/log/$app/production.log is a symbolic link, then move it to $final_path/log/production.log + if [ ! -L "/var/log/$app/production.log" ] + then + mv "/var/log/$app/production.log" "$final_path/log/production.log" + chown -R $app: "$final_path/log/production.log" + fi + + # Restart with news parameters + ynh_systemd_action -n $app -a restart -l "Creating process id file" -p "$final_path/log/production.log" + + carton exec script/lufi sqliteToOtherDB +fi + +carton install --deployment --without=sqlite --without=mysql --without=htpasswd --without=test +popd + +#================================================= +# SETUP LOGROTATE +#================================================= +ynh_print_info "Upgrading logrotate configuration..." + +# Use logrotate to manage app-specific logfile(s) +ynh_use_logrotate --non-append + +#================================================= +# ADVERTISE SERVICE IN ADMIN PANEL +#================================================= + +yunohost service add $app --log "$final_path/log/production.log" #================================================= # RESTART LUFI #================================================= -sudo systemctl restart lufi.service +ynh_systemd_action -n $app -a reload -l "Creating process id file" -p "$final_path/log/production.log" #================================================= # SETUP SSOWAT #================================================= +ynh_print_info "Upgrading SSOwat configuration..." -ynh_app_setting_set $app skipped_uris "/" +ynh_app_setting_set $app unprotected_uris "/" if [ $is_public -eq 0 ] -then - ynh_app_setting_set "$app" unprotected_uris "/" +then + if [ "$path_url" == "/" ]; then + # If the path is /, clear it to prevent any error with the regex. + path_url="" + fi + # Modify the domain to be used in a regex + domain_regex=$(echo "$domain" | sed 's@-@.@g') + ynh_app_setting_set $app protected_regex "$domain_regex$path_url/stats$","$domain_regex$path_url/manifest.webapp$","$domain_regex$path_url/$","$domain_regex$path_url/d/.*$","$domain_regex$path_url/m/.*$" fi #================================================= # RELOAD NGINX #================================================= +ynh_print_info "Reloading nginx web server..." -sudo systemctl reload nginx -sudo yunohost app ssowatconf +systemctl reload nginx +yunohost app ssowatconf + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info "Upgrade of $app completed" diff --git a/sources/source_dir b/sources/source_dir deleted file mode 100644 index 99705ae..0000000 --- a/sources/source_dir +++ /dev/null @@ -1 +0,0 @@ -lufi-6f88225661129734c1e7c23e1412e9f7bf3f8966-6f88225661129734c1e7c23e1412e9f7bf3f8966 diff --git a/sources/source_md5 b/sources/source_md5 deleted file mode 100644 index b87a16f..0000000 --- a/sources/source_md5 +++ /dev/null @@ -1 +0,0 @@ -1c5c2a7a1a8617e6fb3739993f3b1ac7 lufi.zip diff --git a/sources/source_url b/sources/source_url deleted file mode 100644 index 12eae4c..0000000 --- a/sources/source_url +++ /dev/null @@ -1 +0,0 @@ -https://framagit.org/luc/lufi/repository/archive.zip?ref=6f88225661129734c1e7c23e1412e9f7bf3f8966