Tips on how to structure your home directory

Published on 2023-09-04. Modified on 2023-09-07.

Someone wrote me an email and asked if I could share some tips on how to structure the $HOME directory, so here we go.

Structuring or organizing directories is not much different from structuring or organizing other stuff and it really comes down to what makes the most sense to you - at least as long as you're only dealing with your own directories. As soon as you're dealing with an organization, things can very quickly get out of hand.

The main purpose behind any kind of organizing is efficiency. That really is the keyword. You need to be able to easily and quickly find what you're looking for and just as easily and quickly be able to store what needs to be stored.

Over the years I have changed my directory structure for my home directory a couple of times, but not so for about the last 10+ years because I have settled on something that works really well for me.

I don't like clutter and I try to keep things simple. If I need some kind of rule book in order to remember how to store my files in my home directory, then this is a clear sign that something has gone wrong.

In my home directory I have all the basic hidden stuff which is a part of any modern Unix operating system such as .config, .aliases, .profile, .gnupg, .mozilla, etc. Though I would prefer that all applications would respect the XDG_CONFIG_HOME, which defaults to $HOME/.config, I don't mess with that and generally don't care too much about that.

In the past I kept my $HOME in Git - the right way ;), which is a really great way to organize dotfiles. Today I still put all my dotfiles in Git because I like to keep a history of changes, but I only leave those dotfiles in place which work identically across the different systems I use. The setup specific dotfiles is kept in a "dotfiles" directory and I then use symlinks (more about that in a little while).

Regarding normal files and directories I primarily use two methods of organizing, namely "category" and "dates".

This is my basic directory structure:

bin
data
edata
mnt
usr/dotfiles

Besides from the above, I just leave the Desktop and Downloads directories, which different applications seem to want to shove down the throat of everybody. In the past I "fought" against those, because I generally don't use them and I don't like them, but life is just too short to mess with crap like that.

Update 2023-09-04: You can set directories such as Desktop, Downloads and others with the user-dirs.dirs - settings for XDG user dirs, which most applications should respect (thanks Hugo for pointing this out!)

In the bin directory I keep my shell scripts and personal binary executables (not stuff installed via the package manager).

The mnt directory I use for different mount points, like when I mount an SD card, a USB disk, some of the shared storage I use in my homelab.

It looks something like this:

mnt
  \foo
  \bar
  \baz

I never auto mount, but generally use shell scripts for mounting. So if I have a USB disk I call "foo", I have a shell script called mfoo. It doesn't matter how the "foo" disk gets recognized by the system, the shell script will make sure that the disk gets mounted at mnt/foo each time, and if the disk is encrypted, it will prompt me for the passphrase, if I don't use a key.

The usr/dotfiles directory is kept in Git together with generic dotfiles that work identically across all systems, like .aliases. I use symlinks to the relevant files in the dotfiles directory. It looks something like this:

$ ls -l ~/usr/dotfiles/config/i3
freebsd-config
linux-config
$ ls -l ~/.config/i3
config -> /home/foo/usr/dotfiles/config/i3/linux-config

linux-config is then a specific configuration file for i3 which I only use on my Linux systems. This might be because the shortcut I use to run Firefox, starts Firefox in a AppArmor controlled Firejail, which doesn't exist on FreeBSD. On FreeBSD I might use Capsicum to get a similar experience. Just as an example.

I have a couple of other subdirectories in the $HOME/usr directory besides the dotfiles directory, but those are not really relevant to mention in detail for this article (a directory for some outdated shell scripts, some wallpapers, etc.)

NOTE: Configuration files (dotfiles) can be managed in many different ways. I have changed my approach a couple of times throughout the years. My preferred method is to keep my $HOME in Git. If you only run a single system or similar systems I can highly recommend the method I describe in the tutorial I have linked to.

But remember this, don't just follow what other people tell you to do, find the way that makes you the most productive, the way that is best wired to "fit your brain, your way of thinking" and then simply change that if you later find a more productive way.

The data and edata directories are the two main directories where I keep all my stuff. These two directories are ZFS datasets that run on a mirrored pool of disks that are separate from my root installation. I run both FreeBSD and several different Linux distributions on my main workstation and these each run on their own set of disks.

All of this could be setup in other ways too, but I prefer this setup. I can easily mount both data and edata from both FreeBSD and Linux.

The difference between data and edata is that edata is a ZFS native encrypted dataset.

By utilizing ZFS I regularly use snapshots and ZFS send and receive for easy backup to network storage. This can be done even without decrypting the encrypted dataset.

You could ask what the point is of having both an encryptet dataset and an unencryptet dataset, why not just put everything into the encryptet dataset?

The fact is that I would rather not have anything encryptet at all. Encryption is great for privacy, but it is an absolute horrible layer of complexity to put on top of an already complex layer of a filesystem and ZFS encryption is not without its bugs, see issues 13533 and 14330.

TIP: I highly recommend that you ALWAYS backup all your important data to multiple different storage solutions and locations - it's okay to be paranoid about important data.

Actually, you SHOULD be paranoid about important data. I learned this the really hard way - a long time ago - when I had just finished writing a 200+ A4 pages book and then lost everything because of a silly mistake and had to start all over and write the book again!

It is impossible to describe that very special feeling that arises when you have just realized what just happened! Noooooooooooooo! Pleeeeeeaseeeeee NOOOOOOOOOOO! (utter despair and disbelief - LOL).

So, today I not only use ZFS send and receive, but I also copy data to other filesystems all together, using rsync. For encryption I utilize both ZFS native encryption, GELI (for my main FreeBSD root disks) and LUKS (for my main Linux root disks) and I also not only follow the 3-2-1 backup rule, but add further copies to multiple systems. That way, even if some bug is found that might cause a problem for me, I have a high degree of being able to get my files without having to mess with the problem.

I do NOT use cloud storage for anything important. I rather keep local copies at places like family, friends or in a safety deposit box (unfortunately, safety deposit boxes are currently being removed from the banks in Denmark).

In the data directory I have a few subdirectories:

books
notes
source

The books directory contains books I have written or I am working on.

The source directory contains source code for various projects I work on.

The notes directory contains a huge amount of personal notes on everything from health to politics to computer related subjects. I write everything in pure text, mainly in Markdown or just without any special markup. Everything is structured according to category or subject and it looks like this (short version):

data/notes/
  astronomy
  business
  electronics
  health
  it
  language
  ...

Each main subject also has a subdirectory called files which I use for stuff I find online related to the subject. Files in the files directory can be images, text, audio and video. If I only have a few files, I just dump them all in the files directory, but if I have a lot, I organize them further by putting them in the relevant categories.

Within each category of directory I might also keep a hidden subdirectory called .outdated. I use this hidden directory to put stuff away that is, well, outdated, but might still come in handy.

It then looks something like this:

$ tree
.
└── data
    └── notes
        └── it
            └── operating-systems
                ├── freebsd
                │   ├── .outdated
                │   ├── files
                │   │   ├── audio
                │   │   ├── images
                │   │   ├── text
                │   │   │   └── why-we-migrated-away-from-y-at-foo.pdf
                │   │   └── video
                │   │       └── how-we-setup-y-at-z.mp4
                │   ├── how-to-do-x.md
                │   └── how-to-setup-y.md
                ├── linux
                └── openbsd

I always keep an exported shell variable that contains the location of my notes. That way I can easily link to any other document or external file from within my notes and use Vim to open the file (if it's a text document) by pressing gf or use Vim's build in ability to execute a shell command from within the document. I use that to view PDF files or play a video, etc.

In my notes I might have a Markdown link to a PDF file which looks like this:

This is the [foo document]($NOTES/it/operating-systems/freebsd/files/text/foo.pdf) relevant for information about foo.

When you have setup a default application for reading PDF files, then from within Vim you can just place the cursor on the filename and then press gx and Vim will open up the PDF file in the relevant PDF reader. Or you can copy and paste the path to the file and then open it with your PDF reader by typing ! from within Vim (I generally use MuPDF or zathura for reading PDF documents):

:!mupdf $NOTES/it/operating-systems/freebsd/files/text/foo.pdf

This works for other applications as well, such as opening video with mpv or images with something like feh.

NOTE: Hyphen vs underscore in filenames and directory names?

Originally, when I stopped using Windows back in about 1998, I was used to using spaces between words in filenames and directories. As I progressed into the world of Linux and BSD, I changed all spaces to underscores, but since I have done (and still do) a lot of web development I eventually settled on hyphens. I not only think it looks better, but the fact is that search engines interpret hyphens in file and directory names as spaces between words. Underscores are usually not recognized, and as such, their presence can negatively affect search engine optimization. Even though files in my home directory are my private files and not something I put out on the web, I have just settled on using hyphens everywhere.

Filename "foo_bar_baz" becomes "foobarbaz" on a search engine, whereas "foo-bar-baz" becomes "foo bar baz".

As mentioned, I also keep an encrypted directory called edata. I do that because I believe that it's important to encrypt private stuff in case your computer gets stolen.

TIP: Remember that if you use encryption for anything which other family members might need to be able to access in case you pass away, you need to make sure that they know how to do that!

The edata directory is organized in a similar fashion with "categories" being the main structure.

documents
  \letters
    \foo
    \bar
  \receipts
\media
  \family
    \audio
    \photos
      \2022
      \2023
    \video
      \2022
      \2023
  \foo
    \photos
      \2022
      \2023
    \video
      \2023
\projects
  \foo
    \documents
      \email
      \letters
    \media
      \photos
        \2023
  \bar
  \baz

Subdirectories within documents and projects are further subdivided by categories depending on the relevant context.

TIP: I have one basic rule which I implement regarding naming files and directories. The rule is this: I need to be able to easily determine what something is just by looking at the name.

If you stumble upon a file that you don't know what is just by looking at the name of the file, open the file immediately and see what it is and then rename it to something that makes better sense the next time you happen to look at the filename.

If you keep leaving files and directories in a mess, it quickly becomes very difficult to fix later.

I personally use long and descriptive file names whenever it's needed to keep me from having to open the file in order to determine what the file is about.

I have many times seen a mess like this in someones directory (I believe we have all been there at some point LOL):

document.pdf
document2.pdf
document3.pdf
Document.pdf
document-new.pdf
new-new-document.pdf
new-new-new-document.pdf
old-document.pdf
...

If you're new to working with files and directories, you will most likely change your structure and setup more than once - don't worry about it, that's normal, it means you're evolving and improving your setup :)

Last, but not least, I don't keep old data lying around forever. When I am sure something isn't useful any longer, I delete it.