Skip to content

Installation with Apache and mod_wsgi

The most convenient installation of the Syncer is using Docker, where all dependencies are satisfied automatically. For bare-metal or VM deployments, this guide covers installation with Apache and mod_wsgi.

mod_wsgi must match the venv's Python version

The distro packages (python3-mod_wsgi, libapache2-mod-wsgi-py3) are compiled against the system Python — typically older than the Python you run the syncer with (e.g. RHEL 9 ships python3.9, Debian 12 ships python3.11, while the syncer needs 3.14). A mismatch surfaces as ModuleNotFoundError: No module named 'application' because mod_wsgi looks in venv/lib/python<wrong>/site-packages instead of the venv's actual site-packages.

The reliable fix is to build mod_wsgi from the venv itself so Apache loads a mod_wsgi.so linked against the same Python that runs the syncer. The instructions below do exactly that.

Base Requirements

dnf install httpd httpd-devel
dnf groupinstall "Development Tools"
dnf install python3.14 python3.14-devel
apt install apache2 apache2-dev build-essential
apt install python3.14 python3.14-dev

The *-devel / *-dev and build-tool packages are needed once to compile mod_wsgi against the venv's Python. They can be removed afterwards.

Also needed is MongoDB — covered in the MongoDB section below.

Install the Syncer

Install the application from PyPI first — follow Installation from PyPI up to and including Customize the Configuration, then come back here. After that step you have:

  • /opt/cmdbsyncer/venv — virtual environment with the cmdbsyncer package installed
  • /opt/cmdbsyncer/local_config.py — generated by cmdbsyncer sys self_configure
  • /opt/cmdbsyncer/app.wsgi — also generated by self_configure, this is what WSGIScriptAlias points at in the vhost below

Installing from the Git checkout instead

If you prefer to run from a Git clone (for development or to track lts/3.12), follow Installation from Code instead — the rest of this guide applies unchanged.

Build mod_wsgi from the venv

Build mod_wsgi inside the same virtual environment so Apache loads a module linked against the syncer's Python:

source /opt/cmdbsyncer/venv/bin/activate
pip install mod_wsgi
mod_wsgi-express module-config

The last command prints two lines, e.g.:

LoadModule wsgi_module "/opt/cmdbsyncer/venv/lib/python3.14/site-packages/mod_wsgi/server/mod_wsgi-py314.cpython-314-x86_64-linux-gnu.so"
WSGIPythonHome "/opt/cmdbsyncer/venv"

Drop both lines into your Apache config so they load before the vhost. The exact filename is fine — copy it verbatim from your output.

mod_wsgi-express module-config | sudo tee /etc/httpd/conf.modules.d/10-wsgi.conf
mod_wsgi-express module-config | sudo tee /etc/apache2/mods-available/wsgi.load
sudo a2enmod wsgi
# Make sure no distro mod_wsgi is also loaded:
sudo apt remove -y libapache2-mod-wsgi-py3

Do not also load the distro mod_wsgi

Loading both the distro libapache2-mod-wsgi-py3 / python3-mod_wsgi and the venv-built one ends in Cannot load mod_wsgi.so or a silent version mismatch. Pick exactly one — the venv build above is the one this guide expects.

Configure Apache

Create /etc/httpd/conf.d/cmdbsyncer.conf:

<VirtualHost *:80>
    ServerName example.com

    WSGIDaemonProcess cmdbsyncer python-home=/opt/cmdbsyncer/venv user=apache group=apache threads=5
    WSGIScriptAlias / /opt/cmdbsyncer/app.wsgi
    WSGIPassAuthorization On

    <Directory /opt/cmdbsyncer>
        WSGIProcessGroup cmdbsyncer
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
</VirtualHost>

Create /etc/apache2/sites-available/cmdbsyncer.conf:

<VirtualHost *:80>
    ServerName example.com

    WSGIDaemonProcess cmdbsyncer python-home=/opt/cmdbsyncer/venv user=www-data group=www-data threads=5
    WSGIScriptAlias / /opt/cmdbsyncer/app.wsgi
    WSGIPassAuthorization On

    <Directory /opt/cmdbsyncer>
        WSGIProcessGroup cmdbsyncer
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
</VirtualHost>

Then enable the site:

a2ensite cmdbsyncer && systemctl reload apache2

HTTPS with SSL Certificate

To run the Syncer over HTTPS, extend the VirtualHost with an SSL block and add a redirect from port 80. Replace the certificate paths with your actual files (e.g. from Let's Encrypt or your CA).

Make sure mod_ssl is installed: dnf install mod_ssl

<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com

    SSLEngine on
    SSLCertificateFile      /etc/pki/tls/certs/example.com.crt
    SSLCertificateKeyFile   /etc/pki/tls/private/example.com.key
    # SSLCertificateChainFile /etc/pki/tls/certs/ca-bundle.crt

    WSGIDaemonProcess cmdbsyncer python-home=/opt/cmdbsyncer/venv user=apache group=apache threads=5
    WSGIScriptAlias / /opt/cmdbsyncer/app.wsgi
    WSGIPassAuthorization On

    <Directory /opt/cmdbsyncer>
        WSGIProcessGroup cmdbsyncer
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
</VirtualHost>

Make sure mod_ssl is enabled: a2enmod ssl

<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com

    SSLEngine on
    SSLCertificateFile      /etc/ssl/certs/example.com.crt
    SSLCertificateKeyFile   /etc/ssl/private/example.com.key
    # SSLCertificateChainFile /etc/ssl/certs/ca-bundle.crt

    WSGIDaemonProcess cmdbsyncer python-home=/opt/cmdbsyncer/venv user=www-data group=www-data threads=5
    WSGIScriptAlias / /opt/cmdbsyncer/app.wsgi
    WSGIPassAuthorization On

    <Directory /opt/cmdbsyncer>
        WSGIProcessGroup cmdbsyncer
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
</VirtualHost>

Then enable the site:

a2ensite cmdbsyncer && systemctl reload apache2

Let's Encrypt

On both distros you can use Certbot to obtain a free certificate automatically:

# RedHat / CentOS
dnf install certbot python3-certbot-apache
# Ubuntu / Debian
apt install certbot python3-certbot-apache

certbot --apache -d example.com

Certbot will update the VirtualHost config and set up automatic renewal.

Apache 2.2 (legacy)

Require all granted was introduced in Apache 2.4. On Apache 2.2 use the old syntax instead:

Order deny,allow
Allow from all

Apache 2.2 is end-of-life — upgrading to 2.4 is strongly recommended.

Key directives explained

Directive Why it is needed
WSGIPassAuthorization On Passes the Authorization HTTP header to the application. Required for REST API authentication — without it, Apache strips the header and all API logins fail.
WSGIDaemonProcess Runs the app in a separate process with its own Python environment.
WSGIApplicationGroup %{GLOBAL} Ensures C extensions (e.g. in the MongoDB driver) work correctly.

MongoDB

Create /etc/dnf.repos.d/mongodb.repo:

[mongodb-org-7.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/dnf/redhat/9/mongodb-org/7.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://pgp.mongodb.com/server-7.0.asc

Then install and start MongoDB:

dnf install -y mongodb-org
systemctl enable --now mongod

Follow the official MongoDB guide for Ubuntu, then run:

systemctl enable --now mongod

Troubleshooting

Access Denied in Apache log : SELinux is blocking access. Either disable it or set the correct context:

```bash
chcon -R -t httpd_sys_content_t /opt/cmdbsyncer
setsebool -P httpd_can_network_connect 1
```

API authentication always returns 401 : Check that WSGIPassAuthorization On is set in your VirtualHost config. Without it the Authorization header never reaches the application.

mod_wsgi uses wrong Python version : Verify that the installed mod_wsgi matches your Python version (python3.14-mod_wsgi for Python 3.14). Mismatches cause silent import failures at startup.

MongoDB fails with "Illegal instruction" or does not start : MongoDB 7.0+ requires AVX CPU instructions. If you are running in a virtual machine (e.g. Proxmox), the default CPU type (kvm64) does not expose AVX to the guest even if the host supports it.

Check whether AVX is available inside the VM:
```bash
grep avx /proc/cpuinfo
```

If the output is empty, configure the VM CPU type in Proxmox to expose AVX. Edit the VM config (e.g. `/etc/pve/qemu-server/<vmid>.conf`) and set a CPU type that includes AVX:
```
cpu: x86-64-v2-AES,flags=+avx;+avx2
```
Then restart the VM. Afterwards MongoDB should start normally.