App-Phoebe
view release on metacpan or search on metacpan
script/phoebe view on Meta::CPAN
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.
Here is an example:
```
The tapping calms me:
Constant mindless murmuring
Rain drops against glass
```
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 have seen things you people would not believe.
=head1 SECURITY
It might be best if you had a separate user for Phoebe:
sudo adduser --disabled-login --disabled-password phoebe
sudo su phoebe --shell=/bin/bash
cd
Now you're in the new home directory, F</home/phoebe>. If you start C<phoebe>
here, your wiki directory will be F</home/phoebe/wiki>. If you haven't installed
L<App::Phoebe> for all your users, you will have to install it again.
cpan App::Phoebe
The Perl files are stored in F</home/phoebe/perl5>.
=head1 QUICKSTART
Start Phoebe.
phoebe
When you run it for the first time, Phoebe is going to prompt you for a hostname
and create certificates for you. If in doubt, answer C<localhost>. The
certificate and a private key are stored in the F<cert.pem> and F<key.pem>
files, using elliptic curves, valid for five years, without password protection.
Do you want to create them right now?
The certificate uses eliptic curves and is valid for five years.
If so, please provide your hostname (e.g. localhost).
If not, just press Enter.
localhost
openssl req -new -x509 -newkey ec -subj "/CN=localhost" -pkeyopt ec_paramgen_curve:prime256v1 -days 1825 -nodes -out cert.pem -keyout key.pem
Generating an EC private key
writing new private key to 'key.pem'
-----
If it aborts, see the L</Troubleshooting> section below. If it runs, open a
second terminal and test it:
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
titan --url=titan://localhost/raw/Welcome --token=hello test.txt
You should get a nice redirect message.
30 gemini://localhost:1965/page/Welcome
You can check the page:
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
=head1 CERTIFICATES
If you want to generate your own certificates, here's how you would generate a
certificate for two domains (you can add as many as you need), and a common name
of "Phoebe" (use whatever you want).
openssl req -new -x509 -newkey ec \
script/phoebe view on Meta::CPAN
$server->{key_file}->{"$host:$port"} = $key_file;
}
}
$cert_file = $key_file = undef;
@host = @port = ();
}
}
# if, at the end, there is a left-over
if ($cert_file or $key_file) {
die "I must have both --key_file and --cert_file\n";
}
push @port, 1965 unless @port;
# let's see if we need to generate certificates
my $default_certs = 0;
# if, at the end, we have some hosts but no certs and keys
for my $host (@host) {
$default_certs = 1;
$server->{host}->{$host} = 1;
push(@{$server->{port}->{$host}}, @port);
for my $port (@port) {
$server->{cert_file}->{"$host:$port"} = 'cert.pem';
$server->{key_file}->{"$host:$port"} = 'key.pem';
}
}
# if, at the end, we had no hosts at all, the default still needs cert and key
if (not keys %{$server->{host}}) {
$default_certs = 1;
$server->{host}->{localhost} = 1;
push(@{$server->{port}->{localhost}}, @port);
for my $port (@port) {
$server->{cert_file}->{"localhost:$port"} = 'cert.pem';
$server->{key_file}->{"localhost:$port"} = 'key.pem';
}
}
# use Data::Dumper;
# warn Dumper($server);
# if the certs don't exist, generate them
if ($default_certs
and (not -f 'cert.pem'
or not -f 'key.pem')) {
generate_certificates();
}
}
sub generate_certificates {
say "The default certificate (and key) files are missing.";
say "Do you want to create them right now?";
say "The certificate uses eliptic curves and is valid for five years.";
say "If so, please provide your hostname (e.g. localhost).";
say "If not, just press Enter.";
local $SIG{'ALRM'} = sub {
die "Timed out!\n";
};
alarm(30); # timeout for the following prompt
my $hostname = <STDIN>;
alarm(0); # done, no more alarm
chomp $hostname;
die "The hostname may not contain any whitespace\n" if $hostname =~ /\s/;
my $cmd = qq(openssl req -new -x509 -newkey ec -subj "/CN=$hostname" )
. qq(-pkeyopt ec_paramgen_curve:prime256v1 -days 1825 -nodes -out cert.pem -keyout key.pem);
if ($hostname) {
say $cmd;
system($cmd) == 0
or die "openssl failed: $?";
}
}
sub help {
my $parser = Pod::Text->new();
$parser->parse_file($0);
exit;
}
sub verify_fingerprint {
my ($ok, $ctx_store, $certname, $error, $cert, $depth) = @_;
return 1;
}
# defaults
$server->{wiki_token} ||= ['hello'];
$server->{wiki_space} ||= [];
$server->{wiki_mime_type} ||= [];
$server->{wiki_dir} ||= $ENV{PHOEBE_DATA_DIR} || './wiki';
$server->{wiki_page} ||= [];
$server->{wiki_main_page} ||= '';
$server->{wiki_page_size_limit} ||= 100000;
configure();
# Reconfigure if we get SIGHUP (via kill -s SIGHUP $pid, for example)
$SIG{HUP} = sub { Mojo::IOLoop->next_tick(\&configure) };
start_servers();
sub configure {
# config file with extra code; restart server if you change it
my $dir = $server->{wiki_dir};
my @config;
push(@config, map { "$dir/conf.d/$_" } grep(/\.p[lm]$/, read_dir("$dir/conf.d"))) if -d "$dir/conf.d";
# allow override of config files in conf.d
push(@config, "$dir/config") if -f "$dir/config";
for my $config (@config) {
$log->info("Running $config");
$log->error("$config cannot be read") unless -r $config;
$log->warn("$config did not return a true value") unless do $config;
$log->error("$@") if $@;
$log->error("$!") if $!;
}
# summarize config results
$log->info("PID: $$");
$log->info("Space: @{$server->{wiki_space}}");
if (keys %{$server->{host}} > 1) {
my $hosts = host_regex();
for (grep(!/^$hosts\//, @{$server->{wiki_space}})) {
( run in 0.803 second using v1.01-cache-2.11-cpan-6aa56a78535 )