├── .github
└── workflows
│ ├── builder.yml
│ └── index.yml
├── .gitignore
├── .vagrant.yml
├── LICENSE
├── README.md
├── Vagrantfile
├── autorunonce
├── builder
├── clean.sh
├── examples
├── moodole_autorunonce
├── netdata_autorunonce
├── pihole_autorunonce
├── planet_RTC_autorunonce
├── planet_autorunonce
└── remote_autorunonce
├── keys
├── 0EBFCD88.key
├── 68576280.key
├── 8B57C5C2836F4BEB.key
└── C99B11DEB97541F0.key
├── lib.sh
└── scripts.d
├── 00_disable_autoresize.sh
├── 00_utc.sh
├── 05_add_keys.sh
├── 05_add_repos.sh
├── 05_better_mirrors.sh
├── 10_pkg_purge.sh
├── 15_pkg_upgrade.sh
├── 16_pkg_install.sh
├── 17_default_mirrors.sh
├── 18_loginmsg.sh
├── 20_balena.sh
├── 20_enable_ssh.sh
├── 20_fix_node.sh
├── 20_install_autorun.sh
├── 20_install_balena_socket.sh
├── 20_install_bluetooth.sh
├── 20_install_do_autorun.sh
├── 20_install_rclocal.sh
├── 20_tiv.sh
├── 20_vim.sh
├── 30_bluetooth.sh
├── 30_docker.sh
├── 30_enable_uart.sh
├── 30_examples_scripts.sh
├── 30_g_ether.sh
├── 30_npminstall.sh
├── 30_opencv_install.sh
├── 30_ssh_keys.py
├── 30_version_txt.sh
├── 31_install_ssh_configs.sh
├── 32_sl.sh
├── 32_terraform.sh
├── 33_usb.sh
├── 34_youtube-dl.sh
├── 35_disable_uptimed.sh
├── 36_log2ram.sh
├── 40_planet.sh
└── 50_rm_files.sh
/.github/workflows/builder.yml:
--------------------------------------------------------------------------------
1 | name: builder
2 |
3 | on:
4 | push:
5 | release:
6 | types: [created]
7 |
8 | jobs:
9 | build-image:
10 | strategy:
11 | fail-fast: false
12 | matrix:
13 | arch: [armhf, arm64]
14 | # arch: [armhf]
15 | # arch: [arm64]
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: checkout
19 | uses: actions/checkout@v2
20 | - name: build
21 | run: |
22 | sudo apt-get update
23 | sudo apt install qemu-user-static g++-arm-linux-gnueabihf g++-aarch64-linux-gnu kpartx aria2 tree s3fs
24 | sudo pip install requests
25 | mkdir images && sudo APIKEY=${{ secrets.GITHUBAPITOKEN }} USERNAME=${{ secrets.GITHUBUSERNAME }} PATH=./node_modules/.bin:$PATH ./builder --noninteractive ${{ matrix.arch }}
26 | - name: release
27 | run: |
28 | image=$(find images/*.img | head -1)
29 | [[ -n "$image" ]] || exit 1
30 | release=$(git tag --points-at HEAD | tail -n2 2>/dev/null | sed -e 's/^release-//')
31 | [[ -z "$release" ]] && echo "Build Successful; no release" >&2 && exit 0
32 | echo "RELEASE=$release" >> $GITHUB_ENV
33 | echo "IMAGE=$image" >> $GITHUB_ENV
34 | - name: sshagent
35 | uses: webfactory/ssh-agent@v0.5.2
36 | with:
37 | ssh-private-key: ${{ secrets.SSHKEY }}
38 | - name: deploy
39 | if: ${{ env.RELEASE }}
40 | run: |
41 | sudo npm install -g @treehouses/cli
42 | export gitter_channel="${{ secrets.CHANNEL }}"
43 | image=${{ env.IMAGE }}
44 | release=${{ env.RELEASE }}
45 | release_is_number() { echo "$release" | grep -Eqx "[0-9]+" ; }
46 | architecture=${{ matrix.arch }}
47 | name="treehouse-$release-$architecture"
48 | if [ "$architecture" == armhf ]; then
49 | name="treehouse-$release"
50 | fi
51 | image_gz="$name.img.gz"
52 | image_sha1=$image_gz.sha1
53 | image_dir="experiment/"
54 | if release_is_number; then
55 | image_dir=""
56 | fi
57 | echo "compressing ..."
58 | gzip -c -9 < "$image" > "$image_gz"
59 | sync
60 | echo "hashing ..."
61 | sha1sum "$image_gz" > "$image_sha1"
62 | sync
63 | echo "${{ secrets.AWSACCESSKEYID }}:${{ secrets.AWSACCESSKEYSECRET }}" > .passwd-s3fs
64 | chmod 600 .passwd-s3fs
65 | sudo rm -rf /var/www/html
66 | sudo mkdir -p /var/www/html
67 | sudo chmod 666 /var/www/html
68 | echo "uploading ..."
69 | sudo s3fs treehouses /var/www/html -o passwd_file=./.passwd-s3fs -o allow_other
70 | sudo cp "$image_gz" "$image_sha1" "/var/www/html/$image_dir"
71 | echo "treehouses image http://download.treehouses.io/$image_dir$image_gz"
72 | treehouses feedback "treehouses image http://download.treehouses.io/$image_dir$image_gz"
73 | mkdir -p ~/.ssh
74 | chmod 700 ~/.ssh
75 | echo "download.ole.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK6diybdi0R/Iptq9qGSP/ZU5zaJ8XrfGSuGvmsVFGKdQAPJsS4GhRm4cq8ucAYoatz9gx/mgJBWgPV6JPbkxiU=" > ~/.ssh/known_hosts
76 | echo "backuping ..."
77 | rsync -Pav "$image_gz" "$image_sha1" deploy@download.ole.org:/data/images/
78 | if release_is_number; then
79 | echo "Marking release as latest image"
80 | ssh deploy@download.ole.org sh -c ":; cd /data/images; ln -sf $name.img.gz latest.img.gz; ln -sf $name.img.gz.sha1 latest.img.gz.sha1"
81 | fi
82 | echo "Download url: http://download.treehouses.io/$image_dir$image_gz"
83 | - name: apache index
84 | if: ${{ env.RELEASE }}
85 | run: |
86 | sudo mv /var/www/html/index.html index.html.old
87 | sudo sync
88 | sudo systemctl start apache2
89 | sudo curl http://localhost -o index.html
90 | sudo mv index.html.old /var/www/html/.
91 | sudo sync
92 | sudo mv ./index.html /var/www/html
93 | sudo rm /var/www/html/index.html.old
94 | - name: new index.html
95 | if: ${{ env.RELEASE }}
96 | uses: chetan/invalidate-cloudfront-action@master
97 | env:
98 | DISTRIBUTION: ${{ secrets.AWSDISTRIBUTIONID }}
99 | PATHS: '/index.html'
100 | AWS_REGION: 'us-east-1'
101 | AWS_ACCESS_KEY_ID: ${{ secrets.AWSACCESSKEYID }}
102 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWSACCESSKEYSECRET }}
103 |
--------------------------------------------------------------------------------
/.github/workflows/index.yml:
--------------------------------------------------------------------------------
1 | name: indexer
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | jobs:
7 | indexer:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: install
11 | run: |
12 | sudo apt-get update
13 | sudo apt install s3fs
14 | - name: mount
15 | run: |
16 | echo "${{ secrets.AWSACCESSKEYID }}:${{ secrets.AWSACCESSKEYSECRET }}" > .passwd-s3fs
17 | chmod 600 .passwd-s3fs
18 | sudo rm -rf /var/www/html
19 | sudo mkdir -p /var/www/html
20 | sudo chmod 666 /var/www/html
21 | sudo s3fs treehouses /var/www/html -o passwd_file=./.passwd-s3fs -o allow_other
22 | - name: apache index
23 | run: |
24 | sudo mv /var/www/html/index.html index.html.old
25 | sudo sync
26 | sudo systemctl start apache2
27 | sudo curl http://localhost -o index.html
28 | sudo mv index.html.old /var/www/html/.
29 | sudo sync
30 | sudo mv ./index.html /var/www/html
31 | sudo rm /var/www/html/index.html.old
32 | - name: new index.html
33 | uses: chetan/invalidate-cloudfront-action@master
34 | env:
35 | DISTRIBUTION: ${{ secrets.AWSDISTRIBUTIONID }}
36 | PATHS: '/index.html'
37 | AWS_REGION: 'us-east-1'
38 | AWS_ACCESS_KEY_ID: ${{ secrets.AWSACCESSKEYID }}
39 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWSACCESSKEYSECRET }}
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | apt_cache/
2 | authorized_keys
3 | download/
4 | images/
5 | ip/
6 | mnt/
7 | temp/
8 | .vagrant/
9 | .*.sw[nop]/
10 | .vagrant.yml
--------------------------------------------------------------------------------
/.vagrant.yml:
--------------------------------------------------------------------------------
1 | #github api key
2 | #read org access
3 | #GITHUB_KEY: example_key
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU AFFERO GENERAL PUBLIC LICENSE
2 | Version 3, 19 November 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU Affero General Public License is a free, copyleft license for
11 | software and other kinds of works, specifically designed to ensure
12 | cooperation with the community in the case of network server software.
13 |
14 | The licenses for most software and other practical works are designed
15 | to take away your freedom to share and change the works. By contrast,
16 | our General Public Licenses are intended to guarantee your freedom to
17 | share and change all versions of a program--to make sure it remains free
18 | software for all its users.
19 |
20 | When we speak of free software, we are referring to freedom, not
21 | price. Our General Public Licenses are designed to make sure that you
22 | have the freedom to distribute copies of free software (and charge for
23 | them if you wish), that you receive source code or can get it if you
24 | want it, that you can change the software or use pieces of it in new
25 | free programs, and that you know you can do these things.
26 |
27 | Developers that use our General Public Licenses protect your rights
28 | with two steps: (1) assert copyright on the software, and (2) offer
29 | you this License which gives you legal permission to copy, distribute
30 | and/or modify the software.
31 |
32 | A secondary benefit of defending all users' freedom is that
33 | improvements made in alternate versions of the program, if they
34 | receive widespread use, become available for other developers to
35 | incorporate. Many developers of free software are heartened and
36 | encouraged by the resulting cooperation. However, in the case of
37 | software used on network servers, this result may fail to come about.
38 | The GNU General Public License permits making a modified version and
39 | letting the public access it on a server without ever releasing its
40 | source code to the public.
41 |
42 | The GNU Affero General Public License is designed specifically to
43 | ensure that, in such cases, the modified source code becomes available
44 | to the community. It requires the operator of a network server to
45 | provide the source code of the modified version running there to the
46 | users of that server. Therefore, public use of a modified version, on
47 | a publicly accessible server, gives the public access to the source
48 | code of the modified version.
49 |
50 | An older license, called the Affero General Public License and
51 | published by Affero, was designed to accomplish similar goals. This is
52 | a different license, not a version of the Affero GPL, but Affero has
53 | released a new version of the Affero GPL which permits relicensing under
54 | this license.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | TERMS AND CONDITIONS
60 |
61 | 0. Definitions.
62 |
63 | "This License" refers to version 3 of the GNU Affero General Public License.
64 |
65 | "Copyright" also means copyright-like laws that apply to other kinds of
66 | works, such as semiconductor masks.
67 |
68 | "The Program" refers to any copyrightable work licensed under this
69 | License. Each licensee is addressed as "you". "Licensees" and
70 | "recipients" may be individuals or organizations.
71 |
72 | To "modify" a work means to copy from or adapt all or part of the work
73 | in a fashion requiring copyright permission, other than the making of an
74 | exact copy. The resulting work is called a "modified version" of the
75 | earlier work or a work "based on" the earlier work.
76 |
77 | A "covered work" means either the unmodified Program or a work based
78 | on the Program.
79 |
80 | To "propagate" a work means to do anything with it that, without
81 | permission, would make you directly or secondarily liable for
82 | infringement under applicable copyright law, except executing it on a
83 | computer or modifying a private copy. Propagation includes copying,
84 | distribution (with or without modification), making available to the
85 | public, and in some countries other activities as well.
86 |
87 | To "convey" a work means any kind of propagation that enables other
88 | parties to make or receive copies. Mere interaction with a user through
89 | a computer network, with no transfer of a copy, is not conveying.
90 |
91 | An interactive user interface displays "Appropriate Legal Notices"
92 | to the extent that it includes a convenient and prominently visible
93 | feature that (1) displays an appropriate copyright notice, and (2)
94 | tells the user that there is no warranty for the work (except to the
95 | extent that warranties are provided), that licensees may convey the
96 | work under this License, and how to view a copy of this License. If
97 | the interface presents a list of user commands or options, such as a
98 | menu, a prominent item in the list meets this criterion.
99 |
100 | 1. Source Code.
101 |
102 | The "source code" for a work means the preferred form of the work
103 | for making modifications to it. "Object code" means any non-source
104 | form of a work.
105 |
106 | A "Standard Interface" means an interface that either is an official
107 | standard defined by a recognized standards body, or, in the case of
108 | interfaces specified for a particular programming language, one that
109 | is widely used among developers working in that language.
110 |
111 | The "System Libraries" of an executable work include anything, other
112 | than the work as a whole, that (a) is included in the normal form of
113 | packaging a Major Component, but which is not part of that Major
114 | Component, and (b) serves only to enable use of the work with that
115 | Major Component, or to implement a Standard Interface for which an
116 | implementation is available to the public in source code form. A
117 | "Major Component", in this context, means a major essential component
118 | (kernel, window system, and so on) of the specific operating system
119 | (if any) on which the executable work runs, or a compiler used to
120 | produce the work, or an object code interpreter used to run it.
121 |
122 | The "Corresponding Source" for a work in object code form means all
123 | the source code needed to generate, install, and (for an executable
124 | work) run the object code and to modify the work, including scripts to
125 | control those activities. However, it does not include the work's
126 | System Libraries, or general-purpose tools or generally available free
127 | programs which are used unmodified in performing those activities but
128 | which are not part of the work. For example, Corresponding Source
129 | includes interface definition files associated with source files for
130 | the work, and the source code for shared libraries and dynamically
131 | linked subprograms that the work is specifically designed to require,
132 | such as by intimate data communication or control flow between those
133 | subprograms and other parts of the work.
134 |
135 | The Corresponding Source need not include anything that users
136 | can regenerate automatically from other parts of the Corresponding
137 | Source.
138 |
139 | The Corresponding Source for a work in source code form is that
140 | same work.
141 |
142 | 2. Basic Permissions.
143 |
144 | All rights granted under this License are granted for the term of
145 | copyright on the Program, and are irrevocable provided the stated
146 | conditions are met. This License explicitly affirms your unlimited
147 | permission to run the unmodified Program. The output from running a
148 | covered work is covered by this License only if the output, given its
149 | content, constitutes a covered work. This License acknowledges your
150 | rights of fair use or other equivalent, as provided by copyright law.
151 |
152 | You may make, run and propagate covered works that you do not
153 | convey, without conditions so long as your license otherwise remains
154 | in force. You may convey covered works to others for the sole purpose
155 | of having them make modifications exclusively for you, or provide you
156 | with facilities for running those works, provided that you comply with
157 | the terms of this License in conveying all material for which you do
158 | not control copyright. Those thus making or running the covered works
159 | for you must do so exclusively on your behalf, under your direction
160 | and control, on terms that prohibit them from making any copies of
161 | your copyrighted material outside their relationship with you.
162 |
163 | Conveying under any other circumstances is permitted solely under
164 | the conditions stated below. Sublicensing is not allowed; section 10
165 | makes it unnecessary.
166 |
167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168 |
169 | No covered work shall be deemed part of an effective technological
170 | measure under any applicable law fulfilling obligations under article
171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172 | similar laws prohibiting or restricting circumvention of such
173 | measures.
174 |
175 | When you convey a covered work, you waive any legal power to forbid
176 | circumvention of technological measures to the extent such circumvention
177 | is effected by exercising rights under this License with respect to
178 | the covered work, and you disclaim any intention to limit operation or
179 | modification of the work as a means of enforcing, against the work's
180 | users, your or third parties' legal rights to forbid circumvention of
181 | technological measures.
182 |
183 | 4. Conveying Verbatim Copies.
184 |
185 | You may convey verbatim copies of the Program's source code as you
186 | receive it, in any medium, provided that you conspicuously and
187 | appropriately publish on each copy an appropriate copyright notice;
188 | keep intact all notices stating that this License and any
189 | non-permissive terms added in accord with section 7 apply to the code;
190 | keep intact all notices of the absence of any warranty; and give all
191 | recipients a copy of this License along with the Program.
192 |
193 | You may charge any price or no price for each copy that you convey,
194 | and you may offer support or warranty protection for a fee.
195 |
196 | 5. Conveying Modified Source Versions.
197 |
198 | You may convey a work based on the Program, or the modifications to
199 | produce it from the Program, in the form of source code under the
200 | terms of section 4, provided that you also meet all of these conditions:
201 |
202 | a) The work must carry prominent notices stating that you modified
203 | it, and giving a relevant date.
204 |
205 | b) The work must carry prominent notices stating that it is
206 | released under this License and any conditions added under section
207 | 7. This requirement modifies the requirement in section 4 to
208 | "keep intact all notices".
209 |
210 | c) You must license the entire work, as a whole, under this
211 | License to anyone who comes into possession of a copy. This
212 | License will therefore apply, along with any applicable section 7
213 | additional terms, to the whole of the work, and all its parts,
214 | regardless of how they are packaged. This License gives no
215 | permission to license the work in any other way, but it does not
216 | invalidate such permission if you have separately received it.
217 |
218 | d) If the work has interactive user interfaces, each must display
219 | Appropriate Legal Notices; however, if the Program has interactive
220 | interfaces that do not display Appropriate Legal Notices, your
221 | work need not make them do so.
222 |
223 | A compilation of a covered work with other separate and independent
224 | works, which are not by their nature extensions of the covered work,
225 | and which are not combined with it such as to form a larger program,
226 | in or on a volume of a storage or distribution medium, is called an
227 | "aggregate" if the compilation and its resulting copyright are not
228 | used to limit the access or legal rights of the compilation's users
229 | beyond what the individual works permit. Inclusion of a covered work
230 | in an aggregate does not cause this License to apply to the other
231 | parts of the aggregate.
232 |
233 | 6. Conveying Non-Source Forms.
234 |
235 | You may convey a covered work in object code form under the terms
236 | of sections 4 and 5, provided that you also convey the
237 | machine-readable Corresponding Source under the terms of this License,
238 | in one of these ways:
239 |
240 | a) Convey the object code in, or embodied in, a physical product
241 | (including a physical distribution medium), accompanied by the
242 | Corresponding Source fixed on a durable physical medium
243 | customarily used for software interchange.
244 |
245 | b) Convey the object code in, or embodied in, a physical product
246 | (including a physical distribution medium), accompanied by a
247 | written offer, valid for at least three years and valid for as
248 | long as you offer spare parts or customer support for that product
249 | model, to give anyone who possesses the object code either (1) a
250 | copy of the Corresponding Source for all the software in the
251 | product that is covered by this License, on a durable physical
252 | medium customarily used for software interchange, for a price no
253 | more than your reasonable cost of physically performing this
254 | conveying of source, or (2) access to copy the
255 | Corresponding Source from a network server at no charge.
256 |
257 | c) Convey individual copies of the object code with a copy of the
258 | written offer to provide the Corresponding Source. This
259 | alternative is allowed only occasionally and noncommercially, and
260 | only if you received the object code with such an offer, in accord
261 | with subsection 6b.
262 |
263 | d) Convey the object code by offering access from a designated
264 | place (gratis or for a charge), and offer equivalent access to the
265 | Corresponding Source in the same way through the same place at no
266 | further charge. You need not require recipients to copy the
267 | Corresponding Source along with the object code. If the place to
268 | copy the object code is a network server, the Corresponding Source
269 | may be on a different server (operated by you or a third party)
270 | that supports equivalent copying facilities, provided you maintain
271 | clear directions next to the object code saying where to find the
272 | Corresponding Source. Regardless of what server hosts the
273 | Corresponding Source, you remain obligated to ensure that it is
274 | available for as long as needed to satisfy these requirements.
275 |
276 | e) Convey the object code using peer-to-peer transmission, provided
277 | you inform other peers where the object code and Corresponding
278 | Source of the work are being offered to the general public at no
279 | charge under subsection 6d.
280 |
281 | A separable portion of the object code, whose source code is excluded
282 | from the Corresponding Source as a System Library, need not be
283 | included in conveying the object code work.
284 |
285 | A "User Product" is either (1) a "consumer product", which means any
286 | tangible personal property which is normally used for personal, family,
287 | or household purposes, or (2) anything designed or sold for incorporation
288 | into a dwelling. In determining whether a product is a consumer product,
289 | doubtful cases shall be resolved in favor of coverage. For a particular
290 | product received by a particular user, "normally used" refers to a
291 | typical or common use of that class of product, regardless of the status
292 | of the particular user or of the way in which the particular user
293 | actually uses, or expects or is expected to use, the product. A product
294 | is a consumer product regardless of whether the product has substantial
295 | commercial, industrial or non-consumer uses, unless such uses represent
296 | the only significant mode of use of the product.
297 |
298 | "Installation Information" for a User Product means any methods,
299 | procedures, authorization keys, or other information required to install
300 | and execute modified versions of a covered work in that User Product from
301 | a modified version of its Corresponding Source. The information must
302 | suffice to ensure that the continued functioning of the modified object
303 | code is in no case prevented or interfered with solely because
304 | modification has been made.
305 |
306 | If you convey an object code work under this section in, or with, or
307 | specifically for use in, a User Product, and the conveying occurs as
308 | part of a transaction in which the right of possession and use of the
309 | User Product is transferred to the recipient in perpetuity or for a
310 | fixed term (regardless of how the transaction is characterized), the
311 | Corresponding Source conveyed under this section must be accompanied
312 | by the Installation Information. But this requirement does not apply
313 | if neither you nor any third party retains the ability to install
314 | modified object code on the User Product (for example, the work has
315 | been installed in ROM).
316 |
317 | The requirement to provide Installation Information does not include a
318 | requirement to continue to provide support service, warranty, or updates
319 | for a work that has been modified or installed by the recipient, or for
320 | the User Product in which it has been modified or installed. Access to a
321 | network may be denied when the modification itself materially and
322 | adversely affects the operation of the network or violates the rules and
323 | protocols for communication across the network.
324 |
325 | Corresponding Source conveyed, and Installation Information provided,
326 | in accord with this section must be in a format that is publicly
327 | documented (and with an implementation available to the public in
328 | source code form), and must require no special password or key for
329 | unpacking, reading or copying.
330 |
331 | 7. Additional Terms.
332 |
333 | "Additional permissions" are terms that supplement the terms of this
334 | License by making exceptions from one or more of its conditions.
335 | Additional permissions that are applicable to the entire Program shall
336 | be treated as though they were included in this License, to the extent
337 | that they are valid under applicable law. If additional permissions
338 | apply only to part of the Program, that part may be used separately
339 | under those permissions, but the entire Program remains governed by
340 | this License without regard to the additional permissions.
341 |
342 | When you convey a copy of a covered work, you may at your option
343 | remove any additional permissions from that copy, or from any part of
344 | it. (Additional permissions may be written to require their own
345 | removal in certain cases when you modify the work.) You may place
346 | additional permissions on material, added by you to a covered work,
347 | for which you have or can give appropriate copyright permission.
348 |
349 | Notwithstanding any other provision of this License, for material you
350 | add to a covered work, you may (if authorized by the copyright holders of
351 | that material) supplement the terms of this License with terms:
352 |
353 | a) Disclaiming warranty or limiting liability differently from the
354 | terms of sections 15 and 16 of this License; or
355 |
356 | b) Requiring preservation of specified reasonable legal notices or
357 | author attributions in that material or in the Appropriate Legal
358 | Notices displayed by works containing it; or
359 |
360 | c) Prohibiting misrepresentation of the origin of that material, or
361 | requiring that modified versions of such material be marked in
362 | reasonable ways as different from the original version; or
363 |
364 | d) Limiting the use for publicity purposes of names of licensors or
365 | authors of the material; or
366 |
367 | e) Declining to grant rights under trademark law for use of some
368 | trade names, trademarks, or service marks; or
369 |
370 | f) Requiring indemnification of licensors and authors of that
371 | material by anyone who conveys the material (or modified versions of
372 | it) with contractual assumptions of liability to the recipient, for
373 | any liability that these contractual assumptions directly impose on
374 | those licensors and authors.
375 |
376 | All other non-permissive additional terms are considered "further
377 | restrictions" within the meaning of section 10. If the Program as you
378 | received it, or any part of it, contains a notice stating that it is
379 | governed by this License along with a term that is a further
380 | restriction, you may remove that term. If a license document contains
381 | a further restriction but permits relicensing or conveying under this
382 | License, you may add to a covered work material governed by the terms
383 | of that license document, provided that the further restriction does
384 | not survive such relicensing or conveying.
385 |
386 | If you add terms to a covered work in accord with this section, you
387 | must place, in the relevant source files, a statement of the
388 | additional terms that apply to those files, or a notice indicating
389 | where to find the applicable terms.
390 |
391 | Additional terms, permissive or non-permissive, may be stated in the
392 | form of a separately written license, or stated as exceptions;
393 | the above requirements apply either way.
394 |
395 | 8. Termination.
396 |
397 | You may not propagate or modify a covered work except as expressly
398 | provided under this License. Any attempt otherwise to propagate or
399 | modify it is void, and will automatically terminate your rights under
400 | this License (including any patent licenses granted under the third
401 | paragraph of section 11).
402 |
403 | However, if you cease all violation of this License, then your
404 | license from a particular copyright holder is reinstated (a)
405 | provisionally, unless and until the copyright holder explicitly and
406 | finally terminates your license, and (b) permanently, if the copyright
407 | holder fails to notify you of the violation by some reasonable means
408 | prior to 60 days after the cessation.
409 |
410 | Moreover, your license from a particular copyright holder is
411 | reinstated permanently if the copyright holder notifies you of the
412 | violation by some reasonable means, this is the first time you have
413 | received notice of violation of this License (for any work) from that
414 | copyright holder, and you cure the violation prior to 30 days after
415 | your receipt of the notice.
416 |
417 | Termination of your rights under this section does not terminate the
418 | licenses of parties who have received copies or rights from you under
419 | this License. If your rights have been terminated and not permanently
420 | reinstated, you do not qualify to receive new licenses for the same
421 | material under section 10.
422 |
423 | 9. Acceptance Not Required for Having Copies.
424 |
425 | You are not required to accept this License in order to receive or
426 | run a copy of the Program. Ancillary propagation of a covered work
427 | occurring solely as a consequence of using peer-to-peer transmission
428 | to receive a copy likewise does not require acceptance. However,
429 | nothing other than this License grants you permission to propagate or
430 | modify any covered work. These actions infringe copyright if you do
431 | not accept this License. Therefore, by modifying or propagating a
432 | covered work, you indicate your acceptance of this License to do so.
433 |
434 | 10. Automatic Licensing of Downstream Recipients.
435 |
436 | Each time you convey a covered work, the recipient automatically
437 | receives a license from the original licensors, to run, modify and
438 | propagate that work, subject to this License. You are not responsible
439 | for enforcing compliance by third parties with this License.
440 |
441 | An "entity transaction" is a transaction transferring control of an
442 | organization, or substantially all assets of one, or subdividing an
443 | organization, or merging organizations. If propagation of a covered
444 | work results from an entity transaction, each party to that
445 | transaction who receives a copy of the work also receives whatever
446 | licenses to the work the party's predecessor in interest had or could
447 | give under the previous paragraph, plus a right to possession of the
448 | Corresponding Source of the work from the predecessor in interest, if
449 | the predecessor has it or can get it with reasonable efforts.
450 |
451 | You may not impose any further restrictions on the exercise of the
452 | rights granted or affirmed under this License. For example, you may
453 | not impose a license fee, royalty, or other charge for exercise of
454 | rights granted under this License, and you may not initiate litigation
455 | (including a cross-claim or counterclaim in a lawsuit) alleging that
456 | any patent claim is infringed by making, using, selling, offering for
457 | sale, or importing the Program or any portion of it.
458 |
459 | 11. Patents.
460 |
461 | A "contributor" is a copyright holder who authorizes use under this
462 | License of the Program or a work on which the Program is based. The
463 | work thus licensed is called the contributor's "contributor version".
464 |
465 | A contributor's "essential patent claims" are all patent claims
466 | owned or controlled by the contributor, whether already acquired or
467 | hereafter acquired, that would be infringed by some manner, permitted
468 | by this License, of making, using, or selling its contributor version,
469 | but do not include claims that would be infringed only as a
470 | consequence of further modification of the contributor version. For
471 | purposes of this definition, "control" includes the right to grant
472 | patent sublicenses in a manner consistent with the requirements of
473 | this License.
474 |
475 | Each contributor grants you a non-exclusive, worldwide, royalty-free
476 | patent license under the contributor's essential patent claims, to
477 | make, use, sell, offer for sale, import and otherwise run, modify and
478 | propagate the contents of its contributor version.
479 |
480 | In the following three paragraphs, a "patent license" is any express
481 | agreement or commitment, however denominated, not to enforce a patent
482 | (such as an express permission to practice a patent or covenant not to
483 | sue for patent infringement). To "grant" such a patent license to a
484 | party means to make such an agreement or commitment not to enforce a
485 | patent against the party.
486 |
487 | If you convey a covered work, knowingly relying on a patent license,
488 | and the Corresponding Source of the work is not available for anyone
489 | to copy, free of charge and under the terms of this License, through a
490 | publicly available network server or other readily accessible means,
491 | then you must either (1) cause the Corresponding Source to be so
492 | available, or (2) arrange to deprive yourself of the benefit of the
493 | patent license for this particular work, or (3) arrange, in a manner
494 | consistent with the requirements of this License, to extend the patent
495 | license to downstream recipients. "Knowingly relying" means you have
496 | actual knowledge that, but for the patent license, your conveying the
497 | covered work in a country, or your recipient's use of the covered work
498 | in a country, would infringe one or more identifiable patents in that
499 | country that you have reason to believe are valid.
500 |
501 | If, pursuant to or in connection with a single transaction or
502 | arrangement, you convey, or propagate by procuring conveyance of, a
503 | covered work, and grant a patent license to some of the parties
504 | receiving the covered work authorizing them to use, propagate, modify
505 | or convey a specific copy of the covered work, then the patent license
506 | you grant is automatically extended to all recipients of the covered
507 | work and works based on it.
508 |
509 | A patent license is "discriminatory" if it does not include within
510 | the scope of its coverage, prohibits the exercise of, or is
511 | conditioned on the non-exercise of one or more of the rights that are
512 | specifically granted under this License. You may not convey a covered
513 | work if you are a party to an arrangement with a third party that is
514 | in the business of distributing software, under which you make payment
515 | to the third party based on the extent of your activity of conveying
516 | the work, and under which the third party grants, to any of the
517 | parties who would receive the covered work from you, a discriminatory
518 | patent license (a) in connection with copies of the covered work
519 | conveyed by you (or copies made from those copies), or (b) primarily
520 | for and in connection with specific products or compilations that
521 | contain the covered work, unless you entered into that arrangement,
522 | or that patent license was granted, prior to 28 March 2007.
523 |
524 | Nothing in this License shall be construed as excluding or limiting
525 | any implied license or other defenses to infringement that may
526 | otherwise be available to you under applicable patent law.
527 |
528 | 12. No Surrender of Others' Freedom.
529 |
530 | If conditions are imposed on you (whether by court order, agreement or
531 | otherwise) that contradict the conditions of this License, they do not
532 | excuse you from the conditions of this License. If you cannot convey a
533 | covered work so as to satisfy simultaneously your obligations under this
534 | License and any other pertinent obligations, then as a consequence you may
535 | not convey it at all. For example, if you agree to terms that obligate you
536 | to collect a royalty for further conveying from those to whom you convey
537 | the Program, the only way you could satisfy both those terms and this
538 | License would be to refrain entirely from conveying the Program.
539 |
540 | 13. Remote Network Interaction; Use with the GNU General Public License.
541 |
542 | Notwithstanding any other provision of this License, if you modify the
543 | Program, your modified version must prominently offer all users
544 | interacting with it remotely through a computer network (if your version
545 | supports such interaction) an opportunity to receive the Corresponding
546 | Source of your version by providing access to the Corresponding Source
547 | from a network server at no charge, through some standard or customary
548 | means of facilitating copying of software. This Corresponding Source
549 | shall include the Corresponding Source for any work covered by version 3
550 | of the GNU General Public License that is incorporated pursuant to the
551 | following paragraph.
552 |
553 | Notwithstanding any other provision of this License, you have
554 | permission to link or combine any covered work with a work licensed
555 | under version 3 of the GNU General Public License into a single
556 | combined work, and to convey the resulting work. The terms of this
557 | License will continue to apply to the part which is the covered work,
558 | but the work with which it is combined will remain governed by version
559 | 3 of the GNU General Public License.
560 |
561 | 14. Revised Versions of this License.
562 |
563 | The Free Software Foundation may publish revised and/or new versions of
564 | the GNU Affero General Public License from time to time. Such new versions
565 | will be similar in spirit to the present version, but may differ in detail to
566 | address new problems or concerns.
567 |
568 | Each version is given a distinguishing version number. If the
569 | Program specifies that a certain numbered version of the GNU Affero General
570 | Public License "or any later version" applies to it, you have the
571 | option of following the terms and conditions either of that numbered
572 | version or of any later version published by the Free Software
573 | Foundation. If the Program does not specify a version number of the
574 | GNU Affero General Public License, you may choose any version ever published
575 | by the Free Software Foundation.
576 |
577 | If the Program specifies that a proxy can decide which future
578 | versions of the GNU Affero General Public License can be used, that proxy's
579 | public statement of acceptance of a version permanently authorizes you
580 | to choose that version for the Program.
581 |
582 | Later license versions may give you additional or different
583 | permissions. However, no additional obligations are imposed on any
584 | author or copyright holder as a result of your choosing to follow a
585 | later version.
586 |
587 | 15. Disclaimer of Warranty.
588 |
589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597 |
598 | 16. Limitation of Liability.
599 |
600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608 | SUCH DAMAGES.
609 |
610 | 17. Interpretation of Sections 15 and 16.
611 |
612 | If the disclaimer of warranty and limitation of liability provided
613 | above cannot be given local legal effect according to their terms,
614 | reviewing courts shall apply local law that most closely approximates
615 | an absolute waiver of all civil liability in connection with the
616 | Program, unless a warranty or assumption of liability accompanies a
617 | copy of the Program in return for a fee.
618 |
619 | END OF TERMS AND CONDITIONS
620 |
621 | How to Apply These Terms to Your New Programs
622 |
623 | If you develop a new program, and you want it to be of the greatest
624 | possible use to the public, the best way to achieve this is to make it
625 | free software which everyone can redistribute and change under these terms.
626 |
627 | To do so, attach the following notices to the program. It is safest
628 | to attach them to the start of each source file to most effectively
629 | state the exclusion of warranty; and each file should have at least
630 | the "copyright" line and a pointer to where the full notice is found.
631 |
632 |
633 | Copyright (C)
634 |
635 | This program is free software: you can redistribute it and/or modify
636 | it under the terms of the GNU Affero General Public License as published
637 | by the Free Software Foundation, either version 3 of the License, or
638 | (at your option) any later version.
639 |
640 | This program is distributed in the hope that it will be useful,
641 | but WITHOUT ANY WARRANTY; without even the implied warranty of
642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 | GNU Affero General Public License for more details.
644 |
645 | You should have received a copy of the GNU Affero General Public License
646 | along with this program. If not, see .
647 |
648 | Also add information on how to contact you by electronic and paper mail.
649 |
650 | If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source. For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code. There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 |
658 | You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
662 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/treehouses/builder/actions) [](https://codeclimate.com/github/treehouses/builder/maintainability) [](https://gitter.im/treehouses/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2 |
3 | # builder
4 |
5 | `builder` is based on [Raspbian](https://www.raspbian.org/) and
6 | allows the user to develop and tailor their own custom Raspberry Pi images.
7 | The script will modify the latest Raspbian image by installing packages,
8 | purging packages and executing custom commands, and then finally
9 | creates a bootable .img file that can be burned to the microSD card.
10 |
11 | ## Instructions
12 |
13 | These instructions will get you a copy of the project up and
14 | running on your local machine for development and testing purposes.
15 |
16 | ### Prerequisites
17 |
18 | System requirements:
19 |
20 | * Operating System - Debian/Ubuntu
21 | * microSD card reader
22 | * class10 microSD card (minimum 8 Gb)
23 | * Packages - kpartx wget gpg parted qemu-arm-static
24 |
25 | Note:
26 |
27 | To install the required packages, run the following command in Debian/Ubuntu:
28 |
29 | ```bash
30 | sudo apt-get install kpartx wget gpg parted qemu-arm-static.
31 | ```
32 |
33 | For other operating systems like MacOS or Windows, check out the `Vagrantfile` inside the repository.
34 |
35 | ### Getting Started
36 |
37 | ```
38 | git clone https://github.com/treehouses/builder.git
39 | cd builder
40 | ./builder --chroot
41 | ```
42 |
43 | You should be in a chrooted environment when it is completed.
44 | You can access the RPi images' files and folders or carry on with any extra modifications.
45 | To exit the chrooted environment just type `exit` and
46 | then you should be back in your own shell again.
47 | The image in this stage is now ready to write to the microSD card.
48 |
49 | ### Add gpg key
50 |
51 | ```bash
52 | sudo bash -c 'wget -O - https://packagecloud.io/gpg.key | apt-key add -'
53 | ```
54 |
55 | ### Customize
56 |
57 | * `INSTALL_PACKAGES` - Install packages found in the APT repositories.
58 |
59 | * To add a custom package not found in the default APT repositories:
60 | add the package name into `INSTALL_PACKAGES`,
61 | then add the custom repository to `ADD_REPOS`.
62 |
63 | * `PURGE_PACKAGES` - Remove packages already installed on the default Raspbian image.
64 |
65 | * `CUSTOM_COMMANDS` - Add extra commands to execute upon the completion of
66 | the `builder`, which is run under a chroot environment.
67 |
68 | * For instance, to enable ssh on boot for the RPi,
69 | the command `sudo touch /boot/ssh` is included in `CUSTOM_COMMANDS`.
70 | The semi-colon is there to separate the commands and
71 | will execute regardless whether or not the previous command is successful.
72 |
73 | ### Retrieve builds
74 |
75 | After exiting from the chroot environment, successful builds
76 | are found in the `builder/images` directory.
77 | There should be a few files in that directory.
78 | The .zip file is the unmodified base image,
79 | which is downloaded by the script when executed.
80 | The .img file is the new customized image and
81 | is now ready to be burned onto the microSD card.
82 |
83 | #### To remove unwanted modifications otherwise
84 |
85 | `bash clean.sh`
86 |
87 | ### Write to microSD card and try out the image
88 |
89 | We will need a few hardware and software:
90 |
91 | * Raspberry Pi 3/4 (or Zero W)
92 | * 5V 2.4A/3A (1.2A for Pi Zero) power supply with microUSB connector
93 | * A microSD card reader
94 | * A [Class 10](https://www.sdcard.org/developers/overview/speed_class/index.html)
95 | microSD card (minimal 8GB, but we strongly recommend 16GB or greater)
96 | * Software for burning OS image to microSD card. We recommend [Etcher](https://etcher.io),
97 | but there are many from which to choose
98 |
99 | Open Etcher, select the location of the .img file,
100 | the destination drive of the microSD card,
101 | then press the flash button to write the image onto the microSD card.
102 | Remember that this process will wipe out everything on the selected drive,
103 | so make sure to select the right one.
104 |
105 | ## Release
106 |
107 | This project uses Github Actions to automatically build and upload a new treehouse image
108 | to [http://dev.ole.org](http://dev.ole.org). The `builder.yml` configuration file
109 | tells Github Actions to run the deployment if a tag is applied to the commit.
110 |
111 | * New image's name will be `treehouse-` followed by
112 | whatever is after `release-` in the tag
113 | * New image's SHA-1 checksum will be calculated and uploaded as `.img.gz.sha1`
114 | * If the tag is formated like `release-` followed by only numbers,
115 | `latest.img.gz` and `latest.img.gz.sha1` would be a symbolic link of
116 | the newly uploaded image and its SHA-1 checksum
117 | * At this time, both `stable.img.gz` and `branch.img.gz` on [http://dev.ole.org](http://dev.ole.org)
118 | are manually linked to their specific image
119 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | Vagrant.configure(2) do |config|
5 |
6 | config.vm.box = "treehouses/buster64"
7 | config.vm.box_version = "0.13.25"
8 | # config.vm.box_check_update = false
9 |
10 | config.vm.hostname = "treehouses"
11 |
12 | config.vm.provider "virtualbox" do |vb|
13 | vb.name = "treehouses"
14 | vb.memory = "2222"
15 | end
16 |
17 | # load GITHUB_KEY ... please fix .vagrant.yml
18 | vagrantyml = YAML.load_file('./.vagrant.yml')
19 | githubapikey = vagrantyml.fetch('GITHUB_KEY')
20 |
21 | # config.vm.network "forwarded_port", guest: 80, host: 8080
22 | config.vm.network "forwarded_port", guest: 22, host: 2222, host_ip: "0.0.0.0", id: "ssh", auto_correct: true
23 |
24 | config.vm.provision "shell", inline: <<-SHELL
25 | echo "git checkout ?"
26 | mkdir -p /vagrant/images
27 | cd /vagrant
28 | dos2unix * */* */*/* */*/*/* */*/*/*/* */*/*/*/*/*
29 | export GITHUB_KEY='#{githubapikey}'
30 | python scripts.d/30_ssh_keys.py
31 | sudo -u vagrant screen -dmS build sudo bash -c 'export GITHUB_KEY="#{githubapikey}";export PATH="$PATH:/sbin:/usr/sbin:/usr/lib/go-1.14/bin";export GOPATH="$PATH:/home/vagrant/go";cd /vagrant;./builder --chroot; exec bash'
32 | SHELL
33 | end
34 |
--------------------------------------------------------------------------------
/autorunonce:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # ----- BASIC CONFIGURATIONS: -----
4 |
5 | # Sets hostname to a desirable name
6 | # (default: treehouses)
7 | hostname='treehouses'
8 |
9 | # If "button", bluetooth is enabled unless GPIO 18 is pulled to ground
10 | # If "normal", bluetooth is always on.
11 | # If "off", bluetooth is always off
12 | # (Default: button)
13 | bluetooth="button"
14 |
15 | # If true, this allows trusted treehouses team members to log on to the system without a password
16 | # It will search for key pairs or authorized_key files directly in /boot folder to incorporate in the ssh server
17 | # (default: true)
18 | treehousesteamsshkeys="true"
19 | addauthorizedkey=""
20 |
21 |
22 | # ----- INTERNET CONFIGURATIONS: -----
23 |
24 | # Options for connectiontype:
25 | # "ethernet" connects to ethernet only
26 | # "wifi" connects to an existing router
27 | # "apinternet" turns the raspberry pi into a hotspot with internet connection
28 | # "aplocal" turns the raspberry pi into a hotspot without internet connection
29 | # "bridge" connects to an existing router, creates a raspberry pi hotspot and bridges these two connections.
30 | connectiontype="apinternet"
31 |
32 | # Change this value to true if you are using a hidden network
33 | # (default: false)
34 | hidden="false"
35 |
36 | # wifiname: Insert the name (SSID) of your wifi router
37 | # wifipassword: Insert the password of your wifi router. Leave field empty for open networks
38 | # (Edit if "connectiontype" is "wifi" or "bridge")
39 | wifiname=''
40 | wifipassword=''
41 |
42 | # for Enterprise only, please leave it blank if you are not using WPA2-Enterprise
43 | identity=''
44 |
45 | # hotspotname: Change to the name you want your hotspot to have, raspberry pi will be a hotspot with this name as SSID
46 | # hotspotpassword:
47 | # Insert the password you want your Raspberry Pi hotspot to have. Can be blank for no password (open network)
48 | # Passwords must be 8 characters or more. If your password has less, it will be configured as open network
49 | # (Edit if "connectiontype" is "apinternet", "aplocal" or "bridge")
50 | hotspotname='treehouses'
51 | hotspotpassword=''
52 |
53 |
54 | # ----- OTHER CONFIGURATION: -----
55 |
56 | # startvnc: If true, it starts vnc and gui (default: false)
57 | startvnc="false"
58 |
59 | # starttor: If true, it starts a tor hidden service (default: false)
60 | # starttornotice: If true, publishes these addresses to treehouses gitter or "tornoticeurl" (default: false)
61 | starttor="false"
62 | starttornotice="false"
63 | tornoticeapiurl=""
64 |
65 | # startplanet: If true, this starts the docker service (default: true)
66 | # updateplanet: If true, this updates the planet to the latest revision (default: false)
67 | startplanet="true"
68 | updateplanet="false"
69 |
70 | # enablecoralboard: If true, this enables the use of the Coral Enviro board. (default: false)
71 | # startcoralenvirodemo: If true, this starts the demo on Coral Enviro board. (default: false)
72 | enablecoralenviroboard="false"
73 | startcoralenvirodemo="false"
74 |
75 |
76 | # No need to edit below this line
77 | #----------------------------------------------------------------------------------------------------#
78 |
79 | # sets the desired hostname for your raspberry pi
80 | treehouses rename $hostname
81 |
82 | # expands the filesystem
83 | treehouses expandfs
84 |
85 | # configures the wifi antenna of the raspberry pi
86 | if [ ! $(treehouses detect wifi) ]; then connectiontype="ethernet"; fi; # default network when no wifi
87 | if [ ${#hotspotpassword} -lt 8 ]; then hotspotpassword=''; fi; # no password if the password is < 8 characters long
88 | case $connectiontype in
89 | "ethernet")
90 | ;;
91 | "wifi")
92 | if [ "$hidden" == "false" ]; then
93 | if [ -z $identity ]; then
94 | treehouses wifi $wifiname $wifipassword
95 | else
96 | treehouses wifi $wifiname $wifipassword $identity
97 | fi
98 | else
99 | if [ -z $identity ]; then
100 | treehouses wifihidden $wifiname $wifipassword
101 | else
102 | treehouses wifihidden $wifiname $wifipassword $identity
103 | fi
104 | fi;;
105 | "apinternet")
106 | if [ "$hidden" == "false" ]; then
107 | treehouses ap internet $hotspotname $hotspotpassword
108 | else
109 | treehouses aphidden internet $hotspotname $hotspotpassword
110 | fi;;
111 | "aplocal")
112 | if [ "$hidden" == "false" ]; then
113 | treehouses ap local $hotspotname $hotspotpassword
114 | else
115 | treehouses aphidden local $hotspotname $hotspotpassword
116 | fi;;
117 | "bridge")
118 | treehouses bridge $wifiname $hotspotname $wifipassword $hotspotpassword;;
119 | *)
120 | echo "Unsupported configuration. Switching to default ap internet config";
121 | treehouses ap internet treehouses;;
122 | esac
123 |
124 | # disables button for bluetooth if Coral Env board is present, or constant bluetooth is selected
125 | if [ $bluetooth != "off" ] && [ $(treehouses detect bluetooth) ]; then
126 | if [ $bluetooth = "button" ] && [ $enablecoralenviroboard = "false" ]; then
127 | treehouses button bluetooth
128 | else
129 | treehouses bluetooth on
130 | fi
131 | fi
132 |
133 | # starts vnc and gui services
134 | if [ $startvnc = "true" ]; then
135 | treehouses vnc on
136 | fi
137 |
138 | # starts tor service
139 | if [ $starttor = "true" ]; then
140 | treehouses tor add 22
141 | if [ $startplanet = "true" ]; then
142 | treehouses tor add 80
143 | treehouses tor add 2200
144 | fi
145 | sleep 10
146 | sync
147 | if [ $starttornotice = "true" ]; then
148 | if [ ${#tornoticeapiurl} -ge 0 ]; then
149 | treehouses tor notice delete
150 | treehouses tor notice add $tornoticeapiurl
151 | fi
152 | treehouses tor notice on
153 | fi
154 | sync
155 | sleep 10
156 | fi
157 |
158 | # updates planet if there is an internet connection
159 | if [ $updateplanet = "true" ] && [ "$(treehouses internet)" ]; then
160 | docker pull treehouses/planet:latest
161 | docker pull treehouses/planet:db-init
162 | docker tag treehouses/planet:latest treehouses/planet:local
163 | docker tag treehouses/planet:db-init treehouses/planet:db-init-local
164 | fi
165 |
166 | # removes treehouses team members sshkeys and places keys to .ssh folder
167 | if [ $treehousesteamsshkeys = "false" ]; then
168 | treehouses sshkey deleteall
169 | fi
170 | if [[ ! -z $addauthorizedkey ]]; then
171 | treehouses sshkey add $addauthorizedkey
172 | fi
173 |
174 | # starts planet
175 | if [ $startplanet = "true" ]; then
176 | {
177 | echo "#!/bin/sh"
178 | echo
179 | echo "if [ \"$(treehouses container)\" = \"balena\" ]; then"
180 | echo " export DOCKER_HOST=localhost:2375"
181 | echo "fi"
182 | echo "sleep 1"
183 | echo
184 | echo "planet_autorun=true"
185 | echo
186 | echo "if [ \"\$planet_autorun\" = true ]; then"
187 | echo " treehouses services planet up"
188 | echo "fi"
189 | } > /boot/autorun
190 |
191 | mv /srv/tenalp /srv/planet
192 | sync;sync;sync
193 | treehouses services planet up
194 | fi
195 |
196 | # starts coral environmental board demo
197 | if [ "$startcoralenvirodemo" = "true" ] && [ -e /sys/bus/iio/devices/iio:device0 ]; then
198 | treehouses coralenv demo-always-on
199 | fi
200 |
201 | # boots to console if RPiZero or RPi3A+ (not enough RAM?)
202 | case "$(treehouses detect rpi)" in
203 | RPIZW|RPI3A+)
204 | treehouses bootoption console;;
205 | esac
206 |
207 | if [ "$(treehouses rebootneeded)" = "true" ]; then
208 | reboot
209 | fi
210 |
--------------------------------------------------------------------------------
/builder:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Download Raspbian Image, remove first-boot stuff, add repos and install packages.
3 |
4 | # Raspbian
5 | architecture="$2"
6 | case "$architecture" in
7 | "armhf" | "")
8 | RASPBIAN_TORRENT_URL=https://downloads.raspberrypi.org/raspios_armhf/images/raspios_armhf-2021-05-28/2021-05-07-raspios-buster-armhf.zip.torrent
9 | RASPBIAN_SHA256=b6c04b34d231f522278fc822d913fed3828d0849e1e7d786db72f52c28036c62
10 | ;;
11 | "arm64")
12 | RASPBIAN_TORRENT_URL=downloads.raspberrypi.org/raspios_arm64/images/raspios_arm64-2021-05-28/2021-05-07-raspios-buster-arm64.zip.torrent
13 | RASPBIAN_SHA256=f882c4c7202074277938b04fa770411c4b8a12f49e9ad2c2d70966e168b7bcb4
14 | ;;
15 | esac
16 |
17 | RASPBIAN_IMAGE_FILE=$(basename $RASPBIAN_TORRENT_URL | sed -e "s/.zip.torrent/.img/g")
18 |
19 | EXTRA_IMAGE_SIZE=1850MB
20 |
21 | MINIMAL_SPACE_LEFT=111111
22 |
23 | source lib.sh
24 |
25 | missing_deps=()
26 | for prog in kpartx wget gpg parted qemu-arm-static aria2c jq curl; do
27 | if ! type $prog &>/dev/null ; then
28 | missing_deps+=( "$prog" )
29 | fi
30 | done
31 | if (( ${#missing_deps[@]} > 0 )) ; then
32 | die "Missing required programs: ${missing_deps[*]}
33 | On Debian/Ubuntu try 'sudo apt install kpartx qemu-user-static parted wget curl jq aria2'"
34 |
35 | fi
36 |
37 | function _umount {
38 | for dir in "$@" ; do
39 | if grep -q "$dir" /proc/self/mounts ; then
40 | if ! umount -f "$dir" ; then
41 | # shellcheck disable=SC2046,SC2086
42 | die "Could not umount $dir, check running procs:$NL$(lsof 2>/dev/null | grep $(readlink -f $dir))"
43 | fi
44 | fi
45 | done
46 | }
47 |
48 | function _get_image {
49 | echo "Fetching $RASPBIAN_TORRENT_URL"
50 | mkdir -p images
51 | if [ ! -f "$RASPBIAN_TORRENT" ]; then
52 | wget "$RASPBIAN_TORRENT_URL" -O "$RASPBIAN_TORRENT" || die "Download of $RASPBIAN_TORRENT failed"
53 | fi
54 | aria2c --enable-dht=true --bt-enable-lpd=true --continue "$RASPBIAN_TORRENT" -d images --seed-time 0
55 | echo -n "Checksum of "
56 | sha256sum --strict --check - <<<"$RASPBIAN_SHA256 *$IMAGE_ZIP" || die "Download checksum validation failed, please check http://www.raspberrypi.org/downloads"
57 | }
58 |
59 | function _decompress_image {
60 | unzip -o "$IMAGE_ZIP" -d images || die "Could not unzip $IMAGE_ZIP"
61 | }
62 |
63 | function _disable_daemons {
64 | # Prevent services from being started inside the chroot.
65 | POLICY_RC_D=mnt/img_root/usr/sbin/policy-rc.d
66 | echo "#!/bin/sh" >> $POLICY_RC_D
67 | echo "exit 101" >> $POLICY_RC_D
68 | chmod +x $POLICY_RC_D
69 | }
70 |
71 | function _enable_daemons {
72 | POLICY_RC_D=mnt/img_root/usr/sbin/policy-rc.d
73 | rm -f $POLICY_RC_D
74 | }
75 |
76 | function _disable_ld_preload {
77 | cfg=mnt/img_root/etc/ld.so.preload
78 |
79 | if grep -q '^[^#]' $cfg; then
80 | sed -i -e 's/^/#/' $cfg || die "Could not disable ld.so.preload"
81 | fi
82 | }
83 |
84 | function _enable_ld_preload {
85 | cfg=mnt/img_root/etc/ld.so.preload
86 |
87 | if grep -q '^#' $cfg; then
88 | sed -i -e 's/^#//' $cfg || die "Could not enable ld.so.preload"
89 | fi
90 | }
91 |
92 | function _resize_image {
93 | RESIZE_IMAGE_PATH=images/$RASPBIAN_IMAGE_FILE
94 | if [[ -L "images" ]];
95 | then
96 | rsync -Pav "images/$RASPBIAN_IMAGE_FILE" .
97 | RESIZE_IMAGE_PATH=$RASPBIAN_IMAGE_FILE
98 | fi
99 |
100 | start_sector=$(fdisk -l "$RESIZE_IMAGE_PATH" | awk -F" " '{ print $2 }' | sed '/^$/d' | sed -e '$!d')
101 | LOOP_BASE=$(losetup -a | grep -c 'loop') #formerly loop0, loop1, loop2
102 | echo "LOOP BASE: $LOOP_BASE"
103 | LOOP_ONE=$(( LOOP_BASE + 1 ))
104 | echo "LOOP ONE: $LOOP_ONE"
105 | LOOP_TWO=$(( LOOP_BASE + 2 ))
106 | echo "LOOP TWO: $LOOP_TWO"
107 | truncate -s +$EXTRA_IMAGE_SIZE "$RESIZE_IMAGE_PATH"
108 | losetup "/dev/loop$LOOP_ONE" "$RESIZE_IMAGE_PATH"
109 | fdisk "/dev/loop$LOOP_ONE" </dev/null
158 | }
159 |
160 | function _prepare_chroot {
161 | _disable_ld_preload
162 |
163 | cp -a "$(type -p qemu-arm-static)" mnt/img_root/usr/bin/ || die "Could not copy qemu-arm-static"
164 | _chroot date &>/dev/null || die "Could not chroot date"
165 |
166 | mount -t devpts devpts -o noexec,nosuid,gid=5,mode=620 mnt/img_root/dev/pts || die "Could not mount /dev/pts"
167 | mount -t proc proc mnt/img_root/proc || die "Could not mount /proc"
168 | mount -t sysfs sys mnt/img_root/sys || die "Could not mount /sys"
169 | mount -t tmpfs -o mode=1777 none mnt/img_root/run || "Could not mount /run"
170 |
171 | mkdir -p apt_cache
172 | mount --bind apt_cache mnt/img_root/var/cache/apt/archives
173 | }
174 |
175 | function _cleanup_chroot {
176 | _umount mnt/img_root/var/cache/apt/archives \
177 | mnt/img_root/{proc,sys,run,dev/pts}
178 | _enable_daemons
179 | _enable_ld_preload
180 | }
181 |
182 | function _check_space_left {
183 | space_left=$(df | grep "dev/mapper/loop$LOOP_BASE\p2" | awk '{printf $4}')
184 | echo "Space left: ${space_left}K"
185 | }
186 |
187 | function _count_authorized_keys_lines {
188 | authorized_keys_lines=$(wc -l < mnt/img_root/root/.ssh/authorized_keys)
189 | echo "There are ${authorized_keys_lines} line(s) in /root/.ssh/authorized_keys"
190 | }
191 |
192 | function _modify_image {
193 | echo "Modifying Image"
194 |
195 | _prepare_chroot
196 | _disable_daemons
197 |
198 | run-parts --arg="$architecture" --exit-on-error -v --regex '[a-zA-Z.-_]*' scripts.d ||\
199 | die "Image modification scripts failed"
200 |
201 | _enable_daemons
202 | _check_space_left
203 | _count_authorized_keys_lines
204 | _cleanup_chroot
205 | }
206 |
207 | function _usage {
208 | echo "
209 | Usage: $0 <--chroot|--noninteractive>
210 |
211 | Download Raspbian Image, remove first-boot stuff, add repos and install packages.
212 |
213 | Open interactive Shell in chroot or write result to SD Card
214 |
215 | License: GNU General Public License, see http://www.gnu.org/copyleft/gpl.html for full text
216 | "
217 | }
218 |
219 | function _shell {
220 | _prepare_chroot
221 | chroot mnt/img_root bash -i
222 | _cleanup_chroot
223 | }
224 |
225 | export LANG="C" LANGUAGE="C" LC_ALL="C.UTF-8"
226 | shopt -s nullglob
227 |
228 | if [[ $# -eq 0 || "$*" == *-h* ]] ; then
229 | _usage
230 | exit 1
231 | fi
232 |
233 | if [[ "$USER" != root && $(id -u) != "0" ]] ; then
234 | # restart as root
235 | echo "Switching over to run as root"
236 | exec sudo "$(readlink -f "$0")" "$@"
237 | echo "Need sudo permission to run as root!"
238 | exit 1
239 | fi
240 |
241 | if grep -wq "$(readlink -f mnt)" /proc/self/mounts; then
242 | die "mnt/ is already mounted!"
243 | fi
244 |
245 | rm -Rf --one-file-system mnt temp
246 | function exittrap {
247 | set +u +e
248 | _close_image
249 | echo "Script execution time: $SECONDS seconds"
250 | }
251 | trap exittrap 0
252 | trap exittrap ERR
253 |
254 | function _print_tag {
255 | tag=$(git tag --sort=-creatordate | sed -n '1p')
256 | echo
257 | echo "latest tag is '$tag'"
258 | echo
259 | }
260 |
261 | _print_tag
262 |
263 | RASPBIAN_TORRENT=images/$(basename $RASPBIAN_TORRENT_URL)
264 | echo "$RASPBIAN_TORRENT"
265 | IMAGE_ZIP=${RASPBIAN_TORRENT%.torrent}
266 | echo "$IMAGE_ZIP"
267 | IMAGE=${IMAGE_ZIP%.zip}.img
268 | echo "$IMAGE"
269 |
270 | if [ ! -e "$IMAGE_ZIP" ]; then
271 | _get_image
272 | fi
273 |
274 | _decompress_image
275 | _resize_image
276 | _open_image
277 |
278 | if [[ "$1" == "--chroot" ]] ; then
279 | _modify_image
280 | echo "Starting interactive Shell in image chroot"
281 | _shell
282 | elif [[ "$1" == "--noninteractive" ]] ; then
283 | _modify_image
284 | elif [[ "$1" == "--shell" ]]; then
285 | _shell
286 | else
287 | die "Usage error. Try $0 --help"
288 | fi
289 |
290 | #if [[ $space_left -lt $MINIMAL_SPACE_LEFT ]]; then
291 | # echo "Not enough space left."
292 | # exit 1
293 | #fi
294 |
295 | if [[ $authorized_keys_lines -le 20 ]]; then
296 | echo "/root/.ssh/authorized_keys has 20 line or less."
297 | exit 1
298 | fi
299 |
300 | # vim:autoindent:tabstop=2:shiftwidth=2:expandtab:softtabstop=2:
301 |
--------------------------------------------------------------------------------
/clean.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sudo rm -rf temp mnt gh-cli
4 |
--------------------------------------------------------------------------------
/examples/moodole_autorunonce:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | hostname='ole'
4 | hotspotname='treehouse'
5 | moodleversion='3.4'
6 |
7 | treehouses rename $hostname
8 | treehouses expandfs
9 |
10 | wget -O /home/pi/moodole.yml https://raw.githubusercontent.com/treehouses/moodole/master/$moodleversion/arm/docker-compose-ready.yml
11 | docker-compose -f /home/pi/moodole.yml -p moodole up -d --build
12 |
13 | # write '/boot/autorun.sh'
14 | {
15 | echo '#!/bin/sh'
16 | echo ''
17 | echo 'sleep 1'
18 | echo 'docker-compose -f /home/pi/moodole.yml -p moodole start'
19 | } > /boot/autorun
20 |
21 | treehouses ap internet $hotspotname
22 |
23 | sync
24 | sync
25 | sync
26 |
27 | reboot
28 |
--------------------------------------------------------------------------------
/examples/netdata_autorunonce:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | {
4 | echo 'services:'
5 | echo ' netdata:'
6 | echo ' image: firehol/netdata:armv7hf'
7 | echo ' ports:'
8 | echo ' - "4949:19999"'
9 | echo ' - "19999:19999"'
10 | echo ' volumes:'
11 | echo ' - /proc:/host/proc'
12 | echo ' - /sys:/host/sys'
13 | echo ' cap_add:'
14 | echo ' - SYS_PTRACE'
15 | echo 'version: "2"'
16 | } > /root/netdata.yml
17 |
18 | {
19 | echo "#!/bin/sh"
20 | echo
21 | echo "sleep 1"
22 | echo "docker-compose -f /root/netdata.yml -p netdata up -d"
23 | } > /boot/autorun
24 |
25 | sync; sync; sync
26 | /boot/autorun
27 |
--------------------------------------------------------------------------------
/examples/pihole_autorunonce:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # ----- BASIC CONFIGURATIONS: -----
4 |
5 | # Sets hostname to a desirable name
6 | # (default: treehouses)
7 | hostname='treehouses'
8 |
9 | # Set your Pihole Admin password
10 | # (default is no password)
11 | piholepassword=''
12 |
13 |
14 | # ----- INTERNET CONFIGURATIONS: -----
15 |
16 | # Options for connectiontype:
17 | # "ethernet" connects to ethernet only
18 | # "wifi" connects to an existing router
19 | # "apinternet" turns the raspberry pi into a hotspot with internet connection
20 | # "aplocal" turns the raspberry pi into a hotspot without internet connection
21 | # "bridge" connects to an existing router, creates a raspberry pi hotspot and bridges these two connections.
22 | connectiontype="ethernet"
23 |
24 | # wifiname: Insert the name (SSID) of your wifi router
25 | # wifipassword: Insert the password of your wifi router. Leave field empty for open networks
26 | # (Edit if "connectiontype" is "wifi" or "bridge")
27 | wifiname=''
28 | wifipassword=''
29 |
30 | # hotspotname: Change to the name you want your hotspot to have, raspberry pi will be a hotspot with this name as SSID
31 | # hotspotpassword:
32 | # Insert the password you want your Raspberry Pi hotspot to have. Can be blank for no password (open network)
33 | # Passwords must be 8 characters or more. If your password has less, it will be configured as open network
34 | # (Edit if "connectiontype" is "apinternet", "aplocal" or "bridge")
35 | hotspotname='treehouses'
36 | hotspotpassword=''
37 |
38 |
39 | # No need to edit below this line
40 | #----------------------------------------------------------------------------------------------------#
41 |
42 | treehouses rename $hostname
43 | treehouses expandfs
44 | treehouses button bluetooth
45 |
46 | # configures the wifi antenna of the raspberry pi
47 | if [ ${#hotspotpassword} -lt 8 ]; then hotspotpassword=''; fi; # no password if the password is < 8 characters long
48 | case $connectiontype in
49 | "ethernet")
50 | ;;
51 | "wifi")
52 | treehouses wifi $wifiname $wifipassword;;
53 | "apinternet")
54 | treehouses ap internet $hotspotname $hotspotpassword;;
55 | "aplocal")
56 | treehouses ap local $hotspotname $hotspotpassword;;
57 | "bridge")
58 | treehouses bridge $wifiname $hotspotname $wifipassword $hotspotpassword;;
59 | *)
60 | echo "Unsupported configuration. Switching to default ap internet config";
61 | treehouses ap internet treehouses;;
62 | esac
63 |
64 | mkdir -p /srv/pihole
65 |
66 | sync;sync;sync
67 |
68 | {
69 | echo "version: \"3\""
70 | echo
71 | echo "# More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/"
72 | echo "services:"
73 | echo " pihole:"
74 | echo " container_name: pihole"
75 | echo " image: pihole/pihole:4.3.1-4_armhf"
76 | echo " ports:"
77 | echo " - \"53:53/tcp\""
78 | echo " - \"53:53/udp\""
79 | echo " - \"67:67/udp\""
80 | echo " - \"8053:80/tcp\""
81 | echo " - \"443:443/tcp\""
82 | echo " environment:"
83 | echo " TZ: 'America/New_York'"
84 | echo " WEBPASSWORD: $piholepassword"
85 | echo " # Volumes store your data between container upgrades"
86 | echo " volumes:"
87 | echo " - './etc-pihole/:/etc/pihole/'"
88 | echo " - './etc-dnsmasq.d/:/etc/dnsmasq.d/'"
89 | echo " dns:"
90 | echo " - 127.0.0.1"
91 | echo " - 1.1.1.1"
92 | echo " # Recommended but not required (DHCP needs NET_ADMIN)"
93 | echo " # https://github.com/pi-hole/docker-pi-hole#note-on-capabilities"
94 | echo " cap_add:"
95 | echo " - NET_ADMIN"
96 | echo " restart: unless-stopped"
97 | } > /srv/pihole/pihole.yml
98 |
99 | {
100 | echo "#!/bin/sh"
101 | echo
102 | echo "sleep 1"
103 | echo
104 | echo "service dnsmasq stop"
105 | echo "docker-compose -f /srv/pihole/pihole.yml -p pihole up -d"
106 | } > /boot/autorun
107 |
108 | sync;sync;sync
109 |
110 | case "$(treehouses detect rpi)" in
111 | RPIZW|RPI3A+)
112 | treehouses bootoption console
113 | esac
114 |
115 | reboot
116 |
--------------------------------------------------------------------------------
/examples/planet_RTC_autorunonce:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | hostname='ole'
4 | hotspotname='treehouse'
5 |
6 | # real time clock: rasclock or ds3231
7 | rtc='rasclock'
8 | # rtc='ds3231'
9 |
10 | # On the first boot the RED led mode will be heartbeat and the GREEN led will be off
11 | treehouses led red heartbeat
12 | treehouses led green none
13 |
14 | treehouses rename $hostname
15 | treehouses expandfs
16 | treehouses bluetooth on
17 | # this script was made to run using ethernet. If you have no access to it we recommend you switch to bridge
18 | #treehouses wifi [password]
19 | treehouses ap internet $hotspotname
20 | #treehouses bridge $hotspotname [password] [hotspotpassword]
21 |
22 | # real time clock
23 | treehouses rtc on "$rtc"
24 |
25 | # download Planet
26 | mkdir -p /srv/planet
27 | cd /srv/planet/ || exit 1
28 | wget https://raw.githubusercontent.com/open-learning-exchange/planet/master/docker/planet.yml
29 | wget https://raw.githubusercontent.com/open-learning-exchange/planet/master/docker/volumes.yml
30 | wget https://raw.githubusercontent.com/open-learning-exchange/planet/master/docker/install.yml
31 |
32 | sync; sync; sync
33 |
34 | docker-compose -f planet.yml -f volumes.yml -f install.yml -p planet pull
35 | docker tag treehouses/planet:db-init treehouses/planet:db-init-local
36 | docker tag treehouses/planet:latest treehouses/planet:local
37 |
38 | sync; sync; sync
39 |
40 | # second autorunonce
41 | mv /boot/autoranonce* /boot/autoranonce.first
42 | sync
43 |
44 | {
45 | echo '#!/bin/sh'
46 | echo
47 | echo "sudo treehouses led green timer"
48 | echo "sudo treehouses led red timer"
49 | echo
50 | echo "while ! curl -X GET https://google.com ; do"
51 | echo " sleep 5"
52 | echo "done"
53 | echo
54 | # On the second boot the GREEN led mode will be heartbeat and the RED led will be off
55 | echo "sudo treehouses led green heartbeat"
56 | echo "sudo treehouses led red none"
57 | echo
58 | echo "sudo treehouses ntp local"
59 | echo
60 | echo "sync;sync;sync; reboot"
61 | } > /boot/autorunonce
62 |
63 | {
64 | echo "#!/bin/sh"
65 | echo
66 | echo "sleep 1"
67 | echo
68 | echo "if [ -f /srv/planet/pwd/credentials.yml ]; then"
69 | echo " docker-compose -f /srv/planet/planet.yml -f /srv/planet/volumes.yml -f /srv/planet/pwd/credentials.yml -p planet up -d"
70 | echo "else"
71 | echo " docker-compose -f /srv/planet/planet.yml -f /srv/planet/volumes.yml -p planet up -d"
72 | echo "fi"
73 | } > /boot/autorun
74 |
75 | sync; sync; sync; reboot
76 |
--------------------------------------------------------------------------------
/examples/planet_autorunonce:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | hostname='ole'
4 | hotspotname='treehouse'
5 |
6 | # On the first boot the RED led mode will be heartbeat and the GREEN led will be off
7 | treehouses led red heartbeat
8 | treehouses led green none
9 |
10 | treehouses rename $hostname
11 | treehouses expandfs
12 | treehouses bluetooth on
13 | # this script was made to run using ethernet. If you have no access to it we recommend you switch to bridge
14 | #treehouses wifi [password]
15 | treehouses ap internet $hotspotname
16 | #treehouses bridge $hotspotname [password] [hotspotpassword]
17 |
18 | # download Planet
19 | mkdir -p /srv/planet
20 | cd /srv/planet || exit 1
21 | wget https://raw.githubusercontent.com/open-learning-exchange/planet/master/docker/planet.yml
22 | wget https://raw.githubusercontent.com/open-learning-exchange/planet/master/docker/volumes.yml
23 | wget https://raw.githubusercontent.com/open-learning-exchange/planet/master/docker/install.yml
24 |
25 | sync; sync; sync
26 |
27 | docker-compose -f planet.yml -f volumes.yml -f install.yml -p planet pull
28 | docker tag treehouses/planet:db-init treehouses/planet:db-init-local
29 | docker tag treehouses/planet:latest treehouses/planet:local
30 |
31 | {
32 | echo "#!/bin/sh"
33 | echo
34 | echo "sleep 1"
35 | echo
36 | echo "if [ -f /srv/planet/pwd/credentials.yml ]; then"
37 | echo " docker-compose -f /srv/planet/planet.yml -f /srv/planet/volumes.yml -f /srv/planet/pwd/credentials.yml -p planet up -d"
38 | echo "else"
39 | echo " docker-compose -f /srv/planet/planet.yml -f /srv/planet/volumes.yml -p planet up -d"
40 | echo "fi"
41 | } > /boot/autorun
42 |
43 | sync; sync; sync; reboot
44 |
--------------------------------------------------------------------------------
/examples/remote_autorunonce:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | treehouses expandfs
4 | treehouses bluetooth on
5 |
--------------------------------------------------------------------------------
/keys/0EBFCD88.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP PUBLIC KEY BLOCK-----
2 | Version: GnuPG v1
3 |
4 | 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
61 | YT90qFF93M3v01BbxP+EIY2/9tiIPbrd
62 | =0YYh
63 | -----END PGP PUBLIC KEY BLOCK-----
64 |
--------------------------------------------------------------------------------
/keys/68576280.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP PUBLIC KEY BLOCK-----
2 | Version: GnuPG v1
3 | Comment: GPGTools - https://gpgtools.org
4 |
5 | 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
51 | =CLGF
52 | -----END PGP PUBLIC KEY BLOCK-----
53 |
--------------------------------------------------------------------------------
/keys/8B57C5C2836F4BEB.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP PUBLIC KEY BLOCK-----
2 |
3 | mQENBF/Jfl4BCADTPUXdkNu057X+P3STVxCzJpU2Mn+tUamKdSdVambGeYFINcp/
4 | EGwNGhdb0a1BbHs1SWYZbzwh4d6+p3k4ABzVMO+RpMu/aBx9E5aOn5c8GzHjZ/VE
5 | aheqLLhSUcSCzChSZcN5jz0hTGhmAGaviMt6RMzSfbIhZPj1kDzBiGd0Qwd/rOPn
6 | Jr4taPruR3ecBjhHti1/BMGd/lj0F7zQnCjp7PrqgpEPBT8jo9wX2wvOyXswSI/G
7 | sfbFiaOJfDnYengaEg8sF+u3WOs0Z20cSr6kS76KHpTfa3JjYsfHt8NDw8w4e3H8
8 | PwQzNiRP9tXeMASKQz3emMj/ek6HxjihY9qFABEBAAG0umdMaW51eCBSYXB0dXJl
9 | IEF1dG9tYXRpYyBTaWduaW5nIEtleSAoLy9kZXBvdC9nb29nbGUzL3Byb2R1Y3Rp
10 | b24vYm9yZy9jbG91ZC1yYXB0dXJlL2tleXMvY2xvdWQtcmFwdHVyZS1wdWJrZXlz
11 | L2Nsb3VkLXJhcHR1cmUtc2lnbmluZy1rZXktMjAyMC0xMi0wMy0xNl8wOF8wNS5w
12 | dWIpIDxnbGludXgtdGVhbUBnb29nbGUuY29tPokBKAQTAQgAHAUCX8l+XgkQi1fF
13 | woNvS+sCGwMFCQPDCrACGQEAAEF6CACaekro6aUJJd3mVtrtLOOewV8et1jep5ew
14 | mpOrew/pajRVBeIbV1awVn0/8EcenFejmP6WFcdCWouDVIS/QmRFQV9N6YXN8Piw
15 | alrRV3bTKFBHkwa1cEH4AafCGo0cDvJb8N3JnM/Rmb1KSGKr7ZXpmkLtYVqr6Hgz
16 | l+snrlH0Xwsl5r3SyvqBgvRYTQKZpKqmBEd1udieVoLSF988kKeNDjFa+Q1SjZPG
17 | W+XukgE8kBUbSDx8Y8q6Cszh3VVY+5JUeqimRgJ2ADY2/3lEtAZOtmwcBlhY0cPW
18 | Vqga14E7kTGSWKC6W96Nfy9K7L4Ypp8nTMErus181aqwwNfMqnpnuQENBF/Jfl4B
19 | CADDSh+KdBeNjIclVVnRKt0QT5593yF4WVZt/TgNuaEZ5vKknooVVIq+cJIfY/3l
20 | Uqq8Te4dEjodtFyKe5Xuego6qjzs8TYFdCAHXpXRoUolT14m+qkJ8rhSrpN0TxIj
21 | WJbJdm3NlrgTam5RKJw3ShypNUxyolnHelXxqyKDCkxBSDmR6xcdft3wdQl5IkIA
22 | wxe6nywmSUtpndGLRJdJraJiaWF2IBjFNg3vTEYj4eoehZd4XrvEyLVrMbKZ5m6f
23 | 1o6QURuzSrUH9JT/ivZqCmhPposClXXX0bbi9K0Z/+uVyk6v76ms3O50rIq0L0Ye
24 | hM8G++qmGO421+0qCLkdD5/jABEBAAGJAR8EGAEIABMFAl/Jfl4JEItXxcKDb0vr
25 | AhsMAAAbGggAw7lhSWElZpGV1SI2b2K26PB93fVI1tQYV37WIElCJsajF+/ZDfJJ
26 | 2d6ncuQSleH5WRccc4hZfKwysA/epqrCnwc7yKsToZ4sw8xsJF1UtQ5ENtkdArVi
27 | BJHS4Y2VZ5DEUmr5EghGtZFh9a6aLoeMVM/nrZCLstDVoPKEpLokHu/gebCwfT/n
28 | 9U1dolFIovg6eKACl5xOx+rzcAVp7R4P527jffudz3dKMdLhPrstG0w5YbyfPPwW
29 | MOPp+kUF45eYdR7kKKk09VrJNkEGJ0KQQ6imqR1Tn0kyu4cvkfqnCUF0rrn7CdBq
30 | LSCv1QRhgr6TChQf7ynWsPz5gGdVjh3tIw==
31 | =dsvF
32 | -----END PGP PUBLIC KEY BLOCK-----
33 |
--------------------------------------------------------------------------------
/keys/C99B11DEB97541F0.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP PUBLIC KEY BLOCK-----
2 |
3 | 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
39 | thQyULWTJXRidPWVyWWqegyubCbY0cY=
40 | =ki4q
41 | -----END PGP PUBLIC KEY BLOCK-----
--------------------------------------------------------------------------------
/lib.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Constants
3 | # shellcheck disable=SC2034
4 | NL="$(echo)"
5 |
6 | function die {
7 | echo 1>&2 ERROR: "$*"
8 | exit 1
9 | }
10 |
11 | function _op {
12 | "$@" &> >(sed -e 's/^/| /')
13 | }
14 |
15 | function _chroot {
16 | chroot mnt/img_root "$@"
17 | }
18 |
19 | function _apt {
20 | _op _chroot apt-get -o Acquire::ForceIPv4=true -o APT::Acquire::Retries=3 -qq "$@"
21 | }
22 |
23 | function _pip3_install {
24 | _op _chroot pip3 install "$@"
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/scripts.d/00_disable_autoresize.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | sed -i 's| quiet init=/usr/lib/raspi-config/init_resize.sh||' mnt/img_root/boot/cmdline.txt || die "Could notdisable autoresize"
6 |
--------------------------------------------------------------------------------
/scripts.d/00_utc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | _op _chroot ln -sf /usr/share/zoneinfo/UTC /etc/localtime
6 |
--------------------------------------------------------------------------------
/scripts.d/05_add_keys.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | # List of extra GPG keys to import from the LOCAL SYSTEM!
6 | ADD_REPO_KEYS=(
7 | 68576280 # nodesource
8 | 0EBFCD88 # docker release (ce deb)
9 | C99B11DEB97541F0 # gh
10 | 8B57C5C2836F4BEB # coral
11 | )
12 |
13 | GPG="gpg --no-permission-warning --no-default-keyring --quiet --keyring "
14 | KEYRING=$PWD/apt_keys.gpg
15 | rm -f "$KEYRING"
16 | cat keys/*.key | $GPG "$KEYRING" --import
17 |
18 | missing_keys=()
19 | for key in "${ADD_REPO_KEYS[@]}" ; do
20 | if ! $GPG "$KEYRING" --list-keys "$key" >/dev/null 2>&1 ; then
21 | missing_keys+=( "$key" )
22 | fi
23 | done
24 |
25 | if [[ ${#missing_keys[@]} -gt 0 ]]; then
26 | die "missing GPG keys! try: $GPG $KEYRING --recv-keys ${missing_keys[*]}"
27 | fi
28 |
29 | $GPG "$KEYRING" --export "${ADD_REPO_KEYS[@]}" | \
30 | $GPG mnt/img_root/etc/apt/trusted.gpg --trustdb-name mnt/img_root/etc/apt/trustdb.gpg --import - || \
31 | die "Could not import GPG keys ${ADD_REPO_KEYS[*]} for apt"
32 | rm -f "$KEYRING"
--------------------------------------------------------------------------------
/scripts.d/05_add_repos.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | architecture="$1"
4 | source lib.sh
5 |
6 | case "$architecture" in
7 | "armhf" | "")
8 | pkgs=("raspbian-archive-keyring" "apt-transport-https")
9 | os=raspbian
10 | ;;
11 | "arm64")
12 | pkgs=("apt-transport-https")
13 | os=debian
14 | ;;
15 | esac
16 |
17 | is_installed() {
18 | pkg="$1"
19 | _chroot dpkg-query -s "$pkg" 2>/dev/null | grep -qx 'Status: install ok installed'
20 | }
21 |
22 | install_stuff() {
23 | local need_install
24 |
25 |
26 |
27 | for pkg in ${pkgs[*]}; do
28 | if ! is_installed "$pkg"; then
29 | need_install="$need_install $pkg"
30 | echo "need to install $pkg"
31 | fi
32 | done
33 |
34 | if [ -n "$need_install" ]; then
35 | echo "updating package sources"
36 | _apt update --allow-releaseinfo-change || die "Could not update package sources"
37 | _apt install "${pkgs[@]}"
38 | fi
39 | }
40 |
41 | # List of extra APT repositories
42 | ADD_REPOS=(
43 | # curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key > keys/68576280.key
44 | "deb https://deb.nodesource.com/node_10.x buster main"
45 | # curl -fsSL https://download.docker.com/linux/debian/gpg > keys/0EBFCD88.key
46 | "deb [arch=$architecture] https://download.docker.com/linux/$os buster stable"
47 | # curl https://cli.github.com/packages/githubcli-archive-keyring.gpg > keys/C99B11DEB97541F0.key
48 | "deb [arch=$architecture] https://cli.github.com/packages buster main"
49 | # curl https://packages.cloud.google.com/apt/doc/apt-key.gpg > keys/8B57C5C2836F4BEB.key
50 | "deb https://packages.cloud.google.com/apt coral-cloud-stable main"
51 | )
52 |
53 | LIST=mnt/img_root/etc/apt/sources.list.d/treehouses.list
54 |
55 | if [[ "${ADD_REPOS:-}" && ! -f "$LIST" ]] ; then
56 | install_stuff
57 | for repo in "${ADD_REPOS[@]}" ; do
58 | echo "$repo"
59 | done > $LIST || die "Could not add repos ${ADD_REPOS[*]}"
60 | _apt update --allow-releaseinfo-change || die "Could not update package sources"
61 | fi
62 |
--------------------------------------------------------------------------------
/scripts.d/05_better_mirrors.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | exit 0
3 | architecture="$1"
4 | source lib.sh
5 |
6 | cp mnt/img_root/etc/apt/sources.list mnt/img_root/etc/apt/sources.list.orig
7 | case "$architecture" in
8 | "armhf" | "")
9 | cat << EOF > mnt/img_root/etc/apt/sources.list
10 | #deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
11 | deb http://mirrors.ocf.berkeley.edu/raspbian/raspbian buster main contrib non-free rpi
12 | # Uncomment line below then 'apt-get update' to enable 'apt-get source'
13 | #deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
14 | EOF
15 | ;;
16 | "arm64")
17 | #Todo http://debian-archive.trafficmanager.net/debian/
18 | ;;
19 | esac
20 |
--------------------------------------------------------------------------------
/scripts.d/10_pkg_purge.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | # List of packages to remove
6 | PURGE_PACKAGES=(
7 | wolfram-engine
8 | # sonic-pi
9 | # scratch
10 | # squeak-plugins-scratch squeak-vm
11 | dphys-swapfile
12 | )
13 |
14 | # shellcheck disable=SC2207
15 | PURGE_PACKAGES=( $(
16 | for package in "${PURGE_PACKAGES[@]}" ; do
17 | if _chroot dpkg -s "$package" &>/dev/null ; then
18 | echo "$package"
19 | fi
20 | done
21 | ) )
22 |
23 | if [[ ${PURGE_PACKAGES:-} ]] ; then
24 | echo "Removing unwanted packages ${PURGE_PACKAGES[*]}"
25 | _apt purge "${PURGE_PACKAGES[@]}" ||\
26 | die "Could not remove ${PURGE_PACKAGES[*]}"
27 | _apt autoremove ||\
28 | die "Error in auto remove"
29 | fi
30 |
31 |
--------------------------------------------------------------------------------
/scripts.d/15_pkg_upgrade.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | echo "Holding nodejs Package"
6 | _op _chroot apt-mark hold nodejs
7 | # temporay fix to not break GUI icons and background
8 | _op _chroot apt-mark hold libfm-data
9 | _op _chroot apt-mark hold libfm-extra4
10 | _op _chroot apt-mark hold libfm-gtk-data
11 | _op _chroot apt-mark hold libfm-gtk4
12 | _op _chroot apt-mark hold libfm-modules
13 | _op _chroot apt-mark hold libfm4
14 | _op _chroot apt-mark hold raspberrypi-ui-mods
15 |
16 | echo "Installing Updates"
17 | _apt update || die "Could not update package sources"
18 | _apt dist-upgrade || die "Could not upgrade system"
19 |
20 | _op _chroot apt-mark unhold libfm-data
21 | _op _chroot apt-mark unhold libfm-extra4
22 | _op _chroot apt-mark unhold libfm-gtk-data
23 | _op _chroot apt-mark unhold libfm-gtk4
24 | _op _chroot apt-mark unhold libfm-modules
25 | _op _chroot apt-mark unhold libfm4
26 | _op _chroot apt-mark unhold raspberrypi-ui-mods
27 |
--------------------------------------------------------------------------------
/scripts.d/16_pkg_install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | INSTALL_PACKAGES=(
6 | avahi-daemon vim lshw iotop screen tmux # essentials
7 | docker-ce aufs-dkms- # docker
8 | # quicksynergy # dogi
9 | matchbox-keyboard # virtual keyboard
10 | mdadm initramfs-tools rsync # for RAID1
11 | elinks links lynx # text mode web browser
12 | hostapd dnsmasq # rpi access point
13 | dos2unix # for converting dos characters to unix in autorunonce
14 | nodejs # version 8.5.0-1nodesource1
15 | autossh
16 | python3-pip python3-dbus
17 | bluez minicom bluez-tools libbluetooth-dev # bluetooth hotspot
18 | avahi-autoipd # for usb0
19 | rng-tools # for ap bridge
20 | tor
21 | openvpn
22 | shadowsocks-libev proxychains4 # socks5 proxy
23 | libpam-google-authenticator # two factor authentication
24 | jq # for parsing json / treehouses command
25 | net-tools # netstat
26 | iproute2 # ss command
27 | nmap # network mapping package
28 | htop
29 | speedtest-cli # speedtest.net
30 | libffi-dev # for building docker-compose using pip
31 | #python3-coral-enviro # Coral environmental board # breaks with new kernel
32 | bc # for memory command
33 | libusb-dev # for usb.sh
34 | dnsutils
35 | uptimed # for measuring rpi uptime
36 | pagekite # tunnels command
37 | sl
38 | gh
39 | netcat-openbsd # for arm64
40 | mc ranger
41 | bats # unit testing
42 | libhdf5-dev libatlas-base-dev libqt4-test # opencv # libjasper1
43 | imagemagick # tiv
44 | python3-bcrypt python3-nacl # fix slow pip
45 | )
46 |
47 | if [[ ${INSTALL_PACKAGES:-} ]] ; then
48 | echo "Installing ${INSTALL_PACKAGES[*]}"
49 | _apt install "${INSTALL_PACKAGES[@]}" || die "Could not install ${INSTALL_PACKAGES[*]}"
50 | fi
51 |
52 | _op _chroot apt-mark hold tor #TODO bring back to upstream
53 |
--------------------------------------------------------------------------------
/scripts.d/17_default_mirrors.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | exit 0
3 | architecture="$1"
4 | source lib.sh
5 |
6 | case "$architecture" in
7 | "armhf" | "")
8 | cat << EOF > mnt/img_root/etc/apt/sources.list
9 | deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
10 | #deb http://mirrors.ocf.berkeley.edu/raspbian/raspbian buster main contrib non-free rpi
11 | # Uncomment line below then 'apt-get update' to enable 'apt-get source'
12 | #deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
13 | EOF
14 | ;;
15 | "arm64")
16 | #Todo http://debian-archive.trafficmanager.net/debian/
17 | ;;
18 | esac
19 |
20 | _apt update || die "Could not update package sources"
21 |
--------------------------------------------------------------------------------
/scripts.d/18_loginmsg.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | motd=mnt/img_root/etc/motd
4 | green="\033[1;32m"
5 | red="\033[0;31m"
6 | reset="\033[0m"
7 | {
8 | echo -e "${red}################################################################################"
9 | echo -e "#${green} _ _ _ ${red}#"
10 | echo -e "#${green} | |_ _ __ ___ ___ | |__ ___ _ _ ___ ___ ___ (_) ___ ${red}#"
11 | echo -e "#${green} | __|| '__|/ _ \\ / _ \\| '_ \\ / _ \\ | | | |/ __| / _ \\/ __| | | / _ \\ ${red}#"
12 | echo -e "#${green} | |_ | | | __/| __/| | | || (_) || |_| |\\__ \\| __/\\__ \\ _ | || (_) | ${red}#"
13 | echo -e "#${green} \\__||_| \\___| \\___||_| |_| \\___/ \\__,_||___/ \\___||___/(_)|_| \\___/ ${red}#"
14 | echo -e "#${red} #"
15 | echo -e "#${red} Welcome to the treehouses project! ${red}#"
16 | echo -e "#${red} For more information, please visit: ${reset}http://treehouses.io ${red}#"
17 | echo -e "#${red} To begin using treehouses type ${reset}treehouses help ${red}#"
18 | echo -e "#${red} Please feel free to contact us in the ${reset}https://gitter.im/treehouses/Lobby ${red}#"
19 | echo -e "${red}################################################################################${reset}"
20 | } > $motd
21 |
22 | chmod +x $motd
23 |
--------------------------------------------------------------------------------
/scripts.d/20_balena.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | architecture="$1"
4 |
5 |
6 | source lib.sh
7 |
8 | echo "Balena installation"
9 |
10 | # get the latest version
11 | releases=$(curl -s https://api.github.com/repos/balena-os/balena-engine/releases/latest -H "Authorization: token $APIKEY" | jq -r ".assets[].browser_download_url")
12 |
13 | case "$architecture" in
14 | "armhf" | "")
15 | archlink=armv7l
16 | armv6link=$(echo "$releases" | tr " " "\\n" | grep armv6)
17 | armv7link=$(echo "$releases" | tr " " "\\n" | grep armv7)
18 | # armv7
19 | wget -c "$armv7link"
20 | tar xvzf "$(basename "$armv7link")" ./balena-engine/balena-engine
21 | mv balena-engine/balena-engine mnt/img_root/usr/bin/balena-engine-armv7l
22 | _op _chroot chown root:root /usr/bin/balena-engine-armv7l
23 | rm -rf balena-engine/
24 | # armv6
25 | wget -c "$armv6link"
26 | tar xvzf "$(basename "$armv6link")" ./balena-engine/balena-engine
27 | mv balena-engine/balena-engine mnt/img_root/usr/bin/balena-engine-armv6l
28 | _op _chroot chown root:root /usr/bin/balena-engine-armv6l
29 | rm -rf balena-engine/
30 | ;;
31 | "arm64")
32 | archlink=arm64
33 | aarch64link=$(echo "$releases" | tr " " "\\n" | grep aarch64)
34 | wget -c "$aarch64link"
35 | tar xvzf "$(basename "$aarch64link")" ./balena-engine/balena-engine
36 | mv balena-engine/balena-engine mnt/img_root/usr/bin/balena-engine-arm64
37 | _op _chroot chown root:root /usr/bin/balena-engine-arm64
38 | rm -rf balena-engine/
39 | ;;
40 | esac
41 |
42 | _op _chroot touch /usr/bin/balena-engine
43 | _op _chroot ln -sr /usr/bin/balena-engine /usr/bin/balena-engine-containerd
44 | _op _chroot ln -sr /usr/bin/balena-engine /usr/bin/balena-engine-containerd-ctr
45 | _op _chroot ln -sr /usr/bin/balena-engine /usr/bin/balena-engine-containerd-shim
46 | _op _chroot ln -sr /usr/bin/balena-engine /usr/bin/balena-engine-daemon
47 | _op _chroot ln -sr /usr/bin/balena-engine /usr/bin/balena-engine-proxy
48 | _op _chroot ln -sr /usr/bin/balena-engine /usr/bin/balena-engine-runc
49 | _op _chroot ln -sr /usr/bin/balena-engine /usr/bin/balena
50 | _op _chroot rm /usr/bin/balena-engine
51 | _op _chroot ln -sr /usr/bin/balena-engine-$archlink /usr/bin/balena-engine
52 |
53 | _op _chroot groupadd balena
54 | _op _chroot usermod -aG balena pi
55 | _op _chroot usermod -aG balena root
56 |
57 | _op _chroot rm -rf /var/lib/balena-engine
58 | _op _chroot ln -sr /var/lib/docker /var/lib/balena-engine
59 |
60 | #install balena service scripts
61 |
62 | cat << EOF > mnt/img_root/etc/systemd/system/balena.socket
63 | [Unit]
64 | Description=Balena Socket for the API
65 | PartOf=balena.service
66 |
67 | [Socket]
68 | ListenStream=/var/run/balena.sock
69 | SocketMode=0660
70 | SocketUser=root
71 | SocketGroup=balena
72 |
73 | [Install]
74 | WantedBy=sockets.target
75 | EOF
76 |
77 | cat << EOF > mnt/img_root/etc/systemd/system/balena.service
78 | [Unit]
79 | Description=Balena Application Container Engine
80 | Documentation=https://www.balena.io/engine/
81 | After=network-online.target balena.socket firewalld.service
82 | Wants=network-online.target
83 | Requires=balena.socket
84 |
85 | [Service]
86 | Type=notify
87 | # the default is not to use systemd for cgroups because the delegate issues still
88 | # exists and systemd currently does not support the cgroup feature set required
89 | # for containers run by balena
90 | ExecStart=/usr/bin/balena-engine-daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/balena-engine.sock
91 | ExecReload=/bin/kill -s HUP $MAINPID
92 | LimitNOFILE=1048576
93 | # Having non-zero Limit*s causes performance problems due to accounting overhead
94 | # in the kernel. We recommend using cgroups to do container-local accounting.
95 | LimitNPROC=infinity
96 | LimitCORE=infinity
97 | # Uncomment TasksMax if your systemd version supports it.
98 | # Only systemd 226 and above support this version.
99 | #TasksMax=infinity
100 | TimeoutStartSec=0
101 | # set delegate yes so that systemd does not reset the cgroups of balena containers
102 | Delegate=yes
103 | # kill only the balena process, not all processes in the cgroup
104 | KillMode=process
105 | # restart the balena process if it exits prematurely
106 | Restart=on-failure
107 | StartLimitBurst=3
108 | StartLimitInterval=60s
109 |
110 | [Install]
111 | WantedBy=multi-user.target
112 | EOF
113 |
114 | _op _chroot chmod +x /etc/systemd/system/balena.service
115 | _op _chroot chmod +x /etc/systemd/system/balena.socket
--------------------------------------------------------------------------------
/scripts.d/20_enable_ssh.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | _op _chroot systemctl enable ssh
6 |
--------------------------------------------------------------------------------
/scripts.d/20_fix_node.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | architecture="$1"
4 | source lib.sh
5 |
6 | case "$architecture" in
7 | "armhf" | "")
8 | echo "TODO: Fix node"
9 | # armv6l
10 | wget https://nodejs.org/dist/v10.16.0/node-v10.16.0-linux-armv6l.tar.gz
11 | tar xvzf node-v10.16.0-linux-armv6l.tar.gz node-v10.16.0-linux-armv6l/bin/node
12 | mv node-v10.16.0-linux-armv6l/bin/node mnt/img_root/usr/bin/node-armv6l
13 | _op _chroot chown root:root /usr/bin/node-armv6l
14 | rm -rf node-v10.16.0-linux-armv6l
15 | # armv7l
16 | _op _chroot mv /usr/bin/node /usr/bin/node-armv7l
17 | _op _chroot ln -sr /usr/bin/node-armv7l /usr/bin/node
18 | ;;
19 | "arm64")
20 | # arm64
21 | _op _chroot mv /usr/bin/node /usr/bin/node-arm64
22 | _op _chroot ln -sr /usr/bin/node-arm64 /usr/bin/node
23 | ;;
24 | esac
--------------------------------------------------------------------------------
/scripts.d/20_install_autorun.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | cat << EOF > mnt/img_root/etc/systemd/system/autorun.service
6 | [Unit]
7 | Description=run autorun(once)(.sh) scripts from USB stick or in /boot
8 | After=local_fs.target remote_fs.target network-online.target
9 |
10 | [Service]
11 | Type=oneshot
12 | RemainAfterExit=yes
13 | ExecStart=/usr/local/bin/do_autorun start
14 | Restart=no
15 |
16 | [Install]
17 | WantedBy=multi-user.target
18 |
19 | EOF
20 |
21 | mkdir -p "mnt/img_root/etc/systemd/system/multi-user.target.wants"
22 | _op _chroot ln -sn /etc/systemd/system/autorun.service /etc/systemd/system/multi-user.target.wants/autorun.service
23 | _op _chroot chmod +x /etc/systemd/system/multi-user.target.wants/autorun.service
24 |
--------------------------------------------------------------------------------
/scripts.d/20_install_balena_socket.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | cat << 'EOF' > mnt/img_root/etc/systemd/system/balena.socket
6 | [Unit]
7 | Description=Balena Socket for the API
8 | PartOf=balena.service
9 |
10 | [Socket]
11 | ListenStream=/var/run/balena.sock
12 | SocketMode=0660
13 | SocketUser=root
14 | SocketGroup=balena
15 |
16 | [Install]
17 | WantedBy=sockets.target
18 | EOF
19 |
20 | _op _chroot chmod +x /etc/systemd/system/balena.socket
--------------------------------------------------------------------------------
/scripts.d/20_install_bluetooth.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | cat << EOF > mnt/img_root/etc/systemd/system/rpibluetooth.service
6 | [Unit]
7 | Description=Bluetooth server
8 | After=rpibluetooth.service
9 | Requires=rpibluetooth.service bluetooth.service
10 |
11 | StartLimitIntervalSec=500
12 | StartLimitBurst=5
13 |
14 | [Service]
15 | Restart=always
16 | RestartSec=5s
17 |
18 | ExecStart=/usr/bin/python3 /usr/local/bin/bluetooth-server.py &
19 |
20 | [Install]
21 | WantedBy=multi-user.target
22 | EOF
23 |
24 | _op _chroot chmod +x /etc/systemd/system/rpibluetooth.service
--------------------------------------------------------------------------------
/scripts.d/20_install_do_autorun.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | mkdir -p mnt/img_root/usr/local/bin
6 |
7 | cat <<'EOF' > mnt/img_root/usr/local/bin/do_autorun
8 | #!/bin/bash
9 |
10 | rebootrequired=0
11 |
12 | led_mode() {
13 | mode="$1"
14 | trigger=/sys/class/leds/led0/trigger
15 | [ -e $trigger ] && echo "$mode" > $trigger
16 | }
17 |
18 | log() {
19 | echo "do_autorun:" "$@"
20 | }
21 |
22 | find_script() {
23 | base_name="$1"
24 |
25 | for ext in "" .sh .txt; do
26 | script="$base_name$ext"
27 |
28 | if [ -e "$script" ]; then
29 | echo "$script"
30 | return
31 | fi
32 | done
33 | }
34 |
35 | wifiunblock(){
36 | if [[ $(rfkill list wifi -o soft -n) == "blocked" ]]; then
37 | rfkill unblock wifi
38 | log "wifi unblocked"
39 | fi
40 | }
41 |
42 | autorunonce(){
43 | log "searching for autorunonce script"
44 | script=$(find_script "$1/autorunonce")
45 |
46 | if [ -z "$script" ]; then
47 | log "no autorunonce found"
48 | return 1
49 | fi
50 |
51 | newname="$(basename "$script" | sed -e 's/run/ran/')"
52 | newscript="$(dirname "$script")/$newname"
53 | log "moving autorunonce script: $script -> $newscript"
54 | mv -v "$script" "$newscript"
55 | log "converting dos newlines to unix"
56 | dos2unix "$newscript"
57 | sync
58 | log "running autorunonce script $script"
59 | led_mode timer
60 | bash "$newscript"
61 | log "autorunonce script is done"
62 | }
63 |
64 | autorun(){
65 | log "searching for autorun script"
66 | script=$(find_script "$1/autorun")
67 |
68 | if [ -z "$script" ]; then
69 | log "no autorun script found"
70 | return 1
71 | fi
72 |
73 | log "converting dos newlines to unix"
74 | dos2unix "$script"
75 |
76 | log "running autorun script $script"
77 | led_mode heartbeat
78 | sudo screen -dmS treehouses bash -c 'sudo '"$script"
79 | log "autorun script started in screen"
80 | }
81 |
82 | oneforall() {
83 | service=$1
84 | arch=$(uname -m)
85 | log "one${service}forall"
86 | symlink=$service
87 | [[ $symlink == balena ]] && symlink=${symlink}-engine
88 | case "$arch" in
89 | "armv6l")
90 | log "$arch - rpi0/1"
91 | if [ "$(readlink -- /usr/bin/${service})" != "${symlink}-armv6l" ]
92 | then
93 | unlink /usr/bin/${symlink}
94 | ln -sr /usr/bin/${symlink}-armv6l /usr/bin/${symlink}
95 | fi
96 | ;;
97 | "armv7l")
98 | log "$arch - rpi2/3"
99 | if [ "$(readlink -- /usr/bin/${symlink})" != "${symlink}-armv7l" ]
100 | then
101 | unlink /usr/bin/${symlink}
102 | ln -sr /usr/bin/${symlink}-armv7l /usr/bin/${symlink}
103 | fi
104 | ;;
105 | "aarch64")
106 | log "$arch - arm64"
107 | ;;
108 | *)
109 | log "$arch - something went wrong"
110 | ;;
111 | esac
112 | }
113 |
114 | usbgadget() {
115 | case "$(treehouses detectrpi)" in
116 | RPIZ|RPIZW)
117 | if grep -q -w "^#dtoverlay=dwc2" /boot/config.txt
118 | then
119 | sed -i -e 's/#dtoverlay=dwc2/dtoverlay=dwc2/g' /boot/config.txt
120 | rebootrequired=1
121 | fi
122 |
123 | if grep -q "#modules-load=dwc2,g_ether" /boot/cmdline.txt
124 | then
125 | sed -i -e 's/#modules-load=dwc2,g_ether/modules-load=dwc2,g_ether/g' /boot/cmdline.txt
126 | rebootrequired=1
127 | fi
128 | ;;
129 | *)
130 | if grep -q -w "^dtoverlay=dwc2" /boot/config.txt
131 | then
132 | sed -i -e 's/dtoverlay=dwc2/#dtoverlay=dwc2/g' /boot/config.txt
133 | rebootrequired=1
134 | fi
135 |
136 | if grep -q " modules-load=dwc2,g_ether" /boot/cmdline.txt
137 | then
138 | sed -i -e 's/ modules-load=dwc2,g_ether/ #modules-load=dwc2,g_ether/g' /boot/cmdline.txt
139 | rebootrequired=1
140 | fi
141 | esac
142 | }
143 |
144 | start() {
145 | led_mode default-on
146 | log "starting"
147 | wifiunblock
148 | usbgadget
149 | oneforall balena
150 | oneforall node
151 | if [[ rebootrequired -eq 1 ]]
152 | then
153 | reboot
154 | fi
155 | mkdir -p /data
156 | if [ -b /dev/sda1 ]
157 | then
158 | log "usb stick"
159 | mountpoint -q /data || mount /dev/sda1 /data
160 | cd /data || exit 1
161 | autorunonce /data || autorun /data
162 | else
163 | log "no usb stick"
164 | cd /boot || exit 1
165 | autorunonce /boot || autorun /boot
166 | fi
167 | }
168 |
169 | stop() {
170 | log "stopping"
171 | sudo screen -X -S "treehouses" quit
172 | }
173 |
174 |
175 | # Some things that run always
176 | touch /var/lock/autorun
177 |
178 | # Carry out specific functions when asked to by the system
179 | case "$1" in
180 | start)
181 | start
182 | ;;
183 | stop)
184 | stop
185 | ;;
186 | *)
187 | echo "Usage: $0 {start|stop}"
188 | exit 1
189 | ;;
190 | esac
191 |
192 | exit 0
193 |
194 | EOF
195 |
196 | _op _chroot chmod +x /usr/local/bin/do_autorun
197 |
--------------------------------------------------------------------------------
/scripts.d/20_install_rclocal.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cat << EOF > mnt/img_root/etc/rc.local
4 | #!/bin/sh -e
5 | #
6 | # rc.local
7 | #
8 | # This script is executed at the end of each multiuser runlevel.
9 | # Make sure that the script will "exit 0" on success or any other
10 | # value on error.
11 | #
12 | # In order to enable or disable this script just change the execution
13 | # bits.
14 | #
15 | # By default this script does nothing.
16 |
17 | # Print the IP address
18 | _IP=$(hostname -I) || true
19 | if [ "$_IP" ]; then
20 | printf "My IP address is %s\n" "$_IP"
21 | fi
22 |
23 | if [ -f "/etc/tunnel" ];
24 | then
25 | /etc/tunnel
26 | fi
27 |
28 | exit 0
29 |
30 | EOF
--------------------------------------------------------------------------------
/scripts.d/20_tiv.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | architecture="$1"
4 |
5 | git clone https://github.com/stefanhaustein/TerminalImageViewer.git
6 | (
7 | cd TerminalImageViewer || exit 0
8 | workingver=e69c53e4cc03f370fd335b65ccdeb97d3ece294c
9 | currentver=$(git rev-parse HEAD)
10 | [[ "$workingver" != "$currentver" ]] && echo "TODO: a new version has been released, check https://github.com/stefanhaustein/TerminalImageViewer"
11 | git checkout $workingver
12 | )
13 |
14 | case "$architecture" in
15 | "armhf" | "")
16 | CXX=arm-linux-gnueabihf-g++ make -C TerminalImageViewer/src/main/cpp
17 | ;;
18 | "arm64")
19 | CXX=aarch64-linux-gnu-g++ make -C TerminalImageViewer/src/main/cpp
20 | ;;
21 | esac
22 | mv TerminalImageViewer/src/main/cpp/tiv mnt/img_root/usr/local/bin/
23 |
--------------------------------------------------------------------------------
/scripts.d/20_vim.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | _op _chroot update-alternatives --set editor /usr/bin/vim.basic
6 |
7 |
--------------------------------------------------------------------------------
/scripts.d/30_bluetooth.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | curl --silent --show-error --fail "https://raw.githubusercontent.com/treehouses/control/master/server.py" -o mnt/img_root/usr/local/bin/bluetooth-server.py
6 |
7 | cat mnt/img_root/usr/local/bin/bluetooth-server.py | grep ^class
8 |
9 | echo "Switching bluetooth device class to 0x00010c - computer"
10 | sed -i -e 's/#Class = .*/Class = 0x00010c/g' mnt/img_root/etc/bluetooth/main.conf
11 |
12 | _pip3_install 'pybluez==0.23'
13 |
--------------------------------------------------------------------------------
/scripts.d/30_docker.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | architecture="$1"
4 |
5 | [[ $architecture == "" ]] && architecture=arm
6 | [[ $architecture == "armhf" ]] && architecture=arm
7 |
8 | source lib.sh
9 |
10 | # IMAGES=(
11 | # portainer/portainer:linux-arm
12 | # #pihole/pihole:4.3.1-4_armhf
13 | # #firehol/netdata:armv7hf
14 | # )
15 |
16 | MULTIS=(
17 | treehouses/couchdb:2.3.1
18 | treehouses/planet:latest
19 | treehouses/planet:db-init
20 | portainer/portainer:alpine
21 | )
22 |
23 | OLD=$(pwd -P)
24 | cd /var/lib || die "ERROR: /var/lib folder doesn't exist, exiting"
25 |
26 | service docker stop
27 | mv docker docker.temp
28 | mkdir -p "$OLD/mnt/img_root/var/lib/docker"
29 | ln -s "$OLD/mnt/img_root/var/lib/docker" docker
30 | service docker start
31 |
32 | # for image in "${IMAGES[@]}" ; do
33 | # docker pull "$image"
34 | # done
35 |
36 | mkdir -p ~/.docker
37 | echo '{"experimental": "enabled"}' > ~/.docker/config.json
38 |
39 | mkdir -p "$OLD/mnt/img_root/root/.docker"
40 | cp ~/.docker/config.json "$OLD/mnt/img_root/root/.docker/."
41 |
42 | for multi in "${MULTIS[@]}" ; do
43 | docker manifest inspect "$multi"
44 | name=$(echo "$multi" | cut -d ":" -f 1)
45 | tag=$(echo "$multi" | cut -d ":" -f 2)
46 | hash=$(docker manifest inspect "$multi" | jq '.manifests' | jq -c "map(select(.platform.architecture | contains(\"$architecture\")))" | jq '.[0]' | jq '.digest' | sed -e 's/^"//' -e 's/"$//')
47 | docker pull "$name@$hash"
48 | docker tag "$name@$hash" "$name:$tag"
49 | done
50 |
51 | docker tag treehouses/planet:db-init treehouses/planet:db-init-local
52 | docker tag treehouses/planet:latest treehouses/planet:local
53 |
54 | sync; sync; sync
55 |
56 | docker images
57 |
58 | service docker stop
59 | unlink docker
60 | mv docker.temp docker
61 | service docker start
62 |
63 | cd "$OLD" || die "ERROR: $OLD folder doesn't exist, exiting"
64 |
65 | _op _chroot adduser pi docker
66 |
67 | # installs docker-compose using pip3
68 | _pip3_install docker-compose --no-cache-dir
69 |
--------------------------------------------------------------------------------
/scripts.d/30_enable_uart.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | ROOT=mnt/img_root
6 | CONFIG=$ROOT/boot/config.txt
7 |
8 | # Set up firmware configuration
9 |
10 | if ! grep -q "^enable_uart=" $CONFIG; then
11 | {
12 | echo
13 | echo "# Enable UART on Pi 3"
14 | echo "enable_uart=1"
15 | } >> $CONFIG
16 | fi
17 |
--------------------------------------------------------------------------------
/scripts.d/30_examples_scripts.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ROOT=mnt/img_root
4 | mkdir -p $ROOT/boot/examples
5 | cp -r examples/* $ROOT/boot/examples
6 | cp autorunonce $ROOT/boot/autorunonce
7 |
--------------------------------------------------------------------------------
/scripts.d/30_g_ether.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Make the pi into a USB ethernet gadget.
4 | ROOT=mnt/img_root
5 | CONFIG=$ROOT/boot/config.txt
6 | CMDLINE=$ROOT/boot/cmdline.txt
7 | USB0IFACE=$ROOT/etc/network/interfaces.d/usb0
8 |
9 | # Set up firmware configuration
10 | {
11 | echo
12 | echo "# Enable USB gadget mode"
13 | echo "#dtoverlay=dwc2"
14 | } >> $CONFIG
15 |
16 | sed -i -e 's/$/ #modules-load=dwc2,g_ether/' $CMDLINE
17 |
18 | # Configure the network interface
19 | {
20 | echo
21 | echo "auto usb0"
22 | echo "allow-hotplug usb0"
23 | echo "iface usb0 inet ipv4ll"
24 | } >> $USB0IFACE
25 |
26 |
--------------------------------------------------------------------------------
/scripts.d/30_npminstall.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | echo "Installing @treehouses/cli script"
6 |
7 | mkdir node_root
8 | npm config set prefix "$PWD/node_root"
9 | npm install --unsafe-perm -g @treehouses/cli@1.26.4
10 | npm install --unsafe-perm -g bats-support@0.3.0
11 | npm install --unsafe-perm -g bats-assert@2.0.0
12 | (cd node_root || exit 1; tar c .) | (cd mnt/img_root/usr || exit 1; tar x)
13 | echo "$PWD"
14 | if [ ! -L "$PWD/mnt/img_root/etc/bash_completion.d/_treehouses" ]; then ln -sr "$PWD/mnt/img_root/usr/lib/node_modules/@treehouses/cli/_treehouses" "$PWD/mnt/img_root/etc/bash_completion.d/_treehouses"; fi
15 | ls -al "$PWD/mnt/img_root/etc/bash_completion.d/_treehouses"
16 | npm config delete prefix
17 | rm -rf node_root
18 |
--------------------------------------------------------------------------------
/scripts.d/30_opencv_install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | _op _chroot pip3 install opencv-python==4.1.0.25 opencv-contrib-python==4.1.0.25
6 | _op _chroot pip3 install --upgrade imutils
7 |
8 | echo "Verify your install worked by the following commands:"
9 | echo
10 | echo "python3"
11 | echo "import cv2"
12 | echo "cv2.__version__"
13 | echo ""
14 | echo "You should see \"4.1.0\" or higher if it worked."
15 | echo "If installation is successful, you'll need to restart to get the camera working."
16 | echo "Upon reboot, run the following to verify the camera works: "
17 | echo "sudo raspistill -e png -n -o /home/pi/Pictures/activation_test.png"
18 | echo
19 | echo "Trained classifiers for detecting objects can be found at https://github.com/opencv/opencv/tree/master/data/haarcascades"
--------------------------------------------------------------------------------
/scripts.d/30_ssh_keys.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # Obtain the public ssh keys of each of the public members of open-learning-exchange organization
4 |
5 | import requests
6 | import os
7 |
8 | r = requests.get('https://api.github.com/orgs/treehouses/teams/support/members', auth=(os.getenv("USERNAME"), os.getenv("APIKEY")))
9 | print(r)
10 | users = r.json()
11 | members = []
12 | for user in users:
13 | members.append(user['login'])
14 |
15 | print ("Found %d members. Getting keys for users" % len(members))
16 |
17 | with open('authorized_keys', 'w') as keylog:
18 | for member in members:
19 | keys_content = requests.get('https://github.com/' + member +'.keys', auth=(os.getenv("USERNAME"), os.getenv("APIKEY")))
20 | keys = (keys_content.text.splitlines())
21 | print(keys)
22 | if len(keys):
23 | print("info: user %s has keys" % member)
24 | else:
25 | print("info: user %s has NO keys" % member)
26 | for key in keys:
27 | keylog.write("%s %s\n" % (key.strip(), member))
--------------------------------------------------------------------------------
/scripts.d/30_version_txt.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | architecture="$1"
3 | set -e
4 |
5 | ROOT=mnt/img_root
6 | case "$architecture" in
7 | "armhf" | "")
8 | version=$(git tag --sort=-creatordate | sed -n '1p')
9 | ;;
10 | "arm64")
11 | version="$(git tag --sort=-creatordate | sed -n '1p')-$architecture"
12 | ;;
13 | esac
14 | echo "writing version.txt: $version"
15 | echo "$version" > $ROOT/boot/version.txt
--------------------------------------------------------------------------------
/scripts.d/31_install_ssh_configs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | ROOT=mnt/img_root
6 |
7 | {
8 | echo "Host *.onion"
9 | echo " ProxyCommand nc -x localhost:9050 -X 5 %h %p"
10 | } > config
11 |
12 | _install() {
13 | owner="$1"
14 | home="$2"
15 | install -o "$owner" -g "$owner" -m 700 -d "$home/.ssh"
16 | install -o "$owner" -g "$owner" -m 600 authorized_keys "$home/.ssh"
17 | install -o "$owner" -g "$owner" -m 600 config "$home/.ssh"
18 | }
19 |
20 | echo "installing SSH keys for root"
21 | _install root $ROOT/root
22 | echo "installing SSH keys for pi"
23 | _install 1000 $ROOT/home/pi
24 |
--------------------------------------------------------------------------------
/scripts.d/32_sl.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | _op _chroot ln -sr /usr/games/sl /usr/local/bin/sl
6 | ls -al mnt/img_root/usr/local/bin/sl
7 |
--------------------------------------------------------------------------------
/scripts.d/32_terraform.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | wget https://releases.hashicorp.com/terraform/0.13.3/terraform_0.13.3_linux_arm.zip
4 | unzip terraform_0.13.3_linux_arm.zip
5 |
6 | mkdir -p mnt/img_root/usr/local/bin/
7 | mv terraform mnt/img_root/usr/local/bin/.
8 |
--------------------------------------------------------------------------------
/scripts.d/33_usb.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | _op _chroot wget https://raw.githubusercontent.com/codazoda/hub-ctrl.c/master/hub-ctrl.c
6 | _op _chroot gcc -o hub-ctrl hub-ctrl.c -lusb
7 |
8 | mkdir -p mnt/img_root/usr/local/bin/
9 | _op _chroot mv hub-ctrl usr/local/bin/.
10 | chmod +x mnt/img_root/usr/local/bin/hub-ctrl
11 | _op _chroot rm -f hub-ctrl.c
12 |
--------------------------------------------------------------------------------
/scripts.d/34_youtube-dl.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | curl -L https://yt-dl.org/downloads/latest/youtube-dl -k -o mnt/img_root/usr/local/bin/youtube-dl #without certificate
4 | chmod a+rx mnt/img_root/usr/local/bin/youtube-dl
5 |
--------------------------------------------------------------------------------
/scripts.d/35_disable_uptimed.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | rm -f mnt/img_root/etc/systemd/system/multi-user.target.wants/uptimed.service
--------------------------------------------------------------------------------
/scripts.d/36_log2ram.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | _op _chroot curl -Lo log2ram.tar.gz https://github.com/azlux/log2ram/archive/master.tar.gz
6 | _op _chroot tar xf log2ram.tar.gz
7 | _op _chroot rm log2ram.tar.gz
8 | _op _chroot cd log2ram-master
9 | _op _chroot ./install.sh
10 | _op _chroot cd ..
11 | _op _chroot rm -r log2ram-master
12 | _op _chroot systemctl stop log2ram
13 | _op _chroot systemctl disable log2ram
14 |
15 |
--------------------------------------------------------------------------------
/scripts.d/40_planet.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 |
5 | planetdir='tenalp'
6 |
7 | # download Planet
8 | wget https://raw.githubusercontent.com/open-learning-exchange/planet/master/docker/planet.yml
9 | wget https://raw.githubusercontent.com/open-learning-exchange/planet/master/docker/install.yml
10 | wget https://raw.githubusercontent.com/open-learning-exchange/planet/master/docker/volumes.yml
11 |
12 | {
13 | echo "services:"
14 | echo " couchdb:"
15 | echo " volumes:"
16 | echo " - \"$(pwd -P)/mnt/img_root/srv/$planetdir/data:/opt/couchdb/data\""
17 | echo " - \"$(pwd -P)/mnt/img_root/srv/$planetdir/log:/opt/couchdb/var/log\""
18 | echo " planet:"
19 | echo " volumes:"
20 | echo " - \"$(pwd -P)/mnt/img_root/srv/$planetdir/pwd:/usr/share/nginx/html/credentials\""
21 | echo "version: \"2\""
22 | } > volumestravis.yml
23 |
24 | sync; sync; sync
25 |
26 | docker-compose -f planet.yml -f volumestravis.yml -f install.yml -p planet pull
27 | docker tag treehouses/planet:db-init treehouses/planet:db-init-local
28 | docker tag treehouses/planet:latest treehouses/planet:local
29 |
30 | sync; sync; sync
31 |
32 | docker-compose -f planet.yml -f volumestravis.yml -p planet up -d
33 |
34 | # check if couch-db is working
35 | while ! curl -X GET http://127.0.0.1:2200/_all_dbs ; do
36 | sleep 1
37 | done
38 | echo "couch is up"
39 |
40 | cp -a planet.yml install.yml volumes.yml "mnt/img_root/srv/$planetdir/"
41 |
42 | # temporary couchdb local.ini fix
43 |
44 | {
45 | echo "; CouchDB Configuration Settings"
46 | echo ""
47 | echo "; Custom settings should be made in this file. They will override settings"
48 | echo "; in default.ini, but unlike changes made to default.ini, this file won't be"
49 | echo "; overwritten on server upgrade."
50 | echo ""
51 | echo "[chttpd]"
52 | echo "bind_address = any"
53 | echo ""
54 | echo "[httpd]"
55 | echo "bind_address = any"
56 | echo ""
57 | echo "[log]"
58 | echo "writer = file"
59 | echo "file = /opt/couchdb/var/log/couch.log"
60 | echo ""
61 | echo "[couchdb]"
62 | echo "uuid = 2442283a086e83c280831811afce124c"
63 | } > local.ini
64 |
65 | sync; sync; sync
66 | mkdir "mnt/img_root/srv/$planetdir/conf/"
67 |
68 | cp -a local.ini "mnt/img_root/srv/$planetdir/conf/"
69 | tree -f "mnt/img_root/srv/$planetdir/conf"
70 |
71 | # check if couch-db docker has finish
72 | while $(docker inspect -f "{{.State.Running}}" "$(docker ps -f name=planet_db-init* -a -q)") == "true"; do
73 | sleep 1
74 | done
75 | echo "couch has finished"
76 |
77 | tree -f "mnt/img_root/srv/$planetdir"
78 |
79 | # sync and stop docker
80 | sync; sync; sync
81 | docker-compose -f planet.yml -f volumestravis.yml -p planet stop
82 |
--------------------------------------------------------------------------------
/scripts.d/50_rm_files.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source lib.sh
4 | # List of files/directories to remove
5 | REMOVE=(
6 | /home/pi/MagPi
7 | /home/travis
8 | )
9 |
10 | for file in "${REMOVE[@]}" ; do
11 | _op _chroot rm -rf "$file"
12 | echo "- '$file' removed"
13 | done
14 |
15 | sync; sync; sync
16 | # _op _chroot tree /home/
17 |
--------------------------------------------------------------------------------