Wise Words on Writing

Wisdom on writing from Paul Graham:

Expect 80% of the ideas in an essay to happen after you start writing it, and 50% of those you start with to be wrong.

I’ve wrestled with that “50% wrong” part for a long time. There’s a tendency to hang on tight and defend those initial ideas, even after the ground underneath them has crumbled.

Fedora Ambushes Apache

The Scenario starts with your having a box running Fedora Core under your control, and, for whatever reason, you want to keep some web-visible files in your /home partition. (I’m trying to keep long-term stuff in /home so that I can reinstall the OS without having having to move stuff onto another box and back.)

Following the oft-published recipe, you add the following to httpd.conf

  Alias /stuff /home/me/stuff
  <Directory /home/me/stuff>
    Options ExecCGI
    AllowOverride All
    Order allow,deny
    Allow from all
  </Directory>

and you create /home/me/stuff and make sure that’s it’s readable by the apache user.

Now the fun starts. You try “http://mybox/stuff” in your browser of choice, but get a “Forbidden. You don’t have permission to access /stuff/ on this server.” response. Checking /var/log/httpd/error_log you find something like

  [Fri Mar 25 11:16:15 2005] [error] [client 209.257.117.196]
    (13)Permission denied: access to /test/ denied

You double-check permissions, try again, fail again, and google for help. You find posts from number of folks having the same problem, all getting told that their permissions are wrong. (Which is the right answer, but not at all in the obvious way.)

You might get the inspiration to instead try the approach of adding a symbolic link from /var/www/html/stuff to /home/me/stuff (after verifying that Options FollowSymLinks is in effect). This also fails, and the error log shows

  [Fri Mar 25 11:22:09 2005] [error] [client 209.257.117.196]
    Symbolic link not allowed: /var/www/html/stuff

Googling for help shows others with the same problem, all being told to check permissions or verify that FollowSymLinks is on. Many posts begging for help are unanswered. No help there.

So what’s going on?

The Clue is in /var/log/messages, which will say something like

 Mar 25 11:16:15 mybox kernel: audit(1111778175.632:0):
    avc:  denied  { getattr } for  pid=16778
    exe=/usr/sbin/httpd path=/home/me/stuff dev=hda5 ino=4440065
    scontext=root:system_r:httpd_t tcontext=user_u:object_r:user_home_t tclass=dir

Huh?

The Punchline is that Fedora Core includes an entirely separate, parallel security mechanism called SELinux (Security-enhanced Linux), which is configured out-of-the-box to restrict which directories httpd has access to. (Dig through /etc/selinux/ for hints about what’s going on.) So despite following the published advice on how to configure Apache to let you use a directory outside of the normal hierarchy, and despite applying your hard-earned Unix skills, Fedora is yanking the rug out from under you when your back is turned, and then arranging to have Apache blame you.

Armed with this knowledge, googling for “selinux apache” will get you to Understanding and Customizing the Apache HTTP SELinux Policy (Beta Document), which is right where you though to look in the first place, right?

When I asked for a show of hands at work, two people knew about SELinux, and one had just learned about it the day before. The other had been following Fedora a lot more closely than the rest of us.

There went three hours of my life that I’ll never get back.

Test-Driven Language Study

I learned Perl and Python by reading a lot of other people’s code, and by writing lots of small programs (and a few bigger ones). When faced with a “how do I make the language do…” problem, I’d fumble through a growing collection of scripts looking for that one place where I’d solved a particular problem before. Having a big collection of prior solutions is handy, but searching is problematic. Some patterns aren’t amenable to grep.

I’ve been playing around with Ruby (and the Rails framework) for several months, and have decided that it’s time to have a serious go at the language, using the the “Pick Axe” book as a guide. The pile of experimental scripts was beginning to grow again, until Mike Clark provided the transforming idea: Capture knowledge about how a language works by writing unit tests. In this case, one really big file of unit tests.

The idea is stunning in its obvious simplicity.

After an evening of digging through my pile of Ruby experiments, collecting up the useful pieces into a set of unit tests, I have a file with just over 100 unit tests, divided into categories like “tests about strings”, “tests about numbers”, and so on. Another evening’s work should double that number. Now, much of what I learn about Ruby will be captured in one easily searchable place.

I did encounter one anomaly, which I’ve boiled down to a simple test case.

  require 'test/unit'
    
  class TestUnitTest < Test::Unit::TestCase
    def testAssert
      assert true
      assert not false      # syntax error
      assert(not false)     # syntax error
    end
  end

After scratching my head at this for a while, I took it to the #ruby-lang IRC channel, where the resident experts pondering it and announced that it’s a problem in the implementation of Ruby’s parser, and that the workaround is to write

      assert((not false))

I wouldn’t have guessed that. But now I’ve captured the problem and its workaround in a unit test.

The Unix Clock Achieves Final Unity

Here’s one of those one-in-a-lifetime Geek things*:

  % perl -e 'print time, $/'
  1111111110
  % perl -e 'print time, $/'
  1111111111
  % perl -e 'print time, $/'
  1111111112
  %

Now how cool is that?

In theory, I retire the day before the Unix clocks wraps, though judging from the number of old COBOL programmers who found re-employment during the Y2K run-up, I might land some consulting work fixing old Unix apps.


* The Unix clock counts the number of seconds since January 1, 1970 at 00:00 GMT. Due to an accident of history, the number of seconds in Unix time is limited to the largest number that can be represented in a 32-bit integer. That number of seconds takes us to January 19, 2038. Then, *poof*, Unix boxes worldwide burst into flame, and civilization grinds to a halt, just like what happened when Y2K hit. Today was the last day that the number of seconds in Unix time can be represented by a string of 1’s.

Late-Night Configuration Problems

Previously:

  • Install Fedora Core 3. Turn off a bunch of services. done
  • Setup Samba and move a bunch of stuff off of other boxes. done
  • Turn on and configure Apache. done
  • Configure the router to port forward HTTP and SSH to the new box. Test. done
  • Setup a skeleton “nothing to see here” web page and test. done
  • Setup some other random web stuff and test. done
  • Get dynamic DNS set up through dyndns.org, and teach the router about it. Test. done

Picking up the story again last night at 1 AM:

  • Setup and configure MySQL. done
  • Migrate databases off of the old box. done
  • Generate SSL cert for Apache, restart, and test locally. done
  • Setup a virtual domain for dynamic DNS. Test locally. done
  • Configure the router to also port forward HTTPS. Test… Connection refused. Hm… Double-check the router to make sure I didn’t get dyslexic with the HTTPS port number. Nope. Check the httpd logs. Nothing. Restart Apache and try again. HTTP works; HTTPS doesn’t. Triple check everything. Nada. wtf?

The punchline, found at 2 AM after much flailing, was in the firewall rules file, /etc/sysconfig/iptables, which I’d touched once to get Samba working, and then forgot about. The FC3 install had ports unblocked for HTTP and SSH, but not HTTPS. Go figure. Add a line to support tcp on port 443, restart iptables, and test. Ah. Much better. Now I can sleep the sleep of those who can securely serve up a “nothing to see here” page from a home linux box.

Backhoes and their fellow travelers

Our phone and DSL where out on Friday and much of the weekend, along with the rest of the neighborhood. On Friday, one of the SBC repair people told us that the lines had been cut during trenching. I talked with another repair guy today, who said that it’d been the cable company doing the trenching. “They do this too us all the time,” he said. “We’ll have it all fixed in another day or two.”

I wonder what percentage of our monthly cable bill goes to covering stuff like this.