Archive

Archive for the ‘Ubuntu’ Category

Blast from the Past: Create a GTK+ application on Linux with Objective-C

March 15th, 2017 No comments

This post was originally published on December 8, 2010. The original can be found here.

Note that while you can still write GTK+ applications on Linux using Objective-C as outlined in this post you may want to check out my little project CoreGTK which makes the whole experience a lot nicer 🙂


As sort of follow-up-in-spirit to my older post I decided to share a really straight forward way to use Objective-C to build GTK+ applications.

Objective-what?

Objective-C is an improvement to the iconic C programming language that remains backwards compatible while adding many new and interesting features. Chief among these additions is syntax for real objects (and thus object-oriented programming). Popularized by NeXT and eventually Apple, Objective-C is most commonly seen in development for Apple OSX and iOS based platforms. It ships with or without a large standard library (sometimes referred to as the Foundation Kit library) that makes it very easy for developers to quickly create fast and efficient programs. The result is a language that compiles down to binary, requires no virtual machines (just a runtime library), and achieves performance comparable to C and C++.

Marrying Objective-C with GTK+

Normally when writing a GTK+ application the language (or a library) will supply you with bindings that let you create GUIs in a way native to that language. So for instance in C++ you would create GTK+ objects, whereas in C you would create structures or ask functions for pointers back to the objects. Unfortunately while there used to exist a couple of different Objective-C bindings for GTK+, all of them are quite out of date. So instead we are going to rely on the fact that Objective-C is backwards compatible with C to get our program to work.

What you need to start

I’m going to assume that Ubuntu will be our operating system for development. To ensure that we have what we need to compile the programs, just install the following packages:

  1. gnustep-core-devel
  2. libgtk2.0-dev

As you can see from the list above we will be using GNUstep as our Objective-C library of choice.

Setting it all up

In order to make this work we will be creating two Objective-C classes, one that will house our GTK+ window and another that will actually start our program. I’m going to call my GTK+ object MainWindow and create the two necessary files: MainWindow.h and MainWindow.m. Finally I will create a main.m that will start the program and clean it up after it is done.

Let me apologize here for the poor code formatting; apparently WordPress likes to destroy whatever I try and do to make it better. If you want properly indented code please see the download link below.

MainWindow.h

In the MainWindow.h file put the following code:

#import <gtk/gtk.h>
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>

//A pointer to this object (set on init) so C functions can call
//Objective-C functions
id myMainWindow;

/*
* This class is responsible for initializing the GTK render loop
* as well as setting up the GUI for the user. It also handles all GTK
* callbacks for the winMain GtkWindow.
*/
@interface MainWindow : NSObject
{
//The main GtkWindow
GtkWidget *winMain;
GtkWidget *button;
}

/*
* Constructs the object and initializes GTK and the GUI for the
* application.
*
* *********************************************************************
* Input
* *********************************************************************
* argc (int *): A pointer to the arg count variable that was passed
* in at the application start. It will be returned
* with the count of the modified argv array.
* argv (char *[]): A pointer to the argument array that was passed in
* at the application start. It will be returned with
* the GTK arguments removed.
*
* *********************************************************************
* Returns
* *********************************************************************
* MainWindow (id): The constructed object or nil
* arc (int *): The modified input int as described above
* argv (char *[]): The modified input array modified as described above
*/
-(id)initWithArgCount:(int *)argc andArgVals:(char *[])argv;

/*
* Frees the Gtk widgets that we have control over
*/
-(void)destroyWidget;

/*
* Starts and hands off execution to the GTK main loop
*/
-(void)startGtkMainLoop;

/*
* Example Objective-C function that prints some output
*/
-(void)printSomething;

/*
********************************************************
* C callback functions
********************************************************
*/

/*
* Called when the user closes the window
*/
void on_MainWindow_destroy(GtkObject *object, gpointer user_data);

/*
* Called when the user presses the button
*/
void on_btnPushMe_clicked(GtkObject *object, gpointer user_data);

@end

MainWindow.m

For the class’ actual code file fill it in as show below. This class will create a GTK+ window with a single button and will react to both the user pressing the button, and closing the window.

#import “MainWindow.h”

/*
* For documentation see MainWindow.h
*/

@implementation MainWindow

-(id)initWithArgCount:(int *)argc andArgVals:(char *[])argv
{
//call parent class’ init
if (self = [super init]) {

//setup the window
winMain = gtk_window_new (GTK_WINDOW_TOPLEVEL);

gtk_window_set_title (GTK_WINDOW (winMain), “Hello World”);
gtk_window_set_default_size(GTK_WINDOW(winMain), 230, 150);

//setup the button
button = gtk_button_new_with_label (“Push me!”);

gtk_container_add (GTK_CONTAINER (winMain), button);

//connect the signals
g_signal_connect (winMain, “destroy”, G_CALLBACK (on_MainWindow_destroy), NULL);
g_signal_connect (button, “clicked”, G_CALLBACK (on_btnPushMe_clicked), NULL);

//force show all
gtk_widget_show_all(winMain);
}

//assign C-compatible pointer
myMainWindow = self;

//return pointer to this object
return self;
}

-(void)startGtkMainLoop
{
//start gtk loop
gtk_main();
}

-(void)printSomething{
NSLog(@”Printed from Objective-C’s NSLog function.”);
printf(“Also printed from standard printf function.\n”);
}

-(void)destroyWidget{

myMainWindow = NULL;

if(GTK_IS_WIDGET (button))
{
//clean up the button
gtk_widget_destroy(button);
}

if(GTK_IS_WIDGET (winMain))
{
//clean up the main window
gtk_widget_destroy(winMain);
}
}

-(void)dealloc{
[self destroyWidget];

[super dealloc];
}

void on_MainWindow_destroy(GtkObject *object, gpointer user_data)
{
//exit the main loop
gtk_main_quit();
}

void on_btnPushMe_clicked(GtkObject *object, gpointer user_data)
{
printf(“Button was clicked\n”);

//call Objective-C function from C function using global object pointer
[myMainWindow printSomething];
}

@end

main.m

To finish I will write a main file and function that creates the MainWindow object and eventually cleans it up. Objective-C (1.0) does not support automatic garbage collection so it is important that we don’t forget to clean up after ourselves.

#import “MainWindow.h”
#import <Foundation/NSAutoreleasePool.h>

int main(int argc, char *argv[]) {

//create an AutoreleasePool
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

//init gtk engine
gtk_init(&argc, &argv);

//set up GUI
MainWindow *mainWindow = [[MainWindow alloc] initWithArgCount:&argc andArgVals:argv];

//begin the GTK loop
[mainWindow startGtkMainLoop];

//free the GUI
[mainWindow release];

//drain the pool
[pool release];

//exit application
return 0;
}

Compiling it all together

Use the following command to compile the program. This will automatically include all .m files in the current directory so be careful when and where you run this.

gcc `pkg-config –cflags –libs gtk+-2.0` -lgnustep-base -fconstant-string-class=NSConstantString -o “./myprogram” $(find . -name ‘*.m’) -I /usr/include/GNUstep/ -L /usr/lib/GNUstep/ -std=c99 -O3

Once complete you will notice a new executable in the directory called myprogram. Start this program and you will see our GTK+ window in action.

If you run it from the command line you can see the output that we coded when the button is pushed.

Wrapping it up

There you have it. We now have a program that is written in Objective-C, using C’s native GTK+ ‘bindings’ for the GUI, that can call both regular C and Objective-C functions and code. In addition, thanks to the porting of both GTK+ and GNUstep to Windows, this same code will also produce a cross-platform application that works on both Mac OSX and Windows.

Source Code Downloads

Source Only Package
File name: objective_c_gtk_source.zip
File hashes: Download Here
File size: 2.4KB
File download: Download Here

Originally posted on my personal website here.

Blast from the Past: VOIP with Linode, Ubuntu, Asterisk and FreePBX

March 1st, 2017 No comments

This post was originally published on October 29, 2010. The original can be found here.


Overview and Introduction

I’ve been dabbling with managing a VOIP server for the past year or so, using CentOS, Asterisk and FreePBX on a co-located server. Recently Dave and I needed to move to our own machine, and decided to use TEH CLOUD to reduce management and get a fresh start. There are hundreds of hosts out there offering virtual private servers (VPS’s). We’ve standardized on Linode for our small business for a few reasons. While I don’t want to sound like a complete advertisement, I’ve been incredibly impressed with them:

  • Performance. The host systems at Linode run at least 4-way 2GHz Xeon dual-core CPUs (I’ve seen higher as well) and you’re guaranteed the RAM you pay for. Pricing is generally based on how much memory you need.
  • Pricing. For a 512MB Linode, you pay $19.95 US per month. Slicehost (a part of Rackspace, and a Linode competitor) charges the same amount for a 256MB slice. Generally you want at least 512MB RAM for a Linux machine that’s not a test/development box.
  • Features. If you have multiple VMs in the same datacenter, you can assign them private IPs and internal traffic doesn’t count toward your bandwidth allowance. Likewise, bandwidth is pooled among all your VMs; so buying two VMs with 200GB bandwidth each gives 400GB for all your systems.

With full root access and the Linux distribution of your choice, it’s very easy to set up and tear down VMs.

Why VOIP?
When people hear VOIP, they generally assume either a flaky enterprise system with echoing calls or something like Skype. Properly configured, a VOIP system offers a number of really interesting features:

  • Low-cost long distance and international calling. The provider we use, voip.ms, offers outgoing calls for $0.0052 per minute to Canada and $0.0105/minute to the US on their value route.
  • Cheap phone numbers – direct inward dialing – are available for $0.99 per month in your region. These phone numbers are virtual and can be configured to do nearly anything you want. Incoming calls are $0.01/minute, and calls between voip.ms numbers are free.
  • Want to take advantage of cheap long distance from your cell phone? Set up a Direct Inward System Access path, which gives you a dial tone for making outgoing calls when you call a local number. Put your DID number on your My5 list, and you’re set to reduce bill overages.
  • Voicemail becomes much more useful when the VOIP server sends you an email with a WAV attachment and caller ID information.
  • Want to set up an interactive voice response menu, time conditions, blacklist telemarketers, manage group conferences or have witty hold music? All available with FreePBX and Asterisk.

Continue reading for server setup details and security best practices…

Configuration
I opted to use Ubuntu 10.04 LTS on the server, since there are handy directions for configuring Asterisk and FreePBX. The guide is pretty handy, but some adjustments had to be made to the article for the latest versions of Ubuntu and Asterisk:

  • When installing Asterisk, make sure to install the sox package for additional sound and recording support.
  • Back up your /etc/asterisk/modules.conf file before installing FreePBX, and then restore it after the installation is complete. The FreePBX installation seems to clobber this file.
  • Replace all instances of the asteriskcdr database with asteriskcdrdb for proper call reporting functionality. Likewise, you’ll have to recompile and install the asterisk-addons package as per Launchpad bug 560656:
    cd /usr/src
    apt-get build-dep asterisk-mysql
    apt-get -b source asterisk-mysql
    dpkg -i asterisk-mysql*.deb
  • Don’t use the amportal script for managing Asterisk/FreePBX; use
    /etc/init.d/asterisk [start|stop|restart]

    instead.

Let It Ring
There’s plenty of great FreePBX documentation available online – you shouldn’t have a problem getting up and running once the installation is finished. As always, you should follow best server security practices:

  • Enforce username/password authentication with .htaccess and htpasswd and HTTPS for your management console, or only expose FreePBX administration over localhost/127.0.0.1 and tunnel in. There are plenty of articles on configuring OpenSSL and Apache2.
  • Consider running SSH on an alternate port (not 22), and denying direct logins from the root user account. Enforce strong passwords and use tools such as fail2ban and DenyHosts to limit SSH attacks.
  • Use a firewall. Ubuntu’s ufw is very simple to manage. For an Asterisk server, you’ll want to allow UDP ports 5060 and 10000-20000 (for voice traffic), or a range defined in
    /etc/asterisk/rtp.conf

Feel free to post comments here on server setup or general VOIP questions, and I’ll do my best to help out!

Blast from the Past: Compile Windows programs on Linux

February 26th, 2017 No comments

This post was originally published on September 26, 2010. The original can be found here.


Windows?? *GASP!*

Sometimes you just have to compile Windows programs from the comfort of your Linux install. This is a relatively simple process that basically requires you to only install the following (Ubuntu) packages:

To compile 32-bit programs

  • mingw32 (swap out for gcc-mingw32 if you need 64-bit support)
  • mingw32-binutils
  • mingw32-runtime

Additionally for 64-bit programs (*PLEASE SEE NOTE)

  • mingw-w64
  • gcc-mingw32

Once you have those packages you just need to swap out “gcc” in your normal compile commands with either “i586-mingw32msvc-gcc” (for 32-bit) or “amd64-mingw32msvc-gcc” (for 64-bit). So for example if we take the following hello world program in C

#include <stdio.h>
int main(int argc, char** argv)
{
printf(“Hello world!\n”);
return 0;
}

we can compile it to a 32-bit Windows program by using something similar to the following command (assuming the code is contained within a file called main.c)

i586-mingw32msvc-gcc -Wall “main.c” -o “Program.exe”

You can even compile Win32 GUI programs as well. Take the following code as an example

#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
char *msg = “The message box’s message!”;
MessageBox(NULL, msg, “MsgBox Title”, MB_OK | MB_ICONINFORMATION);

return 0;
}

this time I’ll compile it into a 64-bit Windows application using

amd64-mingw32msvc-gcc -Wall -mwindows “main.c” -o “Program.exe”

You can even test to make sure it worked properly by running the program through wine like

wine Program.exe

You might need to install some extra packages to get Wine to run 64-bit applications but in general this will work.

That’s pretty much it. You might have a couple of other issues (like linking against Windows libraries instead of the Linux ones) but overall this is a very simple drop-in replacement for your regular gcc command.

*NOTE: There is currently a problem with the Lucid packages for the 64-bit compilers. As a work around you can get the packages from this PPA instead.

Originally posted on my personal website here.

Sudo apt-get install basic-linux-pt3 –Install & Setup

February 18th, 2017 No comments

It’s been a busy little while, so I haven’t had time to get this written up. So lets see what I can still remember.

Installing Ubuntu Server was as easy as you’d expect. Booting into it wasn’t. Turns out that the BIOS on this box is setup not to boot from the ODD SATA port. It’ll boot from any of the four drives, or from USB; but not from that extra SATA port. My friend’s, who already has the box running, solution was to setup a RAID, where the ODD SATA is RAID number 0, which then allows it to be booted from. I went for a much simpler solution, after noticing that the install process lets you select the location of the GRUB loader. This server has a USB port and a MicroSD card reader inside the case, both bootable. I have plenty of spare MicroSD cards lying around (seriously, since when is 1GB or 2GB big enough for anybody?), so I just inserted one, and reinstalled specifying the MicroSD card as the location for the GRUB.

It felt good to have my new box booting up and actually running. I got its static IP and OpenSSH setup, checked I could access it through Putty, and finally got it up on the shelf and off my desk. Everything from this point on I’ve done in Putty, with no monitor attached to the server. Lets face it, its not like there’s any difference between one white-on-black text interface and another.

Next, I turned my attention to mounting my drives. The mount command is simple enough, but obviously I want my drives to be available right away after boot; so it was time to learn about ‘fstab’ and ‘UUID’s. Luckily this is a fairly straightforward process, especially since my drives only have a single partition on each, other than having to write down the long UUID to copy from the terminal output to the fstab file. I haven’t been able to work with copy & paste in PuTTY. One thing I started to realise at this point is that while Ubuntu boots nice and quickly, the server itself doesn’t.  So each time I want to see if my fiddling has worked, I pretty much have time to make a cup of tea. From looking through various guides etc. I simply used:

UUID=<UUID> /mnt/<mountpoint> ext4 defaults 0 2

for each of my additional drives. After a reboot, I had access to all of my files and media as it was on my old NAS. I spent a little time clearing out the directory structures it had left behind, program files etc. to leave a nice, clean access to all of my files.

NFS and Samba were just as easy to get set up as they had been on the virtual machines. Although with so many different things I wanted to share, I had to add a lot of different entries into each file.  Thankfully there’s no need to reboot after each edit, the services can simply be restarted to pick up the new settings. Samba is simple enough to test, since I’m managing the server over SSH on PuTTY in Windows. NFS required me to test in one of the VMs 0nce again; but after some work, both seemed to be working. I’m not 100% happy with some of my setup, since I’m just allowing open access to anyone on some of these shares. Chances are I’ll be fine, but I’ll want to come back at some point to try and tighten up my user management.

Emby server has a very good set of installation instructions. The main new part for me was adding the new repository, but this means it’ll be kept up to date when I perform other apt-get upgrades. Everything else related to Emby is managed through its web GUI, so straight forward stuff.

In fact, I was surprised at how simple it was to get the majority of things working. FTP just kinda worked, I just needed to make symlinks from my home directory to the other places I need to access. Even Transmission wasn’t too bad to get going and allow my remote GUI to connect. Ont thing that started to get harder from this point was keeping track of the different ports and services I was using. I took some time to make a list of computers and services to plan my external port mapping, and got things like FTP, SSH and Transmission forwarded. Internally I’ve just used the defaults for simplicity; externally I’ve made sure they’re set to something completely different.

Next Up:

Bash-ing things around

This post was originally published on Nathanael’s site here.

Categories: Nathanael Y, Ubuntu Tags: , , , , , , ,

Sudo apt-get install basic-linux-pt2 –Testing-&-VMs

February 17th, 2017 No comments

With the hardware sorted (bar some jiggery-pokery to get the ODD to SSD bay converter to fit properly), I set about deciding what I want this box to do.

The list I came up with looks like this:

  • Media serving to my Kodi devices (2 Raspberry Pi systems, my android tablet, and a new Ubuntu PC I’m putting together for retro gaming with my kids)
  • FTP – I like to use my NAS like my own personal cloud. My tablet can mount an FTP in its file browser just like any other folder. No sFTP support, though, unfortunately (and I don’t like any of the file browsers I tried which do).
  • Transmission (or Deluge) – the main reason for swapping the 4GB of RAM out for 16GB
  • SSH (obviously!)
  • Dropbox and Google Drive – for when various apps and things integrate well with these mobile apps.
  • Backup – the WD My Cloud EX4’s backup options are very poor.
  • General file sharing with Windows and Ubuntu – Samba & NFS, naturally.
  • Hosting & tinkering with other bits I might want to try & learn about – a website (for practise, not for public viewing), a git… who knows.

Being basically completely unfamiliar with most of this stuff, I was undecided between Ubuntu Desktop or Server for quite a while. Desktop obviously just has so much of this stuff already ready to go, it mounts things automatically, I can use the GUI as a fallback if something isn’t right, its just more like what I’m accustomed to. On the other hand, having the GUI running all the time will just use up unnecessary RAM  – granted I probably don’t have a shortage of that, but still…

In the end I installed both onto VMs on my Windows machine, made copies (so I had a clean version always ready to go without having to reinstall again), and started playing.

First up I wanted to sort how I was going to deal with my media backend. On my current setup I use the Kodi client on one of my PCs to manage a central SQL database. While it works, its a bit slow and rather inneficient, so I went looking for either a headless Kodi backend, or just a way to run it without the GUI. I found all sorts of ideas, builds and code , none of which I understand or feel like I could implement. After a discussion with a linux guru (one of my Uni lecturers) it was clear that my plan was probably not going to work; he had pointed out that he just runs his on DLNA, and that Plex seems to be quite good too. More research, and a question in /r/Kodi later, I had been pointed in the direction of Emby, a backend for Kodi without many of the limitations of Plex and DLNA. Installation was simple enough, but accessing the Web UI wasn’t. When I had setup the VMs I had just left their network settings as NAT; this, it turns out, makes accessing the network from the VM possible, but not accessing the VM from elsewhere on the network (includingother VMs on the same system). I did try to just change the settings in the VM to add a bridged adapter, but it didn’t work. Not knowing enough about networking on linux to fix this, I just went ahead and reinstalled, this time setting up the VM with two network adapters – one NAT and another bridged. This worked a treat, and after adding a few media files and installing Kodi on the Desktop VM, I was able to play videos no problem.

Next, for no particular reason, was getting NFS working. I found guides, forums, blogs etc (my Google-fu is pretty strong) and set about trying. I was sure it should be working, I’d installed nfs-kernel-server, added the entry into /etc/exports, setup the permissions, but I just couldn’t mount it in the Desktop VM – even though I could watch them through Kodi. I ended up having to ask Reddit’s linux4noobs sub. Simple answer… sudo /etc/init.d/nfs-kernel-server start … and instantly it mounted no problem. Turns out that Kodi was actually watching a transcoded stream from Emby, until I had NFS working. Thankfully Samba took less time and hassle to get working (surprisingly), and pretty soon I could access files across both linux and Windows. And there was much rejoycing.

At this point I was getting impatient (plus this microserver is taking up a chunk of space on my desk where I really ought to be doing uni work), so I quickly checked I knew how to setup a static IP, and turned my attention to the real thing.

Next Up:

Booting up The Box
Installing, reinstalling and shenanigans

This post was originally published on Nathanael’s site here.

Sudo apt-get install basic-linux-pt1 –The-Task

February 16th, 2017 No comments

I’ve had it in mind to start learning linux for a while, and now I’ve found the perfect project to help me do just that: building my own NAS.

Until November I was perfectly happy with my business grade Draytek router. I bought it about 6 years ago,  particularly because it could host its own VPN, instead of just passing through to a Windows PC. It has served me well. I was also reasonably satisfied with my Western Digital EX4 NAS unit in most respects. Then Gigabit FTTH was installed in my area, and I got a free trial – all hell broke loose (very much in a Fist World Problems sense).

The first thing which became apparent is that my ‘nice’ router was outdated. Its best WAN to LAN topped out at 93Mb, while its LAN to WAN maxed at 73Mb (incidentally this also means that I already wasnt getting the benefit of my old 250Mb connection). My new connection is a Gigabit, symmetric line which realistically gives me up to about 700Mb in either direction. Not wanting to go back to relying on the equipment provided by ISPs, I went out (well, I went online) and found myself something which can cope with over 900Mb in either direction (Netgear Nighthawk R7000 if youre interested). ‘”Excellent”, I thought, “now I’m all set”… but no. The knock on effect of getting such fast internet soon became apparent in my NAS. After adding just a few torrents to Transmission, the speed steadily rose until it was approaching 10MB/s, at which point all interfaces to the device practically stopped responding. I surmised that the cause was likely the limited 512M of RAM inside the poor thing, and so went in search of a replacement.

As I looked around, it quickly became clear that most of the available devices on the market were out of my price bracket. While I would have liked to get myself something like a Synology, it just wasn’t going to happen. A friend of mine pointed me in the direction of an HP Gen 8 Proliant Microserver (http://compadvance.co.uk/en/item/323618/HP-Proliant-MicroServer-Gen8-G1610T-4GB) which he has, and after some extra checking around, I decided it looked good. I also decided to up the 4GB of RAM to 16GB, and add an SSD for the OS in the ODD bay.

Now the fun really started. Naturally I didn’t want to put Windows on this thing (although this is what my friend has done), I obviously wanted to run linux. And as its intended to sit quietly, (apparently) minding its own business for the most part, I wanted to keep as much RAM as possible free by not running a GUI. Ubuntu Server seemed like the perfect choice; except I have practically no experience setting up servers, working in command line (Basic ls, cp and rm don’t really count), or using Ubuntu or linux for anything at all (I’ve tinkered, but thats about it).

Well, no time like the present to learn.

Next Up:

Learning and testing on VMs

This post was originally published on Nathanael’s site here.

Categories: Nathanael Y, Ubuntu Tags: ,

Ripping DVDs on Ubuntu 14.04

January 24th, 2017 No comments

Remember DVDs? For those of you too young to have had to deal with the hassle of physical media, DVDs were how us old folks got all of our movies and TV seasons before Netflix existed. These days, I’ve got boxes of the things gathering dust in closets. I hadn’t thought about them since the last time I moved until last night, when my wife asked if I could make her Yoga DVDs available on our home Plex server.

I mean… yes? Sure, why not? Can’t be too hard right? Now all I need is a computer with a DVD drive…

After realizing that one of our laptops still has the appropriate hole in the side of it, I slid one of her disks into the slot, and listened while the machine made all sorts of noises and did… nothing at all.

At first, I thought maybe the drive was broken. So I dug through a drawer to find an old CD (another ancient fossil of a format, kids), and confirmed that the drive did, in fact, work. Physical capability confirmed, I figured that I might be running up against some kind of format issue, and did some Googling.

My cursory research turned up a helpful  page in the Ubuntu Documentation that provides instructions for installing the libdvdread4 package, which includes a set of libraries that allow Ubuntu machines to read DVDs. For Ubuntu 14.04, the instructions look something like this:

~$ sudo apt-get install libdvdread4
~$ sudo /usr/share/doc/libdvdread4/install-css.sh

After this, I had to restart my computer. I’m not sure why, but assumed that it had something to do with the fact that hardware is involved. Once it came back from its brief nap, it happily mounted the DVD that I had left in the drive.

The next step was to install Handbrake from the Ubuntu Software Centre. This is a handy little utility with a tropical-themed logo that can convert damned near any video format to nearly any other. I’ve used it in the past to shrinkify video for playback on my iPhone with great success.

If you open up Handbrake and use the Source button to choose your DVD, it will scan the disc, find the titles available, and show ’em in a dropdown box. Simply select the one that you want to rip, give it a reasonable file name, choose where to put the file on your machine, select High Profile from the presets box on the right hand side of the window, and press the big Start button up at the top.

If yoga were this easy, I’d be exercising instead of writing this article

Pleased with my progress, I returned to my wife, told her that I had made her yoga DVDs available, and asked when she was going to start sporting abs as tight as Jillian Michael’s. She was not impressed. You can’t win them all.

Categories: Jon F, Ubuntu Tags: ,

Fixing Areca Backup on Ubuntu 16.04 (and related distributions)

December 30th, 2016 No comments

Seems like I’m at it again, this time fixing Areca Backup on Ubuntu 16.04 (actually Linux Mint 18.1 in my case). For some reason when I download the current version (Areca 7.5 for Linux/GTK) and try and run the areca.sh script I get the following error:

tyler@computer $ ./areca.sh
ls: cannot access ‘/usr/java’: No such file or directory
No valid JRE found in /usr/java.

This is especially odd because I quite clearly do have Java installed:

tyler@computer $ java -version
openjdk version “1.8.0_111”
OpenJDK Runtime Environment (build 1.8.0_111-8u111-b14-2ubuntu0.16.04.2-b14)
OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)

Now granted this may be an issue exclusive to OpenJDK, or just this version of OpenJDK, but I’m hardly going to install Sun Java just to make this program work.

After some digging I narrowed it down to the look_for_java() function inside of the areca_run.sh script located in the Areca /bin/ directory. Now I’m quite sure there is a far more elegant solution than this but I simply commented out the vast majority of this function and hard coded the directory of my system’s Java binary. Here is how you can do the same.

First locate where your Java is installed by running the which command:

tyler@computer $ which java
/usr/bin/java

As you can see from the output above my java executable exists in my /usr/bin/ directory.

Next open up areca_run.sh inside of the Areca /bin/ directory and modify the look_for_java() function. In here you’ll want to set the variable JAVA_PROGRAM_DIR to your directory above (i.e. in my case it would be /usr/bin/) and then return 0 indicating no error. You can either simply delete the rest or just comment out the remaining function script by placing a # character at the start of each line.

#Method to locate matching JREs
look_for_java() {
JAVA_PROGRAM_DIR=”/usr/bin/”
return 0
# IFS=$’\n’
# potential_java_dirs=(`ls -1 “$JAVADIR” | sort | tac`)
# IFS=
# for D in “${potential_java_dirs[@]}”; do
#    if [[ -d “$JAVADIR/$D” && -x “$JAVADIR/$D/bin/java” ]]; then
#       JAVA_PROGRAM_DIR=”$JAVADIR/$D/bin/”
#       echo “JRE found in ${JAVA_PROGRAM_DIR} directory.”
#       if check_version ; then
#          return 0
#       else
#          return 1
#       fi
#    fi
# done
# echo “No valid JRE found in ${JAVADIR}.”
# return 1
}

Once you’ve saved the file you should be able to run the normal areca.sh script now without encountering any errors!


This post originally appeared on my personal website here.

5 apt tips and tricks

December 22nd, 2016 No comments

Everyone loves apt. It’s a simple command line tool to install new programs and update your system, but beyond the standard commands like update, install and upgrade did you know there are a load of other useful apt-based commands you can run?

1) Search for a package name with apt-cache search

Can’t remember the exact package name but you know some of it? Make it easy on yourself and search using apt-cache. For example:

apt-cache search Firefox

It lists all results for your search. Nice and easy!

It lists all results for your search. Nice and easy!

2) Search for package information with apt-cache show

Want details of a package before you install it? Simple just search for it with apt-cache show.

apt-cache show firefox

More details than you probably even wanted!

More details than you probably even wanted!

3) Upgrade only a specific package

So you already know that you can upgrade your whole system by running

apt-get upgrade

but did you know you can upgrade a specific package instead of the whole system? It’s easy, just specify the package name in the upgrade command. For example to upgrade just firefox run:

apt-get upgrade firefox

4) Install specific package version

Normally when you apt-get install something you get the latest version available but what if that’s not what you wanted? What if you wanted a specific version of the package instead? Again, simple, just specify it when you run the install command. For example run:

apt-get install firefox=version

Where version is the version number you wish to install.

5) Free up disk space with clean

When you download and install packages apt will automatically cache them on your hard drive. This can be useful for a number of reasons, for example some distributions use delta packages so that only what has changed between versions are re-downloaded. In order to do this it needs to have a base cached file already on your hard drive. However these files can take up a lot of space and often times don’t get a lot of updates anyway. Thankfully there are two quick commands that free up this disk space.

apt-get clean

apt-get autoclean

Both of these essentially do the same thing but the difference here is autoclean only gets rid of cached files that have a newer version also cached on your hard drive. These older packages won’t be used anymore and so they are an easy way to free up some space.

There you have it, you are now officially 5 apt commands smarter. Happy computing!

 

Blast from the Past: 10 reasons why Mint might not fail in India

December 21st, 2016 No comments

This post was originally published on July 7, 2010. The original can be found here.


Last evening while reading the SA forums, I encountered a thread about Linux and what was required to bring it to the general public. One of the goons mentioned a post that indicated ten reasons why Ubuntu wasn’t ready for the desktop in India. I kid you not – the most ridiculous reason was because users couldn’t perform the important ritual of right click/Refreshing on the desktop five or more times before getting down to work.

Here are Bharat’s reasons why Ubuntu fails, followed by why I think Mint might succeed instead in its place (while still employing his dubious logic.) When I refer to Indian users, of course, I’m taking his word for it – he’s obviously the authority here.

GRUB Boot Loader does not have an Aesthetic Appeal.

Bharat complains about the visual appearance of Grub – how it does not create a good first impression. This is, of course, in spite of Windows’ horrible boot menu when there’s more than one operating system or boot option to select. Apparently Indian users all have full-color splash screens with aesthetic appeal for BIOS, video card and PCI add-in initialization as well; this is just the icing on the cake that makes them go “eurrrgh” and completely discount Ubuntu.

To improve relations with India and eliminate this eyesore, Mint has added a background image during this phase of boot. My good friend Tyler also informs me that there’s a simple option in the Mint Control Center called “Start-Up Manager” that alllows easy configuration of grub to match a system’s native resolution and color depth.

Login Screen-Users are required to type in their username.

Again, another seemingly impenetrable barrier. Has nobody in India worked in an environment where typing in usernames AND passwords is required – like, for example, posting a blog entry on WordPress or signing into Gmail? In any event, Mint’s GNOME installation definitely gives a clickable list for this awfully onerous task.

Desktop-The Refresh option is missing!

I’m just going to directly lift this description as to the burning need for right click / Refresh:

What does an average Indian user do when the desktop loads in Windows?He rights clicks on the desktop and refreshes the desktop about 5-6 times or until he is satisfied.This is a ritual performed by most Indian Users after switching on the computer and just before shutting down the computer.
When this average user tries to perform his ‘Refresh’ ritual in Ubuntu,he is in for a rude shock.The Ubuntu Desktop does not have a Refresh Option or any other simliar option like Reload in the Right Click Menu.
So I advice Ubuntu Developers to include to a Refresh or a Reload option in the right click menu on the Desktop and in the Nautilus File Manager.The option should be equivalent of pressing Ctrl+R.As of now ,pressing Ctrl+R refreshes the Desktop in Ubuntu.

Mint’s developers have unfortunately not come around to this clearly superior way of thinking by default yet.

Read more…

Stop screen tearing with Nvidia/Intel graphics combo

November 29th, 2016 No comments

Ever since upgrading my laptop to Linux Mint 18 I’ve noticed some pronounced screen tearing happening. Initially I figured this was something I would simply have to live with due to the open source driver being used instead of the proprietary one, but after some Googling I found a way to actually fix the issue.

Following this post on Ask Ubuntu I created a new directory at /etc/X11/xorg.conf.d/ and then created a new file in there called 20-intel.conf. Inside of this file I placed the following text:

Section “Device”
Identifier      “Intel Graphics”
Driver          “intel”
Option          “TearFree”          “true”
EndSection

A quick reboot later and I’m happy to say that my screen no longer tears as I scroll down long web pages.

Even Borat agrees!

Even Borat agrees!

Removing old Kernels in Ubuntu 16.04/Linux Mint 18

October 25th, 2016 No comments

Recently I’ve noticed that my /boot partition has become full and I’ve even had some new kernel updates fail as a result. It seems the culprit is all of the older kernels still lying around on my system even though they are no longer in use. Here are the steps I took in order to remove these old kernels and reclaim my /boot partition space.

A few warnings:

  • Always understand commands you are running on your machine before you run them. Especially when they start with sudo.
  • Be very careful when removing kernels – you may end up with a system that doesn’t boot!
  • My rule of thumb is to only remove kernels older than the most recent 2 (assuming I haven’t had any bad experiences with either of them). This allows me to revert back to a slightly older version if I find something that no longer works in the latest version.
First determine what kernel your machine is actually currently running

For example running the command:

uname -a

prints out the text “4.4.0-45-generic“. This is the name of the kernel my system is currently using. I do not want to remove this one!

Next get a list of all installed kernels

You can do this a few different ways but I like using the following command:

dpkg --list | grep linux-image

This should print out a list similar to the one in the screenshot below.

Example list of installed kernels

Example list of installed kernels

From this list you can identify which ones you want to remove to clear up space. On my system I had versions 4.4.0-21.37, 4.4.0-36.55, 4.4.0-38.57 and 4.4.0-45.66 so following my rule above I want to remove both 4.4.0-21.37 and 4.4.0-36.55.

Remove the old kernels

Again this can be done a number of different ways but seeing as we’re already in the terminal why not use our trust apt-get command to do the job?

sudo apt-get purgelinux-image-4.4.0-21-generic linux-image-4.4.0-36-generic

and just like that almost 500MB of disk space is freed up!

Ubuntu 16.04 VNC woes? Try this!

October 2nd, 2016 No comments

You may recall a few years back I made a very similar post about Ubuntu 14.04’s ‘VNC woes’. Well unfortunately it seems things have changed slightly between 14.04 and 16.04 and now the setting that once fixed everything now doesn’t persist and is only good for that session. Thankfully it is pretty easy to adapt the existing work around into a script that gets run on startup in order to ‘fix it’ forever. Note that these steps should also work on any Ubuntu derivatives such as Linux Mint 18, etc.

Credit goes to the excellent post over at ThinkingMedia for confirming that the fix is basically the same as the one I had for 14.04. What follows is their instructions on creating a start up script:

1. Create a text file called vino-fix.sh and place the following in it:

#!/bin/bash
export DISPLAY=0:0
gsettings set org.gnome.Vino require-encryption false 

2. Modify the file’s permissions so that it becomes executable. You can do this via the terminal with the following command:

chmod +x vino-fix.sh

3. Create a new startup application and point it at your script. Now every time you reboot it will run that script for you and ‘fix’ the issue.

One last thing I should point out – this work around disables the built in VNC encryption. Generally I would absolutely not recommend disabling any sort of security like this however VNC at its core is not really a secure protocol to begin with. You are far better off setting up VNC to only listen to local connections and then using SSH+VNC for your secure remote desktop needs. Just my two cents.

Fix: trying to overwrite ‘/usr/share/accounts/services/google-im.service’ installing kubuntu-desktop

June 5th, 2016 No comments

I have an Ubuntu 16.04 desktop installation with Unity and wanted to try KDE, so I ran sudo apt-get install kubuntu-desktop. apt failed with the following message:

trying to overwrite '/usr/share/accounts/services/google-im.service', which is also in package account-plugin-google [...]

The original issue at Ask Ubuntu has several suggestions but none of them worked – any apt commands returned the same requirement to run apt-get -f install, which in turn gave the original “trying to overwrite” error message. synaptic also wasn’t installed so I couldn’t use it (or install it, as all other apt installation commands failed.)

I was able to get the dpkg database out of its bad state and continue to install kubuntu-desktop by running the following:

dpkg -P account-plugin-google unity-scope-gdrive
apt-get -f install

(Link to original Kubuntu bug for posterity: https://bugs.launchpad.net/kubuntu-ppa/+bug/1451728)

This post was cross-posted to my personal website.

Categories: God Damnit Linux, Jake B, KDE, Kubuntu, Ubuntu Tags:

Automating Let’s Encrypt certificates on nginx

February 19th, 2016 1 comment

Let’s Encrypt is a new Certificate Authority that provides free SSL certificates. It is intended to be automated, so that certificates are renewed automatically. We’re using Let’s Encrypt certificates for our set of free Calculus practice problems. Our front end is currently served by an Ubuntu server running nginx, and here’s how we have it scripted on that machine. In a future post, I’ll describe how it’s automated on our Docker setup with HAProxy.

First of all, we’re using acme-tiny instead of the official Let’s Encrypt client, since it’s much smaller and, IMHO, easier to use. It takes a bit more to set up, but works well once it’s set up.

We installed acme-tiny in /opt/acme-tiny, and created a new letsencrypt user. The letsencrypt user is only used to run the acme-tiny client with reduced priviledge. In theory, you could run the entire renewal process with a reduced priviledge user, but the rest of the process is just basic shell commands, and my paranoia level is not that high.

We created an /opt/acme-tiny/challenge directory, owned by the letsencrypt user, and we created /etc/acme-tiny with the following contents:

  • account.key: the account key created in step 1 from the acme-tiny README. This file should be readable only by the letsencrypt user.
  • certs: a directory containing a subdirectory for each certificate that we want. Each subdirectory should have a domain.csr file, which is the certificate signing request created in step 2 from the acme-tiny README. The certs directory should be publicly readable, and the subdirectories should be writable by the user that the cron job will run as (which does not have to be the letsencrypt user).
  • private: a directory containing a subdirectory for each certificate that we want, like we had with the certs directory. Each subdirectory has a file named privkey.key, which will be the private key associated with the certificate. To coincide with the common setup on Debian systems, the private directory should be readable only by the ssl-cert group.

Instead of creating the CSR files as described in the acme-tiny README, I created a script called gen_csr.sh:

#!/bin/bash
openssl req -new -sha256 -key /etc/acme-tiny/private/"$1"/privkey.pem -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:") <(cat /etc/acme-tiny/certs/"$1"/domains | sed "s/\\s*,\\s*/,DNS:/g")) > /etc/acme-tiny/certs/"$1"/domain.csr

The script is invoked as gen_scr.sh <name>. It reads a file named /etc/acme-tiny/certs/<name>/domains, which is a text file containing a comma-separated list of domains, and it writes the /etc/acme-tiny/certs/<name>/domain.csr file.

Now we need to configure nginx to serve the challenge files. We created a /etc/nginx/snippets/acme-tiny.conf file with the following contents:

location /.well-known/acme-challenge/ {
    auth_basic off;
    alias /opt/acme-tiny/challenge/;
}

(The “auth_basic off;” line is needed because some of our virtual hosts on that server use basic HTTP authentication.) We then modify the sites in /etc/nginx/sites-enabled that we want to use Let’s Encrypt certificates to include the line “include snippets/acme-tiny.conf;“.

After this is set up, we created a /usr/local/sbin/letsencrypt-renew script that will be used to request a new certificate:

#!/bin/sh
set +e

# only renew if certificate will expire within 20 days (=1728000 seconds)
openssl x509 -checkend 1728000 -in /etc/acme-tiny/certs/"$1"/cert.pem && exit 255

set -e
DATE=`date +%FT%R`
su letsencrypt -s /bin/sh -c "python /opt/acme-tiny/acme_tiny.py --account-key /etc/acme-tiny/account.key --csr /etc/acme-tiny/certs/\"$1\"/domain.csr --acme-dir /opt/acme-tiny/challenge/" > /etc/acme-tiny/certs/"$1"/cert-"$DATE".pem
ln -sf cert-"$DATE".pem /etc/acme-tiny/certs/"$1"/cert.pem
wget https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem -O /etc/acme-tiny/lets-encrypt-x1-cross-signed.pem
cat /etc/acme-tiny/certs/"$1"/cert-"$DATE".pem /etc/acme-tiny/lets-encrypt-x1-cross-signed.pem > /etc/acme-tiny/certs/"$1"/fullchain-"$DATE".pem
ln -sf fullchain-"$DATE".pem /etc/acme-tiny/certs/"$1"/fullchain.pem

The script will only request a new certificate if the current certificate will expire within 20 days. The certificates are stored in /etc/acme-tiny/certs/<name>/cert-<date>.pem (symlinked to /etc/acme-tiny/certs/<name>/cert.pem). The full chain (including the intermediate CA certificate) is stored in /etc/acme-tiny/certs/<name>/fullchain-<date>.pem (symlinked to /etc/acme-tiny/certs/<name>/fullchain.pem).

As-is, the script must be run as root, since it does a su to the letsencrypt user. It should be trivial to modify it to use sudo instead, so that it can be run by any user that has the appropriate permissions on /etc/acme-tiny.

the letsencrypt-renew script is run by another script that will restart the necessary servers if needed. For us, the script looks like this:

#!/bin/sh

letsencrypt-renew sbscalculus.com

RV=$?

set -e

if [ $RV -eq 255 ] ; then
  # renewal not needed
  exit 0
elif [ $RV -eq 0 ] ; then
  # restart servers
  service nginx reload;
else
  exit $RV;
fi

This is then called by a cron script of the form chronic /usr/local/sbin/letsencrypt-renew-and-restart. Chronic is a script from the moreutils package that runs a command and only passes through its output if it fails. Since the renewal script checks whether the certificate will expire, we run the cron task daily.

Of course, once you have the certificate, you want to tell nginx to use it. We have another file in /etc/nginx/snippets that, aside from setting various SSL parameters, includes

ssl_certificate /etc/acme-tiny/certs/sbscalculus.com/fullchain.pem;
ssl_certificate_key /etc/acme-tiny/private/sbscalculus.com/privkey.pem;

This is the setup we use for one of our server. I tried to make it fairly general, and it should be fairly easy to modify for other setups.

 

This article was originally published at Hubert’s personal website here.

Categories: Hubert C, Linux, Ubuntu Tags: ,

Distro hopping: how to install Plex Home Theater on elementary OS

September 15th, 2015 No comments

Plex is great. It is a very easy to use cross-platform program that lets you view and watch your own personal media almost anywhere. The main component is the Plex Media Server which actually hosts and provides the media but they have another program that offers a very nice interface to browse and view these files called the Plex Home Theater. Unfortunately while they have builds for Windows and OS X there are currently no such officially supported versions for linux. Thankfully the community has stepped in and provided the means to get this running on your distribution of choice. This post will show how to install it on elementary OS (or any other Ubuntu based distributions).

Visiting this page you can see that there are instructions for different distributions. As elementary OS is derivative of Ubuntu we’ll use that provided repository to install the program. The first step is to open a terminal and run the following command:

 sudo apt-add-repository ppa:plexapp/plexht

This will add the community repository to your system so that you can find and install the program normally. Next you just need to run the update command to re-sync with the repositories and then the install command to actually install the program:

sudo apt-get update
sudo apt-get install plexhometheater

Once the command finishes Plex Home Theater should be successfully installed.

Plex!

Plex!

Have fun watching your movies!

This post is part of a series:

Applying updates to Docker and the Plex container

December 7th, 2014 No comments

In my last post, I discussed several Docker containers that I’m using for my home media streaming solution. Since then, Plex Media Server has updated to 0.9.11.4 for non-Plex Pass users, and there’s another update if you happen to pay for a subscription. As the Docker container I used (timhaak/plex) was version 0.9.11.1 at the time, I figured I’d take the opportunity to describe how to

  • update Docker itself to the latest version
  • run a shell inside the container as another process, to review configuration and run commands directly
  • update Plex to the latest version, and describe how not to do this
  • perform leet hax: commit the container to your local system, manually update the package, and re-commit and run Plex

Updating Docker

I alluded to the latest version of Docker having features that make it easier to troubleshoot inside containers. Switching to the latest version was pretty simple: following the instructions to add the Docker repository to my system, then running

sudo apt-get update
sudo apt-get install lxc-docker

upgraded Docker to version 1.3.1 without any trouble or need to manually uninstall the previous Ubuntu package.

Run a shell using docker exec

Let’s take a look inside the plex container. Using the following command will start a bash process so that we can review the filesystem on the container:

docker exec -t -i plex /bin/bash

You will be dropped into a root prompt inside the plex container. Check out the filesystem: there will be a /config and a /data directory pointing to “real” filesystem locations. You can also use ps aux to review the running processes, or even netstat -anp to see active connections and their associated programs. To exit the shell, use Ctrl+C – but the container will still be running when you use docker ps -a from the host system.

Updating Plex in-place: My failed attempt

Different Docker containers will have different methods of performing software updates. In this case, looking at the Dockerfile for timhaak/plex, we see that a separate repository was added for the Plex package – so we should be able to confirm that the latest version is available. This also means that if you destroy your existing container, pull the latest image, then launch a new copy, the latest version of Plex will be installed (generally good practice.)

But wait – the upstream repository at http://shell.ninthgate.se/packages/debian/pool/main/p/plexmediaserver/ does contain the latest .deb packages for Plex, so can’t we just run an apt-get update && apt-get upgrade?

Well, not exactly. If you do this, the initial process used to run Plex Media Server inside the Docker container (start.sh) gets terminated, and Docker takes down the entire plex container when the initial process terminates. Worse, if you then decide to re-launch things with docker start plex, the new version is incompletely installed (dpkg partial configuration).

So the moral of the story: if you’re trying this at home, the easiest way to upgrade is to recreate your Plex container with the following commands:

docker stop plex

docker rm plex

# The 'pull' process may take a while - it depends on the original repository and any dependencies in the Dockerfile. In this case it has to pull the new version of Plex.
docker pull timhaak/plex

# Customize this command with your config and data directories.
docker run -d -h plex --name="plex" -v /etc/docker/plex:/config -v /mnt/nas:/data -p 32400:32400 timhaak/plex

Once the container is up and running, access http://yourserver:32400/web/ to confirm that Plex Media Server is running. You can check the version number by clicking the gear icon next to your server in the left navigation panel, then selecting Settings.

Hacking the container: commit it and manually update Plex from upstream

If you’re more interested in hacking the current setup, there’s a way to commit your existing Plex image, manually perform the upgrade, and restart the container.

First, make sure the plex container is running (docker start plex) and then commit the container to your local filesystem (replacing username with your preferred username):

docker commit plex username/plex:latest

Then we can stop the container, and start a new instance where bash is the first process:

docker stop plex

docker rm plex

# Replace username with the username you selected above.
docker run -t -i --name="plex" -h plex username/plex:latest /bin/bash

Once inside the new plex container, let’s grab the latest Plex Media Server package and force installation:

curl -O https://downloads.plex.tv/plex-media-server/0.9.11.4.739-a4e710f/plexmediaserver_0.9.11.4.739-a4e710f_amd64.deb

dpkg -i plexmediaserver_0.9.11.4.739-a4e710f_amd64.deb

# When prompted, select Y to install the package maintainer's versions of files. In my instance, this updated the init script as well as the upstream repository.

Now, we can re-commit the image with the new Plex package. Hit Ctrl+D to exit the bash process, then run:

docker commit plex username/plex:latest

docker rm plex

# Customize this command with your config and data directories.
docker run -d -h plex --name="plex" -v /etc/docker/plex:/config -v /mnt/nas:/data -p 32400:32400 username/plex /start.sh

# Commit the image again so it will run start.sh if ever relaunched:
docker commit plex username/plex:latest

You’ll also need to adjust your /etc/init/plex.conf upstart script to point to username/plex.

The downside of this method is now that you’ve forked the original Plex image locally and will have to do this again for updates. But hey, wasn’t playing around with Docker interesting?

Categories: Docker, Jake B, Plex, Ubuntu Tags:

Running a containerized media server with Ubuntu 14.04, Docker, and Plex

November 23rd, 2014 1 comment

I recently took it upon myself to rebuild a general-purpose home server – installing a new Intel 530 240GB solid-state drive to replace a “spinning rust” drive, and installing a fresh copy of Ubuntu 14.04 now that 14.04.1 has released and there is much less complaining online.

The “new hotness” that I’d like to discuss has been the use of Docker to containerize various processes. Docker gets a lot of press these days, but the way I see it is a way to ensure that your special snowflake applications and services don’t get the opportunity to conflict with one another. In my setup, I have four containers running:

I like the following things about Docker:

  • Since it’s new, there are a lot of repositories and configuration instructions online for reference.
  • I can make sure that applications like Sonarr/NZBDrone get the right version of Mono that won’t conflict with my base system.
  • As a network administrator, I can ensure that only the necessary ports for a service get forwarded outside the container.
  • If an application state gets messed up, it won’t impact the rest of the system as much – I can destroy and recreate the individual container by itself.

There are some drawbacks though:

  • Because a lot of the images and Dockerfiles out there are community-based, there are some that don’t follow best practices or fall out of an update cycle.
  • Software updates can become trickier if the application is unable to upgrade itself in-place; you may have to pull a new Dockerfile and hope that your existing configuration works with a new image.
  • From a security standpoint, it’s best to verify exactly what an image or Dockerfile does before running it – for example, that it pulls content from official repositories (the docker-plex configuration is guilty of using a third-party repo, for example.)

To get started, on Ubuntu 14.04 you can install a stable version of Docker following these instructions, although the latest version has some additional features like docker exec that make “getting inside” containers to troubleshoot much easier. I was able to get all these containers running properly with the current stable version (1.0.1~dfsg1-0ubuntu1~ubuntu0.14.04.1). Once Docker is installed, you can grab each of the containers above with a combination of docker search and docker pull, then list the downloaded containers with docker images.

There are some quirks to remember. On the first run, you’ll need to docker run most of these containers and provide a hostname, box name, ports to forward and shared directories (known as volumes). On all subsequent runs, you can just use docker start $container_name – but I’ll describe a cheap and easy way of turning that command into an upstart service later. I generally save the start commands as shell scripts in /usr/local/bin/docker-start/*.sh so that I can reference them or adjust them later. The start commands I’ve used look like:

Plex
docker run -d -h plex --name="plex" -v /etc/docker/plex:/config -v /mnt/nas:/data -p 32400:32400 timhaak/plex
SABnzbd+
docker run -d -h sabnzbd --name="sabnzbd" -v /etc/docker/sabnzbd:/config -v /mnt/nas:/data -p 8080:8080 -p 9090:9090 timhaak/sabnzbd
Sonarr
docker run -d -h sonarr --name="sonarr" -v /etc/docker/sonarr:/config -v /mnt/nas:/data -p 8989:8989 tuxeh/sonarr
CouchPotato
docker run -d -h couchpotato --name="couchpotato" -e EDGE=1 -v /etc/docker/couchpotato:/config -v /mnt/nas:/data -v /etc/localtime:/etc/localtime:ro -p 5050:5050 needo/couchpotato
These applications have a “/config” and a “/data” shared volume defined. /data points to “/mnt/nas”, which is a CIFS share to a network attached storage appliance mounted on the host. /config points to a directory structure I created for each application on the host in /etc/docker/$container_name. I generally apply “chmod 777” permissions to each configuration directory until I find out what user ID the container is writing as, then lock it down from there.

For each initial start command, I choose to run the service as a daemon with -d. I also set a hostname with the “-h” parameter, as well as a friendly container name with “–name”; otherwise Docker likes to reference containers with wild adjectives combined with scientists, like “drunk_heisenberg”.

Each of these containers generally has a set of instructions to get up and running, whether it be on Github, the developer’s own site or the Docker Hub. Some, like SABnzbd+, just require that you go to http://yourserverip:8080/ and complete the setup wizard. Plex required an additional set of configuration steps described at the original repository:

  • Once Plex starts up on port 32400, access http://yourserverip:32400/web/ and confirm that the interface loads.
  • Switch back to your host machine, and find the place where the /config directory was mounted (in the example above, it’s /etc/docker/plex). Enter the Library/Application Support/Plex Media Server directory and edit the Preferences.xml file. In the <Preferences> tag, add the following attribute: allowedNetworks=”192.168.1.0/255.255.255.0″ where the IP address range matches that of your home network. In my case, the entire file looked like:

    <?xml version="1.0" encoding="utf-8"?>
    <Preferences MachineIdentifier="(guid)" ProcessedMachineIdentifier="(another_guid)" allowedNetworks="192.168.1.0/255.255.255.0" />

  • Run docker stop plex && docker start plex to restart the container, then load http://yourserverip:32400/web/ again. You should be prompted to accept the EULA and can now add library locations to the server.

Sonarr needed to be updated (from the NZBDrone branding) as well. From the GitHub README, you can enable in-container upgrades:

[C]onfigure Sonarr to use the update script in /etc/service/sonarr/update.sh. This is configured under Settings > (show advanced) > General > Updates > change Mechanism to Script.

To automatically ensure these containers start on reboot, you can either use restart policies (Docker 1.2+) or write an upstart script to start and stop the appropriate container. I’ve modified the example from the Docker website slightly to stop the container as well:

description "SABnzbd Docker container"
author "Jake"
start on filesystem and started docker
stop on runlevel [!2345]
respawn
script
/usr/bin/docker start -a sabnzbd
end script
pre-stop exec /usr/bin/docker stop sabnzbd

Copy this script to /etc/init/sabnzbd.conf; you can then copy it to plex, couchpotato, and sonarr.conf and change the name of the container and title in each. You can then test it by rebooting your system and running “docker ps -a” to ensure that all containers come up cleanly, or running “docker stop $container; service $container start”. If you run into trouble, the upstart logs are in /var/log/upstart/$container_name.conf.

Hopefully this introduction to a media server with Docker containers was thought-provoking; I hope to have further updates down the line for other applications, best practices and how this setup continues to operate in its lifetime.

Categories: Docker, Jake B, Plex, Ubuntu Tags:

How to set a static IP address on Ubuntu 14.04 server (and others)

September 16th, 2014 No comments

This assumes you want to set a static IP address on the network device eth0.

Open up the interfaces file

sudo nano /etc/network/interfaces

and remove or comment out the line that says

iface eth0 inet dhcp

then add the following lines in its place:

iface eth0 inet static
address [static IP address, i.e. 192.168.1.123]
netmask [i.e. 255.255.255.0]
network [i.e. 192.168.1.0]
broadcast [i.e. 192.168.1.255]
gateway [i.e. 192.168.1.1]
dns-nameservers [i.e. 8.8.8.8]

Save the file and reboot the server. On some systems you may also need to update /etc/resolv.conf and /etc/hosts

Ubuntu 14.04 VNC woes? Try this!

April 28th, 2014 No comments

If, like me, you’ve recently upgraded to Ubuntu 14.04 only to find out that for whatever reason you can no longer VNC to that machine anymore (either from Windows or even an existing Linux install) have no fear because I’ve got the fix for you!

Simply open up a terminal and run the following line:

gsettings set org.gnome.Vino require-encryption false

Obviously if you use VNC encryption you may not want to do this but if you’re like me and just use VNC on the local network it should be safe enough to disable.