Asdqwe logo.

Asdqwe, software development focused in video games.

asdqwe@asdqwe.com

How to use debootstrap to create disposable environments

Before we start:

  1. $ means run as user.
  2. # means run as root.
  3. Unexpected things can happen. Always have/make backups.
  4. Always read/research the respective manual/documentation.
  5. Always double check your commands. Things like dd, cp, mv, rm, etc, can be VERY destructive.
  6. THIS GUIDE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THIS GUIDE OR THE USE OR OTHER DEALINGS IN THIS GUIDE.

Table of contents:

  1. Introduction
  2. Installing debootstrap
  3. Creating a build environment
  4. Accessing the build environment
  5. Exiting the build environment
  6. Removing the build environment
  7. Tips
  8. Scripts

1.Introduction:

I like keep Linux installations as minimal as possible, having only the packages and dependencies I'll actually use. I also like to recompile most programs to trim unneeded features or dependencies. That, more often than not, becomes a problem, since recompiling usually requires the installation of lots of development libraries and compiling dependencies which I'll probably never use again. Although those can be later removed, it's a pain to cleanup.

An interesting solution for this problem is creating a disposable environment and compiling software inside it. That way, it can hold all required compiling dependencies and not bloat the host system. When it's no longer needed, it can just be removed without bothering with any cleanup.

There are many ways to achieve this, but the one I find most convenient is using Debootstrap, which is a tool that allows to install Debian (or Ubuntu) on a given directory without the need to go through the regular installation process, which you can later access from your host Linux installation.

On this guide, lets go through the steps to: install debootstrap on Debian; install Debian on a given directory; mount and access it with chroot; exit and unmount it; remove the build environment; some tips; and some helpful shell scripts.

2.Installing debootstrap:

Start by installing debootstrap from the repositories:

  1. $ sudo apt-get update
  2. $ sudo apt-get install debootstrap

3.Creating a build environment:

Create a buildenv directory on your /mnt folder, where the disposable build environment will be installed:

  1. $ sudo mkdir /mnt/buildenv

Use deboostrap to download and install a Debian installation on that directory:

  1. $ sudo debootstrap --arch amd64 jessie /mnt/buildenv http://ftp.us.debian.org/debian/

Optional/recommended: add the deb-src repositories to the apt sources.list:

  1. $ echo "deb-src http://ftp.us.debian.org/debian/ jessie main" | sudo tee -a /mnt/buildenv/etc/apt/sources.list

4.Accessing the build environment:

To enter the build environment:

  1. $ sudo mount --bind /dev/ /mnt/buildenv/dev
  2. $ sudo mount -t proc none /mnt/buildenv/proc
  3. $ LANG=C.UTF-8 sudo chroot /mnt/buildenv /bin/bash

If you close the terminal window by accident while inside the build environment, you can return to it with:

  1. $ LANG=C.UTF-8 sudo chroot /mnt/buildenv /bin/bash

To access something inside your build environment from your host, just access the folder directly, e.g.:

  1. $ cp /mnt/buildenv/someFolder/someFile /home/username/
  2. $ sudo cp /home/username/otherFile /mnt/buildenv/someFolder/

5.Exiting the build environment:

First, inside the build environment:

  1. # exit

And then, on the host system:

  1. $ sudo umount /mnt/buildenv/proc/
  2. $ sudo umount /mnt/buildenv/dev/

6.Removing the build environment:

When you have finished everything and no longer need the build environment, you can just remove the buildenv folder (don't forget to exit the chroot and unmount it first):

  1. $ sudo rm -r /mnt/buildenv/

7.Tips:

The first time you enter the build environment do not forget to update your repositories:

  1. # apt-get update

8.Scripts:

If you'll be using this a lot, it may be helpful to create some shell scripts. These are some I assembled:

file: becreate · showselect all

  1. #!/bin/bash
  2. # A shell script to help creating build environments using debootstrap.
  3. # Usage: becreate distro version arch name
  4. # e.g.: becreate debian jessie amd64 buildenv
  5. # Function to check the distro and configure the mirror_url:
  6. function checkDistro {
  7. if [ $1 = "debian" ]; then
  8. mirror_url="http://ftp.us.debian.org/debian/"
  9. true
  10. elif [ $1 = "ubuntu" ]; then
  11. mirror_url="http://archive.ubuntu.com/ubuntu/"
  12. true
  13. else
  14. false
  15. fi
  16. }
  17. # Check if the required parameters were passed:
  18. if [ "$#" -eq 4 ]; then
  19. # If the required parameters were passed, continue.
  20. # Check if a directory with that name does not exists:
  21. if [ ! -d "/mnt/$4" ]; then
  22. # If a directory with that name does not exist, continue.
  23. # Check if the distro parameter is known:
  24. if checkDistro ${1,,}; then
  25. # If the distro parameter is known, continue.
  26. # Check if there is a script matching that version:
  27. if [ -f "/usr/share/debootstrap/scripts/${2,,}" ]; then
  28. # If there is a script matching that version, continue.
  29. # Since the directory does not exist, create it:
  30. sudo mkdir /mnt/$4
  31. echo -e "\n /mnt/$4 directory created.\n"
  32. # Issue the debootstrap command:
  33. sudo debootstrap --arch ${3,,} ${2,,} /mnt/$4 $mirror_url
  34. # Check if there's any error during the debootstrap process:
  35. if [ "$?" -eq 0 ]; then
  36. # If there're no errors during the debootstrap process, configure the sources.list:
  37. echo "deb-src $mirror_url ${2,,} main" | sudo tee -a /mnt/$4/etc/apt/sources.list
  38. echo -e "\n ${1,,} ${2,,} ${3,,} installed at /mnt/$4 .\n"
  39. else
  40. # If there're errors during the debootstrap process, return and error and exit.
  41. echo -e "\n Error: debootstrap failed. Aborted.\n"
  42. exit 1
  43. fi
  44. else
  45. # If there is no script matching that version, return and error and exit.
  46. echo -e "\n Error: unknown version. Aborted.\n"
  47. exit 1
  48. fi
  49. else
  50. # If the distro parameter is unknown, return an error and exit.
  51. echo -e "\n Error: unknown distro. Aborted.\n"
  52. exit 1
  53. fi
  54. else
  55. # If a directory with that name does exist, return an error and exit.
  56. echo -e "\n Error: directory with that name already exists. Aborted.\n"
  57. exit 1
  58. fi
  59. else
  60. # If there were more or less than four parameters, return an error, print an usage/help message and exit.
  61. echo -e "\n Error: missing parameters. Aborted.\n"
  62. echo -e " Usage: becreate distro version arch name"
  63. echo -e " e.g.: becreate debian jessie amd64 buildenv\n"
  64. exit 1
  65. fi

file: bestart · showselect all

  1. #!/bin/bash
  2. # A shell script to mount and access a build environment.
  3. # Usage: bestart name
  4. # e.g.: bestart buildenv
  5. # Check if the build environment name parameter was passed:
  6. if [ "$#" -eq 1 ]; then
  7. # If the build environment name parameter was passed, continue.
  8. # Check if a directory with that name exists:
  9. if [ -d "/mnt/$1" ]; then
  10. # If a directory with that name exists, continue.
  11. # Check if there's a chroot running for that directory:
  12. if ( ! ps a -o cmd | grep "chroot /mnt/$1" | grep -v "grep" > /dev/null ); then
  13. # If there's no chroot running for that directory, continue.
  14. # Check if there's any mountpoints:
  15. if ( ! mount | grep /mnt/$1 > /dev/null ); then
  16. # If there're no mountpoints, continue.
  17. # Mount the directory and chroot into it:
  18. sudo mount --bind /dev/ /mnt/$1/dev
  19. sudo mount -t proc none /mnt/$1/proc
  20. sudo LANG=C.UTF-8 chroot /mnt/$1 /bin/bash
  21. else
  22. # If there are mountpoints, return an error and exit.
  23. echo -e ""
  24. mount | grep /mnt/$1
  25. echo -e "\n Error: /mnt/$1 already mounted. Aborted.\n"
  26. exit 1
  27. fi
  28. else
  29. # If there's a chroot running for that directory, return an error and exit.
  30. echo -e "\n Error: chroot found at /mnt/$1. Exit it first. Aborted.\n"
  31. exit 1
  32. fi
  33. else
  34. # If a directory with that name does not exist, return an error and exit.
  35. echo -e "\n Error: directory $1 not found at /mnt/. Aborted.\n"
  36. exit 1
  37. fi
  38. else
  39. # If there was more or less than one parameter, return an error, print an usage/help message and exit.
  40. echo -e "\n Error: missing parameter. Aborted.\n"
  41. echo -e " Usage: bestart name"
  42. echo -e " e.g.: bestart buildenv\n"
  43. exit 1
  44. fi

file: bestop · showselect all

  1. #!/bin/bash
  2. # A shell script to unmount a build environment after you exit it.
  3. # Usage: bestop name
  4. # e.g.: bestop buildenv
  5. # Check if the directory parameter was passed:
  6. if [ "$#" -eq 1 ]; then
  7. # If the directory parameter was passed, continue.
  8. # Check if if a directory with that name exists:
  9. if [ -d "/mnt/$1" ]; then
  10. # If if a directory with that name exists, continue.
  11. # Check if there's a chroot running for that directory:
  12. if ( ! ps a -o cmd | grep "chroot /mnt/$1" | grep -v "grep" > /dev/null ); then
  13. # If there's no chroot running for that directory, continue.
  14. # Check if there's any mountpoints:
  15. if ( mount | grep /mnt/$1 > /dev/null ); then
  16. # If there's any mountpoint, continue.
  17. # Check if there's a dev mountpoint:
  18. if ( mount | grep /mnt/$1/dev > /dev/null ); then
  19. # If there's a dev mountpoint, continue.
  20. # Unmount it.
  21. sudo umount /mnt/$1/dev/
  22. # Return a message confirming what was unmounted.
  23. echo -e " /mnt/$1/dev/ unmounted."
  24. fi
  25. # Check if there's a proc mountpoint:
  26. if ( mount | grep /mnt/$1/proc > /dev/null ); then
  27. # If there's a proc mountpoint, continue.
  28. # Unmount it.
  29. sudo umount /mnt/$1/proc/
  30. # Return a message confirming what was unmounted.
  31. echo -e " /mnt/$1/proc/ unmounted."
  32. fi
  33. echo -e ""
  34. else
  35. # If there are no mountpoints, return an error and exit.
  36. echo -e "\n Error: there's nothing to unmount. Aborted.\n"
  37. exit 1
  38. fi
  39. else
  40. # If there's a chroot running for that directory, return an error and exit.
  41. echo -e "\n Error: chroot found at /mnt/$1. Exit it first. Aborted.\n"
  42. exit 1
  43. fi
  44. else
  45. # If if a directory with that name does not exist, return an error and exit.
  46. echo -e "\n Error: directory $1 not found at /mnt/. Aborted.\n"
  47. exit 1
  48. fi
  49. else
  50. # If there was more or less than one parameter, return an error, print an usage/help message and exit.
  51. echo -e "\n Error: missing parameter. Aborted.\n"
  52. echo -e " Usage: bestop name"
  53. echo -e " e.g.: bestop buildenv\n"
  54. exit 1
  55. fi

return