diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..6c08377a --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,80 @@ + + +#### What were you doing? + + + +1. ... +2. ... +3. ... + + + +#### What did you expect to happen? + +#### What happened instead? + +#### Did the same happen when running OctoPrint in safe mode? + + + +#### Version of OctoPi + + + + +#### Printer model & used firmware incl. version + + + + +#### Screenshot(s)/video(s) showing the problem: + + + +I have read the FAQ. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..97238fb2 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,66 @@ +name: Build Image + +on: + repository_dispatch: + push: + schedule: + - cron: '0 0 * * *' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Install Dependencies + run: | + sudo apt update + sudo apt install coreutils p7zip-full qemu-user-static + + - name: Checkout CustomPiOS + uses: actions/checkout@v2 + with: + repository: 'guysoft/CustomPiOS' + path: CustomPiOS + + - name: Checkout Project Repository + uses: actions/checkout@v2 + with: + path: repository + submodules: true + + - name: Download Raspbian Image + run: | + cd repository/src/image + wget -c --trust-server-names 'https://downloads.raspberrypi.org/raspios_lite_armhf_latest' + + - name: Update CustomPiOS Paths + run: | + cd repository/src + ../../CustomPiOS/src/update-custompios-paths + + - name: Force apt mirror to work around intermittent mirror hiccups + run: | + echo "OCTOPI_APTMIRROR=http://mirror.us.leaseweb.net/raspbian/raspbian" > repository/src/config.local + + - name: Build Image + run: | + sudo modprobe loop + cd repository/src + sudo bash -x ./build_dist + + - name: Copy output + id: copy + run: | + source repository/src/config + NOW=$(date +"%Y-%m-%d-%H%M") + IMAGE=$NOW-octopi-$DIST_VERSION + + cp repository/src/workspace/*.img $IMAGE.img + + echo "::set-output name=image::$IMAGE" + + # artifact upload will take care of zipping for us + - uses: actions/upload-artifact@v1 + if: github.event_name == 'schedule' + with: + name: ${{ steps.copy.outputs.image }} + path: ${{ steps.copy.outputs.image }}.img diff --git a/.gitignore b/.gitignore index 4774137a..1638832a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,15 @@ src/config.local +src/custompios_path src/image/*.zip +src/image-raspios_lite_arm64/*.zip +src/image-variants/*.zip +**/key.json +src/nightly_build_scripts/index.html +src/nightly_build_scripts/node_modules +src/workspace-* +src/workspace +src/build.log +src/vagrant/*.log +src/vagrant/.vagrant +.vscode +.idea diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + 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) + + 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: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.rst b/README.rst index f30d8dc8..d3d46c6e 100644 --- a/README.rst +++ b/README.rst @@ -5,36 +5,55 @@ OctoPi .. :scale: 50 % .. :alt: OctoPi logo -A `Raspberry Pi `_ distribution for 3d printers. It includes the `OctoPrint `_ host software for 3d printers out of the box and `mjpg-streamer with RaspiCam support `_ for live viewing of prints and timelapse video creation. OctoPi also includes `OctoPiPanel `_, which is an LCD display app that works with OctoPrint, and scripts to configure supported display.s +A `Raspberry Pi `_ distribution for 3d printers. It includes the `OctoPrint `_ host software for 3d printers out of the box and `mjpg-streamer with RaspiCam support `_ for live viewing of prints and timelapse video creation. + This repository contains the source script to generate the distribution out of an existing `Raspbian `_ distro image. Where to get it? ---------------- -Official mirror is `here `_ +Download the latest stable build via this button: + +.. image:: https://i.imgur.com/NvUOGfS.png + :target: https://octopi.octoprint.org/latest -Alternative mirror is `here `_ +Official mirror is `here `_ +Second mirror is `here `_ -There is also a torrent for 0.10.0 `here `_ . +Nightly builds are available `here `_ -Nightly builds are avilable `here `_ +64bit Nightly builds are available `here `_ How to use it? -------------- -#. unzip the image and dd it to an sd card like any other Raspberry Pi image -#. boot the pi and connect it to a lan or wifi network, like any other Rasbpian installation. -#. OctoPrint is located at `http://octopi.local `_ and also at `https://octopi.local `_. Since the SSL certificate is self signed (and generated upon first boot), you will get a certificate warning at the latter location, please ignore it. -#. If a webcam was plugged in, MJPG-streamer is on port 8080. You can reach it at: `http://octopi.local:8080/?action=stream `_. It is also setup so that you can reach it under `http://octopi.local/webcam/?action=stream `_ and SSL respectively. +#. Unzip the image and install it to an sd card `like any other Raspberry Pi image `_ +#. Configure your WiFi by editing ``octopi-wpa-supplicant.txt`` on the root of the flashed card when using it like a thumb drive +#. Boot the Pi from the card +#. Log into your Pi via SSH (it is located at ``octopi.local`` `if your computer supports bonjour `_ or the IP address assigned by your router), default username is "pi", default password is "raspberry". Run ``sudo raspi-config``. Once that is open: + + a. Change the password via "Change User Password" + b. Optionally: Change the configured timezone via "Localization Options" > "Timezone". + c. Optionally: Change the hostname via "Network Options" > "Hostname". Your OctoPi instance will then no longer be reachable under ``octopi.local`` but rather the hostname you chose postfixed with ``.local``, so keep that in mind. + + You can navigate in the menus using the arrow keys and Enter. To switch to selecting the buttons at the bottom use Tab. + + You do not need to expand the filesystem, current versions of OctoPi do this automatically. + +OctoPrint is located at `http://octopi.local `_ and also at `https://octopi.local `_. Since the SSL certificate is self signed (and generated upon first boot), you will get a certificate warning at the latter location, please ignore it. + +To install plugins from the commandline instead of OctoPrint's built-in plugin manager, :code:`pip` may be found at :code:`/home/pi/oprint/bin/pip`. Thus, an example install cmd may be: :code:`/home/pi/oprint/bin/pip install ` + +If a USB webcam or the Raspberry Pi camera is detected, MJPG-streamer will be started automatically as webcam server. OctoPrint on OctoPi ships with correctly configured stream and snapshot URLs pointing at it. If necessary, you can reach it under `http://octopi.local/webcam/?action=stream `_ and SSL respectively, or directly on its configured port 8080: `http://octopi.local:8080/?action=stream `_. + Features -------- + * `OctoPrint `_ host software for 3d printers out of the box -* `Raspbian `_ tweaked for maximum preformance for printing out of the box +* `Raspbian `_ tweaked for maximum performance for printing out of the box * `mjpg-streamer with RaspiCam support `_ for live viewing of prints and timelapse video creation. -* `OctoPiPanel `_, which is an LCD display app that works with OctoPrint -* Configuration scripts for verious LCD displays Developing ---------- @@ -43,10 +62,11 @@ Requirements ~~~~~~~~~~~~ #. `qemu-arm-static `_ +#. `CustomPiOS `_ #. Downloaded `Raspbian `_ image. #. root privileges for chroot #. Bash -#. realpath +#. git #. sudo (the script itself calls it, running as root without sudo won't work) Build OctoPi From within OctoPi / Raspbian / Debian / Ubuntu @@ -56,20 +76,71 @@ OctoPi can be built from Debian, Ubuntu, Raspbian, or even OctoPi. Build requires about 2.5 GB of free space available. You can build it by issuing the following commands:: - sudo apt-get install realpath qemu-user-static + sudo apt-get install gawk util-linux qemu-user-static git p7zip-full python3 + git clone https://github.com/guysoft/CustomPiOS.git git clone https://github.com/guysoft/OctoPi.git cd OctoPi/src/image - curl -J -O -L http://downloads.raspberrypi.org/raspbian_latest + wget -c --trust-server-names 'https://downloads.raspberrypi.org/raspios_lite_armhf_latest' cd .. + ../../CustomPiOS/src/update-custompios-paths sudo modprobe loop - sudo bash -x ./build + sudo bash -x ./build_dist + +Building OctoPi Variants +~~~~~~~~~~~~~~~~~~~~~~~~ + +OctoPi supports building variants, which are builds with changes from the main release build. An example and other variants are available in `CustomPiOS, folder src/variants/example `_. + +docker exec -it mydistro_builder:: + + sudo docker exec -it mydistro_builder build [Variant] + +Or to build a variant inside a container:: + + sudo bash -x ./build_dist [Variant] + +Building Using Docker +~~~~~~~~~~~~~~~~~~~~~~ +`See Building with docker entry in wiki `_ + +Building Using Vagrant +~~~~~~~~~~~~~~~~~~~~~~ +There is a vagrant machine configuration to let build OctoPi in case your build environment behaves differently. Unless you do extra configuration, vagrant must run as root to have nfs folder sync working. + +Make sure you have a version of vagrant later than 1.9! + +If you are using older versions of Ubuntu/Debian and not using apt-get `from the download page `_. + +To use it:: + + sudo apt-get install vagrant nfs-kernel-server virtualbox + sudo vagrant plugin install vagrant-nfs_guest + sudo modprobe nfs + cd ../OctoPi + git clone https://github.com/guysoft/CustomPiOS.git + cd OctoPi/src + ../../CustomPiOS/src/update-custompios-paths + cd OctoPi/src/vagrant + sudo vagrant up + run_vagrant_build.sh + +After provisioning the machine, its also possible to run a nightly build which updates from devel using:: + + cd OctoPi/src/vagrant + run_vagrant_build.sh + +To build a variant on the machine simply run:: + + cd src/vagrant + run_vagrant_build.sh [Variant] + Usage ~~~~~ -#. If needed, override existing config settings by creating a new file ``src/config.local``. You can override all settings found in ``src/config``. If you need to override the path to the Raspbian image to use for building OctoPi, override the path to be used in ``ZIP_IMG``. By default the most recent file matching ``*-raspbian.zip`` found in ``src/image`` will be used. -#. Run ``src/build`` as root. +#. If needed, override existing config settings by creating a new file ``src/config.local``. You can override all settings found in ``src/modules/octopi/config``. If you need to override the path to the Raspbian image to use for building OctoPi, override the path to be used in ``ZIP_IMG``. By default the most recent file matching ``*-raspbian.zip`` found in ``src/image`` will be used. +#. Run ``src/build_dist`` as root. #. The final image will be created at the ``src/workspace`` Code contribution would be appreciated! diff --git a/media/rpi-imager-OctoPi.png b/media/rpi-imager-OctoPi.png new file mode 100644 index 00000000..ac738869 Binary files /dev/null and b/media/rpi-imager-OctoPi.png differ diff --git a/src/build b/src/build deleted file mode 100755 index 05880ff2..00000000 --- a/src/build +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -OCTOPI_PATH=$(dirname $(realpath -s $0)) -source $OCTOPI_PATH/config -source $OCTOPI_PATH/octopi diff --git a/src/build_dist b/src/build_dist new file mode 100755 index 00000000..d64a0acc --- /dev/null +++ b/src/build_dist @@ -0,0 +1,10 @@ +#! /bin/bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +export DIST_PATH=${DIR} +export CUSTOM_PI_OS_PATH=$(<${DIR}/custompios_path) +export PATH=$PATH:$CUSTOM_PI_OS_PATH +echo ${CUSTOM_PI_OS_PATH} + +${CUSTOM_PI_OS_PATH}/build_custom_os $@ diff --git a/src/chroot_script b/src/chroot_script deleted file mode 100755 index 1d779e26..00000000 --- a/src/chroot_script +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env bash -set -x -# OctoPI generation script -# Helper script that runs in a Raspbian chroot to create the OctoPI distro -# Written by Guy Sheffer -# GPL V3 -fixLd(){ - sed -i 's@/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so@\#/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so@' /etc/ld.so.preload -} - -gitclone(){ -if [ $GIT_REPO_OVERRIDE != "" ] ; then - REPO=$GIT_REPO_OVERRIDE`echo $1 | awk -F '/' '{print $(NF)}'` - sudo -u pi git clone $REPO - sudo -u pi git remote set-url $1 -else - sudo -u pi git clone $1 -fi -} - -unpackHome(){ - shopt -s dotglob - cp -av /filesystem/home/* /home/pi - shopt -u dotglob - chown -hR pi:pi /home/pi -} - -unpackRoot(){ - shopt -s dotglob - cp -av /filesystem/root/* / - shopt -u dotglob -} - -unpackBoot(){ - shopt -s dotglob - cp -av /filesystem/boot/* /boot - shopt -u dotglob -} - -fixLd -unpackHome -unpackBoot -apt-get update - -apt-get remove -y --purge scratch squeak-plugins-scratch squeak-vm wolfram-engine python-minecraftpi minecraft-pi sonic-pi oracle-java8-jdk - -#apt-get octoprint virtualenv -apt-get -y --force-yes install python-virtualenv python-dev git python-numpy screen libts-bin - -pushd /home/pi - - #build virtualenv - sudo -u pi virtualenv --system-site-packages oprint - - #OctoPrint - gitclone https://github.com/foosel/OctoPrint.git - pushd OctoPrint - sudo -u pi /home/pi/oprint/bin/python setup.py install - popd - - #OctoPiPanel - gitclone https://github.com/jonaslorander/OctoPiPanel.git - pushd OctoPiPanel - sudo -u pi /home/pi/oprint/bin/pip install -r requirements.txt - popd - - #Make sure user pi has access to serial ports - sudo usermod -a -G tty pi - sudo usermod -a -G dialout pi - - #mjpg-streamer - sudo apt-get -y --force-yes install subversion libjpeg8-dev imagemagick libav-tools cmake libv4l-dev - gitclone https://github.com/jacksonliam/mjpg-streamer.git - pushd mjpg-streamer - mv mjpg-streamer-experimental/* . - sudo -u pi make - popd - - #Add pyserial that can handle non-standard baud rates - sudo -u pi svn co http://pyserial.svn.sourceforge.net/svnroot/pyserial/trunk pyserial - pushd pyserial - pushd pyserial - sudo -u pi /home/pi/oprint/bin/python setup.py install - popd - popd - - #make autostart scripts - pushd scripts - chmod 755 webcamDaemon - chmod 755 genCert - popd - - #setup haproxy for http and https, and webcam - export HAPROXY_VERSION=1.5.8 - sudo apt-get -y --force-yes install ssl-cert libssl-dev libpcre3-dev checkinstall - rm /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/certs/ssl-cert-snakeoil.pem - sudo -u pi wget http://www.haproxy.org/download/1.5/src/haproxy-${HAPROXY_VERSION}.tar.gz - sudo -u pi tar xzvf haproxy-${HAPROXY_VERSION}.tar.gz - rm haproxy-${HAPROXY_VERSION}.tar.gz - sudo -u pi mv `ls | grep haproxy | head -n 1` haproxy-ss - pushd haproxy-ss - sudo -u pi make TARGET=linux2628 USE_LINUX_SPLICE=1 USE_LINUX_TPROXY=1 USE_PCRE=1 USE_OPENSSL=1 - mkdir -p /usr/local/share/man/man1 /usr/local/doc /usr/local/doc/haproxy - sudo checkinstall --default --pkgname haproxy --pkgversion 1.5 - popd - rm -rf haproxy-ss - - adduser --system --disabled-password --disabled-login --home /var/lib/haproxy \ - --no-create-home --quiet --force-badname --group haproxy - - #Add fbcp for TFT screens - gitclone https://github.com/tasanakorn/rpi-fbcp - pushd rpi-fbcp - mkdir build - pushd build - cmake .. - make - install fbcp /usr/local/bin/fbcp - make clean - popd - popd -popd - -sed -i 's@exit 0@@' /etc/rc.local - -echo "/home/pi/scripts/genCert" >> /etc/rc.local -echo "sudo -u pi /home/pi/scripts/webcamDaemon &" >> /etc/rc.local -echo "/usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg" >> /etc/rc.local -echo "exit 0" >> /etc/rc.local - -#automatic startup -echo "pi ALL=NOPASSWD: /sbin/shutdown" > /etc/sudoers.d/octoprint-shutdown -echo "pi ALL=NOPASSWD: /sbin/service" > /etc/sudoers.d/octoprint-service - -#reach printer by name -sudo apt-get -y --force-yes install avahi-daemon -echo octopi > /etc/hostname -sed -i 's@raspberrypi@octopi@' /etc/hosts - -# enable raspicam -echo "# enable raspicam" >> /boot/config.txt -echo "start_x=1" >> /boot/config.txt -echo "gpu_mem=128" >> /boot/config.txt - -#unpack root in the end, so etc file are not overwritten, might need to add two roots int he future -unpackRoot - -#setup runlevels for initscripts -sudo update-rc.d octoprint defaults 99 - -#cleanup -fixLd -sudo apt-get clean - -sed -i 's@\#/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so@/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so@' /etc/ld.so.preload diff --git a/src/config b/src/config old mode 100644 new mode 100755 index 9d20d99e..506f300e --- a/src/config +++ b/src/config @@ -1,24 +1,11 @@ -CONFIG_DIR=$(dirname $(realpath -s $BASH_SOURCE)) +export DIST_NAME=OctoPi +export DIST_VERSION=1.0.0 +export MODULES="base(raspicam, network, disable-services(octopi), password-for-sudo)" -if [ -f $CONFIG_DIR/config.local ]; then - source $CONFIG_DIR/config.local -fi +export RPI_IMAGER_NAME="${DIST_NAME} version ${DIST_VERSION}" +export RPI_IMAGER_DESCRIPTION="A Raspberry Pi distribution for 3D printers. Ships OctoPrint out-of-the-box." +export RPI_IMAGER_ICON="https://raw.githubusercontent.com/guysoft/OctoPi/devel/media/rpi-imager-OctoPi.png" -[ -n "$SCRIPT_PATH" ] || SCRIPT_PATH=$CONFIG_DIR -[ -n "$IMAGE_PATH" ] || IMAGE_PATH=$SCRIPT_PATH/image -[ -n "$ZIP_IMG" ] || ZIP_IMG=`ls -t $IMAGE_PATH/*-raspbian.zip | head -n 1` - -[ -n "$OCTOPI_WORKSPACE" ] || OCTOPI_WORKSPACE=$SCRIPT_PATH/workspace -[ -n "$CHROOT_SCRIPT_PATH" ] || CHROOT_SCRIPT_PATH=$SCRIPT_PATH/chroot_script -[ -n "$MOUNT_PATH" ] || MOUNT_PATH=$OCTOPI_WORKSPACE/mount - -echo "================================================================" -echo "Using the following config:" -echo "SCRIPT_PATH = $SCRIPT_PATH" -echo "IMAGE_PATH = $IMAGE_PATH" -echo "ZIP_IMG = $ZIP_IMG" -echo "OCTOPI_WORKSPACE = $OCTOPI_WORKSPACE" -echo "CHROOT_SCRIPT_PATH = $CHROOT_SCRIPT_PATH" -echo "MOUNT_PATH = $MOUNT_PATH" -echo "================================================================" +export BASE_IMAGE_ENLARGEROOT=2000 +export BASE_IMAGE_RESIZEROOT=200 diff --git a/src/filesystem/boot/cmdline-pi-tft.txt b/src/filesystem/boot/cmdline-pi-tft.txt deleted file mode 100644 index 5f7c9b28..00000000 --- a/src/filesystem/boot/cmdline-pi-tft.txt +++ /dev/null @@ -1 +0,0 @@ -dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait fbtft_device.name=rpi-display fbtft_device.speed=32000000 fbtft_device.rotate=270 fbtft_device.debug=0 fbtft_device.verbose=0 fbcon=map:10 fbcon=font:ProFont6x11 logo.nologo diff --git a/src/filesystem/boot/octopi.txt b/src/filesystem/boot/octopi.txt deleted file mode 100644 index d2427b3e..00000000 --- a/src/filesystem/boot/octopi.txt +++ /dev/null @@ -1,28 +0,0 @@ -### Configure which camera to use -# -# Available options are: -# - auto: tries first usb webcam, if that's not available tries raspi cam -# - usb: only tries usb webcam -# - raspi: only tries raspi cam -# -# Defaults to auto -# -#camera="auto" - -### Additional options to supply to MJPG Streamer for the USB camera -# -# See https://github.com/foosel/OctoPrint/wiki/MJPG-Streamer-configuration -# for available options -# -# Defaults to a resolution of 640x480 px and a framerate of 10 fps -# -#camera_usb_options="-r 640x480 -f 10" - -### additional options to supply to MJPG Streamer for the RasPi Cam -# -# See https://github.com/foosel/OctoPrint/wiki/MJPG-Streamer-configuration -# for available options -# -# Defaults to 10fps -# -#camera_raspi_options="-fps 10" diff --git a/src/filesystem/home/.octoprint/config.yaml b/src/filesystem/home/.octoprint/config.yaml deleted file mode 100755 index 9332f778..00000000 --- a/src/filesystem/home/.octoprint/config.yaml +++ /dev/null @@ -1,18 +0,0 @@ -webcam: - stream: /webcam/?action=stream - snapshot: http://127.0.0.1:8080/?action=snapshot - ffmpeg: /usr/bin/avconv -system: - actions: - - name: Shutdown - command: sudo shutdown -h now - action: shutdown - confirm: You are about to shutdown the system. - - name: Reboot - command: sudo shutdown -r now - action: reboot - confirm: You are about to reboot the system - - name: Restart OctoPrint - command: sudo service octoprint restart - action: restart - confirm: You are about to restart OctoPrint diff --git a/src/filesystem/home/scripts/OctoPiPanel b/src/filesystem/home/scripts/OctoPiPanel deleted file mode 100755 index ec58fa07..00000000 --- a/src/filesystem/home/scripts/OctoPiPanel +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -#Set API key of OctoPiPanel -KEY=$(grep key /home/pi/.octoprint/config.yaml | awk -F " " '{ print $2}') -sed -i 's/API_KEY_GOES_HERE/'"${KEY}"'/g' /home/pi/OctoPiPanel/OctoPiPanel.cfg - -sudo /home/pi/oprint/bin/python /home/pi/OctoPiPanel/OctoPiPanel.py diff --git a/src/filesystem/home/scripts/calibrate-rpi-display b/src/filesystem/home/scripts/calibrate-rpi-display deleted file mode 100755 index 5d66d741..00000000 --- a/src/filesystem/home/scripts/calibrate-rpi-display +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/event0 ts_calibrate - diff --git a/src/filesystem/home/scripts/enable-adafruit-pitft b/src/filesystem/home/scripts/enable-adafruit-pitft deleted file mode 100755 index 0a196854..00000000 --- a/src/filesystem/home/scripts/enable-adafruit-pitft +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -echo "" -echo "Installing Adafruit PiTFT Display on this installation of OctoPi, do not turn off your Pi during this process!" -echo "" - -cd ~ -mkdir pitft -cd pitft - -wget http://adafru.it/pitftsh -mv pitftsh pitft.sh -chmod +x pitft.sh - -sudo ./pitft.sh -t 28r -r - -cd ~ -sudo rm pitft -R - -echo "" -echo "Reboot you Pi to use the Adafruit Pi TFT Display" -echo "" diff --git a/src/filesystem/home/scripts/enable-rpi-display b/src/filesystem/home/scripts/enable-rpi-display deleted file mode 100755 index 8cf87bcd..00000000 --- a/src/filesystem/home/scripts/enable-rpi-display +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -echo "Enabling RPi-Display on this installation of OctoPi, do not turn off your Pi during this process!" -sudo sed -i 's/^blacklist spi-bcm2708/#blacklist spi-bcm2708/g' /etc/modprobe.d/raspi-blacklist.conf -sudo REPO_URI=https://github.com/notro/rpi-firmware BRANCH=builtin rpi-update - -if [ ! -f /boot/cmdline.txt.bak ]; then - sudo cp /boot/cmdline.txt /boot/cmdline.txt.bak -fi -sudo cp /boot/cmdline-pi-tft.txt /boot/cmdline.txt - -if ! `grep --quiet ads7846_device /etc/modules`; then - echo "ads7846_device model=7846 cs=1 gpio_pendown=25 speed=2000000 keep_vref_on=1 swap_xy=1 pressure_max=255 x_plate_ohms=60 x_min=200 x_max=3900 y_min=200 y_max=3900" | sudo tee --append /etc/modules > /dev/null; -fi diff --git a/src/filesystem/home/scripts/genCert b/src/filesystem/home/scripts/genCert deleted file mode 100755 index 8204637b..00000000 --- a/src/filesystem/home/scripts/genCert +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -if [ ! -f /etc/ssl/private/ssl-cert-snakeoil.key ]; then - echo "Generating SSL certificate" - sudo make-ssl-cert generate-default-snakeoil --force-overwrite - sudo cat /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/certs/ssl-cert-snakeoil.pem > /etc/ssl/snakeoil.pem -fi diff --git a/src/filesystem/home/scripts/webcamDaemon b/src/filesystem/home/scripts/webcamDaemon deleted file mode 100755 index 1874f818..00000000 --- a/src/filesystem/home/scripts/webcamDaemon +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -MJPGSTREAMER_HOME=/home/pi/mjpg-streamer -MJPGSTREAMER_INPUT_USB="input_uvc.so" -MJPGSTREAMER_INPUT_RASPICAM="input_raspicam.so" - -# init configuration -camera="auto" -camera_usb_options="-r 640x480 -f 10" -camera_raspi_options="-fps 10" - -if [ -e "/boot/octopi.txt" ]; then - source "/boot/octopi.txt" -fi - -# runs MJPG Streamer, using the provided input plugin + configuration -function runMjpgStreamer { - input=$1 - pushd $MJPGSTREAMER_HOME - echo Running ./mjpg_streamer -o "output_http.so -w ./www" -i "$input" - LD_LIBRARY_PATH=. ./mjpg_streamer -o "output_http.so -w ./www" -i "$input" - popd -} - -# starts up the RasPiCam -function startRaspi { - logger "Starting Raspberry Pi camera" - runMjpgStreamer "$MJPGSTREAMER_INPUT_RASPICAM $camera_raspi_options" -} - -# starts up the USB webcam -function startUsb { - logger "Starting USB webcam" - runMjpgStreamer "$MJPGSTREAMER_INPUT_USB $camera_usb_options" -} - -# we need this to prevent the later calls to vcgencmd from blocking -# I have no idea why, but that's how it is... -vcgencmd version - -# echo configuration -echo camera: $camera -echo usb options: $camera_usb_options -echo raspi options: $camera_raspi_options - -# keep mjpg streamer running if some camera is attached -while true; do - if [ -e "/dev/video0" ] && { [ "$camera" = "auto" ] || [ "$camera" = "usb" ] ; }; then - startUsb - elif [ "`vcgencmd get_camera`" = "supported=1 detected=1" ] && { [ "$camera" = "auto" ] || [ "$camera" = "raspi" ] ; }; then - startRaspi - else - echo "No camera detected, trying again in two minutes" - fi - - sleep 120 -done - diff --git a/src/filesystem/root/etc/default/octoprint b/src/filesystem/root/etc/default/octoprint deleted file mode 100644 index b956a183..00000000 --- a/src/filesystem/root/etc/default/octoprint +++ /dev/null @@ -1,19 +0,0 @@ -# Configuration for /etc/init.d/octoprint - -# The init.d script will only run if this variable non-empty. -OCTOPRINT_USER=pi - -# On what port to run daemon, default is 5000 -PORT=5000 - -# Path to the OctoPrint executable, use this to override the default setting "/usr/bin/octoprint" -DAEMON=/home/pi/oprint/bin/octoprint - -# What arguments to pass to octoprint, usually no need to touch this -DAEMON_ARGS="--port=$PORT" - -# Umask of files octoprint generates, Change this to 000 if running octoprint as its own, separate user -UMASK=022 - -# Should we run at startup? -START=yes diff --git a/src/filesystem/root/etc/init.d/octoprint b/src/filesystem/root/etc/init.d/octoprint deleted file mode 100755 index 87bf9875..00000000 --- a/src/filesystem/root/etc/init.d/octoprint +++ /dev/null @@ -1,141 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: octoprint -# Required-Start: $local_fs networking -# Required-Stop: -# Should-Start: -# Should-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: OctoPrint daemon -# Description: Starts the OctoPrint daemon with the user specified in -# /etc/default/octoprint. -### END INIT INFO - -# Author: Sami Olmari - -PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin -DESC="Octoprint Daemon" -NAME="Octoprint" -DAEMON=/usr/bin/octoprint -PIDFILE=/var/run/$NAME.pid -PKGNAME=octoprint -SCRIPTNAME=/etc/init.d/$PKGNAME - -# Read configuration variable file if it is present -[ -r /etc/default/$PKGNAME ] && . /etc/default/$PKGNAME - -# Exit if the octoprint is not installed -[ -x "$DAEMON" ] || exit 0 - -# Load the VERBOSE setting and other rcS variables -[ -f /etc/default/rcS ] && . /etc/default/rcS - -# Define LSB log_* functions. -# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. -. /lib/lsb/init-functions - -if [ -z "$START" -o "$START" != "yes" ] -then - log_warning_msg "Not starting $PKGNAME, edit /etc/default/$PKGNAME to start it." - exit 0 -fi - -if [ -z "$OCTOPRINT_USER" ] -then - log_warning_msg "Not starting $PKGNAME, OCTOPRINT_USER not set in /etc/default/$PKGNAME." - exit 0 -fi - -# -# Function to verify if a pid is alive -# -is_alive() -{ - pid=`cat $1` > /dev/null 2>&1 - kill -0 $pid > /dev/null 2>&1 - return $? -} - -# -# Function that starts the daemon/service -# -do_start() -{ - # Return - # 0 if daemon has been started - # 1 if daemon was already running - # 2 if daemon could not be started - - is_alive $PIDFILE - RETVAL="$?" - - if [ $RETVAL != 0 ]; then - start-stop-daemon --start --background --quiet --pidfile $PIDFILE --make-pidfile \ - --exec $DAEMON --chuid $OCTOPRINT_USER --user $OCTOPRINT_USER --umask $UMASK -- $DAEMON_ARGS - RETVAL="$?" - fi -} - -# -# Function that stops the daemon/service -# -do_stop() -{ - # Return - # 0 if daemon has been stopped - # 1 if daemon was already stopped - # 2 if daemon could not be stopped - # other if a failure occurred - - start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $OCTOPRINT_USER --pidfile $PIDFILE - RETVAL="$?" - [ "$RETVAL" = "2" ] && return 2 - - rm -f $PIDFILE - - [ "$RETVAL" = "0" ] && return 0 || return 1 -} - -case "$1" in - start) - [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" - do_start - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - stop) - [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" - do_stop - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - restart) - log_daemon_msg "Restarting $DESC" "$NAME" - do_stop - case "$?" in - 0|1) - do_start - case "$?" in - 0) log_end_msg 0 ;; - 1) log_end_msg 1 ;; # Old process is still running - *) log_end_msg 1 ;; # Failed to start - esac - ;; - *) - # Failed to stop - log_end_msg 1 - ;; - esac - ;; - *) - echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2 - exit 3 - ;; -esac - diff --git a/src/filesystem/root/etc/octopi_version b/src/filesystem/root/etc/octopi_version deleted file mode 100644 index d9df1bbc..00000000 --- a/src/filesystem/root/etc/octopi_version +++ /dev/null @@ -1 +0,0 @@ -0.11.0 diff --git a/src/image-raspios_lite_arm64/README b/src/image-raspios_lite_arm64/README new file mode 100644 index 00000000..e5aa7b03 --- /dev/null +++ b/src/image-raspios_lite_arm64/README @@ -0,0 +1,5 @@ +Place zipped Raspberry Pi OS 64bit image here. + +If not otherwise specified, the build script will always use the most +recent zip file matching the file name pattern "*-raspbian.zip" or "*-rpios.zip" located +here. diff --git a/src/image-rpios_arm64/README b/src/image-rpios_arm64/README new file mode 100644 index 00000000..63a2c46b --- /dev/null +++ b/src/image-rpios_arm64/README @@ -0,0 +1,5 @@ +Place zipped Raspberry Pi OS image here for the arm64 variant. Or any other variant you want to build/ + +If not otherwise specified, the build script will always use the most +recent zip file matching the file name pattern "*-raspbian.zip" or "*-rpios.zip" or "*-rpios.xz" located +here. diff --git a/src/image/README b/src/image/README index 8c07825f..4203497c 100644 --- a/src/image/README +++ b/src/image/README @@ -1,5 +1,5 @@ -Place zipped Rasbian image here. +Place zipped Raspberry Pi OS image here. Or any other variant you want to build/ If not otherwise specified, the build script will always use the most -recent zip file matching the file name pattern "*-raspbian.zip" located +recent zip file matching the file name pattern "*-raspbian.zip" or "*-rpios.zip" or "*-rpios.xz" located here. diff --git a/src/modules/octopi/config b/src/modules/octopi/config new file mode 100755 index 00000000..b39f19a3 --- /dev/null +++ b/src/modules/octopi/config @@ -0,0 +1,30 @@ +############################################################################### +# All our config settings must start with OCTOPI_ + +# OctoPrint archive +[ -n "$OCTOPI_OCTOPRINT_PACKAGE" ] || OCTOPI_OCTOPRINT_PACKAGE="OctoPrint" +[ -n "$OCTOPI_INCLUDE_OCTOPRINT" ] || OCTOPI_INCLUDE_OCTOPRINT=yes + +# CuraEngine archive & version +[ -n "$OCTOPI_CURAENGINE_VERSION" ] || OCTOPI_CURAENGINE_VERSION=15.04.6 +[ -n "$OCTOPI_CURAENGINE_ARCHIVE" ] || OCTOPI_CURAENGINE_ARCHIVE=https://github.com/Ultimaker/CuraEngine/archive/$OCTOPI_CURAENGINE_VERSION.zip +[ -n "$OCTOPI_INCLUDE_CURAENGINE" ] || OCTOPI_INCLUDE_CURAENGINE=no + +# mjpg streamer +[ -n "$OCTOPI_MJPGSTREAMER_ARCHIVE" ] || OCTOPI_MJPGSTREAMER_ARCHIVE=https://github.com/jacksonliam/mjpg-streamer/archive/master.zip +[ -n "$OCTOPI_INCLUDE_MJPGSTREAMER" ] || OCTOPI_INCLUDE_MJPGSTREAMER=yes + +# FFMPEG HLS +[ -n "$OCTOPI_INCLUDE_FFMPEG_HLS" ] || OCTOPI_INCLUDE_FFMPEG_HLS=yes + +# HAProxy +[ -n "$OCTOPI_INCLUDE_HAPROXY" ] || OCTOPI_INCLUDE_HAPROXY=yes + +# yq +[ -n "$OCTOPI_YQ_DOWNLOAD" ] || OCTOPI_YQ_DOWNLOAD=$(wget -q -O - https://api.github.com/repos/mikefarah/yq/releases/latest | grep "browser_download_url" | grep "yq_linux_arm" | cut -d : -f 2,3 | tr -d \" | tr -d ,) + +[ -n "$OCTOPI_COMMIT" ] || OCTOPI_COMMIT=`pushd "${DIST_PATH}" > /dev/null ; git rev-parse HEAD ; popd > /dev/null` + +# Fixed apt mirror +[ -n "$OCTOPI_APTMIRROR" ] || OCTOPI_APTMIRROR= + diff --git a/src/modules/octopi/filesystem/boot/octopi-network.txt b/src/modules/octopi/filesystem/boot/octopi-network.txt new file mode 100644 index 00000000..85c4c0b1 --- /dev/null +++ b/src/modules/octopi/filesystem/boot/octopi-network.txt @@ -0,0 +1,3 @@ +# Using this file to configure your network connection is no longer supported. +# +# Please use octopi-wpa-supplicant.txt instead. diff --git a/src/modules/octopi/filesystem/boot/octopi.txt b/src/modules/octopi/filesystem/boot/octopi.txt new file mode 100644 index 00000000..24cc430e --- /dev/null +++ b/src/modules/octopi/filesystem/boot/octopi.txt @@ -0,0 +1,95 @@ +### Windows users: To edit this file use Notepad++, VSCode, Atom or SublimeText. +### Do not use Notepad or WordPad. + +### MacOSX users: If you use Textedit to edit this file make sure to use +### "plain text format" and "disable smart quotes" in "Textedit > Preferences" + +### Configure which camera to use +# +# Available options are: +# - auto: tries first usb webcam, if that's not available tries raspi cam +# - usb: only tries usb webcam +# - raspi: only tries raspi cam +# +# Defaults to auto +# +#camera="auto" + +### Additional options to supply to MJPG Streamer for the USB camera +# +# See https://faq.octoprint.org/mjpg-streamer-config for available options +# +# Defaults to a resolution of 640x480 px and a framerate of 10 fps +# +#camera_usb_options="-r 640x480 -f 10" + +### Additional webcam devices known to cause problems with -f +# +# Apparently there a some devices out there that with the current +# mjpg_streamer release do not support the -f parameter (for specifying +# the capturing framerate) and will just refuse to output an image if it +# is supplied. +# +# The webcam daemon will detect those devices by their USB Vendor and Product +# ID and remove the -f parameter from the options provided to mjpg_streamer. +# +# By default, this is done for the following devices: +# Logitech C170 (046d:082b) +# GEMBIRD (1908:2310) +# Genius F100 (0458:708c) +# Cubeternet GL-UPC822 UVC WebCam (1e4e:0102) +# +# Using the following option it is possible to add additional devices. If +# your webcam happens to show above symptoms, try determining your cam's +# vendor and product id via lsusb, activating the line below by removing # and +# adding it, e.g. for two broken cameras "aabb:ccdd" and "aabb:eeff" +# +# additional_brokenfps_usb_devices=("aabb:ccdd" "aabb:eeff") +# +# If this fixes your problem, please report it back so we can include the device +# out of the box: https://github.com/guysoft/OctoPi/issues +# +#additional_brokenfps_usb_devices=() + +### Additional options to supply to MJPG Streamer for the RasPi Cam +# +# See https://faq.octoprint.org/mjpg-streamer-config for available options. +# +# NOTE: Newer raspi cam modules are reporting as usb devices causing these +# options to be ignored. Set `camera="raspi"` to avoid these issues. +# +# Defaults to 10fps +# +#camera_raspi_options="-fps 10" + +### Configuration of camera HTTP output +# +# Usually you should NOT need to change this at all! Only touch if you +# know what you are doing and what the parameters mean. +# +# Below settings are used in the mjpg-streamer call like this: +# +# -o "output_http.so -w $camera_http_webroot $camera_http_options" +# +# Current working directory is the mjpg-streamer base directory. +# +#camera_http_webroot="./www-octopi" +#camera_http_options="-n" + +# Configuration of network monitoring +# +# This enables network monitoring for wifi connections with a simple ping test. +# If connection terminates by variable reasons system tries to restart the wifi connection to reestablish a connection. +# The connection test is done every minute. +# By default it is disabled (0 = off / 1 = on) +# destination_host can be an ip address or a hostname (for hostname ensure dns resosultion is working correctly) +enable_network_monitor=0 +destination_host=192.168.1.1 + +### EXPERIMENTAL +# Support for different streamer types. +# +# Available options: +# mjpeg [default] - stable MJPG-streamer +# hls - experimental FFMPEG HLS streamer +#camera_streamer=mjpeg diff --git a/src/modules/octopi/filesystem/home/pi/.octoprint/config.yaml b/src/modules/octopi/filesystem/home/pi/.octoprint/config.yaml new file mode 100644 index 00000000..b6002e8a --- /dev/null +++ b/src/modules/octopi/filesystem/home/pi/.octoprint/config.yaml @@ -0,0 +1,14 @@ +webcam: + stream: /webcam/?action=stream + snapshot: http://127.0.0.1:8080/?action=snapshot + ffmpeg: /usr/bin/ffmpeg +plugins: + cura: + cura_engine: /usr/local/bin/cura_engine + discovery: + publicPort: 80 +server: + commands: + systemShutdownCommand: sudo shutdown -h now + systemRestartCommand: sudo shutdown -r now + serverRestartCommand: sudo service octoprint restart diff --git a/src/modules/octopi/filesystem/home/pi/OctoPrint/README.txt b/src/modules/octopi/filesystem/home/pi/OctoPrint/README.txt new file mode 100644 index 00000000..4214bd8f --- /dev/null +++ b/src/modules/octopi/filesystem/home/pi/OctoPrint/README.txt @@ -0,0 +1,7 @@ +OctoPrint 1.3.6 and newer no longer rely on a git checkout for updates, +so OctoPi no longer goes that route either. + +Feel free to manually create a git clone though if you need it (e.g. for +branch based updates or on board development): + + ~/scripts/add-octoprint-checkout diff --git a/src/modules/octopi/filesystem/home/pi/scripts/add-octoprint-checkout b/src/modules/octopi/filesystem/home/pi/scripts/add-octoprint-checkout new file mode 100755 index 00000000..8a87651b --- /dev/null +++ b/src/modules/octopi/filesystem/home/pi/scripts/add-octoprint-checkout @@ -0,0 +1,49 @@ +#!/bin/bash + +OCTOPRINT_FOLDER=/home/pi/OctoPrint +OCTOPRINT_CONFIG=/home/pi/.octoprint/config.yaml + +if [ "${PWD}" == "${OCTOPRINT_FOLDER}" ]; then + echo "Error: you are in the folder: "${OCTOPRINT_FOLDER} + echo "This is where OctoPrint is going to be checked out, please change to a different folder before running this script" + exit 1 +fi + +pause() { + read -n1 -r -p $'Press any key to continue or Ctrl+C to exit...\n' key +} + +echo +echo "This will add a git checkout of OctoPrint to ~/OctoPrint." +echo +echo "This can be helpful if you want to run development branches" +echo "of OctoPrint or do local development yourself." +echo +echo "It is however not needed for OctoPrint's normal operation." +echo +echo "If you do not want to add the git checkout after all, please" +echo "hit Ctrl+C now." +echo + +pause + +echo "--- Adding git checkout" + +rm -r $OCTOPRINT_FOLDER || true +git clone https://github.com/foosel/OctoPrint.git $OCTOPRINT_FOLDER + +echo "--- Configuring checkout folder in OctoPrint's config.yaml" + +echo "plugins: {softwareupdate: {checks: {octoprint: {update_folder: $OCTOPRINT_FOLDER}}}}" | yq m -i $OCTOPRINT_CONFIG - + +echo +echo "--- Done!" +echo + +echo "Your git checkout is now available at ~/OctoPrint. Please note that it" +echo "is currently not installed. If you want to replace the default installation" +echo "of OctoPrint with whatever is currently checked out in your git checkout" +echo "you'll need to do this manually. You'll also need to keep your checkout" +echo "up to date manually if you still have OctoPrint's update mode set to release" +echo "tracking." +echo diff --git a/src/modules/octopi/filesystem/home/pi/scripts/install-desktop b/src/modules/octopi/filesystem/home/pi/scripts/install-desktop new file mode 100755 index 00000000..a00004ae --- /dev/null +++ b/src/modules/octopi/filesystem/home/pi/scripts/install-desktop @@ -0,0 +1,77 @@ +#!/bin/bash + +if [ "$(id -u)" != "0" ] +then + echo "Please run this with sudo or as user root" 2>&1 + echo "Since we need to install a couple of packages, sudo" 2>&1 + echo "actually IS needed here. Thanks :)" 2>&1 + exit 1 +fi + +pause() { + read -n1 -r -p $'Press any key to continue or Ctrl+C to exit...\n' key +} + +echo +echo "This will install the desktop environment on your Pi" +echo "Please keep in mind that the desktop environment needs" +echo "system resources that then might not be available for" +echo "printing, possible leading to print artifacts." +echo "It is not recommended to run the desktop environment" +echo "alongside OctoPrint if you do not have a Pi with" +echo "multiple cores (e.g. Pi1 or PiZero). Even then, use" +echo "at your own risk." +echo +echo "If you do not want to install the desktop environment" +echo "after all, please hit Ctrl+C now." +echo + +pause + +echo +echo "The desktop environment can be set up to start" +echo "automatically when the Pi boots." +echo "If you want to have it set up this way, please" +echo "type 'yes' now. Type 'no' if not." +echo -n "Finish with ENTER: " + +read x_on_boot +[ "$x_on_boot" == "yes" ] || x_on_boot="no" + +echo +echo "Going to install the desktop environment (automatic start on boot: $x_on_boot)" +echo +echo "This will take a while, do NOT switch off the Pi or close this console until done!" +echo + +echo +echo "--- Updating our package list" +echo + +apt-get update + +echo +echo "--- Installing desktop packages" +echo + +apt-get install --yes raspberrypi-ui-mods + +if [ "$x_on_boot" == "yes" ] +then + echo + echo "--- Setting up Pi to boot to desktop" + echo + systemctl set-default graphical.target +else + echo + echo "--- Setting up Pi to not boot to desktop" + echo + systemctl set-default multi-user.target +fi + +echo +echo "--- Done!" +echo + +echo "You might want to reboot now: sudo reboot" +echo diff --git a/src/modules/octopi/filesystem/home/pi/scripts/safemode b/src/modules/octopi/filesystem/home/pi/scripts/safemode new file mode 100755 index 00000000..1965f0c2 --- /dev/null +++ b/src/modules/octopi/filesystem/home/pi/scripts/safemode @@ -0,0 +1,10 @@ +#!/bin/sh + +if grep -q "startOnceInSafeMode" ~/.octoprint/config.yaml; +then + # If found,replace the existing line + sed -i 's/.*startOnceInSafeMode: false.*/\ \ startOnceInSafeMode: true/' ~/.octoprint/config.yaml +else + # Append otherwise + sed -i '/server:/a \ \ startOnceInSafeMode: true' ~/.octoprint/config.yaml +fi diff --git a/src/modules/octopi/filesystem/home/pi/scripts/welcome b/src/modules/octopi/filesystem/home/pi/scripts/welcome new file mode 100755 index 00000000..46af4349 --- /dev/null +++ b/src/modules/octopi/filesystem/home/pi/scripts/welcome @@ -0,0 +1,44 @@ +#!/bin/bash + +_NAME=$(hostname) +_IP=$(hostname -I) +_OCTOPRINT_VERSION=$(/home/pi/oprint/bin/python -c "from octoprint._version import get_versions; print(get_versions()['version'])" || echo "unknown") +_OCTOPI_VERSION=$(cat /etc/octopi_version || echo "unknown") + +echo +echo "------------------------------------------------------------------------------" +echo "Access OctoPrint from a web browser on your network by navigating to any of:" +echo + +for name in $_NAME; +do + echo " http://$name.local" +done +for ip in $_IP; +do + if [[ $ip =~ .*:.* ]] + then + echo " http://[$ip]" + else + echo " http://$ip" + fi +done + +echo +echo "https is also available, with a self-signed certificate." + +if ! which lightdm 2>&1 >/dev/null; +then + echo "------------------------------------------------------------------------------" + echo "This image comes without a desktop environment installed because it's not " + echo "required for running OctoPrint. If you want a desktop environment you can " + echo "install it via" + echo + echo " sudo /home/pi/scripts/install-desktop" +fi + +echo "------------------------------------------------------------------------------" +echo "OctoPrint version : $_OCTOPRINT_VERSION" +echo "OctoPi version : $_OCTOPI_VERSION" +echo "------------------------------------------------------------------------------" +echo diff --git a/src/modules/octopi/filesystem/home/root/bin/gencert b/src/modules/octopi/filesystem/home/root/bin/gencert new file mode 100755 index 00000000..9145677f --- /dev/null +++ b/src/modules/octopi/filesystem/home/root/bin/gencert @@ -0,0 +1,11 @@ +#!/bin/sh + +keyfile=/etc/ssl/private/ssl-cert-snakeoil.key +pemfile=/etc/ssl/certs/ssl-cert-snakeoil.pem +certfile=/etc/ssl/snakeoil.pem + +if [ ! -f $keyfile ] || [ ! -s $keyfile ] || [ ! -f $pemfile ] || [ ! -s $pemfile ] || [ ! -f $certfile ] || [ ! -s $certfile ]; then + echo "Generating SSL certificate" + sudo make-ssl-cert generate-default-snakeoil --force-overwrite + sudo cat $keyfile $pemfile > $certfile +fi \ No newline at end of file diff --git a/src/modules/octopi/filesystem/home/root/bin/git b/src/modules/octopi/filesystem/home/root/bin/git new file mode 100644 index 00000000..4e8a986a --- /dev/null +++ b/src/modules/octopi/filesystem/home/root/bin/git @@ -0,0 +1,18 @@ +#!/bin/bash + +if [ "$(id -u)" == "0" ] +then + echo "Please do not run git as root, your regular user account is enough :)" + echo "The rationale behind this restriction is to prevent cloning the OctoPrint" + echo "repository as root, which will most likely break some functionality." + echo + echo "If you need to run git with root rights for some other application than" + echo "what comes preinstalled on this image you can remove this sanity check:" + echo + echo " sudo rm /root/bin/git" + echo + echo "You might have to restart your login session after doing that." + exit 1 +fi + +exec /usr/bin/git "$@" diff --git a/src/modules/octopi/filesystem/home/root/bin/streamer_select b/src/modules/octopi/filesystem/home/root/bin/streamer_select new file mode 100755 index 00000000..9d965140 --- /dev/null +++ b/src/modules/octopi/filesystem/home/root/bin/streamer_select @@ -0,0 +1,32 @@ +#!/bin/bash + +# Exit on any error. +set -e + +CONFIG_FILE=/boot/octopi.txt +MJPEG_TYPE=mjpeg +HLS_TYPE=hls +MJPEG_SERVICE=webcamd.service +HLS_SERVICE=ffmpeg_hls.service +DEFAULT_TYPE=${MJPEG_TYPE} +FLAG_DIRECTORY=/etc/octopi_streamer + +source ${CONFIG_FILE} + +if [ -z ${camera_streamer+x} ]; then + echo "No streamer type is set. Defaulting to '${DEFAULT_TYPE}'." + camera_streamer=${DEFAULT_TYPE} +fi + +rm -rf ${FLAG_DIRECTORY} +mkdir -p ${FLAG_DIRECTORY} + +echo "Setting streamer type '${camera_streamer}'." +if [ "${camera_streamer}" = "${MJPEG_TYPE}" ]; then + touch ${FLAG_DIRECTORY}/${MJPEG_TYPE} +elif [ "${camera_streamer}" = "${HLS_TYPE}" ]; then + touch ${FLAG_DIRECTORY}/${HLS_TYPE} +else + echo "Streamer type '${camera_streamer}' is not supported." + exit 1 +fi \ No newline at end of file diff --git a/src/modules/octopi/filesystem/home/root/bin/user-fix b/src/modules/octopi/filesystem/home/root/bin/user-fix new file mode 100755 index 00000000..09735c9e --- /dev/null +++ b/src/modules/octopi/filesystem/home/root/bin/user-fix @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Written by Gina Häußge originally at https://github.com/OctoPrint/OctoPi-UpToDate/blob/e70ccdaf0cd4ef4adfaa3f9b6b288fb6bfda116a/scripts/files/user-fix + +set -e + +USERID=1000 +FIRSTUSER=`getent passwd $USERID | cut -d: -f1` +FIRSTUSERHOME=`getent passwd $USERID | cut -d: -f6` + +CURRENT=`grep User= /etc/systemd/system/octoprint.service | cut -d= -f2` + +if [ "$CURRENT" = "pi" -a "$FIRSTUSER" != "pi" ]; then + # if we get here it means that the first user was renamed but we haven't yet + # updated all of OctoPi's files that depend on that name, so let's do that now + + # first we need to figure out if we can use the new user name in systemd files + # directly or if we need to use the UID - we do that by checking if the + # escaped name differes from the plain name, if so something is non ASCII + # and the UID is the safer bet + FIRSTUSERESC=`systemd-escape "$FIRSTUSER"` + if [ "$FIRSTUSER" != "$FIRSTUSERESC" ]; then + SERVICEUSER=$USERID + else + SERVICEUSER=$FIRSTUSER + fi + + # fix OctoPrint service file + echo "Fixing service file" + sed -i "s!User=pi!User=$SERVICEUSER!g" /etc/systemd/system/octoprint.service + sed -i "s!ExecStart=/home/pi/!ExecStart=$FIRSTUSERHOME/!g" /etc/systemd/system/octoprint.service + systemctl daemon-reload + + # fix sudoers files + echo "Fixing sudoers" + sed -i "s!^pi!$FIRSTUSER!g" /etc/sudoers.d/octoprint-service + sed -i "s!^pi!$FIRSTUSER!g" /etc/sudoers.d/octoprint-shutdown + + # fix scripts + echo "Fixing scripts" + sed -i "s!/home/pi/!$FIRSTUSERHOME/!g" $FIRSTUSERHOME/scripts/add-octoprint-checkout + sed -i "s!/home/pi/!$FIRSTUSERHOME/!g" $FIRSTUSERHOME/scripts/welcome + sed -i "s!/home/pi/!$FIRSTUSERHOME/!g" $FIRSTUSERHOME/.bashrc + sed -i "s!/home/pi/!$FIRSTUSERHOME/!g" /root/bin/webcamd + + # fix virtualenv + echo "Fixing paths in virtual environment" + cd $FIRSTUSERHOME/oprint + sudo -u $FIRSTUSER $FIRSTUSERHOME/.local/bin/virtualenv-tools --update-path $FIRSTUSERHOME/oprint + + # finally, reboot for all of this to actually take affect + echo "Adjusted scripts to new user, restarting services..." + systemctl reboot +fi \ No newline at end of file diff --git a/src/modules/octopi/filesystem/home/root/bin/webcamd b/src/modules/octopi/filesystem/home/root/bin/webcamd new file mode 100755 index 00000000..89d5d96a --- /dev/null +++ b/src/modules/octopi/filesystem/home/root/bin/webcamd @@ -0,0 +1,324 @@ +#!/bin/bash + +######################################################################## +### DO NOT EDIT THIS FILE TO CHANGE THE CONFIG!!! ### +### ---------------------------------------------------------------- ### +### There is no need to edit this file for changing resolution, ### +### frame rates or any other mjpg-streamer parameters. Please edit ### +### /boot/octopi.txt instead - that's what it's there for! You can ### +### even do this with your Pi powered down by directly accessing the ### +### file when using the SD card as thumb drive in your regular ### +### computer. ### +######################################################################## + +MJPGSTREAMER_HOME=/opt/mjpg-streamer +MJPGSTREAMER_INPUT_USB="input_uvc.so" +MJPGSTREAMER_INPUT_RASPICAM="input_raspicam.so" + +brokenfps_usb_devices=("046d:082b" "1908:2310" "0458:708c" "0458:6006" "1e4e:0102" "0471:0311" "038f:6001" "046d:0804" "046d:0825" "046d:0994" "0ac8:3450") + +config_dir="/boot/octopi.conf.d" + +echo "Starting up webcamDaemon..." +echo "" + +cfg_files=() +cfg_files+=/boot/octopi.txt +if [[ -d ${config_dir} ]]; then + cfg_files+=( `ls ${config_dir}/*.txt` ) +fi + +array_camera_config=() +array_camera=() +array_camera_usb_options=() +array_camera_usb_device=() +array_camera_raspi_options=() +array_camera_http_webroot=() +array_camera_http_options=() +array_additional_brokenfps_usb_devices=() +array_camera_device=() +array_assigned_device=() + +echo "--- Configuration: ----------------------------" +for cfg_file in ${cfg_files[@]}; do + # init configuration - DO NOT EDIT, USE /boot/octopi.conf.d/*.txt INSTEAD! + camera="auto" + camera_usb_options="-r 640x480 -f 10" + camera_raspi_options="-fps 10" + camera_http_webroot="./www-octopi" + camera_http_options="-n --listen 127.0.0.1" + additional_brokenfps_usb_devices=() + + if [[ -e ${cfg_file} ]]; then + source "$cfg_file" + fi + usb_options="$camera_usb_options" + + # if webcam device is explicitly given in /boot/octopi.txt, save the path of the device + # to a variable and remove its parameter from usb_options + extracted_device=`echo $usb_options | sed 's@.*-d \(/dev/\(video[0-9]\+\|v4l/[^ ]*\)\).*@\1@'` + if [ "$extracted_device" != "$usb_options" ] + then + # the camera options refer to a device, save it in a variable + # replace video device parameter with empty string and strip extra whitespace + usb_options=`echo $usb_options | sed 's/\-d \/dev\/\(video[0-9]\+\|v4l\/[^ ]*\)//g' | awk '$1=$1'` + else + extracted_device="" + fi + + # echo configuration + echo "cfg_file: $cfg_file" + echo "camera: $camera" + echo "usb options: $camera_usb_options" + echo "raspi options: $camera_raspi_options" + echo "http options: -w $camera_http_webroot $camera_http_options" + echo "" + echo "Explicitly set USB device: $extracted_device" + echo "-----------------------------------------------" + echo "" + + array_camera_config+=( $cfg_file ) + array_camera+=( $camera ) + array_camera_usb_options+=("$usb_options") + array_camera_usb_device+=("$extracted_device") + array_camera_raspi_options+=("$camera_raspi_options") + array_camera_http_webroot+=("$camera_http_webroot") + array_camera_http_options+=("$camera_http_options") + array_camera_brokenfps_usb_devices+=("${brokenfps_usb_devices[*]} ${additional_brokenfps_usb_devices[*]}") + array_camera_device+=("") +done + +# check if array contains a string +function containsString() { + local e match="$1" + shift + for e; do [[ "$e" == "$match" ]] && return 0; done + return 1 +} + +# cleans up when the script receives a SIGINT or SIGTERM +function cleanup() { + # make sure that all child processed die when we die + local pids=$(jobs -pr) + [ -n "$pids" ] && kill $pids + exit 0 +} + +# waits for our child processes +function awaitChildren() { + local pids=$(jobs -pr) + for pid in $pids; do + wait $pid + done +} + +# says goodbye when the script shuts down +function goodbye() { + # say goodbye + echo "" + echo "Goodbye..." + echo "" +} + +# runs MJPG Streamer, using the provided input plugin + configuration +function runMjpgStreamer { + input=$1 + + # There are problems with 0x000137ab firmware on VL805 (Raspberry Pi 4}). + # Try to autodetect offending firmware and temporarily fix the issue + # by changing power management mode + echo "Checking for VL805 (Raspberry Pi 4)..." + if [[ -f /usr/bin/vl805 ]]; then + VL805_VERSION=$(/usr/bin/vl805) + VL805_VERSION=${VL805_VERSION#*: } + echo " - version 0x${VL805_VERSION} detected" + case "$VL805_VERSION" in + 00013701) + echo " - nothing to be done. It shouldn't cause USB problems." + ;; + 000137ab) + echo -e " - \e[31mThis version is known to cause problems with USB cameras.\e[39m" + echo -e " You may want to downgrade to 0x0013701." + echo -e " - [FIXING] Trying the setpci -s 01:00.0 0xD4.B=0x41 hack to mitigate the" + echo -e " issue. It disables ASPM L1 on the VL805. Your board may (or may not) get" + echo -e " slightly hotter. For details see:" + echo -e " https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=244421" + setpci -s 01:00.0 0xD4.B=0x41 + ;; + *) + echo " - unknown firmware version. Doing nothing." + ;; + esac + else + echo " - It seems that you don't have VL805 (Raspberry Pi 4)." + echo " There should be no problems with USB (a.k.a. select() timeout)" + fi + + pushd $MJPGSTREAMER_HOME > /dev/null 2>&1 + echo Running ./mjpg_streamer -o "output_http.so -w $camera_http_webroot $camera_http_options" -i "$input" + LD_LIBRARY_PATH=. ./mjpg_streamer -o "output_http.so -w $camera_http_webroot $camera_http_options" -i "$input" & + sleep 1 & + sleep_pid=$! + wait ${sleep_pid} + popd > /dev/null 2>&1 +} + +# starts up the RasPiCam +function startRaspi { + logger -s "Starting Raspberry Pi camera" + runMjpgStreamer "$MJPGSTREAMER_INPUT_RASPICAM $camera_raspi_options" +} + +# starts up the USB webcam +function startUsb { + options="$usb_options" + device="video0" + + # check for parameter and set the device if it is given as a parameter + input=$1 + if [[ -n $input ]]; then + device=`basename "$input"` + fi + + # add video device into options + options="$options -d /dev/$device" + + uevent_file="/sys/class/video4linux/$device/device/uevent" + if [ -e $uevent_file ]; then + # let's see what kind of webcam we have here, fetch vid and pid... + product=`cat $uevent_file | grep PRODUCT | cut -d"=" -f2` + vid=`echo $product | cut -d"/" -f1` + pid=`echo $product | cut -d"/" -f2` + + if [[ -n "$vid" && -n "$pid" ]]; then + vidpid=`printf "%04x:%04x" "0x$vid" "0x$pid"` + + # ... then look if it is in our list of known broken-fps-devices and if so remove + # the -f parameter from the options (if it's in there, else that's just a no-op) + for identifier in ${brokenfps_usb_devices[@]}; + do + if [ "$vidpid" = "$identifier" ]; then + echo + echo "Camera model $vidpid is known to not work with -f parameter, stripping it out" + echo + options=`echo $options | sed -e "s/\(\s\+\|^\)-f\s\+[0-9]\+//g"` + fi + done + fi + fi + + logger -s "Starting USB webcam" + runMjpgStreamer "$MJPGSTREAMER_INPUT_USB $options" +} + +# make sure our cleanup function gets called when we receive SIGINT, SIGTERM +trap "cleanup" SIGINT SIGTERM +# say goodbye when we EXIT +trap "goodbye" EXIT + +# we need this to prevent the later calls to vcgencmd from blocking +# I have no idea why, but that's how it is... +vcgencmd version > /dev/null 2>&1 + +# keep mjpg streamer running if some camera is attached +while true; do + + # get list of usb video devices into an array + video_devices=($(find /dev -regextype sed -regex '\/dev/video[0-9]\+' | sort 2> /dev/null)) + + # add list of raspi camera into an array + vcgencmd_regex="supported=1 detected=1.*" + # Example output matching: supported=1 detected=1, libcamera interfaces=0 + if [[ "`vcgencmd get_camera`" =~ $vcgencmd_regex ]]; then + video_devices+=( "raspi" ) + fi + + echo "Found video devices:" + printf '%s\n' "${video_devices[@]}" + + for scan_mode in "usb" "usb-auto" "raspi" "auto"; do + camera=$scan_mode + if [[ "usb-auto" == "$scan_mode" ]]; then + camera="usb" + fi + for ((i=0;i<${#array_camera[@]};i++)); do + if [[ -z ${array_camera_device[${i}]} ]] && [[ $camera == ${array_camera[${i}]} ]]; then + camera_config="${array_camera_config[${i}]}" + usb_options="${array_camera_usb_options[${i}]}" + camera_usb_device="${array_camera_usb_device[${i}]}" + camera_raspi_options="${array_camera_raspi_options[${i}]}" + camera_http_webroot="${array_camera_http_webroot[${i}]}" + camera_http_options="${array_camera_http_options[${i}]}" + brokenfps_usb_devices="${array_camera_brokenfps_usb_devices[${i}]}" + + if [[ ${camera_usb_device} ]] && { [[ "usb" == ${scan_mode} ]] || [[ "auto" == ${scan_mode} ]]; }; then + # usb device is explicitly set in options + usb_device_path=`readlink -f ${camera_usb_device}` + if containsString "$usb_device_path" "${array_camera_device[@]}"; then + if [[ "auto" != ${scan_mode} ]]; then + array_camera_device[${i}]="already_in_use" + echo "config file='$camera_config':Video device already in use." + continue + fi + elif containsString "$usb_device_path" "${video_devices[@]}"; then + array_camera_device[${i}]="$usb_device_path" + # explicitly set usb device was found in video_devices array, start usb with the found device + echo "config file='$camera_config':USB device was set in options and found in devices, starting MJPG-streamer with the configured USB video device: $usb_device_path" + startUsb "$usb_device_path" + continue + fi + + elif [[ -z ${camera_usb_device} ]] && { [[ "usb-auto" == ${scan_mode} ]] || [[ "auto" == ${scan_mode} ]]; }; then + for video_device in "${video_devices[@]}"; do + if [[ "raspi" != "$video_device" ]]; then + if containsString "$video_device" "${array_camera_device[@]}"; then + : #already in use + else + array_camera_device[${i}]="$video_device" + # device is not set explicitly in options, start usb with first found usb camera as the device + echo "config file='$camera_config':USB device was not set in options, starting MJPG-streamer with the first found video device: ${video_device}" + startUsb "${video_device}" + break + fi + fi + done + if [[ -n ${array_camera_device[${i}]} ]]; then + continue + fi + fi + + if [[ "raspi" == ${scan_mode} ]] || [[ "auto" == ${scan_mode} ]]; then + video_device="raspi" + if containsString "$video_device" "${array_camera_device[@]}"; then + if [[ "auto" != ${scan_mode} ]]; then + array_camera_device[${i}]="already_in_use" + echo "config file='$camera_config':RasPiCam device already in use." + fi + elif containsString "$video_device" "${video_devices[@]}"; then + array_camera_device[${i}]="$video_device" + echo "config file='$camera_config':Starting MJPG-streamer with video device: ${video_device}" + startRaspi + sleep 30 & + sleep_pid=$! + wait ${sleep_pid} + fi + fi + fi + done + done + + array_assigned_device=( ${array_camera_device[*]} ) + if [[ ${#array_camera[@]} -eq ${#array_assigned_device[@]} ]]; then + echo "Done bringing up all configured video devices" + awaitChildren + + # reset array_camera_device to empty + array_camera_device=() + for cam in ${array_camera[@]}; do + array_camera_device+=("") + done + fi + + echo "Scanning again in two minutes" + sleep 120 +done diff --git a/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-octoprint.http b/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-octoprint.http new file mode 100644 index 00000000..0f506571 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-octoprint.http @@ -0,0 +1,106 @@ +HTTP/1.0 503 Service Unavailable +Cache-Control: no-cache +Connection: close +Content-Type: text/html + + + + OctoPrint is currently not running + + + +
+

The OctoPrint server is currently not running

+ +

+ If you just started up your Raspberry Pi, please wait a couple of seconds, then + try to refresh this page. +

+ +

+ If the issue persists, please log into your Raspberry Pi via SSH and check the following: +

+ +
    +
  • + Verify that the process is running: + ps -ef | grep -i octoprint | grep -i python should show a + python process: +
    pi@octopi:~ $ ps -ef | grep -i octoprint | grep -i python
    +pi 1441 1 6 11:12 ? 00:00:15 /home/pi/oprint/bin/python
    +/home/pi/oprint/bin/octoprint --host=127.0.0.1 --port=5000
    +
  • +
  • + If it isn't, the question is why. Take a look into + ~/.octoprint/logs/octoprint.log, there might + be an error logged in there that helps to determine + what's wrong. +
  • +
  • + You might also want to try if you can restart the server + (if no obvious error is visible): + sudo service octoprint restart. +
  • +
+ +

+ If all that doesn't help to trouble shoot the issue, you can seek + support on the OctoPrint Community Forum. + Please provide your OctoPi and OctoPrint versions as well as your octoprint.log + and explain what you already tried and observed as detailed as possible. +

+
+ + + diff --git a/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-webcam-hls.http b/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-webcam-hls.http new file mode 100644 index 00000000..e94373b1 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-webcam-hls.http @@ -0,0 +1,68 @@ +HTTP/1.0 503 Service Unavailable +Cache-Control: no-cache +Connection: close +Content-Type: text/html + + + + HLS Webcam server is currently not running + + + +
+

The HLS webcam server is currently not running

+
+ + + diff --git a/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-webcam.http b/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-webcam.http new file mode 100644 index 00000000..699a835c --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-webcam.http @@ -0,0 +1,111 @@ +HTTP/1.0 503 Service Unavailable +Cache-Control: no-cache +Connection: close +Content-Type: text/html + + + + Webcam server is currently not running + + + +
+

The webcam server is currently not running

+ +

+ If you do not have a camera attached, this is normal and can be safely ignored. +

+ +

+ Otherwise, if you just started up your Raspberry Pi or just plugged in your camera, + please wait a couple of seconds. +

+ +

+ If the issue persists, please check the following: +

+ +
    +
  • + If you have a Raspberry Pi camera, verify that it is properly attached. The ribbon + cable can be plugged in the wrong way. Power off your Pi first, do not attempt + to attach or detach the Raspberry Pi camera while the Pi is powered! +
  • +
  • + If you have a USB camera, it might be that it does not support MJPG (Motion JPEG) natively and needs the + -y parameter to work. Try editing octopi.txt, + add -y to camera_usb_options and make sure to remove the leading #, e.g.: +
    camera_usb_options="-r 640x480 -f 10 -y"
    + Reboot your Raspberry Pi with the camera attached and see if that makes it work.
    + Note: If your camera doesn't support MJPG natively, the webcam server will have to use valuable + system resources to transcode the camera stream which could be better used for printing. Consider + getting a camera that does support MJPG natively. +
  • +
  • + Log into your Raspberry Pi via SSH. Check if your camera is detected by the system via lsusb. + If it is check what the webcam server is reporting in /var/log/webcamd.log, there might be an + error logged in there that helps to determine what's wrong. +
  • +
+ +

+ If all that doesn't help to trouble shoot the issue, you can seek + support on the OctoPrint Community Forum. + Please provide your camera model, lsusb output and /var/log/webcamd.log and explain what you + already tried and observed as detailed as possible. +

+
+ + + diff --git a/src/filesystem/root/etc/haproxy/haproxy.cfg b/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.1.x.cfg similarity index 51% rename from src/filesystem/root/etc/haproxy/haproxy.cfg rename to src/modules/octopi/filesystem/root/etc/haproxy/haproxy.1.x.cfg index c12058d0..443dd002 100644 --- a/src/filesystem/root/etc/haproxy/haproxy.cfg +++ b/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.1.x.cfg @@ -2,12 +2,13 @@ global maxconn 4096 user haproxy group haproxy - daemon - log 127.0.0.1 local0 debug + log /dev/log local1 debug + tune.ssl.default-dh-param 2048 defaults log global mode http + compression algo gzip option httplog option dontlognull retries 3 @@ -20,18 +21,29 @@ defaults timeout server 15min frontend public - bind *:80 - bind 0.0.0.0:443 ssl crt /etc/ssl/snakeoil.pem + bind :::80 v4v6 + bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem option forwardfor except 127.0.0.1 use_backend webcam if { path_beg /webcam/ } + use_backend webcam_hls if { path_beg /hls/ } + use_backend webcam_hls if { path_beg /jpeg/ } default_backend octoprint backend octoprint + acl needs_scheme req.hdr_cnt(X-Scheme) eq 0 + reqrep ^([^\ :]*)\ /(.*) \1\ /\2 - reqadd X-Scheme:\ https if { ssl_fc } + reqadd X-Scheme:\ https if needs_scheme { ssl_fc } + reqadd X-Scheme:\ http if needs_scheme !{ ssl_fc } option forwardfor server octoprint1 127.0.0.1:5000 + errorfile 503 /etc/haproxy/errors/503-no-octoprint.http backend webcam reqrep ^([^\ :]*)\ /webcam/(.*) \1\ /\2 server webcam1 127.0.0.1:8080 + errorfile 503 /etc/haproxy/errors/503-no-webcam.http + +backend webcam_hls + server webcam_hls_1 127.0.0.1:28126 + errorfile 503 /etc/haproxy/errors/503-no-webcam-hls.http diff --git a/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.2.x.cfg b/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.2.x.cfg new file mode 100644 index 00000000..b9c30185 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.2.x.cfg @@ -0,0 +1,49 @@ +global + maxconn 4096 + user haproxy + group haproxy + log /dev/log local1 debug + tune.ssl.default-dh-param 2048 + +defaults + log global + mode http + compression algo gzip + option httplog + option dontlognull + retries 3 + option redispatch + option http-server-close + option forwardfor + maxconn 2000 + timeout connect 5s + timeout client 15m + timeout server 15m + +frontend public + bind :::80 v4v6 + bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem + option forwardfor except 127.0.0.1 + use_backend webcam if { path_beg /webcam/ } + use_backend webcam_hls if { path_beg /hls/ } + use_backend webcam_hls if { path_beg /jpeg/ } + default_backend octoprint + +backend octoprint + acl needs_scheme req.hdr_cnt(X-Scheme) eq 0 + + http-request replace-path ^([^\ :]*)\ /(.*) \1\ /\2 + http-request add-header X-Scheme https if needs_scheme { ssl_fc } + http-request add-header X-Scheme http if needs_scheme !{ ssl_fc } + option forwardfor + server octoprint1 127.0.0.1:5000 + errorfile 503 /etc/haproxy/errors/503-no-octoprint.http + +backend webcam + http-request replace-path /webcam/(.*) /\1 + server webcam1 127.0.0.1:8080 + errorfile 503 /etc/haproxy/errors/503-no-webcam.http + +backend webcam_hls + server webcam_hls_1 127.0.0.1:28126 + errorfile 503 /etc/haproxy/errors/503-no-webcam-hls.http diff --git a/src/modules/octopi/filesystem/root/etc/init.d/change_hostname b/src/modules/octopi/filesystem/root/etc/init.d/change_hostname new file mode 100755 index 00000000..7c5ef568 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/init.d/change_hostname @@ -0,0 +1,60 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: change_hostname +# Required-Start: $local_fs +# Required-Stop: +# Default-Start: 3 +# Default-Stop: +# Short-Description: Change pi's hostname via /boot/octopi-hostname.txt +# Description: +### END INIT INFO + +. /lib/lsb/init-functions + +do_start () { + text_file="/boot/octopi-hostname.txt" + if [ ! -f "$text_file" ] + then + exit 0 + fi + + old_hostname=`hostname` + new_hostname=`head -n1 "$text_file" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | tr -d '\n'` + + if [ ! -n "$new_hostname" ] + then + log_failure_msg "No new host name provided, refusing to change to empty host name" + exit 1 + fi + + # make sure we do have a valid hostname here (see RFC 952 and 1123, a-zA-Z0-9 only) + sanitized_hostname=`echo "$new_hostname" | tr -cd '[[:alnum:]]-'` + if [ "$new_hostname" = "$sanitized_hostname" ] + then + rm "$text_file" + echo "$new_hostname" > /etc/hostname + sed -i -e "s@$old_hostname@$new_hostname@g" /etc/hosts + + log_success_msg "Change of host name prepared, rebooting to apply..." + /sbin/reboot + else + log_failure_msg "Hostname $new_hostname contains invalid characters (only a-zA-Z0-9 are allowed), refusing to change" + fi +} + +case "$1" in + start|"") + do_start + ;; + restart|reload|force-reload) + echo "Error: argument '$1' not supported" >&2 + exit 3 + ;; + stop) + # No-op + ;; + *) + echo "Usage: change_hostname [start|stop]" >&2 + exit 3 + ;; +esac diff --git a/src/modules/octopi/filesystem/root/etc/init.d/change_password b/src/modules/octopi/filesystem/root/etc/init.d/change_password new file mode 100755 index 00000000..851d3e2b --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/init.d/change_password @@ -0,0 +1,46 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: change_password +# Required-Start: $local_fs +# Required-Stop: +# Default-Start: 3 +# Default-Stop: +# Short-Description: Change pi's password via /boot/octopi-password.txt +# Description: +### END INIT INFO + +. /lib/lsb/init-functions + +do_start () { + text_file="/boot/octopi-password.txt" + if [ ! -f "$text_file" ] + then + exit 0 + fi + + new_password=`head -n1 "$text_file" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | tr -d '\n'` + if [ ! -n "$new_password" ] + then + log_failure_msg "No new password provided, refusing to change to empty password" + exit 1 + fi + + (echo "pi:$new_password" | chpasswd && rm "$text_file" && log_success_msg "Password for user pi changed and change file deleted") || log_failure_msg "Could not change password" +} + +case "$1" in + start|"") + do_start + ;; + restart|reload|force-reload) + echo "Error: argument '$1' not supported" >&2 + exit 3 + ;; + stop) + # No-op + ;; + *) + echo "Usage: change_password [start|stop]" >&2 + exit 3 + ;; +esac diff --git a/src/modules/octopi/filesystem/root/etc/logrotate.d/webcamd b/src/modules/octopi/filesystem/root/etc/logrotate.d/webcamd new file mode 100644 index 00000000..2c5b5c68 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/logrotate.d/webcamd @@ -0,0 +1,10 @@ +/var/log/webcamd.log +{ + rotate 4 + weekly + missingok + notifempty + compress + delaycompress + sharedscripts +} diff --git a/src/modules/octopi/filesystem/root/etc/network/if-up.d/powersave_off b/src/modules/octopi/filesystem/root/etc/network/if-up.d/powersave_off new file mode 100755 index 00000000..9801cf33 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/network/if-up.d/powersave_off @@ -0,0 +1,23 @@ +#!/bin/sh + +set -e + +# Don't bother for loopback +if [ "$IFACE" = lo ]; then + exit 0 +fi + +# Only run from ifup. +if [ "$MODE" != start ]; then + exit 0 +fi + +# Only run once +if [ "$ADDRFAM" != meta ]; then + exit 0 +fi + +/usr/sbin/iw dev wlan0 set power_save off + +exit 0 + diff --git a/src/modules/octopi/filesystem/root/etc/nginx/sites-available/default b/src/modules/octopi/filesystem/root/etc/nginx/sites-available/default new file mode 100644 index 00000000..a4183d87 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/nginx/sites-available/default @@ -0,0 +1,11 @@ +server { + listen 127.0.0.1:28126; + + root /run/webcam; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } +} \ No newline at end of file diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/ffmpeg_hls.service b/src/modules/octopi/filesystem/root/etc/systemd/system/ffmpeg_hls.service new file mode 100644 index 00000000..3a1f463b --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/ffmpeg_hls.service @@ -0,0 +1,54 @@ +[Unit] +Description=FFMPEG HLS webcam streaming service +ConditionPathExists=/etc/octopi_streamer/hls + +[Service] +User=root +Restart=always +RestartSec=5 +WatchdogSec=21600 +Nice=10 +ExecStartPre=/bin/rm -rf /run/webcam +ExecStartPre=/bin/mkdir -p /run/webcam/hls +ExecStartPre=/bin/mkdir -p /run/webcam/hls/240p +ExecStartPre=/bin/mkdir -p /run/webcam/hls/480p +ExecStartPre=/bin/mkdir -p /run/webcam/jpeg +ExecStartPre=/bin/cp /var/lib/ffmpeg_hls/stream.m3u8 /run/webcam/hls/stream.m3u8 +ExecStartPre=/bin/chown -R webcam:webcam /run/webcam +ExecStartPre=/bin/chmod -R 0755 /run/webcam + +ExecStart=/usr/bin/sudo -u webcam \ + /opt/ffmpeg-hls/ffmpeg \ + \ + -framerate 30 -video_size 640x480 \ + -i /dev/video0 \ + -pix_fmt yuv420p \ + \ + -c:v mjpeg -q:v 0 \ + -f image2 -r 1 -update 1 -atomic_writing 1 \ + /run/webcam/jpeg/frame.jpg \ + \ + -c:v h264_v4l2m2m -level:v 4.0 \ + -b:v 1264k -flags +cgop \ + -g 30 -keyint_min 30 \ + \ + -f hls -hls_time 1 \ + -hls_flags delete_segments+program_date_time+temp_file+independent_segments \ + -hls_allow_cache 0 -hls_segment_type fmp4 \ + -hls_list_size 32 -hls_delete_threshold 64 \ + /run/webcam/hls/480p/stream.m3u8 \ + \ + -vf scale=-1:240 \ + \ + -c:v h264_v4l2m2m -level:v 4.0 \ + -b:v 240k -flags +cgop \ + -g 30 -keyint_min 30 \ + \ + -f hls -hls_time 1 \ + -hls_flags delete_segments+program_date_time+temp_file+independent_segments \ + -hls_allow_cache 0 -hls_segment_type fmp4 \ + -hls_list_size 32 -hls_delete_threshold 64 \ + /run/webcam/hls/240p/stream.m3u8 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/gencert.service b/src/modules/octopi/filesystem/root/etc/systemd/system/gencert.service new file mode 100644 index 00000000..c22b6ffa --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/gencert.service @@ -0,0 +1,17 @@ +[Unit] +Description=Ensure that haproxy certs are generated + +DefaultDependencies=no + +Before=network-pre.target +Wants=network-pre.target + +After=local-fs.target +Wants=local-fs.target + +[Service] +Type=oneshot +ExecStart=/root/bin/gencert + +[Install] +WantedBy=multi-user.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.service b/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.service new file mode 100644 index 00000000..ec4a008e --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.service @@ -0,0 +1,8 @@ +[Unit] + Description=Network Monitor + ConditionPathExists=/usr/local/bin/networkcheck + +[Service] + User=root + Type=simple + ExecStart=/usr/local/bin/networkcheck & diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.timer b/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.timer new file mode 100644 index 00000000..940694fe --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.timer @@ -0,0 +1,10 @@ +[Unit] + Description=Network Monitor Trigger (every 1 minutes) + After=network.target + +[Timer] + OnCalendar=*-*-* *:*:00 + AccuracySec=1s + +[Install] + WantedBy=timers.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/octoprint.service b/src/modules/octopi/filesystem/root/etc/systemd/system/octoprint.service new file mode 100644 index 00000000..191f4e05 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/octoprint.service @@ -0,0 +1,14 @@ +[Unit] +Description=The snappy web interface for your 3D printer +After=network.online.target +Wants=network.online.target + +[Service] +Environment="HOST=127.0.0.1" +Environment="PORT=5000" +Type=simple +User=pi +ExecStart=/home/pi/oprint/bin/octoprint serve --host=${HOST} --port=${PORT} + +[Install] +WantedBy=multi-user.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/streamer_select.service b/src/modules/octopi/filesystem/root/etc/systemd/system/streamer_select.service new file mode 100644 index 00000000..402fd512 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/streamer_select.service @@ -0,0 +1,10 @@ +[Unit] +Description=OctoPi streamer selector +Before=webcamd.service ffmpeg_hls.service nginx.service + +[Service] +Type=oneshot +ExecStart=/root/bin/streamer_select + +[Install] +WantedBy=multi-user.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/user-fix.service b/src/modules/octopi/filesystem/root/etc/systemd/system/user-fix.service new file mode 100644 index 00000000..b95981ca --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/user-fix.service @@ -0,0 +1,18 @@ +# Written by Gina Häußge originally at https://github.com/OctoPrint/OctoPi-UpToDate/blob/e70ccdaf0cd4ef4adfaa3f9b6b288fb6bfda116a/scripts/files/user-fix.service +[Unit] +Description=Ensure that user name changes are applied as needed + +DefaultDependencies=no + +Before=network-pre.target +Wants=network-pre.target + +After=local-fs.target +Wants=local-fs.target + +[Service] +Type=oneshot +ExecStart=/root/bin/user-fix + +[Install] +WantedBy=multi-user.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service b/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service new file mode 100644 index 00000000..451d2377 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service @@ -0,0 +1,15 @@ +[Unit] +Description=the OctoPi webcam daemon with the user specified config +ConditionPathExists=/etc/octopi_streamer/mjpeg + +[Service] +WorkingDirectory=/root/bin +StandardOutput=append:/var/log/webcamd.log +StandardError=append:/var/log/webcamd.log +ExecStart=/root/bin/webcamd +Restart=always +Type=simple +RestartSec=1 + +[Install] +WantedBy=multi-user.target diff --git a/src/filesystem/root/etc/udev/rules.d/95-ads7846.rules b/src/modules/octopi/filesystem/root/etc/udev/rules.d/95-ads7846.rules similarity index 100% rename from src/filesystem/root/etc/udev/rules.d/95-ads7846.rules rename to src/modules/octopi/filesystem/root/etc/udev/rules.d/95-ads7846.rules diff --git a/src/modules/octopi/filesystem/root/usr/lib/systemd/system/nginx.service b/src/modules/octopi/filesystem/root/usr/lib/systemd/system/nginx.service new file mode 100644 index 00000000..8ef64228 --- /dev/null +++ b/src/modules/octopi/filesystem/root/usr/lib/systemd/system/nginx.service @@ -0,0 +1,20 @@ +# NGINX service definition based on Debian buster version. +[Unit] +Description=NGINX server for serving HLS and JPEG frames +Documentation=man:nginx(8) +After=network.target nss-lookup.target +ConditionPathExists=/etc/octopi_streamer/hls + +[Service] +Type=forking +PIDFile=/run/nginx.pid +ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' +ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' +ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload +ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid +TimeoutStopSec=5 +KillMode=mixed +Nice=10 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/modules/octopi/filesystem/root/usr/local/bin/networkcheck b/src/modules/octopi/filesystem/root/usr/local/bin/networkcheck new file mode 100755 index 00000000..0ab1f406 --- /dev/null +++ b/src/modules/octopi/filesystem/root/usr/local/bin/networkcheck @@ -0,0 +1,28 @@ +#!/bin/bash + +source /boot/octopi.txt + +if [ $enable_network_monitor == 1 ] && [ "$destination_host" != "" ]; then + + if [ -f /boot/octopi-wpa-supplicant.txt ]; then # check if config file exists + input="/boot/octopi-wpa-supplicant.txt" + while IFS= read -r line; do # read config file line by line + if [[ $line =~ ^network=.* ]]; then # check if we have a network config if a line starts with "network=" + echo "network config found..." + ping -c4 $destination_host > /dev/null # check if destination is reachable - possible by default the router + if [ $? != 0 ]; then + echo "Destination not reachable - reconfigure interface..." + sudo wpa_cli -i wlan0 reconfigure # reconfigure network to trigger reconnect + sudo dhclient -v # ensure connection will be established by refresh dhcp lease + echo "Reconnect done." + exit 0 # if we detect multiple network configs exit after 1st one - one reconnect is enough :-) + else + echo "Destination reachable - no action needed." + exit 0 # destination reached - exit loop + fi + fi + done < "$input" + fi +else + echo "Network monitoring not enabled." +fi diff --git a/src/modules/octopi/filesystem/root/var/lib/ffmpeg_hls/stream.m3u8 b/src/modules/octopi/filesystem/root/var/lib/ffmpeg_hls/stream.m3u8 new file mode 100644 index 00000000..a28b385e --- /dev/null +++ b/src/modules/octopi/filesystem/root/var/lib/ffmpeg_hls/stream.m3u8 @@ -0,0 +1,6 @@ +#EXTM3U +#EXT-X-VERSION:3 +#EXT-X-STREAM-INF:BANDWIDTH=245760,RESOLUTION=320x240 +240p/stream.m3u8 +#EXT-X-STREAM-INF:BANDWIDTH=1294336,RESOLUTION=640x480 +480p/stream.m3u8 \ No newline at end of file diff --git a/src/modules/octopi/start_chroot_script b/src/modules/octopi/start_chroot_script new file mode 100755 index 00000000..d78f49e6 --- /dev/null +++ b/src/modules/octopi/start_chroot_script @@ -0,0 +1,349 @@ +#!/usr/bin/env bash +# OctoPI generation script +# Helper script that runs in a Raspbian chroot to create the OctoPI distro +# Written by Guy Sheffer and Gina Häußge +# GPL V3 +######## +set -x +set -e + +export LC_ALL=C + +source /common.sh + +if [ -n "$OCTOPI_APTMIRROR" ]; +then + echo "Switching apt mirror in /etc/apt/sources.list to $OCTOPI_APTMIRROR" + cp /etc/apt/sources.list /etc/apt/sources.list.backup + sed -i "s@http://raspbian.raspberrypi.org/raspbian/@$OCTOPI_APTMIRROR@g" /etc/apt/sources.list +fi + +WEBCAM_USER=webcam +FFMPEG_HLS_COMMIT=c6fdbe26ef30fff817581e5ed6e078d96111248a +FFMPEG_HLS_DIR=/opt/ffmpeg-hls + +### Script #### + +unpack /filesystem/home/pi /home/"${BASE_USER}" "${BASE_USER}" +unpack /filesystem/home/root /root root +unpack /filesystem/boot /boot + +apt-get update + +# in case we are building from a regular raspbian image instead of the lite one... +remove_extra=$(remove_if_installed scratch squeak-plugins-scratch squeak-vm wolfram-engine python-minecraftpi minecraft-pi sonic-pi oracle-java8-jdk bluej libreoffice-common libreoffice-core freepats greenfoot nodered) +echo "removing:" $remove_extra +apt-get remove -y --purge $remove_extra +apt-get autoremove -y + +apt-get -y --force-yes install python3 python3-virtualenv python3-dev git screen subversion cmake cmake-data avahi-daemon libavahi-compat-libdnssd1 libffi-dev libssl-dev libatlas3-base unzip + +echo " - Reinstall iputils-ping" +apt-get install --reinstall iputils-ping + +pushd /home/"${BASE_USER}" + + # build virtualenv + sudo -u "${BASE_USER}" python3 -m virtualenv --python=python3 oprint + sudo -u "${BASE_USER}" /home/"${BASE_USER}"/oprint/bin/pip install --upgrade pip + + # OctoPrint + if [ "$OCTOPI_INCLUDE_OCTOPRINT" == "yes" ] + then + echo "--- Installing OctoPrint" + PIP_DEFAULT_TIMEOUT=60 sudo -u "${BASE_USER}" /home/"${BASE_USER}"/oprint/bin/pip install $OCTOPI_OCTOPRINT_PACKAGE + fi + + #mjpg-streamer + if [ "$OCTOPI_INCLUDE_MJPGSTREAMER" == "yes" ] + then + install_dir=/opt/mjpg-streamer + echo "--- Installing mjpg-streamer to $install_dir" + if [ "${BASE_DISTRO}" == "ubuntu" ]; then + apt-get -y --allow-downgrades --allow-remove-essential --allow-change-held-packages install libjpeg8-dev + else + if [ $( is_in_apt libjpeg62-turbo-dev ) -eq 1 ]; then + apt-get -y --force-yes install libjpeg62-turbo-dev + elif [ $( is_in_apt libjpeg8-dev ) -eq 1 ]; then + apt-get -y --force-yes install libjpeg8-dev + fi + fi + + apt-get -y --force-yes --no-install-recommends install imagemagick ffmpeg libv4l-dev + + wget $OCTOPI_MJPGSTREAMER_ARCHIVE -O mjpg-streamer.zip + unzip mjpg-streamer.zip + rm mjpg-streamer.zip + + pushd mjpg-streamer-master/mjpg-streamer-experimental + # As said in Makefile, it is just a wrapper around CMake. + # To apply -j option, we have to unwrap it. + build_dir=_build + mkdir -p $build_dir + pushd $build_dir + cmake -DCMAKE_BUILD_TYPE=Release .. + popd + + make -j $(nproc) -C $build_dir + + mkdir -p $install_dir + + install -m 755 $build_dir/mjpg_streamer $install_dir + find $build_dir -name "*.so" -type f -exec install -m 644 {} $install_dir \; + + # copy bundled web folder + cp -a -r ./www $install_dir + chmod 755 $install_dir/www + chmod -R 644 $install_dir/www + + # create our custom web folder and add a minimal index.html to it + mkdir $install_dir/www-octopi + pushd $install_dir/www-octopi + cat <> index.html + +mjpg_streamer test page + +

Snapshot

+

Refresh the page to refresh the snapshot

+Snapshot +

Stream

+Stream + + +EOT + popd + popd + rm -rf mjpg-streamer-master + + # symlink for backwards compatibility + sudo -u "${BASE_USER}" ln -s $install_dir /home/"${BASE_USER}"/mjpg-streamer + fi + + # FFMPEG HLS + if [ "$OCTOPI_INCLUDE_FFMPEG_HLS" == "yes" ] + then + apt-get install -y --force-yes --no-install-recommends nginx + + ARCH=arm + if [ "${BASE_ARCH}" == "aarch64" ]; then + ARCH=aarch64 + fi + + FFMPEG_BUILD_DIR=$(mktemp -d) + pushd ${FFMPEG_BUILD_DIR} + FFMPEG_ARCHIVE=ffmpeg.tar.gz + wget https://api.github.com/repos/FFmpeg/FFmpeg/tarball/${FFMPEG_COMMIT} -O ${FFMPEG_ARCHIVE} + tar xvzf ${FFMPEG_ARCHIVE} + cd FFmpeg* + ./configure \ + --arch="${ARCH}" \ + --disable-doc \ + --disable-htmlpages \ + --disable-manpages \ + --disable-podpages \ + --disable-txtpages \ + --disable-ffplay \ + --disable-ffprobe + make -j$(nproc) + mkdir -p ${FFMPEG_HLS_DIR} + copy_and_export ffmpeg-hls-"${ARCH}" ffmpeg "${FFMPEG_HLS_DIR}" + popd + rm -r ${FFMPEG_BUILD_DIR} + + useradd ${WEBCAM_USER} + usermod -aG video ${WEBCAM_USER} + fi + + #CuraEngine + if [ "$OCTOPI_INCLUDE_CURAENGINE" == "yes" ] + then + echo "--- Installing CuraEngine" + folder=CuraEngine-$OCTOPI_CURAENGINE_VERSION + zipfile=$folder.zip + apt-get -y install gcc-4.9 g++-4.9 + sudo -u "${BASE_USER}" wget -O$zipfile $OCTOPI_CURAENGINE_ARCHIVE + sudo -u "${BASE_USER}" unzip $zipfile + pushd $folder + sudo -u "${BASE_USER}" make -j$(nproc) CXX=g++-4.9 VERSION=$OCTOPI_CURAENGINE_VERSION + cp build/CuraEngine /usr/local/bin/cura_engine + popd + sudo -u "${BASE_USER}" rm -r $folder $zipfile + fi + + #setup haproxy for http and https, and webcam + if [ "$OCTOPI_INCLUDE_HAPROXY" == "yes" ] + then + echo "--- Installing haproxy" + apt-get -y --force-yes install ssl-cert haproxy + rm /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/certs/ssl-cert-snakeoil.pem + fi + + # fetch current yq build and install to /usr/local/bin + wget -O yq $OCTOPI_YQ_DOWNLOAD && chmod +x yq && mv yq /usr/local/bin + +popd + +#Make sure user pi / ${BASE_USER} has access to serial ports +usermod -a -G tty "${BASE_USER}" +usermod -a -G dialout "${BASE_USER}" + +# If building against Ubuntu, make sure vcgencmd is available and pi has the rights to use it +if [ "${BASE_DISTRO}" == "ubuntu" ]; then + apt-get -y --force-yes install libraspberrypi-bin + usermod -a -G video "${BASE_USER}" +fi + +# store octopi commit used to build this image +echo "$OCTOPI_COMMIT" > /etc/octopi_commit + +# Keep legacy compatibility +ln -s /etc/custompios_buildbase /etc/octopi_buildbase + +# allow pi / ${BASE_USER} user to run shutdown and service commands +echo "${BASE_USER} ALL=NOPASSWD: /sbin/shutdown" > /etc/sudoers.d/octoprint-shutdown +echo "${BASE_USER} ALL=NOPASSWD: /usr/sbin/service" > /etc/sudoers.d/octoprint-service + +#make sure users don't run git with sudo, thus breaking permissions, by adding /root/bin to the +#default sudo path and placing a git wrapper script there that checks if it's run as root +sed -i "s@secure_path=\"@secure_path=\"/root/bin:@g" /etc/sudoers +chmod +x /root/bin/git + +# add some "How To" info to boot output +# Note, this code is also in /filesystem/home/pi/scripts/ +sed -i 's@exit 0@@' /etc/rc.local +cat <<'EOT' >> /etc/rc.local + +echo +echo "------------------------------------------------------------" +echo +echo "You may now open a web browser on your local network and " +echo "navigate to any of the following addresses to access " +echo "OctoPrint:" +echo +for name in $_NAME; +do + echo " http://$name.local" +done + +for ip in $(hostname -I); +do + echo " http://$ip" +done + +echo +echo "https is also available, with a self-signed certificate." +echo +echo "------------------------------------------------------------" +echo +EOT + +echo 'exit 0' >> /etc/rc.local + +# add a longer welcome text to ~pi/.bashrc / ~${BASE_USER}/.bashrc +echo "source /home/${BASE_USER}/scripts/welcome" >> /home/${BASE_USER}/.bashrc + +#unpack root in the end, so etc file are not overwritten, might need to add two roots int he future +unpack /filesystem/root / + +##################################################################### +### setup services + +### Disable GUI at start +systemctl_if_exists disable lightdm.service || true + +update-rc.d change_password defaults +update-rc.d change_hostname defaults + + +### OctoPrint + +if [ "$OCTOPI_INCLUDE_OCTOPRINT" == "yes" ] +then + systemctl_if_exists enable octoprint.service +else + # let's remove the configs for system services we don't need + rm /etc/systemd/system/octoprint.service +fi + +### haproxy + +if [ "$OCTOPI_INCLUDE_HAPROXY" == "yes" ] +then + systemctl_if_exists enable gencert.service + + haproxy_version=$(dpkg -s haproxy | grep '^Version:' | awk '{print $2}') + if [[ $haproxy_version = 2.* ]]; then + mv /etc/haproxy/haproxy.2.x.cfg /etc/haproxy/haproxy.cfg + rm /etc/haproxy/haproxy.1.x.cfg + else + mv /etc/haproxy/haproxy.1.x.cfg /etc/haproxy/haproxy.cfg + rm /etc/haproxy/haproxy.2.x.cfg + fi +else + # let's remove the configs for system services we don't need + rm /etc/systemd/system/gencert.service + + # also we need to make OctoPrint bind to all interfaces because otherwise + # it will be unaccessible... + [ -f /etc/systemd/system/octoprint.service ] && sed -i "s@HOST=127.0.0.1@HOST=0.0.0.0@" /etc/systemd/system/octoprint.service +fi + +### CuraEngine + +if [ ! "$OCTOPI_INCLUDE_CURAENGINE" == "yes" ] +then + # unconfigure the cura engine path in octoprint's config.yaml + sudo -u "${BASE_USER}" sed -i -e "s@cura_engine: /usr/local/bin/cura_engine@cura_engine:@g" /home/"${BASE_USER}"/.octoprint/config.yaml +fi + +### Streamer select service. + +systemctl_if_exists enable streamer_select.service + +### mjpg_streamer + +if [ "$OCTOPI_INCLUDE_MJPGSTREAMER" == "yes" ] +then + systemctl_if_exists enable webcamd.service +### use legacy camera stack on bullseye for now + if grep "camera_auto_detect=1" /boot/config.txt + then + sed -i "s/camera_auto_detect=1/camera_auto_detect=0/g" /boot/config.txt + fi +else + rm /etc/logrotate.d/webcamd + rm /etc/systemd/system/webcamd.service + rm /root/bin/webcamd +fi + +### HLS streamer + +systemctl_if_exists enable ffmpeg_hls.service + +### Network monitoring + +systemctl_if_exists enable networkcheck.timer + +### Firmare flashing + +echo "--- Installing avrdude" +apt-get -y install avrdude + +### User-fixing +# Users can change their username easily via the Raspberry Pi imager, which breaks some of OctoPi's scripts +# we need to install virtualenv-tools3, so let's get pip and that +apt install -y python3-pip +sudo -u pi pip3 install --user virtualenv-tools3 + +systemctl_if_exists enable user-fix.service + + +#cleanup +apt-get clean +apt-get autoremove -y + +if [ -n "$OCTOPI_APTMIRROR" ]; +then + echo "Reverting /etc/apt/sources.list" + mv /etc/apt/sources.list.backup /etc/apt/sources.list +fi diff --git a/src/nightly_build_scripts/cleanup_storage.js b/src/nightly_build_scripts/cleanup_storage.js new file mode 100644 index 00000000..971be31a --- /dev/null +++ b/src/nightly_build_scripts/cleanup_storage.js @@ -0,0 +1,108 @@ +/** + * Usage: node cleanup_storage.js [] + * + * action: + * "print" or "delete" + * keyfile: + * The key.json file to use for authentication + * + * Setup: + * npm install pkgcloud + */ + +//~~ setup + +// imports + +var pkgcloud = require('pkgcloud'), + fs = require('fs'), + path = require('path'); + +// polyfills + +if (!String.prototype.startsWith) { + String.prototype.startsWith = function (str) { + return !this.indexOf(str); + } +} + +if (!String.prototype.endsWith) { + String.prototype.endsWith = function(searchString, position) { + var subjectString = this.toString(); + if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { + position = subjectString.length; + } + position -= searchString.length; + var lastIndex = subjectString.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; + }; +} + +//~~ argument parsing + +// "delete" -> delete, "print" -> only print +if (process.argv.length < 3) { + console.log("Missing mandatory action parameter"); + process.exit(); +} +var action = process.argv[2]; + +// key file to use => ./key.json or second command line argument +var keyfile = path.join(__dirname, 'key.json'); +if (process.argv.length >= 4) { + keyfile = process.argv[3]; +} + +//~~ helpers + +var sortByDate = function(a, b) { + if (a.timeCreated < b.timeCreated) return 1; + if (a.timeCreated > b.timeCreated) return -1; + return 0; +} + +//~~ action and go + +// construct client +var client = require('pkgcloud').storage.createClient({ + provider: 'google', + keyFilename: keyfile, // path to a JSON key file +}); +var container = "octoprint"; + +// fetch our files and render our page +var matchers = [ + { + matcher: function(obj) { return !obj.name.startsWith("stable/") && !obj.name.startsWith("bananapi-m1/") && /octopi-(wheezy|jessie)-/.test(obj.name); }, + limit: 14 + }, + { + matcher: function(obj) { return /^bananapi-m1\//.test(obj.name); }, + limit: 14 + } +] + +var now = new Date(); +client.getFiles(container, function (err, files) { + matchers.forEach(function(m) { + var cutoff = new Date(); + cutoff.setDate(now.getDate() - m.limit); + + var filesToDelete = files.filter(m.matcher) + .filter(function(obj) { return new Date(Date.parse(obj.timeCreated)) < cutoff }); + + filesToDelete.forEach(function (file) { + if (action == "delete") { + client.removeFile(container, encodeURIComponent(file.name), function(err) { + if (err) { + console.log("Error deleting " + file.name + ": " + err); + } else { + console.log("Deleted " + file.name + " on " + container); + } + }); + } else { + console.log("Would now delete " + file.name + " on " + container); + } + }); + }); +}); diff --git a/src/nightly_build_scripts/generate_nightly_page.js b/src/nightly_build_scripts/generate_nightly_page.js new file mode 100644 index 00000000..5d761ab8 --- /dev/null +++ b/src/nightly_build_scripts/generate_nightly_page.js @@ -0,0 +1,215 @@ +/** + * Usage: node generate_nightly_page.js [ [ []]] + * + * keyfile: + * The key.json file to use for authentication + * outputfile: + * The file where to write the output to + * templatefile: + * The HTML template to use, supports the following placeholders: + * - "{{ title }}" - will be replaced with page title + * - "{{ description }}" - will be replaced with page description + * - "{{ content }}" - will be replaced with page content + * + * Setup: + * npm install pkgcloud + * For NodeJS < 0.10 also + * npm install readable-stream + */ + +//~~ setup + +// imports + +var pkgcloud = require('pkgcloud'), + fs = require('fs'), + path = require('path'), + stream = require('stream'), + util = require('util'); + +// polyfills + +if (!String.prototype.startsWith) { + String.prototype.startsWith = function (str) { + return !this.indexOf(str); + } +} + +if (!String.prototype.endsWith) { + String.prototype.endsWith = function(searchString, position) { + var subjectString = this.toString(); + if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { + position = subjectString.length; + } + position -= searchString.length; + var lastIndex = subjectString.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; + }; +} + +//~~ argument parsing + +// key file to use => ./key.json or first command line argument +var keyfile = path.join(__dirname, 'key.json'); +if (process.argv.length >= 3) { + keyfile = process.argv[2]; +} + +// output file => ./index.html or second command line argument +var outputfile = path.join(__dirname, 'index.html'); +if (process.argv.length >= 4) { + outputfile = process.argv[3]; +} + +// template file ==> ./template.html or third command line argument +var templatefile = path.join(__dirname, 'template.html'); +if (process.argv.length >= 5) { + templatefile = process.argv[4]; +} + +//~~ helpers + +var filterByExtension = function(fileObjs, extensions) { + return fileObjs.filter(function (obj) { + var name = obj.name; + return extensions.some(function (extension) { return name.endsWith(extension); }) + }); +} + +var filterByName = function(fileObjs, name) { + return fileObjs.filter(function (obj) { return obj.name.startsWith(name) }); +} + +var filterNameByRegex = function(fileObjs, regex) { + return fileObjs.filter(function (obj) { return regex.test(obj.name) }); +} + +var stripLeading = function(name, toStrip) { + return name.substring(toStrip.length); +} + +var sortByDate = function(a, b) { + if (a.timeCreated < b.timeCreated) return 1; + if (a.timeCreated > b.timeCreated) return -1; + return 0; +} + +var formatDate = function(date) { + return date.replace(/T/, ' ').replace(/\..+/, '') + " UTC"; +} + +var formatSize = function(bytes) { + // Formats the given file size in bytes + if (!bytes) return "-"; + + var units = ["bytes", "KB", "MB"]; + for (var i = 0; i < units.length; i++) { + if (bytes < 1024) { + return bytes.toFixed(1) + units[i]; + } + bytes /= 1024; + } + return bytes.toFixed(1) + "GB"; +} + +var convertHash = function(hash) { + // Converts a hash from base64 to hex + return new Buffer(hash, 'base64').toString('hex'); +} + +var outputTable = function(fileObjs, s, nameProcessor, limit) { + // Outputs an HTML table to for the provided , limiting them to + // and preprocessing the filename with + + limit = limit || 20; + + s.write('\n'); + s.write('\n'); + + // sort by date and limit + fileObjs.sort(sortByDate).slice(0, limit).forEach(function(fileObj) { + console.log("Processing file object: %j", fileObj); + + var url = "https://storage.googleapis.com/octoprint/" + fileObj.name; + var name = nameProcessor(fileObj.name); + + s.write(''); + s.write('"); + s.write('"); + s.write(""); + s.write(""); + s.write("\n"); + }); + + s.write('
NameCreation DateSizeMD5 Hash
' + name + "' + formatDate(fileObj.timeCreated) + "" + formatSize(fileObj.size) + "" + convertHash(fileObj.md5Hash) + "
\n'); +} + +var outputPage = function(files, s) { + // Outputs the page for to stream , using the template. + var title = "OctoPi Downloads"; + var description = "OctoPi Downloads"; + + var Writable = stream.Writable || require('readable-stream').Writable; + function StringStream(options) { + Writable.call(this, options); + this.buffer = ""; + } + util.inherits(StringStream, Writable); + StringStream.prototype._write = function (chunk, enc, cb) { + this.buffer += chunk; + cb(); + }; + + var output = new StringStream(); + + output.write(""); + + output.write("

Raspberry Pi

\n"); + + output.write("

Stable Builds

\n") + outputTable(filterNameByRegex(files, /^stable\/.*octopi-(wheezy|jessie|stretch|buster)-.*/), + output, + function(name) { return stripLeading(name, "stable/") }, + 3); + + output.write("

Nightly Builds

\n"); + output.write("Warning: These builds are untested and can be unstable and/or broken. If in doubt use a stable build."); + outputTable(filterNameByRegex(files.filter(function (obj) { return !obj.name.startsWith("stable/") && !obj.name.startsWith("bananapi-m1/") }), /octopi-(wheezy|jessie|stretch|buster)-armhf/), + output, + function(name) { return name }, + 14); + + output.write("

64Bit Nightly Builds

\n") + + output.write("

Nightly Builds arm64

\n"); + output.write("Warning: These builds are untested and can be unstable and/or broken."); + outputTable(filterNameByRegex(files.filter(function (obj) { return !obj.name.startsWith("stable/") && !obj.name.startsWith("bananapi-m1/") }), /octopi-(wheezy|jessie|stretch|buster)-arm64/), + output, + function(name) { return name }, + 14); + + var content = output.buffer; + fs.readFile(templatefile, "utf8", function (err, template) { + var result = template.replace(/{{ content }}/g, content) + .replace(/{{ title }}/g, title) + .replace(/{{ description }}/g, description); + s.write(result); + }) + +} + +//~~ action and go + +// construct client +var client = require('pkgcloud').storage.createClient({ + provider: 'google', + keyFilename: keyfile, // path to a JSON key file +}); +var container = "octoprint"; + +// fetch our files and render our page +client.getFiles(container, function (err, files) { + var stream = fs.createWriteStream(outputfile); + outputPage(filterByExtension(files, [".zip"]), stream); +}); + diff --git a/src/nightly_build_scripts/template.html b/src/nightly_build_scripts/template.html new file mode 100644 index 00000000..9dabfbd8 --- /dev/null +++ b/src/nightly_build_scripts/template.html @@ -0,0 +1,76 @@ + + + + + + + + + {{ title }} + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+ {{ content }} +
+
+
+
+
+ + + + + diff --git a/src/nightly_build_scripts/update_git_mirrors b/src/nightly_build_scripts/update_git_mirrors new file mode 100755 index 00000000..03346a08 --- /dev/null +++ b/src/nightly_build_scripts/update_git_mirrors @@ -0,0 +1,12 @@ +#!/bin/bash +MIRROR_LOCATION=/var/www/git +mkdir $MIRROR_LOCATION +pushd MIRROR_LOCATION + for repo in `ls` + do + pushd $repo + git fetch --prune + git update-server-info + popd + done +popd diff --git a/src/octopi b/src/octopi deleted file mode 100755 index 4bf3f41f..00000000 --- a/src/octopi +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash -# OctoPi generation script -# This script takes a Raspbian image and adds to it octoprint and verions addons -# Written by Guy Sheffer -# GPL V3 -mkdir -p $OCTOPI_WORKSPACE -mkdir -p $MOUNT_PATH - -pushd $OCTOPI_WORKSPACE - rm *.img - unzip $ZIP_IMG - IMG_PATH=`ls | grep .img` - - # mount root and boot partition - sudo mount -o loop,offset=$((512*122880)) $IMG_PATH $MOUNT_PATH - sudo mount -o loop,offset=$((512*8192)) $IMG_PATH $MOUNT_PATH/boot - - #Edit pi filesystem - pushd $MOUNT_PATH - - #make QEMU boot (remember to return) - #sed -i 's@include /etc/ld.so.conf.d/\*.conf@\#include /etc/ld.so.conf.d/\*.conf@' etc/ld.so.conf - - #move OctoPi filesystem files - cp -av $SCRIPT_PATH/filesystem . - - #black magic of qemu-arm-static - cp `which qemu-arm-static` usr/bin - cp $CHROOT_SCRIPT_PATH chroot_script - chmod 755 chroot_script - - chroot . usr/bin/qemu-arm-static /bin/bash /chroot_script - - #cleanup - rm chroot_script - rm -rfv filesystem - popd - - # unmount first boot, then root partition - sudo umount $MOUNT_PATH/boot - sudo umount $MOUNT_PATH - chmod 777 $IMG_PATH -popd - diff --git a/src/release b/src/release deleted file mode 100755 index 611e0794..00000000 --- a/src/release +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -pushd workspace - -FILENAME=$(basename `ls . | grep .img | tail -n 1` .img) -OCTOPI_FILENAME=$(echo $FILENAME-`cat ../filesystem/root/etc/octopi_version` | sed 's/raspbian/octopi/') -mv ${FILENAME}.img $OCTOPI_FILENAME.img -zip $OCTOPI_FILENAME.zip $OCTOPI_FILENAME.img - -popd diff --git a/src/vagrant/Vagrantfile b/src/vagrant/Vagrantfile new file mode 100644 index 00000000..a5b90944 --- /dev/null +++ b/src/vagrant/Vagrantfile @@ -0,0 +1,17 @@ +vagrant_root = File.dirname(__FILE__) +Vagrant.configure("2") do |o| + # o.vm.box = "octopi-build" + o.vm.box= "debian/buster64" + o.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'" + o.vm.synced_folder File.read("../custompios_path").gsub("\n",""), "/CustomPiOS", create:true, type: "nfs" + o.vm.synced_folder "../", "/distro", create:true, type: "nfs" + o.vm.network :private_network, ip: "192.168.55.55" + o.vm.provision :shell, :path => "setup.sh", args: ENV['SHELL_ARGS'] + + #o.vbguest.auto_update = false + + o.vm.provider "virtualbox" do |v| + v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] + v.customize ["modifyvm", :id, "--natdnsproxy1", "on"] + end +end diff --git a/src/vagrant/run_vagrant_build.sh b/src/vagrant/run_vagrant_build.sh new file mode 100755 index 00000000..1ef3189b --- /dev/null +++ b/src/vagrant/run_vagrant_build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +sudo vagrant ssh -- -t "sudo /CustomPiOS/nightly_build_scripts/custompios_nightly_build $@" + diff --git a/src/vagrant/setup.sh b/src/vagrant/setup.sh new file mode 100644 index 00000000..71a32b03 --- /dev/null +++ b/src/vagrant/setup.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +sudo apt-get update +sudo apt-get install -y gawk util-linux realpath git qemu-user-static p7zip-full unzip zip + diff --git a/src/variants/rpios_arm64/config b/src/variants/rpios_arm64/config new file mode 100755 index 00000000..36278105 --- /dev/null +++ b/src/variants/rpios_arm64/config @@ -0,0 +1,8 @@ +export BASE_ARCH=aarch64 +export BASE_DISTRO=raspios64 +export BASE_IMAGE_PATH=${DIST_PATH}/image-rpios_arm64 +# export BASE_ZIP_IMG=`ls -t $BASE_IMAGE_PATH/*-{ubuntu}-*-arm64-*.xz | head -n 1` +export BASE_IGNORE_VARIANT_NAME=yes +export BASE_USER=pi +export BASE_USER_PASSWORD=raspberry +export RPI_IMAGER_NAME="${DIST_NAME} version ${DIST_VERSION} 64-bit" diff --git a/src/variants/rpios_arm64/filesystem/root/etc/haproxy/haproxy.cfg b/src/variants/rpios_arm64/filesystem/root/etc/haproxy/haproxy.cfg new file mode 100644 index 00000000..8ef4d164 --- /dev/null +++ b/src/variants/rpios_arm64/filesystem/root/etc/haproxy/haproxy.cfg @@ -0,0 +1,49 @@ +global + maxconn 4096 + user haproxy + group haproxy + log /dev/log local1 debug + tune.ssl.default-dh-param 2048 + +defaults + log global + mode http + compression algo gzip + option httplog + option dontlognull + retries 3 + option redispatch + option http-server-close + option forwardfor + maxconn 2000 + timeout connect 5s + timeout client 15min + timeout server 15min + +frontend public + bind :::80 v4v6 + bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem + option forwardfor except 127.0.0.1 + use_backend webcam if { path_beg /webcam/ } + use_backend webcam_hls if { path_beg /hls/ } + use_backend webcam_hls if { path_beg /jpeg/ } + default_backend octoprint + +backend octoprint + acl needs_scheme req.hdr_cnt(X-Scheme) eq 0 + + http-request replace-path ^([^\ :]*)\ /(.*) \1\ /\2 + http-request add-header X-Scheme https if needs_scheme { ssl_fc } + http-request add-header X-Scheme http if needs_scheme !{ ssl_fc } + option forwardfor + server octoprint1 127.0.0.1:5000 + errorfile 503 /etc/haproxy/errors/503-no-octoprint.http + +backend webcam + http-request replace-path /webcam/(.*) /\1 + server webcam1 127.0.0.1:8080 + errorfile 503 /etc/haproxy/errors/503-no-webcam.http + +backend webcam_hls + server webcam_hls_1 127.0.0.1:28126 + errorfile 503 /etc/haproxy/errors/503-no-webcam-hls.http diff --git a/src/variants/rpios_arm64/filesystem/root/etc/systemd/system/webcamd.service b/src/variants/rpios_arm64/filesystem/root/etc/systemd/system/webcamd.service new file mode 100644 index 00000000..5154d6e8 --- /dev/null +++ b/src/variants/rpios_arm64/filesystem/root/etc/systemd/system/webcamd.service @@ -0,0 +1,15 @@ +[Unit] +Description=the OctoPi webcam daemon with the user specified config +# ConditionPathExists=/etc/octopi_streamer/mjpeg + +[Service] +WorkingDirectory=/root/bin +StandardOutput=append:/var/log/webcamd.log +StandardError=append:/var/log/webcamd.log +ExecStart=/root/bin/webcamd +Restart=always +Type=simple +RestartSec=1 + +[Install] +WantedBy=multi-user.target diff --git a/src/variants/rpios_arm64/post_chroot_script b/src/variants/rpios_arm64/post_chroot_script new file mode 100644 index 00000000..918c8bc9 --- /dev/null +++ b/src/variants/rpios_arm64/post_chroot_script @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -x +set -e + +export LC_ALL=C + +source /common.sh +install_cleanup_trap + +# Unpack the filesystem changes for the variant +unpack /filesystem/root / + +# add-apt-repository ppa:ubuntu-raspi2/ppa -y +apt-get update +apt-get -y --force-yes install libraspberrypi-bin rpi.gpio-common +apt-get clean +apt-get autoremove -y diff --git a/src/variants/ubuntu_arm64/config b/src/variants/ubuntu_arm64/config new file mode 100755 index 00000000..1f54aa96 --- /dev/null +++ b/src/variants/ubuntu_arm64/config @@ -0,0 +1,10 @@ +export BASE_ARCH=aarch64 +export BASE_DISTRO=ubuntu + +export BASE_IMAGE_PATH=${DIST_PATH}/image-ubuntu_arm64 +export BASE_ZIP_IMG=`ls -t $BASE_IMAGE_PATH/*-{ubuntu}-*-arm64-*.xz | head -n 1` +export BASE_IGNORE_VARIANT_NAME=yes +export BASE_USER=pi +export BASE_USER_PASSWORD=raspberry +export RPI_IMAGER_NAME="${DIST_NAME} version ${DIST_VERSION} 64bit" + diff --git a/src/variants/ubuntu_arm64/filesystem/root/etc/haproxy/haproxy.cfg b/src/variants/ubuntu_arm64/filesystem/root/etc/haproxy/haproxy.cfg new file mode 100644 index 00000000..8ef4d164 --- /dev/null +++ b/src/variants/ubuntu_arm64/filesystem/root/etc/haproxy/haproxy.cfg @@ -0,0 +1,49 @@ +global + maxconn 4096 + user haproxy + group haproxy + log /dev/log local1 debug + tune.ssl.default-dh-param 2048 + +defaults + log global + mode http + compression algo gzip + option httplog + option dontlognull + retries 3 + option redispatch + option http-server-close + option forwardfor + maxconn 2000 + timeout connect 5s + timeout client 15min + timeout server 15min + +frontend public + bind :::80 v4v6 + bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem + option forwardfor except 127.0.0.1 + use_backend webcam if { path_beg /webcam/ } + use_backend webcam_hls if { path_beg /hls/ } + use_backend webcam_hls if { path_beg /jpeg/ } + default_backend octoprint + +backend octoprint + acl needs_scheme req.hdr_cnt(X-Scheme) eq 0 + + http-request replace-path ^([^\ :]*)\ /(.*) \1\ /\2 + http-request add-header X-Scheme https if needs_scheme { ssl_fc } + http-request add-header X-Scheme http if needs_scheme !{ ssl_fc } + option forwardfor + server octoprint1 127.0.0.1:5000 + errorfile 503 /etc/haproxy/errors/503-no-octoprint.http + +backend webcam + http-request replace-path /webcam/(.*) /\1 + server webcam1 127.0.0.1:8080 + errorfile 503 /etc/haproxy/errors/503-no-webcam.http + +backend webcam_hls + server webcam_hls_1 127.0.0.1:28126 + errorfile 503 /etc/haproxy/errors/503-no-webcam-hls.http diff --git a/src/variants/ubuntu_arm64/filesystem/root/etc/systemd/system/webcamd.service b/src/variants/ubuntu_arm64/filesystem/root/etc/systemd/system/webcamd.service new file mode 100644 index 00000000..5154d6e8 --- /dev/null +++ b/src/variants/ubuntu_arm64/filesystem/root/etc/systemd/system/webcamd.service @@ -0,0 +1,15 @@ +[Unit] +Description=the OctoPi webcam daemon with the user specified config +# ConditionPathExists=/etc/octopi_streamer/mjpeg + +[Service] +WorkingDirectory=/root/bin +StandardOutput=append:/var/log/webcamd.log +StandardError=append:/var/log/webcamd.log +ExecStart=/root/bin/webcamd +Restart=always +Type=simple +RestartSec=1 + +[Install] +WantedBy=multi-user.target diff --git a/src/variants/ubuntu_arm64/post_chroot_script b/src/variants/ubuntu_arm64/post_chroot_script new file mode 100644 index 00000000..918c8bc9 --- /dev/null +++ b/src/variants/ubuntu_arm64/post_chroot_script @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -x +set -e + +export LC_ALL=C + +source /common.sh +install_cleanup_trap + +# Unpack the filesystem changes for the variant +unpack /filesystem/root / + +# add-apt-repository ppa:ubuntu-raspi2/ppa -y +apt-get update +apt-get -y --force-yes install libraspberrypi-bin rpi.gpio-common +apt-get clean +apt-get autoremove -y