Tiny Core Linux – Shrink your Virtual Machines to nothing

Last weekend I decided to clean up my VmWare folder. As you may know I’m using a lot of virtual machines to teach IT-security to some students. There are “hackits” for SQL-Injection, Command-Injection, XSS, sniffing and so on. Each of this hackits life within their own virtual machine and consume disk space. A lot of disk space. Actually to much space for my laptop. On the other hand, most of them only have some basic services installed, like apache, bind, mysql, dhcpd and so on. Until now i’ve used the relatively slick debian distribution. As small as you can setup debian, it’s about 1 GiB in size. It actually doesn’t matter if you install one service or 10.

Then, some days ago, I’ve stumped across “Tiny Core Linux”. There exist two versions of it: one with a nice X-desktop and one with only the command line. But the greatest thing about it is that it only consumes <10MiB of space, it’s running completely from RAM and it’s fast as light!

At this point I’ve started about fascinating about how great this distribution would be for creating hackits. I could create hundreds of them and still using less disk space than one debian based installation. WOW!

 


 

So here we go… Enjoy this mini-HowTo…

 

Setup a basic Tiny Core Linux

What you need

All you need is to download the ISO for their website

I’ve choosen the microcore iso because I don’t use any GUI but it doesn’t matter if you take the other one. It’s all the same 🙂

Setting up the VMWare

  1. Create a new virtual machine
  2. Select the downloaded ISO as boot CDROM
  3. As operating system choose “Linux” / “Other Linux 2.6.x kernel”
  4. Select “Customize Settings” because we don’t need a hard drive of 8GiB 🙂
  5. Remove the existing 8GiB hard drive
  6. Add a new hard drive (make sure to select IDE and NOT SCSI, it wont get recognized by Tiny Core) with ~1GiB in size
  7. Boot!

Pepare the harddrive

After the boot we will be presented with a shell. Then go and find the harddisk with the command:

1
tc@box:~$ sudo fdisk -l

So /dev/hda is our hard disk. Lets make one big parition on it using fdisk.

Now we can format the disk. I’ve choose a ext4 filesystem. Then reboot.

1
2
sudo mkfs.ext4 /dev/hda1
sudo reboot

Define the “tce” drive

At the boot prompt (before the kernel gets loaded) you can define wich is your tce partition. You only have to do this once.

boot: microcore tce=hda1

This is where our changes to the live-system will get saved if we instruct TinyCore to do so.

Basic concepts of TinyCore



I could call TC is revolutionary simple and its the “revolutionary” part making it difficult to understand it, not the “simple” part 😉
Quote from Bloodhound in IRC #tinycorelinux@freenode


TinyCore / MicroCore Linux is different than other distributions.

  1. The whole system is loaded into RAM at boottime
  2. The system is reseted to it’s original state after every boot by default
  3. Theres actually no such thing like “installation” (at least it’s not recommendet)

If you want to read the whole story (and you really should) you’ll find it here: Core Concepts.

The “setup” we are having here is the following:

  • OS is booted from original CDROM-ISO
  • We keep track of changes we’d like to be persistent within a file (/opt/.filetool.lst)
  • Everytime we make persistent changes to our system we create a backup. So all files or directories we have defined within .filetool.lst will be saved to our disk and reapplied after reboot.

Important files

/opt/.filetool.lst

With this file you define what you would like to backup. Every directory path or file name you add to this file will get backed up (if you tell the system to do so) and gets restored after the reboot. All the data get stored on the tce-partition (/mnt/hda1/tce/mydata.tgz). The file looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
opt/bootlocal.sh
opt/bootsync.sh
opt/shutdown.sh
opt/tcemirror
opt/.filetool.lst
opt/.xfiletool.lst
home                    # everything within the /home partition
usr/local/etc/ssh       # this directory holds the sshd_config and the private/public key's so they don't gets recreated after every reboot
etc/passwd              # if you add a user this file needs to be saved
etc/group               # this is only important if you change / add groups
etc/shadow              # if you change a password or add a user you have to save this file
usr/local/apache2/conf  # this is used if you have apache2 installed to safe the apache configuration

The comments in the above file listing aren’t within the file! I don’t know if comments are allowed!

/opt/bootsync.sh

1
2
3
4
5
#!/bin/sh
# put other system startup commands here, the boot process will wait until they complete.
# Use bootlocal.sh for system startup commands that can run in the background
# and therefore not slow down the boot process.
/opt/bootlocal.sh &

/opt/bootlocal.sh

Within this shell file you write everything you would like to be executed during startup. This can be ip-configurations or the starting of daemons. The file looks basicaly like this:

1
2
3
#!/bin/sh
# put other system startup commands here
sudo /usr/local/etc/init.d/openssh start

/opt/shutdown.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh
# put user shutdown commands here

# If no backup of home was done then loop through valid users to clean up.
if [ ! -e /tmp/backup_done ] || ! grep -q "^home" /opt/.filetool.lst; then
  awk 'BEGIN { FS=":" }  $3 >= 1000 && $1 != "nobody" { print $1 }' /etc/passwd > /tmp/users
  while read U; do
    while read F; do
      TARGET="/home/${U}/$F"
      if [ -d "$TARGET" ]; then
        rm -rf "$TARGET"
      else
        if [ -f "$TARGET" ]; then
          rm -f "$TARGET"
        fi
      fi
    done < /opt/.xfiletool.lst      
  done < /tmp/users
fi

Structure of the tce partition

1
2
3
4
5
6
7
8
9
10
11
/mnt/hda1/.
    |-- lost+found
    `-- tce
        |-- mydata.tgz         # all data defined within /opt/.filetool.lst gets saved within this archive
        |-- onboot.lst         # this is the startup script responsible for booting daemons
        `-- optional           # here you will find all extension installed
            |-- apache2.tcz
            |-- apache2.tcz.dep
            |-- apache2.tcz.md5.txt
            .
            .  # more extensions...

Content of mydata.tgz

1
 

Install openssh-server

To install the openssh-server enter the folowing commands:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Install the server
tce-load -wi openssh

# Configure the server (you may edit/add security to the sshd_config file)
sudo cp /usr/local/etc/ssh/sshd_config.example /usr/local/etc/ssh/sshd_config

# Make the settings permanent (so you are able to reboot without destroying your config)
echo usr/local/etc/ssh >> /opt/.filetool.lst

# Enable the server at startup
echo sudo /usr/local/init.d/openssh start >> /opt/bootlocal.sh

# Change the password of tc and make sure to save the changes from now on
# and add /etc/passwd, /etc/groups and /etc/shadow to backup-list
sudo passwd tc
echo etc/passwd >> /opt/.filetool.lst
echo etc/group >> /opt/.filetool.lst
echo etc/shadow >> /opt/.filetool.lst

# Save the configuration permanently within mydata.tgz
filetool.sh -b -p

Install apache2

1
2
3
4
5
6
7
8
9
# Install apache and some missing dependencies
tce-load -wi ncurses
tce-load -wi apache2

# Make sure it loads after reboot
echo sudo apachectl start >> /opt/bootlocal.sh

# Make shure that the config gets backed-up
echo usr/local/apache2/conf >> /opt/.filetool.lst

By default apache is running as user nobody which and group stuff. I prefere apache to run as user apache and group apache. Therefore we have to create the corresponding user and groups.

1
2
3
4
5
6
7
# Add a system group for our apache daemon
sudo addgroup -g 500 apache
     
# Add user with it's home /home/apache, no shell, no password and a userid
# 500 and member of the apache group. This will also create the directory
# /home/apache for you.
sudo adduser -h /home/apache -s /bin/false -D -u 500 -G apache apache

Also I prefer having the webroot directory within apache’s home directory

1
2
3
# Now create some more directories
mkdir /home/apache/cgi-bin
mkdir /home/apache/htdocs

To reflect this changes we have to modify some entries in /usr/local/apache2/conf/httpd.conf

  • User apache
  • Group apache
  • DocumentRoot “/home/apache/htdocs”
  • ScriptAlias /cgi-bin/ “/home/apache/cgi-bin/”

Afterward it’s time to backup

1
filetool.sh -b -p

Creating extension packages

Even if the repository of TinyCore extensions is huge, now and then rise the need of installing some software which isn’t in the repository already. In this section we will look at the process of creating a extension from source-tarball.

The official guide can be found here.

Basic package concept

A package consist of several files. These are:

  • [package].tcz – This is the actual package with its binaries, libraries and configfiles
  • [package].tcz.md5.txt – This file contains the md5-sum of the [package].tcz. It is generated by md5sum [package].tcz > [package].tcz.md5.txt
  • [package].tcz.list – This file contains a listing of all files contained in [package].tcz
  • [package].tcz.info – This file contains a description of the package (Version, License, Developer, Packager,Pourpose of the software…)
  • [package].tcz.dep – This file contains the list of prerequisit software packages (dependencies) which have to be installed to use the package.
  • [package].tcz.build-dep – This file documents the package build process (Compiler-Flags, Applied patches…)
  • [package].tar.gz – This is the actual sourcecode used to build the software

Note that not all of these files are mandatory.

The easiest way to understand the process of building extensions is to do it. So here’s an example:

Building CLISH (CommandLineSHell)

CLISH is a modular framework for implementing a CISCO-like CLI on a *NIX system. Arbitary command menus and actions can be defined using XML files. This software handles the user interaction, and forks the appropriate system commands to perform any actions.

Create the build environment

For my build environment I’ve copied my virtual machine with mircocore + ssh. Than you have to install some package to get the compiler, libraries and tools.

1
2
tce-load -wi compiletc
tce-load -wi squashfs-tools

Get the software source

Download the software you’ll like to compile. In our case this is CLISH from http://clish.sourceforge.net/. Then you have to extract the source. This is everithing done as the tc user.

1
2
3
4
wget 'http://prdownloads.sourceforge.net/clish/clish-0.7.3.tar.gz?download'
mv clish-0.7.3.tar.gz?download clish-0.7.3.tar.gz
tar xvfz clish-0.7.3.tar.gz
cd clish-0.7.3/

Build the software

According to the official “creating extension manual” the following compiler flags are recommendet for compatibility:

1
2
3
export CFLAGS="-march=i486 -mtune=i686 -Os -pipe"
export CXXFLAGS="-march=i486 -mtune=i686 -Os -pipe"
export LDFLAGS="-Wl,-O1"

Then compile the software as usual (read README, INSTALL… contained in the source tar-ball). In our example CLISH doesn’t reflect the option “–sysconfdir” correctly. If we define –prefix=/usr/local then the configuration directory should be /usr/local/etc/clish but its /etc/clish. So we have to modify the source code within the file clish/shell/shell_spawn.c. To create a patch we copy the folder clish-0.7.3 to clish-0.7.3.work and modify the the folowing line within clish/shell/shell_spawn.c:

1
const char *default_path = "/etc/clish;~/.clish";

Then we create the patch with:

1
 diff -Naur clish-0.7.3 clish-0.7.3.work > clish-0.7.3.sysconfdir.patch

This will result in a patch with the folowing content:

1
2
3
4
5
6
7
8
9
10
11
12
diff -Naur clish-0.7.3/clish/shell/shell_spawn.c clish-0.7.3.work/clish/shell/shell_spawn.c
--- clish-0.7.3/clish/shell/shell_spawn.c   2008-03-07 08:42:59.000000000 +0000
+++ clish-0.7.3.work/clish/shell/shell_spawn.c  2011-04-16 18:10:37.402454276 +0000
@@ -16,7 +16,7 @@
 /*
  * if CLISH_PATH is unset in the environment then this is the value used.
  */
-const char *default_path = "/etc/clish;~/.clish";
+const char *default_path = "/usr/local/etc/clish;~/.clish";
 
 /*-------------------------------------------------------- */
 /*

Now we can apply the patch to the original source code with:

1
patch -p0 < clish-0.7.3.patch

… and build the software:

1
2
3
4
5
cd clish-0.7.3
./configure --prefix=/usr/local
make
touch /tmp/mark
make DESTDIR=/tmp/package install

This should build and install the software under /tmp/package. Next we are populate /usr/local/etc/clish/ with some default configuration files…

1
2
mkdir -p /tmp/package/usr/local/etc/clish
cp xml-examples/* /tmp/package/usr/local/etc/clish/

… and we are ready to create the extension-package.

Creating the package

First we are going to cleanup the /tmp/package directorie a bit. We are stripping binaries, removing documentation (if there’s any), if there are a lot of development files move them to a dedicated [package]-dev package and so on.

1
2
3
cd /tmp/package
find . | xargs file | grep "executable" | grep ELF | grep "not stripped" | cut -f 1 -d : | xargs strip --strip-unneeded
find . | xargs file | grep "shared object" | grep "not stripped" | cut -f 1 -d : | xargs strip -g

then we are creating a listing of all files which gets installed if you apply this package

1
find usr -not -type d > ../clish.tcz.list

This create our first mandatory file: the listing of all files wich get installed when we apply the package!

then we create the package itself

1
2
3
cd /tmp
mksquashfs package clish.tcz
md5sum clish.tcz > clish.tcz.md5.txt

Two more mandatory files of our package: the software itself and a md5 sum of it saved in a seperate file.

But there are still some files missing. Since clish doesn’t have any dependencies to other packages we don’t have to create the file clish.tcz.dep. But if it would then this file is pretty easy to create. It just lists all packages wich have to be installed prior our package. Here is a example of the .dep file of apache2:

1
2
3
apr-util.tcz
openssl-0.9.8.tcz
pcre.tcz

If you are following this mini-HowTo you may have noticed, that there’s one dependency missing: ncurses.tcz 🙂

Theres still some files missing: clish.tcz.info and clish.tcz.build-dep. So lets create clish.tcz.info first:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Title:          clish.tcz
Description:    Modular CISCO-like CLI for tinycore
Version:        0.7.3
Author:         Graeme McKerrell
Original-site:  http://clish.sourceforge.net/
Copying-policy: GPL
Size:           240.0K
Extension_by:   <your name>
Comments:       Clish is a modular framework for implementing a CISCO-like
        CLI on a *NIX system. Arbitary command menus and actions
        can be defined using XML files. This software handles the
        user interaction, and forks the appropriate system commands
        to perform any actions.
        This extension is PPI compatible.
                ----------
                Change-log:     2011/04/16 First version

and the clish.tcz.build-dep. Here you write down how you have build your package. Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
wget 'http://prdownloads.sourceforge.net/clish/clish-0.7.3.tar.gz?download'
mv clish-0.7.3.tar.gz?download clish-0.7.3.tar.gz
tar xvfz clish-0.7.3.tar.gz
cd clish-0.7.3/
export CFLAGS="-march=i486 -mtune=i686 -Os -pipe"
export CXXFLAGS="-march=i486 -mtune=i686 -Os -pipe"
export LDFLAGS="-Wl,-O1"

--- patch ---
vi clish/shell/shell_spawn.c
const char *default_path = "/usr/local/etc/clish;~/.clish";
--- patch ---

./configure --prefix=/usr/local --sysconfdir=/usr/local/etc
make
touch /tmp/mark
make DESTDIR=/tmp/package install

mkdir -p /tmp/package/usr/local/etc/clish
cp xml-examples/* /tmp/package/usr/local/etc/clish/

cd /tmp/package
find . | xargs file | grep "executable" | grep ELF | grep "not stripped" | cut -f 1 -d : | xargs strip --strip-unneeded
find . | xargs file | grep "shared object" | grep "not stripped" | cut -f 1 -d : | xargs strip -g
find usr -not -type d > ../clish.tcz.list

cd /tmp
mksquashfs package clish.tcz
md5sum clish.tcz > clish.tcz.md5.txt

Now we have the following files:

  • clish.tcz
  • clish.tcz.md5.txt
  • clish.tcz.list
  • clish.tcz.info
  • clish.tcz.build-dep
  • clish-0.7.3.tar.gz
  • clish-0.7.3.sysconfdir.patch

save your files to a save directory, and install it with:

1
tce-load -i clish.tcz

Important: Test your package! If you would like to contribute to the project there seems some more hurdles to take. Please refer to the official documentation here.

This entry was posted in Tiny Core Linux, VMware. Bookmark the permalink.

One Response to Tiny Core Linux – Shrink your Virtual Machines to nothing

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.