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!
Contents
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
- Create a new virtual machine
- Select the downloaded ISO as boot CDROM
- As operating system choose “Linux” / “Other Linux 2.6.x kernel”
- Select “Customize Settings” because we don’t need a hard drive of 8GiB 🙂
- Remove the existing 8GiB hard drive
- Add a new hard drive (make sure to select IDE and NOT SCSI, it wont get recognized by Tiny Core) with ~1GiB in size
- 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.
- The whole system is loaded into RAM at boottime
- The system is reseted to it’s original state after every boot by default
- 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
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.
One Response to Tiny Core Linux – Shrink your Virtual Machines to nothing