small pixel drawing of a pufferfish zoa

6f58d512
wahat
Jes Olson j3s@c3f.net
Sun, 26 Mar 2023 14:10:51 -0700
99cfefbc
fmt: clean up some stuff
Jes Olson j3s@c3f.net
Tue, 22 Nov 2022 22:56:38 -0800
8e2d9d18
Add zoa fmt
Jes Olson j3s@c3f.net
Tue, 22 Nov 2022 22:50:35 -0800
                           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   [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  
    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  ...
    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
clone
git clone https://git.j3s.sh/zoa