Serving Oddµ via a socket

Recently, Chris Brannon sent me a patch for Oddµ that allowed it to listen at a Unix-domain socket instead of a host and port.

Chris Brannon

Oddµ

I decided to investigate since I don't know anything about sockets. If you see something that can be improved, let me know.

I'm going to use systemd, but for my user.

I have two files, one for the socket and one for the service. These are not the same files as the ones provided with the Oddµ sources. Those are intended to be used together with a web server that acts as a reverse proxy. These files are for me testing the installation using netcat and curl.

Socket

Make sure the directory for the socket exists:

mkdir --parents /home/alex/.local/run/oddmu

This is the file "oddmu-unix-domain.socket":

[Unit]
Description=Oddmu server socket
[Socket]
ListenStream=/home/alex/.local/run/oddmu/oddmu.sock
Accept=no
[Install]
WantedBy=sockets.target

Enable and start it:

systemctl --user enable ./oddmu-unix-domain.socket
systemctl --user start oddmu-unix-domain.socket

Service

Make sure the directory for the wiki exists and copy the template files:

mkdir --parents /home/alex/.local/share/oddmu
cp *.html /home/alex/.local/share/oddmu

This is the file "oddmu-unix-domain.service":

[Unit]
Description=Oddmu
After=network.target
Requires=oddmu-unix-domain.socket
[Install]
WantedBy=default.target
[Service]
Type=simple
Restart=always
StandardInput=socket
StandardOutput=journal
StandardError=journal
ExecStart=/home/alex/src/oddmu/oddmu
WorkingDirectory=/home/alex/.local/share/oddmu
Environment="ODDMU_WEBFINGER=1"
Environment="ODDMU_LANGUAGES=de,en"

This doesn't limit a lot of capabilities, but I guess I trust my own code.

Install it:

systemctl --user enable ./oddmu-unix-domain.service
systemctl --user start oddmu-unix-domain.service

Test

Check the journal:

journalctl --user --follow --unit oddmu-unix-domain

Do some requests using netcat:

echo -e "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n" \
  | ncat --unixsock ~/.local/run/oddmu/oddmu.sock
echo -e "GET /view/index HTTP/1.1\r\nHost: localhost\r\n\r\n" \
  | ncat --unixsock ~/.local/run/oddmu/oddmu.sock
echo -e "GET /edit/index HTTP/1.1\r\nHost: localhost\r\n\r\n" \
  | ncat --unixsock ~/.local/run/oddmu/oddmu.sock

Using curl:

curl --unix-socket ~/.local/run/oddmu/oddmu.sock \
  http://localhost/edit/index
curl --unix-socket ~/.local/run/oddmu/oddmu.sock \
  --form body="Hello!" http://localhost/save/index
curl --unix-socket ~/.local/run/oddmu/oddmu.sock \
  http://localhost/view/index

What now?

I don't think I'm going to change my web server setup. But using sockets and `systemctl --user` has been interesting.

Thank you, Chris Brannon, for sending that patch!

Apache

If you're installing Apache for the first time, on Debian:

sudo apt install apache2
sudo a2enmod proxy proxy_http

Create a file "/etc/apache2/sites-available/oddmu.conf":

<VirtualHost *:80>
    ServerName localhost
    ProxyPassMatch "^/((view|diff|edit|save|add|append|upload|drop|search)/(.*))?$" \
      "unix:/home/alex/.local/run/oddmu/oddmu.sock|http://localhost/$1"
</VirtualHost>

Restart Apache to load the module configuration and the site configuration.

sudo a2ensite oddmu
sudo systemctl restart 

Test it:

curl http://localhost/view/index

There's a curious problem with this expression, however. If you use *curl(1)* to get the root path, Apache hangs:

curl http://transjovian.org/

A workaround is to add the redirect manually and drop the question-mark:

RedirectMatch "^/$" "/view/index"
ProxyPassMatch "^/((view|diff|edit|save|add|append|upload|drop|search)/(.*))$" \
      "unix:/home/alex/.local/run/oddmu/oddmu.sock|http://localhost/$1"

New release

Yeah, I think this Unix domain socket stuff is cool enough to warrant a release. I migrated my three sites over to this setup. No more weird ports.

​#Oddµ ​#Administration