⬅️ Previous post: Getting online with LAMP and No-IP


Installing WebtreesInstalling ‘intl’ and preparing the data folderCreating the MariaDB databaseTweaking the default PHP configurationTroubleshooting SELinux errorsWhat’s next for the server?


Now that I have a server machine running Linux and a LAMP stack accessible via the internet, I’m ready to install the Webtrees software. Debugging the SELinux permission errors took some time, and got much easier once I learned how properly troubleshoot. Here’s what I went through to get it running.

Installing Webtrees

The Webtrees software is not included in Gentoo’s portage tree, but installation is simple nonetheless. The software is downloadable from Webtrees.net using the server’s wget command. The package you receive is then simply unzipped to install the software. I found it much easier to do this directly from the /var/www/localhost/htdocs directory than from the home directory or other such location. Downloading and unzipping the software in htdocs ensured that the correct SELinux contexts will be applies from to the software files. So for the current version as of this writing:

root# cd /var/www/localhost/htdocs
root# wget https://github.com/fisharebest/webtrees/releases/download/2.0.6/webtrees-2.0.6.zip
root# unzip webtrees-2.0.6.zip

This unzipped the software files onto the server in a folder called webtrees. I took the opportunity at this time to perform some URL customization. As is, the URL for my family tree would have been http://genealogybytim.zapto.org/webtrees. By changing the name of the folder to grahamtree, I was able to customize the URL to http://genealogybytim.zapto.org/grahamtree. Another option might have been to empty the contents of the webtrees folder directly into htdocs and erasing the index.html file there. This might have had the effect of leading http://genealogybytim.zapto.org directly to my tree. Not having tested this option, I’m not exactly sure how well it would have worked. I was content to leave http://genealogybytim.zapto.org as an HTML home page that links to my family tree, which resides at http://genealogybytim.zapto.org/grahamtree. Once I had unzipped and renamed the webtrees folder, I was ready to configure the site.

The trick to configuring the webtrees site is that it must be done from outside of the home network. Viewing the site from within the home network, using either http://localhost/grahamtree or http://10.0.0.201/grahamtree would have given the initial appearance of working, but ultimately would have configured the site incorrectly. Visiting the site from outside of my home network, as most of my site’s visitors would, was the way to ensure correct configuration. I accomplished this alternatively by either connecting my main computer to the Internet through my smart phone’s Wi-Fi hotspot or by using the Tor browser to reroute my requests through several other servers before it returned to my home server.

A successful installation shows the setup wizard:

The first page of the setup wizard asks for the administrator’s language preference.

After selecting the desired language for the site, the setup wizard performs some checks on the server’s capabilities and reports back any issues that need to be addressed.

Installing ‘intl’ and preparing the data folder

In my several experiments with installing Webtrees, I’ve seen only two different server configuration errors reported on the setup wizard’s second screen. The first has been a ‘missing intl module’ error. This is corrected by adding intl to the USE flags in make.conf, re-emerging PHP, and re-starting Apache. It’s an easy, albeit time consuming, fix. The other configuration error was tougher to for me to crack on an SELinux-enforcing system.

Webtrees needs permission to write to its data folder. This does not occur naturally during the installation process. The server administrator must make it happen. The wizard offers advice for fixing this problem: Change the data folder’s permissions to 777. In other words, grant the data folder universal write permissions. This is rare advice for a Linux application. Granting universal write permission is usually anathema to advice-offering Linux developers on security grounds, but Webtrees‘ primary developer justified the advice on the grounds that “99% of users won’t have root access, and therefore won’t be able to” grant write permission to the data folder by any other method. He continued, “It’s what the majority of web applications do.”

The second page of the wizard tests the preparation of the server and alerts if any modifications are necessary. Unless preparations are made in advance, it will warn that data folder is unwritable.

I’m new to the server game, so I’m in no position to argue. The command for granting universal write permissions as instructed would be:

$ chmod -R 777 /var/www/localhost/htdocs/grahamtree/data

As the brand new administrator of my own home server, however, I have a slight security advantage at this particular juncture: I do have root access to the server system, so I can use the chown command to give the Apache process ownership of the website’s files:

root# chown -R apache:apache /var/localhost/htdocs/grahamtree

The latter command doesn’t grant universal write permission; it grants write permission only to the Apache server and to the root user, so it is theoretically a more secure way to provide Webtrees write access to the data folder. Ordinarily, changing this permission (or ownership, in our case) would have been sufficient to proceed in the installation process, but SELinux requires additional steps. SELinux has its own file type label, namely httpd_sys_rw_content_t, that grants Apache write access to folders on the server. The label should be applied to the data folder in the usual way:

root# semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/localhost/htdocs/grahamtree/data(/.*)?"
root# restorecon -R /var/www/localhost/htdocs/grahamtree/data

Besides this, Webtrees requires one additional permission, and that is the permission to operate a scripting language, namely PHP, on Apache. This is set by the SELinux boolean httpd_builtin_scripting:

root# setsebool -P httpd_builtin_scripting on

PHP is now able to write to Webtrees‘ data folder, and the wizard should permit advancement to the next step of the process.

The setup wizard has accepted the server configuration and allows setup to proceed.

Creating the MariaDB database

The next page of the setup wizard asked what kind of database I’ll be using. Since MariaDB is a drop-in replacement for MySQL,” MySQL is the correct response to that question on my server. One could take an entire course with a textbook like a city telephone book to fully understand all of the workings of MariaDB, but this is not necessary to create the database that Webtrees needs to store your family history data. A few simple terminal commands will do the job, beginning with logging into MariaDB for the first time, and continuing to any number of easily Googled instructions. Examples include:

Once the database is are created, entering the information into the wizard is a simple matter. I just had to remember:

  • The MariaDB username I created,
  • The password I gave to that MariaDB user, and
  • The name of the database I created.

If creating the database by command line is not to one’s liking, PHPMyAdmin can most certainly create the database graphically, although I haven’t yet actually made a database that way myself. The commands seem to suffice.

Tweaking the default PHP configuration

Once the MariaDB database has been created and Webtrees has access to it, the installation of the software is complete. There are, however, some tweaks you can make to the PHP configuration that will enhance the usability of the software.

I’ve been in the genealogy game for quite some time now, so I’ve built up a sizable GEDCOM file. If you, too, have built up a sizable GEDCOM file you might find difficulty uploading it to your Webtrees installation. PHP caps uploads at 2M by default. One of the first tweaks I made to the PHP configuration was to increase the file size upload caps.

root# nano /etc/php/apache2-php7.4/php.ini

Once editing this file, I used Ctrl-W to search for the setting upload_max_filesize and increased the value to 20M.

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 20M
There was a time when I seemed to be having trouble with RAM limits and timeouts. That seemed to clear up after I resolved some SELinux permission errors, but in case you notice this problem on your server, there are settings for that.

; Maximum execution time of each script, in seconds
; http://php.net/max-execution-time
; Note: This directive is hardcoded to 0 for the CLI SAPI
max_execution_time = 60

; Maximum amount of memory a script may consume
; http://php.net/memory-limit
memory_limit = 1024M

If you notice from the screenshots in the previous section, Webtrees was able to identify 1024M available RAM and a 60 second timeout on the server. Those numbers came from these settings. They seem to be above and beyond the call, given the information provided in the server capacity report. If I don’t see any more trouble with RAM and timeouts, I’ll consider moving these numbers back down.

Other settings I fiddled with in the process were max_file_uploads, and post_max_size. I’m not quite sure now why I did that, but it seems not to have caused any harm. The point is, the php.ini file contains many server settings that might be tweaked should the need arise.

Troubleshooting SELinux errors

This one took me a while to figure out. It helped me through a few things, and it’ll help me again in the future. I first looked to the Gentoo Wiki for help troubleshooting SELinux permission errors. The page speaks of an apparently excellent debugger called setroubleshoot which is unfortunately unavailable on Gentoo, “but it is available on RedHat Enterprise Linux and related distributions”. Gentoo’s python-exec package does provide a pair of decent troubleshooting utilities, however, that aren’t mentioned on the wiki page as of this writing: audit2why and audit2allow.

The Gentoo Wiki describes the use of the ausearch command. I tailored the command to debug SELinux permission errors caused by Apache:

root# ausearch -c apache2 -ts [time in 24-hour format]

This command lists any SELinux errors logged by audit since the time given. To debug an SELinux permission error, I would launch this command at a certain recent time, a couple minutes ago, say 18:00, and I make sure no errors return. Then I went ahead and did the thing on the web site that threw an error. After that, I would re-run the ausearch command again to see whether any new errors get reported.

The errors messages that ausearch returns are not easily human readable, but the audit2why command helps with that.

root# ausearch -c apache2 -ts 18:00  |  audit2why

If I was lucky, the audit2why command would offer a simple solution, such as setting an SELinux boolean. This is how I discovered, at length, that the httpd_builtin_scripting boolean was causing permission problems with the data folder. If I was unlucky, I would receive an ‘allow’ statement that, if added to SELinux’s configuration, would allow the activity mentioned in the logs to occur. The ‘allow’ statement is added to the configuration by running the audit2allow command and specifying a module filename.

root# ausearch -c apache2 -ts 18:00  |  audit2allow -M apache_01

This command creates a .te (type enforcement) file, which contains the ‘allow’ statement in proper code form, and it creates a .pp (policy package) file, which is the compiled version the ‘allow’ statement, ready to load with the semodule command, as instructed.

root# semodule -i apache_01.pp

The audit2allow man page warns against overuse of this utility: “Care must be exercised while acting on the output of this utility to ensure that the operations being permitted do not pose a security threat. Often it is better to define new domains and/or types, or make other structural changes to narrowly allow an optimal set of operations to succeed, as opposed to blindly implementing the sometimes broad changes recommended by this utility. Certain permission denials are not fatal to the application, in which case it may be preferable to simply suppress logging of the denial via a ‘dontaudit’ rule rather than an ‘allow’ rule.”

An unwanted modules may later be removed with this command, similar as above but with an -r flag, and without the .pp extension:

root# semodule -r apache_01

I’ve made a habit of ending my own home brewed SELinux modules with numbers so they will be easy to spot for removal when I no longer need them.

What’s next for the server?

At this time, my server is up and running mostly smoothly. I’ll want to tinker with user permissions and homepage design to get the site functioning as I want it, but other than that, I now have what I set out to have: A Webtrees site live to the Internet on an SELinux-enforcing home server! Monetary investment in this site has so far been limited to:

  • $26 for one year the genealogybytim.com domain name.
  • $16 to replace the hard drive on the old computer, which was showing the warning signs of failure.

Where does my little server go from here? Well, I have two additional items on the agenda:

  • Implement SSL Encryption to protect e-mail addresses of those requesting membership to the web site. Certbot seems to be the right tool for the job. It may be the hubris talking after my recent success, but it actually looks pretty easy!
  • Set up a sendmail mail server so the site can autonomously e-mail members such cool things as family history newsletters and site updates. This tasks seems more challenging, but apparently I can more easily link my gmail account to the site and have it send emails that way.