oddmu-apache(5)

Name

oddmu-apache - how to setup Apache as a reverse proxy for Oddmu

Description

The oddmu program serves the current working directory as a wiki on port 8080. This is an unpriviledged port so an ordinary user account can do this. Alternatively, you can reverse proxy HTTP over a Unix-domain socket, as shown later.

The best way to protect the wiki against vandalism and spam is to use a regular web server as reverse proxy. This page explains how to setup Apache on Debian to do this.

Configuration

HTTPS is not part of Oddmu. You probably want to configure this in your webserver. I guess you could use stunnel, too. If you're using Apache, you can use "mod_md" to manage your domain.

The examples below use the domain "transjovian.org" and the Apache installation is the one that comes with Debian.

The site itself is configured in a file called "/etc/apache2/sites-available/transjovian.conf" and a link points there from "/etc/apache2/sites-enabled". Create this link using *a2ensite*(1).

MDomain transjovian.org
MDCertificateAgreement accepted
ServerAdmin alex@alexschroeder.ch

<VirtualHost *:80>
  ServerName transjovian.org
  Redirect "/" "https://transjovian.org/"
</VirtualHost>
<VirtualHost *:443>
  ServerName transjovian.org
  SSLEngine on
  ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|list|delete|rename|search|archive)/(.*))?$" \
                 "http://localhost:8080/$1"
</VirtualHost>

First, it manages the domain, getting the necessary certificates. It redirects regular HTTP traffic from port 80 to port 443. It turns on the SSL engine for port 443. It proxies the requests for Oddmu to port 8080. Importantly, it doesn't send *all* the requests to Oddmu. This allows us to still host static files using the web server (see **Serve static files**).

This is what happens:

Restart the server, gracefully:

apachectl graceful

In a situation where Apache acts as a reverse proxy, you can prevent some actions from being proxied. If you don't want to allow strangers to make changes, search or archive the site, use a limited setup like the following:

MDomain transjovian.org
MDCertificateAgreement accepted
ServerAdmin alex@alexschroeder.ch

<VirtualHost *:80>
  ServerName transjovian.org
  Redirect "/" "https://transjovian.org/"
</VirtualHost>
<VirtualHost *:443>
  ServerName transjovian.org
  SSLEngine on
  ProxyPassMatch "^/(view/.*)?$" "http://localhost:8080/$1"
</VirtualHost>

You'll need to edit the source pages some other way. Edit them locally and upload them using rsync; edit them remotely using an editor that can do this; use SSHFS to mount the remote directory locally for editing; use *stunnel*(8) to access the remote wiki on the local port 8080 for editing. There are probably a lot more such options available. All of them have the drawback that they're probably not easy to use when on a mobile phone.

Allow HTTP for viewing

When looking at pages, you might want to allow HTTP since no password is required. Therefore, proxy the read-only requests from the virtual host on port 80 to the wiki instead of redirecting them to port 443.

MDomain transjovian.org
MDCertificateAgreement accepted
ServerAdmin alex@alexschroeder.ch

<VirtualHost *:80>
  ServerName transjovian.org
  ProxyPassMatch "^/((view|diff|search|archive)/(.*))?$" \
                 "http://localhost:8080/$1"
  RedirectMatch  "^/((edit|save|add|append|upload|drop|list|delete|rename)/(.*))?$" \
                 "https://transjovian.org/$1"
</VirtualHost>
<VirtualHost *:443>
  ServerName transjovian.org
  SSLEngine on
  ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|list|delete|rename|search|archive)/(.*))?$" \
                 "http://localhost:8080/$1"
</VirtualHost>

Using a Unix-domain Socket

Instead of having Oddmu listen on a TCP port, you can have it listen on a Unix-domain socket. This requires socket activation. An example of configuring the service is given in *oddmu.service(5)*.

On the Apache side, you can proxy to the socket directly. This sends all requests to the socket:

ProxyPass "/" "unix:/run/oddmu/oddmu.sock|http://localhost/"

Now, all traffic between the web server and the wiki goes over the socket at "/run/oddmu/oddmu.sock".

To test it on the command-line, use a tool like *curl(1)*. Make sure to provide the correct servername!

curl http://transjovian.org/view/index

You probably want to serve some static files as well (see **Serve static files**). In that case, you need to use the ProxyPassMatch directive.

ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|list|delete|rename|search|archive)/(.*))?$" \
               "unix:/run/oddmu/oddmu.sock|http://localhost/$1"

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|preview|diff|edit|save|add|append|upload|drop|list|delete|rename|search|archive)/(.*))$" \
               "unix:/run/oddmu/oddmu.sock|http://localhost/$1"

If you know why this is happening, let me know.

Access

Access control is not part of Oddmu. By default, the wiki is editable by all. This is most likely not what you want unless you're running it stand-alone, unconnected to the Internet – a personal memex on your laptop, for example.

The following instructions create user accounts with passwords just for Oddmu. These users are not real users on the web server and don't have access to a shell, mail, or any other service.

Create a new password file called ".htpasswd" and add the user "alex". The "-c" flag creates the file.

cd /home/oddmu
htpasswd -c .htpasswd alex

To add more users, don't use the "-c" option or you will overwrite the existing file. To add another user, use no option at all.

htpasswd .htpasswd berta

To remove a user, use the "-D" option.

htpasswd -D .htpasswd berta

Modify your site configuration and protect the "/edit/", "/save/", "/add/", "/append/", "/upload/", "/drop/", "/list/", "/delete/" and "/rename/" URLs with a password by adding the following to your "" section:

<LocationMatch "^/(edit|save|add|append|upload|drop|list|delete|rename)/">
  AuthType Basic
  AuthName "Password Required"
  AuthUserFile /home/oddmu/.htpasswd
  Require valid-user
</LocationMatch>

The way Oddmu handles subdirectories is that all files and directories are visible, except for "hidden" files and directories (whose name starts with a period). Specifically, do not rely on Apache to hide locations in subdirectories from public view. Search reveals the existence of these pages and produces an extract, even if users cannot follow the links. Archive links pack all the subdirectories, including locations you may have hidden from view using Apache.

If you to treat subdirectories as separate sites, you need to set the environment variable ODDMU_FILTER to a regular expression matching the those directories. If search starts in a directory that doesn't match the regular expression, all directories matching the regular expression are excluded. See oddmu-filter(7).

oddmu-filter(7)

In the following example, ODDMU_FILTER is set to "^secret/".

`http://transjovian.org/search/index?q=something` does not search the "secret/" directory and its subdirectories are excluded.

`http://transjovian.org/search/secret/index?q=something` searches just the "secret" directory and its subdirectories.

You need to configure the web server to prevent access to the "secret/" directory:

<LocationMatch "^/(edit|save|add|append|upload|drop|list|delete|rename|(view|preview|search|archive)/secret)/">
  AuthType Basic
  AuthName "Password Required"
  AuthUserFile /home/oddmu/.htpasswd
  Require valid-user
</LocationMatch>

Serve static files

If you want to serve static files as well, add a document root to your webserver configuration. In this case, the document root is the directory where all the data files are. Apache does not serve files such as ".htpasswd".

DocumentRoot /home/oddmu
<Directory /home/oddmu>
  Require all granted
</Directory>

Make sure that none of the subdirectories look like the wiki paths "/view/", "/diff/", "/edit/", "/save/", "/add/", "/append/", "/upload/", "/drop/", "/list", "/delete/", "/rename/" "/search/" or "/archive/". For example, create a file called "robots.txt" containing the following, telling all robots that they're not welcome.

User-agent: *
Disallow: /

Your site now serves "/robots.txt" without interfering with the wiki, and without needing a wiki page.

Another option would be to create a CSS file and use it with a <link> element in all the templates instead of relying on the <style> element.

The "view.html" template would start as follows:

<!DOCTYPE html>
<html lang="{{.Language}}">
  <head>
    <meta charset="utf-8">
    <meta name="format-detection" content="telephone=no">
    <meta name="viewport" content="width=device-width">
    <title>{{.Title}}</title>
    <link href="/css/oddmu-2023.css" rel="stylesheet" />
    <link rel="alternate" type="application/rss+xml" title="Alex Schroeder: {{.Title}}" href="/view/{{.Name}}.rss" />
  </head>
…

In this case, "/css/oddmu-2023.css" would be the name of your stylesheet. If your document root is "/home/oddmu", then the filename of your stylesheet would have to be "/home/oddmu/css/oddmu-2023.css" for this to work.

Different logins for different access rights

What if you have a site with various subdirectories and each subdirectory is for a different group of friends? You can set this up using your webserver. One way to do this is to require specific usernames (which must have a password in the password file mentioned above.

This requires a valid login by the user "alex" or "berta":

<LocationMatch "^/(edit|save|add|append|upload|drop|list|delete|rename)/intetebi/">
  Require user alex berta
</LocationMatch>

Private wikis

Based on the above, you can prevent people from *reading* the wiki. The location must cover all the URLs in order to protect everything.

<Location />
  AuthType Basic
  AuthName "Password Required"
  AuthUserFile /home/oddmu/.htpasswd
  Require valid-user
</Location>

Virtual hosting

Virtual hosting in this context means that the program serves two different sites for two different domains from the same machine. Oddmu doesn't support that, but your webserver does. Therefore, start an Oddmu instance for every domain name, each listening on a different port. Then set up your web server such that ever domain acts as a reverse proxy to a different Oddmu instance.

See also

oddmu(1), oddmu-filter(7), oddmu-nginx(5)

oddmu(1)

oddmu-filter(7)

oddmu-nginx(5)

"Apache Core Features". https://httpd.apache.org/docs/current/mod/core.html

https://httpd.apache.org/docs/current/mod/core.html

"Apache: Authentication and Authorization". https://httpd.apache.org/docs/current/howto/auth.html

https://httpd.apache.org/docs/current/howto/auth.html

"Apache Module mod_proxy". https://httpd.apache.org/docs/current/mod/mod_proxy.html

https://httpd.apache.org/docs/current/mod/mod_proxy.html

"Robot exclusion standard" on Wikipedia. https://en.wikipedia.org/wiki/Robot_exclusion_standard

https://en.wikipedia.org/wiki/Robot_exclusion_standard

"<style>: The Style Information element" https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style

"<link>: The External Resource Link element" https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link

Authors

Maintained by Alex Schroeder alex@gnu.org.

alex@gnu.org