The Importance of a Pleasurable User Experience

I’ve been thinking of getting myself a Raspberry Pi and configuring it to be my home network wireless gateway. While researching all the hardware pieces to get I thought I should try to decide on a Linux distribution. That quest prompted this post.

I’ve been using Fedora 19 with KDE for a good while now in an ESX VM. It does all the things I need and then some. But beyond that it’s been a pleasure working with it. I love the organized output yum provides. Other features like delta rpms and yum ps are also useful and just nice. I find the systemd user experience to be fantastic. It’s easy and simple to use. SELinux hasn’t bothered me so far. I can’t wrap my head around firewalld just yet but it stays out of my way as well. Fedora’s policy of sticking to upstream defaults means I get a purer upstream experience in an integrated distro. This is not always a good thing because KDE really has cumbersome or missing default settings. But once set up properly, KDE just runs and runs. I am in a Windows environment at work and RDP is just natural to use. Fedora 19 with KDE runs well enough over RDP using the xrdp package. I do get some harmless(?) error messages when first logging in over RDP but my work continues unabated.

With the release of Fedora 20 Beta I decided to give GNOME a try. My first impression is that it has a really good design for the shell, albeit on the minimalist side, and has great keyboard shortcuts. Some default settings don’t make sense to me but exploring gsettings has fixed some of the ones I care about. For the kind of work I do I have found GNOME Shell 3.10 to be an absolute pleasure to work with. It stays out of my way and I can focus on the things that really matter. Unlike all the hoopla about “power users” disliking GNOME Shell’s minimalism I found it to be very refreshing.

Coming back to Raspberry Pi, I’m quite comfortable with Fedora these days. In fact, when I use CentOS 6.4 I miss a lot of the things I’ve gotten used to in Fedora. So my first choice for RPi is Fedora, or Pidora, the spin specially made for it. The downside is that Pidora is tracking Fedora 18 and I want something new. I had hoped Fedora 20 would support RPi out of the box but can’t find any information on it.

My second option for RPi is Raspbian, a spin of Debian. Having gotten used to yum and systemd I find apt-get/aptitude and /etc/init.d to be far less pleasurable to work with. They get the job done equally well but I don’t like using them all that much. It’s just a matter of preference. I tried to dabble with creating deb and rpm packages and my initial take was that rpm is easier to create and manage. I’ll keep Raspbian as a second option for my RPi because I have experience with Debian. But I’d also like the Debian project to focus a bit more on making their tools more “fun” to use. Adopting systemd will be a good first step.

Ubuntu isn’t an option for RPi since they don’t support it just yet. I installed Ubuntu 13.10 in a VM to see how much it has changed since 12.04. I have to say the first thing I did was disable online searches in Dash, remove the Amazon icon from the launcher, and enable workspaces. These three things mean that Unity is no longer the same pleasurable experience it was in 12.04. Having used GNOME Shell 3.10 I missed the HUD but Unity’s “feature” of hiding the menu items became annoying quickly. It wasn’t so when I used 12.04 but KDE and GNOME Shell have made me realize you don’t really need to hide menu items even if you have HUD.

Ubuntu also has the issue of Upstart. It’s great to be able to use start/stop commands but not all services recognize them. I have to use start/stop, /etc/init.d, or service to start or stop my services. There’s no single method to do so. Enabling and disabling services is also cumbersome. I also dislike the policy of starting services right after installing or upgrading. Given these issues I find Ubuntu to not be a pleasurable experience anymore.

openSUSE 13.1 released today and it has some great things going for it. I haven’t tried it out but it’s because of one main thing: YaST. At the core of my being I find YaST to be a redundant tool for a lot of things, especially networking, firewall, and package management. I’d be very happy to skip YaST and just use CLI tools to manage most core things. I find those tools to provide a better experience than YaST’s CLI. I asked Jos Poortvliet, openSUSE’s community manager, on Twitter whether YaST was necessary and he said it wasn’t. I’ll take his word and try out openSUSE again, especially since they have a special build for RPi. I’ll revise my stance and make openSUSE my first choice for RPi. Maybe YaST will be helpful in creating my wireless gateway.

I also tried out Arch for the first time. It took me about 3-4 hours to make a customized list of steps to do a UEFI install as well as a BIOS install in a VM. I can say with all honesty that it wasn’t hard to install Arch at all since the wiki is so helpful. The wiki could be better but it’s still very useful. I thought that Arch’s simplicity and DIY nature would be a perfect fit for my RPi. I can install only the things I need and nothing more. I was excited.

And as I configured my VM further I realized I really have to do everything myself. Even the useradd command needs all the flags, compared to Fedora where you just provide the username. This brought me to my first crossroads: do I really want to create my own distro (so to speak) or have fun with setting up a wireless gateway? I think I’ll choose the latter. I want a distro to work out of the box which I can then use to do things other than creat emy own version of a Linux distro. Arch is a pleasure to use if you want to learn Linux but a burden if you want to use Linux to build something. I also feel like I want to go beyond re-inventing the wheel every time I do a new install, instead I want to build on top of the thousands of hours volunteers have spent building a solid distro, be it Fedora, openSUSE, Ubuntu, Debian, or whatever. I want to build a solution not a distro. I’ll still keep Arch as a candidate for my RPi because its simplicity is a very compelling factor.

So there you have it. I have tried to describe a pleasurable user experience by intertwining reviews of different distros with my needs for a wireless gateway using RPi. I find Fedora to be the most pleasurable distro today. It represents the hard work of a lot of upstream contributors in a package that’s friendly. It may not be the distro for new users but if I’m setting up a system for someone new to Linux, and I had to provide support for it, I’d use Fedora. For my RPi I’ll use openSUSE, Pidora, Raspbian, and Arch in that order. I’ll stop when I find the most pleasurable distro for that use case.

GNOME 3.10 Post Install Customization

With the release of Fedora 20 Beta I thought I’d give GNOME a try after having used KDE in Fedora 19. Although I’m still learning my way across the desktop environment, a few things struck with me immediately.

The GNOME design is minimal, to say the least. They have disabled a lot of features by default and some of them really bugged me. On the other hand, there were more default settings (especially keyboard shortcuts) than I found in KDE. Your best friends in GNOME are gsettings, gnome-tweak-tool, and dconf-editor, if you want to customize GNOME Shell. I’m finding out that they may not be enough, though.

Anyways, the three things that I changed right away were:

  • Show date in the top bar/panel
    gsettings set org.gnome.desktop.interface clock-show-date true
  • Show seconds in the top bar/panel
    gsettings set org.gnome.desktop.interface clock-show-seconds true
  • Show logout option
    gsettings set org.gnome.shell always-show-log-out true

You may also want to install gnome-tweak-tool and dconf-editor.

su -c 'yum install gnome-tweak-tool dconf-editor'

These are GUI tools to help you customize the Shell. If you want to stick with CLI then run gsettings list-recursively and explore all the available options.

virtualenv with Python 3 using venv

Python 3 comes with its own virtualenv built in, and it’s called venv. Using it is fairly simple and quick. Make sure you have installed Python 3 on your system. Also make sure you have installed the Python 3 development library for your distribution. For example, install python3-devel on Fedora and python3-dev on Ubuntu.

Then run the following command to create your virtualenv.

cg@codeghar [~] $ pyvenv ~/myvenv

Note: In Ubuntu 14.04 (attempted on 2014-04-17) you may get an error:

cg@codeghar [~] $ pyvenv-3.4 ~/myvenv
Error: Command '['/home/cg/myvenv/bin/python3.4', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1

To work around it, make sure you use the --without-pip flag, like so pyvenv-3.4 ~/myvenv --without-pip.

If you do an ls you’ll notice that the python you used to create this virtualenv is copied into your virtualenv. Thus your virtualenv will continue to use its local copy. You now need to “activate” this virtualenv.

cg@codeghar [~] $ source ~/myvenv/bin/activate

Sidebar: At some point you’ll want to “deactivate” your virtualenv. To do this just run the deactivate command.

Next step is to install setuptools. At one point Distribute was set to replace/supersede setuptools but that’s not the case anymore. Don’t worry, we’ll still use pip but to first get pip we need setuptools.

cg@codeghar [~] $ cd ~/myvenv

cg@codeghar [~/myvenv] $ mkdir pypioffline

cg@codeghar [~/myvenv/pypioffline] $ cd pypioffline

The latest version of setup tools at the time of writing was 1.1.6 so we’ll download it to the temporary/optional directory pypioffline.

cg@codeghar [~/myvenv/pypioffline] $ curl -O https://pypi.python.org/packages/source/s/setuptools/setuptools-1.1.6.tar.gz

cg@codeghar [~/myvenv/pypioffline] $ tar xvzf setuptools-1.1.6.tar.gz

cg@codeghar [~/myvenv/pypioffline] $ cd setuptools-1.1.6

cg@codeghar [~/myvenv/pypioffline/setuptools-1.1.6] $ python ez_setup.py

cg@codeghar [~/myvenv/pypioffline/setuptools-1.1.6] $ easy_install pip

That’s pretty much it.

venv — Creation of virtual environments

Install Python 3 locally under /home directory in CentOS 6.4

First off, why would you want to install local Python 3? There could be many reasons, some of which may be:

  • You don’t want to touch the system-installed Python
  • You don’t have root privileges
  • You want to run your private/personal scripts without affecting other users on the system
  • You want to run multiple versions of Python not available on your system

For whatever the reasons you want to install Python locally in your home directory, it’s not as difficult as I had first thought it to be. This is a good alternative especially since Python3 is not officially available in CentOS 6.4.

There are four major steps:

  1. Install Development Tools
  2. Download Python Source Code
  3. Compile and Install Python
  4. Modify your $PATH

Install Development Tools

You will need some tools to compile Python. The easiest way to obtain them in CentOS is to install the ‘Development Tools’ group.

cg@codeghar [~] $ su -c 'yum groupinstall "Development Tools"'

You also need some libraries that Python uses to provide “batteries included” support.

cg@codeghar [~] $ su -c 'yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel'

Download Python Source Code

Head over to Python.org and download the version you want to install. For this post I used Python 3.3.2.

cg@codeghar [~] $ curl -O http://python.org/ftp/python/3.3.2/Python-3.3.2.tar.bz2

Now just un-tar the file so you can use its contents.

cg@codeghar [~] $ tar xvf Python-3.3.2.tar.bz2

You should see these two items in your home directory:

cg@codeghar [~] $ ls

Python-3.3.2  Python-3.3.2.tar.bz2

Compile and Install Python

You now have Python source and tools to compile it. Change directory to the un-tar’ed source code.

cg@codeghar [~] $ cd Python-3.3.2

Run configure.

cg@codeghar [~/Python-3.3.2] $ ./configure

Create a directory where you will install your local Python.

cg@codeghar [~/Python-3.3.2] $ mkdir -p ~/usr/local

Compile and install Python to the directory you just created.

cg@codeghar [~/Python-3.3.2] $ make altinstall prefix=$HOME/usr/local exec-prefix=$HOME/usr/local

Modify your $PATH

You now want to add ~/usr/local/bin to your $PATH so you don’t have to enter the full path to the Python binary every time you want to use it. Change directory to where local Python binary is located.

cg@codeghar [~/Python-3.3.2] $ cd ~/usr/local/bin

Create an alias so you can refer to it as python3. This is optional but I like to do it because I can then use python to refer to the Python that came with CentOS and python3 to refer to my locally installed Python3.

cg@codeghar [~/usr/local/bin] $ ln -s python3.3 python3

Now add this path to your $PATH environment variable. Notice that we add the new path before existing $PATH. This is so that our local Python is always used before any other.

cg@codeghar [~/usr/local/bin] $ echo "export PATH=\$HOME/usr/local/bin:\$PATH" >> ~/.bashrc

When you open a new terminal window, or log off and then log on, or (even better) run source ~/.bashrc, you can run the following commands to see that your local Python is now on your path.

cg@codeghar [~] $ which python3.3

~/usr/local/bin/python3.3

cg@codeghar [~] $ which python3

~/usr/local/bin/python3

cg@codeghar [~] $ which python

/usr/bin/python

You can even run your local Python.

cg@codeghar [~] $ python3

Python 3.3.2 (default, Sep 26 2013, 15:30:36) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print ("Hello World!")
Hello World!
>>> 

Conclusion

You can now run your local Python. There’s no need to keep the tar file and the source code around. You may want to delete them.

cg@codeghar [~] $ rm -rf ~/Python-3.3.2

cg@codeghar [~] $ rm ~/Python-3.3.2.tar.bz2

Another thing to consider is virtual environments, virtualenv or venv (in Python 3). Since Python3 comes with its built-in venv, just create an alias for its binary as well.

cg@codeghar [~] $ cd ~/usr/local/bin

cg@codeghar [~/usr/local/bin] $ ln -s pyvenv-3.3 pyvenv

There’s one more modification you need to make to get pyvenv to work. Open the file and change the path to your locally installed Python.

cg@codeghar [~/usr/local/bin] $ vim pyvenv-3.3

Original line is:

#!/usr/local/bin/python3.3

After changing it should look something like:

#!/home/cg/usr/local/bin/python3.3

You can now use this local pyvenv to create your virtualenvs.

Hat Tips

How to install locally python on linux home directory?; Installing Python 3 on CentOS/Redhat 5.x From Source; UNIX / Linux: Set your PATH Variable using set or export command; .bash_profile vs .bashrc; RHEL / CentOS Linux Install Core Development Tools Automake, Gcc (C/C++), Perl, Python & Debuggers

Beginning AES with Python3

Encryption is a vast field and one post can never do it justice. But I’ll try to provide code examples on how to use the PyCrypto library to work with AES.

Disclaimer: My programming skills might not be up to par when it comes to encryption. Try to learn from my mistakes (when I make them).

Install the library in Fedora:

yum install python3 python3-crypto

Let’s just dive into the code. I have tried to make it simple and clear.

#!/usr/bin/env python3
from Crypto.Cipher import AES
from Crypto import Random
from base64 import b64encode, b64decode
from Crypto.Util import Counter
from binascii import hexlify

print('```GENERAL```')
print('AES block size: {0}'.format(AES.block_size))
original_key = 'This is my k\u00eay!! The extra stuff will be truncated before using it.'
key = original_key.encode('utf-8')[0:32]
print('Original Key: {0}'.format(original_key))
print('Usable Key: {0}'.format(key))
print('Base64 Encoded key: {0}'.format(b64encode(key).decode('utf-8')))
message = '0123456789'.encode('utf-8')
print('Original Message: {0}'.format(message))

#````````````````````````````````

# MODE CFB
print('```MODE CFB```')
cfb_iv = Random.new().read(AES.block_size)
print('Base64 Encoded IV: {0}'.format(b64encode(cfb_iv).decode('utf-8')))



cfb_cipher_encrypt = AES.new(key, AES.MODE_CFB, cfb_iv)
cfb_msg_encrypt = b64encode(cfb_cipher_encrypt.encrypt(message))
print ('Mode CFB, Base64 Encoded, Encrypted message: {0}'.format( cfb_msg_encrypt.decode('utf-8')))



cfb_cipher_decrypt = AES.new(key, AES.MODE_CFB, cfb_iv)
cfb_msg_decrypt = cfb_cipher_decrypt.decrypt(b64decode(cfb_msg_encrypt)).decode('utf-8')
print('Mode CFB, Decrypted message: {0}'.format(cfb_msg_decrypt))



#````````````````````````````````

# MODE CTR
print('```MODE CTR```')
def ctr_pad_message(in_message):
    # http://stackoverflow.com/questions/14179784/python-encrypting-with-pycrypto-aes
    # We use PKCS7 padding
    length = 16 - (len(in_message) % 16)
    return (in_message + bytes([length])*length)
def ctr_unpad_message(in_message):
    return in_message[:-in_message[-1]]


ctr_iv = int(hexlify(Random.new().read(AES.block_size)), 16)
print('CTR IV (int): {0}'.format(ctr_iv))
ctr_encrypt_counter = Counter.new(128, initial_value=ctr_iv)
ctr_decrypt_counter = Counter.new(128, initial_value=ctr_iv)



ctr_padded_message = ctr_pad_message(message)
print('Mode CTR, Padded message: {0}'.format(ctr_padded_message))
ctr_cipher_encrypt = AES.new(key, AES.MODE_CTR, counter=ctr_encrypt_counter)
ctr_msg_encrypt = b64encode(ctr_cipher_encrypt.encrypt(ctr_padded_message))
print('Mode CTR, Base64 Encoded, Encrypted message: {0}'.format( ctr_msg_encrypt.decode('utf-8')))



ctr_cipher_decrypt = AES.new(key, AES.MODE_CTR, counter=ctr_decrypt_counter)
ctr_msg_decrypt = ctr_cipher_decrypt.decrypt(b64decode(ctr_msg_encrypt))
ctr_unpadded_message = ctr_unpad_message(ctr_msg_decrypt)
print('Mode CTR, Decrypted message: {0}'.format(ctr_msg_decrypt))
print('Mode CTR, Unpadded, Decrypted message: {0}'.format(ctr_unpadded_message))

Here I have provided examples for two modes: CFB and CTR. Although both of them should not use fixed blocks for some reason CTR expects you to use fixed blocks in this library.

Working with Third Party Repositories on CentOS 6.4

I have been playing around with CentOS a bit. It has older versions of all software I use or is missing some other software I need. The first problem (older version of software) is remedied by using additional repositories: Software Collections, IUS. The second problem, missing software, is also remedied by additional repositories: EPEL, RepoForge (formerly RPMForge).

You may want to list your current repositories:

yum repolist

When adding a repository, find the rpm that’ll add/enable the repository. You’ll usually find these on the project’s website. For example, RepoForge, IUS, EPEL have instructions and links on where to find the rpm.

As an example, we’ll add the RepoForge repository.

rpm -ivh 'http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm'

You could also use yum to install the rpm:

yum localinstall http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm

Now when you list the repos on your machine, you’ll see something like:

yum repolist

Loaded plugins: fastestmirror, presto, ps
Loading mirror speeds from cached hostfile
 * base: centos-mirror.jchost.net
 * epel: mirror.pnl.gov
 * extras: mirror.ancl.hawaii.edu
 * rpmforge: apt.sw.be
 * updates: ftp.usf.edu
repo id        repo name                                            status
base           CentOS-6 - Base                                      6,381
extras         CentOS-6 - Extras                                       13
rpmforge       RHEL 6 - RPMforge.net - dag                          4,597
updates        CentOS-6 - Updates                                   1,123
repolist: 21,606

To view the packages available from a repository, disable (temporarily) all repos except the one you’re interested in.

yum --disablerepo='*' --enablerepo='rpmforge' list available

To remove a third party repository, first find the rpm and then remove it.

rpm -qa rpmforge*

rpmforge-release-0.5.3-1.el6.rf.x86_64

Or you can use yum:

yum list rpmforge*

If you’re curious to know what the removal will look like, you can test it first.

rpm -e --test -vv rpmforge-release-0.5.3-1.el6.rf.x86_64

D: loading keyring from pubkeys in /var/lib/rpm/pubkeys/*.key
D: couldn't find any keys in /var/lib/rpm/pubkeys/*.key
D: loading keyring from rpmdb
D: opening  db environment /var/lib/rpm cdb:mpool:joinenv
D: opening  db index       /var/lib/rpm/Packages rdonly mode=0x0
D: locked   db index       /var/lib/rpm/Packages
D: opening  db index       /var/lib/rpm/Name rdonly mode=0x0
D:  read h#     200 Header sanity check: OK
D: added key gpg-pubkey-c105b9de-4e0fd3a3 to keyring
D:  read h#     261 Header sanity check: OK
D: added key gpg-pubkey-6b8d79e6-3f49313d to keyring
D: Using legacy gpg-pubkey(s) from rpmdb
D:  read h#     265 Header V3 DSA/SHA1 Signature, key ID 6b8d79e6: OK
D: ========== --- rpmforge-release-0.5.3-1.el6.rf x86_64/linux 0x0
D: opening  db index       /var/lib/rpm/Requirename rdonly mode=0x0
D: ========== recording tsort relations
D: ========== tsorting packages (order, #predecessors, #succesors, tree, depth)
D:     0    0    0    0    1   -rpmforge-release-0.5.3-1.el6.rf.x86_64
D: erasing packages
D: sanity checking 1 elements
D: computing 26 file fingerprints
D: computing file dispositions
D: opening  db index       /var/lib/rpm/Basenames rdonly mode=0x0
D: 0x0000fd00     4096    121121780     32464498 /
D: ========== +++ rpmforge-release-0.5.3-1.el6.rf x86_64-linux 0x0
D:     erase: rpmforge-release-0.5.3-1.el6.rf has 26 files, test = 1
D: closed   db index       /var/lib/rpm/Requirename
D: closed   db index       /var/lib/rpm/Basenames
D: closed   db index       /var/lib/rpm/Name
D: closed   db index       /var/lib/rpm/Packages
D: closed   db environment /var/lib/rpm

Now you can remove the repo:

rpm -e rpmforge-release-0.5.3-1.el6.rf.x86_64

Or you can use yum:

yum erase rpmforge-release

Additional Resources:
RedHat software collections and CentOS

The sorry state of services in Ubuntu

Read the post How do I choose which way to enable/disable, start/stop, or check the status of a service?. Compare that with systemctl enable/disable/start/stop/status service and tell me, for a user, which is easier?

Yes, with juju charms individual services don’t matter as much. But some of us are not running clouds. We still use a handful of computers, physical and virtual. I would rather let my computer handle services for me. I’d rather not sit there trying to determine which command to use to perform a simple function.

Ubuntu has invested a lot in Upstart and has every right to stick with it. But is it too much to ask for Canonical/Ubuntu to move all services to Upstart? That way at least we don’t have SysV and Upstart running alongside each other and causing this mess. Even Fedora hasn’t moved a lot of services, especially xinetd-based, to systemd but they are still much farther along in a couple years than Ubuntu has been so far. Where’s the inclination of the Ubuntu community and Canonical to not leave things half done?

If Upstart is the future then be done with the migration so you can move on to some other aspect of the system. Add the simple features we all need. So far it appears Ubuntu and Canonical start something innovative and then leave it unfinished to chase something else. They need to fix this culture so that technical users can use a great distribution with fewer headaches.

Follow

Get every new post delivered to your Inbox.

Join 31 other followers