N.B. chroot.sh
updated for OpenBSD 6.0.
OpenBSD's httpd
runs chrooted, so to support the python CGI
scripts used by my websites, all the required python binaries,
libraries, and supporting shared libraries had to be copied into the
chroot environment.
The chroot location was changed from the default of
/var/www
to /home/www
. Flags to slowcgi (which
acts as the interface to httpd's fastcgi implementation, were
changed to match, thus:
slowcgi_flags="-p /home/www -s /home/www/run/slowcgi.sock"
The web site organisation I'd adopted for apache put the cgi-bin
directory outside of the document root. This is supported by
httpd
, but the DOCUMENT_ROOT variable passed in by httpd to
the cgi program contains the location of cgi-bin, so it becomes
impossible to access the document files (e.g. the system.template)
without setting up soft links or having the cgi-bin programs know
the layout conventions.
The solution I chose was to change the site building script
(make publish)
to create the appropriate soft link when on
OpenBSD. The link has to be relative, as we are in a chroot environment.
The next difficulty was caused by a bug in the python library file
posixpath.py
, which is called by setup.py
. This
produces the following error, when run in a chroot environment:
KeyError: 'getpwuid(): uid not found: 67'
Python is attempting to look up the www user from somewhere (I
assumed /etc/passwd
). This didn't exist in the chroot
environment, but even when I copied in /etc/passwd
to the
chroot enrionment, the error still occured. The other workaround
described was to specify the HOME environment variable. Since I
didn't want to install sh
in the chroot, I tried to set it
via os.environ
. That didn't work either, because
setup.py
is run before the python script is
processed. Finally, I patched the chrooted library file. That
worked, but is ugly.
A better fix was to specify the -S argument to the python shebang:
-S Disable the import of the module site and the site-dependent manipulations of sys.path that it entails.
Or, even better, copy pwd.db
to the chrooted etc. After
experimentation, that one file appears to satisfy python's
getpwuid().
A script to create a chrooted environment for python (or at least for my requirements) is shown below.
#!/bin/sh # # Enable python to operate for a chrooted environment (for httpd) # export CHROOT=/home/www rm -rf ${CHROOT}/usr ${CHROOT}/var ${CHROOT}/etc ${CHROOT}/sbin \ ${CHROOT}/run ${CHROOT}/logs mkdir -p ${CHROOT}/usr/local/bin ${CHROOT}/usr/lib ${CHROOT}/usr/libexec \ ${CHROOT}/sbin ${CHROOT}/var/run ${CHROOT}/etc \ ${CHROOT}/usr/local/lib ${CHROOT}/run ${CHROOT}/logs cp -p /sbin/ldconfig ${CHROOT}/sbin cp -p /usr/local/bin/python2.7 ${CHROOT}/usr/local/bin/python cp -p /usr/local/lib/libpython2.7.so.* ${CHROOT}/usr/local/lib cp -p /usr/lib/libpthread.so.* ${CHROOT}/usr/lib cp -p /usr/lib/libutil.so.* ${CHROOT}/usr/lib cp -p /usr/lib/libstdc++.so.* ${CHROOT}/usr/lib cp -p /usr/lib/libm.so.* ${CHROOT}/usr/lib cp -p /usr/lib/libc.so.* ${CHROOT}/usr/lib cp -p /usr/libexec/ld.so ${CHROOT}/usr/libexec cp -p /usr/lib/libz.so.* ${CHROOT}/usr/lib cp -p /usr/lib/libpthread.so.* ${CHROOT}/usr/lib cp -p /usr/lib/libutil.so.* ${CHROOT}/usr/lib cp -p /usr/lib/libm.so.* ${CHROOT}/usr/lib cp -p /usr/lib/libssl.so* ${CHROOT}/usr/lib # libcrypto required for OpenBSD 6.0 cp -p /usr/lib/libcrypto.so* ${CHROOT}/usr/lib cp -p /etc/pwd.db ${CHROOT}/etc cp -pr /usr/local/lib/python2.7 ${CHROOT}/usr/local/lib # build ld.hints.so file so python can find its libraries chroot ${CHROOT} /sbin/ldconfig /usr/local/lib
The following resources helped:
httpd
configuration file
# magenta httpd.conf # Macros ext_addr="*" # # Global Options # # prefork 3 chroot "/home/www" # # Servers # # A name-based "virtual" server server "magenta.hydrus.org.uk" { alias "magenta" listen on $ext_addr port 80 root "/hydrus/data" log access "hydrus-access.log" log error "hydrus-error.log" location "/cgi-bin/*" { fastcgi } }