71

If I have 3 domains, domain1.com, domain2.com, and domain3.com, is it possible to set up a default virtual host to domains not listed? For example, if I would have:

<VirtualHost 192.168.1.2 204.255.176.199>
DocumentRoot /www/docs/domain1
ServerName domain1
ServerAlias host
</VirtualHost>

<VirtualHost 192.168.1.2 204.255.176.199>
DocumentRoot /www/docs/domain2
ServerName domain2
ServerAlias host
</VirtualHost>

<VirtualHost 192.168.1.2 204.255.176.199>
DocumentRoot /www/docs/everythingelse
ServerName *
ServerAlias host
</VirtualHost>

If you register a domain and point it to my server, it would default to everythingelse showing the same as domain3. Is that possible?

SJaguar13
  • 927
  • 1
  • 6
  • 12

10 Answers10

94

When using name-based virtual hosts, the first virtual host configuration loaded will be the default (Source: Apache Wiki). For example, with the configuration below, otherwise unmatched domains will match with domain-one.com:

NameVirtualHost *:80

<VirtualHost *:80>
  ServerName domain-one.com
  # Other options and directives ..
</VirtualHost>

<VirtualHost *:80>
  ServerName domain-two.com
  # Other options and directives ..
</VirtualHost>

Many servers do not have a monolithic configuration file, but have several host-specific configuration files organized as follows:

/etc/apache2
|-- sites_available  (actual configuration files)
`-- sites_enabled    (symlinks to files in sites_available)

In this case, to make a particular virtual host configuration load first, rename the symlink to something which will be first when sorted, such as 00-default.


Some of the other answers are not quite correct. According to the Apache Wiki, not setting a ServerName in a virtual host is incorrect. If the host without a ServerName is not loaded first, Apache may never even use it, since the first host loaded would be the default.

Furthermore, while ServerAlias * will indeed match anything, it may also override other virtual hosts defined later. Maybe this approach would work if it's always the last virtual host to be defined (as in the configuration given in the question), but this means adding a new directive and changing the sort order instead of just changing the order as above.

Jason Blevins
  • 1,171
  • 1
  • 7
  • 4
  • 2
    + 1 million internets to you Sir! It has to be first to be default. – Ryan Jun 11 '12 at 15:14
  • Do you know which one comes first, httpd.conf or conf.d/xyz.conf? – Esa Varemo Sep 16 '12 at 21:59
  • 2
    "the first virtual host configuration loaded will be the default" solved my problem with local SSL domains on XAMPP (Windows). It looks like Apache uses first vhost as defaults for each port, so in order to properly handle non-matched domains for both unsecured/secured requests, there should be 2 explicit "default" configs for 80/443 ports defined at the beginning of `httpd-vhosts.conf` – Wirone Apr 17 '15 at 07:17
  • 1
    @EsaVaremo - httpd.conf will be loaded first, and it will have an Include line that sources conf.d/xyz.conf (or likely, conf.d/*). any config (including vhosts) before the Include line will be processed first; anything after the include line is processed after the included files. – Dan Pritts May 01 '15 at 15:48
  • Thank you so much for mentioning ``ServerAlias *``. – SuperSandro2000 Jun 14 '21 at 13:18
  • The '00-' prefix did the work, awesome. – Hüseyin Yağlı Apr 08 '22 at 20:30
45

Yes, that should work, except ServerAlias should be "*", with ServerName set to an actual hostname. You might need to make sure that VirtualHost is the very last loaded...

freiheit
  • 14,334
  • 1
  • 46
  • 69
  • It should work, but doesn't. If a domain is not specifically listed, I get "Firefox can't find the server." – SJaguar13 Nov 06 '09 at 22:22
  • 2
    Did you set it as "ServerName host" and "ServerAlias *"? I didn't emphasize this enough originally, but ServerName does not take wildcards, only ServerAlias does. ServerName needs to be an actual hostname. – freiheit Nov 06 '09 at 22:44
  • Also, do the other virtualhosts work? What version of apache? – freiheit Nov 06 '09 at 22:46
  • "Firefox can't find the server." is not an apache problem. You need more detail (what server if any is contacted, what is the error code...) – Law29 Nov 30 '15 at 22:11
  • Weird that does not work for me, it always picks the first virtualhost regardless of host header – jjxtra Jun 01 '19 at 18:59
7

Don't specify a servername, and that becomes your default vhost..

<VirtualHost *:80>
ServerAdmin webmaster@localhost

DocumentRoot /var/www
<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>
<Directory /var/www/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
</Directory>
</VirtualHost> 

Also be sure that you haven't specified a DocumentRoot in the main httpd.conf file, as that will take precedence over the vhosts.

Vid Luther
  • 770
  • 5
  • 10
  • I have that as the first virtual host listed, and I still get "Firefox can't find the server." – SJaguar13 Nov 08 '09 at 06:18
  • 2
    I disagree. I had my first virtual host set without a ServerName, however, it seems to conflict with some virtual hosts, but not others. I solved the issue by adding a ServerName, but setting it to some random domain that's not on my server. Since it's the first virtual host, it's used as the default, but only matches when a domain not matched to any other ServerName is used. – joshaidan Jul 09 '13 at 16:20
2

Use the _default_ virtual host and place it first in httpd-vhosts.conf as specified in http://httpd.apache.org/docs/2.2/vhosts/examples.html

"Catching every request to any unspecified IP address and port, i.e., an address/port combination that is not used for any other virtual host [...] A default vhost never serves a request that was sent to an address/port that is used for name-based vhosts. If the request contained an unknown or no Host: header it is always served from the primary name-based vhost (the vhost for that address/port appearing first in the configuration file)."

Snippet from a live but obfuscated httpd-vhosts.conf which happens to lock all vhosts to port 80:

# Listen for virtual host requests on all IP addresses.
# This directive cannot be removed:
NameVirtualHost *:80

<VirtualHost _default_:80>
# This vhost catches client requests with host headers which have
# not been matched by ServerName or ServerAlias directives in other vhosts.
#
# We redirect all such requests to a particular named vhost:
    RewriteCond %{HTTP_HOST}    ^(.*)$
    RewriteRule ^(.*)$  http://my.site.of.choice [R=permanent,L]
</VirtualHost>

# Name based vhosts here:
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName  my.other.site
    ServerAlias my.other.site2 my.other.site3
</VirtualHost>

# more vhosts etc...

An in-depth explanation of the vhost matching process can be found here: http://httpd.apache.org/docs/2.2/vhosts/details.html

ErikE
  • 4,676
  • 1
  • 19
  • 25
  • 3
    `_default_` is used only for non-matched *IPs*, so when you have wildcarded vhost (*:80) it will never be used. – Wirone Apr 17 '15 at 07:38
2

Wildcard include your site configuration files:

Include path/to/site/confs/*httpd.conf

Organize your site conf files so they are loaded in an expected order. Example...

01-httpd.conf

02-site1-httpd.conf

03-site2-httpd.conf

etc...

Apache will read these in order. Then create one that will always load last to catch any unmatched virtual hosts and return a 404 instead of loading a default site.

99-catchall-httpd.conf

<VirtualHost *:8080>
 ServerName null
 ServerAlias *
 Redirect 404 /
</VirtualHost>

<VirtualHost *:8443>
 ServerName null
 ServerAlias *
 Redirect 404 /
</VirtualHost>

Be sure to replace the ports with whatever ports your httpd listens on. Or if you have httpd listening on specific interfaces, you'll need to add a catchall for each interface instead, like so:

<VirtualHost 192.168.1.101:8080>
 ServerName null
 ServerAlias *
 Redirect 404 /
</VirtualHost>
<VirtualHost 192.168.1.101:8443>
 ServerName null
 ServerAlias *
 Redirect 404 /
</VirtualHost>

<VirtualHost 192.168.1.102:8080>
 ServerName null
 ServerAlias *
 Redirect 404 /
</VirtualHost>

<VirtualHost 192.168.1.102:8443>
 ServerName null
 ServerAlias *
 Redirect 404 /
</VirtualHost>

Hope this helps. I use this method to load sites in the order I specify and prevent unmatched virtual hosts from loading an unexpected site unintentionally.

2

Order is important - move your vhost definition for everything else to the head of the list.

0

In addition to the answers given here (especially the one from @Jason Blevins), there is a potential pitfall here. It took me some time to figure this out.

As stated, Apache will use the first VirtualHost entry if no other entry matches einther the HostName or HostAlias directive.

However, be careful when you mix virtual hosts that are tied to a specific IP address and some that are not (<VirtualHost 192.168.1.1:80> vs. <VirtualHost *:80>).

If a request is made to an IP address that has one or more IP-bound virtual hosts, it will use the first VirtualHost entry tied to that address, even if it is not the first one. In other words, more specific matches are preferred to the unspecific ones on the IP address match, too.

Example

<VirtualHost *>
DocumentRoot /www/docs/domain1
ServerName host1.exmple.com
ServerAlias host
</VirtualHost>

<VirtualHost 192.168.1.1>
DocumentRoot /www/docs/domain2
ServerName host2.exmple.com
ServerAlias host
</VirtualHost>

If a request is made to host foobar.example.com, and that resolves to 192.168.1.1, Apache will serve from /www/docs/domain2, which may be unexpected.

To solve this, either...

  • make all virtual hosts IP-independent (<VirtualHost *>), or
  • add a separate default VirtualHost entry for each IP address served.

If in doubt, run apachectl -S (or whatever command is appropriate on your system) to get a list of VirtualHosts. It will tell you which one is used as default.

fbitterlich
  • 101
  • 1
0

Aardvark technique

On Apache 2.4.x, Ubuntu 20.04, there is no httpd.conf file.

Virtually hosted sites are configured using /etc/apache2/sites-available/, and enabled using a symbolic link in /etc/apache2/sites-enabled, I use the following technique to address the default host glitch.

Set up a fake site called aardvark.aaa and map it to a default page. It works because in Apache2, virtual hosts are loaded alphabetically, and aardvark.aaa will be the first. (If you have a site named aaa.com, you're out of luck :^)

  1. Copy /etc/apache2/sites-available/000-default.conf to /etc/apache2/sites-available/aardvark.aaa.conf.

sudo cp 000-default.conf aardvark.aaa.conf

Configure like so

    ServerAdmin foo@bar.com
    ServerName aardvark.aaa
    ServerAlias www.aardvark.aaa
    DocumentRoot /var/www/aardvark
  1. Create a symbolic link in /etc/apache2/sites-enabled/ to your config file in ~/sites-available. This will cause the site to be enabled, loaded, and visible in browser:

ln -s ../sites-available/aardvark.aaa.conf

  1. Create an /var/www/aardvark/index.html file in /var/www/ like so

    $ cat > index.html

    hello, world

[CTRL-D]

  1. Bounce your server

    $ sudo systemctl restart apache2

  2. Confirm that aardvark.aaa is loaded first with this command

    $ sudo apache2ctl -S

    root@ip-172-26-2-167:/etc/apache2/sites-enabled# sudo apache2ctl -S VirtualHost configuration: *:80 is a NameVirtualHost default server aardvark.aaa (/etc/apache2/sites-enabled/aardvark.aaa.conf:1) port 80 namevhost aardvark.aaa (/etc/apache2/sites-enabled/aardvark.aaa.conf:1) alias www.aardvark.aaa

  3. Browse to your host/ip address. You should see:

    hello, world

kmiklas
  • 101
  • 2
0

The best solution is to rename the site configuration file starting with a "1" so it will load first and that will be your default site.

Apache2 makes the first loaded vhost file as the default page.

squillman
  • 37,618
  • 10
  • 90
  • 145
xoompa
  • 11
  • 1
0

when using <VirtualHost *:port> and specifying ServerName/ServerAlias for the hosts you care about, which is what I needed to do.

A bit of background in my situation:

I have a dynamic IP address from my ISP so my IP address is registered at a dynamic IP address registering company (noip.org in my case). One of my "hosts" needed to be registered at my DNS registration as myabc.example.com as a CNAME which points to host1.ddns.net. But host2.ddns.net was left as is. I wanted myabc.example.com and host1.ddns.net to go to site1 and host2.ddns.net to go to site 2 and anything else including my IP address to go to default.

The first conf file read will be the default, i.e. 000_def.conf, 001_site1.conf, 002_site2.conf will be read in that order with 000_def.conf as the default site. (note: in my case, I have these "files" in /etc/apache2/sites-enabled which are actually dynamic links to the actual conf file in /etc/apache2/sites-available)

Because ServerName is being used in 001_site1.conf and 002_site2.conf, it must also be set to something in 000_def.conf.

# 000_def.conf:
<VirtualHost *:80>  
ServerName null
# NOTE: DO NOT USE "ServerAlias *" this seems to override the other conf files.
</VirtualHost>


# 001_site1.conf
<VirtualHost *:80>  
ServerName myabc.example.com
ServerAlias mylocalhostname host1.ddns.net
</VirtualHost>


# 002_site2.conf:
<VirtualHost *:80>  
ServerName host2.ddns.net
</VirtualHost>
kasperd
  • 29,894
  • 16
  • 72
  • 122
alan
  • 1