Home Server (v3) – Ubuntu

I found myself recently rebuilding my home server (again).  In December, I lost a drive out of my LVM large disk array and felt that it was time to give CentOS a try at home.  Try as I might, I just wasn’t a fan, and went back to Ubuntu 12.04 LTS.  I tried to do an in-place upgrade (unadvised until 14.04.1 releases later this summer) and wound up being unsatisfied with the results.  So, at the end of June, I began the arduous process of rebuilding to 12.04 and documenting the process along the way.

As a refresher, I have 2x 2TB Seagate hard drives that are setup in software RAID-0 (to create a 4TB “single” drive), and 1x 250gb hard drive.  The OS is installed onto the 250gb, while the 4TB “disk” is mounted to “/data”.  I use dyndns.com to provide a simple domain identity (since my router supports it).  The rest of the internals on the box are inconsequential.  The 4TB disk was created during the installation process.

At the end of the day, I have a home linux-based, headless server that I can use for web development, hosts an instance of GitLab CE, shares media via Samba and NFS, shares my printer amongst the multiple PCs, and of course can serve as a backup location for any of the computers in my house.

The majority of the install and tips comes from various tutorials on howtoforge.com.  Those are:

Overall – http://www.howtoforge.com/perfect-server-ubuntu-12.04-lts-apache2-bind-dovecot-ispconfig-3

Samba – http://www.howtoforge.com/ubuntu-12.04-samba-standalone-server-with-tdbsam-backend

PHP-FPM – http://www.howtoforge.com/using-php5-fpm-with-apache2-on-ubuntu-12.04-lts

I know that I’m repeating quite a bit of the steps in some spots, and in other spots, being woefully inadequate.

After the installation from disk is done, while still physically at the terminal, I change the hostname and network interface to a static IP and make sure that I have SSH up and running before I disconnect the monitor and keyboard.

apt-get update && apt-get upgrade

apt-get install openssh-server ssh

apt-get update  && apt-get install samba cups

nano /etc/samba/smb.conf

Edit the file, looking for following (change values as necessary):

security = user
map to guest = bad user
passdb backend = tdbsam

Make sure to have blocks for “other” shares (such as the music folder)

[Music]
comment = Music, Mp3's
path = /music
force user = username force group = usergroup
read only = No
guest ok = Yes
public = yes
browseable = yes

Don’t forget to allow your “home” directories available. Mine are set to be hidden unless the user is “logged in” on Windows – (just uncomment the lines)

# Un-comment the following (and tweak the other settings below to suit)
 # to enable the default home directory shares. This will share each
 # user's home director as \\server\username
 [homes]
 comment = Home Directories
 browseable = no
# By default, the home directories are exported read-only. Change the
 # next parameter to 'no' if you want to be able to write to them.
 read only = no

Make sure to restart samba (or reboot) before trying to connect to the shares.

service smbd restart

Now add your user account into samba (you’ll be asked for the password).

smbpasswd -a user

I also set up NFS file sharing/serving because for some strange reason, my HTPC has issues with Samba.

apt-get install nfs-kernel-server portmap

For me, it’s as simple as editing /etc/exports and adding the following line:

/data               192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)

After that, just run

exportfs -a

Now, onto setting up shared printing through CUPS.

nano /etc/cups/cupsd.conf

You’ll be editing the following areas to look like this –

# Only listen for connections from the local machine.
Listen *:631 <--- change this
Listen /var/run/cups/cups.sock

# Restrict access to the server...
<Location />
 #Require valid-user
 Order Deny,Allow
 Deny From ALL
 Allow From 127.0.0.1
 Allow From 192.168.1.0/24
</Location>

# Restrict access to the admin pages...
<Location /admin>
 Order Deny,Allow
 Deny from ALL
 Allow From 127.0.0.1
 Allow From 192.168.1.0/24
</Location>

# Restrict access to configuration files...
<Location /admin/conf>
 AuthType Default
 Require user @SYSTEM
 Order Deny, Allow
 Deny from ALL
 Allow from 127.0.0.1
 Allow from 192.168.1.0/24
</Location>

What we’ve done here is limited the access to just local ip’s on our subnet.  (This is just htaccess editing.)  Given that I don’t allow access to port 631 outside of my router anyways, this is overkill for me, but your setup may differ.  Make sure you’ve changed the 127.0.0.1 to “*” so it listens on all interfaces.  Once you’re done, make sure you can access the CUPS server by visiting serverip:631 in a browser.

If you want, you can add the printer now (assuming it’s plugged in) by following the fairly straightforward interface.  Once the printer is setup, from your windows computers, click on the “printers” tab and right click & copy the link for the printer.  When you go to setup on your Windows box, you’ll go to Start -> Devices and Printers -> Add Printer -> Add Network printer.  Click “printer that I want isn’t listed” and select the 2nd option.  Paste the address in the box, making sure to change the https:// to http://.  Follow the rest of the steps and you should be good to go.

Onto the web server stuff.  Most tutorials suggest that you setup in /var/www (or /var/www/html if on CentOS).  While this is certainly convenient, I find that it doesn’t really mimic the feel of being on a shared hosting platform, or even just running multiple sites on the same server.  I prefer running out of userdirs (like on shared hosts).  To save some time when adding users later, edit the skeleton setup file to include a public_html folder.

mkdir /etc/skel/public_html

Now when you setup a new user, there will automatically be a “public_html” folder.

apt-get install mysql-server mysql-client

Follow the on-screen prompts to set your mysql root password (different from your root password).  Now, onto Apache & PHP-FPM.

apt-get install apache2-mpm-worker

apt-get install libapache2-mod-fastcgi php5-fpm php5

a2enmod actions fastcgi alias rewrite

service apache2 restart

Now to set Apache to use fastcgi and php-fpm.  I prefer this method because it’s somewhat (and I use that term loosely) similar to setting up for NGINX.  It’s also less of a headache than running suexec/suphp and mod_php or using httpd_itk/apache2-itk.  If you eventually branch out to a VPS and want to use the new SPDY protocol, this is a MUST (using suexec/suphp or php-fpm).

nano /etc/apache2/conf.d/fastcgi.conf

<IfModule mod_fastcgi.c>
  AddHandler php5-fcgi .php
  Action php5-fcgi /php5-fcgi
  Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi
  FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /tmp/php5-fpm.sock -pass-header Authorization
</IfModule>

and edit /etc/php5/fpm/pool.d/www.conf and change the following section: (you’re commenting out the port and creating a unix socket).  I prefer running my sockets out of the /tmp directory, but that’s me.

;listen = 127.0.0.1:9000
listen = /tmp/php5-fpm.sock

We need to make sure that the default pool also can work across all undefined hosts (just in case)

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions.
; Default Values: user and group are set as the running user
; mode is set to 0666
listen.owner = www-data
listen.group = www-data
;listen.mode = 0666

Also, we need to define the session save path at the end of the file.  Add the following line –

php_admin_value[session.save_path] = /var/lib/php5/www

And make the directory, while assigning it to the www-data user (so the PHP applications can stay “logged in”).

mkdir /var/lib/php5/www  && chown www-data:www-data /var/lib/php5/www

Restart PHP-FPM

service php5-fpm restart

Now install some extra PHP things…

apt-get install php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl

We also install APC caching
apt-get install php-pear php5-dev make libpcre3-dev
pecl install apc

Now we need to edit php.ini

nano /etc/php5/fpm/php.ini

add the following at the end:

[apc]
extension=apc.so
apc.write_lock = 1
apc.slam_defense = 0

And we install phpMyAdmin

apt-get install phpmyadmin

Select “apache2” and decline the dbconfig-common option.

Now, onto configuring the server to use the /home/user/public_html directory.  We’ll copy the default fpm pool and make some changes.

cp /etc/php5/fpm/pool.d/www.conf /etc/php5/fpm/pool.d/user.conf

edit the user.conf and we’re going to change just a few things at the moment…

;pool name ('www' here)
[user]
user = username
group = usergroup
listen = /tmp/php5-fpm-user.sock

It’s important that you also uncomment and modify the “listen.owner” and “listen.group” lines, so that when all is said and done, if you run WordPress, you can do file modifications and such from the admin area.

php_admin_value[session.save_path] = /var/lub/php5/user

mkdir /var/lib/php5/user  && chown user:user /var/lib/php5/user

Now we set up our “default” site to point to the user directory.

nano /etc/apache2/sites-available/default

The final result should look something like this (bold is the changes)

<VirtualHost *:80>
 ServerAdmin webmaster@localhost

 ServerName examples.com
 ServerAlias *.example.com

DocumentRoot /home/user/public_html
 <Directory />
  Options FollowSymLinks
  AllowOverride None
 </Directory>
 <Directory /home/user/public_html>
  Options Indexes FollowSymLinks MultiViews
  AllowOverride All
  Order allow,deny
  allow from all
 </Directory>
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
 <Directory "/usr/lib/cgi-bin">
  AllowOverride None
  Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
  Order allow,deny
  Allow from all
 </Directory>
ErrorLog ${APACHE_LOG_DIR}/user-error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/user-access.log combined
Alias /doc/ "/usr/share/doc/"
<Directory "/usr/share/doc/">
 Options Indexes MultiViews FollowSymLinks
 AllowOverride None
 Order deny,allow
 Deny from all
 Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>
<IfModule mod_fastcgi.c>
 AddHandler php5-fcgi .php
 Action php5-fcgi /php5-fcgi
 Alias /php5-fcgi-user /usr/lib/cgi-bin/php5-fcgi-user
 FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi-user -socket /tmp/php5-fpm-user.sock -pass-header Authorization
</IfModule>
</VirtualHost>

The ServerName and ServerAlias bits are important, especially if you plan to use WordPress in multisite mode for development.  Servername is necessary any time you want to run multiple sites (like gitlab below).

While I don’t use my home box as a true email server, I do have postfix installed and routed through Mailjet (a free service) to deliver any service mails.  I use a service from mailjet to ensure deliverability for my real email server, so I just use that for the home box as well.  Mailjet is free for the first 6,000 emails per month, so I highly recommend it for something like this.  You can also use a gmail account as a relayhost (not covered here).

apt-get install postfix

Configuration options:

Internet with smarthost
SMTP relay: in.mailjet.com

Next, you’ll need to edit /etc/postfix/main.cf and add the following lines at the end:

smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/saslpasswd
smtp_always_send_ehlo = yes

Next we’ll need to create that saslpasswd file, and it should look like this:

in.mailjet.com username:userpassword

(Keep in mind the username/pass is actually a long string, and NOT what you log into mailjet with).

Now just run postmap /etc/postfix/saslpasswd and restart postfix.

I started to use git versioning for my projects, and rather than using the hosted platform, I run my own Gitlab instance.  (Totally optional.)

I followed the install instructions from https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md up until section 6 (NGINX).  Since I use apache, there’s a few differences in the setup at this point.

a2enmod proxy proxy_balancer proxy_http rewrite

gem install passenger

passenger-install-apache2-module

At the end of the install, it will have a few lines you’ll need to add to the apache config files (or vhost files).  My vhost file looks something like below –

LoadModule passenger_module /usr/local/lib/ruby/gems/2.1.0/gems/passenger-4.0.45/buildout/apache2/mod_passenger.so

<IfModule mod_passenger.c>
 PassengerRoot /usr/local/lib/ruby/gems/2.1.0/gems/passenger-4.0.45
 PassengerDefaultRuby /usr/local/bin/ruby
</IfModule>

<VirtualHost *:80>
 ServerName gitlab.example.com

 # !!! Be sure to point DocumentRoot to 'public'!
 DocumentRoot /home/gitlab/gitlab/public

 <Directory /home/gitlab/gitlab/public>
   # This relaxes Apache security settings.
   AllowOverride all
   # MultiViews must be turned off.
   Options -MultiViews
 </Directory>

</VirtualHost>

For the final step, install fail2ban.  I feel this is important because it will attempt to limit “brute force” SSH attacks against your server.

apt-get install fail2ban

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit the jail.local as you see fit.  The defaults aren’t too bad, but one of the things I found was I was getting emails every ban that was executed on my CentOS servers.  All the lines that have “sendmail” as an action I deleted from my configs.  On Ubuntu, you’ll need to delete the lines that start with:

%(mta)s-whois

(commenting those out seemed to throw errors for me).  Make sure you’ve enabled fail2ban on startup: update-rc.d fail2ban defaults. 

I don’t run a traditional FTP server (security reasons), and find that SFTP over SSH works just fine for what little I do.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.