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 thecmdbsyncerpackage installed/opt/cmdbsyncer/local_config.py— generated bycmdbsyncer sys self_configure/opt/cmdbsyncer/app.wsgi— also generated byself_configure, this is whatWSGIScriptAliaspoints 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.