Howto: Lighttpd web server setting up virtual hosting

Lighttpd logo

Last time I wrote about setting and installing lighttpd web server.

Virtual hosting allows sharing a lighttpd web server so that you can have multiple domains hosted on single web server. For example:
=> etc

Our setup

Lighttpd supports both Name-based and IP-based virtual hosts. Let us see how to configure two web sites for:

First create a directory for each domain:

# mkdir -p /home/lighttpd/
# mkdir -p /home/lighttpd/
# chown lighttpd:ftpuser1 /home/lighttpd/
# chown lighttpd:ftpuser2 /home/lighttpd/

Replace ftpuser1 and 2 with actual ftp username.

Also create a log directory for each domain:
# mkdir /var/log/lighttpd/
# mkdir /var/log/lighttpd/

Only allow a web server to access our logs:
# chown -R lighttpd:lighttpd /var/log/lighttpd

Open lighttpd configuration file:
# vi /etc/lighttpd/lighttpd.conf

Add support for domain
$HTTP["host"] =~ "(^|\.)nixcraft\.com$" {
server.document-root = "/home/lighttpd/"
server.errorlog = "/var/log/lighttpd/nixcraft/error.log"
accesslog.filename = "/var/log/lighttpd/nixcraft/access.log"
server.error-handler-404 = "/e404.php"

Add support for domain
$HTTP["host"] =~ "(^|\.)theos\.in$" {
server.document-root = "/home/lighttpd/"
server.errorlog = "/var/log/lighttpd/"
accesslog.filename = "/var/log/lighttpd/"
server.error-handler-404 = "/e404.php"


  • $HTTP[“host”] =~ “(^|\.)theos\.in$” : It will match request for both and domain
  • server.document-root = “/home/lighttpd/” : Server document root. You must set ftp/ssh user home directory to this root only
  • server.errorlog = “/var/log/lighttpd/” : Server access log file
  • accesslog.filename = “/var/log/lighttpd/”: Server error log file
  • server.error-handler-404 = “/e404.php” : Web server error 404 handler file

Save and close the file. Restart the server:
# /etc/init.d/lighttpd restart

Upload file(s) to respective web-root and test your configuration with a web browser.

🐧 Get the latest tutorials on Linux, Open Source & DevOps via RSS feed or Weekly email newsletter.

🐧 28 comments so far... add one
CategoryList of Unix and Linux commands
Disk space analyzersncdu pydf
File Managementcat
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network UtilitiesNetHogs dig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04
28 comments… add one
  • Calvin Chan May 15, 2007 @ 6:56


    I have been trying to setting up this virtual host for my server. However, I am running into this problem where the error log is not stored in the right directory. I have followed everything in your guide. The only difference is that instead of using host, I am using ip based address. It seems like the error will store in the the directory that list ed last first.

    For example:

    $SERVER[“socket”] == “a.b.c.d:80” {
    server.document-root = “/var/www/html/a.b.c.d/”
    server.errorlog = “/var/log/lighttpd/a.b.c.d/error.log”

    $SERVER[“socket”] == “” {
    server.document-root = “/var/www/html/”
    server.errorlog = “/var/log/lighttpd/”

    The error will store in directory. Do you know if there’s a solution to that? Any help would be greatly appreciated. Thanks in advance.


  • 🐧 nixCraft May 15, 2007 @ 12:49

    I’m sorry but I don’t get your problem. Can you explain more..???

  • rxKaffee May 23, 2007 @ 19:53

    It seems that you can only define server.errorlog once in lighty configuration. ie. one errorlog for the whole server and all vhosts.

  • ligesh Jul 3, 2007 @ 4:41

    Yes. The server.errorlog doesn’t work on a per virtualhost basis. Is that a bug or by design?


  • kunal Jul 22, 2007 @ 14:29

    Please check the permissions of your log files

    is the user is root or lighttpd or the user u have created.

    Must note that logfolder/files have lighttpd as owner not root

  • Jain Jul 23, 2007 @ 10:15

    Hi after all the settings done as aforesaid when i try to run my site in browser it give me an error while if i open my site trough IP of the server then it vl open

    in server.bind i m using IP address and and i m trying to open my site
    server.port = 90

    when in browser i type it will open my default page

    but if i type then gives me error problem loading page.

    How to handle this error.
    pls help me

  • Jain Jul 23, 2007 @ 10:22

    opening site in browser with port number

  • shiato han Jul 17, 2008 @ 9:05

    can lighttpd do this kind of virtual hosting (

    linux newbie

  • Terry Jul 21, 2008 @ 14:55

    Regular reader of articles. Just one thing I can’t get sorted out here. What I haven’t done yet that is preventing Lighttpd from running. Error: “can’t find name apache” A clue to sort this out would be great!

  • Roon Oct 27, 2008 @ 12:59

    Thanks for this, I have migrated from apache to lighttpd on my VPS and it has meant that I don’t have to upgrade my VPS memory any more!

    Saved me some money!

  • Dan Wincet Jan 10, 2009 @ 5:04

    Calvin Chan, rxKaffee, and ligesh are right, lighttpd only uses the server.errorlog which appears last in the config file, regardless of any conditionals.

    i wish you would test your config to make sure it works before posting bogus “tutorials” like this.

  • dreams Apr 8, 2009 @ 16:43

    I am all confused. I have installed lighttpd on my embedded linux box. If this box is connected to the pc via USB, I am able to access the webserver. But if I configure the server for some static ip, say a.b.c.d and try to access it by typing http://a.b.c.d:80, I do not get anything at all.

    Do we have to do anything (some change in the .conf file). What is ipv6 and ipv4 all about?

  • Hitur Petur Jun 17, 2009 @ 11:33

    A quick note why might this exacmple not match.
    $HTTP[“host”] =~ “(^|.)$” {
    A port number might be appended to the end…so..

    $HTTP[“host”] =~ “(^|.)[0-9]*)?$”

    Is probably a better guess. This worked for me. Cheers.

  • firmit Jun 21, 2009 @ 6:47

    I had to add my virtual hostname in /etc/hosts as well: localhost vhost1 # which is defined in /etc/lighttp/vhosts.conf

  • Anand Sep 19, 2009 @ 8:15


    I mention the ftp username, where is the pass?

  • Ela Oct 1, 2009 @ 15:39


    Please can you find out why this error log is creating. its increasing day by day. Please tell me a solution to delete this file when it is more than 10 mb.

    [Tue Sep 08 11:08:31 2009] [error] [client] File does not exist: /var/www/vhosts/louis
    [Wed Sep 09 00:20:51 2009] [error] [client] File does not exist: /var/www/vhosts/louis
    [Wed Sep 09 13:43:39 2009] [error] [client] File does not exist: /var/www/vhosts/louisvi
    [Thu Sep 10 18:56:31 2009] [error] [client] File does not exist: /var/www/vhosts/louis
    [Fri Sep 11 00:21:22 2009] [error] [client] File does not exist: /var/www/vhosts/louis
    [Wed Sep 16 00:36:03 2009] [error] [client] File does not exist: /var/www/vhosts/louisvi
    [Wed Sep 16 05:43:16 2009] [error] [client] File does not exist: /var/www/vhosts/louis
    [Wed Sep 16 10:37:25 2009] [error] [client] File does not exist: /var/www/vhosts/louisv
    [Wed Sep 16 10:37:26 2009] [error] [client] File does not exist: /var/www/vhosts/louisv
    [Wed Sep 16 15:58:09 2009] [error] [client] File does not exist: /var/www/vhosts/louisv
    [Thu Sep 17 03:06:00 2009] [error] [client] File does not exist: /var/www/vhosts/louisv
    [Thu Sep 17 07:21:51 2009] [error] [client] File does not exist: /var/www/vhosts/louis
    [Sat Sep 19 02:22:02 2009] [error] [client 76.73.3[Sat Sep 26 11:05:18 2009] [error] [client 66.249.
    71.211] File does not exist: /var/www/vhosts/
    [Sat Sep 26 20:40:23 2009] [error] [client] File does not exist: /var/www/vhosts/

  • Vamsi Oct 19, 2009 @ 14:29

    Thanks..really helpful..
    I was scratching my head to host multiple domains on my vps..


  • HB Dec 6, 2009 @ 1:36

    My newdomain-script lighttpd&mod_mysql_vhost&wordpress_permalink

    echo "Enter new zone"
    read zone
    echo "Enter new domain"
    read domain
    echo "Your new domain is $domain.$zone"
    if [ ! -d  /var/www/servers/$domain.$zone ];
    mkdir /var/www/servers/$domain.$zone
    mkdir /var/www/servers/$domain.$zone/www && chown www-data:www-data /var/www/servers/$domain.$zone/www
    mkdir /var/www/servers/$domain.$zone/logs && chown www-data:www-data /var/www/servers/$domain.$zone/logs
    mkdir /var/www/servers/$domain.$zone/cgi && chown www-data:www-data /var/www/servers/$domain.$zone/cgi
    mkdir /var/www/servers/$domain.$zone/subdomain && chown www-data:www-data /var/www/servers/$domain.$zone/subdomain
    echo '$HTTP["host"] =~ "(^|.)'$domain'.'$zone'$" {' > /etc/lighttpd/vhosts/50-$domain.$zone.conf
    echo 'server.document-root = "/var/www/servers/'$domain'.'$zone'/www/"' >> /etc/lighttpd/vhosts/50-$domain.$zone.conf
    echo 'accesslog.filename = "/var/www/servers/'$domain'.'$zone'/logs/access.log"' >> /etc/lighttpd/vhosts/50-$domain.$zone.conf
    echo 'server.errorlog = "/var/www/servers/'$domain'.'$zone'/logs/error.log"' >> /etc/lighttpd/vhosts/50-$domain.$zone.conf
    echo '#server.error-handler-404 = "/"' >> /etc/lighttpd/vhosts/50-$domain.$zone.conf
    echo '# Wordpress Permalinks' >> /etc/lighttpd/vhosts/50-$domain.$zone.conf
    echo 'include "wp-rewrite.conf"' >> /etc/lighttpd/vhosts/50-$domain.$zone.conf
    echo '}' >> /etc/lighttpd/vhosts/50-$domain.$zone.conf
    echo "[client]" > /home/user/.my.cnf
    echo "port            = 3306" >> /home/user/.my.cnf
    echo "socket          = /var/run/mysqld/mysqld.sock" >> /home/user/.my.cnf
    echo "default-character-set=utf8" >> /home/user/.my.cnf
    echo "user=inshttpd" >> /home/user/.my.cnf
    echo "password=qwertyui" >> /home/user/.my.cnf
    echo "insert into "'`domains`'" ("'`domain`'", "'`docroot`'") values ('$domain.$zone', '/var/www/servers/$domain.$zone/www');"
    > /tmp/$domain.$zone.sql
    /usr/bin/mysql httpd  /dev/null
    # Wordpress Permalinks
    url.rewrite-once = (
      "^/(wp-.+).*/?" => "$0",
      "^/images/.*/?" => "$0",
      "^/temp/.*/?" => "$0",
      "^/(sitemap.xml)" => "$0",
      "^/(xmlrpc.php)" => "$0",
      "^/keyword/([A-Za-z_0-9-]+)/?$" => "/index.php?keyword=$1",
      "^/.*?(?.*)?$" => "/index.php$1"
    • salem Nov 13, 2014 @ 4:51

      Tanks for script I’ll checkout if it’s works .

  • DanielS Jan 13, 2010 @ 7:37

    I just wanted to say thanks, this post helped me get all of my virtual host’s back up and running in no time! I had been using ispconfig3 prior and decided why have extra bloat when I can do it myself with just a little work, and this proved to be much better then what I had before! It’s noticably faster and I can’t thank you enough!

    Also I noticed that user lighttpd wasn’t created however www-data worked fine, is this a problem to be using this user:group instead of lighttpd:lighttpd security wise or other?

    Thanks again!

  • Deo Jan 7, 2011 @ 3:17

    thanks for the inputs. this works for me.


    $SERVER[“socket”] == “:8081” {
    server.document-root = “/var/www/app_name/”
    server.errorlog = “/var/log/lighttpd/app_name/error.log”

  • ankit Mar 29, 2011 @ 11:44

    I am facing the problem in linking the cgi script to the HTML page . whenever i try to open it in the web browser a 404 error appears.
    cgi.assign = ( “.cgi” => “http://ip-address/mnt/apps/web/cgi-bin/” )

    $SERVER[“socket”] == “:80” {
    My cgi bin has a .cgi file in it.

  • satimis Apr 14, 2011 @ 13:51


    # chown lighttpd:ftpuser1 /home/lighttpd/
    # chown lighttpd:ftpuser2 /home/lighttpd/

    Please shed me some light on the groups “ftpuser1” and “ftpuser2”. What they are? Thanks.

    Neither I have user “lighttpd”. Whether run “addusr” to add it?


  • Marc Aug 18, 2011 @ 11:11

    In the first step you create a directory for logs:

    # mkdir /var/log/lighttpd/

    but later you create a file server.errorlog = “/var/log/lighttpd/nixcraft/error.log”

    Did you mean server.errorlog = “/var/log/lighttpd/ ?

  • Nassou Sep 7, 2011 @ 2:10

    Is probably the biggest handicap for lighttpd, guys it’s not possible to set error log for each vhost like apache,nginx etc.

    So this conditionnal will not work :

    $HTTP[“host”] =~ “(^|.)$” {
    >>>> server.errorlog = “/var/log/lighttpd/nixcraft/error.log”

    You have one lighttpd running, so one error.log, so says one of the developers of lighty

    The only method is to track the errors by hand on the script or other, example :

    I will repeat what was said above, lighttpd is designed like that, let’s wait for a patch or other, who knows ?


  • vijay Mar 28, 2012 @ 9:48

    Hi all.. i have configured as wat u said but still i get error “server not found”
    i have added following line in my lighttpd.conf
    $HTTP[“host”] =~ “(^|.)$” {
    server.document-root = “/home/lighttpd/”
    server.errorlog = “/var/log/lighttpd/error.log”
    accesslog.filename = “/var/log/lighttpd/access.log”
    I have upload my webfiles under /
    after that i restarted lighttpd.i opened browser and type
    but it shows server not found.

  • ali Mar 3, 2015 @ 7:12

    can any body tell me how virtual hosting enable in lighttpd in centos 6.5..
    i want to host multiple web site form my server ,,,it may be name based or ip based what ever you have material regarding ….i have done all those step which you have pasted above ….

  • Dan Aug 15, 2015 @ 23:52

    I’m trying to pull a couple of sites into my home office on a rpi 2. I’m using a ddns company and their DUC, set to an obscure port to get around my port 80 block by my ISP. I originally set up using a port redirect on the ddns coming in as my static ip address. How do I set up another domain to ge served by lighttpd? Do I use a different port?

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre> for code samples. Still have questions? Post it on our forum