Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Yes. An Ubuntu LAMP server can host Python and PHP side by side. Install Apache and Ubuntu’s libapache2-mod-wsgi-py3 package, place the Python application in a project-owned virtual environment, expose an application WSGI callable, and map it with WSGIScriptAlias in a virtual host. Run the app in an isolated mod_wsgi daemon process, leave PHP locations handled by Apache’s PHP module, test the configuration, and add HTTPS before publishing the site.

What the finished setup looks like

Apache remains the public web server. It receives requests on ports 80 and 443, selects a virtual host from the host name, and then routes each URL according to its handler:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • PHP URLs are handled by the PHP module already used by the LAMP site.
  • Python WSGI URLs are sent through WSGIScriptAlias to a WSGI entry file.
  • Static assets such as CSS, JavaScript, images, and downloadable files are served directly by Apache when an Alias is configured.

mod_wsgi loads Python into Apache-managed processes and calls the WSGI application for matching requests. In the recommended daemon arrangement, the Python application receives its own mod_wsgi process group instead of sharing an application process with unrelated Apache modules.

Component Role Typical location or command
Ubuntu Operating system and package manager apt
Apache HTTP Server Public HTTP/HTTPS listener, virtual hosts, static files, PHP routing /etc/apache2/
mod_wsgi Connects Apache to a Python WSGI callable libapache2-mod-wsgi-py3
Virtual environment Isolates the application’s Python packages /srv/myapp/.venv
WSGI entry file Exports a callable named application /srv/myapp/myapp.wsgi
Database Optional application data service in the LAMP stack Use the database engine and credentials required by the app

Requirements and boundaries to check first

  • An Ubuntu server with administrative access and enough memory for Apache, PHP, the Python application, and its database workload.
  • The application must be WSGI-compatible, as Flask and Django are. FastAPI and Starlette are ASGI frameworks and do not natively run on a WSGI server.
  • The Python interpreter used to create the virtual environment must be compatible with the Python installation against which mod_wsgi was built.
  • The application files and virtual environment must be readable and traversable by the Apache service account. A private home directory that denies traversal will cause import or permission failures.
  • For public traffic, DNS should point the site name to the server and firewall rules should allow the required HTTP and HTTPS ports.

Ubuntu’s supported package route is Apache plus libapache2-mod-wsgi-py3. A virtual environment separates packages, but it cannot change the Python version embedded in the mod_wsgi module.

#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter | 4Pack Type C Female to A Male Cable Converter for Apple Duo 17 16 15 14 Plus,iWatch Watch 12 11 10,iPad 9 8 Air,Airpods 5 4
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.

Install Apache and Ubuntu’s mod_wsgi package

Update package metadata and install Apache:

sudo apt update
sudo apt install apache2

Install the distribution WSGI module:

sudo apt install libapache2-mod-wsgi-py3

Ubuntu enables the module automatically when the package is installed. If it was disabled previously, enable it explicitly and restart Apache after changing modules:

sudo a2enmod wsgi
sudo systemctl restart apache2

Confirm that Apache can see the module:

apache2ctl -M | grep wsgi

The command should show a loaded WSGI module. If it does not, inspect the package installation and run sudo a2enmod wsgi again before continuing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Create an application directory and virtual environment

Keep deployable application code in a service-oriented path such as /srv/myapp, rather than in a user’s home directory with restrictive permissions. Create the directory, install the Python virtual-environment support if it is not already present, and create the environment with the system interpreter:

sudo mkdir -p /srv/myapp
sudo apt install python3 python3-venv
sudo python3 -m venv /srv/myapp/.venv

Copy or deploy the application into /srv/myapp. Install the exact, pinned dependencies with the virtual environment’s interpreter:

sudo /srv/myapp/.venv/bin/python -m pip install --upgrade pip
sudo /srv/myapp/.venv/bin/python -m pip install -r /srv/myapp/requirements.txt

Do not assume that activating a shell environment changes what Apache uses. Apache will use the interpreter and packages selected by the mod_wsgi daemon configuration. The environment should be created with the same Python installation used to build the installed mod_wsgi module; a virtual environment built with a different Python major or minor version cannot make that module load another interpreter.

Set ownership deliberately. A common pattern is to let a deployment account own releases while granting the Apache service account read and execute access. The exact account names and permissions depend on your deployment process, but Apache must be able to traverse every parent directory, read the WSGI file and Python modules, and read static files.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter | USB C Dongle with 90W Max Power Delivery, 3×5Gbps USB A Data Ports, for MacBook, Dell, and More (Charger Not Included)
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.

Expose the WSGI application

mod_wsgi looks for a callable named application. The file can have any name, but a .wsgi suffix makes its purpose clear.

Flask entry file

If your Flask package defines an object named app in myapp/__init__.py or another importable module, create /srv/myapp/myapp.wsgi:

from myapp import app as application

The directory containing the myapp package must be on Python’s import path. The daemon configuration below supplies /srv/myapp as python-path.

Django entry file

Django normally generates a WSGI module inside the project package. A typical generated file contains:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import os
from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
application = get_wsgi_application()

You can point Apache directly at that generated file, or create a small wrapper that imports it. Use the project’s real settings module name, and verify that the Django package is installed in the selected virtual environment.

Configure an Apache virtual host in daemon mode

Create a site file under /etc/apache2/sites-available/, for example /etc/apache2/sites-available/myapp.conf. The following example mounts the Python application at /myapp and serves its static directory directly:

Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter | 85W Max PD, 2 USB 3.0 & 1 USBC Data Ports, SD/TF Card Reader, for Laptops/Mac and Other Type C Devices (Charger Not Included)
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
<VirtualHost *:80>
    ServerName example.com

    WSGIDaemonProcess myapp 
        python-home=/srv/myapp/.venv 
        python-path=/srv/myapp
    WSGIProcessGroup myapp
    WSGIScriptAlias /myapp /srv/myapp/myapp.wsgi

    <Directory /srv/myapp>
        Require all granted
    </Directory>

    Alias /myapp/static /srv/myapp/static
    <Directory /srv/myapp/static>
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/myapp-error.log
    CustomLog ${APACHE_LOG_DIR}/myapp-access.log combined
</VirtualHost>

Replace example.com, the URL prefix, the project path, and the static directory with values from your deployment. The important directives are:

Directive Purpose
WSGIDaemonProcess Creates a named daemon process group and selects the virtual environment and project import path.
WSGIProcessGroup Assigns requests handled by this virtual host to that daemon group.
WSGIScriptAlias Maps a URL prefix to the WSGI script that exposes application.
Alias Maps a URL for files Apache should serve without invoking Python.
<Directory> Grants Apache permission to serve or read the specified filesystem path.

Do not expose the entire project directory as a downloadable directory. The broad <Directory /srv/myapp> permission is convenient for a simple deployment, but a hardened configuration can grant access only to the WSGI file and the specific static or media directories while keeping source files inaccessible to direct requests.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Enable the site, validate Apache, and make the first request

  1. Enable the virtual host:
    sudo a2ensite myapp.conf
  2. Check Apache’s syntax before reloading:
    sudo apache2ctl configtest

    Continue only when it reports Syntax OK.

  3. Reload Apache so existing connections are handled gracefully:
    sudo systemctl reload apache2
  4. Request the mapped URL locally or from a browser, such as http://example.com/myapp/.
  5. Watch the site-specific and global logs while testing:
    sudo tail -f /var/log/apache2/myapp-error.log
    sudo tail -f /var/log/apache2/error.log

If you changed a loaded module rather than only a virtual host, restart Apache instead of relying on a reload:

sudo systemctl restart apache2

Flask-specific deployment details

Keep the Flask application object importable without running a development server. The WSGI file should import the object; it should not call app.run(). Environment-specific settings, secrets, and database URLs should be provided through the service’s environment or a protected configuration mechanism rather than committed to source control.

When the application is mounted below a prefix such as /myapp, confirm that URL generation, static paths, and any framework proxy settings understand that prefix. If the application is intended to occupy the whole host name, map the root URL instead:

WSGIScriptAlias / /srv/myapp/myapp.wsgi

Use one approach consistently; defining overlapping aliases can make it unclear which handler receives a request.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray | Data transfer & Fast charging for MacBook, iPhone 17/16/15, iPad, Samsung Galaxy, Apple Watch
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft

Django-specific deployment details

Run Django’s deployment preparation commands with the virtual environment’s interpreter. For a project that uses collected static files, a typical command is:

sudo /srv/myapp/.venv/bin/python /srv/myapp/manage.py collectstatic

Point the Apache Alias at the directory configured by Django’s STATIC_ROOT. Keep user-uploaded media in a separate directory and grant Apache read access only when the application’s policy allows direct downloads. Database migrations should be run as a controlled deployment step, not automatically on every Apache request.

Serve PHP and Python on the same Ubuntu server

Apache chooses a handler by URL and configuration, so a LAMP site can keep PHP at one set of paths and route Python at another. For example, an existing document root can continue to serve /index.php, while /myapp/ is handled by WSGIScriptAlias. Use separate virtual hosts when the applications have different domain names; use URL prefixes only when the applications are designed to coexist under one host.

Requirement Recommended arrangement
PHP and Python on different domains One Apache virtual host per domain, with the appropriate handler in each host.
PHP at the root and Python under a path Keep the PHP document root and add a non-overlapping WSGIScriptAlias such as /myapp.
Shared static assets Use explicit Apache Alias directives and directory permissions; do not make Python generate files Apache can serve directly.
Different Python runtimes Do not attempt to select another runtime with a second virtual environment in the same Apache instance; use separate mod_wsgi instances and a proxying front end.

Test for accidental URL overlap. A broad WSGI alias at / will capture requests that you expected PHP or static-file rules to handle.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Static files, uploads, and permissions

Serving static files directly from Apache avoids sending every image, stylesheet, or JavaScript request through Python. Use an Alias and a matching <Directory> block for each public directory. Keep application source, virtual-environment files, private configuration, and logs outside publicly aliased paths.

  • Grant read permission to files and execute permission on each parent directory Apache must traverse.
  • Use a dedicated media directory for user uploads and decide explicitly whether uploads are public.
  • Do not grant write permission to the Apache account across the whole application tree. If the app must write uploads, limit write access to the upload directory.
  • After each deployment, verify that the static URL returns the file directly and that a private source file cannot be downloaded.

WSGI versus ASGI: when Apache alone is not enough

Flask and Django can expose WSGI callables, so mod_wsgi is suitable for them when their dependencies and deployment mode are compatible. FastAPI and Starlette are ASGI frameworks; they do not natively run on a WSGI server. For those applications, run an ASGI-compatible server as a separate process and configure Apache as a reverse proxy to that process. The proxy design should include a local bind address, a controlled service account, timeout settings appropriate to the application, and log forwarding. Do not point WSGIScriptAlias at an ASGI application and expect it to work.

Best Value
Sale
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display | 85W Max PD, 1 Powered USB-C 5Gbps & 2 Powered USB-A 3.0 5Gbps Data Ports, for MacBook Pro, MacBook Air, Dell and More (Black)
  • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
  • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
  • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
  • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
  • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Python versions and mod_wsgi limits

Apache loads one copy of the mod_wsgi module, and that module has one Python library linked into it. Consequently, one Apache instance cannot simultaneously host one application requiring Python 3.10 and another requiring Python 3.12 merely by giving each application a different virtual environment. Virtual environments isolate packages, not the interpreter embedded in mod_wsgi.

Situation What works What does not
Several apps using the same linked Python version Separate virtual environments and separate daemon process groups. Sharing one environment when dependency versions conflict.
Apps requiring different linked Python versions Separate mod_wsgi-express instances, each built for its Python, behind a front-end Apache proxy. Trying to solve the mismatch with python-home alone.
Distribution mod_wsgi versus a PyPI-built module Use the Ubuntu package for the system Python, or build mod_wsgi deliberately for the desired interpreter and operate that instance separately. Mixing a module built for one interpreter with a virtual environment created by another.

The distribution package is the simplest supported path on Ubuntu. A custom PyPI-built mod_wsgi can be appropriate when an application needs a Python version not provided by the distribution package, but it adds build, upgrade, and service-management responsibilities.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Embedded mode versus daemon mode

In embedded mode, mod_wsgi runs application code inside Apache worker processes. Daemon mode gives the application a named process group with its own restart and resource boundary. For ordinary deployments, daemon mode is the safer default because it reduces interaction with unrelated Apache modules and makes per-application virtual-environment settings explicit.

Characteristic Embedded mode Daemon mode
Process ownership Apache worker processes Dedicated mod_wsgi daemon processes
Isolation from other sites Lower Higher
Per-application Python settings Less explicit Configured with WSGIDaemonProcess
Default choice for separate production apps Usually not preferred Usually preferred

Add HTTPS before public exposure

Do not leave a production login, session cookie, admin interface, or API on plain HTTP. Ubuntu documents Apache’s SSL module and a default SSL virtual-host configuration. Enable SSL support and the default SSL site when appropriate:

sudo a2enmod ssl
sudo a2ensite default-ssl
sudo systemctl reload apache2

Install a certificate through a separately verified certificate workflow, then configure the certificate and key paths in the TLS virtual host. Replace the example HTTP virtual host’s ServerName, preserve the same WSGI daemon and alias rules in the HTTPS host, and redirect HTTP to HTTPS only after confirming the secure host works. Protect the private key with restrictive filesystem permissions and renew certificates before expiry.

Troubleshooting by symptom

Apache reports a syntax error

  • Run sudo apache2ctl configtest and fix the first reported file and line before addressing later messages.
  • Check that WSGIDaemonProcess, WSGIProcessGroup, and WSGIScriptAlias are spelled exactly and appear in a context supported by your installed module.
  • Confirm that the site file is enabled and that a duplicate virtual host is not receiving the request.

The browser returns HTTP 500

  • Read the site-specific error log and the global Apache error log at the moment of the request.
  • Look for an import error, missing package, syntax error, database connection failure, or permission denial.
  • Run the import manually with the same virtual-environment interpreter:
    sudo -u www-data /srv/myapp/.venv/bin/python -c "from myapp import app; print(app)"

    Adjust the module and service account to your deployment.

  • Verify that python-home points to the virtual environment itself and that python-path points to the directory containing the application package.

The application imports locally but not under Apache

  • Your shell may be using a different Python executable or a different current directory.
  • Check the permissions on every parent directory between / and the project files.
  • Confirm that dependencies were installed into /srv/myapp/.venv, not into a user’s unrelated environment.
  • Ensure the WSGI file exports application and does not start a development server.

Static files return 404 or 403

  • Compare the URL in the browser with the exact Alias prefix.
  • Check that the filesystem path exists and that the <Directory> block grants access.
  • For a 403, inspect directory traversal and file-read permissions for the Apache service account.
  • For Django, run collectstatic and point the alias at STATIC_ROOT, not at an arbitrary source directory.

The wrong application or PHP handles the request

  • Check the requested host name and the order of enabled virtual hosts.
  • Look for overlapping aliases, especially a root-level WSGIScriptAlias / that captures PHP or static paths.
  • Use separate host names when URL-prefix routing would create ambiguous ownership.

A different Python version is required

Changing only python-home will not change the Python linked into mod_wsgi. Build or install a mod_wsgi instance for the required interpreter, run it separately, and place a front-end Apache in proxy mode when multiple interpreter versions must be served on one machine.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Production checklist

  • Pin application dependencies and record the Python version used to create the virtual environment.
  • Run Apache’s configuration check before every reload.
  • Keep WSGI applications in daemon mode unless a specific compatibility reason requires another arrangement.
  • Separate application source, private settings, static files, and user uploads.
  • Give Apache only the read or write permissions it actually needs.
  • Configure application and Apache logs, then rotate and monitor them.
  • Test failure recovery: restart Apache, redeploy a dependency, and verify that the site returns without manual shell activation.
  • Use HTTPS for every public endpoint and protect certificate keys.
  • Back up application data and database contents independently of the web-server configuration.
  • For ASGI applications, use an ASGI server and reverse-proxy architecture rather than mod_wsgi.

Choosing the deployment shape

Need Recommended design Reason
One Flask or Django app on Ubuntu Ubuntu Apache, distribution mod_wsgi, one virtual environment, daemon mode Uses the supported package path with clear process isolation.
Several WSGI apps on the same Python version One daemon process group and virtual environment per app Separates package sets while sharing the Apache-linked interpreter.
PHP and one Python app on one domain Keep PHP in its existing document root and map Python under a non-overlapping prefix Apache can dispatch each URL family to its correct handler.
Python apps needing different interpreter versions Separate mod_wsgi instances behind a proxying Apache One Apache-loaded mod_wsgi module cannot link two Python versions.
FastAPI or Starlette ASGI server behind Apache reverse proxy These frameworks are ASGI, not native WSGI applications.

Commands at a glance

sudo apt update
sudo apt install apache2 libapache2-mod-wsgi-py3 python3-venv
sudo a2enmod wsgi
sudo mkdir -p /srv/myapp
sudo python3 -m venv /srv/myapp/.venv
sudo /srv/myapp/.venv/bin/python -m pip install -r /srv/myapp/requirements.txt
sudo a2ensite myapp.conf
sudo apache2ctl configtest
sudo systemctl reload apache2

The commands install the server components and prepare the environment; the application’s WSGI file, virtual-host paths, permissions, dependency list, database settings, and HTTPS certificate still need to be configured for the particular project.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.