Self-extracting Config Files with makeself

Have you ever had the problem of installing a new Linux distro and scping your config files to the home directory? Window/Desktop manager configs, .vimrc, .bashrc/.zshrc, and others. This problem is compounded with installations to multiple virtual machines, raspberry pis, etc. Luckily, there is a very handy tool that can make this process much easier and get your system up and running!

I recently found a tool called makeself while looking for an easy way to install patch files for my work. Makeself is an easy way to create self-extracting archives. Projects such as VirtualBox, Loki Software, and the Linux installer for Google Earth all use makeself to install their software. In this tutorial I’ll show you how to use makeself and a little bit of shell scripting to create an installer for your config files. This way, all you’ll need is one file that will extract the config files to the home directory. And best of all, this is very customizable. Use this tutorial as a starting point and build your install script however you’d like!

 

Setup


The first thing we’ll need to do is install makeself. There’s a package available on Ubuntu and the AUR for Arch. If you aren’t able to find the makeself package, it can also be pulled from GitHub at https://github.com/megastep/makeself. Here are the options depending on your situation:

# Ubuntu package
sudo apt-get install makeself
# AUR
pacaur -S makeself
# Pull from GitHub. git required.
git clone https://github.com/megastep/makeself

 

Collect config files


Next, let’s create a temporary directory that we will copy our config files to. This directory will mock our current $HOME directory in the way we organize the files. This will be important when we extract these files on the next Linux system.

# Go to your home directory
cd ~/

# Create a directory for the config files. 
mkdir config_files

# Copy your config files to the config_files/ directory.
cp .vimrc .bashrc .zshrc .xinitrc .toprc .tmux.conf config_files/

# If you have files in .config/, like an i3 config for example,
# make the directories before copying over the files to keep
# the same structure. The -p will create all parent directories
# if needed.
mkdir -p config_files/.config/i3
cp .config/i3/config config_files/.config/i3

# ... same for if you have a .vim directory. Use -r to recursively
# copy all files.
mkdir -p config_files/.vim/bundle
cp -r .vim/bundle/Vundle.vim config_files/.vim/bundle/

At this point, all config files should be in config_files/.

 

Create the “payload”


We will now “tar” the config files. If you’re not familiar with the tool tar, it is an archiving utility like what .zip files are. This archive will be the payload that we will extract onto our next system. Since this payload will be extracted on top of the home directory, it needs to be structured similar to our home directory.

tar -cvf payload.tar -C config_files/ .

If you’re not familiar with some of the flags, lets break them down.

-cvf This creates the archive, prints verbose output and the desired filename of the archive.

-C This changes the current directory to be config_files/

. This period is not a mistake. Once we change directory into config_files/, we want to archive everything in that directory. The . tells tar ‘this directory’.

We won’t add any compression flags since makeself takes care of compression when we package this all up in a later step.

 

Create staging directory


Next, we will create the directory that will hold our payload and install script. This is the directory that we’ll pass to makeself to compress and make executable.

# Be sure to be in your home directory
mkdir config_stage

# Copy the payload to this directory
cp payload.tar config_stage/

# Create an empty file that will be our install script
touch config_stage/install.sh

# And modify the file to be executable
chmod +x config_stage/install.sh

 

Write install script


This install script will extract the payload.tar into the target’s home directory. It will be a very simple one line script. Depending on your use case, this script can be modified to fit your needs. It also doesn’t need to be a bash script. It could be a python script or even a rust binary; makeself doesn’t care as long as its executable and can be ran on the target system. But for simplicity, I will be writing it in bash.

config_stage/install.sh

#!/bin/bash

tar -xvf ./payload.tar -C "$HOME" &&
echo "Config files extracted successfully!"

The script will be written as if you are inside this staging directory.

Lets also go over that tar command:

-xvf This x‘tracts the archive, with verbose output, for the file ./payload.tar

-C Again, this will set the current directory for tar to be the home directory.

$HOME This is an environment variable that stores the path of the currently logged in user’s home directory. For example: for the user bob, the $HOME directory would be /home/bob/.

&& This is to make sure that if the tar command fails, all commands following will not be executed. This is very handy if the next commands require the command before it to succeed.

And thats, it! We are ready to use makeself to create our self-executing archive!

 

Run makeself


Now we will run makeself against our config_stage/ directory. If you had pulled the GitHub version, change makeself to the path to makeself.sh in the git directory (ex: makeself/makeself.sh)

makeself --sha256 ./config_stage  my-configs-installer.run "My config files installer" ./install.sh

Here’s an breakdown of the command:
--sha256 This tells makeself to add a sha256 hash of the contents to its integrity check. Integrity checking is very important because we don’t want to have any corrupted files. If there is a problem transferring to another system and a part of the file failed to be sent, makeself will make sure to check and let you know.

./config_stage is this directory to archive that will be extracted to a temporary directory on the system.

my-configs-installer.run is the name of the executable that makeself will create. This can be any name you’d like.

"My config files installer" This is the label for the executable. It also can be anything you’d like.

./install.sh This is the install script we wrote to be executed after the config_stage/ is extracted to a temporary directory. We wrote this with a ./ as if we were in the config_stage/ directory.

The output should be similar to this and a new file my-configs-installer.run will be in your home directory!

Header is 588 lines long

About to compress 4460 KB of data...
Adding files to archive named "my-configs-installer.run"...
./
./payload.tar
./install.sh
CRC: 2272251193
SHA256: 710b5c0e2b9c6b3b6bcd42274427ac47487f98afab088626eb472c72bd37e778
MD5: 03c9bde4560f41d7de3cd0237fd0d38c

Self-extractable archive "my-configs-installer.run" successfully created.

 

Executing on target system


When executed on the target system (by entering ./my-configs-installer.run), it will first extract config_stage/ to a temporary directory in /tmp/. Then it will run the ./install.sh that will extract payload.tar to the home directory. Once the script has finished, everything in the temporary directory will be deleted. Its that simple!

This executable file can be sent to any system you’d like to install your config files to. But the great thing is, its potential is endless. If there are other things that you do repetitively when setting up a new system, you can just add it to the install.sh script! No more having to do all of it by hand!

Makeself has more features that you might have fun playing with. To learn more you can just run makeself --help.



 

Other helpful commands


The executable comes with a few helpful commands built in automatically. Here’s a few command examples:

–help

Makeself version 2.4.0
 1) Getting help or info about ./my-configs-installer.run :
  ./my-configs-installer.run --help   Print this message
  ./my-configs-installer.run --info   Print embedded info : title, default target directory, embedded script ...
  ./my-configs-installer.run --lsm    Print embedded lsm entry (or no LSM)
  ./my-configs-installer.run --list   Print the list of files in the archive
  ./my-configs-installer.run --check  Checks integrity of the archive

 2) Running ./my-configs-installer.run :
  ./my-configs-installer.run [options] [--] [additional arguments to embedded script]
  with following options (in that order)
  --confirm             Ask before running embedded script
  --quiet       Do not print anything except error messages
  --accept              Accept the license
  --noexec              Do not run embedded script
  --keep                Do not erase target directory after running
            the embedded script
  --noprogress          Do not show the progress during the decompression
  --nox11               Do not spawn an xterm
  --nochown             Do not give the extracted files to the current user
  --nodiskspace         Do not check for available disk space
  --target dir          Extract directly to a target directory (absolute or relative)
                        This directory may undergo recursive chown (see --nochown).
  --tar arg1 [arg2 ...] Access the contents of the archive through the tar command
  --                    Following arguments will be passed to the embedded script

–check

Verifying archive integrity...  100%   SHA256 checksums are OK.  100%   MD5 checksums are OK. All good.

–info

Identification: My config files installer
Target directory: config_stage
Uncompressed size: 4460 KB
Compression: gzip
Date of packaging: Sun Sep 2 22:25:03 PDT 2018
Built with Makeself version 2.4.0 on linux-gnu
Build command was: /usr/bin/makeself 
    "--sha256" 
    "./config_stage" 
    "my-configs-installer.run" 
    "My configs installer" 
    "./install.sh"
Script run after extraction:
     ./install.sh
config_stage will be removed after extraction
Loading Likes...

3 thoughts on “Self-extracting Config Files with makeself”

  1. This guide helped me. I have implemented the sequence of steps in a script that allows you to easily manage the whole process. github.com/FabrizioCafolla/self-extractable-archives-linux

Leave a Reply

Your email address will not be published. Required fields are marked *