App-phoebe
view release on metacpan or search on metacpan
# Phoebe Wiki
**Table of Contents**
- [Phoebe](#phoebe)
- [Gemtext](#gemtext)
- [Editing the wiki](#editing-the-wiki)
- [Editing via the web](#editing-via-the-web)
- [Installation](#installation)
- [Dependencies](#dependencies)
- [Quickstart](#quickstart)
- [Image uploads](#image-uploads)
- [Using systemd](#using-systemd)
- [Troubleshooting](#troubleshooting)
- [Files](#files)
- [Options](#options)
- [Uploads](#uploads)
- [Notes](#notes)
- [Security](#security)
- [Privacy](#privacy)
- [Example](#example)
- [Certificates and File Permission](#certificates-and-file-permission)
- [Main Page and Title](#main-page-and-title)
- [robots.txt](#robots-txt)
- [Configuration](#configuration)
- [Wiki Spaces](#wiki-spaces)
- [Tokens per Wiki Space](#tokens-per-wiki-space)
- [Virtual Hosting](#virtual-hosting)
- [Multiple Certificates](#multiple-certificates)
- [See also](#see-also)
- [License](#license)
- [Gemini](#gemini)
- [Client Certificates](#client-certificates)
- [Gemini](#gemini)
- [Ijirait](#ijirait)
- [phoebe-ctl](#phoebe-ctl)
- [Commands](#commands)
- [Spartan](#spartan)
- [Titan](#titan)
- [App::Phoebe](#appphoebe)
- [App::Phoebe::BlockFediverse](#appphoebeblockfediverse)
- [App::Phoebe::Chat](#appphoebechat)
- [App::Phoebe::Comments](#appphoebecomments)
- [App::Phoebe::Css](#appphoebecss)
- [App::Phoebe::DebugIpNumbers](#appphoebedebugipnumbers)
- [App::Phoebe::Favicon](#appphoebefavicon)
- [App::Phoebe::Galleries](#appphoebegalleries)
- [App::Phoebe::Gopher](#appphoebegopher)
- [App::Phoebe::HeapDump](#appphoebeheapdump)
- [App::Phoebe::Iapetus](#appphoebeiapetus)
- [App::Phoebe::Ijirait](#appphoebeijirait)
- [App::Phoebe::MokuPona](#appphoebemokupona)
- [App::Phoebe::Oddmuse](#appphoebeoddmuse)
- [App::Phoebe::PageHeadings](#appphoebepageheadings)
- [App::Phoebe::RegisteredEditorsOnly](#appphoeberegisterededitorsonly)
- [App::Phoebe::Spartan](#appphoebespartan)
- [App::Phoebe::SpeedBump](#appphoebespeedbump)
- [App::Phoebe::StaticFiles](#appphoebestaticfiles)
- [App::Phoebe::TokiPona](#appphoebetokipona)
- [App::Phoebe::Web](#appphoebeweb)
- [App::Phoebe::WebComments](#appphoebewebcomments)
- [App::Phoebe::WebEdit](#appphoebewebedit)
- [App::Phoebe::Wikipedia](#appphoebewikipedia)
# Phoebe
**phoebe** \[**--host=**_hostname_ ...\] \[**--port=**_port_\]
\[**--cert\_file=**_filename_\] \[**--key\_file=**_filename_\]
\[**--log\_level=error**|**warn**|**info**|**debug**\] \[**--log\_file=**_filename_\]
\[**--wiki\_dir=**_directory_\] \[**--wiki\_token=**_token_ ...\]
\[**--wiki\_page=**_pagename_ ...\] \[**--wiki\_main\_page=**_pagename_\]
\[**--wiki\_mime\_type=**_mimetype_ ...\] \[**--wiki\_page\_size\_limit=**_n_\]
\[**--wiki\_space=**_space_ ...\]
Phoebe does two and a half things:
It's a program that you run on a computer and other people connect to it using
It's a wiki, which means that people can edit the pages without needing an
account. All they need is a client that speaks both Gemini and Titan, and the
password. The default password is "hello". ð
Optionally, people can also access it using a regular web browser.
Gemini itself is very simple network protocol, like Gopher or Finger, but with
TLS. Gemtext is a very simple markup language, a bit like Markdown, but line
oriented. See ["GEMTEXT"](#gemtext).
To take a look for yourself, check out the test wiki via the web or via the web.
- [What is Gemini?](https://gemini.circumlunar.space/)
- [Gemini link collection](https://git.sr.ht/~kr1sp1n/awesome-gemini)
- [Test site, via the web](https://transjovian.org:1965/test)
- [Test site, via Gemini](gemini://transjovian.org/test)
# Gemtext
Pages are written in gemtext, a lightweight hypertext format. You can use your
favourite text editor to write them.
A text line is a paragraph of text.
This is a paragraph.
This is another paragraph.
A link line starts with "=>", a space, a URL, optionally followed by whitespace
and some text; the URL can be absolute or relative.
=> http://transjovian.org/ The Transjovian Council on the web
=> Welcome Welcome to The Transjovian Council
A line starting with "\`\`\`" toggles preformatting on and off.
Example:
```
./phoebe
```
A line starting with "#", "##", or "###", followed by a space and some text is a
heading.
## License
The GNU Affero General Public License.
A line starting with "\*", followed by a space and some text is a list item.
* one item
* another item
A line starting with ">", followed by a space and some text is a quote.
The monologue at the end is fantastic, with the city lights and the rain.
> I've seen things you people wouldn't believe.
# Editing the wiki
How do you edit a Phoebe wiki? You need to use a Titan-enabled client.
Titan is a companion protocol to Gemini: it allows clients to upload files to
Gemini sites, if servers allow this. On Phoebe, you can edit "raw" pages. That
is, at the bottom of a page you'll see a link to the "raw" page. If you follow
it, you'll see the page content as plain text. You can submit a changed version
of this text to the same URL using Titan. There is more information for
developers available on Community Wiki. [https://communitywiki.org/wiki/Titan](https://communitywiki.org/wiki/Titan)
Known clients:
This repository comes with a Perl script called `titan` to upload files.
[https://alexschroeder.ch/cgit/phoebe/plain/titan](https://alexschroeder.ch/cgit/phoebe/plain/titan)
_Gemini Write_ is an extension for the Emacs Gopher and Gemini client
_Elpher_. [https://alexschroeder.ch/cgit/gemini-write/](https://alexschroeder.ch/cgit/gemini-write/)
[https://thelambdalab.xyz/elpher/](https://thelambdalab.xyz/elpher/)
Gemini & Titan for Bash are two shell functions that allow you to download and
upload files. [https://alexschroeder.ch/cgit/gemini-titan/about/](https://alexschroeder.ch/cgit/gemini-titan/about/)
## Editing via the web
The Configuration section of the Phoebe space on _The Transjovian Council_ has
an example config on how to enable editing via the web.
- [https://transjovian.org:1965/phoebe/page/Configuration](https://transjovian.org:1965/phoebe/page/Configuration)
- [gemini://transjovian.org/phoebe/page/Configuration](gemini://transjovian.org/phoebe/page/Configuration)
# Installation
Using `cpan`:
cpan App::phoebe
Manual install:
perl Makefile.PL
make
make install
## Dependencies
If you are not using `cpan` or `cpanm` to install Phoebe, you'll need to
install the following dependencies:
- [Algorithm::Diff](https://metacpan.org/pod/Algorithm%3A%3ADiff), or `libalgorithm-diff-xs-perl`
- [File::ReadBackwards](https://metacpan.org/pod/File%3A%3AReadBackwards), or `libfile-readbackwards-perl`
- [File::Slurper](https://metacpan.org/pod/File%3A%3ASlurper), or `libfile-slurper-perl`
- [Mojolicious](https://metacpan.org/pod/Mojolicious), or `libmojolicious-perl`
- [IO::Socket::SSL](https://metacpan.org/pod/IO%3A%3ASocket%3A%3ASSL), or `libio-socket-ssl-perl`
- [Modern::Perl](https://metacpan.org/pod/Modern%3A%3APerl), or `libmodern-perl-perl`
- [URI::Escape](https://metacpan.org/pod/URI%3A%3AEscape), or `liburi-escape-xs-perl`
- [Net::IDN::Encode](https://metacpan.org/pod/Net%3A%3AIDN%3A%3AEncode), or `libnet-idn-encode-perl`
- [Encode::Locale](https://metacpan.org/pod/Encode%3A%3ALocale), or `libencode-locale-perl`
I'm going to be using `curl` and `openssl` in the ["Quickstart"](#quickstart) instructions,
so you'll need those tools as well. And finally, when people download their
data, the code calls `tar` (available from packages with the same name on
Debian derived systems).
The `update-readme.pl` script I use to generate `README.md` also requires some
libraries:
- [Pod::Markdown](https://metacpan.org/pod/Pod%3A%3AMarkdown), or `libpod-markdown-perl`
- [Text::Slugify](https://metacpan.org/pod/Text%3A%3ASlugify), which has no Debian package, apparently ð
## Quickstart
I'm going to assume that you're going to create a new user just to be safe.
sudo adduser --disabled-login --disabled-password phoebe
sudo su phoebe --shell=/bin/bash
cd
Now you're in your home directory, `/home/phoebe`. We're going to install
things right here.
cpan App::phoebe
Start Phoebe. It's going to prompt you for a hostname and create certificates
for you. If in doubt, answer `localhost`. The certificate and a private key are
stored in the `cert.pem` and `key.pem` files, using elliptic curves, valid for
five years, without password protection.
perl5/bin/phoebe
This starts the server in the foreground. If it aborts, see the
["Troubleshooting"](#troubleshooting) section below. If it runs, open a second terminal and test
it:
perl5/bin/gemini gemini://localhost/
You should see a Gemini page starting with the following:
20 text/gemini; charset=UTF-8
Welcome to Phoebe!
Success!! ð ðð
Let's create a new page using the Titan protocol, from the command line:
echo "Welcome to the wiki!" > test.txt
echo "Please be kind." >> test.txt
perl5/bin/titan --url=titan://localhost/raw/Welcome --token=hello test.txt
You should get a nice redirect message, with an appropriate date.
30 gemini://localhost:1965/page/Welcome
You can check the page, now (replacing the appropriate date):
perl5/bin/gemini gemini://localhost:1965/page/Welcome
You should get back a page that starts as follows:
20 text/gemini; charset=UTF-8
Welcome to the wiki!
Please be kind.
Yay! ðð ðð
If you have a bunch of Gemtext files in a directory, you can upload them all in
one go:
titan --url=titan://localhost/ --token=hello *.gmi
## Image uploads
OK, how do image uploads work? First, we need to specify which MIME types Phoebe
accepts. The files are going to be served back with that MIME type, so even if
somebody uploads an executable and claim it's an image, other people's clients
will treat it as an image instead of executing it (one hopes!) â so let's start
with a list of common MIME types.
- `image/jpeg` is for photos (usually with the `jpg` extension)
- `image/png` is for graphics (usually with the `png` extension)
- `audio/mpeg` is for sound (usually with the `mp3` extension)
Let's continue using the setup we used for the ["Quickstart"](#quickstart) section. Restart
the server and allow photos:
perl5/bin/phoebe --wiki_mime_type=image/jpeg
Upload the image using the `titan` script:
perl5/bin/titan --url=titan://localhost:1965/jupiter.jpg \
--token=hello Pictures/Planets/Juno.jpg
You should get back a redirect to the uploaded image:
30 gemini://localhost:1965/file/jupiter.jpg
How did the `titan` script know the MIME-type to use for the upload? If you
don't specify a MIME-type using `--mime`, the `file` utility is called to
guess the MIME type of the file.
Test it:
file --mime-type --brief Pictures/Planets/Juno.jpg
The result is the MIME-type we enabled for our wiki:
image/jpeg
Here's what happens when you're trying to upload an unsupported MIME-type:
titan --url=titan://localhost:1965/earth.png \
--token=hello Pictures/Planets/Earth.png
What you get back explains the problem:
59 This wiki does not allow image/png
In order to allow such graphics as well, you need to restart Phoebe:
phoebe --wiki_mime_type=image/jpeg --wiki_mime_type=image/png
Except that in my case, the image is too big:
59 This wiki does not allow more than 100000 bytes per page
I could scale it down before I upload the image, using `convert` (which is part
of ImageMagick):
convert -scale 20% Pictures/Planets/Earth.png earth-small.png
Try again:
titan --url=titan://localhost:1965/earth.png \
--token=hello earth-small.png
Alternatively, you can increase the size limit using the
`--wiki_page_size_limit` option, but you need to restart Phoebe:
phoebe --wiki_page_size_limit=10000000 \
--wiki_mime_type=image/jpeg --wiki_mime_type=image/png
Now you can upload about 10MBâ¦
## Using systemd
Systemd is going to handle daemonisation for us. There's more documentation
available online.
[https://www.freedesktop.org/software/systemd/man/systemd.service.html](https://www.freedesktop.org/software/systemd/man/systemd.service.html).
Basically, this is the template for our service:
[Unit]
Description=Phoebe
After=network.target
[Service]
Type=simple
WorkingDirectory=/home/phoebe
ExecStart=/home/phoebe/phoebe
Restart=always
User=phoebe
Group=phoebe
MemoryMax=100M
MemoryHigh=90M
[Install]
WantedBy=multi-user.target
Save this as `phoebe.service`, and then link it:
sudo ln -s /home/phoebe/phoebe.service /etc/systemd/system/
Reload systemd:
sudo systemctl daemon-reload
Start Phoebe:
sudo systemctl start phoebe
Check the log output:
sudo journalctl --unit phoebe
## Troubleshooting
ð¥ **1408A0C1:SSL routines:ssl3\_get\_client\_hello:no shared cipher** ð¥ If you
created a new certificate and key using elliptic curves using an older OpenSSL,
you might run into this. Try to create a RSA key instead. It is larger, but at
least it'll work.
openssl req -new -x509 -newkey rsa \
-days 1825 -nodes -out cert.pem -keyout key.pem
# Files
Your home directory should now also contain a wiki directory called `wiki`,
your wiki directory. In it, you'll find a few more files:
`page` is the directory with all the page files in it; each file has the `gmi`
extension and should be written in Gemtext format
`index` is a file containing all the files in your `page` directory for quick
access; if you create new files in the `page` directory, you should delete the
`index` file â it will get regenerated when needed; the format is one page name
(without the `.gmi` extension) per line, with lines separated from each other
by a single `\n`
`keep` is the directory with all the old revisions of pages in it â if you've
only made one change, then it won't exist; if you don't care about the older
revisions, you can delete them; assuming you have a page called `Welcome` and
edit it once, you have the current revision as `page/Welcome.gmi`, and the old
revision in `keep/Welcome/1.gmi` (the page name turns into a subdirectory and
each revision gets an apropriate number)
`file` is the directory with all the uploaded files in it â if you haven't
uploaded any files, then it won't exist; you must explicitly allow MIME types
for upload using the `--wiki_mime_type` option (see _Options_ below)
`meta` is the directory with all the meta data for uploaded files in it â there
should be a file here for every file in the `file` directory; if you create new
files in the `file` directory, you should create a matching file here; if you
have a file `file/alex.jpg` you want to create a file `meta/alex.jpg`
containing the line `content-type: image/jpeg`
`changes.log` is a file listing all the pages made to the wiki; if you make
changes to the files in the `page` or `file` directory, they aren't going to
be listed in this file and thus people will be confused by the changes you made
â your call (but in all fairness, if you're collaborating with others you
probably shouldn't do this); the format is one change per line, with lines
separated from each other by a single `\n`, and each line consisting of time
stamp, pagename or filename, revision number if a page or 0 if a file, and the
numeric code of the user making the edit (see ["Privacy"](#privacy) below), all separated
from each other with a `\x1f`
`config` probably doesn't exist, yet; it is an optional file containing Perl
code where you can add new features and change how Phoebe works (see
["Configuration"](#configuration) below)
`conf.d` probably doesn't exist, either; it is an optional directory containing
even more Perl files where you can add new features and change how Phoebe works
(see ["Configuration"](#configuration) below); the idea is that people can share stand-alone
configurations that you can copy into this directory without having to edit your
own `config` file.
# Options
- `--wiki_token` is for the token that users editing pages have to
provide; the default is "hello"; you can use this option multiple times
and give different users different passwords, if you want
- `--wiki_page` is an extra page to show in the main menu; you can use
this option multiple times; this is ideal for general items like _About_
or _Contact_
- `--wiki_main_page` is the page containing your header for the main
page; that's were you would put your ASCII art header, your welcome
message, and so on, see ["Main Page and Title"](#main-page-and-title) below
- `--wiki_mime_type` is a MIME type to allow for uploads; text/plain is
always allowed and doesn't need to be listed; you can also just list the
type without a subtype, eg. `image` will allow all sorts of images (make
sure random people can't use your server to exchange images â set a
password using `--wiki_token`)
- `--wiki_page_size_limit` is the number of bytes to allow for uploads,
both for pages and for files; the default is 10000 (10kB)
- `--host` is the hostname to serve; the default is `localhost` â you
probably want to pick the name of your machine, if it is reachable from
the Internet; if you use it multiple times, each host gets its own wiki
space (see `--wiki_space` below)
- `--port` is the port to use; the default is 1965
- `--wiki_dir` is the wiki data directory to use; the default is either
the value of the `PHOEBE_DATA_DIR` environment variable, or the "./wiki"
subdirectory
- `--wiki_space` adds an extra space that acts as its own wiki; a
subdirectory with the same name gets created in your wiki data directory
and thus you shouldn't name spaces like any of the files and directories
already there (see ["FILES"](#files)); not that settings such as
`--wiki_page` and `--wiki_main_page` apply to all spaces, but the page
content will be different for every wiki space
- `--cert_file` is the certificate PEM file to use; the default is
`cert.pem`
- `--key_file` is the private key PEM file to use; the default is
`key.pem`
- `--log_level` is the log level to use (`fatal`, `error`, `warn`,
`info`, `debug`); the default is `warn`
- `--log_file` is the log file to use; the default is undefined, which
means that STDERR is used
## Uploads
If you allow uploads of binary files, these are stored separately from the
regular pages; the wiki doesn't keep old revisions of files around. If somebody
overwrites a file, the old revision is gone.
You definitely don't want random people uploading all sorts of images, videos
and binaries to your server. Make sure you set up those [tokens](#security)
using `--wiki_token`!
# Notes
## Security
The server uses "access tokens" to check whether people are allowed to edit
files. You could also call them "passwords", if you want. They aren't associated
with a username. You set them using the `--wiki_token` option. By default, the
only password is "hello". That's why the Titan command above contained
"token=hello". ð
If you're going to check up on your wiki often (daily!), you could just tell
people about the token on a page of your wiki. Spammers would at least have to
read the instructions and in my experience the hardly ever do.
You could also create a separate password for every contributor and when they
leave the project, you just remove the token from the options and restart
Phoebe. They will no longer be able to edit the site.
## Privacy
The server only actively logs changes to pages. It calculates a "code" for every
contribution: it is a four digit octal code. The idea is that you could colour
every digit using one of the eight standard terminal colours and thus get little
four-coloured flags.
This allows you to make a pretty good guess about edits made by the same person,
without telling you their IP numbers.
The code is computed as follows: the IP numbers is turned into a 32bit number
using a hash function, converted to octal, and the first four digits are the
code. Thus all possible IP numbers are mapped into 8â´=4096 codes.
If you increase the log level, the server will produce more output, including
information about the connections happening, like `2020/06/29-15:35:59 CONNECT
SSL Peer: "[::1]:52730" Local: "[::1]:1965"` and the like (in this case `::1`
is my local address so that isn't too useful but it could also be your visitor's
IP numbers, in which case you will need to tell them about it using in order to
comply with the
[GDPR](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation).
# Example
Here's an example for how to start Phoebe. It listens on `localhost` port 1965,
adds the "Welcome" and the "About" page to the main menu, and allows editing
using one of two tokens.
phoebe \
--wiki_token=Elrond \
--wiki_token=Thranduil \
--wiki_page=Welcome \
--wiki_page=About
Here's what my `phoebe.service` file actually looks like:
[Unit]
Description=Phoebe
After=network.target
This command removes pages from the `page` directory, removes all the kept
revisions in the `keep` directory, and all the mentions in the `change.log`.
Use this if spammers and vandals created page names you want to eliminate.
**phoebe-ctl html-export** \[**--source=**`subdirectory` ...\]
\[**--target=**`directory`\] \[**--no-extension**\]
This command converts all the pages in the subdirectories provided to HTML and
writes the HTML files into the target directory. The subdirectories must exist
inside your wiki data directory. The default wiki data directory is `wiki` and
the default source subdirectory is undefined, so the actual files to be
processed are `wiki/page/*.gmi`; if you're using virtual hosting, the
subdirectory might be your host name; if you're using spaces, those need to be
appended as well.
Example:
phoebe-ctl html-export --wiki_dir=/home/alex/phoebe \
--source=transjovian.org \
--source=transjovian.org/phoebe \
--source=transjovian.org/gemini \
--source=transjovian.org/titan \
--target=/home/alex/transjovian.org
This will create HTML files in `/home/alex/transjovian.org`,
`/home/alex/transjovian.org/phoebe`, `/home/alex/transjovian.org/gemini`, and
`/home/alex/transjovian.org/titan`.
Note that the _links_ in these HTML files do not include the `.html` extension
(e.g. `/test`), so this relies on your web server doing the right thing: if a
visitor requests `/test` the web server must serve `/test.html`. If that
doesn't work, perhaps using `--no-extension` is your best bet: the HTML files
will be written without the `.html` extension. This should also work for local
browsing, although it does look strange, all those pages with the `.html`
extension.
# Spartan
**titan** \[**--help**\] \[**--verbose**\] _URL_
This is a very simple test client. All it does is print the response. The header
is printed to standard error so the rest can be redirected to get just the
content.
spartan URL
Usage:
spartan spartan://mozz.us/
Send some text:
echo "Hello $USER!" | script/spartan spartan://mozz.us/echo
# Titan
**titan** \[**--help**\] **--url=**_URL_ \[**--token=**_TOKEN_\] \[**--mime=**_MIMETYPE_\]
\[**--cert\_file=**_FILE_ **--key\_file=**_FILE_\] \[_FILES_ ...\]
This is a script to upload content to a Titan-enabled site like Phoebe.
**--url=URL** specifies the Titan URL to use; this should be really similar to
the Gemini URL you used to read the page.
**--token=TOKEN** specifies the token to use; this is optional but spammers and
vandals basically ensured that any site out on the Internet needs some sort of
protection; how to get a token depends on the site you're editing.
**--mime=MIMETYPE** specifies the MIME type to send to the server. If you don't
specify a MIME type, the `file` utility is used to determine the MIME type of
the file you're uploading.
**FILES...** are the files to upload, if any; this is optional: you can also use
a pipe, or type a few words by hand (terminating it with a Ctrl-D, the end of
transmission byte).
Note that if you specify multiple files, the URL must end in a slash and all the
filenames are used as page names. So, uploading `Alex.gmi` and `Berta.gmi` to
`titan://localhost/` will create `gemini://localhost/Alex` and
`gemini://localhost/Berta`.
The following two options control the use of client certificates:
**--cert\_file=FILE** specifies an optional client certificate to use; if you
don't specify one, the default is to try to use `client-cert.pem` in the
current directory.
**--key\_file=FILE** specifies an optional client certificate key to use; if you
don't specify one, the default is to try to use `client-key.pem` in the current
directory.
Usage:
echo "This is my test." > test.txt
titan --url=titan://transjovian.org/test/raw/testing --token=hello text.txt
Or from a pipe:
echo "This is my test." \
| titan --url=titan://transjovian.org/test/raw/testing --token=hello
# App::Phoebe
This module contains the core of the Phoebe wiki. Import functions and variables
from this module to write extensions, or to run it some other way. Usually,
`script/phoebe` is used to start a Phoebe server. This is why all the
documentation regarding server startup can be found there.
This section describes some hooks you can use to customize your wiki using the
`config` file, or using a Perl file (ending in `*.pl` or `*.pm`) in the
`conf.d` directory. Once you're happy with the changes you've made, restart the
server, or send a SIGHUP if you know the PID.
Here are the ways you can hook into Phoebe code:
`@extensions` is a list of code references allowing you to handle additional
URLs; return 1 if you handle a URL; each code reference gets called with $stream
([Mojo::IOLoop::Stream](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AStream)), the first line of the request (a Gemini URL, a Gopher
selector, a finger user, a HTTP request line), a hash reference for the headers
(in the case of HTTP requests), and a buffer of bytes (e.g. for Titan or HTTP
PUT or POST requests).
`@main_menu` adds more lines to the main menu, possibly links that aren't
simply links to existing pages.
`@footer` is a list of code references allowing you to add things like licenses
or contact information to every page; each code reference gets called with
$stream ([Mojo::IOLoop::Stream](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AStream)), $host, $space, $id, $revision, and $format
('gemini' or 'html') used to serve the page; return a gemtext string to append
at the end; the alternative is to overwrite the `footer` or `html_footer` subs
â the default implementation for Gemini adds History, Raw text and HTML link,
and `@footer` to the bottom of every page; the default implementation for HTTP
just adds `@footer` to the bottom of every page.
If you do hook into Phoebe's code, you probably want to make use of the
following variables:
`$server` stores the command line options provided by the user.
You can set the normal Gopher via `$gopher_port` and the encrypted Gopher ports
via `$gophers_port` (note the extra s). The values either be a single port, or
an array of ports. See the example below.
In this example we first switch to the package namespace, set some variables,
and then we _use_ the package. At this point the ports are specified and the
server processes it starts go up, one for ever IP number serving the hostname.
package App::Phoebe::Gopher;
our $gopher_host = "alexschroeder.ch";
our $gopher_port = [70,79]; # listen on the finger port as well
our $gophers_port = 7443; # listen on port 7443 using TLS
our $gopher_main_page = "Gopher_Welcome";
use App::Phoebe::Gopher;
Note the `finger` port in the example. This works, but it's awkward since you
have to finger `page/alex` instead of `alex`. In order to make that work, we
need some more code.
package App::Phoebe::Gopher;
use App::Phoebe qw(@extensions port $log);
use Modern::Perl;
our $gopher_host = "alexschroeder.ch";
our $gopher_port = [70,79]; # listen on the finger port as well
our $gophers_port = 7443; # listen on port 7443 using TLS
our $gopher_main_page = "Gopher_Welcome";
our @extensions;
push(@extensions, \&finger);
sub finger {
my $stream = shift;
my $selector = shift;
my $port = port($stream);
if ($port == 79 and $selector =~ m!^[^/]+$!) {
$log->debug("Serving $selector via finger");
gopher_serve_page($stream, $gopher_host, undef, decode_utf8(uri_unescape($selector)));
return 1;
}
return 0;
}
use App::Phoebe::Gopher;
# App::Phoebe::HeapDump
Perhaps you find yourself in a desperate situation: your server is leaking
memory and you don't know where. This extension provides a way to use
[Devel::MAT::Dumper](https://metacpan.org/pod/Devel%3A%3AMAT%3A%3ADumper) by allowing users identified with a known fingerprint of
their client certificate to initiate a dump.
You must set the fingerprints in your `config` file.
package App::Phoebe;
our @known_fingerprints = qw(
sha256$fce75346ccbcf0da647e887271c3d3666ef8c7b181f2a3b22e976ddc8fa38401);
use App::Phoebe::HeapDump;
Once have restarted the server, [gemini://localhost/do/heap-dump](gemini://localhost/do/heap-dump) will write a
heap dump to its wiki data directory. See [Devel::MAT::UserGuide](https://metacpan.org/pod/Devel%3A%3AMAT%3A%3AUserGuide) for more.
# App::Phoebe::Iapetus
This allows known editors to upload files and pages using the Iapetus protocol.
See [Iapetus documentation](https://codeberg.org/oppenlab/iapetus).
In order to be a known editor, you need to set `@known_fingerprints` in your
`config` file. Hereâs an example:
package App::Phoebe;
our @known_fingerprints;
@known_fingerprints = qw(
sha256$fce75346ccbcf0da647e887271c3d3666ef8c7b181f2a3b22e976ddc8fa38401
sha256$54c0b95dd56aebac1432a3665107d3aec0d4e28fef905020ed6762db49e84ee1);
use App::Phoebe::Iapetus;
The way to do it is to run the following, assuming the certificate is named
`client-cert.pem`:
openssl x509 -in client-cert.pem -noout -sha256 -fingerprint \
| sed -e 's/://g' -e 's/SHA256 Fingerprint=/sha256$/' \
| tr [:upper:] [:lower:]
This should give you the fingerprint in the correct format to add to the list
above.
Make sure your main menu has a link to the login page. The login page allows
people to pick the right certificate without interrupting their uploads.
=> /login Login
# App::Phoebe::Ijirait
The ijirait are red-eyed shape shifters, and a game one plays via the Gemini
protocol, and Ijiraq is also one of the moons of Saturn.
The Ijirait game is modelled along traditional MUSH games ("multi-user shared
hallucination"), that is: players have a character in the game world; the game
world consists of rooms; these rooms are connected to each other; if two
characters are in the same room, they see each other; if one of them says
something, the other hears it.
When you visit the URL using your Gemini browser, you're asked for a client
certificate. The common name of the certificate is the name of your character in
the game.
As the server doesn't know whether you're still active or not, it assumes a
10min timout. If you were active in the last 10min, other people in the same
"room". Similarly, if you "say" something, whatever you said hangs on the room
description for up to 10min as long as your character is still in the room.
There is no configuration. Simply add it to your `config` file:
use App::Phoebe::Ijirait;
In a virtual host setup, this extension serves all the hosts. Here's how to
serve just one of them:
package App::Phoebe::Ijirait;
our $host = "campaignwiki.org";
use App::Phoebe::Ijirait;
# App::Phoebe::MokuPona
This serves files from your moku pona directory. See [App::mokupona](https://metacpan.org/pod/App%3A%3Amokupona).
If you need to change the directory (defaults to `$HOME/.moku-pona`), or if you
need to change the host (defaults to the first one), use the following for your
`config` file:
package App::Phoebe::MokuPona;
our $dir = "/home/alex/.moku-pona";
our $host = "alexschroeder.ch";
use App::Phoebe::MokuPona;
# App::Phoebe::Oddmuse
This extension allows you to serve files from an Oddmuse wiki instead of a real
Phoebe wiki directory.
The tricky part is that most Oddmuse wikis don't use Gemini markup (âgemtextâ)
and therefore care is required. The extension tries to transmogrify typical
Oddmuse markup (based on my own wikis) to Gemini.
Here's one way to configure it. I use Apache as my proxy server and have
multiple Oddmuse wikis running on the same machine, each only serving
`localhost`. I need to recreate some of the Apache configuration, here.
( run in 0.746 second using v1.01-cache-2.11-cpan-b16cb0d3907 )