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.

Prerequisites

This tutorial builds on the previous tutorial: Start a minimal project. Follow the below steps if skipping the previous tutorial.

  1. Extract the 01-start-minimal-project.end.tar and run chillbox server-init inside the hello-chillbox/ directory.

  2. The current user (alice) will also need to be updated:

Update chillbox.toml
[[user]]
name = "alice" (1)
password_hash = "..." (2)
public_ssh_key = [
   "..." (3)
]
1 Alice is the current user for this tutorial.
2 Copy and paste the '.current_user_data.password_hash' value from ./chillbox/statefile.json
3 Copy and paste the '.current_user_data.public_ssh_key[0]' value from ./chillbox/statefile.json

1. Initialize a vagrant project in hello-chillbox

  1. 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
  2. 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
  3. Set the 'ssh_config' attribute to define a custom ssh-config that will be included when chillbox uses ssh and scp 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"
  4. 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

  1. 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"
  2. 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
  3. 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

  1. 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"
  2. 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

  1. Login to the virtual machine as the alice user.

    ssh -F "$(chillbox ssh-unlock)" alice@hello-chillbox-example-server
  2. 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 that answers.txt file; the alice user will need to use sudo 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.
  3. 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.
Continue to the next tutorial to work with a real server.

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.