Yet Another Web Server HOWTO
A guide to configuring a static web server using Lighttpd on CentOS 7Table of Contents
Yet Another Web Server HOWTO
Version 1.0.0
Note
This is currently in ‘recipe’ format and doesn't explain why or go into depth. Future plan for this doc is to be more detailed in those areas.
What you get
- Web Server
- Static virtual hosting
- Let's Encrypt SSl certificates
- Admin
- Some attack reduction and blocking
Not in this document
Future work
- Add alternate path for web app support (e.g. CGI, uwSGI, etc).
Out of Scope (i.e. Lots of Other Documentation Sources for These)
- Initial host/instance setup
- General admin utilities and convenience setup
Prerequisites
- An internet accessible host
- DNS Service (such as easydns.ca, self-hosted, etc)
- For this HOWTO: CentOS 7, 1 GiB RAM, 10 GiB HD (e.g. virtual HD)
- Repos
- Defaults + EPEL (to install epel do
yum install epel-release
)
- Defaults + EPEL (to install epel do
Packages
The following packages need to be installed for this setup
(e.g. yum install package1 package2 ...
)
Admin Tools
- policycoreutils
- policycoreutils-python
- rsync
Web Server
- httpd-tools
- lighttpd
Let's Encrypt / ACME SSL Certificates
- certbot
Attack Detection / Blocking
- fail2ban
- fail2ban-firewalld
- fail2ban-server
First Steps
- Configure networking,admin users etc for your host/instance
- (Optional) Install your preferred admin/monitoring utilities etc.
- Install “Admin Tools” listed above
- Add ‘EPEL’ repository listed above
Web Server & Let's Encrypt Configuration
If you are not serving web pages or apps other Certbot configuration might be more suitable for getting Let's Encrypt SSL certificates for your mail server.
Web Server (HTTP: only serves ACME / Let's Encrypt verification)
- Install “Web Server” packages above
- In file
/etc/lighttpd/lighttpd.conf
1. below
```
var.vhosts_dir = server_root + "/vhosts"
```
add
```
var.vhosts_acme_dir = server_root + "/vhosts-acme"
```
2. At end, add:
```
$HTTP["scheme"] == "http" {
include "/etc/lighttpd/vhosts-acme.d/*.conf"
}
```
- Configure IP binding
1. Uncomment the ``server.bind = "localhost"`` line and
replace ``localhost`` with your hostname (e.g.
``example.com``)
2. Below it add ``$SERVER["socket"] == "0.0.0.0:80" { }``.
Optionally replace ``0.0.0.0`` with your ipv4 address.
-
In file, `/etc/lighttpd/conf.d/dirlisting.conf`
-
set `dir-listing.activate` to `"disable"` (unless you want a browse-able list of files and directories for directories without an index file).
-
- In file
/etc/lighttpd/modules.conf
1. inside the directiveserver.modules =
, uncomment or add the following-
mod_alias
, -
mod_redirect
, 2. If you want to redirect example.com to www.example.com, after the closing parentheses forserver-modules
add$HTTP[“scheme”] == “http” { $HTTP[“host”] == “example.com” { url.redirect = (".*” => “http://www.example.com$0”) } }
-
3. Uncomment `include "conf.d/compress.conf"`
4. Execute `mkdir -p /var/cache/lighttpd/compress`
5. Peform `restorecon -Rv /var/cache/lighttpd`
-
For each static virtual host to serve, under
/etc/lighttpd/vhosts-acme.d/
include a file such aswww.example.com.conf
(NB: The filename must end in.conf
):$HTTP["host"] == "www.example.com" { var.server_name = "www.example.com" server.name = server_name server.document-root = vhosts_acme_dir + "/www.example.com" accesslog.filename = log_root + "/" + server_name + "/access.log" }
-
Issue
setsebool -P httpd_setrlimit on
-
In
/etc/lighttpd/lighttpd.conf
setserver.max-connections=512
or setserver.max-fd=2048
(depending on traffic and resources) -
Run
lighttpd-angel -t -f /etc/lighttpd/lighttpd.conf
and correct any errors detected. -
Execute
systemctl restart lighttpd
-
Do
systemctl enable --now lighttpd
Web Server (HTTPS: the real servers; requires SSL)
Prerequisites: Installed and configured web server as above.
Let's Encrypt (Part 1)
-
Install “Let's Encrypt” package above (certbot)
-
Add certbot user and group
adduser -U --system -M certbot passwd -l certbot
-
mkdir -p /etc/letsencrypt/renewal-hooks/deploy && chown -R certbot:certbot /etc/letsencrypt
-
Place the following script in
/etc/letsencrypt/renewal-hooks/deploy
aslighttpd
and make it executable#!/bin/sh RET=0 for CERTBOT_DOMAIN in $RENEWED_DOMAINS; do cd /etc/letsencrypt/live/${CERTBOT_DOMAIN} && cat fullchain.pem privkey.pem >lighttpd.pem && chmod 640 lighttpd.pem || RET=1 done exit $RET
-
Place the following script in
/etc/cron.daily
ascertbot
and make it executable#!/bin/sh /bin/su -c "certbot -q -n renew" certbot
-
Issue
mkdir -p /var/lib/letsencrypt && chown certbot:certbot /var/lib/letsencrypt
-
Do
mkdir -p /var/log/letsencrypt && chown certbot:adm /var/log/letsencrypt
-
Perform
certbot register
Lighttpd configuration (Part 2)
-
Create ACME / Let's Encrypt verification directories (these will be internet accessible from per-vhost directories down (e.g.
www.example.com
in the example below will be the web root))mkdir -p /var/www/vhosts-acme/www.example.com/.well-known chown -R certbot:certbot /var/www/vhosts-acme/www.example.com/.well-known
-
Repeat for each vhost you want to enable
-
Issue
firewall-cmd --add-service http firewall-cmd --add-service https firewall-cmd --runtime-to-permanent
Let's Encrypt (Part 2)
-
Issue
su - certbot certbot certonly --staging --webroot -w /var/www/vhosts-acme/www.example.com -d www.example.com -d example.com
-
If the command completes successfully, repeat the
certbot
command, without--staging
. -
Issue
cd /etc/letsencrypt/live/<default-domain> # In the example above <default-domain> is www.example.com cat fullchain.pem privkey.pem >lighttpd.pem chmod 640 lighttpd.pem exit
Note that Certbot recommendation is to put all hostnames on one
certificate (see certbot --help --webroot
for more information),
unless one has specific reasons for having separate certificates.
If you need separate certificates than you will need to issue the
commands above for each certificate or set of certificates.
Lighttpd configuration (Part 3)
-
In
/etc/lighttpd/lighttpd.conf
, before$HTTP["scheme"] == "http" { include "/etc/lighttpd/vhosts-acme.d/*.conf" }
which you added previously, add
$SERVER[“socket”] == “0.0.0.0:443” { include “ssl.conf” } $SERVER[“socket”] == “[::]:443” { include “ssl.conf” }
-
Add a file
/etc/lighttpd/ssl.conf
that looks like:ssl.engine = "enable" ssl.pemfile = "/etc/letsencrypt/live/www.example.com/lighttpd.pem" include "/etc/lighttpd/vhosts.d/*.conf"
-
And add a file
/etc/lighttpd/vhosts.d/www.example.com.conf
for each virtual host you are adding (in this casewww.example.com
) that looks like:$HTTP["host"] == "www.example.com" { var.server_name = "www.example.com" server.name = server_name server.document-root = vhosts_dir + "/www.example.com" accesslog.filename = log_root + "/" + server_name + "/access.log" }
-
In file
/etc/lighttpd/modules.conf
-
inside the directive
server.modules =
, uncomment or add the following"mod_openssl"
,
-
And if you want to use HTTP authentication for some pages or sites, also uncomment or add the following
"mod_auth"
,"mod_authn_file"
,
-
If you want to redirect HTTP to HTTPS, before
$HTTP["scheme"] == "http" { $HTTP["host"] == "example.com" { url.redirect = (".*" => "http://www.example.com$0") } }
which you added above, add
$HTTP["scheme"] == "http" { $HTTP["host"] == "example.com" { url.redirect = (".*" => "https://www.example.com$0") } }
and after, add
$HTTP["scheme"] == "http" { $HTTP["url"] !~ "^/.well-known/acme-challenge/" { $HTTP["host"] =~ ".*" { url.redirect = ( "^/(.*)" => "https://%0/$1" ) } } }
-
-
If you uncommented/added an mod_auth* line, make sure
/etc/lighttpd/conf.d/auth.conf
is all commented out -
If you want to require HTTP authentication for a page or site
-
in
/etc/vhosts.d/<host-to-require-auth>
, above the closing brace (}
) in the<host>.conf
listed previously, add something similar to:auth.backend = "htdigest" auth.backend.htdigest.userfile = "/etc/lighttpd/users/<host>" auth.require = ( "/" => ( "method" => "digest", "realm" => "[auth-realm]", "require" => "valid-user" ) )
-
Use
htdigest
to create/etc/lighttpd/users/<host>
(man htdigest
for details)
-
-
Do
mkdir -p /var/www/vhosts/www.example.com
for each static vhost you are creating.
DNS Setup
- Add a DNS A record for your ‘base hostname’ (e.g. for example.com with <your-ip>).
- Add a DNS CNAME record for any virtual hosts (e.g. for www.example.com add a CNAME record pointing to example.com)
- Your bare domain name (e.g. example.com) should be A or AAAA records and not CNAMEs. This also helps if you move some subdomains, or the top level domain and some subdomains to services like Netlify.
Attack Detection/Blocking
-
Install “Attack Detection/Blocking” packages listed above
-
Create
/etc/fail2bain/jail.local
like the following:[sshd] port = ssh,<your-alternate-ssh-port-if-applicable> filter = sshd-aggressive enabled = true [selinux-ssh] port = ssh,<your-alternate-ssh-port-if-applicable> enabled = true [lighttpd-auth] enabled = true [recidive] enabled = true
-
Run
touch /var/log/fail2ban.log
-
And finally execute
systemctl enable fail2ban && systemctl start fail2ban