← All documentation  |  Playground

Deploying on cPanel

Deploying AutoDoc on cPanel

This guide describes deploying AutoDoc on a cPanel server using the Setup Python App feature and Phusion Passenger, plus the portable LibreOffice install required for real page counting and preview/generation.


Prerequisites


Repository Location

Clone outside the web root, e.g. /home/<cpanel-user>/autodoc. Do not place it inside public_html.


Python Application

Create a Python application in cPanel:


Dependencies

Includes both pyproject.toml and requirements.txt. Click Ensure Dependencies in cPanel after every git pull that touches either file — several features (python-docx, pypdf, python-multipart, markdown) were added incrementally, and a missed "Ensure Dependencies" step is a common cause of a generic 500 error after deploying a new feature.


Passenger Startup File

import os
import sys

from a2wsgi import ASGIMiddleware

BASE_DIR = os.path.dirname(__file__)
SRC_DIR = os.path.join(BASE_DIR, "src")

if SRC_DIR not in sys.path:
    sys.path.insert(0, SRC_DIR)

from autodoc.app import app

application = ASGIMiddleware(app)

Environment variables (.env)

Beyond the standard DATABASE_URL/SECRET_KEY/APPLICATION_NAME, AutoDoc needs:

LIBREOFFICE_PATH=/home/<cpanel-user>/opt/libreoffice/opt/libreoffice24.8/program/soffice

ENABLE_PROJECT_GENERATOR should be left unset — AutoDoc is a leaf application, not a project-generator template; that feature is intentionally disabled here.


Installing LibreOffice (portable, no root)

Shared cPanel hosting has no root access, so a normal package-manager install isn't possible. LibreOffice's official tarballs can be extracted directly into the account's own home directory instead — no system-wide changes, isolated entirely to this account, trivially removable.

Check the server's glibc version first — this determines which LibreOffice release will actually run:

ldd --version | head -1

This server has glibc 2.28. The current LibreOffice release (26.x at time of writing) requires a newer glibc than that and fails at runtime with GLIBC_2.3x not found errors. LibreOffice 24.8.7.2 was confirmed to work on this server — if glibc is upgraded later, a newer LibreOffice release could be tried again (check https://download.documentfoundation.org/libreoffice/stable/ for current releases, or the old/ archive for earlier ones if the current release needs a newer glibc).

# Download and extract the bundle
mkdir -p ~/opt/libreoffice_src ~/opt/libreoffice
cd ~/opt/libreoffice_src
wget https://downloadarchive.documentfoundation.org/libreoffice/old/24.8.7.2/rpm/x86_64/LibreOffice_24.8.7.2_Linux_x86-64_rpm.tar.gz
tar xzf LibreOffice_24.8.7.2_Linux_x86-64_rpm.tar.gz

# Extract every .rpm inside into ~/opt/libreoffice WITHOUT installing them
# (rpm2cpio/cpio are standard tools on any RPM-based Linux, no root needed)
cd ~/opt/libreoffice_src/LibreOffice_24.8.7.2_Linux_x86-64_rpm/RPMS
for f in *.rpm; do rpm2cpio "$f" | (cd ~/opt/libreoffice && cpio -idm); done

# Find the soffice binary
find ~/opt/libreoffice -name soffice -type f
# -> /home/<cpanel-user>/opt/libreoffice/opt/libreoffice24.8/program/soffice

# Clean up the download/extraction leftovers (only ~/opt/libreoffice itself is needed)
rm -rf ~/opt/libreoffice_src

Test it directly before wiring it into the app:

echo "test" > /tmp/lo_test.txt
~/opt/libreoffice/opt/libreoffice24.8/program/soffice --headless --convert-to pdf --outdir /tmp -env:UserInstallation=file:///tmp/lo_profile /tmp/lo_test.txt
ls -la /tmp/lo_test.pdf   # should exist
rm -f /tmp/lo_test.txt /tmp/lo_test.pdf
rm -rf /tmp/lo_profile

If this fails with a GLIBC_2.3x not found error, the chosen LibreOffice version is too new for this server — try an older release from the old/ archive.

Finally, add the path to .env (see above) and restart the app. The install is ~696MB.


Deployment Workflow

  1. Commit and push locally.
  2. SSH into the server, cd ~/autodoc && git pull origin main.
  3. Click Ensure Dependencies in cPanel if requirements.txt/pyproject.toml changed.
  4. Restart: touch tmp/restart.txt.
  5. Verify — check /health, and if the change touched documents, actually upload a test .docx and confirm the response.

A recurring gotcha: NOT NULL columns need a manual step

The app auto-migrates nullable columns on every startup (sync_missing_columns() in database/config.py), but a NOT NULL column added to an existing model will not be added automatically to a table that already exists — the safe path is to DROP TABLE <table> (only when it holds no real data yet) and let it recreate on the next restart:

mysql -u indiapri_autodoc_user -p indiapri_autodoc -e "DROP TABLE IF EXISTS <table>;"
touch tmp/restart.txt

This has come up twice already (documents.values/page_count, then app_settings.min_font_size_pt) — if a deploy causes a generic 500 error right after adding a new required model field, this is the first thing to check.


Project Layout

/home/<cpanel-user>/
├── autodoc/
│   ├── passenger_wsgi.py
│   ├── requirements.txt
│   ├── pyproject.toml
│   ├── src/autodoc/
│   └── var/uploads/           # uploaded .docx templates, git-ignored
└── opt/
    └── libreoffice/           # portable LibreOffice install, git-ignored, ~696MB