My read-only home
I got so fed up with random programs putting random files and directories in my home
directory, that I executed chmod -w "$HOME"
a few months ago, making it
impossible to create new directories or files in it. At first, it was only meant as a
temporary measure, until I have all the programs I use under control, but I think I’ll
just keep my $HOME
read-only.
It causes far fewer issues than anticipated and has forced me to add configuration for
every single program, that by default puts stuff in my $HOME
. The results are
beautiful, predictable, and maintainable. No more surprises waiting for the next
ls -A
.
> ls -A
.cache/ .local/ .mozilla/ src/ tmp/ .vim/
.config/ mnt/ .profile@ .ssh/ var/ wrk/
Now this is an amount of output from ls(1)
I feel I can handle. Not perfect,
but a little closer to what I want.
The ideal world™
My goal with this is to get rid of most hidden files, which wouldn’t exist in my little rainbows-and-unicorns world I’m dreaming up (as in, a file with a dot in the beginning is just that and gets no special handling)
> ls -A
etc/ mnt/ src/ tmp/ usr/ var/ wrk/
So where would the remaining hidden files move? I’ve made a little map for you:
.config -> etc
.cache -> var/cache
.local/bin -> usr/bin
.local/lib -> usr/lib
.local/share -> var/lib
.mozilla -> etc/mozilla and var/lib/mozilla
.profile -> etc/profile
.ssh -> etc/ssh and var/lib/ssh
.vim -> etc/vim
I could already get rid of .cache
, .config
, and
.local
, but moving those on a running system is a bit cumbersome and I haven’t
done it yet. I’d probably have to file a few bug reports as well, I’m not sure all the
programs I use handle $XDG_CONFIG_HOME
and friends properly. I’m not even
sure if my dotfiles handle them properly. 😬
Ok, cool, but why?
The whole
XDG situation
is well-defined and facilitates backups (include $XDG_DATA_HOME
and
$XDG_CONFIG_HOME
, exclude $XDG_CACHE_HOME
) or resetting to
factory defaults without loosing user data (delete $XDG_CONFIG_HOME
), among
other advantages like making a setup as above possible with only a handful of environment
variables.
Hidden files always felt messy and like a workaround to me. They don’t provide much benefit apart from hiding a mess of weirdly placed configuration files. A suspicion which gets reinforced by the old legend of them being nothing more than an exploited bug. On the other hand, hiding a mess might just be a good enough reason for them to exist. In the end, it’s probably just personal preference.
My hierarchy is just that and does away with hidden files (in $HOME
at least)
and in my little dream world, we would get rid of some rather useless flags in
ls(1)
and similar special casing in file browsers and libraries. Even the
likes of git wouldn’t strictly require them, they could just use git/
and
git/ignore
instead of .git
and .gitignore
.
rcs(1)
didn’t use hidden files, you know. 🙃
Realistically speaking, we won’t get rid of them of course, but above hierarchy would
allow me to alias ls="ls -A"
, without being met with a massive listing in
$HOME
and I could at least pretend hidden files wouldn’t exist.
Lastly, this hierarchy mimics hier(7)
to some degree, which makes it easier
to build stuff locally and install it to $HOME
. While this is already easy
with specifying a prefix of $HOME/.local
for make(1)
or
configure
, it just feels more consistent to me.
Reality check
This hierarchy is not achievable as outlined above, at least not at the moment.
ssh(1)
for example won’t ever change their default of ~/.ssh
,
since this directory has become something of an API, changing it would break a lot of code
and will not happen.
Other projects won’t change for similar reasons or because they flat out refuse everything
mentioning freedesktop.org, no matter what it is.
¯\_(ツ)_/¯
Given the naming conventions they tend to use, I can’t even blame
those projects too much (who doesn’t like typing XDG_CONFIG_HOME
).
This is another reason I haven’t moved the XDG directories so far, I realised I won’t be able to get the results I wanted. As mentioned above, the following would be possible, and I will move eventually, but for now laziness wins.
> ls -A
etc/ .mozilla/ src/ tmp/ var/ wrk/
mnt/ .profile@ .ssh/ usr/ .vim/
It’s still not enough to alias ls="ls -A"
though. With some determined
$ENV
hackery, I could also get rid of the .profile
link, which
I’ll probably do as well. I could also switch to neovim and
get rid of .vim
, but that would be a bit excessive and wouldn’t look much
cleaner anyway.
The rest of my files
I have been asked, how I lay out my $HOME
and this article is an
explanation of some of the bits I find interesting and worth explaining in detail, but
here’s the rest of my home-hierarchy for completeness:
> tree -L 2
.
├── mnt
│ └── * webdav/nfs/etc mountpoints
├── src
│ ├── archive
│ └── * sources of programs I've built locally/modified
├── tmp
│ └── * downloads and other temporary stuff
├── var
│ ├── archive
│ ├── backup
│ ├── books
│ ├── documents
│ ├── inbox
│ ├── music
│ ├── notes
│ ├── pictures
│ └── videos
└── wrk
├── archive
└── * work and other projects, like this blog