Get Your Hands Dirty
We're thrilled to have you here and ready to dig deeper into the toolkit!
Our hands-on tour will guide you through setting up a ready-to-run distribution with useful features that serve Mio's README via HTTPS. It demonstrates how the system works and hopefully sparks interest in exploring it further. It's all about instant gratification.
The mio-wizard will handle all the heavy lifting by creating the file system structure and helping you bootstrap a fully Mio-driven project. Use this as a starting point and adjust it to your needs.
You should be able to copy and paste each shell block directly into a terminal. It's always a good idea to spawn a new container for experiments.
Fasten your seatbelts; we're starting from scratch.
For every project, it boils down to this list:
- Install Mio —
mio-wizard install - Create a Super Project
- Create Your Identity —
mio-wizard id - Create a Remote Repository
- Initialize the Super Project —
mio-wizard init - Add a Backup Controller —
mio-wizard add-backupctl - Configure Overlays aka Modules
- Integrate Applications and Payloads
- Add Instances —
mio-wizard add-instance - Roll Out —
make install.
If you're looking for a fully automated procedure without the fluff, or if you're stuck in the middle, check out our TL;DR demo.
1. Install Mio#
The mio-wizard – One-Shot Edition can be downloaded from either the Stable Releases or Packages pages. Depending on your Debian 12 / Bookworm base image, you will need to install some additional packages.
curl -OJ https://codeberg.org/api/packages/kosmonum/generic/mio-ose/next/mio-wizard
sudo install -m 755 -o root -g root mio-wizard /usr/local/bin/mio-wizard
sudo mio-wizard install
2. Create a Super Project#
This will be our main workspace directory. Pick a location that works for you.
We will use ~/docs-mio as our starting point!
mkdir ~/docs-mio && cd ~/docs-mio
3. Create Your Identity#
We are going to create an identity consisting of a couple of private keys. It is highly recommended that you create an identity for each super project to address the separation of concerns.
Choose an available identity format that suits your needs.
For sub-addressing, ensure your forge and services can handle it. Use the second or third option to take control of your alias.
ALIAS+COMMENT@DOMAIN.TLDALIAS <EMAIL>ALIAS (COMMENT) <EMAIL>
We will use plus-sub addressing and set our key to expire after one day. The wizard will then ask for our passphrase to unlock the keys for the current session. It will output lots of information to your terminal.
Read them carefully and memorize your avatars.
You will be left with instructions (TODO-NOW.md) explaining how to back up your keys and passphrases, along with possible next steps.
Take it seriously!
MIO_EXPIRE=1d mio-wizard id me@mio.lan
mio-wizard id
This command creates an identity with the following settings:
- Prompts you to enter your identity passphrase.
- Creates a primary key with Subkeys for signing, encryption, and authentication.
- Sets the identity expiration date to tomorrow.
Split/Subkeys Setup
In short, this strategy removes the secret key from the primary identity. Segmenting responsibilities improves security by dedicating the creation of new identities to a single part.
However, this approach increases complexity. Mio will provide proper superuser support later on.
Skip this step for tutorial or demo setups until you are familiar with the concept.
Don't rush, and give it your full attention and dive into Subkeys.
4. Create a Remote Repository#
In order to persist and share your workspace, you need a remote Git repository. Go to your Forge settings and create a new one. Grant your project identity write access using the authentication keys from the .ssh/id.pub file.
For demonstration purposes, we are using a local bare repository.
git init --bare ~/docs-mio.git
5. Initialize the Super Project#
This step initializes our super project and connects it to the repository, ~/docs-mio.git. The project name is demo and it is located under our top-level domain / zone, mio.lan. The last two arguments are optional when bootstrapping an existing project.
By default, we commit and auto-push all changes.
Once again, the wizard provides notes on the next steps.
MIO_SCM_PUSH=1 mio-wizard init file://${HOME}/docs-mio.git demo mio.lan
mio-wizard init
This command bootstraps the project by setting up and synchronizing the following:
- Configuration Overlay
- Secrets
- Identities
- Environmental Variables
Activate Project
Activate the project each time you use it. You'll need your passphrase to access your identity. For this session, however, it was preset.
. ./activate
You have sourced the environment and have new tools at your disposal, prefixed with mio-.
Deactivate Project
Always deactivate projects when you are finished with them. This will clear the passphrase and shut down the identity.
deactivate
6. Add Backup Controller#
You can skip this feature for the demo. However, you will need to come back. Promise us!
Since backups are essential for each instance, an automated management repository controller is necessary.
Currently, Mio uses a Hetzner-Storage-Box for its back end, with more on the way.
To get started, you'll need to complete a few manual tasks. These include creating a Hetzner account*, assigning a project, and ordering a Storage-Box. After that, the wizard will guide you through the final steps.
This boils down to:
- Go to your project at https://console.hetzner.com/.
- Create or Select a Storage-Box and enable SSH and EXTERNAL access!
- Extract and fill in following values:
BOXID(#Number)USER(uXXXXX)USER PASSWORD
- Two API tokens must be created. Follow the instructions to generate one.
- Create a
Security/API-TOKENwith WRITE permission- Name it:
<PROJECT> mio/ctl/backup/api - Copy and Paste the token
- Name it:
- Create a
Security/API-TOKENwith READ-ONLY permission- Name it:
<PROJECT> mio/ctl/backup/ro/api - Copy and Paste the token
- Name it:
- Create a
If needed, you can then use the new tool, mio-backupctl, to manage and maintain your Storage-Boxes.
Sharing Storage-Boxes
Although you can use one Storage-Box across different projects, it's best to create a separate API token for each project.
7. Configure Overlays#
The Configuration Overlay, which is located in the conf folder and exposed via ${MIO_OVERLAY}, forms the core of Mio.
Explore and modify its contents using the mio-files tool, your file browser, your editor or file system operations, such as cat, echo, cp, mv, and rm.
The process begins by refining the modules to be used. This occurs in the conf/mio.mk file.
mio.mk#
${MIO_OVERLAY}/mio.mk
Uncomment and adjust the necessary variables.
## Disable
# MODULES := $(filter-out backup msmtp domain sysstat, $(MODULES))
# TASKS := $(filter-out do-backup, $(TASKS))
## Pin
# SETUP := fixed setup based of MODULES and TASKS
## Inject custom modules
# SETUP_APPS := app app-service
# SETUP_APPS_POST := my-data
modules#
After selecting your modules, you can adjust their defaults and transfer ownership to the class or instance scope by managing conf/<MODULE>/files/ or conf/<MODULE>/files-<INSTANCE>/ folder, or both.
Use the mio-files command to find out which options are available and where they are located.
Set up the login shell for new accounts.
$ mio-files info accounts
LOGIN_SHELL=/usr/bin/bash # (mio) account login shell
SECONDARY_GROUPS=sshlogin # (mio) membership; comma separate
mkdir -p -- "${MIO_OVERLAY}/packages/files"
echo mksh > "${MIO_OVERLAY}/packages/files/sh.conf"
echo /usr/bin/mksh | mio-files set accounts LOGIN_SHELL
# or manually
mkdir -p -- "${MIO_OVERLAY}/accounts/files"
echo /usr/bin/mksh > "${MIO_OVERLAY}/accounts/files/LOGIN_SHELL"
$ mio-files info accounts
LOGIN_SHELL=/usr/bin/mksh # (conf) account login shell
SECONDARY_GROUPS=sshlogin # (mio) membership; comma separate
Apply the changes to the instance scope for miodocs.
echo /usr/bin/mksh | mio-files set accounts LOGIN_SHELL miodocs
# or manually
mkdir -p -- "${MIO_OVERLAY}/accounts/files-miodocs"
echo /usr/bin/mksh > "${MIO_OVERLAY}/accounts/files-miodocs/LOGIN_SHELL"
mio-mk-instance-links
8. Integrate Applications and Payloads#
Now, we're getting to the part you're most interested in: application integration! We will outline how to integrate an application that serves the project's README via HTTPS. The relevant parts of the code are numbered accordingly in the TL;DR demo section.
The goal is to package and install our application under a dedicated user account with minimal effort. Now, let's go through the steps.
8.1 Register App#
The system needs to be aware of all the modules that are going to be installed. This includes our application.
mkdir -p -- conf/app/files
cat <<"EOF" >> conf/mio.mk
SETUP_APPS := app
EOF
8.2 System Dependencies#
Our application depends on system packages, so we're going to pull them in.
mkdir -p -- conf/packages/files
echo python3-venv > conf/packages/files/app.conf
8.3 Prepare the Source#
Since we are assembling our application from scratch, we need to take additional steps. The main task is to produce a self-contained distribution folder/package, which we are going to use as the payload. You need to gather all the required components and artifacts, as well as the runtime dependencies for offline distribution. Most applications come with build or package tasks, or even ready-to-use distribution artifacts, which can serve as a starting point.
8.4 Create the Payload#
The payload is simply a GZIP-compressed TAR archive from the previous bundling step. We placed it in the files folder of the application configuration.
tar cvzf conf/app/files/app.tgz -C ~/docs .
8.5 Payload Installer#
The payload installer is a shell script executed from the root directory of the extracted payload. Its primary function is to install the application and prepare its content for operation.
8.6 Service File#
Since our application must survive reboots, we need to define a service unit file.
8.7 Configure Features#
The features are pulled in via Mio modules. Refer to the TL;DR example for details on the specific configurations.
General Module Configuration Guidance
- Activate the module by adding it to the mio.mk file, unless it is already listed as an installation target.
- Use the
mio-files info <MODULE>tool to look up module configuration defaults. - Use the
echo value | mio-files set <MODULE>orecho value | mio-files set <MODULE> <INSTANCE>tools to perform overwrites on a class or instance basis, or use Unix file system operations as needed. - Use the
mio-git commit -m 'feat: add <MODULE>'tool to commit your changes. - Use
mio-git push --alltool to push your changes. - Use
make <MODULE>to roll out the feature.
Module Template Files
Some modules come with additional files that are not yet shown by the mio-files tool. For now, you need to look them up in the module's documentation.
Ensure Production Safety
These configurations are for demonstration purposes only!
Additional hardening steps must be taken to ensure production safety.
8.7.1 Prometheus#
We use Prometheus to scrape our metrics. However, we need to adjust its availability due to its restrictive defaults.
8.7.2 Alertmanager#
We use Alertmanager to receive notifications about unusual events. Therefore, we have set up a dummy email account.
This is your first time setting up Secrets. First, we store the email account password in our secure mio-pass store and make it available across all instances as a shared secret. Then, we reference its location in a *.pass file. The automation pulls out the secret upon installation.
echo secret-passphrase | mio-pass insert -m instances/mail/default.pw
echo mail/default.pw > conf/alertmanager/files/mail.pw.pass
8.7.3 blackbox_exporter#
We use blackbox_exporter to probe our endpoints. First, we set up the module. Then, we configure it per instance, as detailed in Section [Add instances].
8.7.4 Domain#
We would like to proxy our services and make them available under a fully qualified domain name (FQDN) with certificates.
To accomplish this, we first configure the domain module on a class basis, then assign the {{FQDN}} variable on an instance basis, as detailed in Section [Add Instances].
8.7.5 MY-TRUST-SELF-SIG#
We integrate our own module into the toolkit that registers our self-signed certificates in the system's local certificate authority store. This is for demonstration purposes only. The procedure is as follows: module registration; script definition.
8.8 Commit Changes#
In order to persist and track our setup, we will commit and push all changes.
9. Add Instances#
There are a few steps required to add an instance to the project.
- Spawn and start your new host.
- Set up an SSH server and enable root access using your identity keys (
.ssh/id.pub).
Depending on your service provider or tooling, these steps may be combined into one. - Then, add the instance to your project using the wizard command below.
Once the action has been completed successfully, the wizard will provide guidance on how to configure your DNS infrastructure to make the instance accessible. Follow the instructions.mio-wizard add-instance <INSTANCE-NAME> - Any module requiring instance-based configuration must be configured for the specific instance.
- Fetch hostkeys from instance
ssh-keyscan -H -t ed25519 -4 "<FQDN>" | tee -a .ssh/known_hosts - If you have configured a backup controller, you can use this command to attach a backup repository to your instance:
mio-wizard add-instance-backup <INSTANCE-NAME>
Customize and automate it from the start to your liking!
Adding more instances will make this task repetitive. Therefore, it's wise to start with a scripted approach. This will serve as code-based documentation and quickly pay off by streamlining the process. Place your scripts in the bin folder within this workspace.
10. Roll out#
Hooray! We're leaving the wizard behind and rolling out your configuration.
The make install command applies the configuration to all instances.
For selective installations, specify the HOSTS variable to select the desired instances. Alternatively, you can install individual modules by name. All modules are designed to be run multiple times. Chaining is also supported.
Running Tasks on Individual Instances
make do-backup do-update do-cleanup HOSTS="miodocs"
Now, let's roll out all the configured modules. Let's do it all at once.
make install
Well Done! Let's review What You Received.