Announcement

Collapse
No announcement yet.

Converting a root BTRFS install to a subvolume install in 4 easy steps

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Converting a root BTRFS install to a subvolume install in 4 easy steps

    This How To will guide you to having an Ubuntu install with the default subvolumes of @ and @home as previous Ubuntu installs had.

    I recently learned that the Ubuntu 24.04 installer no longer uses subvolumes when selecting BTRFS as a file system. IMO, there's very little point to using BTRFS without subvolumes.

    Subvolumes allow you to separate parts of your installation which can make snapshots and backups easier and quicker (smaller) and use tools like "timeshift" or "snapper". Subvolumes are like separate partitions but have the ability to expand or contract in size as needed because, unlike partitions, subvolumes freely share all the available space of your file system. You can also use subvolumes to boot multiple distros from the same BTRFS file system. I have 5 distros installed to the same file system.

    After initial install, you have / with the entirety of Ubuntu installed to the root BTRFS file system. This How To will convert your install into a subvolume installation as Ubuntu used in the past. This will allow the use of Timeshift and Snapper and make root and home snapshots and backups easier.

    Bonus: Convert EXT4 to BTRFS, then follow this guide.

    Although it's technically "no longer supported", the "btrfs-convert" tool still works to convert EXT4 to BTRFS. Historically, one of the complaints about this tool was that if left you with a root install (no subvolumes) like the latest Ubuntu does. To move from EXT4 to BTRFS, the steps are:
    1. Run btrfs-convert on your EXT4 root file system.
    2. Edit /etc/fstab to reflect the change from ext4 to btrfs.
    3. Reboot.
    Once you have a booting BTRFS installation, follow the guide below to move to subvolumes.

    General Warning: Anytime you are messing with file systems or partitions, etc., you risk losing data or crashing your install. Make sure you have a usable backup of anything you don't want to risk losing. This How To has been tested and written based on a new installation but if you are using an existing install that you have modified, you'd better have a backup before proceeding.

    Notes:
    This How To was done on a non-UEFI install. If you are an UEFI expert please chime in on what other steps might be necessary.
    To complete this successfully you must know the device name where you installed grub.
    For the purposes of this How To, I will use "/dev/sda/" but your installation will likely be different.
    If you are NOT SURE which drive GRUB is installed to,​ DO NOT proceed until you do.

    STEP 1: Create the @ and @home subvolumes and make it bootable.

    While running from Ubuntu using Terminal:
    Code:
    sudo btrfs subvolume snapshot / /@
    Create the @home subvolume:
    Code:
    sudo btrfs subvolume create /@home
    Make the @ subvolume bootable by editing /etc/grub inside the @ snapshot:
    Code:
    sudo nano /@/etc/fstab
    Edit the root entry from this :
    Code:
    /dev/disk/by-uuid/<UUID> / btrfs defaults 0 1
    to this:
    Code:
    /dev/disk/by-uuid/<UUID> / btrfs subvol=@,defaults 0 1
    Add a new line exactly the same as the above, but change the mount point and subvolume names for home:
    Code:
    /dev/disk/by-uuid/<UUID> /home btrfs subvol=@home,defaults 0 1
    Copy the contents of the /home folder from @ into the home subvolume:
    Code:
    sudo mv /@/home/* /@home/
    You now have the two needed subvolumes.

    STEP 2: Boot to the root subvolume

    To expose the GRUB menu to make booting to the subvolume easier, edit /etc/default/grub;
    Code:
    sudo nano /etc/default/grub
    and change:
    Code:
    GRUB_TIMEOUT_STYLE=hidden
    GRUB_TIMEOUT=0
    to
    Code:
    GRUB_TIMEOUT_STYLE=menu
    GRUB_TIMEOUT=10
    Then update grub to use your edits:
    Code:
    sudo update-grub
    If you're comfortable activating the GRUB menu without this edit, feel free to skip the above part.

    Reboot.

    When the GRUB menu appears, press the "e" key to edit the GRUB menu.
    At the line that begins with "linux" add the subvolume name so it looks like this:
    Code:
    linux /@/boot/...
    and near the end of that line, put this between "ro" and "quiet splash"
    Code:
    rootflags=subvol=@
    so it looks like this:
    Code:
    ro rootflags=subvol=@ quiet splash
    It doesn't actually have to be between them. It just has to be after the kernel version "root=UUID=..." part.

    Edit the line that begins with "initrd" the same way we did the "linux" line at the beginning:
    Code:
    initrd /@/boot/...
    and press F10 to boot.

    If you did everything right, it should immediately boot to your install from the subvolume. If not, reboot and start over at "Reboot" above.

    STEP 3: Verify you are running from the subvolume and update grub:

    To verify this worked, open Terminal again and enter:
    Code:
    mount |grep ' / '
    The output should look like:
    Code:
    /dev/sda2 on / type btrfs (...subvol=/@...)
    There will be more options inside the parenthesis but this is the only one that matters.

    If you see this, you have booted successfully into the subvolume!

    The final task is to update and re-install GRUB so the subvolume is the default boot from now on.

    Code:
    sudo update-grub
    sudo grub-install /dev/sda
    reboot
    Note that since we edited /etc/default/grub AFTER we took our snapshot, GRUB will hide the boot menu on reboot as before.

    If you'd like, go through the above "verify" step again before preceding with the clean up. Do it now.

    STEP 4: Clean up the old install files to reclaim space.

    First, we must mount the root file system:
    Code:
    sudo mount /dev/sda2 /mnt
    cd /mnt
    ll
    Do the "ll" to verify you're on in the root file system. You will see what looks like your install but you will also see your subvolumes in the output:
    Code:
    ...
    '@'/
    '@home'
    bin
    ...
    Now delete everything except '@' and '@home' :
    Code:
    shopt -s extglob
    sudo rm -rf !(@*)
    shopt -u extglob
    Now you may resume use of the system with your install inside a subvolume.

    Remember you must mount the root file system to have access to it to add more subvolumes.

    Last edited by oshunluvr; Yesterday, 11:03 AM.

    Please Read Me

    #2
    I remember back on 22.04 you could edit some of the config files before you started the install script. Is that method not available anymore?

    Comment


      #3
      Originally posted by jfabernathy View Post
      I remember back on 22.04 you could edit some of the config files before you started the install script. Is that method not available anymore?
      Probably, but you'd have to locate the file where that is and edit it AND parts of Ubiquity (the Ubuntu installer) are now in snap of all things. IDK what editing a file inside a snap would do.

      Honestly the above steps only took a few minutes and a couple reboots to complete.

      EDIT: I just checked and the files I used to edit to do this no longer exist.
      Last edited by oshunluvr; Jun 28, 2024, 11:38 AM.

      Please Read Me

      Comment


        #4
        Interesting to learn you can snapshot a whole file system as if it were a subvolume.

        Please Read Me

        Comment


          #5
          In step 1, I wonder why, to make the @home subvolume, you just create the subvolume, and cp -a --reflink=always the contents to it:
          Code:
          cd /
          sudo btrfs su cr @home
          sudo cp -a --reflink=always home/* @home
          That would save the messy "clearing out" and moving home/* up one level.

          However, I haven't got a Ubuntu server install on which to fully check my approach.
          Regards, John Little

          Comment


            #6
            Originally posted by jlittle View Post
            In step 1, I wonder why, to make the @home subvolume, you just create the subvolume, and cp -a --reflink=always the contents to it:
            Code:
            cd /
            sudo btrfs su cr @home
            sudo cp -a --reflink=always home/* @home
            That would save the messy "clearing out" and moving home/* up one level.

            However, I haven't got a Ubuntu server install on which to fully check my approach.
            Interesting idea. I'll test that next time I'm fooling around with this.
            Last edited by oshunluvr; Jun 29, 2024, 05:46 AM.

            Please Read Me

            Comment


              #7
              Originally posted by jlittle View Post
              In step 1, I wonder why, to make the @home subvolume, you just create the subvolume, and cp -a --reflink=always the contents to it:
              Code:
              cd /
              sudo btrfs su cr @home
              sudo cp -a --reflink=always home/* @home
              That would save the messy "clearing out" and moving home/* up one level.

              However, I haven't got a Ubuntu server install on which to fully check my approach.
              I would assume one could use mv rather than cp? Also, BTW, the above was done on Ubuntu Desktop release, not Server - I suppose that doesn't make a difference.

              Please Read Me

              Comment


                #8
                Here's an interesting tidbit:
                Code:
                stuart@Ubuntu:/home$ mount |grep ' / '
                /dev/vda2 on / type btrfs (rw,relatime,discard=async,space_cache=v2,subvolid=5,subvol=/)
                ​
                Note the "device" is mounted but it shows as a subvolume in mount options. That's why you can take a snapshot of /

                That was the new interesting piece for me. I'm wondering now if this is typically how BTRFS would work on a full file system install or if this is something special that Ubuntu did.

                Please Read Me

                Comment


                  #9
                  Originally posted by jlittle View Post
                  In step 1, I wonder why, to make the @home subvolume, you just create the subvolume, and cp -a --reflink=always the contents to it:
                  Code:
                  cd /
                  sudo btrfs su cr @home
                  sudo cp -a --reflink=always home/* @home
                  That would save the messy "clearing out" and moving home/* up one level.

                  However, I haven't got a Ubuntu server install on which to fully check my approach.
                  This does indeed work. I decided to use 'cp' instead of 'mv' because if you mess something up, you're leaving yourself dead in the water. But now, how does one clear out the contents of /home under @home?
                  Last edited by oshunluvr; Jun 29, 2024, 08:27 AM.

                  Please Read Me

                  Comment


                    #10
                    Originally posted by oshunluvr View Post
                    Interesting to learn you can snapshot a whole file system as if it were a subvolume.
                    A long time ago I merged @home into @ and to snapshot my entire system I need only to snapshot @.
                    I then use "btrfs send -p @oldsnapshot @newsnapshot | btrfs archive /backup" to move it to another device.

                    "A nation that is afraid to let its people judge the truth and falsehood in an open market is a nation that is afraid of its people.”
                    – John F. Kennedy, February 26, 1962.

                    Comment


                      #11
                      Originally posted by oshunluvr View Post
                      I decided to use 'cp' instead of 'mv' because if you mess something up, you're leaving yourself dead in the water.
                      mv was my instinctive choice, and is what I've done in the past (after solid backups), but upon reflection came to the same conclusion and looked for a more cautious method. Having seen people lose data with mv (over decades, alas too many) I'll be thinking about cp --reflink the next time I'm considering using mv on btrfs.

                      But now, how does one clear out the contents of /home under @home?
                      There shouldn't be a "home" under @home, unless you had a /home/home to start with. One should check for dot files in /home, too. There might only be .directory but having mounted @home on /home they've been hidden, which is slightly unclean.
                      Regards, John Little

                      Comment


                        #12
                        Originally posted by jlittle View Post
                        There shouldn't be a "home" under @home, unless you had a /home/home to start with. One should check for dot files in /home, too. There might only be .directory but having mounted @home on /home they've been hidden, which is slightly unclean.
                        OK, so you start with an Ubuntu install to the root fs instead of subvolumes, That means home is /home/user/<files>. When you snapshot "/" as "/@/" home now exists twice: /home/user/<files> and /@//home/user/<files>.

                        Now you create @home and then copy the /user/ folder from one or the other existing homes into @home/ leaving you now with three home folders. At some point before mounting @home at @/home you must delete the contents of @/home. If you skip the deletion step you will have @home as a mount hiding the /@/home folder contents. AFAIK, there's no way to make snapshot that excludes the contents of a folder, so @/home exists and contains the contents of /home.

                        The question isn't "Do we have to delete the contents of @/home? (note the slash here)" because we know we do, unless we're just being lazy or sloppy. The question is "What's the least number of steps to get us safely to properly configured subvolumes?"

                        I'm now thinking that by moving the contents of @/home (slash) to @home (no slash) before rebooting into the subvolumes should suffice, and would also leave the original /home intact as prevention against a misstep.

                        EDIT: I went ahead and re-wrote the How-To to make incorporate the above. It's makes it quite a bit simpler.
                        Last edited by oshunluvr; Yesterday, 06:26 AM.

                        Please Read Me

                        Comment


                          #13
                          I re-wrote a couple parts of the How To including creating @home and ran through it from the beginning and was successful.

                          Please Read Me

                          Comment


                            #14
                            edited

                            Comment


                              #15
                              Originally posted by MarkkuE View Post
                              I think, that instead doing something afterwards, it might be easier to do this beforehand. Of course, this can be done only with fresh install, not as upgrade. With live install edit /etc/calamares/modules/mount.conf and add - for example

                              btrfsSubvolumes:
                              - mountPoint: /
                              subvolume: /@
                              # As an alternative:
                              #
                              # subvolume: ""
                              - mountPoint: /home
                              subvolume: /@home
                              - mountPoint: /var/cache
                              subvolume: /@cache
                              - mountPoint: /var/log
                              subvolume: /@log

                              ​This is only copy/paste from git, and you can modify it to your liking

                              I have done this many times, in the same file you can also change the mount options, if you like.
                              Yes, I have written a post on this forum to edit Calamares or Ubiquity to allow custom subvolume names.

                              However, Ubuntu, as is stating in the first line of the How To, does not use Calamares so while your suggestion would work on Kubuntu or KDEneon or possibly others, it does not when using Ubuntu.

                              Please Read Me

                              Comment

                              Working...
                              X