A virtual machine that can be used on your local computer is useful when developing scripts for a server that is managed with Chillbox. This guide will use two tools to accomplish this: Vagrant, and VirtualBox as they have binaries available for multiple platforms. At the end of this tutorial you’ll have an Ubuntu server that can be used for the rest of the tutorials.
1. Initialize a vagrant project in hello-chillbox
-
Add the below Vagrantfile to the project directory.
Create file:Vagrantfile
Vagrant.configure("2") do |config| config.vm.box = "bento/ubuntu-22.04" config.vm.define "hello-chillbox-example-server" config.vm.hostname "hello-chillbox-example-server" config.vm.provision "shell", path: ".chillbox/server/hello-chillbox-example-server/user-data" end
-
Initialize the virtual machine by running the
vagrant
commands. A new file (vagrant-ssh_config
) is created.vagrant up vagrant ssh-config > vagrant-ssh_config
-
Set the 'ssh_config' attribute to define a custom ssh-config that will be included when chillbox uses
ssh
andscp
commands. This custom one is specific for use with Vagrant.Update file:chillbox.toml
instance = "hello-chillbox" archive-directory = ".chillbox" ssh_config = "vagrant-ssh_config"
-
Verify that this way of logging into the virtual machine works. The
chillbox ssh-unlock
command generates a ssh config file at a temporary location and outputs it. The '-F' option refers to a ssh-config file.ssh -F "$(chillbox ssh-unlock)" alice@hello-chillbox-example-server exit
The command vagrant ssh
does basically the same as the above command but logs in as the vagrant user.
1.1. Add the chillbox scripts
-
Update the user-data script to also create the
/srv/files/
directory.Update file:template-tutorial/hello-chillbox-user-data.sh.jinja
#!/usr/bin/env sh set -o errexit # Example user-data script for hello-chillbox tutorial. ## Add user and set the password hash # shellcheck disable=SC2016 id '{{ chillbox_user.name }}' > /dev/null 2> /dev/null \ || useradd -m -s /usr/bin/bash -p '{{ chillbox_user.password_hash }}' '{{ chillbox_user.name }}' ## Add the user's public ssh key. mkdir -p '/home/{{ chillbox_user.name }}/.ssh' cat <<'HERE_PUBLIC_SSH_KEYS' > '/home/{{ chillbox_user.name }}/.ssh/authorized_keys' {{ chillbox_user["public_ssh_key"] | join('\n') }} HERE_PUBLIC_SSH_KEYS chown -R '{{ chillbox_user.name }}' '/home/{{ chillbox_user.name }}/.ssh' chmod -R 700 '/home/{{ chillbox_user.name }}/.ssh' chmod -R 644 '/home/{{ chillbox_user.name }}/.ssh/authorized_keys' groupadd -f --system chillbox-example-group usermod -a -G chillbox-example-group '{{ chillbox_user.name }}' usermod -a -G sudo '{{ chillbox_user.name }}' ## Add initial /srv/files/ directory for the tutorial. mkdir -p /srv/files/ chown -R '{{ chillbox_user.name }}:chillbox-example-group' /srv/files/ chmod 0770 /srv/files/ ## Add chillbox specific directories for storing sensitive and secret files. tmp_dir="$(mktemp -d)" cat <<'CHILLBOXUSERDATACREATEDIRS' > "$tmp_dir/chillbox-user-data-create_dirs.sh" {% include [create_dirs_script, 'chillbox:create_dirs.sh'] %} CHILLBOXUSERDATACREATEDIRS chmod u+x "$tmp_dir/chillbox-user-data-create_dirs.sh" "$tmp_dir/chillbox-user-data-create_dirs.sh" rm -rf "$tmp_dir" ## Create the chillbox scripts used for handling uploaded files that are encrypted. {% include 'chillbox:user-data/static/snippet-create_scripts.sh.jinja' %} mkdir -p /root/chillbox/key key_name="$(hostname -s | xargs)" /usr/local/bin/create-asymmetric-key -n "$key_name" -d /root/chillbox/key mkdir -p /usr/local/share/chillbox/key/ mv "/root/chillbox/key/$key_name.public.pem" /usr/local/share/chillbox/key/ chmod 644 "/usr/local/share/chillbox/key/$key_name.public.pem" mkdir -p /var/lib/chillbox/.watch-chillbox-secrets-and-sensitive-paths/ chown -R '{{ chillbox_user.name }}:chillbox-example-group' /var/lib/chillbox/.watch-chillbox-secrets-and-sensitive-paths/ chmod 0770 /var/lib/chillbox/.watch-chillbox-secrets-and-sensitive-paths/ echo "done"
-
Render the updated user-data script that will be at
.chillbox/server/hello-chillbox-example-server/user-data
. Use the '--force' option to overwrite the previously rendered user-data script.chillbox server-init --force
-
Apply the changed user-data script by provisioning the vagrant virtual machine again.
vagrant provision (1)
1 See When Provisioning Happens for details.
2. Upload files
-
Specify what files should be uploaded to this server by adding each path id to the remote-files list.
Update file:chillbox.toml
[[server]] ip = "127.0.0.1" name = "hello-chillbox-example-server" owner = "alice" remote-files = [ "server-menu-md", "breakfast-menu", "alice-answers", "level_3_lunch_code", ] [server.user-data] template = "tutorial:hello-chillbox-user-data.sh.jinja"
-
Upload the files now that there is a
/srv/files/
directory and the other chillbox directories.chillbox -v upload (1)
1 The '-v' option adds verbosity to the output. The two files without sensitive data were uploaded and extracted to their 'dest' locations:
/srv/files/the-menu.md
and/srv/files/breakfast-menu.md
. The other file has sensitive data so it was encrypted with the server’s public key and is at:/var/lib/chillbox/path_sensitive/alice/srv/files/alice/answers.txt
. The other sensitive file is owned by bob, so that file is skipped when uploading as the alice user.
2.1. Verify uploaded files
-
Login to the virtual machine as the alice user.
ssh -F "$(chillbox ssh-unlock)" alice@hello-chillbox-example-server
-
The server’s private key is kept in the
/root/chillbox/key/
directory which only the root user has access to. The alice user does have sudo privileges. In order to decrypt thatanswers.txt
file; the alice user will need to usesudo
to use the server’s private key.sudo su (1) tmp_dest_path_gz="$(mktemp)" decrypt-file \ -k "/root/chillbox/key/hello-chillbox-example-server.private.pem" \ -i /var/lib/chillbox/path_sensitive/alice/srv/files/alice/answers.txt \ "$tmp_dest_path_gz" (2) (3) mkdir -p /srv/files/alice/ touch /srv/files/alice/answers.txt chown alice /srv/files/alice/answers.txt chmod go-rwx /srv/files/alice/answers.txt chmod u+r /srv/files/alice/answers.txt chmod u-w /srv/files/alice/answers.txt gunzip -c -f "$tmp_dest_path_gz" > /srv/files/alice/answers.txt rm -f "$tmp_dest_path_gz" (4)
1 Need root privileges to use the server’s private key. 2 The file is gzipped before it is encrypted. 3 Securely store the decrypted answers.txt
so only alice can read it.4 Finally unzip and remove the temporary gzip file. This is an example to illustrate how a sensitive file could be securely uploaded and decrypted on the server. This process is somewhat tedious to do manually and should be done automatically. A bit more complex script exists to handle this process automatically, but is only supported on Alpine Linux at this time: init-s6-openrc-path-secret-watcher.sh. -
Now return back to the alice user and show the contents of the
answers.txt
file.exit (1) whoami cat /srv/files/alice/answers.txt && echo "" (2) exit (3)
1 Need to exit out of being the root user and confirm that alice is now the current user. 2 Why is Alice so secretive about her favorite color? 3 Return back to the local machine.
TODO: Create tutorial for a more real world server that serves static files.
Summary
At this point it may seem that chillbox doesn’t really do much besides render some files using templates and upload them to a server. And that is mostly correct. ;) So, why use it? Well, it is simply a tool that does a specific task which can work with other tools.