If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

This is an update to the installation script that is included in the web2py repo. In addition to what it originally did, it now:

  • Installs Python 2.6 (if required) to /opt and recompiles wsgi to support it
  • Installs web2py in /opt/web-apps/
  • Configures SELinux and iptables

The script goes from zero to running the welcome app without any additional changes required to the server. I have tested it on fresh minimal installs of both FC13 and CentOS 5.4 but I don't have a larger collection of servers to test it on.

echo "This script will:
1) Install modules needed to run web2py on Fedora and CentOS/RHEL
2) Install Python 2.6 to /opt and recompile wsgi if not provided
2) Install web2py in /opt/web-apps/
3) Configure SELinux and iptables
5) Create a self signed ssl certificate
6) Setup web2py with mod_wsgi
7) Create virtualhost entries so that web2py responds for '/'
8) Restart Apache.

You should probably read this script before running it.

Although SELinux permissions changes have been made,
further SELinux changes will be required for your personal
apps. (There may also be additional changes required for the
bundled apps.)  As a last resort, SELinux can be disabled.

A simple iptables configuration has been applied.  You may
want to review it to verify that it meets your needs.

Finally, if you require a proxy to access the Internet, please
set up your machine to do so before running this script.

Press ENTER to continue...[ctrl+C to abort]"

read CONFIRM

#!/bin/bash

###
###  Phase 0 - This may get messy.  Lets work from a temporary directory
###

current_dir=`pwd`

if [ -d /tmp/setup-web2py/ ]; then
    mv /tmp/setup-web2py/ /tmp/setup-web2py.old/
fi

mkdir -p /tmp/setup-web2py
cd /tmp/setup-web2py

###
###  Phase 1 - Requirements installation
###

echo
echo " - Installing packages"
echo

# Verify packages are up to date
yum update

# Install required packages
yum install httpd mod_ssl mod_wsgi wget python

# Verify we have at least Python 2.5
typeset -i version_major
typeset -i version_minor

version=`rpm --qf %{Version} -q python`
version_major=`echo ${version} | awk '{split($0, parts, "."); print parts[1]}'`
version_minor=`echo ${version} | awk '{split($0, parts, "."); print parts[2]}'`

if [ ! ${version_major} -ge 2 -o ! ${version_minor} -ge 5 ]; then
    # Setup 2.6 in /opt - based upon
    # http://markkoberlein.com/getting-python-26-with-django-11-together-on

    # Check for earlier Python 2.6 install
    if [ -e /opt/python2.6 ]; then
        # Is Python already installed?
        RETV=`/opt/python2.6/bin/python -V > /dev/null 2>&1; echo $?`
        if [ ${RETV} -eq 0 ]; then
            python_installed='True'
        else
            mv /opt/python2.6 /opt/python2.6-old
        fi
    fi

    # Install Python 2.6 if it doesn't exist already
    if [ ! "${python_installed}" == "True" ]; then
        # Install requirements for the Python build
        yum install sqlite-devel zlib-devel

        mkdir -p /opt/python2.6

        # Download and install
        wget http://www.python.org/ftp/python/2.6.4/Python-2.6.4.tgz
        tar -xzf Python-2.6.4.tgz
        cd Python-2.6.4
        ./configure --prefix=/opt/python2.6 --with-threads --enable-shared --with-zlib=/usr/include
        make && make install

        cd /tmp/setup-web2py
    fi

    # Create links for Python 2.6
    # even if it was previously installed just to be sure
    ln -s /opt/python2.6/lib/libpython2.6.so /usr/lib 
    ln -s /opt/python2.6/lib/libpython2.6.so.1.0 /usr/lib
    ln -s /opt/python2.6/bin/python /usr/local/bin/python
    ln -s /opt/python2.6/bin/python /usr/bin/python2.6 
    ln -s /opt/python2.6/lib/python2.6.so /opt/python2.6/lib/python2.6/config/

    # Update linker for new libraries
    /sbin/ldconfig

    # Rebuild wsgi to take advantage of Python 2.6
    yum install httpd-devel

    cd /tmp/setup-web2py

    wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
    tar -xzf mod_wsgi-3.3.tar.gz
    cd mod_wsgi-3.3
    ./configure --with-python=/usr/local/bin/python
    make &&  make install

    echo "LoadModule wsgi_module modules/mod_wsgi.so" > /etc/httpd/conf.d/wsgi.conf

    cd /tmp/setup-web2py
fi

### MySQL install untested!
# Install mysql packages (optional)
#yum install mysql mysql-server

# Enable mysql to start at boot (optional)
#chkconfig --levels 235 mysqld on
#service mysqld start

# Configure mysql security settings (not really optional if mysql installed)
#/usr/bin/mysql_secure_installation

###
### Phase 2 - Install web2py
###

echo
echo " - Downloading, installing, and starting web2py"
echo

# Create web-apps directory, if required
if [ ! -d "/opt/web-apps" ]; then
    mkdir -p /opt/web-apps

    chmod 755 /opt
    chmod 755 /opt/web-apps
fi

cd /opt/web-apps

# Download web2py
if [ -e web2py_src.zip* ]; then
    rm web2py_src.zip*
fi

wget http://web2py.com/examples/static/web2py_src.zip
unzip web2py_src.zip
chown -R apache:apache web2py

###
### Phase 3 - Setup SELinux context
###

# Set context for Python libraries if Python 2.6 installed
if [ -d /opt/python2.6 ]; then
    cd /opt/python2.6
    chcon -R -t lib_t lib/
fi

# Allow http_tmp_exec required for wsgi
RETV=`setsebool -P httpd_tmp_exec on > /dev/null 2>&1; echo $?`
if [ ! ${RETV} -eq 0 ]; then
    # CentOS doesn't support httpd_tmp_exec
    cd /tmp/setup-web2py

    # Create the SELinux policy
cat > httpd.te << EOF

module httpd 1.0;

require {
    type httpd_t;
    class process execmem;
}

#============= httpd_t ==============
allow httpd_t self:process execmem;
EOF

    checkmodule -M -m -o httpd.mod httpd.te
    semodule_package -o httpd.pp -m httpd.mod
    semodule -i httpd.pp

fi

# Setup the overall web2py SELinux context 
cd /opt
chcon -R -t httpd_user_content_t web-apps/

cd /opt/web-apps/web2py/applications

# Setup the proper context on the writable application directories
for app in `ls`
do
    for dir in databases cache errors sessions private uploads
    do
        mkdir ${app}/${dir}
        chown apache:apache ${app}/${dir}
        chcon -R -t tmp_t ${app}/${dir}
    done
done


###
### Phase 4 - Configure iptables
###

cd /tmp/setup-web2py

# Create rules file - based upon
# http://articles.slicehost.com/assets/2007/9/4/iptables.txt
cat > iptables.rules << EOF
*filter

#  Allows all loopback (lo0) traffic
#  drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

#  Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#  Allows all outbound traffic
-A OUTPUT -j ACCEPT

# Allows SSH, HTTP, and HTTPS
# Consider changing the SSH port and/or using rate limiting
# see http://blog.andrew.net.au/2005/02/16#ipt_recent_and_ssh_attacks
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT
EOF

/sbin/iptables -F
cat iptables.rules | /sbin/iptables-restore
/sbin/service iptables save

###
### Phase 5 - Setup SSL
###

echo
echo " - Creating a self signed certificate"
echo

# Verify ssl directory exists
if [ ! -d "/etc/httpd/ssl" ]; then
    mkdir -p /etc/httpd/ssl
fi

# Generate and protect certificate
openssl genrsa 1024 > /etc/httpd/ssl/self_signed.key
openssl req -new -x509 -nodes -sha1 -days 365 -key /etc/httpd/ssl/self_signed.key > /etc/httpd/ssl/self_signed.cert
openssl x509 -noout -fingerprint -text < /etc/httpd/ssl/self_signed.cert > /etc/httpd/ssl/self_signed.info

chmod 400 /etc/httpd/ssl/self_signed.*

###
### Phase 6 - Configure Apache
###

echo
echo " - Configure Apache to use mod_wsgi"
echo

# Create config
if [ -e /etc/httpd/conf.d/welcome.conf ]; then
    mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.disabled
fi

cat  > /etc/httpd/conf.d/default.conf << EOF

NameVirtualHost *:80
NameVirtualHost *:443

<VirtualHost *:80>
  WSGIDaemonProcess web2py user=apache group=apache
  WSGIProcessGroup web2py
  WSGIScriptAlias / /opt/web-apps/web2py/wsgihandler.py

  <Directory /opt/web-apps/web2py>
    AllowOverride None
    Order Allow,Deny
    Deny from all
    <Files wsgihandler.py>
      Allow from all
    </Files>
  </Directory>

  AliasMatch ^/([^/]+)/static/(.*) /opt/web-apps/web2py/applications/\$1/static/\$2

  <Directory /opt/web-apps/web2py/applications/*/static>
    Options -Indexes
    Order Allow,Deny
    Allow from all
  </Directory>

  <Location /admin>
    Deny from all
  </Location>

  <LocationMatch ^/([^/]+)/appadmin>
    Deny from all
  </LocationMatch>

  CustomLog /var/log/httpd/access_log common
  ErrorLog /var/log/httpd/error_log
</VirtualHost>

<VirtualHost *:443>
  SSLEngine on
  SSLCertificateFile /etc/httpd/ssl/self_signed.cert
  SSLCertificateKeyFile /etc/httpd/ssl/self_signed.key

  WSGIProcessGroup web2py

  WSGIScriptAlias / /opt/web-apps/web2py/wsgihandler.py

  <Directory /opt/web-apps/web2py>
    AllowOverride None
    Order Allow,Deny
    Deny from all
    <Files wsgihandler.py>
      Allow from all
    </Files>
  </Directory>

  AliasMatch ^/([^/]+)/static/(.*) /opt/web-apps/web2py/applications/\$1/static/\$2

  <Directory /opt/web-apps/web2py/applications/*/static>
    Options -Indexes
    ExpiresActive On
    ExpiresDefault "access plus 1 hour"
    Order Allow,Deny
    Allow from all
  </Directory>

  CustomLog /var/log/httpd/access_log common
  ErrorLog /var/log/httpd/error_log
</VirtualHost>

EOF

# Fix wsgi socket locations
echo "WSGISocketPrefix run/wsgi" >> /etc/httpd/conf.d/wsgi.conf

# Restart Apache to pick up changes
service httpd restart

###
### Phase 7 - Setup web2py admin password
###

echo
echo " - Setup web2py admin password"
echo

cd /opt/web-apps/web2py
sudo -u apache python -c "from gluon.main import save_password; save_password(raw_input('admin password: '),443)"

###
### Phase 8 - Verify that required services start at boot
###

/sbin/chkconfig iptables on
/sbin/chkconfig httpd on

###
### Phase 999 - Done!
###

# Change back to original directory
cd ${current_directory}

echo " - Complete!"
echo

Related slices

Comments (2)

  • Login to post



  • 0
    rahuld 14 years ago
    Hi berubejd, I am having a hard time figuring out how to deploy web2py on shared hosting (Cpanel) in my case. The os is centos. Since it is shared, I dont have root access to this machine. What I want to know is if I can use this script to deploy web2py will it harm other applications running on port-80 using Apache or other wise? Excuse me for the same but i m no expert in deployment. Here is the thread on Google Groups that tells what I am doing..for deployment... http://groups.google.com/group/web2py/browse_thread/thread/25e7b7d514cb6d2/d9d2be2e010eed30?lnk=gst&q=deploying+web2py+on+cpanel#d9d2be2e010eed30 Please HELP if you can... Thanks in advance Rahul

  • 0
    cmj 12 years ago

    This line may not be the best option:

    echo "WSGISocketPrefix run/wsgi" >> /etc/httpd/conf.d/wsgi.conf
    

    There is guidance at http://code.google.com/p/modwsgi/wiki/ConfigurationIssues saying certain Linux distros incl Red Hat can lock down run/wsgi and cause an error, so instead to use /var/run/wsgi.  The above could be replaced with this:

    echo "WSGISocketPrefix /var/run/wsgi" >> /etc/httpd/conf.d/wsgi.conf
    

    I did this and it has eliminated certain errors.  My use of this has been on RHEL 6.2 only.

     


Hosting graciously provided by:
Python Anywhere