Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

In apache ports.conf I have

NameVirtualHost *:80
Listen 80

I can't understand that since in NameVirtualHost *:80 the port is already set, why there is a separate Listen 80.

What does it mean? What would be if they were differents?

share|improve this question
add comment

3 Answers

Every program by default need to a port and Kernel dispatch packets to programs via port numbers when you say :

Listen 80

You tell kernel my apache wants to use port 80 , when you get with des-port 80 give me ..., if you try:

root@debian:/home/mohsen# netstat -anp |egrep apache
tcp6       0      0 :::80                   :::*                    LISTEN      25791/apache2   

When you changed Listen line, netstat's ouput will be changed.

But, Virtualhosts:

It dont conflict port, for more details read about VirtualHost by name and VirtualHost by IP

share|improve this answer
add comment

Listen 80 tells Apache to actually set up the socket on port 80, has nothing to do with naming.

NameVirtualHost *:80 tells Apache to refer to the named vhost configs for this particular address/port socket, has nothing to do with setting up the socket.

What would be if they were differents?

The difference would be your configuration would be broken and your server wouldn't work.

share|improve this answer
add comment

From the Apache website:

The Listen directive does not implement Virtual Hosts - it only tells the main server what addresses and ports to listen on. If no directives are used, the server will behave in the same way for all accepted requests. However, can be used to specify a different behavior for one or more of the addresses or ports. To implement a VirtualHost, the server must first be told to listen to the address and port to be used. Then a section should be created for the specified address and port to set the behavior of this virtual host. Note that if the is set for an address and port that the server is not listening to, it cannot be accessed.

Apache is very flexible. The most basic way to use it is without virtual hosts. If you are not using virtual hosts, you can use the Listen directive to specify which network interfaces and ports to use. You can specify basically every option which can be specified in a virtual host right in your http.conf file (which is how Apache.org packages it last I checked BTW).

VirtualHost directives are overrides for this default behavior. They tell Apache to treat certain IP and port combinations differently. If Apache didn't have both then you would NEED to use virtual hosts. This used to be a bigger problem when virtual hosts were first invented. At the time browsers didn't know how to handle them and even though support was added to all popular browsers soon after, many people continued to use outdated browsers at the time. Because that was a long time ago, most Apache distributions now use virtual hosts by default because they are more flexible and make it possible to respond differently depending on IP, port or name.

Even now that we have virtual hosts, the fact that we can specify a default configuration for our domain is useful. Consider the case where someone enters an invalid sub domain name. Since we have a default website we can use it to show a custom page\site when someone tries to access it.

The reverse type of situation could also be true. If you wanted to you could make sites-enabled a shared folder and adjust the contents of the ports configuration files on a per server basis in order to load balance many servers.

That being said, I do think that it's odd that Apache doesn't seem to have a way to automatically set them based on the virtual host configuration.

Just for fun, I wrote a script that could make this work automatically. You can try it if you like but I warn you that you should be cautious about using it because it is almost completely untested. Meaning THIS IS NOT PRODUCTION CODE:

<?php
$path=dirname(__FILE__); // The current file path. It is used so all other paths can reliably be set relatively.

$cfg=array(
   'output_file'=>"$path/var/ports.conf.out", // This is the file to be generated.
   'template_file'=>"$path/tpl_default.php",
   'glob_patterns'=>array( // This array contains a list of directories to search for virtual hosts in.
      "$path/test-enabled/*", // For now I'd just test some copies which you can play with. Once everything is
   ),   // good then you can change this to /etc/apache/sites-enabled

);

##############
define('IS_CLI', PHP_SAPI==='cli');

echo "Auto Vhost Script\n------------------\n\n";

//echo "Arguments: \n"; print_r(arguments($argv));

echo "Output File:\n\t{$cfg['output_file']}\n";
if(!isset($cfg['output_file'])||!is_writable(dirname($cfg['output_file'])))
   die("ERROR: Cannot write to output file.\n");

echo "Template File:\n\t{$cfg['template_file']}\n";
if(!isset($cfg['template_file'])||!is_readable(dirname($cfg['template_file'])))
   die("ERROR: Cannot read to template file.\n");

echo "Search Paths:\n";
foreach($cfg['glob_patterns'] as $pattern) {
   echo "\t$pattern\n";
}
echo "\nReading configuration files...\n";

$vhosts=array();
foreach($cfg['glob_patterns'] as $pattern) {
   echo ">> $pattern\n";
   $files=glob($pattern);
   foreach($files as $file) {
      echo "\t>> ". basename($file) ."\n";
      $handle=@fopen($file, "r");
      if($handle) {
         while(($buffer=fgets($handle, 4096))!==false) {
            $status=procLine($buffer);
            if(!$status) die("ERROR: Failed reading input line.\n");
            if($status===TRUE) continue;
            $vhosts[]=$status;
         }
         if(!feof($handle)) die("ERROR: Unexpected fgets() fail.\n");
         fclose($handle);
      }
   }
}
echo "\n\nGenerating template data...\n";
$nvhost=array();
$listen=array();
foreach($vhosts as $vhost) {
   // We're just going to assume that if you have multiple VirtualHost for the same port that means you want to use
   // *:port . You could improve this by actually checking to see if multiple hosts have been assigned to this port
   // but you'd need to rearrange the data a little.
   if($vhost['is_name']||isset($nvhost[$vhost['port']])) {
      $nvhost[$vhost['port']]='NameVirtualHost *:'.$vhost['port'];
      $listen[$vhost['port']]='Listen '.$vhost['port'];
   } else {
      $nvhost[$vhost['port']]='NameVirtualHost '.$vhost['host'].':'.$vhost['port'];
      if($vhost['host']=='*')
         $listen[$vhost['port']]='Listen '.$vhost['port'];
      else $listen[$vhost['port']]='Listen '.$vhost['host'].':'.$vhost['port'];
   }
}
echo "\n\nWriting output file...\n";

$tpl=file_get_contents($cfg['template_file']);
if($tpl) {
   $tpl=str_replace('{NAME_VHOST}', implode("\n", $nvhost), $tpl);
   $tpl=str_replace('{LISTEN}', implode("\n", $listen), $tpl);
   file_put_contents($cfg['output_file'], $tpl);
}

echo "\n\nDone.\n";

function procLine($line) {
   if(!preg_match("/^(\w)*<VirtualHost(.)*>(\w)*/", $line)) return true;
   $host=substr($line, strpos($line, 'VirtualHost')+12, strlen($line)-strrpos($line, '>')+2);
   $last_square=strrpos($host, ']'); // This is in case the host is specified in IPv6 format
   $cln=strrpos($host, ':');
   if($cln!==FALSE && $cln+1<strlen($host) && $cln>$last_square) {
      $port=substr($host, $cln+1);
      $host=substr($host, 0, $cln);
   } else $port='80';
   $is_range=strpos($host, '*')!==FALSE;
   $is_ip=$is_range||filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)!==FALSE;
   $is_name=!$is_ip;
   return array('host'=>$host, 'port'=>$port, 'is_name'=>$is_name, 'is_ip'=>$is_ip, 'is_range'=>$is_range);
}

All that needs to be setup is the $cfg variable at the top of the script and a ports configuration file template. To use it run it with PHP: php path/to/auto_vhost.php. Once you get that working you can add the php call to /etc/init.d/apache2 near the top (or if you look there is actually a slightly better place but only because this really isn't needed on service apache2 stop commands). Doing this will cause this script to be ran right before Apache starts or restarts so that it'll be what gets loaded.

Here is a sample template file for this:

# This file was generated from a template by auto_vhost.php

{NAME_VHOST}

{LISTEN}

<IfModule mod_ssl.c>
    # If you add NameVirtualHost *:443 here, you will also have to change
    # the VirtualHost statement in /etc/apache2/sites-available/default-ssl
    # to <VirtualHost *:443>
    # Server Name Indication for SSL named virtual hosts is currently not
    # supported by MSIE on Windows XP.
    Listen 443
</IfModule>

<IfModule mod_gnutls.c>
    Listen 443
</IfModule>
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.