1

I am interested in building my own custom Ubuntu remix, and have been doing so with the Ubuntu Mini Remix ISO.

To do this, I mount the disk image and chroot into it, in a manner similar to this guide.

My directory hierarchy for my builds is as such:

home
  |
  \builds
     |
     +build(n)
     |  |
     |  +mnt
     |  +extract-cd
     |  +edit
     |  \&
     |
     +build(n+1)
     |  |
     |  \&
     |
     \sources (various debfiles/ISOs)

Each build has $HOME set to ./edit/root, so anything higher up the hierarchy (./mnt, ./extract-cd, etc.) is inaccesible to the chroot environment.

Is there a way for the packages downloaded by the chroot's apt to be mirrored to a, for example, ~/builds/cache (or, even better, ~/builds/cache/[ubuntu-version]) directory, which could then be used as a repository for other builds?

Such a setup would save me a lot of bandwidth, since only packages which hadn't yet been downloaded/mirrored to the repository would need to be pulled from the web.

Anyway, thanks beforehand for any suggestions/helps.

Snyper
  • 106

3 Answers3

1

One strategy that might work would be to mount (with the --bind option) a common folder to the chroot's package cache. This cache is located at /var/cache/apt/archives/

Using this method would make it so that any command run by apt will operate with the common local archive.

Examples

Having two chroot's share a common apt archive

sudo mount --bind ~/builds/cache <chroot location>/var/cache/apt/archives
sudo mount --bind ~/builds/cache <another chroot location>/var/cache/apt/archives

That would make ~/builds/cache and both chroot's apt archive operating against the same directory.

Havind two chroot's share the local install's archive

sudo mount --bind /var/cache/apt/archives <chroot location>/var/cache/apt/archives
sudo mount --bind /var/cache/apt/archives <another chroot location>/var/cache/apt/archives

Similar to the first one, but now the main install and both chroots will use the same apt archive, ie, apt in all three will look in the same place for downloaded .deb files.

(I thought packages don't directly care about the ubuntu release, just the versions of associated packages. So you may not need to worry about separate folders for each release, and you could even possibly use the local install's package archive.)

Cleaning up

Lastly, and importantly, in the section about cleaning up the chroot in preparation for the final build, you don't want to run apt clean. Since apt is now using the same folder across all chroots setup this way, apt clean will essentially clear the archive for all chroots at once. Instead, within the chroot, run:

umount /var/cache/apt/archives

This will effectively "apt clean" the archive from just the chroot where the command is run, while leaving the common folder untouched.

Bind mounts manual info

The following is a straight copy from the man mount page. Please take a look at it for full explanation of mount --bind, and possibly to see other ways of using bind.

The bind mounts.
          Since  Linux  2.4.0  it  is possible to remount part of the file
          hierarchy somewhere else.  The call is:

                 mount --bind olddir newdir

          or by using this fstab entry:

                 /olddir /newdir none bind

          After this call the same contents are accessible in two  places.
          One  can  also  remount  a single file (on a single file).  It's
          also possible to use the bind mount to create a mountpoint  from
          a regular directory, for example:

                 mount --bind foo foo

          The bind mount call attaches only (part of) a single filesystem,
          not possible submounts.  The  entire  file  hierarchy  including
          submounts is attached a second place by using:

                 mount --rbind olddir newdir

          Note  that  the filesystem mount options will remain the same as
          those on the original mount point,  and  cannot  be  changed  by
          passing  the  -o  option  along  with --bind/--rbind.  The mount
          options can be changed by a separate remount command, for  exam‐
          ple:

                 mount --bind olddir newdir
                 mount -o remount,ro newdir

          Note  that  the behavior of the remount operation depends on the
          /etc/mtab file.  The first command stores the 'bind' flag in the
          /etc/mtab  file  and  the second command reads the flag from the
          file.  If you have a system without the /etc/mtab file or if you
          explicitly  define  source  and  target  for the remount command
          (then mount(8) does not read /etc/mtab), then you  have  to  use
          the  bind  flag  (or  option)  for the remount command too.  For
          example:

                 mount --bind olddir newdir
                 mount -o remount,ro,bind olddir newdir

          Note that remount,ro,bind will  create  a  read-only  mountpoint
          (VFS  entry),  but the original filesystem superblock will still
          be writable, meaning that the olddir will be writable,  but  the
          newdir will be read-only.
user7134
  • 459
  • Thanks for the answer, but this is only half of what I wanted. How would I use the ~/builds/cache directory as a repository for further builds? And would there have to be two copies, one mounted in /var/cache/apt/archives, and one functioning as a repo, or would it be possible for the chroot's local repository to also be mounted at /var/cache/apt/archives at the same time? – Snyper Nov 20 '14 at 01:55
  • I will edit the answer with the man page info on --bind. It is important that you understand what that mount command is doing. It makes the two directories into a single directory at two locations. So, to reuse, you just use a similar mount command. I will edit the answer to see if I can clarify. – user7134 Nov 20 '14 at 21:33
  • Thanks. As I said to BostonHiker, it may not be until tonight that I can try these answers. – Snyper Nov 20 '14 at 22:23
1

I have never used the Ubuntu Mini Remix ISO, but there are a few ways that I have used to accomplish this when running vmbuilder builds:

  1. Install apt-cacher-ng on your system (or a server on your local network) and use it as a proxy for your builds. This creates a local cache of the packages that are used during the build. Thus, after the first build, you will hit cache for any package that has been used before and doesn't have a newer version upstream. It still requires a network connection, because it communicates with the upstream repositories to get newer versions or packages that you have not used yet. The second benefit is that it caches only the necessary files, which is significantly less than a full blown mirror.

EDIT: apt-cahcer-ng itself does not need to be configured in any way - just install it using sudo apt-get install apt-cacher-ng. There are some advanced config options that I have never needed. You can find instructions how to configure your clients (builds) to use the cache here.

  1. You can use debmirror or apt-mirror to create a full mirror. But be aware that this usually takes a few hundred gigabytes disk space, depending on which repositories you chose to mirror (main, restricted, universe, multiverse) and so on. As well, it usually takes significantly longer to mirror (hundreds of gigabytes). And also you have to have cron job to update it or update it manually when you need. The lack of automatic update can be viewed both as a benefit (I have seen cases when bad packages were published upstream and took a few days to replace them with good ones) or a drawback (you do not have the latest security patches).
  • Mirroring the repository entirely is out of the option. Could you provide a more specific answer relating to apt-cacher-ng, showing exactly how I could set up the type of implementation you describe? – Snyper Nov 20 '14 at 01:56
  • I have updated the answer to reflect the usage of apt-cacher-ng. – BostonHiker Nov 20 '14 at 04:56
  • Edit: I might only have the time to try this tonight. I know the bounty time is running down, and for that I am sorry, but I want to be sure that this works. – Snyper Nov 20 '14 at 20:02
  • Not interested in the bounty that much :-), so no worries there. – BostonHiker Nov 20 '14 at 21:57
  • I couldn't get apt-cacher-ng to work for me. Sorry. – Snyper Nov 21 '14 at 14:38
0

I ended up using user7134's answer, along with some information from here.

Since his answer didn't fully fulfill what I had in mind, I'm writing my own answer. Nevertheless, I'm giving him the bounty, since it pointed me towards the right path.

The way to solve the problem is this: after cd-ing to the build(n) directory, before chrooting into the build, run

`sudo mount --bind /home/[username]/builds/cache edit/var/cache/apt/archives`

This will effectively cache the packages that the chrooted build downloads.

Proceed with the build as normal. There is no need, yet, to make our repo, as there would be nothing in it.

Once finished with the build, when unmounting things and cleaning the chroot, type

umount /var/cache/apt/archives

We can then make the repo to use in future builds.

To do so, create the file repobuild.sh, which will look like this:

#! /bin/bash
cd /home/[username]/builds/cache
dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz

Make our script executable by running chmod u+x /home/[username]/repobuild.sh and run the script: /home/[username]/repobuild.sh

Go about preparing to chroot into the new build, making sure to mount /home/[username]/builds/cache in edit/var/cache/apt/archives as shown above.

Chroot into edit and then add

deb file:/var/cache/apt/archives ./

to /etc/apt/sources.list

Run apt-get update, and you are done. Now you can use the cached packages by typing apt-get install [packagename], like you would normally.

Keep in mind that every time a package is added to the cache directory, repobuild.sh will have to be re-run if you want to use the cached package.

Snyper
  • 106
  • Are you sure you need the repository part? I thought apt automatically checked it's local repository for a .deb. If you tried to install stuff and it didn't work, maybe you hadn't run apt-get update yet. – user7134 Nov 21 '14 at 19:17
  • Tried it a couple of times with different debs. It was a no-go. IDK. The repo method works, so I'll just use it, I guess. – Snyper Nov 21 '14 at 21:40