Upgrade from Debian 7 (wheezy) to Debian 9 (stretch) on OpenVZ

I wanted to upgrade a tiny OpenVZ based VPS (128MB of ram and 128MB vswap) from a 32 bits version of Debian 7 (wheezy) to the latest stable Debian 9 (stretch). The host of the VPS is running a 2.6.32-openvz-042stab120.18-amd64 Linux Kernel which is CentOS6 based distro I think, the provider is BuyVM/frantech.

Before embarking in this journey make sure to backup any important data you have on the system, if things goes wrong you have to reinstall your VPS which means all your data will be wiped out!, be warned

The base Debian 7 VPS uses upstart and devtmpfs with udev:

# ps xaf
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:00 init
    2 ?        S      0:00 [kthreadd/58079]
    3 ?        S      0:00  \_ [khelper/58079]
  121 ?        S      0:00 upstart-udev-bridge --daemon
  130 ?        Ss     0:00 /sbin/udevd --daemon
  314 ?        S      0:00 upstart-socket-bridge --daemon
 1637 ?        Sl     0:00 /usr/sbin/rsyslogd -c5
 1748 tty1     Ss+    0:00 /sbin/getty 38400 console
 1750 tty2     Ss+    0:00 /sbin/getty 38400 tty2
 3227 ?        Ss     0:00 /usr/sbin/sshd
 3921 ?        Ss     0:00 vzctl: pts/0               
 3922 pts/0    Ss     0:00  \_ -bash
 3926 pts/0    R+     0:00      \_ ps xaf

# mount
/dev/simfs on / type simfs (rw,relatime,usrquota,grpquota)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
none on /dev type devtmpfs (rw,nosuid,noexec,relatime,mode=755)
none on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,nosuid,nodev,noexec,relatime)
none on /run type tmpfs (rw,nosuid,noexec,relatime,size=13108k,mode=755)
none on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
none on /run/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=52420k)
none on /run/user type tmpfs (rw,nosuid,nodev,noexec,relatime,size=102400k,mode=755)

# dpkg -l upstart udev 
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                          Version                     Architecture                Description
+++-=============================================-===========================-===========================-===============================================================================================
ii  udev                                          175-7.2                     i386                        /dev/ and hotplug management daemon
ii  upstart                                       1.6.1-1                     i386                        event-based init daemon

I want to replace upstart with systemd. At first I was planning to use sysvinit and replace devtmpfs and udev with static entries in /dev, but this was proven to be difficult since I don’t have admin control on the host system to umount /dev in order to create static entries with MAKEDEV on the live VPS, so I settled down with systemd

The following are the steps taken to achieve the objective:

  • fetch the latest updates from wheezy
    # cat /etc/apt/sources.list
    deb http://ftp.debian.org/debian wheezy main contrib non-free
    deb http://ftp.debian.org/debian wheezy-updates main contrib non-free
    deb http://security.debian.org wheezy/updates main contrib non-free
    
    # apt-get update
    # apt-get upgrade -y
    
  • install a text based dialog frontend to debconf (optional)
    # apt-get install -y whiptail
    
  • configure your locale (optional), for me I’ve chosen en_CA.UTF-8 UTF-8 from the locales to be generated and en_CA.UTF-8 for the Default locale for the system environment
    # dpkg-reconfigure locales
    
  • replace upstart with systemd
    # apt-get install -y systemd-sysv
    
  • upgrade to jessie
    # sed -i 's/wheezy/jessie/g' /etc/apt/sources.list
    # apt-get update
    # apt-get upgrade -y
    
  • dist upgrade to jessie
    # apt-get dist-upgrade -y # will take some time to complete, when done cat /etc/debian_version will return 8.x (e.g. 8.9)
    
  • reboot to jessie, systemd should be now the new init
    # reboot -f
    
  • purge leftover upstart configurations and get rid of non needed packages and cached packages under /var/cache/apt/archives
    # dpkg --purge upstart
    # apt-get autoremove -y
    # apt-get clean
    
  • upgrade to stretch
    # sed -i 's/jessie/stretch/g' /etc/apt/sources.list
    # apt-get update
    # apt-get upgrade -y
    
  • dist upgrade to stretch
    # apt-get dist-upgrade -y
    
  • reboot to stretch
    # reboot
    
  • cleanup non needed packages and cached packages under /var/cache/apt/archives
    # apt autoremove -y
    # apt-get clean
    
  • get rid of non needed services (optional)
    # systemctl stop getty@tty2.service
    # systemctl disable getty@tty2.service
    # systemctl stop systemd-logind.service
    # systemctl mask systemd-logind.service
    

ipv6 SLAAC router advertisements in FC20/RHEL7/CentOS7

If you’re using SLAAC to configure devices in your network, there is extra work to do to get thing running in FC20/RHEL7.

On my client machine, I have the following ipv6 configurations:

$ cat /etc/sysctl.d/90-accept_ra.conf 
net.ipv6.conf.default.accept_ra=1

grep ‘^IPV6′ /etc/sysconfig/network-scripts/ifcfg-<dev>

IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_PEERDNS="yes"
IPV6_PEERROUTES="yes"
IPV6_FAILURE_FATAL="no"

Normally this should be enough to get ipv6 working. What I noticed however is that although global ipv6 have been assigned to the client I still can not reach machines outside the network.

ping6 www.google.com
connect: Network is unreachable

In FC20 and RHEL7, NetworkManager is taking control of configuring ipv6 SLAAC:

  • it disable sysctl knob under /proc/sys/net/ipv6/conf/<dev>/accept_ra
    $ cat /proc/sys/net/ipv6/conf/<dev>/accept_ra
    0
    
  • and by default it’s ignoring RA from routers.

To fix that do the following:

  • edit /etc/NetworkManager/NetworkManager.conf and add keyfile to the list of plugins
    [main]
    plugins=ifcfg-rh,keyfile
    

    than restart the service

    # service NetworkManager restart
    
  • nmcli con edit type eth
    nmcli>goto ipv6
    You may edit the following properties: method, dhcp-hostname, dns, dns-search, addresses, routes, ignore-auto-routes, ignore-auto-dns, never-default, may-fail, ip6-privacy
    nmcli ipv6> print
    ipv6.method: auto
    ipv6.ignore-auto-routes: no
    ...
    nmcli ipv6> set ipv6.ignore-auto-routes true
    nmcli ipv6> verify
    Verify setting 'ipv6': OK
    nmcli ipv6> save
    Saving the connection with 'autoconnect=yes'. That might result in an immediate activation of the connection.
    Do you still want to save? [yes] yes
    Connection 'ethernet' (<uuid>) successfully saved.
    nmcli ipv6> quit
    
  • ping6 www.google.com
    should works now!

nginx and gzipped files

Modern web browsers are capable of decompressing/deflating gzipped files on the fly, so I wanted to be able to view the content of the compressed files stored under /usr/share/doc (i.e. Debian’s docs).

The web server I’m using nginx 1.2.1 (Debian’s Wheezy), ships with a proper config file:

       location /doc/ {
                alias /usr/share/doc/;
                autoindex on;
                allow 127.0.0.1;
                allow ::1;
                deny all;
        }

When clicking on a .gz file under /doc/ however, my web browser however (google’s Chrome) was asking me to save the file!.

Troubleshooting this turns on to be that the server is sending a Content-Type: application/octet-stream, make sense for general binary files.

In order to let a web browser capable of deflating gzipped files to handle them properly, we need a Content-Type which can be viewed (e.g. text/plain or text/html) and we need to tell the web browser about the encoding type i.e. Content-Encoding: gzip header for the .gz files.

One solution is to use the nginx’s location directive to identify these files in order to add the proper headers:

location ~ ^/doc/(.*)\.gz$ {
  alias /usr/share;
  gzip off;
  add_header Content-Encoding gzip;
  default_type text/plain;
  try_files $uri $uri =404;
}

If you’re using Debian, you may add the above to /etc/nginx/sites-available/default inside the server directive

If you like to access this over the LAN, just adding an allow x.y.z.0/24; before the deny all; inside the location /doc/ directive would do.

Another annoying thing, since most file under /usr/share/doc don’t have an extension and they’re mostly text file add a default_type text/plain; to the location /doc/ directive