Orginal-Artikel vom 07. April 2009: http://www.sio2.ch/blog/2/ Bearbeitet am 19.03.2011
Um sicher zu sein, dass unser Server auf dem neustem Stand ist machen wir einen Update der Paketdatenbank und ein Update des Systems.
~/# apt-get update ~/# apt-get upgrade
Jetzt werden noch folgende Pakete benötigt:
~/# apt-get install apg build-essential lighttpd mysql-client mysql-server perl php5-cgi phpmyadmin python python-django python-flup python-mysqldb ssh openssh-server sudo vim-nox wget
Hier noch eine kleine Erläuterung der Pakete:
Nun editieren wir die Lighttpd-Konfigurationsdatei in /etc/lighttpd/lighttpd.conf und aktivieren ein paar Servermodule:
server.modules = ( "mod_access", "mod_alias", "mod_accesslog", "mod_compress", "mod_rewrite", "mod_redirect", # ... )
Nun können wir ein paar weitere Module von Lighttpd aktivieren:
~/# lighttpd-enable-mod auth fastcgi proxy userdir
Jetzt ergänzen wir die Lighttpd-Konfigurationsdatei, damit sie auch für jeden Benutzer eine eigene Konfigurationsdatei in /etc/lighttpd/user-conf/ erlaubt. Folgende Zeile muss an den Schluss von /etc/lighttpd/lighttpd.conf hinzugefügt werden:
include_shell "/usr/share/lighttpd/include-user-conf.pl"
Als nächstes müssen wir das kleine Script - /usr/share/lighttpd/include-user-conf.pl - schreiben, welches die Konfigurationen der Benutzer in /etc/lighttpd/user-conf/ auflistet und sie in die Lighttpd-Konfiguration einbindet:
#!/usr/bin/perl -wl use strict; use File::Glob ':glob'; my $confdir = "/etc/lighttpd/"; my $enabled = "user-conf/*.conf"; chdir($confdir); my @files = bsd_glob($enabled); for my $file (@files) { print "include \"$file\""; }
Nun können wir unseren ersten Benutzer einfügen:
~/# adduser account
Dies fügt uns einen user "account" welchen wir als Vorlage benützen werden, um weitere Benutzer zu generieren.
Unser neu generierter Benutzer muss sich in der Gruppe www-data befinden, also fügen wir diesen der Gruppe zu:
~/# adduser account www-data
Unser neuer Benutzer benötigt eine MySQL-Datenbank für seine Django-Projekte. Wir schreiben nun ein kleines Script, das uns für einen beliebigen Benutzer einen MySQL Benutzer generiert. Dafür benötigen wir ein kleines SQL-Template welches wir in /root/confs/create_user.sql abspeichern:
# Create the user CREATE USER '$account'@'localhost' IDENTIFIED BY '$passwd'; # Grant usage to the user GRANT USAGE ON * . * TO '$account'@'localhost' IDENTIFIED BY '$passwd'; # Grant all privileges to his databases GRANT ALL PRIVILEGES ON `$account\_%` . * TO '$account'@'localhost';
Und nun das passende Bash-Script dazu um das Template anzupassen und den Benutzer hinzuzufügen:
#!/usr/bin/env bash function usage { echo "Create a new mysql account" echo "Usage: ${0##*/} uid" if [ "$*" != "" ]; then echo " Error: $*"; fi exit 1 } # the script must be run by root if [ "$USER" != "root" ]; then echo "Must be run as root." exit 1 fi # check parameters if [ $# -ne 1 ]; then usage fi # get the account paramenter account=$1 # generate a random password for the mysql user passwrd=`apg -n 1 -c "0xa2t28n"` tmpsql="/tmp/create_mysql_acc.sql" # create temporary sql file touch $tmpsql sed \ -e "s/\$account/`echo $account`/g" \ -e "s/\$passwd/`echo $passwrd`/g" \ "$HOME/confs/create_user.sql" >> $tmpsql # create the sql user echo "MySQL root password is required" mysql -p < $tmpsql # delete the temporary sql file rm -f $tmpsql # save settings in a file on his home directory touch "/home/$account/mysql.settings" echo "Username: $account" >> "/home/$account/mysql.settings" echo "Password: $passwrd" >> "/home/$account/mysql.settings" # make the file only readable by the user chmod 700 "/home/$account/mysql.settings" chown $account:$account "/home/$account/mysql.settings"
Dieses Script kann z.B. in /usr/local/sbin/create_mysql_acc gespeichert werden und so auch ausgeführt werden:
~/# create_mysql_acc account
Nun kann Lighttpd für die Django-Projekte des erstellten Accounts konfiguriert werden. Auch hier werden wir ein Template verwenden, welches wir in /root/confs/lighttpd.conf abspeichern:
$HTTP["host"] =~ "^(www\.|)$domain$" { server.document-root = "/home/$account/django-projects/website/public_html" fastcgi.server = ( "$proj.fcgi" => ( "main" => ( "socket" => "/tmp/$account/$proj.sock", "check-local" => "disable", ) ) ) url.rewrite-once = ( "^/(media)/.*" => "$0", "^(/.*)" => "/$proj.fcgi$1", ) }
Jetzt braucht es noch ein kleines Bash-Script, welches das Template ausliest, die Variablen ersetzt und dann die Konfiguration in /etc/lighttpd/user-conf/ ablegt:
#!/usr/bin/env bash function usage { echo "Create the lighttpd proj conf and add it to /etc/lighttpd/user-conf/" echo "Usage: ${0##*/} uid domain proj" if [ "$*" != "" ]; then echo " Error: $*"; fi exit 1 } function check_dir { if [ ! -d $1 ]; then echo "Creating directory $1 ..." mkdir $1 fi } # the script must be run by root if [ "$USER" != "root" ]; then echo "Must be run as root." exit 1 fi # check parameters if [ $# -ne 3 ]; then usage "uid or proj missing" fi account=$1; domain=$2; proj=$3; # check if the user exists if [ ! -e /home/$account ]; then usage "User $account does not exist at /home/$account" fi # check if the project already exists if [ ! -e /home/$account/django-projects/$proj ]; then usage "Project $proj does not exist at /home/$account/django-projects" fi # check if the configuration file exists, else create it DIR=/etc/lighttpd/user-conf check_dir $DIR if [ ! -e $DIR/$account.conf ]; then touch $DIR/$account.conf fi sed \ -e "s/\$account/`echo $account`/g" \ -e "s/\$domain/`echo $domain`/g" \ -e "s/\$proj/`echo $proj`/g" \ $HOME/confs/lighttpd.conf >> /etc/lighttpd/user-conf/$account.conf
Dieser Script kann z.B. in /usr/local/sbin/create_lighty_conf gespeichert werden und so auch ausgeführt werden:
~/# create_lighty_conf account example.com website
Nun stellen wir einen Django-Projekt her. Dies ist dank dem django-admin ziemlich simpel und lässt sich auch mit Hilfe eines weiteren Scripts - /usr/local/sbin/startproj - ausführen:
#!/usr/bin/env bash function usage { echo "Create a new django project" echo "Usage: ${0##*/} uid proj" if [ "$*" != "" ]; then echo " Error: $*"; fi exit 1 } function check_dir { if [ ! -d $1 ]; then echo "Creating directory $1 ..." mkdir $1 fi } # check parameters if [ $# -ne 2 ]; then usage fi account=$1 project=$2 # check if the project already exists DIR="/home/$account/django-projects" if [ -e $DIR/$project ]; then usage "Project already exists at /home/$account/django-projects/$project" fi # save the current location location=`pwd` check_dir $DIR cd $DIR/ # create the django project django-admin startproject $project # go back where we were before cd $location # create temporary sql to create the database mysqlfile="/tmp/create_mysql_db.sql" touch $mysqlfile sed \ -e "s/\$account/`echo $account`/g" \ -e "s/\$project/`echo $project`/g" \ "$HOME/confs/create_db.sql" >> $mysqlfile echo "MySQL root password is required" mysql -p < $mysqlfile rm -f $mysqlfile # create the fcgi file DIR="/home/$account/django-projects/$project/public_html" check_dir $DIR fcgifile="$DIR/$project.fcgi" touch $fcgifile sed \ -e "s/\$account/`echo $account`/g" \ -e "s/\$project/`echo $project`/g" \ "$HOME/confs/template.fcgi" >> $fcgifile chown $account:$account -R "/home/$account" chmod 755 -R "/home/$account"
Der Inhalt von /root/confs/create_db.sql ist ein weiteres, sehr simples Template:
CREATE DATABASE `$account_$project` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
Auch /root/confs/template.fcgi enthält ein Template:
#!/usr/bin/env python import sys, os # Add a custom Python path. sys.path.insert(0, "/home/$account/django-projects") # Switch to the directory of your project. (Optional.) # os.chdir("/home/$account/django-projects/$project") # Set the DJANGO_SETTINGS_MODULE environment variable. os.environ['DJANGO_SETTINGS_MODULE'] = "$project.settings" from django.core.servers.fastcgi import runfastcgi runfastcgi(method="threaded", daemonize="false")
Das Script lässt sich folgendermassen ausführen:
~/# startproj account website
Der Benutzer braucht ein Scripts, um die Fastcgi Sockets zu generieren, welches wir django_site nennen und in /usr/local/bin/ abspeichern:
#!/bin/bash function usage { echo echo "'django_site' is a script that starts or stops a django project site." echo echo "Usage: ${0##*/} {start|stop} sitename" if [ "$*" != "" ]; then echo " Error: $*"; fi echo exit 1 } function stopdjango { # check if the pidfile exist and kill if [ -f $1 ]; then kill `cat -- $1` rm -f -- $1 fi # check if socket file exists and delete if [ -e $2/$3.sock ]; then rm -f -- $2/$3.sock fi } # check if the paremeters are given if [ $# -lt 1 ]; then usage elif [ $# -lt 2 ]; then usage "var 'django-project' missing" fi tempdir="/tmp/$USER" djanproj=$2 djanprojdir="$HOME/django-projects/$djanproj" pidfile="$djanprojdir/django.pid" socket="$tempdir/$djanproj.sock" case $1 in "start") # check if the django project exists if [ ! -d $djanprojdir ]; then usage "Django '$djanproj' project does not exist" fi #check for temporary directory and create it if [ ! -d $tempdir ]; then echo "Creating directory $tempdir ..." mkdir $tempdir chown $USER:www-data $tempdir fi stopdjango $pidfile $tempdir $djanproj location=`pwd` #change to the Django dir and execute the runfcgi command cd $djanprojdir echo "Starting django site '$djanproj' ..." python manage.py runfcgi socket=$socket pidfile=$pidfile cd $location # change read and write rights if [ -e $tempdir/$djanproj.sock ]; then chown $USER:www-data $tempdir/$djanproj.sock chmod 775 $tempdir/$djanproj.sock echo "Django project '$djanproj' is running..." else echo "Error: could not write $tempdir/$djanproj.sock" echo "Django project '$djanproj' is NOT running..." fi ;; "stop") echo "Stopping django project '$djanproj'..." stopdjango $pidfile $tempdir $djanproj ;; esac
Der Benutzer kann dann mit diesem Script das Django-Projekt starten:
account@server:~$ django_site start website
oder stoppen:
account@server:~$ django_site stop website
Nun kann der Benutzer - in diesem Fall account - sich an die Arbeit machen und sein Django-Projekt konfigurieren und laufen lassen.
Wir haben nun einen gut funtionierenden Benutzeraccount, welchen wir als Vorlage benützen möchten. Dazu müssen wir lediglich alle Dateien aus dem Benutzerordner - bis auf ~/mysql.settings - nach /etc/skel kopieren.
~/# cp -R /home/account/* /etc/skel/ ~/# rm -f /etc/skel/mysql.settings
Enjoy!