If you find this useful and you use bitcoin, please donate:
Thank you.

The Problem

For those of us who actually use TeXLive, many of us fairly quickly learn the importance of installing it into /usr/local/texlive instead of the RPM method. There are several advantages to this:

What we tend to do is create a user that is the TeXLive administrator account. I use gid 800 uid 800:

groupadd -g 800 texlive
useradd -g 800 -u 800 texlive
mkdir /usr/local/texlive
chown texlive:texlive /usr/local/texlive
passwd texlive

That creates an otherwise unpriveleged user that has write permission to /usr/local/texlive. I can then log in as that user to rsync my TeXLive from another machine or to run the TeXLive network installer.

It works just swell. All my other user accounts, including the root user and the filesystem, are safe from mistakes that happen when administering the TeXLive system, and the TeXLive system is safe from all other users except for what root can do. Except there is one problem. The RPM database doesn't know about it.

Actually there are two problems, both related to RPM.

Problem One: Dependency Bloat

As I'm getting older, using emacs for LaTeX is getting more difficult. I want to use a nice GUI to author my content, one with tabs that are easy to switch between using the mouse, etc., so I found a really cool TeX editor that meets my needs: LaTeXila.

The LaTeXila RPM depends upon something called LaTeX-Mk which when installed wants to pull in over 200 texlive RPMs.

I don't even use the feature of LaTeXila that needs LaTeX-Mk, I only use LaTeXila for the syntax highlight. To compile the TeX I use the command line. And I already have a full TeXLive install, I don't want 200+ useless RPMs installed just so I can use a pretty text editor. Installing that many RPMs means a crapload of them will be updated, slowing down my update process and on several occassions in Fedora, I've had my workflow interrupted with an update warning where every single fucking update was one of these texlive RPMs that I do not even use.

I understand that TeXLive needs to be packaged. It needs to be there for apps that use it in their build process (e.g. documentation) and for the casual user, but it is a royal pain in the ass.

Problem Two: Packages That Install TeX Components

There are some RPMs that are not part of TeXLive but will want to install some TeX components and use the TeX system. On Fedora/Red Hat systems these RPMs will install their style files into /usr/share/texlive/texmf-dist as that is the TEXMF tree that the RPM install of TeXLive uses.

They will then want to run /usr/bin/texhash to update the ls-R files so the TeX system knows where to find the styles.

It is not just as simple as adding /usr/share/texlive/texmf-dist to the TEXMF trees my local install looks in, the texlive user does not have write permission to that directory so it can not update the ls-R file. And for several reasons, I do not want the root user executing the texhash command that is part of my local TeXLive install. The obvious reason is security, the root user should never execute programs that another user on the system has write permission to. As good as SELinux is, I'm surprised it allows it.

The Solution

The solution I have come up with is two-fold. It involves an RPM that provides the various texlive dependencies that cause texlive packages to be pulled into the install process, and the second part involves a cron job running as the texlive user to replicate the /usr/share/texlive/texmf-dist in a directory the texlive user has write permission to.

RPM Package

The RPM will basically just have a lot of Provides: in it to tell the RPM database that dependency is met. I am sure the list is going to grow, to see where it is at right now: texlive-usrlocal.spec.

I probably am going to script something to look through the TeXLive TEXMF tree and insert the correct versions for those various components, but right now I just have it provide 2014 as the version.

I do not intend to add Provides: for every texlive package, that would be ridiculous. Just the ones that various RHEL/CentOS + EPEL packages explicitly require.

That solves the problem of explicit dependencies that various RHEL/CentOS + EPEL may have, but it does not solve the problem of the TEXMF tree or texlive executables that various RPM scriptlets expect to be in /usr/{s,}bin.

That problem is partially solved by the RPM.

The first thing I do is a bit controversial, the RPM creates a file in /etc/profile.d that puts the /usr/local/texlive install at the front of a user's path. I may change that to put it at the back, with it not applying at all to users with a UID less than 500.

I am a little confused with what Red Hat is doing with user IDs. The way I learned system administration, UID 0 was root and system users critical to the system were always under 100, daemons and system users then would increment starting at 100. The system administrator could then assign UIDs in the top half of range how they saw fit. But it look like RHEL has some systems users starting at 999 and incrementing downward from that. I'd really like to know what the fuck the logic is behind that.

It makes it more difficult to restrict a scripts actions based upon UID when the operating system is using UID both at the top and bottom of the range below "normal" users. Ah well.

Back off the sidetrack, the reason I put the /usr/local/texlive at the front of the $PATH is so that I could put wrappers in /usr/bin for RPM scriptlets without them normally being called by users of the TeX system.

The one wrapper in that spec file so far is a wrapper to texhash. When an RPM scriptlet calls it, it is being run as root, and it does not actually do a texhash. Instead it touches a file that will be used as a trigger. When a non-root user calls it, it then attempts to pass the request on to the real texhash.

Hopefully I will not need to many of those wrapper scripts, their only purpose is RPM scriptlets that call executables full path.


This is the second part of the solution. It involves adding a new TEXMF tree to TeXLive.

Basically, once every 5 minutes or so, a cron job running as the texlive user will check the time stamp on the /usr/local/texlive/update-texmf-rpm file against the time stamp on the /usr/local/texlive/texmf-rpm/ls-R file. If the timestamp on the former (assuming it exists) is newer than the timestamp on the latter, then the root user tried to use /usr/bin/texhash which probably means there is a change to files in /usr/share/texlive/texmf-dist.

That will trigger an rsync so that the contents of /usr/local/texlive/update-texmf-rpm will be updated to be identical (except for file owner) to the contents of /usr/share/texlive/texmf-dist and when the rsync is finished, the texlive user will then run the real texhash making the updates known to the TeX system.

It may be a wee bit of a hackish solution, but I believe it will solve the problem.

As far as RPM packages that want to install new fonts and enable font maps, that may be a little bit trickier.