Saturday 17 January 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:

No comments:

Post a Comment