I spent a couple of hours today trying to figure out how to configure Apache Web Server on Mac OS X to execute Python scripts, so I thought I would document the process for my own reference.
OS X is preinstalled with Apache and Python. Apache executable (apachectl) is at /usr/sbin/apachectl and Python is at /usr/bin/python. But the configurations for Apache are at /etc/apache2, specifically in the file httpd.conf. If you open the file and look for DocumentRoot, you will find that default document root is set to /Library/WebServer/Documents.
I did not want to change the default doc root but at the same time did not want to store my scripts in the default folder. I could have created a virtual host or an alias. I decided to do the later because it is simpler than creating virtual host; and I was configuring Python for development only. So just below the document root setting I added the alias –
The idea was to access my Python scripts using url localhost/py/*.py.
I create a simple test file test.py in /Users/Ram/Sites with following content –
Set execute permission for this file (chomod +x test.py).
I then restarted Apache – actually first stopped it (sudo apachectl stop) and then started again (sudo apachectl start). I read somewhere that restart option does not work.
I then browsed to localhost/py/test.py and expected it to display “Apache-Python config working!”. But instead I got “403 Forbidden You don’t have permission to access …” error. When I checked the error log (at /var/log/apache2) I saw –
“Permission denied: access to /py/test.py denied (filesystem path ‘/Users/Ram/Sites’) because search permissions are missing on a component of the path” error.
The solution to fix this issue is described in the Apache Wiki . Apparently it was not enough to set execute permission on individual script file – I had to provide execute permissions for the current folder (/Users/Ram/Sites), and all its parents till the Users folder (/User/Ram and /User).
After above changes the Python script executed successfully.
I was working on a similar setup in Docker (Apache + Python), with one difference that the version of Apache was 2.4.25. Strangely the above solution did not work till I appended ‘*’ to the directory path in httpd.conf –
<Directory "/usr/local/apache2/htdocs/*" > Options +ExecCGI AllowOverride All Require all granted AddHandler cgi-script .py </Directory>