Friday, January 9, 2015

Towards a More Ergonomic Development Setup

I just turned 45. Forty. Frickin'. Five. For the past six months or so (probably right on schedule) I've been experiencing neck, shoulder, wrist, forearm, and elbow pain. It comes and goes but on the bad days it's bad enough to keep me awake at night, so I decided rather than continue to ignore it and keep working directly on a laptop as I have for years now, I better heed my body's warnings (as well as my girlfriend's prompting) so I can keep programming for another 45 years. (Joking. If I'm still blogging about nerd stuff when I'm 90 please put me out of my and everyone else's misery.)

I already made the move to a standing desk, specifically a GeekDesk, a few years ago. At the same time I bought a Herman Miller Embody chair, which I subsequently never used, because standing desk. (I'm reeeeal smart sometimes.) Seriously though both these changes made a huge, huge difference. I no longer have back issues, I have much more energy, and I feel much more alert and engaged when I work while standing. And that Herman Miller chair is absolutely the best chair I've ever owned. It's fantastic on the rare occasion I actually sit in it.

The desk and chair are only one piece of the ergonomic puzzle, however, and the years of twisted wrists on a laptop for way too many hours a day finally started to catch up with me, so this is day one of putting the laptop in a docking station, using an external 24" monitor on a monitor stand, and using an ergonomic keyboard and mouse.

So far, so good! My wrists and arms felt better nearly immediately, and with the monitor much higher my head and neck are now looking straight out instead of me being hunched over and leaning in to see my laptop screen. It feels weird, but it's good weird and I have a feeling after a week or so when I'm totally used to it, and my aches and pains have subsided, I'll feel much better than I have in a long time.

I have two new monitors on the way and a dual-monitor stand, but for now I'm using a Lenovo Easy Reach monitor stand with a ThinkPad Ultra Dock for my ThinkPad T540p. With my GeekDesk down to a height of 40" everything is looking and feeling great.

The biggest change in the setup for me is the new keyboard and mouse, and for that I went with the Microsoft Sculpt Ergonomic Desktop. Yes, the keyboard is a little weird and I think it'll take a few days for me to get back up to my full typing speed, partially because the keyboard is a lot different than what I'm used to, and partially because I (like most people, I assume) don't type 100% correctly. Who knew getting used to doing Bs with my left hand instead of my right would be such a challenge?

I've tried a lot of ergonomic keyboards over the years. I almost went with one I had and tolerated (I'll stop short of saying I liked it) a few years ago, namely the Logitech Wave Mk550, but then I remembered my two major annoyances about that setup. First, when you're used to a laptop keyboard moving to full-stroke keys feels like a TON more work, and my hands felt it. Second is the numeric keypad on the right-hand side of the keyboard. (Seriously, does anyone use those things?) Not only does that make the keyboard feel off-center to me, but it means you're reaching pretty far to get to the mouse (one of the things I LOVE about using a laptop, particularly a ThinkPad, is I don't have to move my hands to move the pointer around), and that gets annoying and hard on the elbow after a while.

The Microsoft Sculpt keyboard addresses both of these annoyances. It has very, very nice laptop-style keys that feel great under my fingers, and the numeric keypad is a completely separate piece of hardware that is currently residing in my closet where it will likely stay for eternity. This makes the mouse much closer so it's less annoying and hard on the forearm and elbow to grab the mouse. I'm still getting used to the keyboard layout but thus far I really like the feel of this keyboard.

The mouse itself is also designed to be ergonomic so it's a little bit funky; it's more of a tall ball than the flat oval-shaped mouse you may be used to. Combined with a mouse pad with a gel wrist pad it puts the hand and wrist in a much more natural, comfortable position, and there's even a nice notch for the thumb. Lefties beware, however: I don't see how you could use this mouse if you're not right-handed since the thumb notch would be on the wrong side.

Changing up all my equipment is a bit jarring but I'll get used to it quickly enough and my body will thank me for it. I'll be curious to see how I'm typing and feeling at the end of the first week with all this, and how things will change again when I get the dual monitor setup going. I'm also debating whether or not I'll need a keyboard tray mounted under the desk since I can adjust the height of the desk itself. Time will tell on that.

If anyone has any ergonomic tips as I move into my new setup I'd love to hear them!

Friday, October 10, 2014

Nginx and Extended Validation SSL Certificates

Quick tip on setting up Nginx with Extended Validation (EV) SSL certificates since this took a bit of trial and error for me this morning and I found a lot of conflicting and in some cases incorrect information while searching around.

If after configuring Nginx with your SSL certificate you're getting an untrusted certificate error, or a 400 error saying the certificate wasn't sent, you're likely missing the intermediate certificate bundle that's required on EV certificates, which if you use Verisign certs is located here:
https://knowledge.verisign.com/support/ssl-certificates-support/index?page=content&actp=CROSSLINK&id=AR2128

According to the Nginx documentation (pro tip: start with the docs, not with what you pull up on StackOverflow), you need to concatenate your host-specific SSL certificate and the intermediate certificate bundle into a single file, with the host-specific SSL certificate first in the file. So you'll end up with a single file (foo.crt) that contains three certificate blocks, and just make sure the one for your host (i.e. the one that goes with your key) comes first.

Once I had all that in place the browser was happy with what Nginx was giving it as far as SSL is concerned.

Friday, May 2, 2014

Ubuntu on Dell XPS 15 (8947-sLV)

The beta version of my excellent Dell Sputnik (XPS 13) wasn't quite cutting the mustard for some side freelance work I'm doing since it only has 4GB of RAM, but I loved the machine so much I opted to get its big brother, the XPS 15. Specifically I got this model, and yes since I needed it pronto I actually bought it in person at the Microsoft Store in Bellevue, WA. I'll always hate myself a little for going to a Microsoft Store but it was darn handy to have one nearby and just go get the new machine as opposed to waiting to have one shipped.

When I got it home I didn't even boot into Windows 8.1, I just stuck an Ubuntu 14.04 USB stick in the machine and installed that. The only trick to installing Ubuntu is you have to go into the BIOS, turn off Secure Boot, and turn on Legacy Boot Mode.

Once Ubuntu is installed everything works out of the box. The screen runs at the full, mind-blowing 3200x1800 resolution, and even the touch screen works. No issues with sound card, WiFi, or anything else. Awesome.

The only annoyance is the default settings for the Synaptics trackpad are a little jumpy. OK, more than a little jumpy. Luckily with a bit of research I found an easy fix that definitely did the trick for me. Basically you just need to change the FingerLow and FingerHigh settings to reduce the sensitivity and the cursor jumps around no more. I used the settings in the link but you can adjust as needed if those specific settings don't work for you.

Only remaining thing to figure out is what to do with this ridiculous amount of screen real estate. Couldn't be more pleased with this laptop!

Tuesday, January 21, 2014

Python + Oracle on Ubuntu Server 12.04

Affectionately known among all non-masochists in the world of IT as The Seventh Circle of Hell (with real hell being preferable), working with Oracle is always a hair-tearing nightmarish fork-in-the-eye please-for-the-love-of-god-kill-me-now experience that none but those who look to Ted Bundy, Jeffrey Dahmer, and John Wayne Gacy for moral and spiritual guidance would wish upon even their most reviled enemies.

Yes, it's that bad. And apparently nowhere is it worse than when one attempts to get Oracle working with Python on Ubuntu.

I'm not even talking about installing the Oracle database server itself here people, I'm just needing a Python application to talk to an existing Oracle database. One would think, as with every other database server on the planet (and yes, I'm including that other slice of hell SQL Server in that statement since it's a damn sight simpler to get working -- even on Linux -- than Oracle), you'd simply apt-get and/or pip install a library or two and be done with it.

If you actually do think that, you've already forgotten that this is Oracle we're talking about.

That said, one does what one has to do to keep the paychecks coming, so if you need to do this here's the steps to make it all happen. (Note that on Step 1 I'm assuming you have already installed all the other Python packages you may need. I'm focusing on the stuff you may not have that you definitely need.)
  1. sudo apt-get install libaio1 alien
  2. Download the RPM of version 11.2.0.4.0 of the Oracle client from http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html (note that as of the date of this writing the 12.x version doesn't work, or at least didn't for me)
    1. You have to have an Oracle Web Account and use that to log in and download this, which makes using wget on the target server itself or automating the process for use with something like a Vagrant provisioning script rather problematic. Short version, you'll have to download this locally and then scp it up to the target server. What I did is downloaded and converted this RPM as well as the other necessary RPM, converted them once, and put them in a git repo from which I can clone in my Vagrant provisioning script. Whether or not that adheres to the licensing agreement, I don't know and I don't care. If you're paranoid, check with a lawyer before repeating my solution on this.
    2. If the version number differs slightly from what I have here, adjust later steps accordingly.
  3. Download the RPM of the Python 2.7/Oracle 11g version of the cx_Oracle Python libraries from http://cx-oracle.sourceforge.net/
  4. scp the RPMs up to the target server as needed.
  5. Convert the RPMs to Debian packages using alien:
    sudo alien -d FILENAME.rpm (where FILENAME is of course the name of each of the two RPM files)
  6. sudo dpkg -i oracle-installclient11.2-basic_11.2.0.4.0-2_amd64.deb
  7. sudo vim /etc/ld.so.conf.d/oracle.conf
    1. Note: this file won't already exist, so you'll be creating this as a new file in this step
  8. Enter the following in the newly created oracle.conf file and save it:
    /usr/lib/oracle/11.2/client64/lib
  9. export ORACLE_HOME=/usr/lib/oracle/11.2/client64
  10. export LD_LIBRARY_PATH=$ORACLE_HOME/lib
  11. sudo ldconfig
  12. sudo dpkg -i cx-oracle_5.1.2-2_amd64.deb
  13. cd /usr/lib/python2.7
  14. sudo mv site-packages/cx_Oracle* dist-packages
  15. sudo rmdir site-packages
  16. sudo ln -s dist-packages site-packages
  17. Verify installation by opening a Python interpreter and run the following:
    import cx_Oracle
    1. If you don't get an import error, everything is working properly
As far as automating this for use with Vagrant,  in my provisioning script I simply echoed the export statements in the steps above into /etc/environment, did source /etc/environment and followed that with ldconfig. Other than that the steps in the bash script are pretty much what's above, but if people are interested in seeing the script let me know and I can post it.

And there you have it. A lot of trial and error and head bashing went into that final solution, and since I kind of cobbled together the steps from various resources I'll post those below in case you want to see some of the other solutions and source material.

Happy Oracleing. Or not.

References

  1. http://iambusychangingtheworld.blogspot.com/2013/06/python-oracle-sqlalchemy-on-ubuntu-1304.html 
  2. http://maxolasersquad.blogspot.com/2011/04/cxoracle-on-ubuntu-1104-natty.html 
  3. https://linuxindetails.wordpress.com/2009/12/26/installation-of-python-cx_oracle-module-for-debian-squeeze/
  4. http://stackoverflow.com/questions/12538238/python-module-cx-oracle-module-could-not-be-found

Wednesday, October 2, 2013

Dropbox on Linux Mint 15

I noticed on Linux Mint that the Dropbox icons and menu options don't appear in my Dropbox directory. I did a little research and this is because by default when you install Dropbox it'll assume you're using Nautilus as your file browser, but by default Linux Mint uses Nemo (which is a fork of Nautilus).

Luckily it's an easy fix:
sudo apt-get install nemo-dropbox

Then quit all running instances of Nemo:
nemo --quit

When you open up your Dropbox directory again you'll see the familiar Dropbox icons.

FreeTDS on Linux Mint 15

If you're trying out or moving to Linux Mint and you're used to setting up FreeTDS on Ubuntu, you'll find that things are just slightly different on Mint.

Quick and easy fix:
sudo apt-get install freetds-bin tdsodbc

Also note that libtdsodbc.so in a different place on Mint than on Ubuntu, so instead of it being located at /usr/local/lib/libtdsodbc.so it'll be here:
/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so

Saturday, July 13, 2013

Generating CSV Files in Django

This is a very quick tip since it's so simple but I did run into one little wrinkle with string encoding while doing this so I thought I'd share.

I had a request to generate a CSV of all the Old Dog Haven "Walk for Old Dogs" registrants so the fine folks managing the event can do email blasts, print registration sheets, and the like.

Since Python has CSV functionality as part of the standard library the generation of the CSV data was very easy, and since the Django HTTP Response object was quite wisely designed to behave as a file-like object, writing the CSV data to the HTTP response was dead simple as well.

The only thing I ran into while writing the data to the response object was there were some non-ASCII characters in the database which threw this error:
'ascii' codec can't encode character u'\xe9' in position 4: ordinal not in range(128)
 
To get around this it was just a matter of tacking .encode('utf-8') to the end of the string objects when writing out the CSV data.

Here's the final result.