HOWTO: Setting up your Debian Linode (lighttpd,mysql,+more!)

Hi,

I thought I'd write a quick how-to on getting your Debian Linode up to par. Some of this information is available through the Linode wiki pages, but I thought I'd compile a step-by-step guide for updating Debian, installing the 'essentials', finding your way around the Linode DNS manager, a little fine tuning, and some simple ways to increase your servers security.

Resynchronize package index from repository and upgrade installed packages.

apt-get update && apt-get upgrade

Install build-essential. (gcc/g++/make/dpkg/libs)

apt-get install build-essential

Add a normal user, and create a group for people who are allowed to SSH in – A directive will be added to the sshd_config a little further down.

adduser <username>groupadd -g 9000 ssh_allow
usermod -aG ssh_allow,staff <username></username></username> 

Please note that by default, the OpenSSH package included with Debian has already had TCPwrapping enabled. If you have previously compiled from source and not sure if you've enabled it, you can check by doing this:

strings /usr/sbin/sshd | grep -i hosts_access

If this does not return a result, please follow the steps below to update to the latest OpenSSH release and recompile with TCPwrapping:

apt-get install zlib1g zlib1g-dev libwrap0 libwrap0-dev libssl-dev && cd /usr/src && wget ftp://mirror.planetunix.net/pub/OpenBSD/OpenSSH/portable/openssh-5.2p1.tar.gz && tar zxvf openssh-5.2p1.tar.gz && cd openssh-5.2p1 && ./configure --prefix=/usr --sysconfdir=/etc/ssh --with-tcp-wrappers && make && make install

==CONTINUE AS NORMAL==

Edit your sshdconfig to deny root logins, and only allow people to connect who is a member of the sshallow group.

nano /etc/ssh/sshd_config
PermitRootLogin no
AllowGroups ssh_allow

While we already have the AllowGroups directive in place, it doesn't hurt to take advantage of hosts.deny/allow.

Deny ALL connections to sshd.

nano /etc/hosts.deny
sshd: ALL

However, allow for these hosts to connect.

nano /etc/hosts.allow
sshd: *.yourisp.com

Restart SSH for the new changes to take effect.

/etc/init.d/ssh restart

Renaming your hostname – Just to add a little personality :)

rm -rf /etc/hostname && echo "newhostname" >>/etc/hostname && hostname -F /etc/hostname && echo "127.0.0.1 newhostname" >>/etc/hosts

Setting permissions on utmp, wtmp, lastlog and changing the ownership so only members of the staff group can view the output of the w, who, last, lastlog commands.

You might also want to add these to your /etc/rc.local.

chmod 0640 /var/log/utmp
chmod 0640 /var/log/wtmp
chmod 0640 /var/log/lastlog
chown :staff /var/log/utmp
chown :staff /var/log/wtmp
chown :staff /var/log/lastlog

Remove world readable permissions of /home.

chmod -R 0751 /home

Installing MySQL, Lighttpd, and PHP5.

apt-get install mysql-client mysql-server lighttpd php5-cgi

Caker's MySQL tune:

/etc/init.d/mysql stop && cd /etc/mysql && mv my.cnf my.orig && wget http://www.linode.com/~caker/uml/my.cnf && /etc/init.d/mysql start

Enabling PHP and Virtual Hostnames in Lighthttpd and,

Creating the document root for each Virtual Hostname:

mkdir -p /www/domain1.com 
mkdir -p /www/domain2.com

Create folders for logs to be stored in corresponding domain names, set file permissions for /www and give lighttpd write access to /var/log/lighttpd.

mkdir  /var/log/lighttpd/domain1.com
mkdir /var/log/lighttpd/domain2.com
chown -R username:username /www
chown -R www-data:username /var/log/lighttpd

Enabling PHP.

nano +533 /ec/php5/cgi/php.ini
change "cgi.fix_pathinfo = 0" to "cgi.fix_pathinfo = 1"

server.modules=

nano +14 /etc/lighttpd/lighttpd.conf
add: "mod_fastcgi",

Add this to the bottom of your config.

nano +168 /etc/lighttpd/lighttpd.conf 
 fastcgi.server    = ( ".php" =>
   ((
     "bin-path" => "/usr/bin/php-cgi",
     "socket" => "/tmp/php.socket",
     "max-procs" => 1,
     "idle-timeout" => 20,
     "bin-environment" => (
       "PHP_FCGI_CHILDREN" => "4",
       "PHP_FCGI_MAX_REQUESTS" => "10000"
     ),
     "bin-copy-environment" => (
       "PATH", "SHELL", "USER"
     ),
     "broken-scriptfilename" => "enable"
   ))
 )

Configuring the Virtual names:

nano +155 /etc/lighttpd/lighttpd.conf 

Comment out the original $HTTP[] { } block and add the new blocks for your domains:

$HTTP["host"] =~ "(^|\.)domain1\.com$" {
server.document-root = "/www/domain1"
server.errorlog = "/var/log/lighttpd/domain1.com/error.log"
accesslog.filename = "/var/log/lighttpd/domain1.com/access.log"
}

$HTTP["host"] =~ "(^|\.)domain2\.com$" {
server.document-root = "/www/domain2"
server.errorlog = "/var/log/lighttpd/domain2.com/error.log"
accesslog.filename = "/var/log/lighttpd/domain2.com/access.log"
}

Restart Lighthttpd.

/etc/init.d/lighttpd restart

Now that you've setup Lighttpd, the only thing left to do is point your domain(s) to your VPS. This can be achieved using the Linode DNS Manager.

1\. Log into your domain registrars control panel (where you registered the domain).
2\. You need to edit the name servers of your domain to point to the Linode ones:

NS1.LINODE.COM
NS2.LINODE.COM
NS3.LINODE.COM
NS4.LINODE.COM

3\. Save your changes, and log out of your registrar's control panel.
4\. Log into https://www.linode.com/members/
5\. Click on the "DNS Manager" Tab.
6\. Click on the "Add a new domain zone" link (bottom right).
7\. Enter your Domain Name.
8\. Click continue.
9\. Add your email address to the SOA E-Mail field.
10\. Click Save.

By default, it will have your domain point to the IP address of your Linode VPS. Wait until your DNS propagates and you're done!

EDIT (a few times :P): Fixed spelling errors/typos, and amended a couple of the processes to make them clearer. Thanks for everyone's feedback.

14 Replies

Cool! Thanks for the post. Picked up a few more tips.

A couple questions/comments

1) What version of Debian did you install?

2) Why use tcp_wrappers with openssh instead of iptables?

2.1) How can I tell if the version already installed isn't configured to use tcpwrappers? OpenSSH5.1p1 Debian-5 is what I have installed from the Linode Debian 5 image.

3) I noticed caker's MySQL config is designed for systems with less than 64MB and from the URL appears to be dated since it's referencing UML instead of Xen. Would it still be good advice to use that setup on systems with more memory available or would it be more efficient to let MySQL have a bit more resources?

I haven't compared that config with others I've found for "low memory" systems via google, but everything I've found appears to be years old and for 64MB or less systems.

Hi waldo,

To answer your questions:

@waldo:

1) What version of Debian did you install?

Linode's Debian 5.0 image.

@waldo:

2) Why use tcp_wrappers with openssh instead of iptables?

This is totally by preference, both will work (just a little differently). TCP wrapping blocks at an application level and will allow the IP to connect to it's specific port. The daemon will refer to the hosts.deny/allow configurations as to whether it will accept or deny that connection.

Iptables works directly on the kernel level, and will drop the packets instantly upon inspection (never reaching the daemon).

@waldo:

2.1) How can I tell if the version already installed isn't configured to use tcpwrappers? OpenSSH5.1p1 Debian-5 is what I have installed from the Linode Debian 5 image.

By default it is configured with TCPwrapping enabled. You are able to confirm this on your installation by checking the results of "strings /usr/sbin/sshd | grep -i hosts_access"

@waldo:

3) I noticed caker's MySQL config is designed for systems with less than 64MB and from the URL appears to be dated since it's referencing UML instead of Xen. Would it still be good advice to use that setup on systems with more memory available or would it be more efficient to let MySQL have a bit more resources?

You are correct, it is for smaller systems. Even though it is outdated it still works fine - From the tests I've ran on my VPS, it saves ~4-7mb in RAM compared to running the default MySQL configuration. If you are running a MySQL driven site that is continually sending queries to your databases, then this configuration would not be suitable and you'd need to modify your configuration to allow for it.

Two notes - you can apt-get install build-essential to get the tools required for compiling. build-essential pulls in make and g++; g++ pulls in cpp/gcc/g++ for real, etc. Also, Debian's OpenSSH comes with TCP wrappers enabled.

@Alucard:

Two notes - you can apt-get install build-essential to get the tools required for compiling. build-essential pulls in make and g++; g++ pulls in cpp/gcc/g++ for real, etc. Also, Debian's OpenSSH comes with TCP wrappers enabled.

Ah, thanks! - I had forgotten about build-essential :) I have modified my original post to include this.

@waldo:

2.1) How can I tell if the version already installed isn't configured to use tcpwrappers? OpenSSH5.1p1 Debian-5 is what I have installed from the Linode Debian 5 image.

$ ldd /usr/sbin/sshd | grep libwrap
        libwrap.so.0 => /lib/libwrap.so.0 (0xb7fc3000)

This shows sshd is built against tcpwrappers. If you don't get any output from this command, then it isn't.

@array:

@waldo:

2.1) How can I tell if the version already installed isn't configured to use tcpwrappers? OpenSSH5.1p1 Debian-5 is what I have installed from the Linode Debian 5 image.

By default it is configured with TCPwrapping enabled. You are able to confirm this on your installation by checking the results of "strings /usr/sbin/sshd | grep -i hosts_access"

Then why do your instructions call for a custom build that won't be updated via apt in case of a security bug? You should pull that out completely

Some good tips, but two things:
4. I don't think that you want usermod -g. That overwrites the user's primary membership. It doesn't add multiple group memberships. Instead, I think you want this:
usermod -G username,sshd_allow,staff username
That way the user's primary membership is still the group named after the user (Debian's default), and you add two new groups. Note that you don't want space after the commas.

  1. To edit the ssh configuration, you want to edit /etc/ssh/sshdconfig. The configuration file isn't at /etc/sshdconfig.

@Telemachus:

Some good tips, but two things:
4. I don't think that you want usermod -g. That overwrites the user's primary membership. It doesn't add multiple group memberships. Instead, I think you want this:
usermod -G username,sshd_allow,staff username
That way the user's primary membership is still the group named after the user (Debian's default), and you add two new groups. Note that you don't want space after the commas.

  1. To edit the ssh configuration, you want to edit /etc/ssh/sshdconfig. The configuration file isn't at /etc/sshdconfig.

:oops: Oops typos!

I've amended my original post to use:

usermod -aG sshd_allow,staff

-aG will append to the existing groups.

@glg:

@array:

@waldo:

2.1) How can I tell if the version already installed isn't configured to use tcpwrappers? OpenSSH5.1p1 Debian-5 is what I have installed from the Linode Debian 5 image.

By default it is configured with TCPwrapping enabled. You are able to confirm this on your installation by checking the results of "strings /usr/sbin/sshd | grep -i hosts_access"

Then why do your instructions call for a custom build that won't be updated via apt in case of a security bug? You should pull that out completely

I included this for whatever reason they didn't have it enabled - (eg: someone that recompiled from source, but didn't include the required configure prefix).

Post has been modified to make it clearer.

I just got started with a Debian 5.0 VPS and this is exactly what I signed up on the forum for. Thank you very much.

@array:

Comment out the original $HTTP[] { } block and add the new blocks for your domains:

$HTTP["host"] =~ "(^|\.)domain1\.com$" {
server.document-root = "/www/domain1"
server.errorlog = "/var/log/lighttpd/domain1.com/error.log"
accesslog.filename = "/var/log/lighttpd/domain1.com/access.log"
}

$HTTP["host"] =~ "(^|\.)domain2\.com$" {
server.document-root = "/www/domain2"
server.errorlog = "/var/log/lighttpd/domain2.com/error.log"
accesslog.filename = "/var/log/lighttpd/domain2.com/access.log"
}

AFAIK lighttpd only allows one server.errorlog directive so the last directive entered takes precedence. The configuration you posted will just have the error.log for the entire server placed under the domian2.com files.

@melon:

AFAIK lighttpd only allows one server.errorlog directive so the last directive entered takes precedence. The configuration you posted will just have the error.log for the entire server placed under the domian2.com files.

Thanks for the tip, I was wondering why my /var/log/lighttpd/error.log wasn't getting anything when I was restarting my service the other day.

I had forgot about this thread!

@twblamer:

I just got started with a Debian 5.0 VPS and this is exactly what I signed up on the forum for. Thank you very much.

Great to hear! :)

@melon:

AFAIK lighttpd only allows one server.errorlog directive so the last directive entered takes precedence. The configuration you posted will just have the error.log for the entire server placed under the domian2.com files.

You're right – I actually didn't know this at the time of writing the tutorial. There doesn't look to be any logging directive in lighttpd which is able to log for each individual vhost, only global -- A little searching found a useful tool called 'vlogger' for splitting the log.

@array:

Caker's MySQL tune:

/etc/init.d/mysql stop && cd /etc/mysql && mv my.cnf my.orig && wget http://www.linode.com/~caker/uml/my.cnf && /etc/init.d/mysql start

Found this useful until i got to about the mysql part, mysqld fail

im going through my.cnf and the cakers fine tuning but its so different from my original one that i dont know if i should continue this tutorial or just find a different one.

here is my error:

 /etc/init.d/mysql[5571]: Check that mysqld is running and that the socket: '/var/run/mysqld/mysqld.sock' exists!
Dec  2 06:26:10 li44-14 /etc/init.d/mysql[5571]:
Dec  2 06:27:11 li44-14 mysqld_safe[5624]: A mysqld process already exists
Dec  2 06:27:25 li44-14 /etc/init.d/mysql[5760]: 0 processes alive and '/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf ping' resulted in
Dec  2 06:27:25 li44-14 /etc/init.d/mysql[5760]: #007/usr/bin/mysqladmin: connect to server at 'localhost' failed
Dec  2 06:27:25 li44-14 /etc/init.d/mysql[5760]: error: 'Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)'
Dec  2 06:27:25 li44-14 /etc/init.d/mysql[5760]: Check that mysqld is running and that the socket: '/var/run/mysqld/mysqld.sock' exists!
Dec  2 06:27:25 li44-14 /etc/init.d/mysql[5760]:

thanks

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct