<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>mattwilson.org &#187; mwilson</title>
	<atom:link href="http://mattwilson.org/blog/author/site-admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://mattwilson.org</link>
	<description>The web site of Matthew R. Wilson</description>
	<lastBuildDate>Fri, 12 Jun 2009 05:41:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Zero character password?</title>
		<link>http://mattwilson.org/blog/general/zero-character-password/</link>
		<comments>http://mattwilson.org/blog/general/zero-character-password/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 05:41:10 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://mattwilson.org/?p=51</guid>
		<description><![CDATA[Signing up for my city&#8217;s new online system for paying my water bill. Is it just me or would a zero-character password in this situation be a bad thing?

]]></description>
			<content:encoded><![CDATA[<p>Signing up for my city&#8217;s new online system for paying my water bill. Is it just me or would a zero-character password in this situation be a bad thing?</p>
<p><img src="http://mattwilson.org/wordpress/wp-content/uploads/2009/06/zero-character-password.png" alt="Web form with a password field that says it accepts zero characters for password" title="zero-character-password" width="658" height="573" /></p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/general/zero-character-password/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Automating Oracle Database Creation</title>
		<link>http://mattwilson.org/blog/solaris/automating-oracle-database-creation/</link>
		<comments>http://mattwilson.org/blog/solaris/automating-oracle-database-creation/#comments</comments>
		<pubDate>Fri, 29 May 2009 19:13:47 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[Solaris]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://mattwilson.org/?p=46</guid>
		<description><![CDATA[Why?
I went through some time when, for some reason, I found myself creating lots of new Oracle databases on various systems. These databases were primarily on remote Solaris systems (because, as always, I don&#8217;t believe in running Oracle on Windows!).
The &#8220;obvious&#8221; way to create databases is with the Database Configuration Assistant (DBCA). However, I was [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Why?</strong></p>
<p>I went through some time when, for some reason, I found myself creating lots of new Oracle databases on various systems. These databases were primarily on remote Solaris systems (because, as always, I don&#8217;t believe in running Oracle on Windows!).</p>
<p>The &#8220;obvious&#8221; way to create databases is with the Database Configuration Assistant (DBCA). However, I was unsatisfied with this approach for several reasons:</p>
<p>First, DBCA is a GUI tool and I only connect to the database server with SSH. To use DBCA, I ran a local X server and used X11 forwarding over SSH. Technically effective, but X over anything other than fast local network is barely usable.</p>
<p>Second, I wanted to provision databases that were as &#8220;lean and mean&#8221; as possible. The databases were usually for development or quick testing of different applications, and most applications didn&#8217;t depend on too much Oracle-specific functionality or advanced Oracle features. The databases that come out of DBCA always seemed a bit bloated to me. Furthermore, for applications that do use specific Oracle features (such as the embedded Java runtime, Streams, CDC, etc.), I want to know specifically what needs to be added to the base database to enable the functionality rather than just relying on a install-everything approach.</p>
<p>Finally, I believe anything you need to do server-side to deploy applications should be automated (or at least support the ability to automate the tasks). Creating the databases using the same automated script across my environments is much lower risk than remembering to click all the same settings in a GUI tool when I move through environments. Another aspect of this is that I was finding databases I created using DBCA on different systems tended to have variances in where various directories were created depending on how Oracle was installed. Over time I&#8217;ve come to like a particular scheme for organizing multiple databases on a single server, so by scripting the process I can go to any server that I&#8217;ve created databases on and know exactly where to find everything.</p>
<p>With all of that in mind, I went in search of the deep dark secrets of creating Oracle databases through PL/SQL instead of DBCA. This really boils down to three steps:</p>
<ol>
<li>Prepare to create the database</li>
<li>Create the database</li>
<li>Run post-creation scripts</li>
</ol>
<p>Preparing to create the database really just involves making the directory structure you want and preparing the Oracle parameters file for the database you are going to create.</p>
<p>Then, creating the database is the big SQL statement to actually (duh!) create the database.</p>
<p>And finally, you need to run the SQL scripts to create the initial schema objects. This is also the first good opportunity to migrate the pfile to an spfile.</p>
<p><strong>How?</strong></p>
<p>The approach I took is to write a shell script that creates the directory structure and outputs the SQL and shell scripts to create the individual database (in the database&#8217;s admin directory so that the creation scripts used for a particular database are tucked away in that particular database&#8217;s directory structure for future reference).</p>
<p>The &#8220;creation script creator script&#8221; has some parameters you can change to indicate where Oracle is installed, and then of course the rest of the script builds paths based on how I normally set things up and like to see it organized. Very briefly, Oracle product is installed under /u01 and all of my data files go under /u02/oradata/<i>database</i> and recovery files go under /u02/orarecovery/<i>database</i>. I throw two control files under /u02 and stash one under /u01 on the theory that /u01 and /u02 should be different LUNs. Any other administrative stuff goes under /u01/app/oracle/admin/<i>database</i>.</p>
<p>The SID of the database you want to create is the only command-line parameter to the script. If you want anything else to be different, you need to edit the script ahead of time. If you don&#8217;t change the template for database creation and parameter file creation in the script, you&#8217;ll end up with a character set of AL32UTF8 and the database configured to use about 512MB of RAM on the system.</p>
<p>So without further ado, here&#8217;s the script I use:</p>
<pre>
#!/bin/sh

DB_SID=$1
DB_DOMAIN=mattwilson.org

ORACLE_BASE=/u01/app/oracle
ORACLE_HOME=${ORACLE_BASE}/product/10.2.0/db_1
ORACLE_ADMIN=${ORACLE_BASE}/admin/${DB_SID}

DATA_PRIMARY=/u02/oradata/${DB_SID}
DATA_SECONDARY=/u01/app/oracle/oradata/${DB_SID}
DATA_RECOVERY=/u02/orarecovery

# Create admin directories
mkdir -p ${ORACLE_ADMIN}
for x in adump bdump cdump udump scripts
do
        mkdir ${ORACLE_ADMIN}/${x}
done

# Create data directories
mkdir -p $DATA_PRIMARY
mkdir -p $DATA_SECONDARY
mkdir -p $DATA_RECOVERY

# Create init.ora file for instance
cat - &gt; ${ORACLE_ADMIN}/scripts/init.ora &lt;&lt; __EOF__
db_name = $DB_SID
db_domain = $DB_DOMAIN

db_block_size = 8192
undo_management = auto
undo_tablespace = undotbs1

control_files = (${DATA_PRIMARY}/${DB_SID}_ctrl_01.ctl,
                 ${DATA_PRIMARY}/${DB_SID}_ctrl_02.ctl,
                 ${DATA_SECONDARY}/${DB_SID}_ctrl_03.ctl)

background_dump_dest = ${ORACLE_ADMIN}/bdump
core_dump_dest = ${ORACLE_ADMIN}/cdump
user_dump_dest = ${ORACLE_ADMIN}/udump
audit_file_dest = ${ORACLE_ADMIN}/adump

db_recovery_file_dest = $DATA_RECOVERY
db_recovery_file_dest_size = 2147483648

sga_target = 402653184
__EOF__

# Create database creation script
cat - &gt; ${ORACLE_ADMIN}/scripts/create.sql &lt;&lt; __EOF__
connect / as sysdba
set echo on
spool ${ORACLE_ADMIN}/scripts/create.log

startup nomount pfile=${ORACLE_ADMIN}/scripts/init.ora;

CREATE DATABASE "${DB_SID}"
MAXINSTANCES 1
MAXLOGHISTORY 1
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
CHARACTER SET AL32UTF8
NATIONAL CHARACTER SET UTF8
DATAFILE '${DATA_PRIMARY}/system01.dbf'
        SIZE 128M
        AUTOEXTEND ON
        NEXT 128M MAXSIZE UNLIMITED
        EXTENT MANAGEMENT LOCAL
SYSAUX DATAFILE '${DATA_PRIMARY}/sysaux01.dbf'
        SIZE 128M
        AUTOEXTEND ON
        NEXT 128M MAXSIZE UNLIMITED
UNDO TABLESPACE "UNDOTBS1" DATAFILE '${DATA_PRIMARY}/undotbs01.dbf'
        SIZE 128M
        AUTOEXTEND ON
        NEXT 16M MAXSIZE UNLIMITED
DEFAULT TEMPORARY TABLESPACE TEMP
        TEMPFILE '${DATA_PRIMARY}/temp01.dbf'
        SIZE 32M
        AUTOEXTEND ON
        NEXT 8M MAXSIZE UNLIMITED
DEFAULT TABLESPACE USERS DATAFILE '${DATA_PRIMARY}/users01.dbf'
        SIZE 64M
        AUTOEXTEND ON
        NEXT 64M MAXSIZE UNLIMITED
LOGFILE GROUP 1 ('${DATA_PRIMARY}/redo01.log') SIZE 64M,
        GROUP 2 ('${DATA_PRIMARY}/redo02.log') SIZE 64M,
        GROUP 3 ('${DATA_PRIMARY}/redo03.log') SIZE 64M;

@?/rdbms/admin/catalog.sql
@?/rdbms/admin/catproc.sql

connect system/manager
@?/sqlplus/admin/pupbld

connect / as sysdba
shutdown immediate;
connect / as sysdba
startup mount pfile=${ORACLE_ADMIN}/scripts/init.ora;
alter database archivelog;
alter database open;
create spfile='${ORACLE_HOME}/dbs/spfile${DB_SID}.ora'
        from pfile='${ORACLE_ADMIN}/scripts/init.ora';
shutdown immediate;
startup;

execute utl_recomp.recomp_serial();

exit;
__EOF__

# Create run script
cat - &gt; ${ORACLE_ADMIN}/scripts/create.sh &lt;&lt; __EOF__
#!/bin/sh
ORACLE_HOME=$ORACLE_HOME
ORACLE_SID=$DB_SID
export ORACLE_HOME ORACLE_SID
\$ORACLE_HOME/bin/sqlplus /nolog @create
__EOF__

chmod +x ${ORACLE_ADMIN}/scripts/create.sh

# All done!
echo -------------------------------------------------------------
echo Ready to run create database script.
echo Go to ${ORACLE_ADMIN}/scripts
echo Then run create.sh in that directory.
echo -------------------------------------------------------------
</pre>
<p>Just save that as something like <code>create-setup-script.sh</code>, make it executable, and you&#8217;re all set!</p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/solaris/automating-oracle-database-creation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IT Mergers and Acquisitions</title>
		<link>http://mattwilson.org/blog/technology/it-mergers-and-acquisitions/</link>
		<comments>http://mattwilson.org/blog/technology/it-mergers-and-acquisitions/#comments</comments>
		<pubDate>Thu, 30 Apr 2009 04:04:34 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://mattwilson.org/?p=43</guid>
		<description><![CDATA[My business unit was recently acquired by another company, along with all of us employees. So now I work for a new company who is going to keep us all in Portland to establish a west-coast office (they&#8217;re back east).
The upshot of all of this is that the IT guys at my old company are [...]]]></description>
			<content:encoded><![CDATA[<p>My business unit was recently acquired by another company, along with all of us employees. So now I work for a new company who is going to keep us all in Portland to establish a west-coast office (they&#8217;re back east).</p>
<p>The upshot of all of this is that the IT guys at my old company are all staying with the old company, so the west coast office of my new company has a long list of IT infrastructure and support needs, but doesn&#8217;t have any local IT staff. Thus, I now have two full time jobs! Keep up with my normal customer consulting duties as well as make the IT transition happen.</p>
<p>Truth be told, I am having fun. It&#8217;s been several years since I last unboxed and configured new Cisco gear, set up new file and print and directory servers, got into wiring closets to patch drops, etc. This particular case is interesting because it&#8217;s not just an outright merger of two companies&#8211;there are really three parties involved since it&#8217;s just the sale of a business unit: Company A, the group of people and resources that are moving from Company A to Company B, and Company B. At the moment the group in the middle is very dependent on IT resources at Company A, some that are clearly only useful to the business unit and can move as-is, and some that are shared so can&#8217;t just move over with the people. And we&#8217;re also trying to involve people in Company B&#8217;s operations as soon as possible, so we&#8217;re all accessing resources in both networks as the disentangling and migration is happening.</p>
<p>At heart I&#8217;m really a systems guy&#8211;server operating systems, networks, the hardware it all runs on, etc. (but please, leave the client desktop hardware and software to someone else!)&#8211;so it&#8217;s nice to get back into it for a little while with real production systems instead of my little Solaris test lab at home. I&#8217;m lucky that when I was an intern at Intel we had a lab with a few Cisco Catalyst 6500-series switches and Cisco 7000-series routers, and before they actually needed to be deployed the network guy let me and some other interns loose to play with them and learn all about how Cisco gear works. If not for that, I probably would be totally lost getting our new layer 3 core switch up and running, but surprisingly all of my IOS knowledge tucked away in long term memory has bubbled back up to the top of the stack pretty quickly. Coupled with Eric&#8217;s <a href="http://www.bitplumber.net/2009/03/cisco-router-switch-standard-configuration-checklist/">excellent checklist for new Cisco switch and router setup</a>, I have our new network ready to start migrating services and eventually cut off all connectivity to the old company.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/technology/it-mergers-and-acquisitions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>If you have a Mac, go buy the MacHeist 3 Bundle!</title>
		<link>http://mattwilson.org/blog/general/if-you-have-a-mac-go-buy-the-macheist-3-bundle/</link>
		<comments>http://mattwilson.org/blog/general/if-you-have-a-mac-go-buy-the-macheist-3-bundle/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 00:01:23 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://mattwilson.org/?p=38</guid>
		<description><![CDATA[If you have a Mac, go buy the MacHeist 3 Bundle!
Right now it has ten applications, worth $621.75 if purchased separately, for only $39. If enough people buy it, we will all get additional applications that would take the total value up to $950.70. Even if you just want one or two applications in the [...]]]></description>
			<content:encoded><![CDATA[<p><strong>If you have a Mac, <a href="http://www.macheist.com/bundle/u/311878/">go buy the MacHeist 3 Bundle</a>!</strong></p>
<p>Right now <strong>it has ten applications, worth $621.75 if purchased separately, for only $39</strong>. If enough people buy it, we will all get additional applications that would take the total value up to $950.70. Even if you just want one or two applications in the bundle, it&#8217;s likely that the price of the apps you are interested in will add up to more than the $39 bundle price.</p>
<p><b>25% of your bundle purchase goes to charity</b>, so you can 1) get some cool Mac apps, 2) help some charities, and 3) help unlock the additional applications (if you buy and the additional apps later get unlocked, you get the newly unlocked apps&#8211;you don&#8217;t have to re-buy, for example).</p>
<p>I&#8217;ve been playing around with a few of the apps already. The Acorn image editor is nice because most of the time I&#8217;m just doing really simple image edits and by the time PhotoShop or The Gimp (which I can&#8217;t really stand) start up, I could have already opened up the image and made the change in Acorn.</p>
<p>The game, World of Goo, is fun. I&#8217;m not a big game person but this one&#8217;s been able to hold my interest thus far. It&#8217;s really well-done and is physics-based.</p>
<p>Kinemac is impressive in that it&#8217;s a $300 app in a $39 bundle. I&#8217;ve never been all that creative so I&#8217;m not sure I&#8217;ll ever do anything really neat with it, but it allows you to pretty simply build 3D animations for presentations or videos.</p>
<p>WireTap Studio is nice because it can record sound from any application on the Mac. So if you&#8217;re streaming your local public radio station in iTunes and want to record a show, you can use WireTap Studio to do it.</p>
<p>If you&#8217;re into cooking, Sous Chef seems like a neat recipe database tool.</p>
<p>And if we get more people to buy the bundle, we&#8217;ll all get BoinxTV, a $199 live video production application, and then when the next milestone hits we&#8217;ll get The Hit List and Espresso, a neat task management and HTML/CSS/JavaScript editing suite.</p>
<p><strong>So <a href="http://www.macheist.com/bundle/u/311878/">go buy the bundle</a>, already!</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/general/if-you-have-a-mac-go-buy-the-macheist-3-bundle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apple, why do you do everything you can to keep me from buying another Mac?</title>
		<link>http://mattwilson.org/blog/technology/apple-why-do-your-machines-suck/</link>
		<comments>http://mattwilson.org/blog/technology/apple-why-do-your-machines-suck/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 20:53:30 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://mattwilson.org/?p=31</guid>
		<description><![CDATA[I&#8217;ve had a 20&#8243; Core Duo iMac for a while now. It&#8217;s been a good machine, Mac OS X is decent to work with for what I do at home, the display looks nice&#8230; really no major complaints except: it only supports 2GB of RAM.
Yeah. This is a machine purchased in June 2006, and it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had a 20&#8243; Core Duo iMac for a while now. It&#8217;s been a good machine, Mac OS X is decent to work with for what I do at home, the display looks nice&#8230; really no major complaints except: <em>it only supports 2GB of RAM</em>.</p>
<p>Yeah. This is a machine purchased in June 2006, and it&#8217;s only expandable to 2GB. All of my PCs that are still around, which were purchased before the iMac, can hold at least 4GB of RAM. And they were all less expensive than the iMac.</p>
<p>Anyway, this iMac could easily be just fine for me for another couple years if only it could hold more RAM. 2GB just isn&#8217;t enough, and there&#8217;s something about the way Mac OS handles memory management that is horribly bad (this is something I noticed both with this iMac and my original Mac Mini before it). Both of my machines at work, one running Windows XP and one running Linux, also only have 2GB of RAM but seem to be able to handle much more of a workload before performance starts degrading.</p>
<p>In any case, 2GB of RAM just isn&#8217;t enough for a machine running Mac OS X. So I&#8217;m thinking, you know, I shouldn&#8217;t have to send loads of cash to Apple for a whole new machine just because they chose ridiculously memory-limited motherboards, but the performance of this machine is just killing me sometimes. My options with this machine are limited, so&#8230;</p>
<p>I head over to Apple&#8217;s site to look at the specs on the latest iMacs. And guess what: they&#8217;re already setting me up to have to buy another one in a couple more years. The whole iMac lineup is limited to 4GB of RAM! This from a company that so loudly boasts about the 64-bitness of their operating systems. It&#8217;s like they don&#8217;t expect anyone to actually run apps on their computers. I don&#8217;t even have high demands: I just want to be able to keep my web browser, iTunes, NetBeans, and a VMWare VM with only 384MB of RAM allocated to it running. If my 2GB machine can&#8217;t even handle that (it can&#8217;t), how long do I think a machine with only 4GB of RAM will last me? I hate that the <em>only</em> reason this computer won&#8217;t last me several more years is because Apple skimped out on how much RAM it can hold.</p>
<p>I can&#8217;t bring myself to buy a computer in 2009 that can only hold 4GB of RAM. So looking for other options, I think, &#8220;well, maybe I need to go to their &#8216;pro&#8217; line of systems,&#8221; even though consumers deserve more than 4GB of RAM too without buying a new computer again in a couple years.</p>
<p>First up: MacBook Pro. Ignoring that it&#8217;s too expensive, I know a lot of people who use these as their main machines with a monitor and keyboard plugged in at the desk. Not my ideal scenario, but luckily I don&#8217;t need to worry about it: even on a supposedly &#8220;professional&#8221; machine, the 15&#8243; MacBook Pro is limited to 4GB of RAM. So we can write that off as a very expensive short-term toy like the iMac.</p>
<p>That just leaves the Mac Pro. The starting price of this puppy is $2,800, and that doesn&#8217;t even get you a monitor like the iMacs or MacBooks. Sure, it holds as much RAM as you want to throw at it, but seriously, I&#8217;m not going to pay $2,800 for a computer.</p>
<p>For the price of an iMac (I&#8217;d probably go with the $1,800 one), you really should be able to expand to more than 4GB of RAM. To ask me to jump from $1,800 to $3,400 (remember, I need to buy a monitor with that Mac Pro) just to satisfy the requirement that I&#8217;m able to run more than a couple of applications at a time is ludicrous.</p>
<p>Just for comparison, I priced out a system that is much faster, can hold much more RAM than the iMac, comes with a 24&#8243; display, etc. at Dell and the grand total is&#8230; $1,200.</p>
<p>So what do I do? I won&#8217;t run Windows at home, of course, but I have no objections to using Linux for my main home system, which I was doing before I got back into Macs. I could build a lightning fast box for much less than even the iMac. But I&#8217;d rather just stick with a Mac if only it could hold more RAM.</p>
<p><strong>Listen up, Apple</strong>: I <em>want</em> to give you my money. Just not $3,400 of it! You&#8217;re making it so hard for me to be your customer. Can&#8217;t you at least <em>try</em> to keep up technical parity in your consumer line with the competition?</p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/technology/apple-why-do-your-machines-suck/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using OpenDS for DB2 Authentication</title>
		<link>http://mattwilson.org/blog/solaris/using-opends-for-db2-authentication/</link>
		<comments>http://mattwilson.org/blog/solaris/using-opends-for-db2-authentication/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 00:21:53 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[Solaris]]></category>
		<category><![CDATA[db2]]></category>
		<category><![CDATA[ldap]]></category>

		<guid isPermaLink="false">http://mattwilson.org/?p=27</guid>
		<description><![CDATA[As I mentioned in the previous article about intalling DB2, the DB2 server uses operating system users for authentication. That means that if you want to give Bob Smith access to a database on the server, you need to create a Unix account for him. I like to keep application authentication separated from operating system [...]]]></description>
			<content:encoded><![CDATA[<p>As I mentioned in the previous article about intalling DB2, the DB2 server uses operating system users for authentication. That means that if you want to give Bob Smith access to a database on the server, you need to create a Unix account for him. I like to keep application authentication separated from operating system authentication in most cases, so I didn&#8217;t like the way DB2 was working. Luckily, DB2 ships with LDAP authentication plugins to solve this problem.</p>
<p>With LDAP, I can keep all of my user authentication and group membership information in an LDAP directory. If you already have a directory set up, such as Microsoft Active Directory, Novell eDirectory, or an OpenLDAP directory that is in use for authentication, then you can just point at that.</p>
<p>In this case, though, I&#8217;m going to create a directory specifically for my DB2 instance. I&#8217;ll use <a href="http://www.opends.org/">OpenDS</a>, an open source Java LDAP server.</p>
<p>After downloading OpenDS, I&#8217;ll put unzip it in <code>/opt</code>, resulting in my installation being in <code>/opt/OpenDS-1.0.0</code>:</p>
<pre>root@lab01v04# <strong>cd /opt</strong>
root@lab01v04# <strong>unzip /root/OpenDS-1.0.0.zip</strong>
Archive:  /root/OpenDS-1.0.0.zip
   creating: OpenDS-1.0.0/
   creating: OpenDS-1.0.0/QuickSetup.app/
   creating: OpenDS-1.0.0/QuickSetup.app/Contents/
   creating: OpenDS-1.0.0/QuickSetup.app/Contents/MacOS/
   creating: OpenDS-1.0.0/QuickSetup.app/Contents/Resources/
   creating: OpenDS-1.0.0/QuickSetup.app/Contents/Resources/Java/
   creating: OpenDS-1.0.0/Uninstall.app/
 [...]
  inflating: OpenDS-1.0.0/setup
  inflating: OpenDS-1.0.0/uninstall
  inflating: OpenDS-1.0.0/upgrade
root@lab01v04#</pre>
<p>I&#8217;m going to create a new user, <code>opends</code>, under which to run the directory server, then change ownership of the installation directory to the new user:</p>
<pre>root@lab01v04# <strong>cd /opt/OpenDS-1.0.0/</strong>
root@lab01v04# <strong>groupadd opends</strong>
root@lab01v04# <strong>useradd -g opends -d /export/home/opends -m \ </strong>
> <strong>-s /usr/bin/ksh93 opends</strong>
64 blocks
root@lab01v04# <strong>passwd opends</strong>
New Password: <strong>...password...</strong>
Re-enter new Password: <strong>...password...</strong>
passwd: password successfully changed for opends
root@lab01v04# <strong>chown -R opends:opends /opt/OpenDS-1.0.0/</strong></pre>
<p>Now I can perform the rest of the steps as the new users. After logging in as the <code>opends</code> user, I change to the OpenDS directory and start the setup program. This will allow me to set up the basics of the directory service.</p>
<p>I&#8217;ll give you the full conversation below. In essence, I&#8217;m accepting most of the defaults. I&#8217;ll be running on port 1389, so I can start the server as a non-root user. The base DN for my directory will be <code>dc=lab,dc=mattwilson,dc=org</code> (&#8221;dc&#8221; is short for &#8220;domain component,&#8221; so this is equivalent to a DNS name of lab.mattwilson.org).</p>
<pre>opends@lab01v04$ <strong>cd /opt/OpenDS-1.0.0/</strong>
opends@lab01v04$ <strong>./setup --cli</strong>

OpenDS Directory Server 1.0.0
Please wait while the setup program initializes...

What would you like to use as the initial root user DN for the Directory
Server? [cn=Directory Manager]:
Please provide the password to use for the initial root user:
Please re-enter the password for confirmation:

On which port would you like the Directory Server to accept connections from
LDAP clients? [1389]:

What do you wish to use as the base DN for the directory data?
[dc=example,dc=com]: <strong>dc=lab,dc=mattwilson,dc=org</strong>
Options for populating the database:

    1)  Only create the base entry
    2)  Leave the database empty
    3)  Import data from an LDIF file
    4)  Load automatically-generated sample data

Enter choice [1]: <strong>1</strong>

Do you want to enable SSL? (yes / no) [no]: <strong>no</strong>

Do you want to enable Start TLS? (yes / no) [no]: <strong>no</strong>

Do you want to start the server when the configuration is completed? (yes /
no) [yes]: <strong>yes</strong>

Setup Summary
=============
LDAP Listener Port: 1389
LDAP Secure Access: disabled
Root User DN:       cn=Directory Manager
Directory Data:     Create New Base DN dc=lab,dc=mattwilson,dc=org.
Base DN Data: Only Create Base Entry (dc=lab,dc=mattwilson,dc=org)

Start Server when the configuration is completed

What would you like to do?

    1)  Setup the server with the parameters above
    2)  Provide the setup parameters again
    3)  Cancel the setup

Enter choice [1]: <strong>1</strong>

Configuring Directory Server ..... Done.
Creating Base Entry dc=lab,dc=mattwilson,dc=org ..... Done.
Starting Directory Server ........ Done.

See /var/tmp/opends-setup-23950.log for a detailed log of this operation.

To see basic server configuration status and configuration you can launch
/opt/OpenDS-1.0.0/bin/status
opends@lab01v04$</pre>
<p>And with that, we have a directory server running! I&#8217;m going to update my path to make it easier to use the various LDAP utilities:</p>
<pre>opends@lab01v04$ <strong>PATH=/opt/OpenDS-1.0.0/bin:$PATH</strong></pre>
<p>Now that the directory server is running, we need to create entries in it to support authentication. At the highest level, we&#8217;re going to create to &#8220;organizational units,&#8221; one for users and one for groups. To create LDAP entries, we use LDIF files. The LDIF file with the &#8220;ou&#8221; definitions, which we&#8217;ll call <code>container-setup.ldif</code>, contains the following:</p>
<pre># users
dn: ou=users,dc=lab,dc=mattwilson,dc=org
objectClass: organizationalUnit
ou: users

# groups
dn: ou=groups,dc=lab,dc=mattwilson,dc=org
objectClass: organizationalUnit
ou: groups</pre>
<p>To actually import these records into the directory, we&#8217;ll use the <code>ldapmodify</code> command. I&#8217;m connecting as the directory manager to the LDAP server running on port 1389, and creating records in the <code>container-setup.ldif</code> file:</p>
<pre>opends@lab01v04$ <strong>ldapmodify -a -D "cn=Directory Manager" -p 1389 \</strong>
> <strong>-c -f container-setup.ldif</strong>
Password for user 'cn=Directory Manager':
Processing ADD request for ou=users,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN ou=users,dc=lab,dc=mattwilson,dc=org
Processing ADD request for ou=groups,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN ou=groups,dc=lab,dc=mattwilson,dc=org</pre>
<p>Next we need to create the users. I need to create users to represent the two operating system users that DB2 is already dependent on: <code>db2inst1</code> and <code>db2fenc1</code>. Additionally, I will create the <code>bsmith</code> user. When we are all done, we should be able to connect as <code>bsmith</code> even though there is no equivalent Solaris user. DB2 should allow the login based on the LDAP entry.</p>
<p>The following user definitions are in <code>user-setup.ldif</code>:</p>
<pre># db2inst1 user -- required to match instance owner
dn: uid=db2inst1,ou=users,dc=lab,dc=mattwilson,dc=org
objectClass: inetOrgPerson
uid: db2inst1
cn: DB2 Instance 1 Owner
sn: DB2 Instance 1 Owner

# db2fenc1 user -- required to match instance fenced user
dn: uid=db2fenc1,ou=users,dc=lab,dc=mattwilson,dc=org
objectClass: top
objectClass: inetOrgPerson
uid: db2fenc1
cn: DB2 Fenced User 1
sn: DB2 Fenced User 1

# "Bob Smith" user
dn: uid=bsmith,ou=users,dc=lab,dc=mattwilson,dc=org
objectClass: inetOrgPerson
uid: bsmith
cn: Bob Smith
sn: Smith
givenName: Bob</pre>
<p>Now we&#8217;ll use the <code>ldapmodify</code> tool again to create these entries:</p>
<pre>opends@lab01v04$ <strong>ldapmodify -a -D "cn=Directory Manager" -p 1389 \</strong>
> <strong>-c -f user-setup.ldif</strong>
Password for user 'cn=Directory Manager':
Processing ADD request for uid=db2inst1,ou=users,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN uid=db2inst1,ou=users,dc=lab,dc=mattwilson,dc=or
g
Processing ADD request for uid=db2fenc1,ou=users,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN uid=db2fenc1,ou=users,dc=lab,dc=mattwilson,dc=or
g
Processing ADD request for uid=bsmith,ou=users,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN uid=bsmith,ou=users,dc=lab,dc=mattwilson,dc=org</pre>
<p>And now we&#8217;ll define the groups. Again, we need to create the current operating system groups that DB2 is using, <code>db2iadm1</code> and <code>db2fadm1</code>. We also need to create the other security groups that DB2 uses by default, <code>SYSADM</code>, <code>SYSMAINT</code>, <code>SYSCTRL</code>, and <code>SYSMON</code>. Note also how we&#8217;re adding members to these groups.</p>
<p>The contents of the <code>group-setup.ldif</code> file are:</p>
<pre># db2iadm1 group
dn: cn=db2iadm1,ou=groups,dc=lab,dc=mattwilson,dc=org
objectClass: top
objectClass: groupOfEntries
cn: db2iadm1
member: uid=db2inst1,ou=users,dc=lab,dc=mattwilson,dc=org

# db2fadm1 group
dn: cn=db2fadm1,ou=groups,dc=lab,dc=mattwilson,dc=org
objectClass: top
objectClass: groupOfEntries
cn: db2fadm1
member: uid=db2fenc1,ou=users,dc=lab,dc=mattwilson,dc=org

# SYSADM group
dn: cn=SYSADM,ou=groups,dc=lab,dc=mattwilson,dc=org
objectClass: groupOfEntries
cn: SYSADM
ou: Groups
member: uid=db2inst1,ou=users,dc=lab,dc=mattwilson,dc=org

# SYSMAINT group
dn: cn=SYSMAINT,ou=groups,dc=lab,dc=mattwilson,dc=org
objectClass: groupOfEntries
cn: SYSMAINT
ou: Groups
member: uid=db2inst1,ou=users,dc=lab,dc=mattwilson,dc=org

# SYSCTRL group
dn: cn=SYSCTRL,ou=groups,dc=lab,dc=mattwilson,dc=org
objectClass: groupOfEntries
cn: SYSCTRL
ou: Groups
member: uid=db2inst1,ou=users,dc=lab,dc=mattwilson,dc=org

# SYSMON group
dn: cn=SYSMON,ou=groups,dc=lab,dc=mattwilson,dc=org
objectClass: groupOfEntries
cn: SYSMON
ou: Groups
member: uid=db2inst1,ou=users,dc=lab,dc=mattwilson,dc=org</pre>
<p>And finally, create these records with <code>ldapmodify</code>:</p>
<pre>opends@lab01v04$ <strong>ldapmodify -a -D "cn=Directory Manager" -p 1389 \</strong>
> <strong>-c -f group-setup.ldif</strong>
tPassword for user 'cn=Directory Manager':
Processing ADD request for cn=db2iadm1,ou=groups,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN cn=db2iadm1,ou=groups,dc=lab,dc=mattwilson,dc=or
g
Processing ADD request for cn=db2fadm1,ou=groups,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN cn=db2fadm1,ou=groups,dc=lab,dc=mattwilson,dc=or
g
Processing ADD request for cn=SYSADM,ou=groups,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN cn=SYSADM,ou=groups,dc=lab,dc=mattwilson,dc=org
Processing ADD request for cn=SYSMAINT,ou=groups,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN cn=SYSMAINT,ou=groups,dc=lab,dc=mattwilson,dc=or
g
Processing ADD request for cn=SYSCTRL,ou=groups,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN cn=SYSCTRL,ou=groups,dc=lab,dc=mattwilson,dc=org
Processing ADD request for cn=SYSMON,ou=groups,dc=lab,dc=mattwilson,dc=org
ADD operation successful for DN cn=SYSMON,ou=groups,dc=lab,dc=mattwilson,dc=org</pre>
<p>The last thing we need to do is assign passwords to the users. OpenDS includes a utility, <code>ldappasswordmodify</code>, to do just that (&#8221;adminPassword&#8221; is the password I set during setup of OpenDS, and &#8220;userPassword&#8221; is what I want to set the user&#8217;s password to):</p>
<pre>opends@lab01v04$ <strong>ldappasswordmodify -p 1389 -D "cn=Directory Manager" \</strong>
> <strong>--authzID "dn:uid=db2inst1,ou=users,dc=lab,dc=mattwilson,dc=org" \</strong>
> <strong>-w adminPassword -n userPassword</strong>
The LDAP password modify operation was successful

opends@lab01v04$ <strong>ldappasswordmodify -p 1389 -D "cn=Directory Manager" \</strong>
> <strong>--authzID "dn:uid=db2fenc1,ou=users,dc=lab,dc=mattwilson,dc=org" \</strong>
> <strong>-w adminPassword -n userPassword</strong>
The LDAP password modify operation was successful

opends@lab01v04$ <strong>ldappasswordmodify -p 1389 -D "cn=Directory Manager" \</strong>
> <strong>--authzID "dn:uid=bsmith,ou=users,dc=lab,dc=mattwilson,dc=org" \</strong>
> <strong>-w adminPassword -n userPassword</strong>
The LDAP password modify operation was successful</pre>
<p>And with that, our LDAP directory is created and populated with users and groups, and the users have passwords so they should be able to log in.</p>
<p>After setting up the directory, we need to configure DB2 to use the LDAP plugins. These require some configuration to tell them how to connect to the LDAP user, and how to find users and groups. The configuration is stored in the file <code>sqllib/cfg/IBMLDAPSecurity.ini</code>, relative to the instance root. In my case, that&#8217;s <code>/export/home/db2inst1/sqllib/cfg/IBMLDAPSecurity.ini</code>.</p>
<p>For the setup we created above, I&#8217;ve entered the following configuration in the file:</p>
<pre>LDAP_HOST = localhost:1389
USER_OBJECTCLASS = inetOrgPerson
USERID_ATTRIBUTE = uid
AUTHID_ATTRIBUTE = uid
USER_BASEDN = ou=users,dc=lab,dc=mattwilson,dc=org
GROUP_OBJECTCLASS = groupOfEntries
GROUP_BASEDN = ou=groups,dc=lab,dc=mattwilson,dc=org
GROUPNAME_ATTRIBUTE = cn
GROUP_LOOKUP_METHOD = SEARCH_BY_DN
GROUP_LOOKUP_ATTRIBUTE = member</pre>
<p>With the configuration in place, we&#8217;ll change the DB2 instance configuration to use the LDAP plugins:</p>
<pre>db2inst1@lab01v04$ <strong>db2 update dbm cfg using srvcon_pw_plugin \</strong>
> <strong>IBMLDAPauthserver</strong>
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
successfully.

db2inst1@lab01v04$ <strong>db2 update dbm cfg using clnt_pw_plugin \</strong>
> <strong>IBMLDAPauthclient</strong>
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
successfully.

db2inst1@lab01v04$ <strong>db2 update dbm cfg using group_plugin IBMLDAPgroups</strong>
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
successfully.</pre>
<p>For the changes to take effect, we need to restart the instance:</p>
<pre>db2inst1@lab01v04$ <strong>db2 terminate</strong>
DB20000I  The TERMINATE command completed successfully.
db2inst1@lab01v04$ <strong>db2stop</strong>
SQL1064N  DB2STOP processing was successful.
db2inst1@lab01v04$ <strong>db2start</strong>
SQL1063N  DB2START processing was successful.</pre>
<p>Now to test it: we&#8217;ll try to connect to the database we created in the last article, <code>mydb</code>, as the user <code>bsmith</code>. Since there&#8217;s no user on my Solaris system named <code>bsmith</code>, this wouldn&#8217;t have worked before the LDAP configuration. If we&#8217;re able to connect, it means DB2 is now using our LDAP directory for authentication:</p>
<pre>db2inst1@lab01v04$ <strong>db2</strong>
(c) Copyright IBM Corporation 1993,2007
Command Line Processor for DB2 Client 9.5.1

You can issue database manager commands and SQL statements from the command
prompt. For example:
    db2 =&gt; connect to sample
    db2 =&gt; bind sample.bnd

For general help, type: ?.
For command help, type: ? command, where command can be
the first few keywords of a database manager command. For example:
 ? CATALOG DATABASE for help on the CATALOG DATABASE command
 ? CATALOG          for help on all of the CATALOG commands.

To exit db2 interactive mode, type QUIT at the command prompt. Outside
interactive mode, all commands must be prefixed with 'db2'.
To list the current command option settings, type LIST COMMAND OPTIONS.

For more detailed help, refer to the Online Reference Manual.

db2 =&gt; <strong>connect to mydb user bsmith</strong>
Enter current password for bsmith:

   Database Connection Information

 Database server        = DB2/SUNX8664 9.5.1
 SQL authorization ID   = BSMITH
 Local database alias   = MYDB

db2 =&gt;</pre>
<p>Success! You can see that we are logged in as <code>bsmith</code>. You can try other experiments to make sure this is really working&mdash;enter an incorrect password or an invalid username that isn&#8217;t defined in LDAP, for example, and the server will correctly reject the connection.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/solaris/using-opends-for-db2-authentication/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Installing DB2 on OpenSolaris</title>
		<link>http://mattwilson.org/blog/solaris/installing-db2-on-opensolaris/</link>
		<comments>http://mattwilson.org/blog/solaris/installing-db2-on-opensolaris/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 07:41:30 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[Solaris]]></category>
		<category><![CDATA[db2]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[opensolaris]]></category>

		<guid isPermaLink="false">http://mattwilson.org/?p=24</guid>
		<description><![CDATA[Why?
The other day, Ben Rockwell mentioned on his blog that the free edition of DB2 was available for 64-bit Solaris on x86 systems. I like learning about new server software, and databases in particular, so I figured I&#8217;d take a look at it.
The majority of my relational database administration experience has been with Oracle, Microsoft [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Why?</strong></p>
<p>The other day, <a href="http://www.cuddletech.com/blog/pivot/entry.php?id=1005">Ben Rockwell mentioned on his blog</a> that the <a href="http://www-01.ibm.com/software/data/db2/express/">free edition of DB2</a> was available for 64-bit Solaris on x86 systems. I like learning about new server software, and databases in particular, so I figured I&#8217;d take a look at it.</p>
<p>The majority of my relational database administration experience has been with Oracle, Microsoft SQL Server, MySQL, and PostgreSQL. Of that mix, I was expecting DB2 to be much more like Oracle than the others&mdash;specifically, complex installation (if you don&#8217;t want to use GUI tools that produce bloated default databases with every option under the sun enabled) and annoying command line tools (it&#8217;s 2009 and <code>sqlplus</code> doesn&#8217;t have any sort of command completion or press-the-up-arrow-to-get-to-previous-command support). I was pleasantly surprised in how easy it was for a mere mortal to install and create a database entirely from the command line. The interactive tools, though, seem about as brain-dead as <code>sqlplus</code>, though, so my guess was partially right (although perhaps slight favor to DB2 for its help system within its interactive command processor, but ding it back down for requiring an explicit line continuation character&#8230;but I&#8217;m getting way ahead of myself, we haven&#8217;t even installed it yet!).</p>
<p>So enough philosophy, let&#8217;s get down to business. Please remember that there&#8217;s a &#8220;GUI setup wizard&#8221; that can do all of this in just a few clicks (for Solaris as well as the other supported platforms, Linux and Windows). But where&#8217;s the fun in that? I like to know <em>exactly</em> what&#8217;s going on in my systems, and I&#8217;ve found that doing things the manual way is a much better way to learn how to support a system in the long run. Also, I like to be able to script most server setup tasks for reliable repeatability. If you&#8217;re with me, here we go!</p>
<p><strong>Installing DB2</strong></p>
<p>I have <a href="http://www-01.ibm.com/software/data/db2/express/download.html">downloaded</a> DB2 9.5 Express-C for Solaris x64, and have the distribution extracted in <code>/root/db2_9.5_expc</code>, ready for installation.</p>
<p>First, I&#8217;ll install the software to the default location, <code>/opt/IBM/db2/V9.5</code>. The <code>-p EXP</code> option is to tell the installer what product to install &mdash; EXP for Express Edition in this case. Before running the installer, I create the <code>/usr/local/bin</code> directory because DB2 puts a command (<code>db2ls</code>) in there. It doesn&#8217;t hurt if that command doesn&#8217;t get installed, but the installer will tell you that there were minor errors. So, the installation of the software:</p>
<pre>root@lab01v04# <strong>mkdir -p /usr/local/bin</strong>
root@lab01v04# <strong>cd /root/db2_9.5_expc</strong>
root@lab01v04# <strong>./db2_install -b /opt/IBM/db2/V9.5 -p EXP -n</strong>
The execution completed successfully.

For more information see the DB2 installation log at
"/tmp/db2_install.log.18091".
root@lab01v04#</pre>
<p><strong>Creating an Instance</strong></p>
<p>Easy enough. Now we need to create an <em>instance</em>. A DB2 instance is what holds databases and everything in them. One instance can hold several database (like Microsoft SQL Server or MySQL, but unlike Oracle). DB2 instances are owned by and tied to a local user account. In addition to the instance owner user, there is a &#8220;fenced user&#8221; that is used to provide a security context in which to run certain code. So we&#8217;ll be creating two users, <code>db2inst1</code>, the instance owner, and <code>db2fenc1</code>, the fenced user. Note that the actual instance data will live inside of the home directory of the instance owner. We&#8217;ll also create two groups, the instance admin group (<code>db2iadm1</code>) and the fenced admin group (<code>db2fadm1</code>). One physical server can run several instances of DB2, so the 1 on the end of the user and group names is just an easy way of identifying this particular instance we&#8217;re creating.</p>
<p>Create the groups, then the users, then set the users&#8217; passwords using the regular Solaris tools:</p>
<pre>root@lab01v04# <strong>groupadd db2iadm1</strong>
root@lab01v04# <strong>groupadd db2fadm1</strong>
root@lab01v04# <strong>useradd -g db2iadm1 -d /export/home/db2inst1 \
               -s /usr/bin/ksh93 -m db2inst1</strong>
64 blocks
root@lab01v04# <strong>useradd -g db2fadm1 -d /export/home/db2fenc1 \
               -s /usr/bin/ksh93 -m db2fenc1</strong>
64 blocks
root@lab01v04# <strong>passwd db2inst1</strong>
New Password: <strong>...password...</strong>
Re-enter new Password: <strong>...password...</strong>
passwd: password successfully changed for db2inst1
root@lab01v04# <strong>passwd db2fenc1</strong>
New Password: <strong>...password...</strong>
Re-enter new Password: <strong>...password...</strong>
passwd: password successfully changed for db2fenc1</pre>
<p>We now have the users ready to go. Finally, our last task as <code>root</code> is to create the actual instance. We&#8217;ll do that with the <code>db2icrt</code> command, which takes an argument for the fenced user and the instance name/user:</p>
<pre>root@lab01v04# <strong>/opt/IBM/db2/V9.5/instance/db2icrt -u db2fenc1 db2inst1</strong>
Sun Microsystems Inc.   SunOS 5.11      snv_104 November 2008
Sun Microsystems Inc.   SunOS 5.11      snv_104 November 2008
DBI1070I  Program db2icrt completed successfully.</pre>
<p>Simple as that. The Sun banner that appears a couple of times is from the instance creation scripts logging in as the users to perform some setup.</p>
<p>Now that the instance is created, we can do the rest of the work as the <code>db2inst1</code> user, so we&#8217;ll change logins. The instance creation tool added an entry to <code>db2inst1</code>&#8217;s <code>.profile</code> file to pull in the environment for all of the DB2 commands.</p>
<p>Our first task is to start the instance:</p>
<pre>db2inst1@lab01v04$ <strong>db2start</strong>
SQL1063N  DB2START processing was successful.</pre>
<p><strong>Creating the First Database</strong></p>
<p>Since this is a new instance, there isn&#8217;t actually anything in it yet (specifically, databases). Now we can create our first database, which we&#8217;ll call <code>mydb</code>.</p>
<pre>db2inst1@lab01v04$ <strong>db2 create database mydb</strong>
DB20000I  The CREATE DATABASE command completed successfully.</pre>
<p>The <code>db2</code> command is the DB2 Command Line Processor (CLP). The CLP is the primary interface to issue commands to the server. You can either run <code>db2 <em>command</em></code> from the shell, which executes the command and exits, or you can use the CLP interactively by running <code>db2</code> with no arguments. To do a couple quick tests on our database, we&#8217;ll use the CLP interactively:</p>
<pre>db2inst1@lab01v04$ <strong>db2</strong>
(c) Copyright IBM Corporation 1993,2007
Command Line Processor for DB2 Client 9.5.1

You can issue database manager commands and SQL statements from the command
prompt. For example:
    db2 =&gt; connect to sample
    db2 =&gt; bind sample.bnd

For general help, type: ?.
For command help, type: ? command, where command can be
the first few keywords of a database manager command. For example:
 ? CATALOG DATABASE for help on the CATALOG DATABASE command
 ? CATALOG          for help on all of the CATALOG commands.

To exit db2 interactive mode, type QUIT at the command prompt. Outside
interactive mode, all commands must be prefixed with 'db2'.
To list the current command option settings, type LIST COMMAND OPTIONS.

For more detailed help, refer to the Online Reference Manual.

db2 =&gt;</pre>
<p>When we launch the CLP, we get some basic usage information and then the prompt. We first need to connect to a database, so we&#8217;ll connect to the one we just created, <code>mydb</code>:</p>
<pre>db2 =&gt; <strong>connect to mydb</strong>

   Database Connection Information

 Database server        = DB2/SUNX8664 9.5.1
 SQL authorization ID   = DB2INST1
 Local database alias   = MYDB</pre>
<p>Looks good. We&#8217;re connected as the <code>db2inst1</code> user to the <code>mydb</code> database. Now we can just issue regular SQL statements, so we&#8217;ll create a table and insert a couple rows. Note that in the DB2 CLP (like the Unix shell), you need to put a backslash on the end of a line if you want to continue the command. Also, do not put semicolons at the end of SQL commands; in interactive mode they are not allowed.</p>
<pre>db2 =&gt; <strong>create table testtab ( \</strong>
db2 (cont.) =&gt; <strong>id integer not null primary key, \</strong>
db2 (cont.) =&gt; <strong>name varchar(50) not null )</strong>
DB20000I  The SQL command completed successfully.
db2 =&gt; <strong>insert into testtab values (1, 'First entry')</strong>
DB20000I  The SQL command completed successfully.
db2 =&gt; <strong>insert into testtab values (2, 'Second entry')</strong>
DB20000I  The SQL command completed successfully.</pre>
<p>Not surprisingly, it&#8217;s working like a SQL database should. We have a table, <code>testtab</code>, which we&#8217;ve inserted two rows into.</p>
<p>Finally, we&#8217;ll disconnect from the database and quit the CLP:</p>
<pre>db2 =&gt; <strong>connect reset</strong>
DB20000I  The SQL command completed successfully.
db2 =&gt; <strong>quit</strong>
DB20000I  The QUIT command completed successfully.</pre>
<p><strong>Enabling Network Connectivity</strong></p>
<p>That works great, but so far we&#8217;ve only accessed the instance locally. To allow connections from clients on other systems, we need to configure the instance to accept TCP/IP connections. This is an instance-level setting, so all of the databases you create in this instance will be available to remote clients.</p>
<p>The first step is to tell the instance what port to listen on. We&#8217;ll use 50,000. Note that <code>svcename</code> in the following command could also be the name of an entry in the <code>/etc/inet/services</code> file, which explains why the parameter is named <code>svcename</code> instead of something with the word &#8220;port.&#8221;</p>
<pre>db2inst1@lab01v04$ <strong>db2 update dbm configuration using svcename 50000</strong>
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
successfully.
SQL1362W  One or more of the parameters submitted for immediate modification
were not changed dynamically. Client changes will not be effective until the
next time the application is started or the TERMINATE command has been issued.
Server changes will not be effective until the next DB2START command.</pre>
<p>Next we need to enable TCP/IP as a communication protocol. This uses a new command, <code>db2set</code>:</p>
<pre>db2inst1@lab01v04$ <strong>db2set DB2COMM=tcpip</strong></pre>
<p>Finally, restart the instance:</p>
<pre>db2inst1@lab01v04$ <strong>db2stop</strong>
SQL1064N  DB2STOP processing was successful.
db2inst1@lab01v04$ <strong>db2start</strong>
SQL1063N  DB2START processing was successful.</pre>
<p>How do we know if it worked? First, we&#8217;ll check to see if there&#8217;s something listening on port 50,000 on our system:</p>
<pre>db2inst1@lab01v04$ <strong>netstat -an | grep 50000</strong>
      *.50000              *.*                0      0 49152      0 LISTEN</pre>
<p>Looks good! <code>netstat</code> reports that a process is accepting connections on port 50000 on all interfaces. To really prove that we&#8217;re ready to start serving clients, though, we&#8217;ll test connectivity from another system.</p>
<p><strong>Connecting From a Remote Client</strong></p>
<p>We installed DB2 on <code>lab01v04</code>. Over on another machine, <code>lab01v03</code>, the DB2 client is installed. I&#8217;m logged in as <code>mwilson</code>, a user that the DB2 server knows nothing about, but I should be able to connect to DB2 as the <code>db2inst1</code> user, which is the &#8220;superuser&#8221; or &#8220;root user&#8221; for the database.</p>
<p>The DB2 client software contains the same <code>db2</code> command to launch the Command Line Processor. To connect to a remote server from a client, you first need to define the &#8220;node,&#8221; which represents the instance. Then you define the specific database within the instance. Once I have the database defined (cataloged in DB2 parlance), I can connect to it by name just like I did on the server, only I&#8217;ll add a username since I don&#8217;t have the benefit of being logged on locally to the server as an authorized user.</p>
<p>I&#8217;ll give you this one in one piece: starting the CLP, cataloging the node and database, then connecting and reading the data we inserted into the table earlier. All of this is happening from <code>lab01v03</code>, talking to the DB2 instance we created on <code>lab01v04</code>.</p>
<pre>mwilson@lab01v03$ <strong>db2</strong>
(c) Copyright IBM Corporation 1993,2007
Command Line Processor for DB2 Client 9.5.1

You can issue database manager commands and SQL statements from the command
prompt. For example:
    db2 =&gt; connect to sample
    db2 =&gt; bind sample.bnd

For general help, type: ?.
For command help, type: ? command, where command can be
the first few keywords of a database manager command. For example:
 ? CATALOG DATABASE for help on the CATALOG DATABASE command
 ? CATALOG          for help on all of the CATALOG commands.

To exit db2 interactive mode, type QUIT at the command prompt. Outside
interactive mode, all commands must be prefixed with 'db2'.
To list the current command option settings, type LIST COMMAND OPTIONS.

For more detailed help, refer to the Online Reference Manual.

db2 =&gt; <strong>catalog tcpip node lab01v04 remote lab01v04 server 50000</strong>
DB20000I  The CATALOG TCPIP NODE command completed successfully.
DB21056W  Directory changes may not be effective until the directory cache is
refreshed.
db2 =&gt; <strong>catalog database mydb at node lab01v04</strong>
DB20000I  The CATALOG DATABASE command completed successfully.
DB21056W  Directory changes may not be effective until the directory cache is
refreshed.
db2 =&gt; <strong>connect to mydb user db2inst1</strong>
Enter current password for db2inst1: <strong>...password...</strong>

   Database Connection Information

 Database server        = DB2/SUNX8664 9.5.1
 SQL authorization ID   = DB2INST1
 Local database alias   = MYDB

db2 =&gt; <strong>select * from testtab</strong>

ID          NAME
----------- --------------------------------------------------
          1 First entry
          2 Second entry                                      

  2 record(s) selected.

db2 =&gt; <strong>connect reset</strong>
DB20000I  The SQL command completed successfully.
db2 =&gt; <strong>quit</strong>
DB20000I  The QUIT command completed successfully.</pre>
<p><strong>Wrapping Up</strong></p>
<p>It worked! With really just a handful of commands, entirely from the command line, we&#8217;ve a) installed DB2, b) created an instance, c) created a database, d) enabled network client connectivity, and e) connected to our database from a remote client. If you&#8217;re familiar with doing the exact same thing using Oracle (please, no GUI installer or automatic bloated database creation with the Database Creation Assistant), you&#8217;ll appreciate just how much of a breeze this was with DB2, despite it being an equally &#8220;enterprise&#8221; database as Oracle. Maybe I&#8217;ll put together an article going through all of my Oracle installation and instance creation scripts for comparison.</p>
<p>In any case, the only thing we didn&#8217;t do is create the DB2 Administration Server (DAS), which allows remote management with the DB2 GUI utilities, but I don&#8217;t plan on needing that for now. If I did, it&#8217;s literally just a matter of creating a user to own the DAS and running the command <code>dascrt -u DASuser</code>.</p>
<p>There is one thing that I&#8217;m not satisfied with at this point, though: the instance uses the local system user accounts for authentication. That means, for example, that if I want a user, mwilson, in my database, I need to create a Unix account for mwilson. Luckily, DB2 ships with an LDAP authentication plugin. This will allow me to store user information in an  LDAP directory and create as many users as I want without making any changes to the operating system hosting DB2. We&#8217;ll get that up and running, using OpenDS, in the next installment.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/solaris/installing-db2-on-opensolaris/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Replacing a Bad Drive with ZFS</title>
		<link>http://mattwilson.org/blog/solaris/replacing-a-bad-drive-with-zfs/</link>
		<comments>http://mattwilson.org/blog/solaris/replacing-a-bad-drive-with-zfs/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 05:07:48 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[Solaris]]></category>

		<guid isPermaLink="false">http://www.mattwilson.org/?p=20</guid>
		<description><![CDATA[One of the drives in my home file server was making occasional nasty clicking noises, which always precedes death in hard drives. The drive is only a couple of months old, so it must have just been a bad apple. Anyway, some quick testing showed that it was failing its SMART self-tests, so it was [...]]]></description>
			<content:encoded><![CDATA[<p>One of the drives in my home file server was making occasional nasty clicking noises, which always precedes death in hard drives. The drive is only a couple of months old, so it must have just been a bad apple. Anyway, some quick testing showed that it was failing its SMART self-tests, so it was quick and easy to get a warranty replacement from Seagate. Luckily replacing the drive was quick and easy and all of the data was safe, since my data is on a zpool consisting of four terabyte drives in a RAID-Z configuration (if you&#8217;re familiar with traditional RAID, think RAID-5). Of course the data is also backed up, because RAID is not a substitute for backups, but as expected ZFS &#8220;just worked&#8221; and the new drive took over for the old drive with no hassles.</p>
<p>If you want to relive the experience, here&#8217;s my session on the server after shutting down, replacing the failing drive, and starting back up. First, on the console, Solaris complained about something not being quite right as soon as the server booted:</p>
<pre>SUNW-MSG-ID: ZFS-8000-FD, TYPE: Fault, VER: 1, SEVERITY: Major
EVENT-TIME: Wed Jan 14 19:12:39 PST 2009
PLATFORM: PowerEdge 1800, CSN: BSQMN91, HOSTNAME: athena
SOURCE: zfs-diagnosis, REV: 1.0
EVENT-ID: c6647451-fa5a-4f4b-99fd-de1e76bb059d
DESC: The number of I/O errors associated with a ZFS device exceeded
      acceptable levels.  Refer to http://sun.com/msg/ZFS-8000-FD for more
      information.
AUTO-RESPONSE: The device has been offlined and marked as faulted.  An attempt
      will be made to activate a hot spare if available.
IMPACT: Fault tolerance of the pool may be compromised.
REC-ACTION: Run 'zpool status -x' and replace the bad device.</pre>
<p>Yeah, it didn&#8217;t like booting with a totally different hard drive in place of a drive that was a member of a zpool. A quick check confirms that Solaris is, indeed, complaining about the drive I replaced:</p>
<pre>mwilson athena:~ [1258]% <strong>zpool status tank</strong>
  pool: tank
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
        the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
   see: http://www.sun.com/msg/ZFS-8000-2Q
 scrub: resilver completed after 0h0m with 0 errors on Wed Jan 14 19:12:11 2009
config:

        NAME        STATE     READ WRITE CKSUM
        tank        DEGRADED     0     0     0
          raidz1    DEGRADED     0     0     0
            c0t2d0  ONLINE       0     0     0
            c0t3d0  UNAVAIL      0     0     0  cannot open
            c0t4d0  ONLINE       0     0     0
            c0t5d0  ONLINE       0     0     0

errors: No known data errors</pre>
<p>No surprises there, we&#8217;ll tell it to replace <code>c0t3d0</code>. Without any additional arguments, the <code>zpool replace</code> command will attempt to replace the old device with the same new device (<code>c0t3d0</code>, that is).</p>
<pre>mwilson athena:~ [1260]% <strong>pfexec zpool replace tank c0t3d0</strong></pre>
<p>That command executes immediately and returns me to the prompt. We can monitor the status while the pool is resilvering:</p>
<pre>mwilson athena:~ [1262]% <strong>zpool status tank</strong>
  pool: tank
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
 scrub: resilver in progress for 0h0m, 0.40% done, 2h45m to go
config:

        NAME              STATE     READ WRITE CKSUM
        tank              DEGRADED     0     0     0
          raidz1          DEGRADED     0     0     0
            c0t2d0        ONLINE       0     0     0
            replacing     DEGRADED     0     0     0
              c0t3d0s0/o  FAULTED      0     0     0  corrupted data
              c0t3d0      ONLINE       0     0     0
            c0t4d0        ONLINE       0     0     0
            c0t5d0        ONLINE       0     0     0

errors: No known data errors</pre>
<p>And some time later&#8230;</p>
<pre>mwilson athena:~ [1273]% <strong>zpool status tank</strong>
  pool: tank
 state: ONLINE
 scrub: resilver completed after 2h34m with 0 errors on Wed Jan 14 21:48:43 2009
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz1    ONLINE       0     0     0
            c0t2d0  ONLINE       0     0     0
            c0t3d0  ONLINE       0     0     0
            c0t4d0  ONLINE       0     0     0
            c0t5d0  ONLINE       0     0     0

errors: No known data errors</pre>
<p>Everything happy again! I love it when things just work how they&#8217;re supposed to.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/solaris/replacing-a-bad-drive-with-zfs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solaris CIFS Server and ZFS ACLs: The Problem</title>
		<link>http://mattwilson.org/blog/solaris/solaris-cifs-server-and-zfs-acls-the-problem/</link>
		<comments>http://mattwilson.org/blog/solaris/solaris-cifs-server-and-zfs-acls-the-problem/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 04:20:00 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[Solaris]]></category>

		<guid isPermaLink="false">http://www.mattwilson.org/blog/solaris/solaris-cifs-server-and-zfs-acls-the-problem/</guid>
		<description><![CDATA[I&#8217;m going to be switching my home file server over to Solaris soon (or, more specifically, Solaris Express Community Edition [SXCE] build 99), and one of the primary goals of this server is to serve up a few directories to Windows or other SMB clients. One of the reasons I&#8217;m switching from Linux to Solaris [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m going to be switching my home file server over to Solaris soon (or, more specifically, Solaris Express Community Edition [SXCE] build 99), and one of the primary goals of this server is to serve up a few directories to Windows or other SMB clients. One of the reasons I&#8217;m switching from Linux to Solaris is because I&#8217;m significantly increasing the disk space and I want to use ZFS for my storage pool. At the same time, I&#8217;m hoping to take advantage of SXCE&#8217;s built-in CIFS server to serve SMB shares.</p>
<p>To prepare for the big switch, I installed the latest build on a test machine and am playing around with setting up a configuration similar to what I&#8217;ll want. Unfortunately, it became clear quickly that I was going to hit problems with the new NFSv4 ACLs implemented in ZFS and how the CIFS server interacts with those ACLs on behalf of Windows clients.</p>
<p>So, in this post, I&#8217;ll walk through what I want to have happen, and what&#8217;s actually happening instead. </p>
<p>I have several users. They all belong to a group named <code>data</code>. There is a directory, <code>/export/sandbox</code>, that is for group project resources for everyone in the <code>data</code> group. All users in the group should be able to create files and directories in <code>sandbox</code>, and everyone else in the <code>data</code> group should be able to modify the files and directories. All users on the system should have read access to the <code>sandbox</code> tree.</p>
<p>This is very easy with traditional Unix permissions. You set the <code>sandbox</code> directory to mode <code>775</code>, set the group to <code>data</code>, and set the setgid bit. For example, if I&#8217;m going to make <code>sandbox</code> a ZFS dataset, I can do:</p>
<pre># <strong>zfs create -o casesensitivity=mixed rpool/export/sandbox</strong>
# <strong>chown root:data /export/sandbox</strong>
# <strong>chmod 775 /export/sandbox</strong>
# <strong>chmod g+s /export/sandbox</strong></pre>
<p>(The <code>casesensitivity</code> option is to make it play well with Windows as a file share)</p>
<p>Finally, in each user&#8217;s profile I can set <code>umask 002</code> and everything works as desired. Let&#8217;s log in as <code>mwilson</code> and do some tests:</p>
<pre>$ <strong>umask</strong>
002
$ <strong>cd /export/sandbox</strong>
$ <strong>ls -l</strong>
total 0
$ <strong>touch test-file</strong>
$ <strong>mkdir test-dir</strong>
$ <strong>ls -l</strong>
total 2
drwxrwsr-x   2 mwilson  data           2 Oct  7 17:35 test-dir/
-rw-rw-r&#45;&#45;   1 mwilson  data           0 Oct  7 17:35 test-file</pre>
<p>Excellent! This is exactly what we wanted: the file&#8217;s group is set to data and it remains writable by the group, as does the directory. Both are read-only for the world. The setgid bit on the new directory is set, so this method will work as users continue making subdirectories deeper in the tree.</p>
<p>But now, we&#8217;re going to add a new requirement: some users will access the sandbox from Windows using SMB. My server is already set up to run the Solaris CIFS server, so it&#8217;s easy to share this folder:</p>
<pre># <strong>zfs set sharesmb=name=sandbox rpool/export/sandbox</strong></pre>
<p>Now from a Windows client, I can go to <code>\\server\sandbox</code> and sure enough I see the directory and its contents. I&#8217;m authenticated as a user that maps to the <code>mwilson</code> Unix user. Now I&#8217;ll create a text file from Windows, then look at the directory listing back in Unix:</p>
<pre>$ <strong>ls -l</strong>
total 5
drwxrwsr-x   2 mwilson  data           2 Oct  7 17:35 test-dir/
-rw-rw-r&#45;&#45;   1 mwilson  data           0 Oct  7 17:35 test-file
&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;&#45;+  1 mwilson  data           0 Oct  7 17:47 windows-file.txt</pre>
<p>Whoa! Look at the file we created, <code>windows-file.txt</code>. That&#8217;s different&#8230; the ZFS ACLs are beginning to rear their ugly heads. The <code>+</code> next to the Unix permissions indicates that this file contains extended ACLs. Let&#8217;s look at the ACL on this file:</p>
<pre>$ <strong>ls -v windows-file.txt</strong>
&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;&#45;+  1 mwilson  data           0 Oct  7 17:47 windows-file.txt
     0:user:mwilson:read_data/write_data/append_data/read_xattr/write_xattr
         /execute/delete_child/read_attributes/write_attributes/delete
         /read_acl/write_acl/write_owner/synchronize:allow
     1:group:2147483648:read_data/write_data/append_data/read_xattr
         /write_xattr/execute/delete_child/read_attributes/write_attributes
         /delete/read_acl/write_acl/write_owner/synchronize:allow</pre>
<p>Okay. Deep breath. This file has ACL entries that say the user named <code>mwilson</code> is allowed to do, well, just about everything you could ever want to do to the file. The group with ID <code>2147483648</code> also has full permissions. Why the weird group number? It&#8217;s something to do with the mapping of Windows users and groups to Unix users and groups&#8230;honestly, I don&#8217;t know where it&#8217;s coming from. Since I&#8217;m mapped to the <code>mwilson</code> user, I wish it would just apply the Unix user&#8217;s group as the effective group if nothing else.</p>
<p>In any case, there seems to be a problem here: the <code>data</code> group no longer has any access to this file! Nor, it seems, does the world have read access.</p>
<p>Let&#8217;s log in as another user, <code>jsmith</code>, who is in the data group and look at the sandbox directory.</p>
<pre>$ <strong>cd /export/sandbox</strong>
$ <strong>ls -l</strong>
./windows-file.txt: Permission denied
total 4
drwxrwsr-x   2 mwilson  data           2 Oct  7 17:35 test-dir
-rw-rw-r&#45;&#45;   1 mwilson  data           0 Oct  7 17:35 test-file</pre>
<p>Wow&#8230; <code>ls</code> gives us an error just trying to list the directory! That&#8217;s pretty bad&#8230;</p>
<p>Just for kicks, we&#8217;ll make a directory from Windows and see what that looks like, as <code>mwilson</code>:</p>
<pre>$ <strong>ls</strong>
total 6
drwxrwsr-x   2 mwilson  data           2 Oct  7 17:35 test-dir/
-rw-rw-r&#45;&#45;   1 mwilson  data           0 Oct  7 17:35 test-file
d&#45;&#45;-&#45;&#45;S-&#45;&#45;+  2 mwilson  data           2 Oct  7 20:45 windows-dir/
&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;&#45;+  1 mwilson  data           0 Oct  7 17:47 windows-file.txt</pre>
<p>Okay, there&#8217;s the directory (<code>windows-dir</code>) but it&#8217;s again different than what we&#8217;re used to. It looks like the Windows file, but has a capital <code>S</code> in the group mode. That indicates that the setgid bit is set, but the execute bit is not set for the group. Let&#8217;s check the ACL that&#8217;s in place:</p>
<pre>$ <strong>ls -dv windows-dir</strong>
d&#45;&#45;&#45;&#45;&#45;S&#45;&#45;&#45;+  2 mwilson  data           2 Oct  7 20:45 windows-dir/
     0:user:mwilson:list_directory/read_data/add_file/write_data
         /add_subdirectory/append_data/read_xattr/write_xattr/execute
         /delete_child/read_attributes/write_attributes/delete/read_acl
         /write_acl/write_owner/synchronize:allow
     1:group:2147483648:list_directory/read_data/add_file/write_data
         /add_subdirectory/append_data/read_xattr/write_xattr/execute
         /delete_child/read_attributes/write_attributes/delete/read_acl
         /write_acl/write_owner/synchronize:allow</pre>
<p>This is just like the file, but with the directory versions of the permission names instead of the file versions of the names.</p>
<p>Where does that leave us? Creating files and directories from the Unix command line gives me the behavior I want, but creating files from Windows through the SMB share leads to dreadful results.</p>
<p>The problem definitely lies with ACL inheritance: I suspect I will need to define the ACLs that I want on the sandbox directory and set the appropriate inheritance flags, then files created in an &#8220;ACL-aware&#8221; fashion, such as by the CIFS server, will end up with the permissions I want. We shall see&#8230;hopefully soon I&#8217;ll have a follow-up post walking through the solution.</p>
<p><strong>Update</strong>: as if it isn&#8217;t obvious by now, I never did follow up and figure out the right ACLs. I ended up using Solaris 10 Update 6, instead of OpenSolaris, to build the new file server. Solaris doesn&#8217;t have the integrated CIFS server yet, so I&#8217;m going the traditional Samba route, with doesn&#8217;t have this problem.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/solaris/solaris-cifs-server-and-zfs-acls-the-problem/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Dear Google: can you please add two features to GMail for me?</title>
		<link>http://mattwilson.org/blog/technology/dear-google-can-you-please-add-two-features-to-gmail-for-me/</link>
		<comments>http://mattwilson.org/blog/technology/dear-google-can-you-please-add-two-features-to-gmail-for-me/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 18:34:10 +0000</pubDate>
		<dc:creator>mwilson</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.mattwilson.org/blog/technology/dear-google-can-you-please-add-two-features-to-gmail-for-me/</guid>
		<description><![CDATA[For several years, I ran my own server to handle my email. At first it was a fun project, gave me good real-world experience, and provided flexibility that I wouldn&#8217;t have had with most hosted options. Procmail and mutt were my friends. Over time, though, it became more of a burden than it was fun [...]]]></description>
			<content:encoded><![CDATA[<p>For several years, I ran my own server to handle my email. At first it was a fun project, gave me good real-world experience, and provided flexibility that I wouldn&#8217;t have had with most hosted options. Procmail and mutt were my friends. Over time, though, it became more of a burden than it was fun to keep up with anti-spam measures, and in the grand scheme of things I just didn&#8217;t feel like spending my free time maintaining caring for and feeding a production mail server.</p>
<p>The death knell for my own server was the introduction of Google Apps For Your Domain. Having played with regular GMail in the past, I liked the interface and its threading model, and I buy into the philosophy of searching email archives instead of trying to organize them. For those and other reasons, moving email to Google Apps sounds like a good option, so I set up a test domain and eventually moved mattwilson.org to Google Apps.</p>
<p>In short, I&#8217;ve been happy with the service and their spam filter is amazingly accurate. So I&#8217;m a happy camper, but there is one area where I&#8217;d like to see a couple of improvements: handling email list subscriptions.</p>
<p>I subscribe to several mail lists, and GMail&#8217;s searching and conversation threading features particularly shine when reading list traffic. Each list gets its own label and messages &#8220;skip the inbox&#8221; so I can just go through and read the lists I&#8217;m interested in as I have time. But here&#8217;s where the problems arise:</p>
<p>First, GMail&#8217;s filters don&#8217;t allow me to reliably drop messages from particular lists in a particular label (for GMail neophytes, think of labels as folders). For some lists I&#8217;ve subscribed to, the only way to identify that I received the message from that list is by looking for a specific header. Unfortunately, I can&#8217;t filter based on headers with GMail so the messages from those lists couldn&#8217;t be filed correctly. Even for the majority of my lists which I filter based on the list address in the &#8220;To&#8221; field, I occasionally get messages in the inbox because the list was bcc&#8217;ed for the particular message. There&#8217;s another header that still identifies the list, but I can&#8217;t act on it. So feature request one: I&#8217;d like to filter based on headers.</p>
<p>Second, I don&#8217;t read every message on every list. My workflow is to click on a label, scan the subject lines, and read the messages that look interesting. This leaves several unread conversations, and in the best case it takes three clicks to mark the remaining conversations as read. If I&#8217;ve been on vacation or not reading list traffic for a couple days and the messages expand past the first list screen, it takes more work to mark them as read. So feature request two: while browsing a label, I&#8217;d like a &#8220;Catch Up&#8221; or &#8220;Mark All As Read&#8221; button right up there next to the Delete button.</p>
<p>GMail is inherently a natural fit for managing an email account that subscribes to mail lists. The search is great, and the conversation interface is wonderful for following threads. With the addition of header-based filtering and a quick way to mark everything from a list as read, it would be truly fantastic.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattwilson.org/blog/technology/dear-google-can-you-please-add-two-features-to-gmail-for-me/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
