Setting up a gemini capsule using the gemini-php server

If you look at the list of gemini server software, there is a wide selection! Having no better heuristic, I just chose one that is written in a language I’m comfortable with and which looked simple to configure. gemini-php it is!

It was mostly simple and the instructions were straightforward but I’ll document a few gotchas and the tweaks I made here.

SSL certificate

When you generate your certificate be sure to increase the number of days from 365 to 36500 because if you don’t then in a year’s time everyone who visited your capsule will receive a scary warning when you issue a new certificate. Just make it expire in 100 years.

During the creation process openssl will ask a few questions. You can type anything for most of them but for the FQDN question be sure to put your domain name in so the certificate matches the URL you’ll be serving from. e.g. in my case.


gemini-php wants to serve files from a subdirectory called “hosts/default”, but I’m using the WP2Smol wordpress plugin to generate gemtext files and they all get created in a subdirectory of my wordpress installation. It was a bit tricky to point gemini-php at that directory. In the end I created a symlink in the hosts directory:

ls -l ~/gemini-php/hosts
total 4
default -> /home/bitnami/smol/wp-content/gemini

Little bit of code hacking

In gemini.class.php there is a security check to guard against path traversal attacks. This was incompatible with my symlink trick above so I needed to disable it. Find the line that says

// check the real path is in the data_dir (path traversal sanity check)

and insert this code below it:

return $return_path;

Gemini-php assumes all your gemtext files have a .gemini extension, which is odd. Add support for .gmi files by amending this code:

if(empty($path_parts['extension']) or $path_parts['extension'] == "gemini")
   $type = "text/gemini";

To be

if(empty($path_parts['extension']) or $path_parts['extension'] == "gemini" or $path_parts['extension'] == "gmi")
$type = "text/gemini";

Finally, find the this code fragment and tweak it slightly:

$valid_hosts = $this->get_valid_hosts();
if(!in_array($hostname, $valid_hosts))
   $hostname = "default";

Just change what $hostname gets set to:

$valid_hosts = $this->get_valid_hosts();
if(!in_array($hostname, $valid_hosts))
   $hostname = "";

With a bit of luck, that’ll do it!