I use a MacBook Pro for my day-to-day operations here at CB1, INC. I’m a huge believer that a development environment should mimic the production environment, so I find myself running a couple virtual machines in VMware Fusion.

The following guide is a reference for myself as well as possibly a helpful resource for setting up your own Linux development environment. Here’s an checklist of the tasks to perform and software to install:

Operating System

Start by installing Ubuntu 10.10 Desktop (or server). I’m not going to cover installing Ubuntu since there are already several other resources out there. Once Ubuntu is installed, open a Terminal:

user@ubuntu:~# sudo passwd root
[sudo] password for user: <type your password>
Enter new UNIX password: <type new root password>
Retype new UNIX password: <type new root password again>
passwd: password updated successfully

user@ubuntu:~# sudo apt-get update
user@ubuntu:~# sudo apt-get upgrade

user@ubuntu:~# mkdir ~/src

New File Permissions

user@ubuntu:~# sudo pico /etc/profile

Change 022 to 002. This setting controls the default permissions when a new file or directory is created. This is mostly useful when managing files over Samba.

Network IP Addresses

Optionally, you may want to assign a static IP address. I set up one IP address for Apache and another for nginx.

user@ubuntu:~# sudo pico /etc/network/interfaces

The following is a reference for adding two static IPs. Change the IPs to meet your needs.

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
	address 192.168.1.200
	netmask 255.255.255.0
	gateway 192.168.1.1

auto eth0:1
iface eth0:1 inet static
	address 192.168.1.201
	netmask 255.255.255.0
user@ubuntu:~# sudo /etc/init.d/networking restart

Packages

Here’s a bunch of packages that will set up compilers, version control, Java, MySQL, Apache, PHP, Memcache, Gearman, Samba, and more.

user@ubuntu:~# sudo apt-get install build-essential autotools-dev autoconf \
 autoconf2.13 openssh-server ethtool traceroute openjdk-6-jdk \
 mysql-server-5.1 bzr subversion subversion-tools ntp ntpdate \
 libpcre3-dev libevent-dev automake bison libtool scons  g++ \
 ncurses-dev libreadline-dev libz-dev libssl-dev  libcurl4-openssl-dev \
 ruby rubygems libzip-ruby1.8 libzip-ruby1.9.1 python-dev ruby-dev \
 libdbus-glib-1-dev uuid-dev libpam0g libpam0g-dev gperf samba valgrind \
 libxml2-dev libfreetype6-dev curl libcurl4-openssl-dev \
 libjpeg62-dev libpng12-dev sqlite3 libsqlite3-dev git-core \
 postgresql postgis gearman libgearman-dev php5 \
 libapache2-mod-php5 php5-dev memcached php5-memcached \
 php5-curl php5-gd php5-mysql php5-pgsql php-apc \
 php5-xdebug php5-fpm libapache2-mod-fastcgi

MySQL

During the package install above, MySQL will prompt you for the root password.

After the packages are installed, we need to allow remote MySQL connections.

user@ubuntu:~# sudo pico /etc/mysql/my.cnf

Comment out the bind-address line.

# bind-address          = 127.0.0.1

SSH

Next, you may optionally increase the connection keep alive interval for remote ssh connections. Timeouts aren’t really an issue for SSH’ing into a local VM, but really helps for remote installs.

user@ubuntu:~# sudo echo "ClientAliveInterval 60" >> /etc/ssh/sshd_config

Samba

Samba allows me to drag and drop files between my Mac and Linux VM. I personally do not enable/install Samba on production servers.

user@ubuntu:~# sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.orig
user@ubuntu:~# sudo pico /etc/samba/smb.conf

You can add a share such as the following:

[ubuntu]
        force user = <your username>
        writeable = yes
        create mode = 644
        path = /home/<your username>
        directory mode = 755
        force group = <your username>

Then create yourself a Samba user:

user@ubuntu:~# sudo smbpasswd -a <your username>

Apache 2

Apache is mostly configured out of the box, but I like to enable rewrite and SSL so I can test production features.

user@ubuntu:~# sudo a2enmod rewrite
user@ubuntu:~# sudo a2enmod ssl

Since I’m going to run Apache and nginx, I’m going bind Apache to eth0.

user@ubuntu:~# sudo pico /etc/apache2/ports.conf
NameVirtualHost 192.168.1.200:80
Listen 192.168.1.200:80

<IfModule mod_ssl.c>
    Listen 192.168.1.200:443
</IfModule>

Now we need to add eth0‘s IP to the default host:

user@ubuntu:~# sudo pico /etc/apache2/sites-enabled/000-default
<VirtualHost 192.168.1.200:80>
        ServerAdmin webmaster@localhost

        DocumentRoot /var/www
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        LogLevel warn
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Restart Apache for the changes to take effect.

user@ubuntu:~# sudo apache2ctl restart

Gearman

By default, Gearman uses memory to store pending jobs in the queue, but I prefer to use MySQL for persistent storage. To do this, first create the queue database and table:

user@ubuntu:~# mysqladmin -uroot -p123123 create gearman
user@ubuntu:~# mysql -uroot -p123123 -e "CREATE TABLE gearman.gearman_queue (
  unique_key VARCHAR(64) NOT NULL,
  function_name VARCHAR(255) NULL,
  priority INT NULL,
  data LONGBLOB NULL,
  PRIMARY KEY (unique_key)
) ENGINE = InnoDB;"

Next update the init script to tell Gearman to use the database:

user@ubuntu:~# sudo mv /etc/default/gearman-job-server /etc/default/gearman-job-server.bak
user@ubuntu:~# sudo echo "PARAMS=\"-q libdrizzle --libdrizzle-host=127.0.0.1" \
   "--libdrizzle-user=root --libdrizzle-password=123123 --libdrizzle-db=gearman" \
   "--libdrizzle-table=gearman_queue --libdrizzle-mysql\"" > /etc/default/gearman-job-server
user@ubuntu:~# sudo /etc/init.d/gearman-job-server restart

Gearman PHP Extension

We need to download and install the Gearman PHP extension if we want to write PHP workers or post jobs to the queue.

user@ubuntu:~# cd ~/src
user@ubuntu:~/src# wget http://pecl.php.net/get/gearman-0.7.0.tgz
user@ubuntu:~/src# tar xzf gearman-0.7.0.tgz
user@ubuntu:~/src# rm gearman-0.7.0.tgz package.xml
user@ubuntu:~/src# cd gearman-0.7.0
user@ubuntu:~/src# phpize
user@ubuntu:~/src# ./configure
user@ubuntu:~/src# make
user@ubuntu:~/src# sudo make install

Next, add the config file to load the Gearman PHP extension:

user@ubuntu:~# sudo echo "extension=gearman.so" >> /etc/php5/conf.d/gearman.ini

memcached PHP Extension

Since we have memcached and the memcached PHP extension install, let’s use it for storing session data:

user@ubuntu:~/src# sudo echo "session.save_handler = memcached
session.save_path = \"127.0.0.1:11211\"" >> /etc/php5/conf.d/memcached.ini

nginx

nginx is web server that is really fast. I use nginx as my primary development web server unless I’m running a web app that only works with Apache. You can choose to install nginx from package, but I like to live life on the bleeding edge, so I’ll be building nginx from source. To install nginx, we need to download the source, compile it, install it, and configure it.

user@ubuntu:~# cd ~/src
user@ubuntu:~/src# wget http://nginx.org/download/nginx-0.8.52.tar.gz
user@ubuntu:~/src# tar xzf nginx-0.8.52.tar.gz
user@ubuntu:~/src# rm nginx-0.8.52.tar.gz
user@ubuntu:~/src# cd nginx-0.8.52
user@ubuntu:~/src# mkdir /var/lib/nginx
user@ubuntu:~/src# ./configure \
    --sbin-path=/usr/sbin \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/lock/nginx.lock \
    --http-log-path=/var/log/nginx/access.log \
    --http-client-body-temp-path=/var/lib/nginx/body \
    --http-proxy-temp-path=/var/lib/nginx/proxy \
    --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
    --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
    --http-scgi-temp-path=/var/lib/nginx/scgi \
    --with-http_stub_status_module
user@ubuntu:~/src# make
user@ubuntu:~/src# sudo make install

user@ubuntu:~# sudo pico /etc/init.d/nginx

Here’s the init script that will start nginx for us:

#! /bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/nginx
NAME=nginx
DESC=nginx
test -x $DAEMON || exit 0
case "$1" in
  start)
        echo -n "Starting $DESC: "
        start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
  stop)
        echo -n "Stopping $DESC: "
        start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON
        echo "$NAME."
        ;;
  restart|force-reload)
        echo -n "Restarting $DESC: "
        start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON
        sleep 1
        start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
  reload)
        echo -n "Reloading $DESC configuration: "
        start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/$NAME.pid --exec $DAEMON
        echo "$NAME."
        ;;
  *)
        echo "Usage: /etc/init.d/$NAME {start|stop|restart|reload|force-reload}" >&2
        exit 1
        ;;
esac
exit 0

Now we need to make the init script executable and enable it:

user@ubuntu:~# sudo chmod +x /etc/init.d/nginx
user@ubuntu:~# sudo update-rc.d nginx defaults

user@ubuntu:~# sudo pico /etc/nginx/nginx.conf

Here’s a starter nginx.conf with some basic settings:

user  www-data www-data;
worker_processes  2;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile                on;
    tcp_nodelay             on;
    tcp_nopush              on;
    keepalive_timeout       65;
    server_name_in_redirect off;
    server_tokens           off;

    add_header Strict-Transport-Security max-age=1800;
    add_header X-Frame-Options deny;

    gzip            on;
    gzip_buffers    16 8k;
    gzip_comp_level 9;
    gzip_types      text/plain text/xml application/x-javascript text/css;

    include /etc/nginx/sites/*;
}
user@ubuntu:~# sudo mkdir /etc/nginx/sites
user@ubuntu:~# sudo pico /etc/nginx/sites/default

Now we need to set up a default host that supports PHP (via PHP-FPM, PHP’s FastCGI Process Manager) and we want the default host to use the eth0:1 IP address:

server {
    listen       192.168.1.201:80 default;
    server_name  _;
    root   /var/www;
    index  index.php;
    location / {
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /index.php?q=$1 last;
            break;
        }
    }
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www$fastcgi_script_name;
        include        fastcgi_params;
    }
    location ~* (\.(htaccess|engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)|code-style\.pl|Entries.*|Repository|Root|Tag|Template)$ {
        deny all;
    }
}

After the config files are good to go, start nginx:

user@ubuntu:~# sudo /etc/init.d/nginx start

Service Names

I also like to add service names so I can see what ports are in use when I run netstat. I added drizzle and Cassandra for fun despite this post not including them.

user@ubuntu:~# sudo cp /etc/services /etc/services.bak
user@ubuntu:~# su
root@ubuntu:~# echo "drizzle     4427/tcp
drizzle     4427/udp
memcached   11211/tcp
memcached   11211/udp
gearmand    4730/tcp
gearmand    4730/udp
fastcgi     9000/tcp
cassandra   9160/tcp" >> /etc/services
root@ubuntu:~# exit

Android SDK

The Android SDK is unfortunately not in package, so you’ll need to download it from the Android Developer site: http://developer.android.com/sdk/index.html.

user@ubuntu:~# wget http://dl.google.com/android/android-sdk_r07-linux_x86.tgz
user@ubuntu:~# tar xzf android-sdk_r07-linux_x86.tgz
user@ubuntu:~# rm android-sdk_r07-linux_x86.tgz
user@ubuntu:~# sudo mv android-sdk-linux_x86 /usr/local
user@ubuntu:~# sudo find /usr/local/android-sdk-linux_x86 -type d -exec chmod 777 {} \;

You’ll need to add the Android SDK path near the top of your ~/.bash_profile or ~/.bashrc:

export PATH=${PATH}:/usr/local/android-sdk-linux_x86/tools

To manage your Android SDK packages and virtual devices, you’ll need to run the android app:

user@ubuntu:~# android

First go to Available Packages and download version 1.6 and 2.2 Android SDK packages. You can also choose to download the documentation, samples, and Google APIs.

Downloading the package may take several minutes. You don’t have to create a virtual device right now if you are planning on installing Appcelerator’s Titanium platform. You can exit the Android app when you’re done.

Desktop Apps

If you’re running Ubuntu Desktop, there are a couple handy apps I install. The first is Google Chrome and can be directly downloaded from the Google Chrome download page.

I find KCachegrind and GHex to be useful:

user@ubuntu:~# sudo apt-get install kcachegrind ghex

Appcelerator Titanium

Titanium is an awesome platform for developing desktop applications for Linux, Mac OS X, and Windows as well as mobile apps for iPhone and Android. We use Titanium Developer to create Titanium projects. Begin by downloading the 64-bit version of Titanium:

user@ubuntu:~# wget -O titanium.tgz http://www.appcelerator.com/download-linux64

There’s also a 32-bit version available at http://www.appcelerator.com/download-linux32.

Next we unpack Titanium Developer and move it to a safe place:

user@ubuntu:~# tar xzf titanium.tgz
user@ubuntu:~# rm titanium.tgz

Next you need to run the installer by double-clicking the Titanium Developer executable. Run the executable and then click the Install button. You can try installing to /opt/titanium, but you might need root privileges.

Next, there are a few issues with outdated libraries, so we simply delete them:

user@ubuntu:~# rm ~/.titanium/runtime/linux/1.0.0/libgobject-2.0.*
user@ubuntu:~# rm ~/.titanium/runtime/linux/1.0.0/libglib-2.0.*
user@ubuntu:~# rm ~/.titanium/runtime/linux/1.0.0/libgio-2.0.*
user@ubuntu:~# rm ~/.titanium/runtime/linux/1.0.0/libgthread-2.0.*

Titanium Developer also complains if /bin/java doesn’t exist, so create a quick link:

user@ubuntu:~# sudo ln -s /usr/bin/java /bin/java

Relaunch Titanium Developer and enter your login credentials. If you don’t have a login, you can get a free account.

After signing in, you may notice there are some updates available in the upper right corner of the window. Click in the box and the updates will be downloaded and installed.

Optionally you can create a launcher icon for your GNOME panel. Don’t forget to escape spaces in the command with a backslash!

Finishing Touches

Lastly, I like to re-arrange my desktop to maximize my coding real estate.

Conclusion

That should get you up and running with a neato dev environment. If you need to run SSL, I wrote a post on Creating Self-Signed Certs on Apache 2.2 and Virtual Hosts and Wildcard SSL Certificates with Apache 2.2.

If you find any typos or additions, please feel free to sound off in the comments!


The Apache HTTP Web Server is a powerful and extensible web server that is the “A” in “LAMP”. One of the neat things about Apache is its API for writing custom modules.

Nick Kew wrote an excellent book called The Apache Modules Book. Anyone who is serious about Apache module development must buy this book.

Modules can be written a number of ways, but the most common way is to use the C programming language. For an C/C++ development IDE, I use KDevelop. It is pretty easy to use once you figure out what you need to do.

It is possible to write modules in C++, but I don’t recommend it if your module’s source can’t be contained in a single source file. There’s all sorts of interesting issues with exported symbols and static function declarations. Another reason to stick with C is pretty much all core modules and examples are written using C. You may give it a try and determine that it works just fine for your project.

Prerequisites

Before you begin, there is a handful of applications and libraries you must have installed:

  • Apache 2
  • KDevelop 3.4
  • GCC (bundled with “build-essential” package)
  • automake
  • autoconf

Creating the Project

Launch KDevelop and select “New Project” from the Project menu. Since we are focusing on using C, select “Simple Hello world program” under the “C” folder. Give your module an “Application name” and specify the location to create the project.

KDevelop New Project

On the next page of the wizard, you must enter your name, but your email address is not required.

KDevelop New Project

The next couple wizard screens ask about version control and source templates. After finishing the wizard, you will be back at the IDE with the new project created.

KDevelop IDE

The Code

Delete all of the source code that the editor created. Next paste the following code which originated from Nick’s version on The Apache Modules Book Companion site.

#include <httpd.h>
#include <http_protocol.h>
#include <http_config.h>

static int helloworld_handler(request_rec* r)
{
	if (!r->handler || strcmp(r->handler, "helloworld"))
		return DECLINED;

	if (r->method_number != M_GET)
		return HTTP_METHOD_NOT_ALLOWED;

	ap_set_content_type(r, "text/html;charset=ascii");
	ap_rputs("<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">n", r);
	ap_rputs("<html><head><title>Hello World!</title></head>;", r);
	ap_rputs("<body><h1>Hello World!</h1></body></html>", r);
	return OK;
}

static void register_hooks(apr_pool_t* pool)
{
	ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA helloworld_module = {
	STANDARD20_MODULE_STUFF,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	register_hooks
};

Configuring the Project

Next we need to reconfigure the build target to create a library instead of a normal program. Right-click the build target and click “Remove”:

Remove build target

When the dialog displays, uncheck the “Also remove from disk” option before clicking “OK”. Now we need to add a new build target. Right-click the “src” folder and select “Add Target”:

Add new build target

From the “Add Target” dialog, change the type to “Libtool Library” and enter the name of the module. Also check the “-avoid-version” and “-module” options.

Add new build target dialog

As soon as the target is created, right-click on it and make sure the checked options saved properly. Right-click on the target again and select “Make Target Active”:

Make target active

Edit the project’s options by right-clicking the “src” folder and selecting “Options”:

Src dropdown menu

Since this is a C project, we want to add the following options to the “CFLAGS” field:

-DLINUX=2 -D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_REENTRANT -pthread
Options - Compiler

From the “Includes” tab, add the following outside include directories:

  • /usr/includes/apr-1.0
  • /usr/includes/apache2
Options - Includes

Reorder the include paths so that “$(all_includes)” is first. Due to a bug or poor design, you must edit the two paths you just added and prepend a “-I”:

Include path prepend -I
Include path prepend -I

Since we deleted the old build target, we need to add the source files to the target by right-clicking the target and selecting “Add Existing Files”:

Adding files to target

From the dialog, drag and drop the files you want to be apart of the target. For this simple example, we only move the “mod_helloworld.c” file.

Adding files to target

Building the Project

We are all set to compile the project. From the “Build” menu, select “Build Active Target”:

Building the active target

If this is the first time you are performing the build, KDevelop will prompt you whether or not you want to run automake. Click the “Run Them” button to continue.

Run automake dialog

When the build is finished, the “Messages” panel will show up and display the build results. If everything went as planned, the output will say the build was successful.

Build results

Deploying the Module

The build process put the shared library file in the following location (assuming debug build):

/path/to/mod_helloworld/debug/src/.libs/libmod_helloworld

We need to install that file in the Apache modules directory which on Ubuntu is:

/usr/lib/apache2/modules

From a terminal, run the following command as root or sudo:

cp /path/to/mod_helloworld/debug/src/.libs/libmod_helloworld /usr/lib/apache2/modules/mod_helloworld.so

Next you’ll need to edit the Apache configuration file. In Ubuntu, the file is located at:

/etc/apache2/apache2.conf

You need to add the LoadModule and <Location> directives so Apache knows when to invoke the module.

LoadModule helloworld_module /usr/lib/apache2/modules/mod_helloworld.so
<Location /helloworld>
    SetHandler helloworld
</Location>

I’ve had spotty luck where to actually insert those settings. After the LogLevel, but before any other LoadModule entries seems to work for me. After you save the changes, restart Apache using the following command as root or sudo:

apache2ctl restart

If your Apache acts funny, try restarting it again.

Testing the Module

The last step is to test the module. Open up your favorite web browser and hit http://localhost/helloworld:

Hello World in Firefox

If everything worked, you should see something similar to the image above.

Where To Go From Here

We have only scratched the surface. The Apache Portable Runtime (APR) provides a ton of functionality that makes developing modules much easier. The Apache Modules Book dives into several topics such as configuration settings, content generators, filters, and database connectivity.

Another great resource is Apache’s own module source code in their Subversion repository: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/.


Security is a always a big concern and there’s no reason your website should go unsecure. You can secure your Apache website with a self-signed SSL certificate. This post describes the process using Apache 2.2 and OpenSSL on a Ubuntu Linux server.

Begin by generating a private key:

$ openssl genrsa -out mycert.key 1024

Next, generating a certificate request and enter the information:

$ openssl req -new -key mycert.key -out mycert.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Next, generate the self-signed certificate. You can specify the number of days the cert is valid for.

$ openssl x509 -req -days 365 -in mycert.csr -signkey mycert.key -out mycert.cert
Signature ok
subject=/C=/ST=/L=/O=/CN=
Getting Private key

You no longer need the .csr request file. Create a folder and move the .key and .cert files into it:

$ sudo mkdir /etc/apache2/ssl
$ sudo mv *.cert /etc/apache2/ssl
$ sudo mv *.key /etc/apache2/ssl
$ sudo chmod 400 /etc/apache2/ssl/*.key

If the cert is protected with a password, by default Apache will prompt for the password when it starts. This can be a problem since you will need to enter the password each time Apache is restarted. We can fix this by having Apache call a program that returns the password.

Create the shell script /etc/apache2/ssl/password.sh and enter the following:

#!/bin/bash
echo “password”;

Next we need to tell Apache to run the script. Apache’s SSL settings are stored in:

/etc/apache2/mods-enabled/ssl.conf

Edit the file and change the SSLPassPhraseDialog to:

SSLPassPhraseDialog exec:/etc/apache2/ssl/password.sh

The last step is to assign the certificate to your Apache site by editing the sites file:

/etc/apache2/sites-enabled/000-default

You’ll need to configure the SSL settings for the site:

<VirtualHost 192.168.1.100:443>
        ...
        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl/mycert.cert
        SSLCertificateKeyFile /etc/apache2/ssl/mycert.key
        ...
</VirtualHost>

Don’t forget to tell Apache to listen on port 443 in the /etc/apache2/ports.conf file. Restart Apache with sudo apache2ctl restart and you should be a little closer to being secure.


Recently I needed to generate a self-signed SSL cert for Apache Tomcat 5.5 on my Ubuntu Linux server. The basic process is to create a Java keystore with the self-signed cert, change Tomcat’s configuration file, and restart the server. Here’s how I did it:

$ keytool -genkey -alias tomcat -keyalg RSA -keystore mycert.jks
Enter keystore password:  changeit
What is your first and last name?
  [Unknown]:  Chris Barber
What is the name of your organizational unit?
  [Unknown]:
What is the name of your organization?
  [Unknown]:  CB1, INC.
What is the name of your City or Locality?
  [Unknown]:  Minneapolis
What is the name of your State or Province?
  [Unknown]:  MN
What is the two-letter country code for this unit?
  [Unknown]:  US
Is CN=Chris Barber, OU=Unknown, O="CB1, INC.", L=Minneapolis, ST=MN, C=US correct?
  [no]:  yes

Enter key password for <tomcat>
        (RETURN if same as keystore password):

By default, Tomcat will assume the password as “changeit”. You can change the password, but then you need to set the keystorePass in Tomcat’s configuration file. Regardless, the password for both the keystore and the cert MUST be the same. Store the keystore in a safe place such as Tomcat’s configuration folder:

/etc/tomcat5.5

Next edit Tomcat’s server configuration file:

/etc/tomcat5.5/server.xml

Locate the SSL connector declaration, uncomment it, and add the keystoreFile path:

<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
<Connector port="8443" maxHttpHeaderSize="8192"
        maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
        enableLookups="false" disableUploadTimeout="true"
        acceptCount="100" scheme="https" secure="true"
        keystoreFile="/etc/tomcat5.5/mycert.jks"
        clientAuth="false" sslProtocol="TLS" />

Save the changes and restart Tomcat:

$ sudo /etc/init.d/tomcat5.5 restart

You should be good to go at this point. Launch your favorite web browser and go to https://localhost:8443.

SSL dialog

Now you are secure and ready to rock.


Host Information Code Snippet

Apr 15, 2007

When you are running a Unix based operating system, you have a neat command called uname that will display information about your computer. If you want it to display everything, then execute it with the -a option.

$ uname -a
Darwin chris-barbers-computer.local 8.9.1 Darwin Kernel Version 8.9.1:
Thu Feb 22 20:55:00 PST 2007; root:xnu-792.18.15~1/RELEASE_I386 i386 i386

This command outputs the following information:

  • Operating system name (-s)
  • Nodename (network name) (-n)
  • Operating system release (-r)
  • Operating system version (-v)
  • Machine hardware name (-m)
  • Generic processor type (-p)

Suppose you want to display that information from within your own application. Whether it’s written in C/C++, PHP, Coldfusion, Java, whatever, you could just execute the uname command six times to parse each bits of information, but that’s not very elegant, especially if you are using writing a C/C++ application.

With a little C code, you can grab this info and dump it in a format that is easy to parse. I’ve actually written it with C++, but you can adapt it to C.

// main.cpp

#include <iostream>
#include <sys/utsname.h>

using namespace std;

int main(void)
{
    utsname u;
    uname(&amp;u);

    cout << "<hostinfo>" << endl;
    cout << "<system-name>" << u.sysname << "</system-name>" << endl;
    cout << "<release>" << u.release << "</release>" << endl;
    cout << "<version>" << u.version << "</version>" << endl;
    cout << "<machine>" << u.machine << "</machine>" << endl;
    cout << "<node-name>" << u.nodename << "</node-name>" << endl;
    cout << "</hostinfo>" << endl;

    return 0;
}

Compile the code with gcc:

$ g++ -o hostinfo main.cpp

And when you run it you get:

$ ./hostinfo
<hostinfo>
<system-name>Darwin</system-name>
<release>8.9.1</release>
<version>Darwin Kernel Version 8.9.1: Thu Feb 22 20:55:00 PST 2007; root:xnu-792.18.15~1/RELEASE_I386</version>
<machine>i386</machine>
<node-name>chris-barbers-computer.local</node-name>
</hostinfo>

That should be easy enough to parse and display where ever you see fit. It doesn’t have to be XML either, you could output it as JSON, tab delimited, or whatever works best. This code works on Mac OS X and Linux.

So, why on Earth would you want to output this? I use it in a C++ application for dump information about the host into the top of the log files. Maybe you have a dozen web application servers and you want a quick way to figure out what kernel version is installed on each. Hopefully someone can come up with something interesting to do with this.