Some Python libraries need a separate program to work. Examples are ffmpeg for audio and video, Tesseract for reading text in images and Chromium for browser automation. List these programs in a file called packages.txt, and Cloudilio installs them every time it builds your app.
A missing system package usually shows up as an error in your publish log or your app's logs. Match your error to a row below.
| If you see | You're using | Add these lines |
|---|---|---|
| FileNotFoundError ... 'ffmpeg' | pydub, Whisper, moviepy | ffmpeg |
| TesseractNotFoundError | pytesseract | tesseract-ocr |
| PDFInfoNotInstalledError | pdf2image | poppler-utils |
| cannot find Chrome binary | Selenium | chromiumchromium-driver |
| libGL.so.1: cannot open shared object file | OpenCV | libgl1libglib2.0-0t64 |
| cannot load library 'pango-1.0-0' | WeasyPrint | libpango-1.0-0libpangoft2-1.0-0libharfbuzz-subset0 |
| FileNotFoundError ... 'soffice' | LibreOffice conversions | libreoffice-writer-nogui |
| ExecutableNotFound ... 'dot' | graphviz, pydot | graphviz |
| Can not find valid pkg-config name | mysqlclient | default-libmysqlclient-devpkg-config |
| Could not find the GDAL library | GeoDjango | binutilslibproj-devgdal-bin |
For OpenCV, try opencv-python-headless in requirements.txt first. It needs no system packages. Our post How to Install System Packages for a Python App explains each package in this table, with code you can test.
Your app runs on Debian 13, also called trixie. It is the system behind the official Python images. Package names differ between Linux systems, so a name from an Ubuntu, Alpine or macOS guide may not work.
apt install or apt-get install.libGL.so.1, use the "search the contents of packages" form on the same site. It shows which package contains that file.
Names that end in -dev are for compiling code. You need them only when pip builds a library from source. A library installed from a ready-made wheel needs only the package without -dev.
Create a plain text file named packages.txt in the same folder as your requirements.txt. If your app sits in a subfolder of your project, put the file in that subfolder. Write one package name per line.
# Convert uploaded audio to MP3, for pydub ffmpeg # Read text in scanned receipts, for pytesseract tesseract-ocr tesseract-ocr-deu
# are comments. Text after a # on any line is skipped too.+, - and . only.apt.txt works the same way. If you have both files, Cloudilio installs the packages from both.packages.txt format, so files from there work unchanged.Publish a new version the way you normally do. To test without touching your live site, start a preview first. A preview builds the app the same way a publish does.
Open the publish log. Near the start of the build, you will see a line that lists your packages.
Installing system packages: ffmpeg, tesseract-ocr, tesseract-ocr-deu
Cloudilio installs system packages before your Python packages. A library that compiles against a system package while pip installs it, such as mysqlclient, finds it ready.
Add a quick check to your app's startup or a scheduled task you can run with Run now. This code prints where each program is installed, or None if it is missing.
import shutil
for program in ["ffmpeg", "tesseract"]:
print(program, shutil.which(program))
You don't need to list these. Every app has them already.
build-essential gives pip a C compiler for packages without a ready-made wheel.libpq-dev lets psycopg2 connect to PostgreSQL.curl downloads files from the command line.| Limit | Value |
|---|---|
| Packages per app | 50 |
| Time for one build | 15 minutes |
| Size of the built app | 5 GB |
| Package versions | The version in Debian's current release |
Large packages make each build slower. LibreOffice and the fonts-noto-cjk fonts are the largest common ones. Chromium and LibreOffice also need more memory than the 256 MB in the Starter plan. Plan for at least 1 GB.
"packages.txt, line 3: '...' isn't a valid package name"
That line has a character a Debian package name can't contain, such as a capital letter, a space inside a name, a semicolon or a version number like ffmpeg=7.1. Fix the line and publish again. Cloudilio checks every name before the build starts, so nothing else runs.
"E: Unable to locate package ..."
Debian has no package with that name. Check the spelling on packages.debian.org/trixie. Some older names changed in Debian 13. For example, libglib2.0-0 is now libglib2.0-0t64.
"Your project lists 51 system packages. The most allowed is 50."
Remove packages your code doesn't use. If you copied a long list from another guide, start with the packages from Step 1 and add more only when an error asks for them.
The build stops after 15 minutes
Large packages and large Python libraries together can take too long. Remove packages you don't need, or replace a heavy library with a lighter one. opencv-python-headless and PyMySQL need no system packages at all.
My app can't run apt-get
That's expected. Your app runs as a normal user without administrator rights, which keeps it safer. Install everything at build time with packages.txt.
Everything installed, but the program still isn't found
Check that packages.txt sits next to the requirements.txt Cloudilio uses, and that the publish log shows the "Installing system packages" line. Some libraries also need the program's path. Selenium, for example, needs /usr/bin/chromium and /usr/bin/chromedriver.