哥使用Linux
分类: LINUX
2007-10-14 11:46:41
Posted by on Wed 22 Feb 2006 at 09:10
This documents my adventure setting up a LAMP server on Sarge with Apache2, PHP5, MySQL5, phpMyAdmin, Smarty, and ADODB. It covers installation and just enough sample code to test everything. It turned out to be pretty long. I should point out that I have deviated from the "Debian Way" by downloading phpMyAdmin, Smarty, and ADODB directly from their respective websites and installing them in /usr/local. I could find no backports for these, and kept running into dependecies on PHP4 which I did not want to install.
Contents
What I Installed and Where I Got It.
Note: The PHP folks say it's a bad idea to use the threading Apache2, so I used the MPM prefork version from Sarge. For more info read the FAQ . Also there is the MPM prefork info .
Before You Start
Installing Apache
As noted above, this is the MPM prefork version available in Sarge. I'm also installing some of the packages it recommends. No changes are required to /etc/apt/sources.list for this.
$> apt-get update $> apt-get upgrade $> apt-get install apache2-mpm-prefork apache2-doc lynx ca-certificates.
Testing Apache
Before we start messing with it, you might as well check that Apache is working. Point a browser at and verify that you see the installed default Apache site. If you don't, check your DNS and firewall. Fix whatever the problem is before you go on.
I decided on these security tweaks from reading the security tips on the Apache site. You can add these to the main config file, but I opted to keep my own config changes separate by putting them in a file in the /etc/apache2/conf.d/ directory. I created a file there named local_configs.conf and put the following in it.
# Tighten access to the file system.# Forbid default access to file system locations Order Deny,Allow Deny from all # prevent use of .htaccess files in all directories # apart from those specifically enabled. AllowOverride None # Limit available info about this server. ServerSignature Off ServerTokens production
Don't forget to reload Apache after changing the config.
Virtual Hosting Refresher
The Debian installation of Apache2 comes all set up do "name-based" virtual hosting right out of the box. This is perfect if you have more than one domain to host on your server, or plan to in the future. For the uninitiated, here's a quick rundown on virtual hosting.
Virtual hosting refers to the practice of running more than one web site (domains) on a single server. The fact that they are running on the same physical server is not apparent to the end user. There are two types of virtual hosting, IP-based and name-based.
IP-based virtual hosting is when you have a different IP address for every domain. We'll not be doing it in this HOWTO.
Name-based virtual hosting is when you have multiple domains running from one IP address, and is what we will be using here. This means that the DNS A records (or CNAME records) for and can both point to the one IP address of your server, and Apache will sort out which site to serve up based on the domain that was requested. If someone points their browser at the IP address of your server, e.g. they will be served the first site that you have configured. Unless you change it, this will be the Apache default site as it is installed by Debian's Apache2 package.
For more info on virtual hosting, .
Getting Familiar With Apache
Setting up a name-based virtual site is easy once you understand the layout a bit. I suggest you scan the file /etc/apache2/README. It's pretty short and clear. For the impatient, here are just the things we are going to touch to get one name-based virtual site up. I'll use "mydomain.com" as the virtual domain in all the examples.
Setting Up a Web Site
First, create a subdirectory of /var/www/ to contain the site. It makes sense to name this directory after the domain that will live there.
$> mkdir /var/www/mydomain.com
Now create the subdirectory /var/www/mydomain.com/docs/. This will be the only directory that is publicly accessible.
$> mkdir /var/www/mydomain.com/docs
Now create /var/www/mydomain.com/docs/index.html, something simple like the following:
Mydomain.com test index page Hello World!
Now create /etc/apache2/sites-available/mydomain.com. We use the
#Basic setup ServerAdmin webmaster@mydomain.com ServerName DocumentRoot /var/www/mydomain.com/docs Order Deny,Allow Allow from all # Don't show indexes for directories Options -Indexes
Now, to enable the site you use the a2ensite command (Note:use a2dissite to disable). The following creates a symlink /etc/apache2/sites-enabled/mydomain.com, which enables the site.
$> a2ensite mydomain.com
You need to reload Apache to see the site...
$> /etc/init.d/apache2 reload
If DNS is working, you should now be able to point your browser at see the index.html page you created above.
Miscellaneous Apache Stuff
There are a few other things I noticed that might be useful to someone. Here they are in no particular order.
Installing PHP 5
We need to add one the dotdeb.org mirrors to sources.list for this. The mirrors are listed at . I chose one from Germany by adding the following to /etc/apt/sources.list
# Use dotdeb.org for LAMP related packages not available in Sarge deb stable all deb-src stable all
Now, thanks to Guillaume Plessis of dotdeb.org, installing PHP5 on Sarge is easy.
$> apt-get update $> apt-get install libapache2-mod-php5
There is a sample php config provided in /usr/share/doc/php5-common/examples/php.ini-recommended. It contains the "warmly recommended" php.ini settings for production servers. I chose to use this config file instead of the installed default. This is a very well commented file and worth the time to read. If you want to use this recommended config instead of the default, first save a copy of the original php.ini file, like so ..
$> mv /etc/php5/apache2/php.ini /etc/php5/apache2/php.ini.original
... and then put the recommended file in place of the original file.
$> cp /usr/share/doc/php5-common/examples/php.ini-recommended \ /etc/php5/apache2/php.ini
Now, like we did with Apache, let's hide info about our php config by telling PHP to hide itself. Open up php.ini in your favorite editor and set expose_php to off.
expose_php = off
Also, I plan to follow the convention of naming all php include files with the .inc extension. For good measure, I want Apache to hide these by default, so I add this to the /etc/apache2/conf.d/local_configs.conf file I created earlier (this is the same way .htaccess files are protected in the main Apache config file).
# Hide all files with the .inc extension.Order allow,deny Deny from all
Installing MySQL
Thanks (again) to the dotdeb.org mirror we have already added, this is easy. apt-get will find the latest version there.
$> apt-get install mysql-server
Don't forget to set a password for the MySQL root user. Do the following, replacing "secret" with your chosen password, and make it a good one.
$> /usr/bin/mysqladmin -u root password 'secret'
Note: It would be wise to create a non-root user for MySQL having just the MySQL permissions absolutely necessary to the PHP applications you are going to write. I'm using the root user for the purposes of this howto.
Also grab the php5 mysql extensions from dotdeb.org:
$> apt-get install php5-mysql
Testing MySQL
Let's create a quick database and table to both verify that MySQL is working, and give us something to test ADODB with later. At a command line, login to MySQL.
$> mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1920 to server version: 5.0.18-Debian_3.dotdeb.1-log Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql>
Now we will, 1) create a database 2) tell MySQL to "use" the database 3) create a table, and 4) insert a couple of records into the table. You should be able to copy and paste these commands at the mysql prompt. BTW, I stole this example out the MySQL Reference Manual.
mysql> CREATE DATABASE mydomain; Query OK, 1 row affected (0.00 sec) mysql> USE mydomain; Database changed mysql> CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20), species VARCHAR(20), sex CHAR(1), birth DATE, death DATE); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO pet VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO pet VALUES ('Libby','Diane','dog','f','2001-04-15',NULL); Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM pet; +----------+-------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+-------+ | Puffball | Diane | hamster | f | 1999-03-30 | NULL | | Libby | Diane | dog | f | 2001-04-15 | NULL | +----------+-------+---------+------+------------+-------+ 2 rows in set (0.00 sec) mysql> quit Bye
I find the MySQL command line painful. phpMyAdmin makes it a lot easier, so let's install it.
.
First we'll create a directory that's out of the way of Debian's package management system in /usr/local. We'll call it php5 since we'll be putting Smarty and ADODB files here as well.
$> mkdir /usr/local/php5
Now we untar phpMyAdmin in this directory (creates /usr/local/php5/phpMyAdmin-2.7.0-pl2), and remove the tar.gz file.
$> cp phpMyAdmin-2.7.0-pl2.tar.gz /usr/local/php5/ $> cd /usr/local/php5/ $> tar -zxvf phpMyAdmin-2.7.0-pl2.tar.gz $> rm phpMyAdmin-2.7.0-pl2.tar.gz
Note: I opt to leave the version info in the phpMyAdmin directory name so I can easily untar a new version right next it without blowing anything away.
Configuring phpMyAdmin
The sample config file provided is config.default.php. We need to copy it to config.inc.php.
$> cd /usr/local/php5/phpMyAdmin-2.7.0-pl2/ $> cp config.default.php config.inc.php
Now we need to make a couple of changes to config.inc.php. First, let's define the URI we'll be using to access PhpMyAdmin (this is not the path to the phpMyAdmin directory, but rather the alias we will use for it in the Apache config). Find the following line,
$cfg['PmaAbsoluteUri'] = '';
and change it to something like this.
$cfg['http:///phpmyadmin'] = '';
Next we need to choose an auth type. The three options are 'config', 'http', and 'cookie'. The 'config' option is the default, and requires you to keep your MySQL password right here in this file, which I don't like. The 'http' option prompts you for the password when you access PhpMyAdmin, but will send the password in clear text, which I also don't like. The 'cookie' option is the best I think, and allows you to define a passphrase with the [blowfish_secret] parameter, which phpMyAdmin will use to encrypt the password in a cookie when you log in. To use the 'cookie' auth type, we need to make two changes. First, find the section of the file that looks like this:
/** * The 'cookie' auth_type uses blowfish algorithm to encrypt the password. If * at least one server configuration uses 'cookie' auth_type, enter here a * passphrase that will be used by blowfish. The maximum length seems to be 46 * characters. */ $cfg[''] = '';
You need to change this line ..
$cfg[''] = '';
.. to something like the following. Note that you have to add the "blowfish_secret" part within the brackets (I don't know why). Note also that you will not be prompted for the passphrase you enter here, so feel free to make it a real ugly one.
$cfg['blowfish_secret'] = 'some_passphrase_under_46_characters_long';
Then find this line ..
$cfg['Servers'][$i]['auth_type'] = 'config';
... and change the auth type from 'config' to 'cookie', like so ..
$cfg['Servers'][$i]['auth_type'] = 'cookie';
That's it. Save the file.
Configuring Apache to Display phpMyAdmin
Now we need to tell Apache where phpMyAdmin lives, and also create an Apache alias for the phpMyAdmin directory (so we don't have to remember to type "phpMyAdmin-2.7.0-pl2" into the browser all the time). Also, since I don't want anyone else to even try logging in to phpMyAdmin, I will restrict access to just the IP address of my own workstation. To do all this we just need to add a small section to the file /etc/apache2/sites-available/mydomain.com that we created earlier. Add a section like the following, remebering to change the IP address to something appropriate.
# Provide an alias to phpmyadmin Alias /phpmyadmin /usr/local/php5/phpMyAdmin-2.7.0-pl2# Restrict phpmyadmin access to just my worksation Order Deny,Allow Deny from all Allow from 192.168.1.2
Reload Apache, and you should be able to point your browser at /phpmyadmin and login as the MySQL root user.
About Smarty
Smarty is a template engine for PHP. It allows you to separate your presentation code (html) from the logic (php) in your web applications. If you don't know why this is important to do, then develop a great big web site with a whole bunch of PHP applications, wait long enough to forget how you did everything, and then try to redesign the site. Or, just read Smarty's . They explain it better than I can.
Installing Smarty
As previously noted I could not find a backport for Smarty, so I just downloaded the latest version from . Once you have the tar.gz let's untar it in the /usr/local/php5 directory we created earlier.
$> cp Smarty-2.6.12.tar.gz /usr/local/php5/ $> cd /usr/local/php5/ $> tar -zxvf Smarty-2.6.12.tar.gz $> rm Smarty-2.6.12.tar.gz
Now edit /etc/php5/apache2/php.ini and add the Smarty /libs subdirectory to the php_include_path, like so:
include_path = ".:/usr/local/php5/Smarty-2.6.12/libs"
Remember, whenever you make a change to php.ini you need to reload Apache.
Now we will create the four directories that Smarty needs to function and set the permissions on them. This is basically right out of the Smarty site's .
cd /var/www/mydomain.com $> mkdir smarty $> mkdir smarty/templates $> mkdir smarty/templates_c $> mkdir smarty/cache $> mkdir smarty/configs $> chown www-data:www-data smarty/templates_c $> chown www-data:www-data smarty/cache $> chmod 775 smarty/templates_c $> chmod 775 smarty/cache
Note: The Smarty documentation says to keep these directories out of the doc root. These are not in our doc root because we defined the doc root for mydomain.com as /var/www/mydomain.com/docs/. It is therefore important to remember not to change the doc root to /var/www/mydomain.com/, which would expose these directories to the world. You can of course put these directories anywhere else you want. My reason for placing them here is that I find it convenient to have just one directory (/var/www/mydomain.com/) containing everything related to the content of a domain.
Testing Smarty
Now let's make a test PHP app. First make a directory for it to live in.
$> mkdir /var/www/mydomain.com/docs/myapp/
Then create a file named index.php in that directory containing the following:
template_dir = '/var/www/mydomain.com/smarty/templates/'; $smarty->compile_dir = '/var/www//mydomain.com/smarty/templates_c/'; $smarty->config_dir = '/var/www/mydomain.com/smarty/configs/'; $smarty->cache_dir = '/var/www/mydomain.com/smarty/cache/'; // Set a smarty variable $smarty->assign('name', 'Johnny'); // Display the smarty template $smarty->display('myapp_index.tpl'); ?>
Now we need to make a template, called myapp_index.tpl, in the directory /var/www/mydomain.com/templates/. Something like the following:
Smarty Hello, {$name}!
Now you should be able to display this template by pointing your browser at /myapp/ and see Hello, Johnny!
A Smarter Smarty Setup
Now that we know it works, let's make our Smarty setup more flexible. We don't really want to define the smarty directory paths in every PHP script when we could just define them once in an include file. First let's make a new directory for it.
$> mkdir /var/www/mydomain.com/includes/
We also want to add this directory to the include_path in php.ini. Don't forget to reload Apache afterwards.
include_path = ".:/usr/local/php5/Smarty-2.6.12/libs:/var/www/mydomain.com/includes"
Now create the file /var/www/mydomain.com/includes/smarty_setup.inc and define the smarty directories in it.
template_dir = '/var/www/mydomain.com/smarty/templates/'; $smarty->compile_dir = '/var/www//mydomain.com/smarty/templates_c/'; $smarty->config_dir = '/var/www/mydomain.com/smarty/configs/'; $smarty->cache_dir = '/var/www/mydomain.com/smarty/cache/'; ?>
With this done, you can simplify /var/www/mydomain.com/myapp/index.php to look like this.
assign('name', 'Johnny'); // Display the smarty template $smarty->display('myapp_index.tpl'); ?>
This is much cleaner looking. More importantly, if there is ever a need to redefine the location of the smarty directories, the only file that will need editing is smarty_setup.inc, not every script ever written. We'll take the same approach with ADODB.
About ADODB
ADODB is a database abstraction class for PHP. It allows you to write PHP scripts that can easily be modified to work with several databases. Using it also has the effect of streamlining your PHP code for databases queries.
Installing ADODB
Installation is straightforward. Just , and untar it in /usr/local/php5 just as we did with Smarty and phpMyAdmin.
$> cp adodb471-1.tgz /usr/local/php5/ $> cd /usr/local/php5/ $> tar -zxvf adodb471-1.tgz $> rm adodb471-1.tgz
Add the adodb directory to php.ini's include_path, and remember to reload apache when you're done.
include_path = ".:/usr/local/php5/Smarty-2.6.12/libs:/usr/local/php5/adodb:/var/www/mydomain.com/includes"
Like we did for Smarty, we're going to make a setup file for ADODB that we can just include in the PHP scripts that will access the database. We'll call it adodb_setup.inc, and put it in the directory /var/www/mydomain/includes. Make it look like the following, changing "secret" to your MySQL root password, and "mydomain" to the name of your database:
Note: Your MySQL password is right here in this file. Keep this file and the directory it lives in out of the doc root.
All Together Now
Now let's pull all this together. We'll go back to our myapp application and have it use ADODB syntax to make a database query. Then we'll display the results using a Smarty template.
First edit /var/www/mydomain.com/myapp/index.php to look like the following. Note that we are including the file adodb_setup.inc that we just created.
SetFetchMode(ADODB_FETCH_ASSOC); // Query the pet table and assign the // result set to the $rs variable $rs = $db->Execute('select * from pet'); // Pass the result set to smarty $smarty->assign('rs', $rs); // Other vars for smarty $smarty->assign('pg_title', 'MyApp'); $smarty->assign('name', 'Johnny'); // Display the smarty template $smarty->display('myapp_index.tpl'); ?>
Finally, edit the file /var/www/domain.com/smarty/templates/myapp_index.tpl to look something like the following, in which Smarty displays the $pg_title and $name variables passed from the PHP script, and also iterates through the database result set (the $rs variable), drawing an html table along the way.
{$pg_title} {$pg_title}
Hello, {$name}.
Results of pet query
Pet Name | Owner | Species | Gender | Birth | Death | |
---|---|---|---|---|---|---|
{$pet.name} | {$pet.owner} | {$pet.species} | {$pet.sex} | {$pet.birth} | {if !$pet.death}Still kicking | {else}{$pet.death} | {/if}
The resulting html from this should look something like the following:
MyApp MyApp
Hello, Johnny.
Results of pet query
Pet Name | Owner | Species | Gender | Birth | Death |
---|---|---|---|---|---|
Puffball | Dianne | hamster | f | 1999-03-30 | Still kicking |
Libby | Dianne | dog | f | 2001-04-15 | Still kicking |