Thank you for visiting!
My little window on internet allowing me to share several of my passions
Categories:
- got
- OpenBSD
- FreeBSD
- PEKwm
- Zsh
- Nvim
- VM
- High Availability
- vdcron
- My Sysupgrade
- FreeBSD
- Nas
- VPN
- DragonflyBSD
- fapws
- Alpine Linux
- Openbox
- Desktop
- Security
- yabitrot
- nmctl
- Tint2
- Firewall
- Project Management
- Hifi
- Alarm
Most Popular Articles:
Last Articles:
Install python3 inside an OpenBSD chroot environment for later cgi scripts
Posted on 2026-02-17 20:19:00 from Vincent in got
On OpenBSD, the built-in httpd runs inside a strict chroot located at /var/www, which greatly improves security but also limits available system resources. When trying to execute Python CGI scripts, administrators often encounter missing shared library errors. This happens because the chroot environment does not automatically include the base system libraries required by Python. In this article, we’ll walk through the exact steps needed to properly install Python 3.12 inside the OpenBSD chroot and make it fully functional.

Installing Python 3.12 Inside an OpenBSD Chroot (httpd /var/www)
Running CGI scripts with OpenBSD’s httpd, or nginx, means working inside the default chroot located at /var/www.
If you try to execute a Python script inside that chroot without preparing the environment correctly, you will quickly face missing library errors such as:
ld.so: python3.12: can't load library 'libpython3.12.so.0.0'
This article explains step-by-step how to properly install Python 3.12 inside /var/www and resolve all required shared library dependencies.
1. Preparing the /dev Directory Inside the Chroot
The chroot needs its own minimal /dev structure.
mkdir /var/www/dev
cp /dev/MAKEDEV /var/www/dev
cd /var/www/dev
./MAKEDEV std
This creates the standard device nodes required for basic operation.
2. Preparing the Dynamic Linker Environment
The dynamic linker inside the chroot must know where to find shared libraries.
Create Required Directories
cd /var/www
mkdir etc
mkdir sbin
Configure Library Search Paths
Create /var/www/etc/ld.so.conf:
echo "/usr/lib" >> etc/ld.so.conf
echo "/usr/local/lib" >> etc/ld.so.conf
Copy ldconfig Into the Chroot
cp /sbin/ldconfig sbin
Generate the Library Cache
chroot /var/www ldconfig /usr/lib /usr/local/lib
At this stage, the chroot is capable of handling shared libraries — provided they exist inside it.
3. Attempting to Install Python
Now try installing Python into the chroot:
pkg_add -B /var/www python
You will likely see errors like:
Can't install python-3.12.11 because of libraries
| library crypto.57.1 not found
| library curses.16.0 not found
| library expat.17.0 not found
| library panel.7.0 not found
| library pthread.28.0 not found
| library readline.6.0 not found
| library ssl.60.1 not found
This happens because pkg_add -B installs into the alternate root but does not automatically copy base system shared libraries into the chroot.
4. Manually Copy Required Shared Libraries
You must manually copy the required libraries from the host system into the chroot.
Copy Base System Libraries
cd /usr/lib
cp -p libcrypto.so.* libssl.so.* libcurses.so.* libpanel.so.* libexpat.so.* libpthread.so.* libreadline.so.* /var/www/usr/lib/
Copy other required Libraries
cp /usr/local/lib/libintl.so.8.1 /var/www/usr/local/lib/
cp /usr/local/lib/libiconv.so.7.1 /var/www/usr/local/lib/
cp /usr/lib/libpthread.so.28.0 /var/www/usr/lib/
Make sure the directory structure exists:
mkdir -p /var/www/usr/lib
mkdir -p /var/www/usr/local/lib
5. Run pkg_add Again
Now retry:
pkg_add -B /var/www python
This time, the installation should proceed correctly.
6. Why This Is Necessary
In OpenBSD:
- The base system libraries live in
/usr/lib - Third-party packages live in
/usr/local/lib httpdruns inside/var/www- The chroot is intentionally minimal to enhance security
Because of this isolation, shared libraries must be explicitly present inside the chroot, otherwise the dynamic linker cannot resolve dependencies.
7. Important Notes
- Every OpenBSD upgrade may change library versions → you must re-copy updated
.sofiles. - Running
ldd /path/to/binaryhelps identify missing dependencies. - Keep the chroot minimal — only copy what is strictly required.
- If you need additional Python modules later, you may have to copy further dependencies.
8. Conclusion
You now have:
- A working Python 3.12 installation inside
/var/www - A functional dynamic linker configuration
- A properly prepared chroot environment for CGI scripts
This setup allows you to safely run Python-based CGI scripts under OpenBSD’s httpd while keeping the strong security model of the default chroot.