Saturday, January 17, 2009

Setting up Subversion on Solaris 10 as an inetd service

Some posts ago I described how I set up Subversion on Solaris 10 in daemon mode and managed via SMF. It exists another way to invoke svnserve: it can be run via inetd. svnserve, when invoked with the -i|--inetd option will use stdin and stdout to communicate to a Subversion client: this is the expected behavior of an inetd-based service.

These instructions are valid for an UNIX system with an inetd implementation. Registration of this configuration as an SMF service is Solaris 10 specific.

Configuring /etc/services

The first thing to do is checking if /etc/services defines the Subversion service. IANA has reserved port 3690 for the Subversion service, so that /etc/services should contain:

svn 3690/tcp
svn 3690/udp

Please note that svn is just a service identifier which will be used during inetd configuration.

Setting up the inetd daemon

The standard UNIX inetd daemon accepts configuration on a file usually called /etc/inet/inetd.conf or /etc/inetd.conf for compatibility with BSD. In the case of Solaris 10, that file is not used anymore and inetd-based services are managed by SMF, too. There indeed is a /etc/inetd.conf file if you check your file system: it's used as a configuration file to be fed as input of the inetconv utility during the configuration of a service. inetconv can be invoked with the -i option to use an alternate file, which is what I usually do. Then, touch a new empty file or make a copy of /etc/inetd.conf which will be used later to configure the SMF service.

inetd.conf syntax

The expected syntax for /etc/inetd.conf file *or the file you'll feed inetconv with) is the following (see the man page for more details):

service-name endpoint-type protocol wait-status uid server-program server-arguments
  • service-name: the name specified in the /etc/services file.
  • endpoint-type: the type of the endpoint, which can be stream, dgram, raw, seqpacket, tli.
  • protocol: a valid protocol entry in the /etc/inet/protocols file. Additionally, tcp6 and udp6 may also be used. In the case of RPC services, it's a string of the type rpc/* or rpc/..., where ... is a combination of nettypes and/or netids.
  • wait-status: this field may assume the values wait or nowait. Basically, it instructs inetd whether to pass over the listening socket to the service process and waiting for it to finish before resuming listening.
  • uid: the user id under which the service will run
  • server-program: the pathname of the server process executable or an internal name if inetd itself will provide this service.
  • server-arguments: the entire command line arguments for the service process, including the service process name itself (argument 0)

Subversion entry

The syntax to use for svnserve is the following:

svn stream tcp nowait svnuser /opt/csw/bin/svnserve svnserve -i -r /home/svnuser/svnrepos
  • I previously set up a standard user, svnuser, under which the Subversion service will run.
  • In this case I'm using the Subversion package installed from Blastwave which installs into /opt/csw/bin.
  • The repositories served by this instance are located into directory /home/svnuser/svnrepos.

Setting up the Subversion user

Creating the user

Subversion server process will run as a regular user called svnuser. This user is a basic user created with:

# useradd -d /export/home/svnuser -m -k /etc/skel -s /bin/bash svnserve
# passwd svnuser
[...]

Assuming that home automounting under /home is configured, I then modify the user with:


# usermod -d /home/svnuser svnuser

In my case, this user was created in the LDAP directory which I manage with Sun Java System Directory Server Enterprise Edition but basically the result is equivalent to running the above mentioned commands.

Creating a default user project (Solaris 10 specific)

I also created an user project for this user, called user.svnuser, so that processes launched after svnuser login will be associated with its project. The project I created just caps the CPU associated with its processes:

# projadd -K "project.cpu-cap=(privileged,50,deny)" user.svnserve

Setting up the SMF service (Solaris 10 specific)

After setting up inetd, under Solaris 10 we have to configure the described service with inetconv. inetconv it's an utility which reads files containing inetd.conf-like records and maps them to auto-generated SMF services. If the file we've generated it's called svn.conf, we have to run the following command:

# inetconv -i svn.conf

and a new SMF service description will be generated, imported and enabled.

Conclusion

Setting up inetd based services it's even easier with Solaris 10. Moreover, the powerful SMF framework will allow the sysadmin to manage and observe every service and enjoy the advantages of SMF. The only problem not (yet) addressed by this blog post is that a nowait inetd service is fork()-ed and exec()-ed by inetd and as Solaris 10 documentation states, during the fork() system call the process and task controls are inherited. This has the effect that even if svnserve is fork()-ed and then run under the svnuser account, the project.cpu-cap entry is having no effect. To discover how to configure an execution method of an SMF-managed service to run into a Solaris 10 project, read this post.


Next steps

You can now:

12 comments:

x said...

I'm unable to access the package repository you indicated. WOuld these instructions work well for say... the sunFreeware packages?

Knowing that the sunfreeware.com packages require Apache2.2.xx (for the svn 1.6.x) would that change anything?

Grey said...

Well, sometimes I had problems connecting to Blastwave too. By the way, are you behind a proxy? It would require additional steps to have wget use the proxy.

Using SunFreeware's packages would not change anything. SVN packages might depend on Apache 2.2 because you could access SVN repositories over HTTP or via WebDAV. This functionality is provided, for example, by two Apache modules. If you need it, setting up Apache is straight forward: The book "Version control with subversion" is your friend, here. You can read it and download it from http://svnbook.red-bean.com/. If your repositories lie behind a firewall, the HTTP protocol may be a viable solution not to configure the firewalls.

x said...

Okay, I'll try them again. My ultimate goal is really to install SVN in the least intrusive way possible. I'd prefer to have it use the default Solaris 10 "system" Apache rather than install yet-another Apache out in /usr/local just for the sake of SVN to work.

I guess my question is really if you know if the WebDAV Apache modules compiled in the Blastwave (or sunFreeware) binaries are compatible with the "stock" Solaris 10 System Apache. My guess is that they will not be, and SVN is such a horrendous pain to compile from scratch... Which is why I'm digging around hoping to find a turn-key-binary solution. :-)

But at least your article explains how I can setup the SVN to operate as a proper Solaris service, and that's something I needed too.

I've compiled and installed the entire zlib/openssh/apache/neon/apr/php/svn chain completely from scratch in Linux before (Slackware) but not Solaris. I'm sure I can do it, but I'd also like to do things "The Solaris Way" where possible.

Thanks for the quick response. I'll let you know if I find any bumps along the way!

Grey said...

You're welcome.

Yes, I understand. That was the kind of problem I went through when I had to setup my repositories. Unfortunately the Apache 2 that ships with Solaris 10 has no mod_svn and you have to go through a recompile. I did it on Slackware too and nowadays recompiling software on Solaris is pretty easier than before. You have a pretty modern GNU toolchain available and that's just a matter of time.

Blastwave packages are high quality packages, in my humble opinion, and I wouldn't go through a recompile just because I'm missing a module. Their packages, are also well organized and isolated. You aren't going to break your server! I also use a zone to do that: http://thegreyblog.blogspot.com/2008/04/setting-up-solaris-zone-for-blastwave.html

If you have to clone it, or move it, or back it up, it's easier, too.

Glad to help and have luck,
Grey.

George said...

Do you have a sample svn.conf? I'm a little unclear about the contents that should go in this file.

Grey said...

Hi George.

Yes I do. Basically it's just a one liner:

svn stream tcp nowait svnuser /opt/csw/bin/svnserve svnserve -i -r /home/svnuser/svnrepos

as I explained in the post. The 5th parameter is the uid, the user under which that process will run. The 6th and the 7th are the server program and its arguments. What's unclear to you?

George said...

Great! After rereading your blog, I missed the part apart having the inetd.conf entry be its own separate file (in this case svn.conf).

I went ahead and ran it and I'm up!


Thanks!

Grey said...

Yes, you're right, it isn't clear as I thought. Thanks to hear that it helped you. I'll fix it as soon as I can.

Bye,
Grey

Dave said...

Excellent guide to setting up Subversion on a Solaris 10 box. Thanks a bundle for the pointers.

I have to admit that the line where you state "In the case of Solaris 10, you should instead create an empty file which will be used later to configure the SMF service." threw me at first. Are we, or are we not creating the /etc/inetd.conf file? You do go on to state that we create the file, so I'm not sure for the reason for that line at all.

Last question: any reason you opted to not use the freely available Collab.net versions of Subversion? I like, and use blastwave & sunfreeware occasionally, but I find the dependencies seem a bit excessive, not to mention cumbersome at times.

Irregardless, thanks for the wonderful pointers.

Grey said...

Thank you Dave, I'm glad this information could help you.

As far as it concerns your first point, I admit you're absolutely right. I'm going to fix it as soon as I can. inetconv's -i option was used to avoid editing the /etc/inetd.conf file directly. Indeed, we're not editing that file, we're just using it as a template.

As far as it concerns your question about using collab.net subversion I've personally got an answer for you: http://thegreyblog.blogspot.com/2008/04/setting-up-solaris-zone-for-blastwave.html

As you can read in that post, I'm setting up Solaris 10 machine with a sparse zone where I install Blastwave's packages. Then, I loopback mount /opt/csw where I need. This way I keep things clean and separate: as far as it concerns my needs, Blastwave's packages are sufficient and I don't need installing packages here and there, especially in machines with a large number of sparse zones (we create at least one for each project our developers are working on).

Hope this helped,
Grey

Dave said...

Grey,

After reading that post on the blastwave install into a non-global zone, my eyes have been opened. It's an excellent way to mitigate the 'pollution' of the global zone with extraneous software, and something I'm sure our shop will adopt.

Of course I'm relatively new to Solaris, but the more I scratch at the surface (and dig around looking for articles like this one), the more I find to like about it. It has it's warts, but all software has warts, it's just whether or not you can live with 'em.
Thanks again for the excellent pointers, and have a great day.

Dave

Grey said...

Hi Dave.

Glad to see that this post was helpful.

Solaris is indeed a great piece of software. Since I started using it, I never thought to change it for anything else. It has its own idiosyncrasies but hey, everybody's got them!