Webserver Configuration

We’re using letsencrypt to get our SSL certs. Letsencrypt will automatically take care of our apache https configuration. A systemd job (renew-tokens) run the /usr/local/bin/renew-tokens.sh daemon which continually renews the afs tokens for the www-data user.


The sections below are no longer accureate, but will remain in case anyone wants to try to set up CGI again.

This document describes how our webservers allow CGI scripts to run with user access rights to AFS. Skip to ‘How to add a user’ if you don’t care about the details. We make use of UID-based PAGs (the default) in the linux OpenAFS cache manager. CGI scripts are run with mod_suexec and Apache is not particularly aware of AFS.


First and foremost, we love SSL and JHU will give us as many certs as we want, it seems; see SSL to make one. Then:

  • Concatenate the .key and the .crt and place it on the web server as /etc/apache2/ssl/apache.pem

  • Set SSL enabled in the apache configuration:

    SSLEngine on
    SSLCertificateFile      /etc/apache2/ssl/apache.pem
    SSLCertificateChainFile /afs/acm.jhu.edu/readonly/group/admins.pub/certs/jhu-cert-chain.pem

Install software on the webserver

A webserver needs to install: runit kstart openafs-krb5`` and a webserver. It is important, for the hack we deploy below, that libpam-afs-session not be installed.

Enabling serving from homedirs

In /etc/apache2/mods-available/userdir.conf

UserDir acmsys/public_html
<Directory /afs/acm.jhu.edu/user/*/acmsys/public_html>
        AllowOverride FileInfo AuthConfig Limit Indexes Options
        Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
        <Limit GET POST OPTIONS>
                Order allow,deny
                Allow from all
        <LimitExcept GET POST OPTIONS>
                Order deny,allow
                Deny from all

and again for /afs/acm.jhu.edu/group/*/acmsys/public_html.


For historical reasons, there are also stanzas missing the acmsys directory. These are likely to disappear at some point once we’re sure everybody’s switched over.

Enabling CGI

The webserver in turn is configured with mod_userdir and mod_suexec thusly. This means that it will use nss to look up UIDs in LDAP and spawn tasks with user UIDs and all that. For /etc/apache2/sites-available/acm

SuexecUserGroup nobody nogroup
UserDir /afs/acm.jhu.edu/user/*/acmsys/public_html /afs/acm.jhu.edu/group/*/acmsys/public_html

And for /etc/apache2/mods-available/userdir.conf, enable CGI

<Directory /afs/acm.jhu.edu/user/*/acmsys/public_html/cgi/>
  Options ExecCGI
  SetHandler cgi-script

and again for /afs/acm.jhu.edu/group/*/acmsys/public_html/cgi.

User keytabs and maintained tokens

Per-user that wants to run CGI scripts, we have a k5start daemon running on the machine. The daemon runs as root and obtains a TGT for www/${user} with a short lifetime and installs this into a kernel keyring. It then forks a process which drops UID to that of ${user} and runs aklog using the TGT in the kernel keyring (accessed by possessor rights, not UID rights; since the webserver is not a possessor and is not running as UID 0, it cannot access the TGTs directly). aklog will install AFS tokens for use by any task of running with the UID of ${user}, as no PAG has been created. The script /etc/sv/www.sh does this, but its contents are reproduced here non-authoritatively:

export AKLOG="su $USR -c aklog"
exec k5start -U -t -K 600 -l 12h -k KEYRING:session -f /etc/service/www-$USR/keytab

The process for a group that wants to run CGI is similar, except that one has to be sure that there is a UNIX user for that group (for the CGI to run as, naturally enough). Check LDAP and all that.

There should be such an entry created for the server itself, probably using the UNIX user www-data and a keytab for service/webserver or possibly the host-based key or something else. The corresponding AFS PTS UID should be a member of system:www which is what we tell everyone to use for acmsys/public_html permissions. See Web Hosting.

How to add a user or group

Create a ${user}/www principal in Kerberos and extract its keytab using kadmin. (Even if this is a group, please use ${group}/www; ${group} is probably not a principal in Kerberos, but that’s fine.)

Run this somewhere with LDAP lookups enabled, or do the lookup and math by hand:

pts createuser ${user}.www $((200000+`id -u ${user}`))

The number is unused and unimportant but is a convention. On the webserver, create a directory /etc/sv/www-${user} ; place the keytab at /etc/sv/www-${user}/keytab with mode 600 owned by root:root. Then

cat >/etc/sv/www-${user}/run <<HERE
exec /etc/sv/www.sh ${user}
chmod +x /etc/sv/www-${user}/run
update-service --add /etc/sv/www-${user}

How to tell a user to set up their public_html

The files in acmsys/public_html/cgi should be owned by the user’s primary uid and gid (NOT the PTS ID of their www hat). ACLs should be set at least as permissively as:

fs sa $HOME                 system:services l
fs sa $HOME/public_html     system:www rl
fs sa $HOME/public_html/cgi system:www rl

The webserver will only serve files which it considers to be publically readable, which means the UNIX mode bits need to be set correctly, despite that this is AFS, so be sure to chmod appropriately.


This should move to What Came with My Account?

Old mod_waklog configuration


This is obsolete. It is preserved here only as a starting point should somebody care to try again with mod_waklog.

Apache runs mod_waklog only to get global tokens. A keytab for system/webserver@ACM.JHU.EDU is extracted to /etc/apache2/keytabs/system_webserver readable only by root.

mod_waklog is configured to be loaded:

LoadModule waklog_module /usr/lib/apache2/modules/mod_waklog.so

and has configuration options

WaklogAFSCell acm.jhu.edu
WaklogEnabled on
WaklogDefaultPrincipal system/webserver@ACM.JHU.EDU /etc/apache2/keytabs/system_webserver