From 4b3cb9ec0322a4f21becabe57464103f20922d47 Mon Sep 17 00:00:00 2001 From: tituspijean Date: Sun, 27 Aug 2023 00:16:10 +0200 Subject: [PATCH 1/5] Initial packaging commit --- LICENSE | 675 ++++++++++++++++++++++++++++- conf/env | 11 + conf/nginx.conf | 32 +- conf/php-fpm.conf | 430 ------------------ conf/systemd.service | 10 +- config_panel.toml.example | 302 ------------- doc/ADMIN.md | 3 - doc/ADMIN_fr.md | 3 - doc/DESCRIPTION.md | 9 +- doc/DESCRIPTION_fr.md | 1 - doc/POST_INSTALL.md | 7 - doc/POST_UPGRADE.md | 1 - doc/PRE_INSTALL.md | 2 +- doc/PRE_INSTALL_fr.md | 1 - doc/PRE_UPGRADE.md | 1 - doc/screenshots/example.jpg | Bin 35451 -> 0 bytes doc/screenshots/homepage.png | Bin 0 -> 166439 bytes manifest.toml | 101 +---- scripts/_common.sh | 2 + scripts/backup | 49 --- scripts/config | 102 ----- scripts/install | 184 ++------ scripts/remove | 30 -- scripts/restore | 55 +-- scripts/upgrade | 107 ++--- sources/extra_files/app/.gitignore | 2 - sources/patches/.gitignore | 2 - tests.toml | 21 + tests.toml.example | 57 --- 29 files changed, 845 insertions(+), 1355 deletions(-) create mode 100644 conf/env delete mode 100644 conf/php-fpm.conf delete mode 100644 config_panel.toml.example delete mode 100644 doc/ADMIN.md delete mode 100644 doc/ADMIN_fr.md delete mode 100644 doc/DESCRIPTION_fr.md delete mode 100644 doc/POST_INSTALL.md delete mode 100644 doc/POST_UPGRADE.md delete mode 100644 doc/PRE_INSTALL_fr.md delete mode 100644 doc/PRE_UPGRADE.md delete mode 100644 doc/screenshots/example.jpg create mode 100644 doc/screenshots/homepage.png delete mode 100644 scripts/config delete mode 100644 sources/extra_files/app/.gitignore delete mode 100644 sources/patches/.gitignore create mode 100644 tests.toml delete mode 100644 tests.toml.example diff --git a/LICENSE b/LICENSE index 2026412..e2c9038 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,673 @@ -File containing the license of your package. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 -More information here: -https://choosealicense.com/ + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + 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, +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. 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 +have the freedom to distribute copies of free software (and charge for +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. + + 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. + + 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. + + 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. + + 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. + + TERMS AND CONDITIONS + + 0. Definitions. + + "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. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +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. 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 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 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 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 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 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 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. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + Copyright (C) 2021 Aliaksei Patapau + + This program is free software: you can redistribute it and/or modify + 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 General Public License for more details. + + 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 the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + ZeroUI Copyright (C) 2021 Aliaksei Patapau + 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 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/conf/env b/conf/env new file mode 100644 index 0000000..e712e34 --- /dev/null +++ b/conf/env @@ -0,0 +1,11 @@ +NODE_ENV=production +LISTEN_ADDRESS=127.0.0.1 +PORT=__PORT__ +ZU_SERVE_FRONTEND=true +ZU_SECURE_HEADERS=true +ZU_CONTROLLER_ENDPOINT=http://__ZT_ADDR__/ +ZU_CONTROLLER_TOKEN=__ZT_TOKEN__ +# Protection is ensured by YunoHost's SSOwat +ZU_DISABLE_AUTH=true +ZU_DEFAULT_PASSWORD=admin +ZU_DEFAULT_USERNAME=admin diff --git a/conf/nginx.conf b/conf/nginx.conf index 86f404e..d501267 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,28 +1,20 @@ #sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; location __PATH__/ { - # Path to source - alias __INSTALL_DIR__/; + proxy_pass http://127.0.0.1:__PORT__/; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + proxy_set_header X-Forwarded-Port $server_port; -### Example PHP configuration (remove it if not used) - index index.php; - - # Common parameter to increase upload size limit in conjunction with dedicated php-fpm file - #client_max_body_size 50M; - - try_files $uri $uri/ index.php; - location ~ [^/]\.php(/|$) { - fastcgi_split_path_info ^(.+?\.php)(/.*)$; - fastcgi_pass unix:/var/run/php/php__PHPVERSION__-fpm-__NAME__.sock; - - fastcgi_index index.php; - include fastcgi_params; - fastcgi_param REMOTE_USER $remote_user; - fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_param SCRIPT_FILENAME $request_filename; - } -### End of PHP configuration part + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; # Include SSOWAT user panel. include conf.d/yunohost_panel.conf.inc; + } diff --git a/conf/php-fpm.conf b/conf/php-fpm.conf deleted file mode 100644 index 13a53b0..0000000 --- a/conf/php-fpm.conf +++ /dev/null @@ -1,430 +0,0 @@ -; Start a new pool named 'www'. -; the variable $pool can be used in any directive and will be replaced by the -; pool name ('www' here) -[__NAMETOCHANGE__] - -; Per pool prefix -; It only applies on the following directives: -; - 'access.log' -; - 'slowlog' -; - 'listen' (unixsocket) -; - 'chroot' -; - 'chdir' -; - 'php_values' -; - 'php_admin_values' -; When not set, the global prefix (or /usr) applies instead. -; Note: This directive can also be relative to the global prefix. -; Default Value: none -;prefix = /path/to/pools/$pool - -; Unix user/group of processes -; Note: The user is mandatory. If the group is not set, the default user's group -; will be used. -user = __USER__ -group = __USER__ - -; The address on which to accept FastCGI requests. -; Valid syntaxes are: -; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on -; a specific port; -; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on -; a specific port; -; 'port' - to listen on a TCP socket to all addresses -; (IPv6 and IPv4-mapped) on a specific port; -; '/path/to/unix/socket' - to listen on a unix socket. -; Note: This value is mandatory. -listen = /var/run/php/php__PHPVERSION__-fpm-__NAMETOCHANGE__.sock - -; Set listen(2) backlog. -; Default Value: 511 (-1 on FreeBSD and OpenBSD) -;listen.backlog = 511 - -; Set permissions for unix socket, if one is used. In Linux, read/write -; permissions must be set in order to allow connections from a web server. Many -; BSD-derived systems allow connections regardless of permissions. -; Default Values: user and group are set as the running user -; mode is set to 0660 -listen.owner = www-data -listen.group = www-data -;listen.mode = 0660 -; When POSIX Access Control Lists are supported you can set them using -; these options, value is a comma separated list of user/group names. -; When set, listen.owner and listen.group are ignored -;listen.acl_users = -;listen.acl_groups = - -; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. -; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original -; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address -; must be separated by a comma. If this value is left blank, connections will be -; accepted from any ip address. -; Default Value: any -;listen.allowed_clients = 127.0.0.1 - -; Specify the nice(2) priority to apply to the pool processes (only if set) -; The value can vary from -19 (highest priority) to 20 (lower priority) -; Note: - It will only work if the FPM master process is launched as root -; - The pool processes will inherit the master process priority -; unless it specified otherwise -; Default Value: no set -; process.priority = -19 - -; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user -; or group is differrent than the master process user. It allows to create process -; core dump and ptrace the process for the pool user. -; Default Value: no -; process.dumpable = yes - -; Choose how the process manager will control the number of child processes. -; Possible Values: -; static - a fixed number (pm.max_children) of child processes; -; dynamic - the number of child processes are set dynamically based on the -; following directives. With this process management, there will be -; always at least 1 children. -; pm.max_children - the maximum number of children that can -; be alive at the same time. -; pm.start_servers - the number of children created on startup. -; pm.min_spare_servers - the minimum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is less than this -; number then some children will be created. -; pm.max_spare_servers - the maximum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is greater than this -; number then some children will be killed. -; ondemand - no children are created at startup. Children will be forked when -; new requests will connect. The following parameter are used: -; pm.max_children - the maximum number of children that -; can be alive at the same time. -; pm.process_idle_timeout - The number of seconds after which -; an idle process will be killed. -; Note: This value is mandatory. -pm = dynamic - -; The number of child processes to be created when pm is set to 'static' and the -; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. -; This value sets the limit on the number of simultaneous requests that will be -; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. -; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP -; CGI. The below defaults are based on a server without much resources. Don't -; forget to tweak pm.* to fit your needs. -; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' -; Note: This value is mandatory. -pm.max_children = 5 - -; The number of child processes created on startup. -; Note: Used only when pm is set to 'dynamic' -; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 -pm.start_servers = 2 - -; The desired minimum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -pm.min_spare_servers = 1 - -; The desired maximum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -pm.max_spare_servers = 3 - -; The number of seconds after which an idle process will be killed. -; Note: Used only when pm is set to 'ondemand' -; Default Value: 10s -;pm.process_idle_timeout = 10s; - -; The number of requests each child process should execute before respawning. -; This can be useful to work around memory leaks in 3rd party libraries. For -; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. -; Default Value: 0 -;pm.max_requests = 500 - -; The URI to view the FPM status page. If this value is not set, no URI will be -; recognized as a status page. It shows the following informations: -; pool - the name of the pool; -; process manager - static, dynamic or ondemand; -; start time - the date and time FPM has started; -; start since - number of seconds since FPM has started; -; accepted conn - the number of request accepted by the pool; -; listen queue - the number of request in the queue of pending -; connections (see backlog in listen(2)); -; max listen queue - the maximum number of requests in the queue -; of pending connections since FPM has started; -; listen queue len - the size of the socket queue of pending connections; -; idle processes - the number of idle processes; -; active processes - the number of active processes; -; total processes - the number of idle + active processes; -; max active processes - the maximum number of active processes since FPM -; has started; -; max children reached - number of times, the process limit has been reached, -; when pm tries to start more children (works only for -; pm 'dynamic' and 'ondemand'); -; Value are updated in real time. -; Example output: -; pool: www -; process manager: static -; start time: 01/Jul/2011:17:53:49 +0200 -; start since: 62636 -; accepted conn: 190460 -; listen queue: 0 -; max listen queue: 1 -; listen queue len: 42 -; idle processes: 4 -; active processes: 11 -; total processes: 15 -; max active processes: 12 -; max children reached: 0 -; -; By default the status page output is formatted as text/plain. Passing either -; 'html', 'xml' or 'json' in the query string will return the corresponding -; output syntax. Example: -; http://www.foo.bar/status -; http://www.foo.bar/status?json -; http://www.foo.bar/status?html -; http://www.foo.bar/status?xml -; -; By default the status page only outputs short status. Passing 'full' in the -; query string will also return status for each pool process. -; Example: -; http://www.foo.bar/status?full -; http://www.foo.bar/status?json&full -; http://www.foo.bar/status?html&full -; http://www.foo.bar/status?xml&full -; The Full status returns for each process: -; pid - the PID of the process; -; state - the state of the process (Idle, Running, ...); -; start time - the date and time the process has started; -; start since - the number of seconds since the process has started; -; requests - the number of requests the process has served; -; request duration - the duration in µs of the requests; -; request method - the request method (GET, POST, ...); -; request URI - the request URI with the query string; -; content length - the content length of the request (only with POST); -; user - the user (PHP_AUTH_USER) (or '-' if not set); -; script - the main script called (or '-' if not set); -; last request cpu - the %cpu the last request consumed -; it's always 0 if the process is not in Idle state -; because CPU calculation is done when the request -; processing has terminated; -; last request memory - the max amount of memory the last request consumed -; it's always 0 if the process is not in Idle state -; because memory calculation is done when the request -; processing has terminated; -; If the process is in Idle state, then informations are related to the -; last request the process has served. Otherwise informations are related to -; the current request being served. -; Example output: -; ************************ -; pid: 31330 -; state: Running -; start time: 01/Jul/2011:17:53:49 +0200 -; start since: 63087 -; requests: 12808 -; request duration: 1250261 -; request method: GET -; request URI: /test_mem.php?N=10000 -; content length: 0 -; user: - -; script: /home/fat/web/docs/php/test_mem.php -; last request cpu: 0.00 -; last request memory: 0 -; -; Note: There is a real-time FPM status monitoring sample web page available -; It's available in: /usr/share/php/7.0/fpm/status.html -; -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;pm.status_path = /status - -; The ping URI to call the monitoring page of FPM. If this value is not set, no -; URI will be recognized as a ping page. This could be used to test from outside -; that FPM is alive and responding, or to -; - create a graph of FPM availability (rrd or such); -; - remove a server from a group if it is not responding (load balancing); -; - trigger alerts for the operating team (24/7). -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;ping.path = /ping - -; This directive may be used to customize the response of a ping request. The -; response is formatted as text/plain with a 200 response code. -; Default Value: pong -;ping.response = pong - -; The access log file -; Default: not set -;access.log = log/$pool.access.log - -; The access log format. -; The following syntax is allowed -; %%: the '%' character -; %C: %CPU used by the request -; it can accept the following format: -; - %{user}C for user CPU only -; - %{system}C for system CPU only -; - %{total}C for user + system CPU (default) -; %d: time taken to serve the request -; it can accept the following format: -; - %{seconds}d (default) -; - %{miliseconds}d -; - %{mili}d -; - %{microseconds}d -; - %{micro}d -; %e: an environment variable (same as $_ENV or $_SERVER) -; it must be associated with embraces to specify the name of the env -; variable. Some exemples: -; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e -; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e -; %f: script filename -; %l: content-length of the request (for POST request only) -; %m: request method -; %M: peak of memory allocated by PHP -; it can accept the following format: -; - %{bytes}M (default) -; - %{kilobytes}M -; - %{kilo}M -; - %{megabytes}M -; - %{mega}M -; %n: pool name -; %o: output header -; it must be associated with embraces to specify the name of the header: -; - %{Content-Type}o -; - %{X-Powered-By}o -; - %{Transfert-Encoding}o -; - .... -; %p: PID of the child that serviced the request -; %P: PID of the parent of the child that serviced the request -; %q: the query string -; %Q: the '?' character if query string exists -; %r: the request URI (without the query string, see %q and %Q) -; %R: remote IP address -; %s: status (response code) -; %t: server time the request was received -; it can accept a strftime(3) format: -; %d/%b/%Y:%H:%M:%S %z (default) -; The strftime(3) format must be encapsuled in a %{}t tag -; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t -; %T: time the log has been written (the request has finished) -; it can accept a strftime(3) format: -; %d/%b/%Y:%H:%M:%S %z (default) -; The strftime(3) format must be encapsuled in a %{}t tag -; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t -; %u: remote user -; -; Default: "%R - %u %t \"%m %r\" %s" -;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" - -; The log file for slow requests -; Default Value: not set -; Note: slowlog is mandatory if request_slowlog_timeout is set -;slowlog = log/$pool.log.slow - -; The timeout for serving a single request after which a PHP backtrace will be -; dumped to the 'slowlog' file. A value of '0s' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_slowlog_timeout = 0 - -; The timeout for serving a single request after which the worker process will -; be killed. This option should be used when the 'max_execution_time' ini option -; does not stop script execution for some reason. A value of '0' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -request_terminate_timeout = 1d - -; Set open file descriptor rlimit. -; Default Value: system defined value -;rlimit_files = 1024 - -; Set max core size rlimit. -; Possible Values: 'unlimited' or an integer greater or equal to 0 -; Default Value: system defined value -;rlimit_core = 0 - -; Chroot to this directory at the start. This value must be defined as an -; absolute path. When this value is not set, chroot is not used. -; Note: you can prefix with '$prefix' to chroot to the pool prefix or one -; of its subdirectories. If the pool prefix is not set, the global prefix -; will be used instead. -; Note: chrooting is a great security feature and should be used whenever -; possible. However, all PHP paths will be relative to the chroot -; (error_log, sessions.save_path, ...). -; Default Value: not set -;chroot = - -; Chdir to this directory at the start. -; Note: relative path can be used. -; Default Value: current directory or / when chroot -chdir = __INSTALL_DIR__ - -; Redirect worker stdout and stderr into main error log. If not set, stdout and -; stderr will be redirected to /dev/null according to FastCGI specs. -; Note: on highloaded environement, this can cause some delay in the page -; process time (several ms). -; Default Value: no -;catch_workers_output = yes - -; Clear environment in FPM workers -; Prevents arbitrary environment variables from reaching FPM worker processes -; by clearing the environment in workers before env vars specified in this -; pool configuration are added. -; Setting to "no" will make all environment variables available to PHP code -; via getenv(), $_ENV and $_SERVER. -; Default Value: yes -;clear_env = no - -; Limits the extensions of the main script FPM will allow to parse. This can -; prevent configuration mistakes on the web server side. You should only limit -; FPM to .php extensions to prevent malicious users to use other extensions to -; execute php code. -; Note: set an empty value to allow all extensions. -; Default Value: .php -;security.limit_extensions = .php .php3 .php4 .php5 .php7 - -; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from -; the current environment. -; Default Value: clean env -;env[HOSTNAME] = $HOSTNAME -;env[PATH] = /usr/local/bin:/usr/bin:/bin -;env[TMP] = /tmp -;env[TMPDIR] = /tmp -;env[TEMP] = /tmp - -; Additional php.ini defines, specific to this pool of workers. These settings -; overwrite the values previously defined in the php.ini. The directives are the -; same as the PHP SAPI: -; php_value/php_flag - you can set classic ini defines which can -; be overwritten from PHP call 'ini_set'. -; php_admin_value/php_admin_flag - these directives won't be overwritten by -; PHP call 'ini_set' -; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. - -; Defining 'extension' will load the corresponding shared extension from -; extension_dir. Defining 'disable_functions' or 'disable_classes' will not -; overwrite previously defined php.ini values, but will append the new value -; instead. - -; Note: path INI options can be relative and will be expanded with the prefix -; (pool, global or /usr) - -; Default Value: nothing is defined by default except the values in php.ini and -; specified at startup with the -d argument -;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -;php_flag[display_errors] = off -;php_admin_value[error_log] = /var/log/fpm-php.www.log -;php_admin_flag[log_errors] = on -;php_admin_value[memory_limit] = 32M - -; Common values to change to increase file upload limit -; php_admin_value[upload_max_filesize] = 50M -; php_admin_value[post_max_size] = 50M -; php_admin_flag[mail.add_x_header] = Off - -; Other common parameters -; php_admin_value[max_execution_time] = 600 -; php_admin_value[max_input_time] = 300 -; php_admin_value[memory_limit] = 256M -; php_admin_flag[short_open_tag] = On diff --git a/conf/systemd.service b/conf/systemd.service index f100e84..ac0f933 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -1,14 +1,16 @@ [Unit] -Description=Small description of the service +Description=ZeroTier Controller Web UI After=network.target [Service] Type=simple User=__APP__ Group=__APP__ -WorkingDirectory=__INSTALL_DIR__/ -ExecStart=__INSTALL_DIR__/script -StandardOutput=append:/var/log/__APP__/__APP__.log +WorkingDirectory=__INSTALL_DIR__/backend/ +Environment=__YNH_NODE_LOAD_PATH__ +EnvironmentFile=__INSTALL_DIR__/.env +ExecStart=__YNH_NODE__ __INSTALL_DIR__/backend/bin/www +StandardOutput=journal StandardError=inherit # Sandboxing options to harden security diff --git a/config_panel.toml.example b/config_panel.toml.example deleted file mode 100644 index ed147af..0000000 --- a/config_panel.toml.example +++ /dev/null @@ -1,302 +0,0 @@ - -## Config panel are available from webadmin > Apps > YOUR_APP > Config Panel Button -## Those panels let user configure some params on their apps using a friendly interface, -## and remove the need to manually edit files from the command line. - -## From a packager perspective, this .toml is coupled to the scripts/config script, -## which may be used to define custom getters/setters. However, most use cases -## should be covered automagically by the core, thus it may not be necessary -## to define a scripts/config at all! - -## ----------------------------------------------------------------------------- -## IMPORTANT: In accordance with YunoHost's spirit, please keep things simple and -## do not overwhelm the admin with tons of misunderstandable or advanced settings. -## ----------------------------------------------------------------------------- - -## The top level describe the entire config panels screen. - -## The version is a required property. -## Here a small reminder to associate config panel version with YunoHost version -## | Config | YNH | Config panel small change log | -## | ------ | --- | ------------------------------------------------------- | -## | 0.1 | 3.x | 0.1 config script not compatible with YNH >= 4.3 | -## | 1.0 | 4.3.x | The new config panel system with 'bind' property | -version = "1.0" - -## (optional) i18n property let you internationalize questions, however this feature -## is only available in core configuration panel (like yunohost domain config). -## So in app config panel this key is ignored for now, but you can internationalize -## by using a lang dictionary (see property name bellow) -# i18n = "prefix_translation_key" - -################################################################################ -#### ABOUT PANELS -################################################################################ - -## The next level describes web admin panels -## You have to choose an ID for each panel, in this example the ID is "main" -## Keep in mind this ID will be used in CLI to refer to your question, so choose -## something short and meaningfull. -## In the webadmin, each panel corresponds to a distinct tab / form -[main] - -## Define the label for your panel -## Internationalization works similarly to the 'description' and 'ask' questions in the manifest -# name.en = "Main configuration" -# name.fr = "Configuration principale" - -## (optional) If you need to trigger a service reload-or-restart after the user -## change a question in this panel, you can add your service in the list. -services = ["__APP__"] -# or services = ["nginx", "__APP__"] to also reload-or-restart nginx - -## (optional) This help properties is a short help displayed on the same line -## than the panel title but not displayed in the tab. -# help = "" - - ############################################################################ - #### ABOUT SECTIONS - ############################################################################ - - ## A panel is composed of one or several sections. - ## - ## Sections are meant to group questions together when they correspond to - ## a same subtopic. This impacts the rendering in terms of CLI prompts - ## and HTML forms - ## - ## You should choose an ID for your section, and prefix it with the panel ID - ## (Be sure to not make a typo in the panel ID, which would implicitly create - ## an other entire panel) - ## - ## We use the context of pepettes_ynh as an example, - ## which is a simple donation form app written in python, - ## and for which the admin will want to edit the configuration - [main.customization] - - ## (optional) Defining a proper title for sections is not mandatory - ## and depends on the exact rendering you're aiming for the CLI / webadmin - name = "" - - ## (optional) This help properties is a short help displayed on the same line - ## than the section title, meant to provide additional details - # help = "" - - ## (optional) As for panel, you can specify to trigger a service - ## reload-or-restart after the user change a question in this section. - ## This property is added to the panel property, it doesn't deactivate it. - ## So no need to replicate, the service list from panel services property. - # services = [] - - ## (optional) By default all questions are optionals, but you can specify a - ## default behaviour for question in the section - optional = false - - ## (optional) It's also possible with the 'visible' property to only - ## display the section depending on the user's answers to previous questions. - ## - ## Be careful that the 'visible' property should only refer to **previous** questions - ## Hence, it should not make sense to have a "visible" property on the very first section. - ## - ## Also, keep in mind that this feature only works in the webadmin and not in CLI - ## (therefore a user could be prompted in CLI for a question that may not be relevant) - # visible = true - - ######################################################################## - #### ABOUT QUESTIONS - ######################################################################## - - ## A section is compound of one or several questions. - - ## --------------------------------------------------------------------- - ## IMPORTANT: as for panel and section you have to choose an ID, but this - ## one should be unique in all this document, even if the question is in - ## an other panel. - ## --------------------------------------------------------------------- - - ## You can use same questions types and properties than in manifest.yml - ## install part. However, in YNH 4.3, a lot of change has been made to - ## extend availables questions types list. - ## See: TODO DOC LINK - - [main.customization.project_name] - - ## (required) The ask property is equivalent to the ask property in - ## the manifest. However, in config panels, questions are displayed on the - ## left side and therefore have less space to be rendered. Therefore, - ## it is better to use a short question, and use the "help" property to - ## provide additional details if necessary. - ask.en = "Name of the project" - - ## (required) The type property indicates how the question should be - ## displayed, validated and managed. Some types have specific properties. - ## - ## Types available: string, boolean, number, range, text, password, path - ## email, url, date, time, color, select, domain, user, tags, file. - ## - ## For a complete list with specific properties, see: TODO DOC LINK - type = "string" - - ######################################################################## - #### ABOUT THE BIND PROPERTY - ######################################################################## - - ## (recommended) 'bind' property is a powerful feature that let you - ## configure how and where the data will be read, validated and written. - - ## By default, 'bind property is in "settings" mode, it means it will - ## **only** read and write the value in application settings file. - ## bind = "settings" - - ## However, settings usually correspond to key/values in actual app configurations - ## Hence, a more useful mode is to have bind = ":FILENAME". In that case, YunoHost - ## will automagically find a line with "KEY=VALUE" in FILENAME - ## (with the adequate separator between KEY and VALUE) - ## - ## YunoHost will then use this value for the read/get operation. - ## During write/set operations, YunoHost will overwrite the value - ## in **both** FILENAME and in the app's settings.yml - - ## Configuration file format supported: yaml, toml, json, ini, env, php, - ## python. The feature probably works with others formats, but should be tested carefully. - - ## Note that this feature only works with relatively simple cases - ## such as `KEY: VALUE`, but won't properly work with - ## complex data structures like multilin array/lists or dictionnaries. - ## It also doesn't work with XML format, custom config function call, php define(), ... - - ## More info on TODO - # bind = ":/var/www/__APP__/settings.py" - - - ## By default, bind = ":FILENAME" will use the question ID as KEY - ## ... but the question ID may sometime not be the exact KEY name in the configuration file. - ## - ## In particular, in pepettes, the python variable is 'name' and not 'project_name' - ## (c.f. https://github.com/YunoHost-Apps/pepettes_ynh/blob/5cc2d3ffd6529cc7356ff93af92dbb6785c3ab9a/conf/settings.py##L11 ) - ## - ## In that case, the key name can be specified before the column ':' - - bind = "name:/var/www/__APP__/settings.py" - - ## --------------------------------------------------------------------- - ## IMPORTANT: other 'bind' mode exists: - ## - ## bind = "FILENAME" (with no column character before FILENAME) - ## may be used to bind to the **entire file content** (instead of a single KEY/VALUE) - ## This could be used to expose an entire configuration file, or binary files such as images - ## For example: - ## bind = "/var/www/__APP__/img/logo.png" - ## - ## bind = "null" can be used to disable reading / writing in settings. - ## This creates sort of a "virtual" or "ephemeral" question which is not related to any actual setting - ## In this mode, you are expected to define custom getter/setters/validators in scripts/config: - ## - ## getter: get__QUESTIONID() - ## setter: set__QUESTIONID() - ## validator: validate__QUESTIONID() - ## - ## You can also specify a common getter / setter / validator, with the - ## function 'bind' mode, for example here it will try to run - ## get__array_settings() first. - # bind = "array_settings()" - ## --------------------------------------------------------------------- - - ## --------------------------------------------------------------------- - ## IMPORTANT: with the exception of bind=null questions, - ## question IDs should almost **always** correspond to an app setting - ## initialized / reused during install/upgrade. - ## Not doing so may result in inconsistencies between the config panel mechanism - ## and the use of ynh_add_config - ## --------------------------------------------------------------------- - - ######################################################################## - #### OTHER GENERIC PROPERTY FOR QUESTIONS - ######################################################################## - - ## (optional) An help text for the question - help = "Fill the name of the project which will received donation" - - ## (optional) An example display as placeholder in web form - # example = "YunoHost" - - ## (optional) set to true in order to redact the value in operation logs - # redact = false - - ## (optional) for boolean questions you can specify replacement values - ## bound to true and false, in case property is bound to config file - # useful if bound property in config file expects something else than integer 1 - yes = "Enable" - # useful if bound property in config file expects something else than integer 0 - no = "Disable" - - ## (optional) A validation pattern - ## --------------------------------------------------------------------- - ## IMPORTANT: your pattern should be between simple quote, not double. - ## --------------------------------------------------------------------- - pattern.regexp = '^\w{3,30}$' - pattern.error = "The name should be at least 3 chars and less than 30 chars. Alphanumeric chars are accepted" - - ## Note: visible and optional properties are also available for questions - - - [main.customization.contact_url] - ask = "Contact url" - type = "url" - example = "mailto: contact@example.org" - help = "mailto: accepted" - pattern.regexp = '^mailto:[^@]+@[^@]+|https://$' - pattern.error = "Should be https or mailto:" - bind = ":/var/www/__APP__/settings.py" - - [main.customization.logo] - ask = "Logo" - type = "file" - accept = ".png" - help = "Fill with an already resized logo" - bind = "__INSTALL_DIR__/img/logo.png" - - [main.customization.favicon] - ask = "Favicon" - type = "file" - accept = ".png" - help = "Fill with an already sized favicon" - bind = "__INSTALL_DIR__/img/favicon.png" - - - [main.stripe] - name = "Stripe general info" - optional = false - - # The next alert is overwrited with a getter from the config script - [main.stripe.amount] - ask = "Donation in the month : XX € - type = "alert" - style = "success" - - [main.stripe.publishable_key] - ask = "Publishable key" - type = "string" - redact = true - help = "Indicate here the stripe publishable key" - bind = ":/var/www/__APP__/settings.py" - - [main.stripe.secret_key] - ask = "Secret key" - type = "string" - redact = true - help = "Indicate here the stripe secret key" - bind = ":/var/www/__APP__/settings.py" - - [main.stripe.prices] - ask = "Prices ID" - type = "tags" - help = """\ - Indicates here the prices ID of donation products you created in stripe interfaces. \ - Go on [Stripe products](https://dashboard.stripe.com/products) to create those donation products. \ - Fill it tag with 'FREQUENCY/CURRENCY/PRICE_ID' \ - FREQUENCY: 'one_time' or 'recuring' \ - CURRENCY: 'EUR' or 'USD' \ - PRICE_ID: ID from stripe interfaces starting with 'price_' \ - """ - pattern.regexp = '^(one_time|recuring)/(EUR|USD)/price_.*$' - pattern.error = "Please respect the format describe in help text for each price ID" diff --git a/doc/ADMIN.md b/doc/ADMIN.md deleted file mode 100644 index c9b5225..0000000 --- a/doc/ADMIN.md +++ /dev/null @@ -1,3 +0,0 @@ -This is a dummy admin doc for this app - -The app install dir is `__INSTALL_DIR__` diff --git a/doc/ADMIN_fr.md b/doc/ADMIN_fr.md deleted file mode 100644 index a138028..0000000 --- a/doc/ADMIN_fr.md +++ /dev/null @@ -1,3 +0,0 @@ -Ceci est une fausse doc d'admin pour cette app - -Le dossier d'install de l'app est `__INSTALL_DIR__` diff --git a/doc/DESCRIPTION.md b/doc/DESCRIPTION.md index 3f2e57a..bffb48e 100644 --- a/doc/DESCRIPTION.md +++ b/doc/DESCRIPTION.md @@ -1 +1,8 @@ -This is a dummy description of this app features +ZeroTier Controller Web UI is a web user interface for a self-hosted ZeroTier network controller. + +This project is highly inspired by [ztncui](https://github.com/key-networks/ztncui) and was developed to address the current limitations of applying the self-hosted [network controllers](https://github.com/zerotier/ZeroTierOne/tree/master/controller). Some [ztncui](https://github.com/key-networks/ztncui) problems cannot be fixed because of the core architecture of the project. ZeroUI tries to solve them and implements the following features: + +- Full React-powered lightweight [SPA](https://en.wikipedia.org/wiki/Single-page_application) that brings a better user experience, and ZeroUI is mobile-friendly. +- ZeroUI has ZeroTier Central compatible API. That means you could use CLI tools and custom applications made only for ZeroTier Central to manage your networks. +- ZeroUI implements controller-specific workarounds that address some existing [issues](https://github.com/zerotier/ZeroTierOne/issues/859). ZTNCUI [does not](https://github.com/key-networks/ztncui/issues/63). +- ZeroUI is more feature complete. ZeroUI has almost all network-controller-supported features, for example, rule editor. The development process hasn't stopped, so you will enjoy new features and bug fixes shortly. diff --git a/doc/DESCRIPTION_fr.md b/doc/DESCRIPTION_fr.md deleted file mode 100644 index 13f4b64..0000000 --- a/doc/DESCRIPTION_fr.md +++ /dev/null @@ -1 +0,0 @@ -Ceci est une fausse description des fonctionalités de l'app diff --git a/doc/POST_INSTALL.md b/doc/POST_INSTALL.md deleted file mode 100644 index f367b62..0000000 --- a/doc/POST_INSTALL.md +++ /dev/null @@ -1,7 +0,0 @@ -This is a dummy disclaimer to display after the install - -The app url is `__DOMAIN____PATH__` - -The app install dir is `__INSTALL_DIR__` - -The app id is `__ID__` diff --git a/doc/POST_UPGRADE.md b/doc/POST_UPGRADE.md deleted file mode 100644 index a58e2ae..0000000 --- a/doc/POST_UPGRADE.md +++ /dev/null @@ -1 +0,0 @@ -This is a dummy disclaimer to display after upgrades diff --git a/doc/PRE_INSTALL.md b/doc/PRE_INSTALL.md index eb3ab3a..d5332fb 100644 --- a/doc/PRE_INSTALL.md +++ b/doc/PRE_INSTALL.md @@ -1 +1 @@ -This is a dummy disclaimer to display prior to the install +ZeroUI requires ZeroTier to be installed beforehand. diff --git a/doc/PRE_INSTALL_fr.md b/doc/PRE_INSTALL_fr.md deleted file mode 100644 index 4a02cd5..0000000 --- a/doc/PRE_INSTALL_fr.md +++ /dev/null @@ -1 +0,0 @@ -Ceci est un faux disclaimer à présenter avant l'installation diff --git a/doc/PRE_UPGRADE.md b/doc/PRE_UPGRADE.md deleted file mode 100644 index 780fc15..0000000 --- a/doc/PRE_UPGRADE.md +++ /dev/null @@ -1 +0,0 @@ -This is a dummy disclaimer to display prior to any upgrade diff --git a/doc/screenshots/example.jpg b/doc/screenshots/example.jpg deleted file mode 100644 index a1efa1a36d593384df59dc13db03fa83b0436d69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35451 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 UE-)&$xd9C0IsX9d#{5|Pe`qLcKmY&$ diff --git a/doc/screenshots/homepage.png b/doc/screenshots/homepage.png new file mode 100644 index 0000000000000000000000000000000000000000..d4b54ac88bbb992c89fbec79bb2b4c14f84b4a16 GIT binary patch literal 166439 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 db.sql - #================================================= # END OF SCRIPT #================================================= diff --git a/scripts/config b/scripts/config deleted file mode 100644 index dca69fb..0000000 --- a/scripts/config +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash -# In simple cases, you don't need a config script. - -# With a simple config_panel.toml, you can write in the app settings, in the -# upstream config file or replace complete files (logo ...) and restart services. - -# The config scripts allows you to go further, to handle specific cases -# (validation of several interdependent fields, specific getter/setter for a value, -# display dynamic informations or choices, pre-loading of config type .cube... ). - -#================================================= -# GENERIC STARTING -#================================================= -# IMPORT GENERIC HELPERS -#================================================= - -source /usr/share/yunohost/helpers - -ynh_abort_if_errors - -#================================================= -# RETRIEVE ARGUMENTS -#================================================= - -install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) - -#================================================= -# SPECIFIC GETTERS FOR TOML SHORT KEY -#================================================= - -get__amount() { - # Here we can imagine to have an API call to stripe to know the amount of donation during a month - local amount = 200 - - # It's possible to change some properties of the question by overriding it: - if [ $amount -gt 100 ] - then - cat << EOF -style: success -value: $amount -ask: - en: A lot of donation this month: **$amount €** -EOF - else - cat << EOF -style: danger -value: $amount -ask: - en: Not so much donation this month: $amount € -EOF - fi -} - -get__prices() { - local prices = "$(grep "DONATION\['" "$install_dir/settings.py" | sed -r "s@^DONATION\['([^']*)'\]\['([^']*)'\] = '([^']*)'@\1/\2/\3@g" | sed -z 's/\n/,/g;s/,$/\n/')" - if [ "$prices" == "," ]; - then - # Return YNH_NULL if you prefer to not return a value at all. - echo YNH_NULL - else - echo $prices - fi -} - - -#================================================= -# SPECIFIC VALIDATORS FOR TOML SHORT KEYS -#================================================= -validate__publishable_key() { - - # We can imagine here we test if the key is really a publisheable key - (is_secret_key $publishable_key) && - echo 'This key seems to be a secret key' -} - -#================================================= -# SPECIFIC SETTERS FOR TOML SHORT KEYS -#================================================= -set__prices() { - - #--------------------------------------------- - # IMPORTANT: setter are trigger only if a change is detected - #--------------------------------------------- - for price in $(echo $prices | sed "s/,/ /"); do - frequency=$(echo $price | cut -d/ -f1) - currency=$(echo $price | cut -d/ -f2) - price_id=$(echo $price | cut -d/ -f3) - sed "d/DONATION\['$frequency'\]\['$currency'\]" "$install_dir/settings.py" - - echo "DONATION['$frequency']['$currency'] = '$price_id'" >> "$install_dir/settings.py" - done - - #--------------------------------------------- - # IMPORTANT: to be able to upgrade properly, you have to saved the value in settings too - #--------------------------------------------- - ynh_app_setting_set $app prices $prices -} - -#================================================= -# GENERIC FINALIZATION -#================================================= -ynh_app_config_run $1 diff --git a/scripts/install b/scripts/install index 4245199..227d174 100755 --- a/scripts/install +++ b/scripts/install @@ -9,26 +9,25 @@ source _common.sh source /usr/share/yunohost/helpers -# Install parameters are automatically saved as settings -# -# Settings are automatically loaded as bash variables -# in every app script context, therefore typically these will exist: -# - $domain -# - $path -# - $language -# ... etc -# -# Resources defined in the manifest are provisioned prior to this script -# and corresponding settings are also available, such as: -# - $install_dir -# - $port -# - $db_name -# ... +#================================================= +# CHECK IF THE APP CAN BE INSTALLED +#================================================= -# -# $app is the app id (i.e. 'example' for first install, -# or 'example__2', '__3', ... for multi-instance installs) -# +# Testing if ZeroTier is installed +yunohost app list | grep -q "id: zerotier" || ynh_die "ZeroTier is needed, but it is not installed. There is a package for that!" + +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Installing dependencies..." --weight=2 + +ynh_install_nodejs --nodejs_version=$nodejs_version +ynh_use_nodejs +$nodejs_path/corepack enable +$nodejs_path/corepack prepare yarn@stable --activate + +# Prevent ERR_OSSL_EVP_UNSUPPORTED error +export NODE_OPTIONS=--openssl-legacy-provider #================================================= # APP "BUILD" (DEPLOYING SOURCES, VENV, COMPILING ETC) @@ -36,95 +35,34 @@ source /usr/share/yunohost/helpers # DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= ynh_script_progression --message="Setting up source files..." --weight=1 - -### `ynh_setup_source` is used to install an app from a zip or tar.gz file, -### downloaded from an upstream source, like a git repository. -### `ynh_setup_source` use the file conf/app.src - -# Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$install_dir" -# $install_dir will automatically be initialized with some decent -# permission by default ... however, you may need to recursively reapply -# ownership to all files such as after the ynh_setup_source step -chown -R $app:www-data "$install_dir" +ynh_script_progression --message="Building the backend..." --weight=3 +pushd $install_dir/backend + $nodejs_path/yarn install +popd + +ynh_script_progression --message="Building the frontend..." --weight=3 +pushd $install_dir/frontend + $nodejs_path/yarn install + $nodejs_path/yarn build +popd + +chown -R $app:$app "$install_dir" +chown $app:www-data "$install_dir" +chown $app:www-data "$install_dir/frontend" +chown -R $app:www-data "$install_dir/frontend/public" #================================================= # SYSTEM CONFIGURATION #================================================= ynh_script_progression --message="Adding system configurations related to $app..." --weight=1 -### `ynh_add_fpm_config` is used to set up a PHP config. -### You can remove it if your app doesn't use PHP. -### `ynh_add_fpm_config` will use the files conf/php-fpm.conf -### If you're not using these lines: -### - You can remove these files in conf/. -### - Remove the section "BACKUP THE PHP-FPM CONFIGURATION" in the backup script -### - Remove also the section "REMOVE PHP-FPM CONFIGURATION" in the remove script -### - As well as the section "RESTORE THE PHP-FPM CONFIGURATION" in the restore script -### with the reload at the end of the script. -### - And the section "PHP-FPM CONFIGURATION" in the upgrade script - -# Create a dedicated PHP-FPM config using the conf/php-fpm.conf or conf/extra_php-fpm.conf -ynh_add_fpm_config - -# Create a dedicated NGINX config using the conf/nginx.conf template ynh_add_nginx_config -### `ynh_systemd_config` is used to configure a systemd script for an app. -### It can be used for apps that use sysvinit (with adaptation) or systemd. -### Have a look at the app to be sure this app needs a systemd script. -### `ynh_systemd_config` will use the file conf/systemd.service -### If you're not using these lines: -### - You can remove those files in conf/. -### - Remove the section "BACKUP SYSTEMD" in the backup script -### - Remove also the section "STOP AND REMOVE SERVICE" in the remove script -### - As well as the section "RESTORE SYSTEMD" in the restore script -### - And the section "SETUP SYSTEMD" in the upgrade script - -# Create a dedicated systemd config ynh_add_systemd_config -### `yunohost service add` integrates a service in YunoHost. It then gets -### displayed in the admin interface and through the others `yunohost service` commands. -### (N.B.: this line only makes sense if the app adds a service to the system!) -### If you're not using these lines: -### - You can remove these files in conf/. -### - Remove the section "REMOVE SERVICE INTEGRATION IN YUNOHOST" in the remove script -### - As well as the section "INTEGRATE SERVICE IN YUNOHOST" in the restore script -### - And the section "INTEGRATE SERVICE IN YUNOHOST" in the upgrade script - -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" - -### Additional options starting with 3.8: -### -### --needs_exposed_ports "$port" a list of ports that needs to be publicly exposed -### which will then be checked by YunoHost's diagnosis system -### (N.B. DO NOT USE THIS is the port is only internal!!!) -### -### --test_status "some command" a custom command to check the status of the service -### (only relevant if 'systemctl status' doesn't do a good job) -### -### --test_conf "some command" some command similar to "nginx -t" that validates the conf of the service -### -### Re-calling 'yunohost service add' during the upgrade script is the right way -### to proceed if you later realize that you need to enable some flags that -### weren't enabled on old installs (be careful it'll override the existing -### service though so you should re-provide all relevant flags when doing so) - -### `ynh_use_logrotate` is used to configure a logrotate configuration for the logs of this app. -### Use this helper only if there is effectively a log file for this app. -### If you're not using this helper: -### - Remove the section "BACKUP LOGROTATE" in the backup script -### - Remove also the section "REMOVE LOGROTATE CONFIGURATION" in the remove script -### - As well as the section "RESTORE THE LOGROTATE CONFIGURATION" in the restore script -### - And the section "SETUP LOGROTATE" in the upgrade script - -# Use logrotate to manage application logfile(s) -ynh_use_logrotate - -# Create a dedicated Fail2Ban config -ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" +yunohost service add $app --description="ZeroTier Controller Web UI" #================================================= # APP INITIAL CONFIGURATION @@ -133,45 +71,14 @@ ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failreg #================================================= ynh_script_progression --message="Adding a configuration file..." --weight=1 -### You can add specific configuration files. -### -### Typically, put your template conf file in ../conf/your_config_file -### The template may contain strings such as __FOO__ or __FOO_BAR__, -### which will automatically be replaced by the values of $foo and $foo_bar -### -### ynh_add_config will also keep track of the config file's checksum, -### which later during upgrade may allow to automatically backup the config file -### if it's found that the file was manually modified -### -### Check the documentation of `ynh_add_config` for more info. +# Let's retrieve information on the ZeroTier installation +zt_token="$(/dev/null then ynh_script_progression --message="Removing $app service integration..." --weight=1 @@ -42,20 +26,6 @@ ynh_remove_systemd_config ynh_remove_nginx_config -ynh_remove_fpm_config - -ynh_remove_logrotate - -ynh_remove_fail2ban_config - -# Remove other various files specific to the app... such as : - -ynh_secure_remove --file="/etc/cron.d/$app" - -ynh_secure_remove --file="/etc/$app" - -ynh_secure_remove --file="/var/log/$app" - #================================================= # END OF SCRIPT #================================================= diff --git a/scripts/restore b/scripts/restore index 2bec09d..33dc88d 100755 --- a/scripts/restore +++ b/scripts/restore @@ -10,6 +10,13 @@ source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers +#================================================= +# CHECK IF THE APP CAN BE INSTALLED +#================================================= + +# Testing if ZeroTier is installed +yunohost app list | grep -q "id: zerotier" || ynh_die "ZeroTier is needed, but it is not installed. Restore its backup first, otherwise there is a package for that, then perform a force-upgrade of ZeroUI." + #================================================= # RESTORE THE APP MAIN DIR #================================================= @@ -17,56 +24,21 @@ ynh_script_progression --message="Restoring the app main directory..." --weight= ynh_restore_file --origin_path="$install_dir" -# $install_dir will automatically be initialized with some decent -# permission by default ... however, you may need to recursively reapply -# ownership to all files such as after the ynh_setup_source step -chown -R $app:www-data "$install_dir" - -#================================================= -# RESTORE THE DATA DIRECTORY -#================================================= -ynh_script_progression --message="Restoring the data directory..." --weight=1 - -ynh_restore_file --origin_path="$data_dir" --not_mandatory - -# (Same as for install dir) -chown -R $app:www-data "$data_dir" - -#================================================= -# RESTORE THE MYSQL DATABASE -#================================================= -ynh_script_progression --message="Restoring the MySQL database..." --weight=1 - -ynh_mysql_connect_as --user=$db_user --password=$db_pwd --database=$db_name < ./db.sql +chown -R $app:$app "$install_dir" +chown $app:www-data "$install_dir" +chown $app:www-data "$install_dir/frontend" +chown -R $app:www-data "$install_dir/frontend/public" #================================================= # RESTORE SYSTEM CONFIGURATIONS #================================================= -# RESTORE THE PHP-FPM CONFIGURATION -#================================================= -ynh_script_progression --message="Restoring system configurations related to $app..." --weight=1 - -# This should be a symetric version of what happens in the install script - -ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" ynh_restore_file --origin_path="/etc/systemd/system/$app.service" systemctl enable $app.service --quiet -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" - -ynh_restore_file --origin_path="/etc/logrotate.d/$app" - -ynh_restore_file --origin_path="/etc/fail2ban/jail.d/$app.conf" -ynh_restore_file --origin_path="/etc/fail2ban/filter.d/$app.conf" -ynh_systemd_action --action=restart --service_name=fail2ban - -# Other various files... - -ynh_restore_file --origin_path="/etc/cron.d/$app" -ynh_restore_file --origin_path="/etc/$app/" +yunohost service add $app --description="ZeroTier Controller Web UI" #================================================= # GENERIC FINALIZATION @@ -76,8 +48,7 @@ ynh_restore_file --origin_path="/etc/$app/" ynh_script_progression --message="Reloading NGINX web server and $app's service..." --weight=1 # Typically you only have either $app or php-fpm but not both at the same time... -ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" -ynh_systemd_action --service_name=php$phpversion-fpm --action=reload +ynh_systemd_action --service_name=$app --action="start" --log_path="systemd" ynh_systemd_action --service_name=nginx --action=reload diff --git a/scripts/upgrade b/scripts/upgrade index a6b3f17..331bcfc 100755 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -9,27 +9,15 @@ source _common.sh source /usr/share/yunohost/helpers -# Settings are automatically loaded as bash variables -# in every app script context, therefore typically these will exist: -# - $domain -# - $path -# - $language -# - $install_dir -# - $port -# ... - -# In the context of upgrade, -# - resources are automatically provisioned / updated / deleted (depending on existing resources) -# - a safety backup is automatically created by the core and will be restored if the upgrade fails - -### This helper will compare the version of the currently installed app and the version of the upstream package. -### $upgrade_type can have 2 different values -### - UPGRADE_APP if the upstream app version has changed -### - UPGRADE_PACKAGE if only the YunoHost package has changed -### ynh_check_app_version_changed will stop the upgrade if the app is up to date. -### UPGRADE_APP should be used to upgrade the core app only if there's an upgrade to do. upgrade_type=$(ynh_check_app_version_changed) +#================================================= +# CHECK IF THE APP CAN BE INSTALLED +#================================================= + +# Testing if ZeroTier is installed +yunohost app list | grep -q "id: zerotier" || ynh_die "ZeroTier is needed, but it is not installed. There is a package for that!" + #================================================= # STANDARD UPGRADE STEPS #================================================= @@ -37,30 +25,12 @@ upgrade_type=$(ynh_check_app_version_changed) #================================================= #ynh_script_progression --message="Ensuring downward compatibility..." --weight=1 -# -# N.B. : the followings setting migrations snippets are provided as *EXAMPLES* -# of what you may want to do in some cases (e.g. a setting was not defined on -# some legacy installs and you therefore want to initiaze stuff during upgrade) -# - -# If db_name doesn't exist, create it -#if [ -z "$db_name" ]; then -# db_name=$(ynh_sanitize_dbid --db_name=$app) -# ynh_app_setting_set --app=$app --key=db_name --value=$db_name -#fi - -# If install_dir doesn't exist, create it -#if [ -z "$install_dir" ]; then -# install_dir=/var/www/$app -# ynh_app_setting_set --app=$app --key=install_dir --value=$install_dir -#fi - #================================================= # STOP SYSTEMD SERVICE #================================================= ynh_script_progression --message="Stopping a systemd service..." --weight=1 -ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" +ynh_systemd_action --service_name=$app --action="stop" --log_path="systemd" #================================================= # "REBUILD" THE APP (DEPLOY NEW SOURCES, RERUN NPM BUILD...) @@ -74,31 +44,41 @@ then # Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$install_dir" + + ynh_use_nodejs + $nodejs_path/corepack enable + $nodejs_path/corepack prepare yarn@stable --activate + + # Prevent ERR_OSSL_EVP_UNSUPPORTED error + export NODE_OPTIONS=--openssl-legacy-provider + + ynh_script_progression --message="Building the backend..." --weight=3 + pushd $install_dir/backend + $nodejs_path/yarn install + popd + + ynh_script_progression --message="Building the frontend..." --weight=3 + pushd $install_dir/frontend + $nodejs_path/yarn install + $nodejs_path/yarn build + popd fi -# $install_dir will automatically be initialized with some decent -# permission by default ... however, you may need to recursively reapply -# ownership to all files such as after the ynh_setup_source step -chown -R $app:www-data "$install_dir" +chown -R $app:$app "$install_dir" +chown $app:www-data "$install_dir" +chown $app:www-data "$install_dir/frontend" +chown -R $app:www-data "$install_dir/frontend/public" #================================================= # REAPPLY SYSTEM CONFIGURATIONS #================================================= ynh_script_progression --message="Upgrading system configurations related to $app..." --weight=1 -# This should be a literal copypasta of what happened in the install's "System configuration" section - -ynh_add_fpm_config - ynh_add_nginx_config ynh_add_systemd_config -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" - -ynh_use_logrotate --non-append - -ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" +yunohost service add $app --description="ZeroTier Controller Web UI" #================================================= # RECONFIGURE THE APP (UPDATE CONF, APPLY MIGRATIONS...) @@ -107,32 +87,21 @@ ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failreg #================================================= ynh_script_progression --message="Updating a configuration file..." --weight=1 -### Same as during install -### -### The file will automatically be backed-up if it's found to be manually modified (because -### ynh_add_config keeps track of the file's checksum) +# Let's retrieve information on the ZeroTier installation +zt_token="$( Date: Sat, 26 Aug 2023 22:16:39 +0000 Subject: [PATCH 2/5] Auto-update README --- README.md | 49 ++++++++++++++++++++----------------------------- README_fr.md | 38 ++++++++++++++++++++------------------ 2 files changed, 40 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 36090c3..d61ef00 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,53 @@ -# Packaging an app, starting from this example - -* Copy this app before working on it, using the ['Use this template'](https://github.com/YunoHost/example_ynh/generate) button on the Github repo. -* Edit the `manifest.json` with app specific info. -* Edit the `install`, `upgrade`, `remove`, `backup`, and `restore` scripts, and any relevant conf files in `conf/`. - * Using the [script helpers documentation.](https://yunohost.org/packaging_apps_helpers) -* Add a `LICENSE` file for the package. -* Edit `doc/DISCLAIMER*.md` -* The `README.md` files are to be automatically generated by https://github.com/YunoHost/apps/tree/master/tools/README-generator - ---- -# Example app for YunoHost +# ZeroUI for YunoHost -[![Integration level](https://dash.yunohost.org/integration/example.svg)](https://dash.yunohost.org/appci/app/example) ![Working status](https://ci-apps.yunohost.org/ci/badges/example.status.svg) ![Maintenance status](https://ci-apps.yunohost.org/ci/badges/example.maintain.svg) +[![Integration level](https://dash.yunohost.org/integration/zeroui.svg)](https://dash.yunohost.org/appci/app/zeroui) ![Working status](https://ci-apps.yunohost.org/ci/badges/zeroui.status.svg) ![Maintenance status](https://ci-apps.yunohost.org/ci/badges/zeroui.maintain.svg) -[![Install Example app with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=example) +[![Install ZeroUI with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=zeroui) *[Lire ce readme en français.](./README_fr.md)* -> *This package allows you to install Example app quickly and simply on a YunoHost server. +> *This package allows you to install ZeroUI quickly and simply on a YunoHost server. If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* ## Overview -This is a dummy description of this app features +ZeroTier Controller Web UI is a web user interface for a self-hosted ZeroTier network controller. + +This project is highly inspired by [ztncui](https://github.com/key-networks/ztncui) and was developed to address the current limitations of applying the self-hosted [network controllers](https://github.com/zerotier/ZeroTierOne/tree/master/controller). Some [ztncui](https://github.com/key-networks/ztncui) problems cannot be fixed because of the core architecture of the project. ZeroUI tries to solve them and implements the following features: + +- Full React-powered lightweight [SPA](https://en.wikipedia.org/wiki/Single-page_application) that brings a better user experience, and ZeroUI is mobile-friendly. +- ZeroUI has ZeroTier Central compatible API. That means you could use CLI tools and custom applications made only for ZeroTier Central to manage your networks. +- ZeroUI implements controller-specific workarounds that address some existing [issues](https://github.com/zerotier/ZeroTierOne/issues/859). ZTNCUI [does not](https://github.com/key-networks/ztncui/issues/63). +- ZeroUI is more feature complete. ZeroUI has almost all network-controller-supported features, for example, rule editor. The development process hasn't stopped, so you will enjoy new features and bug fixes shortly. -**Shipped version:** 1.0~ynh1 - -**Demo:** https://demo.example.com +**Shipped version:** 1.5.1~ynh1 ## Screenshots -![Screenshot of Example app](./doc/screenshots/example.jpg) +![Screenshot of ZeroUI](./doc/screenshots/homepage.png) ## Documentation and resources -* Official app website: -* Official user documentation: -* Official admin documentation: -* Upstream app code repository: -* YunoHost documentation for this app: -* Report a bug: +* Upstream app code repository: +* YunoHost documentation for this app: +* Report a bug: ## Developer info -Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/example_ynh/tree/testing). +Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/zeroui_ynh/tree/testing). To try the testing branch, please proceed like that. ``` bash -sudo yunohost app install https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app install https://github.com/YunoHost-Apps/zeroui_ynh/tree/testing --debug or -sudo yunohost app upgrade example -u https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app upgrade zeroui -u https://github.com/YunoHost-Apps/zeroui_ynh/tree/testing --debug ``` **More info regarding app packaging:** diff --git a/README_fr.md b/README_fr.md index 3880bc4..b1e27ff 100644 --- a/README_fr.md +++ b/README_fr.md @@ -3,49 +3,51 @@ N.B.: This README was automatically generated by https://github.com/YunoHost/app It shall NOT be edited by hand. --> -# Example app pour YunoHost +# ZeroUI pour YunoHost -[![Niveau d’intégration](https://dash.yunohost.org/integration/example.svg)](https://dash.yunohost.org/appci/app/example) ![Statut du fonctionnement](https://ci-apps.yunohost.org/ci/badges/example.status.svg) ![Statut de maintenance](https://ci-apps.yunohost.org/ci/badges/example.maintain.svg) +[![Niveau d’intégration](https://dash.yunohost.org/integration/zeroui.svg)](https://dash.yunohost.org/appci/app/zeroui) ![Statut du fonctionnement](https://ci-apps.yunohost.org/ci/badges/zeroui.status.svg) ![Statut de maintenance](https://ci-apps.yunohost.org/ci/badges/zeroui.maintain.svg) -[![Installer Example app avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=example) +[![Installer ZeroUI avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=zeroui) *[Read this readme in english.](./README.md)* -> *Ce package vous permet d’installer Example app rapidement et simplement sur un serveur YunoHost. +> *Ce package vous permet d’installer ZeroUI 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 -Ceci est une fausse description des fonctionalités de l'app +ZeroTier Controller Web UI is a web user interface for a self-hosted ZeroTier network controller. + +This project is highly inspired by [ztncui](https://github.com/key-networks/ztncui) and was developed to address the current limitations of applying the self-hosted [network controllers](https://github.com/zerotier/ZeroTierOne/tree/master/controller). Some [ztncui](https://github.com/key-networks/ztncui) problems cannot be fixed because of the core architecture of the project. ZeroUI tries to solve them and implements the following features: + +- Full React-powered lightweight [SPA](https://en.wikipedia.org/wiki/Single-page_application) that brings a better user experience, and ZeroUI is mobile-friendly. +- ZeroUI has ZeroTier Central compatible API. That means you could use CLI tools and custom applications made only for ZeroTier Central to manage your networks. +- ZeroUI implements controller-specific workarounds that address some existing [issues](https://github.com/zerotier/ZeroTierOne/issues/859). ZTNCUI [does not](https://github.com/key-networks/ztncui/issues/63). +- ZeroUI is more feature complete. ZeroUI has almost all network-controller-supported features, for example, rule editor. The development process hasn't stopped, so you will enjoy new features and bug fixes shortly. -**Version incluse :** 1.0~ynh1 - -**Démo :** https://demo.example.com +**Version incluse :** 1.5.1~ynh1 ## Captures d’écran -![Capture d’écran de Example app](./doc/screenshots/example.jpg) +![Capture d’écran de ZeroUI](./doc/screenshots/homepage.png) ## Documentations et ressources -* Site officiel de l’app : -* Documentation officielle utilisateur : -* Documentation officielle de l’admin : -* Dépôt de code officiel de l’app : -* Documentation YunoHost pour cette app : -* Signaler un bug : +* Dépôt de code officiel de l’app : +* Documentation YunoHost pour cette app : +* Signaler un bug : ## Informations pour les développeurs -Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/example_ynh/tree/testing). +Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/zeroui_ynh/tree/testing). Pour essayer la branche testing, procédez comme suit. ``` bash -sudo yunohost app install https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app install https://github.com/YunoHost-Apps/zeroui_ynh/tree/testing --debug ou -sudo yunohost app upgrade example -u https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app upgrade zeroui -u https://github.com/YunoHost-Apps/zeroui_ynh/tree/testing --debug ``` **Plus d’infos sur le packaging d’applications :** \ No newline at end of file From cc347af4298926bf8796d199126a75d0038fdb3d Mon Sep 17 00:00:00 2001 From: tituspijean Date: Sun, 27 Aug 2023 00:41:50 +0200 Subject: [PATCH 3/5] Refresh catalog before installing ZeroTier during tests --- tests.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests.toml b/tests.toml index 3b38262..72f8b13 100644 --- a/tests.toml +++ b/tests.toml @@ -9,6 +9,7 @@ test_format = 1.0 # ------------ preinstall = """ + sudo yunohost tools update sudo yunohost app install zerotier """ From 1b03fc1901ace039b18a58b13bf42a0a584a1a88 Mon Sep 17 00:00:00 2001 From: tituspijean Date: Sun, 27 Aug 2023 01:09:45 +0200 Subject: [PATCH 4/5] Reinstall NodeJS upon restore --- scripts/restore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/restore b/scripts/restore index 33dc88d..35cf924 100755 --- a/scripts/restore +++ b/scripts/restore @@ -17,6 +17,13 @@ source /usr/share/yunohost/helpers # Testing if ZeroTier is installed yunohost app list | grep -q "id: zerotier" || ynh_die "ZeroTier is needed, but it is not installed. Restore its backup first, otherwise there is a package for that, then perform a force-upgrade of ZeroUI." +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Reinstalling dependencies..." --weight=2 + +ynh_install_nodejs --nodejs_version=$nodejs_version + #================================================= # RESTORE THE APP MAIN DIR #================================================= From d92ede28979839d4ec1afedd4ef3904165fec79f Mon Sep 17 00:00:00 2001 From: tituspijean Date: Sun, 27 Aug 2023 01:37:48 +0200 Subject: [PATCH 5/5] Improve manifest --- manifest.toml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/manifest.toml b/manifest.toml index 4c468f1..d0efc0f 100644 --- a/manifest.toml +++ b/manifest.toml @@ -22,18 +22,14 @@ architectures = "all" multi_instance = false ldap = false sso = false -disk = "50M" -ram.build = "50M" +disk = "300M" +ram.build = "2G" ram.runtime = "50M" [install] [install.domain] type = "domain" -# [install.path] -# type = "path" -# default = "/example" - [install.init_main_permission] type = "group" default = "admins"