Files
blog.raer.me/content/2025/11/13/blog-entry-135625.md
Freyja Odinthrir f8594af9ba
Some checks failed
/ Connect to deployment host, update, and redeploy docs website. (push) Has been skipped
/ Build static site, docker image, upload artifact... (push) Failing after 2m52s
Add entry on the fhs spec
2025-11-13 13:59:55 -08:00

19 KiB

title: The FHS spec description: Notes taken by me on the Unix Filesystem Hierarchy Standard. tags: unix, linux, notes, general date: 2025-11-13 13:56

FHS

These are my FHS spec notes from 2024-06-26, uploaded here (nostly so my gf can read it, hi Jamie! :D)

The File Hierarchy Standard is a unix standard defining the minimal required directory hierarchy for a functional, portable, distributable filesystem. Distributable refers to the ability to store certain directories on other devices, mounted to the root directory. These can include /var, /etc, /home, /usr, /boot...

  • bin+
  • boot
  • dev
  • etc
  • lib+
  • media
  • mnt
  • opt
  • run
  • sbin+
  • srv
  • tmp
  • usr*
  • var*

(* indicates complex directories) (+ indicates a directory that is usually a symbolic link for one inside /usr)

Table of Contents

Prologue

I have a bug up my ass about studying the hierarchical directory system used on Linux and other unix-like computer systems. I think its a good idea to study things which we interact with and take for granted, in detail. This is something I implement as sort of a general philosophy of life lately. Thus, it has crept into my ongoing studies into computer science. Hence these notes on the FHS and how I can better conform to this standard so as to improve the fluidity of my workflow managing multiple home servers.

(/usr)/bin

Reference

Binary files. The basic commands installed on your system. These are things like rm, sudo, cp, mv and more. This is usually a symbolic link to /usr/bin.

ruleofthumb though it is standard for /bin to exist as a symbolic link, when doing a shebang to something in this dir I like to use the real directory /usr/bin.

Historically, this has been separate from /usr/bin. However, I think it makes more sense in this day-and-age to conform to a variation of the FHS where /bin is a symlink, since it allows /usr to be unified system resources.

/boot

Reference

This is the boot partition. The bootloader and its various config files reside here, as well as the kernel.

/dev

Reference

/dev is where device files reside. These are special files which refer to hardware (or virtual devices) made accessible to the system via drivers.

/etc

Reference

Configuration files for the host system. /etc/opt should contain config files for apps installed to /opt

/home (Optional, apparently. lol)

FHS doesn't officially standardize shit within a user home directory. They specify this, which I find useful:

  • "To find a user's home directory, use a library function such as getpwent, getpwent_r of fgetpwent rather than relying on /etc/passwd because user information may be stored remotely using systems such as NIS." source

Anyway, here are some standard conventions which I see employed in user home directories - and some ideas I have about how users' home directories should be dealt with.

  • In systems with DEs, you'll see capitalized directories called Documents, Downloads, Music, Pictures, Videos. These hold... what they say they hold. I like to use them as-is. KDE likes to include something called Templates which I've never used, or seen used, so I just delete it.
  • ~/bin/ for user-installed binaries or scripts. This is usually defined on the user's PATH variable so they may stick scripts in here for quick execution from their account, without having to stick them in /usr/.
    • I have a tendency to keep my scripts inside of ~/Documents/git/freyjagp/scripts/ because that is a git repo, and I keep my git repos there. Nonetheless, many tools that a user installs may install binaries/scripts in here. Or, into, as we'll describe below....
  • ~/.{TOOL}/ - Many tools will create a hidden directory inside of the home directory for storing config data local to the tool's user. I'm going to think of this as a sort of personal workbench, as opposed to /usr/bin/ or the like, which are like a community workshop.
  • ~/.config/ many user applications will store their configuration files here. Anything that's intended to be run by the user, not as a system-critical program, likes to store configs either here, or ~/.local/share/.
  • ~/.local/ is similar to /usr/local in structure? In practice, I find it to be an inconsistently used place to store stuff that would otherwise be chucked in ~/.config/ or ~/bin/ or ~/.{TOOL}/ directories. It was - I suppose, at some point - supposed to unify how things are done in a /home/user/ directory but... sigh.
  • Other misc. files, such as users' rc files for shells, or shell histories, or somesuch, are also stored in here.

User mounted stuff

Stuff that's mounted for the user automatically is usually done in /run/user/... and having read the standard, this makes sense. Its a runtime mount managed by software since the /run dir should be cleared on shutdown like /tmp.

Anything else that's mounted for the user's usage (and not for the system to have access to) should be mounted to ~/.mnt. Else, stuff mounted for use by the system (variable or otherwise) should be mounted at /var/nfs/... or similar - not /srv since srv should be for things that are publically accessible. Staticfiles, usually.

/home summary

Basically, /home/user stores anything a system user would want to keep backed up should shit hit the fan. It might be convenient to maintain backups of the whole system. But what really matters is the /home dir (to a basic user, at least).

(/usr)/lib

Reference

Shared libraries and kernel modules. Stuff used by the OS and kernel to make code work properly, to compile stuff written in C/C++, etc.

/media

Reference

Media on removable devices. Most commonly USB (though, many linux distributions use software that will mount removable media to /run/media/{USER}). Not really used, though, in my opinion.

/mnt

Temporary mountpoints. So using this for a quick mount -t nfs ... isn't a bad idea. But for something in /etc/fstab I should actually be mounting to something like /srv, /home/{USER}, or /var. This isn't so much a universal mountpoint for things that aren't system mounts but moreso a place for a user or administrator to mount devices in a pinch.

/opt

Applications/software packages. This blurb explains it better than I unerstand it at the time of writing:



    This directory is reserved for all the software and add-on packages that are not part of the default installation. For example, StarOffice, Kylix, Netscape Communicator and WordPerfect packages are normally found here. To comply with the FSSTND, all third party applications should be installed in this directory. Any package to be installed here must locate its static files (ie. extra fonts, clipart, database files) must locate its static files in a separate /opt/'package' or /opt/'provider' directory tree (similar to the way in which Windows will install new software to its own directory tree C:\Windows\Progam Files\"Program Name"), where 'package' is a name that describes the software package and 'provider' is the provider's LANANA registered name.

    Although most distributions neglect to create the directories /opt/bin, /opt/doc, /opt/include, /opt/info, /opt/lib, and /opt/man they are reserved for local system administrator use. Packages may provide "front-end" files intended to be placed in (by linking or copying) these reserved directories by the system administrator, but must function normally in the absence of these reserved directories. Programs to be invoked by users are located in the directory /opt/'package'/bin. If the package includes UNIX manual pages, they are located in /opt/'package'/man and the same substructure as /usr/share/man must be used. Package files that are variable must be installed in /var/opt. Host-specific configuration files are installed in /etc/opt.

    Under no circumstances are other package files to exist outside the /opt, /var/opt, and /etc/opt hierarchies except for those package files that must reside in specific locations within the filesystem tree in order to function properly. For example, device lock files in /var/lock and devices in /dev. Distributions may install software in /opt, but must not modify or delete software installed by the local system administrator without the assent of the local system administrator.

    The use of /opt for add-on software is a well-established practice in the UNIX community. The System V Application Binary Interface [AT&T 1990], based on the System V Interface Definition (Third Edition) and the Intel Binary Compatibility Standard v. 2 (iBCS2) provides for an /opt structure very similar to the one defined here.

    Generally, all data required to support a package on a system must be present within /opt/'package', including files intended to be copied into /etc/opt/'package' and /var/opt/'package' as well as reserved directories in /opt. The minor restrictions on distributions using /opt are necessary because conflicts are possible between distribution installed and locally installed software, especially in the case of fixed pathnames found in some binary software.

    The structure of the directories below /opt/'provider' is left up to the packager of the software, though it is recommended that packages are installed in /opt/'provider'/'package' and follow a similar structure to the guidelines for /opt/package. A valid reason for diverging from this structure is for support packages which may have files installed in /opt/ 'provider'/lib or /opt/'provider'/bin.


source^

after reading the blurb, I understand that opt functions this way:

It can look like this:

  • /opt
    • /bin
    • /doc
    • /include
    • /info
    • /lib
    • /man

These are reserved for system admin usage. They should store (if they are used) copies or symlinks to stuff inside of /opt/{PACKAGE}/[bin,doc,include,info,lib,man]. That's a little complex so I'll just stick to /opt/{PACKAGE}/...

/var/opt and /etc/opt can also serve variable and config files respectively, for applications stored in opt (as opposed to /opt/{PACKAGE}/[etc,var])

In general, though, anything for an application installed to /opt to work should be stored inside /opt/{PACKAGE}/...

Another valid option is /opt/{PROVIDER}/{PACKAGE} but I'll prolly ignore that one.

/root (optional)

The root user's folder.

/run

"This directory contains system information data describing the system since it was booted. Files under this directory must be cleared (removed or truncated as appropriate) at the beginning of the boot process."

This is where things like sockets, or "data relavent to running processes" are kept.

/run should not be writable for unprivileged users; it is a major security problem if any user can write in this directory. User-specific subdirectories should be writable only by each directory's owner.

(/usr)/sbin

Utilities used for system administration (and other root-only commands) are stored in /sbin, /usr/sbin, and /usr/local/sbin. /sbin contains binaries essential for booting, restoring, recovering, and/or repairing the system in addition to the binaries in /bin. [18] Programs executed after /usr is known to be mounted (when there are no problems) are generally placed into /usr/sbin. Locally-installed system administration programs should be placed into /usr/local/sbin. [19]

System binaries. Stuff used by the root user to do administrative and or system things.

/srv

I think taticfiles should be served from here. On my nginx server, instead of doing /var/www/bjongbeuf.com/{NFS-MOUNT} or /mnt/httpserve/bjongbeuf.com/{NFS-MOUNT} I should just be doing /srv/bjongbeuf.com/{NFS}. I suppose, that this shouldn't even necessairily be limited to nfs. This should just have anything that's being served to the public (which in this day-and-age means files served over http). In my opinion, most linux distros do this wrong and it, quite frankly, makes sense for things that are being served to the public to be here. Sure they can be variable. But /var is better for shit like logs, in my opinion.

Funny enough, the standard agrees with me (I hadn't actually read it at the time of writing above paragraph). See here.

There's no standard for how things should be kept here. So I'll probably just do it as I see fit until I settle upon something. For now, I'm thinking something like /srv/{domain-name}/ since I mostly only serve static files from http anyway, it wouldn't really make sense to put them somewhere like /src/http/....

/tmp

Temporary files baby. Anything that you don't mind being lost or cleaned up at some point after you're done with it. Some things also put sockets here for some reason.

/usr

reference

This boi is complex, but I think I can boil it down to a couple of simple things. We've already gone over some of the contents of /usr with /bin and /sbin and /lib. /usr is also meant to hold other directories for system purposes such as include and share and libexec. These aren't terribly important to know off the top of your head. Only that stuff in here that's not in the /usr/local is intended to be installed and managed by the system. If you're manually sticking something in /usr/bin it should be to update an existing package. Otherwise, /usr/local/bin should be used, as /usr/local is reserved for administration by the system administrator.

/var

Var is kind of... where we chuck things that change with the system as time goes on, that must be stored, that aren't config files, or static files, or what-have-you. Logs, spools, mailboxes, and the like. Officially, you aren't supposed to do what I do - making apps store things here. But I'm going to do it anyway, because I need to for configuration management.

Anyway, the things of note in here are /var/log /var/mail. And for my purposes, /var/gitlocal.

Backup strategies

A simple backup strategy employed by - I'd wager - most users (at least by myself) is to simply rsync (or something else, in my case I use borg) the entire /home/user directory. This works if all you care about on the system is your userdata. What if the rest of the system isn't quite so expendable? What if you're serving html content from /srv/example.com that isn't on an nfs share? What if you've installed binaries from external sources (or compiled them yourself)?

Well, we want to consider backing up other folders, then.

There's not going to be a one-size-fits-all solution here but I'll try to generalize...

Example backup strategy

A basic strategy would consider backing up all of:

  • /boot
  • /home
  • /srv
  • /var
  • /root
  • /etc
  • /opt
  • /usr/local

A more efficient strategy might try to consider what exactly do we want to keep from these and why. It might also discard some directories entirely depending on whether we use them.

(I kinda thought I was cooking here but I wasn't lol).

Configuration management strategies

Git, git, git, git, git. Git is god here. but how?

I'm going to attempt to, finally, devise a configuration management strategy that incorporates git, is scriptable, and compliant with FHS.

Configs are stored in /etc and /usr/local/etc. On any system I manage, this will be so - EXCEPT with things that run as docker containers, those will use /opt and I'll explain why later.

/etc and /usr/local/etc should each be initialized as git repositories on system initialization. Then, we create bare git repositories at /var/gitlocal/etc.git and /var/gitlocal/usr_local_etc.git. Optionally, we create (or import) a gpg key for the root account to use for signing git commits. Commits are pushed to, at a minimum, the bare git repos mentioned earlier. Any backup strategy employed on a system using version control under this configuration management strategy, must include at least /var/gitlocal, allowing configuration files to be version controlled and backed up.

When do I do things in /opt???

The only case I see myself using /opt is when I'm deploying docker containers. Binaries installed to the system, but compiled by the sysadmin (such as how I implement nginx) should be installed/configured to /usr/local/bin and /usr/local/etc respectively. It might make sense to install them to /opt at first glance... but I see opt as more of a place to keep application binaries and data in one location should you want to do that. In my use-case, I like to avoid dealing with PVE volumes for any sort of configuration or permanent data stored by a docker container. Sometimes I want to poke around in that data, and a PVE is simply too god-damned inconvenient to deal with. They have their usecases, but not as persistent data stores in my environments. Therefore, /opt is the perfect candidate for my usecase. It has a loosely defined structure that allows me to do things like throwing a valheim server into a directory called /opt/valheim with a docker-compose.yml and its own ./etc and ./var dirs.

Note that there are optionally defined structures for /opt that include symlinking things to /opt/bin and using /etc/opt and /var/opt however I see these as obsolete and unnecessary. A refined standard in my opinion would remove these as options, sticking to opt as a place like I'm using here.