I'd like to make the SUID wrapper optional.

A wrapper is a binary that can be marked setuid (+s): this is not (easily) possible with scripts (such as Perl scripts or bash scripts), so IkiWiki generates a small C program that is compiled into a native binary and set +s. The reason to do that is so that the IkiWiki instance that is invoked by the wrapper runs as the user who owns the wiki's files, rather than the user running the HTTPD.

At the moment, it's pretty much mandatory for IkiWiki to generate wrappers. (It might be possible to prevent it by tinkering with the internal config value wrappers.) I'd like to make it optional.

There are some deployment scenarios (including containers) where it isn't necessary, and removing the requirement for a C compiler would be advantageous.

The content of the wrapper's source code is embedded across IkiWiki/Wrapper.pm, which makes it hard to reason about.

One step would be to add a configuration variable to selectively disable generating the wrappers. However, the wrappers don't just invoke IkiWiki, they do some work (exactly what depends on several other configuration variables). So another step will be to identify that work and, if possible, move it out of the wrapper and into the IkiWiki instance invoked by the wrapper.

Jon, 2025-05-09

Point of support: a non-container deployment pattern that also has no need for suid wrappers is to store the files (and run the webserver) under a site-specific user account. Many of my sites do this.

-- schmonz

stuff the cgi wrapper does

  1. genwrapper hooks (used by at least cvs and git)
  2. blanks the environment and selectively adds a set of variables back
  3. adds an encoding of the %config hash to the variable WRAPPED_OPTIONS (with 'cgi' => 1 set)
  4. drops real GID and real UID (the webserver's) by overwriting them with the effective values (wrapper file owner)
  5. handles the logic for CGI_OVERLOAD_DELAY
  6. takes the CGI lock
  7. handles wrapper_background_command (which means handling git_wrapper_background_command) (which are not yet documented)
  8. calls ikiwiki with no command-line arguments

ikiwiki, called with no command-line arguments, does

  1. getconfig which populates from WRAPPED_OPTIONS
  2. loadplugins
  3. checkconfig
  4. checks $config{cgi}, evals IkiWiki::CGI::cgi()

Without the CGI wrapper, we might not need 1-4 (from the first list above), but we would need to implement 5-7, and either set up WRAPPED_OPTIONS or otherwise pass the necessary arguments.

I wonder if we could move 4-6 from list 1 into IkiWiki::CGI::cgi(). I guess it depends what the lock is for. It's not just a write lock, it's part of load management. At some point I guess mutexing the loading of the perl interpreter was worthwhile. I wonder if that's as much of a problem Today. If we loaded Perl and got as far as IkiWiki::CGI::cgi(), are we still saving some heavy lifting with the lock?

Jon, 2025-10-02

note that IkiWiki::CGI::cgi() takes the write lock (lockwiki()) fairly early on, although after CGI hooks. Jon, 2025-10-07

stuff the post-update hook does

  1. takes the commitlock
  2. clears the environment and adds back PATH,HOME and WRAPPED_OPTIONS ('cgi' => 0)
  3. drops real GID and real UID (the webserver's) by overwriting them with the effective values (wrapper file owner)
  4. handles wrapper_background_command (which means handling git_wrapper_background_command) (which are not yet documented)
  5. calls ikiwiki with no command-line arguments

Jon, 2025-10-04

Replacing the post-update hook is relatively easy. I'm experimenting with this in opinionated-ikiwiki, which already wraps the wrapper to do additional container-specific stuff: I've disabled generating the git wrapper, and extended my wrapper-wrapper to call ikiwiki --setup… --refresh instead of the wrapper. I'm happy to sacrifice support for wrapper_background_command in this configuration. Jon, 2025-10-02