Linux Migration

Migration can be a result of having to restore data from an old server, or simply wanting to upgrade the current server.

These are the basic steps to perform:

Setup Operating System

  • Install Linux.
  • Add command aliases. Edit ~/bashrc:
    alias l='ls -l'
    alias ll='ls -la'

OpenSUSE

  • Install required packages:
    • mc:
      % zypper install mc 
    • apache
    • mysql
    • php:
      % yast2 -i apache2-mod_php5 
      % service apache2 restart
    • mysql support for PHP (and additional optional modules):
      % yast2 -i php5-mysql php5-bcmath php5-bz2 php5-calendar php5-ctype php5-curl php5-dom php5-ftp php5-gd php5-gettext php5-gmp php5-iconv php5-imap php5-ldap php5-mbstring php5-mcrypt php5-odbc php5-openssl php5-pcntl php5-pgsql php5-posix php5-shmop php5-snmp php5-soap php5-sockets php5-sqlite php5-sysvsem php5-tokenizer php5-wddx php5-xmlrpc php5-xsl php5-zlib php5-exif php5-fastcgi php5-pear php5-sysvmsg php5-sysvshm 
    • phpMyAdmin:
      % cd /srv/www/htdocs/support
      % wget http://downloads.sourceforge.net/project/phpmyadmin/phpMyAdmin/3.3.5/phpMyAdmin-3.3.5-all-languages.tar.gz?use_mirror=dfn
      % tar xvfz phpMyAdmin-3.3.5-all-languages.tar.gz
      % mv phpMyAdmin-3.3.5-all-languages phpmyadmin
      • Rename config file:
        % cp config.sample.inc.php config.inc.php 
      • Edit file secret:
        $cfg['blowfish_secret'] = 'yeswecan'; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */

Ubuntu

  • Install required packages:
    • updates:
      % apt-get update 
      % apt-get upgrade
      % sudo do-release-upgrade
      % apt-get install update-manager-core
      % apt-get install build-essentials
    • mc (Midnight Commander):
      % apt-get install mc
    • apache:
      % apt-get install apache2
      % apt-get install libapache2-mod-php5
    • mysql:
      % apt-get install mysql-server
    • samba:
      % apt-get install samba
    • sendmail:
      % apt-get install sendmail
    • php:
      % apt-get install php5
      % apt-get install php5-mysql
      % apt-get install php5-mcrypt
      % apt-get install php5-gd

      Alternatively, install all optional modules:

      % apt-get install php5-mysql php5-bcmath php5-bz2 php5-calendar php5-ctype php5-curl php5-dom php5-ftp php5-gd php5-gettext php5-gmp php5-iconv php5-imap php5-ldap php5-mbstring php5-mcrypt php5-odbc php5-openssl php5-pcntl php5-pgsql php5-posix php5-shmop php5-snmp php5-soap php5-sockets php5-sqlite php5-sysvsem php5-tokenizer php5-wddx php5-xmlrpc php5-xsl php5-zlib php5-exif php5-fastcgi php5-pear php5-sysvmsg php5-sysvshm 

Restore Data

  • Review data that was backed up using system backup procedure.
  • Copy backup data to /data/backup (Ubuntu) or /home/data/backup (openSUSE).
  • Unpack backup data:
    % cd /data/backup
    % tar xzf websitebackup.tar.gz
    % tar xzf mysql-data-backup.tar.gz
    % tar xzf homesbackup.tar.gz
    % tar xzf etc-dir.tar.gz

Setup System Users

  • Create system users. Edit the following files:
    • /etc/passwd
    • /etc/shadow
    • /etc/group
    • /etc/gshadow
  • Create any additional users:
     % useradd <username> -m -G <usergroup> 
  • Create group web with all the web admins in there.
     % groupadd <groupname> 
  • Add any existing users to existing group:
     %  usermod -a -G <groupname> <username> 

Setup MySQL Databases

  • Reset MySQL root password:
     % mysqladmin -p'oldpwd' password newpwd 
  • Restore directories:
    • /var/www
    • /var/lib/mysql
  • Get copy of phpMyAdmin and install it under /var/www/support/phpmyadmin.
  • Setup mysql user with rights to the following databases:
    • joomlausr for audina_joomla1_en (Audina website, English)
    • joomlausr for audina_joomla1_es (Audina website, Spanish)
    • joomlausr for auditiva_joomla15_es (Auditiva website, Spanish).
    • joomlausr for auditiva_joomla15_en (Auditiva website, English).

Setup Apache

Test Page

Test webpage with PHP support:

Virtual Hosts

Setup virtual hosts for apache.

Create virtual host for audina.net. Create or edit file default in /etc/apache2/sites-available:

<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>
 
        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 /var/log/apache2/error.log
 
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
 
        CustomLog /var/log/apache2/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>
 
</VirtualHost>

Create virtual host for auditiva.us. Create file auditiva in /etc/apache2/sites-available:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        ServerName www.auditiva.us
        ServerAlias auditiva.us
 
        DocumentRoot /var/www/auditiva/es
        <Directory />
                Options FollowSymLinks
                #AllowOverride None
        </Directory>
        <Directory /var/www/auditiva/es/>
                Options Indexes FollowSymLinks MultiViews
                #AllowOverride None
                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 /var/log/apache2/auditiva-error.log
 
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
 
        CustomLog /var/log/apache2/auditiva-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>
 
</VirtualHost>

Verify that AllowOverride None is commented out (add a # in front) for websites to take advantage of .htaccess overrides.

Create link to file /etc/apache2/sites-available/auditiva:

$ cd /etc/apache2/sites-enabled
$ ln -s ../sites-available/auditiva 001-auditiva

Setup Samba

  • Restore Samba config files:
    • /etc/samba/smb.conf
    • /etc/samba/smbpasswd
    • /etc/samba/smbusers
    • Restore /var/lib/samba if using tdbsam database file.
  • Add required Samba users:
    % smbpasswd -a <username> 
  • Ubuntu uses the tdbsam backend for storing usernames/passwords (instead of /etc/samba/smbpasswd file).
    • To get an smbpasswd-like output, try:
       % pdbedit -w -L 
    • tdbsam database file is located in /var/lib/samba

Setup Joomla

  • Patch Joomla 1.5.x to work with PHP5/MySQL5:
    • Upgrade Joomla to 1.5.20 at least.
  • Edit the configuration files for the Joomla sites:
    • Audina (English): /var/www/configuration.php
    • Audina (Spanish): /var/www/es/configuration.php
    • Auditiva (English): /var/www/auditiva/en/configuration.php
    • Auditiva (Spanish): /var/www/auditiva/es/configuration.php
  • Edit the following settings:
    • $mosConfig_absolute_path = '/var/www';
    • $mosConfig_cachepath = '/var/www/cache';
    • $mosConfig_db = 'audina_joomla1_en';
    • $mosConfig_live_site = 'http://www.audina.net';
    • $mosConfig_password = 'joomlapass';
    • $mosConfig_user = 'joomlausr';

Sample Joomla 1.x configuration file:

<?php
$mosConfig_MetaAuthor = '1';
$mosConfig_MetaDesc = 'Audina Hearing Instruments, Inc. - Digital, Programmable and Conventional Products, Intuitive Fitting Software, Old Fashioned Customer Care.';
$mosConfig_MetaKeys = 'audina, Audina, Longwood, Orlando, Florida, Manufacturer, Audiologist, Hearing, Hearing Loss, Hearing Instruments, Hearing Aids, Flx, Intellio, Intuition, Simplex, Sparo, BTE, ITE, OTE, Open Ear';
$mosConfig_MetaTitle = '1';
$mosConfig_absolute_path = '/var/www';
$mosConfig_allowUserRegistration = '0';
$mosConfig_back_button = '0';
$mosConfig_cachepath = '/var/www/cache';
$mosConfig_cachetime = '900';
$mosConfig_caching = '0';
$mosConfig_db = 'audina_joomla1_en';
$mosConfig_dbprefix = 'mos_';
$mosConfig_debug = '0';
$mosConfig_dirperms = '0755';
$mosConfig_editor = 'none';
$mosConfig_enable_log_items = '0';
$mosConfig_enable_log_searches = '0';
$mosConfig_enable_stats = '0';
$mosConfig_error_message = 'This site is temporarily unavailable.<br /> Please notify the System Administrator';
$mosConfig_error_reporting = '-1';
$mosConfig_favicon = '';
$mosConfig_fileperms = '0644';
$mosConfig_fromname = 'Audina Hearing Instruments, Inc.';
$mosConfig_gzip = '0';
$mosConfig_helpurl = '';
$mosConfig_hideAuthor = '1';
$mosConfig_hideCreateDate = '1';
$mosConfig_hideEmail = '0';
$mosConfig_hideModifyDate = '1';
$mosConfig_hidePdf = '1';
$mosConfig_hidePrint = '0';
$mosConfig_hits = '1';
$mosConfig_host = 'localhost';
$mosConfig_icons = '1';
$mosConfig_item_navigation = '0';
$mosConfig_lang = 'english';
$mosConfig_lifetime = '1800';
$mosConfig_link_titles = '1';
$mosConfig_list_limit = '50';
$mosConfig_live_site = 'http://www.audina.net';
//$mosConfig_live_site = 'http://192.168.0.133';
$mosConfig_locale = 'en_US';
$mosConfig_mailer = 'mail';
$mosConfig_mailfrom = 'webmaster@audina.net';
$mosConfig_ml_support = '0';
$mosConfig_multipage_toc = '1';
$mosConfig_offline = '0';
$mosConfig_offline_message = 'This site is down for maintenance.<br /> Please check back again soon.';
$mosConfig_offset = '4';
$mosConfig_offset_user = '0';
$mosConfig_pagetitles = '1';
$mosConfig_password = 'joomlapass';
$mosConfig_readmore = '1';
$mosConfig_secret = 'JuNgVY1BnynZQxTa';
$mosConfig_sef = '0';
$mosConfig_sendmail = '/usr/sbin/sendmail';
$mosConfig_session_life_admin = '1800';
$mosConfig_session_type = '0';
$mosConfig_shownoauth = '0';
$mosConfig_sitename = 'Audina Hearing Instruments, Inc.';
$mosConfig_smtpauth = '0';
$mosConfig_smtphost = 'localhost';
$mosConfig_smtppass = '';
$mosConfig_smtpuser = '';
$mosConfig_uniquemail = '0';
$mosConfig_user = 'joomlausr';
$mosConfig_useractivation = '1';
$mosConfig_vote = '0';
setlocale (LC_TIME, $mosConfig_locale);
?>

Setup Subversion

Install and Configure

  • Install Subversion:
     % apt-get install subversion 
  • Setup user permissions:
    • Create svn group:
       %  groupadd svn 
    • Set directory permissions to svn.
       
      % chgrp -R svn /data/repos
      % chmod g+s /data/repos
      % chmod o-rx /data/repos/
    • Add users to svn group:
      % usermod -a -G svn joel
      % usermod -a -G svn smayr
      % usermod -a -G svn ajdavis
  • Create startup script:
    #! /bin/sh
    ### BEGIN INIT INFO
    # Provides:          svnserve
    # Required-Start:    $local_fs $syslog $remote_fs
    # Required-Stop:     $local_fs $syslog $remote_fs
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: Start svnserve
    ### END INIT INFO
     
    # Author: Michal Wojciechowski <odyniec@odyniec.net>
     
    PATH=/sbin:/usr/sbin:/bin:/usr/bin
    DESC="svnserve"
    NAME=svnserve
    DAEMON=/usr/bin/$NAME
    #DAEMON_ARGS="-d -r /usr/local/svn/repos"
    DAEMON_ARGS="-d -r /data/repos"
    PIDFILE=/var/run/$NAME.pid
    SCRIPTNAME=/etc/init.d/$NAME
     
    [ -x "$DAEMON" ] || exit 0
     
    [ -r /etc/default/$NAME ] && . /etc/default/$NAME
     
    . /lib/init/vars.sh
     
    . /lib/lsb/init-functions
     
    do_start()
    {
    	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
    		|| return 1
    	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
    		$DAEMON_ARGS \
    		|| return 2
    }
     
    do_stop()
    {
    	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
    	RETVAL="$?"
    	[ "$RETVAL" = 2 ] && return 2
    	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    	[ "$?" = 2 ] && return 2
    	rm -f $PIDFILE
    	return "$RETVAL"
    }
     
    case "$1" in
      start)
    	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    	do_start
    	case "$?" in
    		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    	esac
    	;;
      stop)
    	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    	do_stop
    	case "$?" in
    		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    	esac
    	;;
      restart|force-reload)
    	log_daemon_msg "Restarting $DESC" "$NAME"
    	do_stop
    	case "$?" in
    	  0|1)
    		do_start
    		case "$?" in
    			0) log_end_msg 0 ;;
    			1) log_end_msg 1 ;; # Old process is still running
    			*) log_end_msg 1 ;; # Failed to start
    		esac
    		;;
    	  *)
    	  	# Failed to stop
    		log_end_msg 1
    		;;
    	esac
    	;;
      *)
    	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    	exit 3
    	;;
    esac
     
    exit 0
  • Enable automatic startup of Subversion server:
     % update-rc.d svnserve defaults 
  • Enable Subversion port in firewall:
    % ufw enable
    % ufw allow to 192.168.0.133 port 3690 
    % ufw status verbose

Restore Repository

  • Create repository container directory:
     % mkdir /data/repos 
  • Create new repository:
     % svnadmin create /data/repos/myproj1 
  • Enable security for project:
    • Edit /data/repos/myproj1/conf:
      [users]
      joel = somepassword
      smayr = anotherpassword
      ajdavis = yetanotherpassword
    • Edit /data/repos/myproj1/svnserve.conf:
      [general]
      anon-access = none
      password-db = passwd
      realm = Software Repository
  • Load backup into new repository:
     % svnadmin load /data/repos/myproj1 < /data/backup/repo-myproj1.svn_dump 

Setup IP Address

  • Setup correct hostname:
     % hostname <newhostname> 
  • Restore IP address to the final one. Edit file /etc/network/interfaces:
    #----------------------------------------
    # Configure Loopback device (lo)
    #----------------------------------------
    auto lo
    iface lo inet loopback
     
    #----------------------------------------
    # Configure Ethernic NIC (eth0)
    #----------------------------------------
    # use dhcp assigned ip address
    #auto eth0
    #iface eth0 inet dhcp
     
    # use static ip address
    auto eth0
    iface eth0 inet static
    address 192.168.0.2
    netmask 255.255.255.0
    network 192.168.0.0
    broadcast 192.168.0.255
    gateway 192.168.0.1
  • Restart interfaces:
     % sudo /etc/init.d/networking restart 

Setup Default Startup Services

  • Run the following registration for the service you need to startup automatically:
     % update-rc.d <servicename> defaults 
  • Some required services:
    % update-rc.d apache2 defaults
    % update-rc.d mysql defaults
    % update-rc.d samba defaults
    % update-rc.d ssh defaults
    % update-rc.d svnserve defaults
  • The option “defaults” puts a link to start the specified service in run levels 2, 3, 4 and 5 (and puts a link to stop the service into 0, 1 and 6).

Setup Firewall

  • Activate firewall:
    % ufw enable 
    % ufw status verbose
  • Add rule to open needed ports (web, ssh, samba, subversion):
    % ufw allow to 192.168.0.2  port 80
    % ufw allow to 192.168.0.2  port 22
    % ufw allow to 192.168.0.2  port 139 from 192.168.0.0/24
    % ufw allow to 192.168.0.2  port 445 from 192.168.0.0/24
    % ufw allow to 192.168.0.2  port 3690 from 192.168.0.0/24

    or better yet, create a script to run at boot time:

    # turn on ufw
    ufw enable
    # log all activity (you'll be glad you have this later)
    ufw logging on
    # allow port 80 for tcp (web stuff)
    ufw allow 80/tcp
    # allow our ssh port
    #ufw allow 5555
    #----------------------------
    # local
    #----------------------------
    # http
    ufw allow to 192.168.0.2  port 80
    # ssh
    ufw allow to 192.168.0.2  port 22
    # samba
    #ufw allow to 192.168.0.2  port 137/udp from 192.168.0.0/24
    #ufw allow to 192.168.0.2  port 138/udp from 192.168.0.0/24
    ufw allow to 192.168.0.2  port 139 from 192.168.0.0/24
    #
    ufw allow to 192.168.0.2  port 445 from 192.168.0.0/24
    # subversion
    ufw allow to 192.168.0.2  port 3690 from 192.168.0.0/24
    # deny everything else
    ufw default deny
    # open the ssh config file and edit the port number from 22 to 5555, ctrl-x to exit
    nano /etc/ssh/sshd_config
    # restart ssh (don't forget to ssh with port 5555, not 22 from now on)
    /etc/init.d/ssh reload
  • Install GUI for uwf firewall (optional):
    % apt-get install gufw 
    • It shows up in the GUI under System > Administration > Firewall Configuration.
Ubuntu 14.04 Migration

Patches to Apply After Installation

Some software packages (eg. Piwik/Matomo, Piwigo) generate this error: pclzip.lib.php : Missing zlib extensions. To fix it, add this code to each file using gzopen (a function deprecated in favor of gzopen64 in Ubuntu 14.04).

<?php
 
/**
 * On ubuntu in some cases, there is a bug that gzopen does not exist and one must use gzopen64 instead
 * Credit goes to the piwik team for this.
 * See more: http://www.thomasmonaco.com/pclzip-lib-php-missing-zlib-extensions/
 */
if (!function_exists('gzopen')
    && function_exists('gzopen64')) {
    function gzopen($filename , $mode = 'r', $use_include_path = 0 )
    {
        return gzopen64($filename , $mode, $use_include_path);
    }
}
 
?>