README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
zoa zoa is a simple, opinionated, shell-based config management tool. zoa is made for individuals or small teams, and works best when it comes to managing simple, traditional linux environments. it's also for individuals who are allergic to meaningless change and deprecation. -> you might like zoa if: - you like configuration management - you like small & simple things - you run alpine, gentoo, linux from scratch, etc - you use a tiling window manager - you like messing with dotfiles - you dislike chef, ansible, saltstack, and puppet intensely - you feel like nix is overcomplicated you might not like zoa if: - you are an abstraction enjoyer - you dislike shell, the language - you dislike working in the terminal -> quickstart (for x64 linux) # install zoa $ wget https://trash.j3s.sh/zoa $ chmod +x zoa $ mv zoa /usr/local/bin/ # set up a zoa script $ printf "%s" "echo hello, world!" > hi $ printf "%s" "ls /noexisty" >> hi $ printf "%s" "uname -a" >> hi # execute zoa! $ zoa run hi you will notice a few interesting things: - zoa gently asked you to make echo posix compliant - zoa notified you that ls exited unsuccessfully - zoa printed all stdout in plaintext -> why? i am a config management professional. (6+ years) i have worked with chef, ansible, and puppet. i made zoa because i think all of those config management systems are overcomplicated for most people / orgs. they're hard to keep up with, and require constant care & maintenance. i designed zoa for myself, and anyone like me! zoa uses shell - the love language of *nix systems - it won't go out of style :) zoa teaches you how to write proper posix-compatible shell, which is a timeless skill. also, shell is just fun & i love it. :D -> design * 1 way zoa exposes only 1 hostname var, 1 copy function, has 0 flags, has 1 way to execute, and 1 way to format your repository. less overhead for you. * be a turtle zoa is starting with a minimal set of built-in functions because i only want to maintain functions in order to address severe pain-points. most things should just be handled via plain shell. * as standards-compliant as reasonable certain standards may be flexible if the UX improvements are worth it. -> moar info pls # zoa has three components 1: the utility 2: env vars and helpers 3: the layout -> 1: the utility zoa is a statically compiled binary, and it has no OS dependencies - simply download it and execute it. zoa expects to run as root. to run zoa: zoa run your-zoa-script ^ the zoa script to execute that's it, you've run zoa! -> 2: env vars and helper functions zoa sets some useful things up for you! -> env vars before zoa runs, it sets a few standard environment variables for your usage. the values shown are the defaults on my dev system. $PATH - search path PATH=/usr/local/bin:/usr/local/bin:/bin:/bin:/usr/bin:/usr/bin $ARCH - hardware type of the running system ARCH=x86_64 $NODENAME - name of this node NODENAME=nostromo.j3s.sh * this env var may vary by distro * for example, it may print "nostromo" on some systems $OS - the operating system name OS=Linux * on BSD systems, this var is a lot more useful * if you want your distro, take a look at OS_RELEASE_ID $RELEASE - release level of operating system RELEASE=5.19.5-arch1-1 * typically, this is the kernel version !WARNING! ALL $OS_RELEASE_* VARIABLES ARE NON-STANDARD, CHECK FOR THEIR EXISTENCE BEFORE RELYING ON THEM. $OS_RELEASE_ID - short uncapitalized name of your distro OS_RELEASE_ID=arch * see above warning $OS_RELEASE_VERSION_ID - version of your distro OS_RELEASE_VERSION_ID= # arch has no version ID * see above warning TODO: expose hardware info, cpu cores, ip address, memory availability, etc -> helper commands zoa has some helper commands for common operations. note that you _can_ use these functions _outside_ of shell scripts, by simply running them. > zoa cp <source> <destination> [mode] copy a file from source to destination. optionally, define the permissions of the destination file (defaults to 0644) zoa cp will do nothing if the files are already the same. examples: zoa cp files/sudoers /etc/sudoers zoa cp files/sshd_config /etc/ssh/sshd_config 0644 TODO: dir support > zoa get <http/https> <destination> download a given url to a given destination. this is useful when the operating system you're running on doesn't provide wget or curl. also, zoa's formatting is nicer. examples: zoa get https://trash.j3s.sh/serial-experiments-lain.mp4 /home/j3s/Videos TODO: git support? > zoa watch <file> <command>... watch a file for changes. if any changes are detected, execute the given command. this is very useful for reloading services when their configuration files change. examples: $ zoa watch /etc/ssh/sshd_config systemctl restart sshd TODO: zoa fmt -> organization ideas here's how a zoa project might be organized: main <-- the script you call files/ <-- dir containing arbitrary text files main is your entrypoint. you could just stick everything in main and be done with it, if you want. scripts/ contains arbitrary shell scripts. you can organize them how you'd like. dirs are supported. files/ contains any files that you might be interested in placing on hosts. "zoa cp" -> flexible example if you want zoa to be a little more capable, here's a decent starting point: main: case $NODENAME in git.j3s.sh) # note that the CERTS env var will # pass into any scripts called after # it is defined, as if they're all 1 # long script export TLS_CERTS='git.j3s.sh' zoa run scripts/certs zoa run scripts/git ;; j3s.sh) export TLS_CERTS='j3s.sh' zoa run scripts/certs zoa run scripts/web ;; esac scripts/certs: certbot renew "$TLS_CERTS" scripts/web: apt install nginx systemctl enable --start nginx BONUS SECTION! :3 :3 <3 :3 common config management patterns in zoa ### define a reusable function in zoa, this is easy - just define a shell function: die() { printf "%s.\n" "$1" exit 1 } every sub-script that is called will automatically have access to it. ### install a package (this is distro dependent) apt update apt install -y cowsay ### install a package, but only if the distro is debian if [ "$OS_RELEASE_ID" = "debian" ]; then apt install -y cowsay fi ### place sshd_config, set permissions, and reload ssh when it changes zoa-file sshd /etc/ssh/sshd_config systemctl restart sshd chown root:root /etc/ssh/sshd_config chmod 0644 /etc/ssh/sshd_config ### append an iptables rule to the input chain rule='INPUT --protocol tcp --dport 69 --jump ACCEPT' iptables --check $rule || iptables --append $rule ### clone a remote git repo, pull it constantly git clone git@git.sr.ht:~example/example /opt/repo || git fetch /opt/repo