change how the site is built

copy the kamid/site "framework" here too; in other words: don't maintain
two copies of every page! \o/
This commit is contained in:
Omar Polo 2022-01-28 08:34:22 +00:00
parent 964686ce0b
commit ac42bb6c7f
10 changed files with 387 additions and 910 deletions

View File

@ -1,19 +1,70 @@
.PHONY: all serve-www serve-gemini upload
MANPAGES = ../gmid.1 \
../gg.1
all: gmid.1.html gmid.1.txt
PAGES = index.gmi \
changelog.gmi \
contrib.gmi \
quickstart.gmi
gmid.1.html: ../gmid.1
./mdoc2html.sh $? $@
TITLE_index.gmi = home
TITLE_changelog.gmi = changelog
TITLE_contrib.gmi = contrib
TITLE_quickstart.gmi = quickstart
gmid.1.txt: ../gmid.1
MANWIDTH=72 man -Tutf8 -l $? | col -b > $@
REPOLOGY_BANNER = https://repology.org/badge/vertical-allrepos/gmid.svg
REPOLOGY_URL = https://repology.org/project/gmid/versions
SUBST = ./subst GITHUB=https://github.com/omar-polo/gmid \
VERS=1.7.5 \
CURV=1.7 \
NEXTV=1.8
SUBST_GEM = ${SUBST} MANEXT=txt EXT=gmi REPOLOGY=${REPOLOGY_URL}
SUBST_WWW = ${SUBST} MANEXT=html EXT=html REPOLOGY=${REPOLOGY_BANNER}
.PHONY: all dirs manpages serve-www serve-gemini upload clean titles
all: dirs manpages pages
cp style.css www/
cp vim-screenshot.png www/
cp vim-screenshot.png gemini/
dirs:
mkdir -p gemini www
manpages:
.for m in ${MANPAGES}
./mdoc2html.sh $m www/${m:T}.html
man -O width=65 -Tutf8 -l $m | col -b > gemini/${m:T}.txt
.endfor
pages:
.for p in ${PAGES}
${MAKE} titles-gem | ./menu.pl $p gemini > gemini/$p
${SUBST_GEM} $p >> gemini/$p
${SUBST_WWW} TITLE=${TITLE_${p}:Q} header.html > www/${p:.gmi=.html}
${MAKE} titles-www | ./menu.pl "${p:.gmi=.html}" html >> www/${p:.gmi=.html}
${SUBST_WWW} $p | ./gem2html >> www/${p:.gmi=.html}
cat footer.html >> www/${p:.gmi=.html}
.endfor
serve-www:
python3 -m http.server 8888
python3 -m http.server --directory www 8888
serve-gemini:
../gmid -p 1966 .
gmid -p 1966 ./gemini
upload:
rsync --delete -a . op:sites/gmid.omarpolo.com
rsync --delete -a . op:gemini/gmid.omarpolo.com
rsync --delete -a www/ op:sites/gmid.omarpolo.com
rsync --delete -a gemini/ op:gemini/gmid.omarpolo.com
titles-gem:
.for p in ${PAGES}
@printf "%s %s\n" "${p}" ${TITLE_${p}:Q}
.endfor
titles-www:
.for p in ${PAGES}
@printf "%s %s\n" "${p:.gmi=.html}" ${TITLE_${p}:Q}
.endfor

View File

@ -1,232 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>gmid | contrib</title>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
body {
font-family: monospace;
font-size: 14px;
max-width: 780px;
margin: 0 auto;
padding: 20px;
padding-bottom: 80px;
}
h1::before {
content: "# ";
}
h2 {
margin-top: 40px;
}
h2::before {
content: "## ";
}
h3::before {
content: "### ";
}
blockquote {
margin: 0;
padding: 0;
}
blockquote::before {
content: "> ";
}
blockquote p {
font-style: italic;
display: inline;
}
p.link::before {
content: "→ ";
}
strong::before { content: "*" }
strong::after { content: "*" }
hr {
border: 0;
height: 1px;
background-color: #222;
width: 100%;
display: block;
margin: 2em auto;
}
img {
border-radius: 5px;
}
pre {
overflow: auto;
padding: 1rem;
background-color: #f0f0f0;
border-radius: 3px;
}
pre.banner {
display: flex;
flex-direction: row;
justify-content: center;
}
code, kbd {
color: #9d109d;
}
img {
display: block;
margin: 0 auto;
max-width: 100%;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #222;
color: white;
}
a {
color: aqua;
}
hr {
background-color: #ddd;
}
pre {
background-color: #353535;
}
code, kbd {
color: #ff4cff;
}
}
@media (max-width: 400px) {
pre.banner { font-size: 9px; }
}
@media (max-width: 500px) {
pre.banner { font-size: 10px; }
}
</style>
</head>
<body>
<header>
<nav>
<a href="index.html">Home</a> |
contrib |
<a href="quickstart.html">Quickstart</a> |
<a href="gmid.1.html">docs</a>
</nav>
</header>
<h1>contrib</h1>
<p>
This directory is for additional contributed files which may be
useful.
</p>
<p>Contents:</p>
<ul>
<li><a href="#dockerfile">Dockerfile</a></li>
<li><a href="#gencert">gencert</a></li>
<li><a href="#openbsd-rc">OpenBSD rc file</a></li>
<li><a href="#systemd-unit-file">Systemd unit file</a></li>
<li><a href="#renew-certs">renew certificates automatically</a></li>
<li><a href="#vim-syntax-files">Vim syntax files</a></li>
</ul>
<hr />
<h2 id="dockerfile">Dockerfile</h2>
<p>
<a href="https://git.omarpolo.com/gmid/tree/contrib/Dockerfile">contrib/Dockerfile</a>
is a simple Dockerfile. The resulting image is a classic alpine
linux image with a statically linked gmid installed as
<code>/bin/gmid</code>.
</p>
<p>To build the image:</p>
<pre># docker build -f contrib/Dockerfile -t gmid .</pre>
<p>and then run it with something along the lines of:</p>
<pre># docker run --rm -it -p 1965:1965 \
-v gmid.conf:/etc/gmid.conf:ro \
-v path/to/keys:/tls:ro \
-v /var/gemini:/var/gemini:ro \
gmid -c /etc/gmid.conf</pre>
<h2 id="gencert">gencert</h2>
<p>
<a href="https://git.omarpolo.com/gmid/tree/contrib/gencert">contrib/gencert</a>
is a simple script to generate self-signed certificates.
</p>
<h2 id="openbsd-rc">OpenBSD rc file</h2>
<p>
<a href="https://git.omarpolo.com/gmid/tree/contrib/gmid">contrib/gmid</a>
is a sample service file for OpenBSD <code>rc(8)</code>.
To install it:
</p>
<pre># cp contrib/gmid /etc/rc.d</pre>
<p>
then the usual
<code>rcctl [start|stop|enable|restart] gmid</code>
are available.
</p>
<h2 id="systemd-unit-file">Systemd unit file</h2>
<p>
<a href="https://git.omarpolo.com/gmid/tree/contrib/gmid.service">contrib/gmid.service</a>
is a simple service file for
systemd. To install it:
</p>
<pre># cp contrib/gmid.service /lib/systemd/system/gmid.service</pre>
<p>
then the usual
<code>systemctl [status|start|enable|stop] gmid</code>
commands can be used to manage the server.
</p>
<p>Some things to keep in mind:</p>
<ul>
<li>
the <code>ExecStart</code> path may depend on the installation.
</li>
<li>
a <code>gmid</code> user needs to be created for e.g. with:
<pre># useradd --system --no-create-home -s /bin/nologin -c "gmid Gemini server" gmid</pre>
</li>
<li>
logs can be inspected with <code>journalctl(1)</code>:
<pre># journalctl -t gmid</pre>
</li>
</ul>
<h2 id="renew-certs">renew certificates automatically</h2>
<p>
<strong>NB:</strong> this script requires features that are
currently available only in the master branch.
</p>
<p>
<a href="https://git.omarpolo.com/gmid/tree/contrib/renew-certs">contrib/renew-certs</a>
is a script meant to be run in a crontab that watch for
certificate expiration. It can optionally renew the certs and
restart gmid too.
</p>
<p>Read the documentation with: <code>perldoc renew-certs</code>.</p>
<h2 id="vim-syntax-files">Vim syntax files</h2>
<p>
<a href="https://git.omarpolo.com/gmid/tree/contrib/vim">contrib/vim</a>
contains a syntax highlighting for vim. To install it, just
copy the files to <code>~/.vim</code>
or <code>/usr/share/vim/vimfiles</code>, e.g.
</p>
<pre>$ mkdir -p ~/.vim
$ cp -R contrib/vim/* ~/.vim/</pre>
<p>To enable Syntastic checker, add to your vimrc:</p>
<pre>let g:syntastic_gmid_checkers = ['gmid']</pre>
<p>The end result is something like this:</p>
<a href="vim-screenshot.png">
<img src="vim-screenshot.png" alt="Screenshot of vim editing gmid.conf with syntax highlighting" />
</a>
</body>
</html>

2
site/footer.html Normal file
View File

@ -0,0 +1,2 @@
</body>
</html>

114
site/gem2html Executable file
View File

@ -0,0 +1,114 @@
#!/usr/bin/env perl
#
# Copyright (c) 2022 Omar Polo <op@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
use v5.10;
use strict;
use warnings;
my $in_pre = 0;
my $in_list = 0;
while (<>) {
chomp;
if ($in_pre && m/^```/) {
$in_pre = 0;
say "</pre>";
} elsif (!$in_pre && m/^```/) {
if ($in_list) {
$in_list = 0;
say "</ul>";
}
$in_pre = 1;
print "<pre>";
} elsif ($in_pre) {
say san($_);
} elsif ($in_list && m/^$/) {
say "</ul>";
$in_list = 0;
} elsif (m/^\*\s+(.*)/) { # NB: at least one space
if (!$in_list) {
$in_list = "item";
say "<ul>";
} elsif ($in_list eq "link") {
$in_list = "item";
say "</ul>";
say "<ul>";
}
output("li", $1);
} elsif (m/^=>\s*([^\s]*)\s*(.*)$/) {
my $href = $1;
my $alt = $2;
# special case: images
if ($1 =~ /\.(png|jpg|svg)$/) {
if ($in_list) {
say "</ul>";
$in_list = 0;
}
say "<img src='$href' alt='$alt' />";
next;
}
if (!$in_list) {
$in_list = "link";
say "<ul class='link-list'>";
} elsif ($in_list eq "item") {
$in_list = "link";
say "</ul>";
say "<ul class='link-list'>";
}
$_ = $alt || $href;
say "<li><a href='$href'>". san() ."</a></li>";
} elsif (m/^###\s*(.*)$/) {
output("h3", $1);
} elsif (m/^##\s*(.*)$/) {
output("h2", $1);
} elsif (m/^#\s*(.*)$/) {
output("h1", $1);
} elsif (m/^>\s*(.*)$/) {
output("blockquote", $1);
} else {
output("p", $_);
}
}
sub san {
s/&/\&amp;/g;
s/</\&lt;/g;
s/>/\&gt;/g;
return $_;
}
sub output {
my ($tn, $content) = @_;
if (!$in_list && $tn eq "li") {
$in_list = 1;
say "<ul>";
}
if ($in_list && $tn ne "li") {
$in_list = 0;
say "</ul>";
}
if ($tn eq "p" && $content eq "") {
return;
}
$_ = $content;
say "<$tn>". san() ."</$tn>";
}

9
site/header.html Normal file
View File

@ -0,0 +1,9 @@
<!doctype html>
<html lang="en">
<head>
<title>TITLE | gmid</title>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="style.css" />
</head>
<body>

View File

@ -1,377 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>gmid</title>
<meta charset="utf8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: monospace;
font-size: 14px;
max-width: 780px;
margin: 0 auto;
padding: 20px;
padding-bottom: 80px;
}
h1::before {
content: "# ";
}
h2 {
margin-top: 40px;
}
h2::before {
content: "## ";
}
h3::before {
content: "### ";
}
blockquote {
margin: 0;
padding: 0;
}
blockquote::before {
content: "> ";
}
blockquote p {
font-style: italic;
display: inline;
}
p.link::before {
content: "→ ";
}
strong::before { content: "*" }
strong::after { content: "*" }
hr {
border: 0;
height: 1px;
background-color: #222;
width: 100%;
display: block;
margin: 2em auto;
}
img {
border-radius: 5px;
}
pre {
overflow: auto;
padding: 1rem;
background-color: #f0f0f0;
border-radius: 3px;
}
pre.banner {
display: flex;
flex-direction: row;
justify-content: center;
}
code, kbd {
color: #9d109d;
}
img {
display: block;
margin: 0 auto;
max-width: 100%;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #222;
color: white;
}
a {
color: aqua;
}
hr {
background-color: #ddd;
}
pre {
background-color: #353535;
}
code, kbd {
color: #ff4cff;
}
}
@media (max-width: 400px) {
pre.banner { font-size: 9px; }
}
@media (max-width: 500px) {
pre.banner { font-size: 10px; }
}
</style>
</head>
<body>
<header>
<nav>
Home |
<a href="contrib.html">contrib</a> |
<a href="quickstart.html">Quickstart</a> |
<a href="gmid.1.html">docs</a>
</nav>
</header>
<h1>gmid</h1>
<blockquote>
<p>A Gemini server</p>
</blockquote>
<h2>Features</h2>
<ul>
<li>sandboxed by default on OpenBSD, FreeBSD and Linux</li>
<li>able to reload the configuration on-the-fly without loosing connections</li>
<li>punycode and IRI support</li>
<li>reverse proxying</li>
<li>CGI and FastCGI support</li>
<li>virtual hosts and per-location rules</li>
<li>low memory footprint</li>
<li>event-based asynchronous I/O model</li>
<li>rich configuration file</li>
</ul>
<h2>Install</h2>
<p>Some distros provide a package — thanks to the maintainers!</p>
<p>
<a href="https://repology.org/project/gmid/versions">
<img src="https://repology.org/badge/vertical-allrepos/gmid.svg" alt="Packaging status">
</a>
</p>
<p>Source code and precompiled binaries for linux are available:</p>
<ul>
<li>
<a href="https://github.com/omar-polo/gmid/releases/download/1.7.5/gmid-1.7.5.tar.gz">gmid-1.7.5.tar.gz</a>
</li>
</ul>
<ul>
<li>
<a href="https://git.omarpolo.com/gmid/">git repository</a>
</li>
<li>
<a href="gemini://git.omarpolo.com/gmid.git/">git repository via Gemini</a>
</li>
<li>
<a href="https://github.com/omar-polo/gmid">GitHub mirror</a>
</li>
</ul>
<ul>
<li>
<a href="https://github.com/omar-polo/gmid/releases/download/1.7.5/gmid.linux.aarch64">gmid.linux.aarch64</a>
</li>
<li>
<a href="https://github.com/omar-polo/gmid/releases/download/1.7.5/gmid.linux.amd64">gmid.linux.amd64</a>
</li>
</ul>
<p>
When in doubt, compile from source: its easy and takes less
than a minute on a raspberry pi 3. The dependencies are:
</p>
<ul>
<li>libevent</li>
<li>OpenSSL/LibreSSL</li>
<li>libtls (from either LibreSSL or LibreTLS)</li>
<li>yacc or GNU bison</li>
</ul>
<p>Once all the dependencies are installed, building is as easy as:</p>
<pre>$ curl -LO https://github.com/omar-polo/gmid/releases/download/1.7.5/gmid-1.7.5.tar.gz
$ tar xzvf gmid-1.7.5.tar.gz
$ cd gmid-1.7.5
$ ./configure
$ make
$ sudo make install # eventually</pre>
<p>
A SHA256 file is available. However, that only checks for
accidental corruption: you can use signify (SHA256.sig and the
public key gmid-1.7.pub) or GPG. The hash of the signify public
key is also included in the SHA256 file and thus signed with my
GPG. The signify public key for the next release gmid-1.8.pub
is also included.
</p>
<ul>
<li>
<a href="https://github.com/omar-polo/gmid/releases/download/1.7.5/SHA256">SHA256</a>
</li>
<li>
<a href="https://github.com/omar-polo/gmid/releases/download/1.7.5/SHA256.gpg">SHA256.gpg</a>
</li>
<li>
<a href="https://github.com/omar-polo/gmid/releases/download/1.7.5/SHA256.sig">SHA256.sig</a>
</li>
</ul>
<p>To verify the signatures with signify(1)</p>
<pre>$ signify -C -p gmid-1.7.pub -x SHA256.sig
Signature Verified
gmid-1.7.pub: OK
gmid-1.7.5.tar.gz: OK
gmid-1.8.pub: OK
gmid.linux.aarch64: OK
gmid.linux.amd64: OK</pre>
<h2>Changelog for the last versions</h2>
<p>1.7.5 “Space-dye Vest” fifth bugfix release — Released October 15, 2021</p>
<p>This version includes the following bugfix:</p>
<ul>
<li>don't die when a connection is closed before being accepted by gmid (i.e. handle <code>ECONNRESET</code>)</li>
</ul>
<hr />
<p>1.7.4 “Space-dye Vest” fourth bugfix release — Released September 24, 2021</p>
<p>This version includes the following bugfix:</p>
<ul>
<li>
fix a possible out-of-bound access when handling a request for
a non-existent file in the root directory of a vhost that's
matched by the cgi option
</li>
</ul>
<p>and the relative regression test.</p>
<hr />
<p>1.7.3 “Space-dye Vest” third bugfix release — Released September 18, 2021</p>
<h3>Improvements</h3>
<ul>
<li>follows symlinks</li>
<li>improved documentation and added key generation example (thanks! Anna)</li>
</ul>
<h3>Bugfix</h3>
<ul>
<li>fix syslog logging on FreeBSD. Reported by Karl Jeacle, thanks!</li>
<li>don't crash if <code>-c</code> is missing in configtest mode (<code>-n</code>). Reported by heph, thanks!</li>
<li>allow fstat64 on linux (needed by glibc on aarch64). Reported by pine, thanks!</li>
</ul>
<hr />
<p>1.7.2 “Space-dye Vest” second bugfix release — Released July 19, 2021</p>
<p>This version includes the following bugfix:</p>
<ul>
<li>
An un-initialized field in the configless code path leads to a
crash on the first request.
</li>
</ul>
<p>and the relative regression test.</p>
<hr />
<p>1.7.1 “Space-dye Vest” bugfix release — Released July 11, 2021</p>
<p>This version includes two bugfixes:</p>
<ul>
<li>use <code>${MAKE}</code> to recursively call make.</li>
<li>
fix the misleading example in the manpage: macros name may not
be reserved words.
</li>
</ul>
<hr />
<p>1.7 “Space-dye Vest” — Released July 10, 2021</p>
<p>
Starting from this version gmid doesn't depend on lex anymore,
but yacc is still needed.
</p>
<h3>New Features</h3>
<ul>
<li>initial fastcgi support! (it&#8217;s still young!)</li>
<li>
added user-defined macros, either via <code>-Dname=val</code> or
directly in the configuration file.
</li>
<li>new <code>include</code> keyword to load additional configuration files.</li>
<li>new <code>env</code> rule to define environment vars for CGI scripts.</li>
<li>new <code>alias</code> rule to define hostname aliases for a server.</li>
<li>allow <code>root</code> to be specified per-location block.</li>
<li>pidfile support with the new <code>-P</code> cli flag.</li>
<li>
define <code>TLS_VERSION</code>, <code>TLS_CIPHER</code> and
<code>TLS_CIPHER_STRENGTH</code> for CGI scripts.
</li>
</ul>
<h3>Improvements</h3>
<ul>
<li>
remove limits on the number of virtual hosts and location
blocks that can be defined.
</li>
<li>print the datetime when logging to stderr.</li>
<li>
use <code>text&#47;x-patch</code> for <code>.patch</code> and <code>.diff</code> files.
</li>
<li>sort the auto index alphabetically.</li>
<li>various improvements to the log management.</li>
<li>drop the dependency on lex.</li>
<li>
added <code>--help</code> as synonym of <code>-h</code> and
<code>-V</code>&#47;<code>--version</code> to print the version.
</li>
<li>
c-like handling of strings in the configuration file: when
two or more strings are next to each-others, are
automatically joined into a single string. This is
particularly useful with <code>$</code>-macros.
</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>
correctly handle CGI scripts that replies with the maxium
header length allowed.
</li>
<li>fixed the <code>static</code> target.</li>
<li>
fixed recursive mkdirs for configless mode (i.e. create
<code>~&#47;.local&#47;share&#47;gmid</code>)
</li>
<li>
logs sent to syslog now have proper priority (before every
message ended up as LOG_CRIT). Found by Anna
&#8220;CyberTailor&#8221;, thanks!
</li>
<li>
ensure <code>%p</code> (path) is always absolute in
<code>block return</code> rules.
</li>
<li>
fix automatic certificate generation, it caused problems on
some adroid devices. Found by Gnuserland, thanks!
</li>
<li>document the <code>log</code> rule.</li>
<li>
the seccomp filter was reworked and now it&#8217;s known to
work properly on a vast range of architectures (to be more
specific: all the architectures supported by alpine linux),
see github issue #4. Prompted and tested by @begss, thanks!
</li>
<li>
various improvements to the configure script, notified and
fixed by Anna &#8220;CyberTailor&#8221;, thanks!
</li>
<li>added a timeout to the regression tests.</li>
</ul>
<h3>Breaking changes</h3>
<ul>
<li>
if duplicate rules are found in the configuration file, an
error is now raised instead of silently using only the last
value.
</li>
<li>
(sort of) <code>gg</code> moved to <code>regress</code> as
it's only used in the regression suite.
</li>
<li>
(notice) the <code>mime "mime-type" "extension"</code> rule was deprecated and
replaced by the new <code>map "mime-type" to-ext "extension"</code>. The
<code>mime</code> rule will be removed in a future version
because its syntax is incompatible with the new string
auto-concat mechanism.
</li>
</ul>
</body>
</html>

39
site/menu.pl Executable file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env perl
use v5.10;
use strict;
use warnings;
my $page = shift or die 'missing page';
my $outtype = shift or die 'missing output type';
my @pages = ();
while (<>) {
chomp;
@pages = (@pages, $_);
}
my $did = 0;
for (@pages) {
my ($href, $text) = m/^([^\s]*)\s*(.*)$/;
if ($outtype eq 'gemini') {
if ($href ne $page) {
say "=> $href $text";
}
} else {
if (!$did) {
$did = 1;
} else {
print "| ";
}
if ($href eq $page) {
print "$text ";
} else {
print "<a href='$href'>$text</a> ";
}
}
}
say "";

View File

@ -1,291 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>gmid quickstart</title>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
body {
font-family: monospace;
font-size: 14px;
max-width: 780px;
margin: 0 auto;
padding: 20px;
padding-bottom: 80px;
}
h1::before {
content: "# ";
}
h2 {
margin-top: 40px;
}
h2::before {
content: "## ";
}
h3::before {
content: "### ";
}
blockquote {
margin: 0;
padding: 0;
}
blockquote::before {
content: "> ";
}
blockquote p {
font-style: italic;
display: inline;
}
p.link::before {
content: "→ ";
}
strong::before { content: "*" }
strong::after { content: "*" }
hr {
border: 0;
height: 1px;
background-color: #222;
width: 100%;
display: block;
margin: 2em auto;
}
img {
border-radius: 5px;
}
pre {
overflow: auto;
padding: 1rem;
background-color: #f0f0f0;
border-radius: 3px;
}
pre.banner {
display: flex;
flex-direction: row;
justify-content: center;
}
code, kbd {
color: #9d109d;
}
img {
display: block;
margin: 0 auto;
max-width: 100%;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #222;
color: white;
}
a {
color: aqua;
}
hr {
background-color: #ddd;
}
pre {
background-color: #353535;
}
code, kbd {
color: #ff4cff;
}
}
@media (max-width: 400px) {
pre.banner { font-size: 9px; }
}
@media (max-width: 500px) {
pre.banner { font-size: 10px; }
}
</style>
</head>
<body>
<header>
<nav>
<a href="/">Home</a> |
<a href="contrib.html">contrib</a> |
Quickstart |
<a href="gmid.1.html">docs</a>
</nav>
</header>
<h1>gmid quickstart</h1>
<p>gmid can be run in two different “modes”:</p>
<dl>
<dt>configless:</dt>
<dd>
a quick way to serve a directory tree from the shell, useful
for testing a capsule before uploading it
</dd>
<dt>daemon mode:</dt>
<dd>
gmid reads the configuration file and runs in the background
</dd>
</dl>
<p>To run gmid in the “configless” mode, just type:</p>
<pre>$ gmid path/to/dir</pre>
<p>
gmid will then generate a certificate inside ~/.local/share/gmid
and serve the given directory locally.
</p>
<h2>Setting up a capsule with gmid</h2>
<p>
To host a Gemini capsule you need to run gmid in “daemon”
mode, and so a configuration file is needed. The format of the
configuration file is described in the manpage and is quite
flexible, but something like the following should be enough to
start:
</p>
<pre># /etc/gmid.conf
server "example.com" {
cert "/etc/ssl/example.com.pem"
key "/etc/ssl/private/example.com/key"
# path to the root directory of your capsule
root "/var/gemini/example.com"
}</pre>
<p>
A certificate is needed for the capsule. Generate one for
e.g. using
<a href="https://git.omarpolo.com/gmid/tree/contrib/gencert">contrib/gencert</a>:
</p>
<pre>$ ./contrib/gencert example.com
Generating a 4096 bit RSA private key
.................................................++++
..........++++
writing new private key to './example.com.key'
-----
Generated files:
./example.com.pem : certificate
./example.com.key : private key</pre>
<p>
Move example.com.pem and example.com.key to a safe place and
double check that the cert and key options in the
configuration points to these files.
</p>
<p>For example, save them in /etc/ssl/ (as root)</p>
<pre># mkdir -p /etc/ssl/private
# chown 700 /etc/ssl/private
# mv example.com.pem /etc/ssl/
# mv example.com.key /etc/ssl/private/</pre>
<p>
Make sure that the cert and key options in the configuration
file points to these files.
</p>
<p>Then running gmid is as easy as</p>
<pre>$ gmid -c /etc/gmid.conf</pre>
<p>Congratulations, your capsule is online!</p>
<h2>Securing your gmid installation</h2>
<p>
gmid employs various techniques to prevent the damage caused by
bugs, but some steps needs to be done manually.
</p>
<p>
If gmid was installed from your distribution package manager,
chance are that it already does all of this and is also
providing a service to run gmid automatically (e.g. a rc script,
a systemd unit file …) Otherwise, its heavily suggested to
create at least a dedicated user.
</p>
<h3>A dedicated user</h3>
<p>
Ideally, gmid should be started as root and drop privileges to a
local user. This way, the certificates can be readable only by
root. For example, on GNU/linux systems a gmid user can be
created with:
</p>
<pre># useradd --system --no-create-home -s /bin/nologin -c "gmid Gemini server" gmid</pre>
<p>
Please consult your OS documentation for more information on the
matter.
</p>
<p>
The configuration then needs to be adjusted to include the
user directive at the top:
</p>
<pre># /etc/gmid.conf
user "gmid"
server "example.com" { … }</pre>
<p>
gmid then needs to be started with root privileges, but will
then switch to the provided user automatically. If by accident
the user option is omitted and gmid is running as root, it
will complain loudly in the logs.
</p>
<h3>chroot</h3>
<p>
Its a common practice for system daemons to chroot themselves
into a directory. From here on Ill assume /var/gemini, but it
can be any directory.
</p>
<p>
A chroot on UNIX-like OS is an operation that changes the
“apparent” root directory (i.e. the “/”) from the current
process and its child. Think of it like imprisoning a process
into a directory and never letting it escape until it
terminates.
</p>
<p>
Using a chroot may complicate the use of CGI scripts, because
then all the dependencies of the scripts (sh, perl, libraries…)
need to be installed inside the chroot too. For this very
reason gmid supports FastCGI.
</p>
<p>
The chroot feature requires a dedicate user, see the previous
section.
</p>
<p>
To chroot gmid inside a directory, use the chroot directive in
the configuration file:
</p>
<pre># /etc/gmid.conf
user "gmid"
# the given directory, /var/gemini in this case, must exists.
chroot "/var/gemini"</pre>
<p>
Note that once chroot is in place, every root directive is
implicitly relative to the chroot, but cert and key arent!
</p>
<p>For example, given the following configuration:</p>
<pre># /etc/gmid.conf
user "gmid"
chroot "/var/gemini"
server "example.com" {
cert "/etc/ssl/example.com.pem"
key "/etc/ssl/example.com.key"
root "/example.com"
}</pre>
<p>
The certificate and the key path are the specified ones, but the
root directory of the virtual host is actually
“/var/gemini/example.com/”.
</p>
</body>
</html>

116
site/style.css Normal file
View File

@ -0,0 +1,116 @@
body {
font-family: monospace;
font-size: 14px;
max-width: 780px;
margin: 0 auto;
padding: 20px;
padding-bottom: 80px;
}
h1::before {
content: "# ";
}
h2 {
margin-top: 40px;
}
h2::before {
content: "## ";
}
h3::before {
content: "### ";
}
blockquote {
margin: 0;
padding: 0;
}
blockquote::before {
content: "> ";
}
blockquote p {
font-style: italic;
display: inline;
}
p.link::before {
content: "→ ";
}
strong::before { content: "*" }
strong::after { content: "*" }
hr {
border: 0;
height: 1px;
background-color: #222;
width: 100%;
display: block;
margin: 2em auto;
}
ul.link-list {
list-style: disclosure-closed;
}
img {
border-radius: 5px;
}
pre {
overflow: auto;
padding: 1rem;
background-color: #f0f0f0;
border-radius: 3px;
}
pre.banner {
display: flex;
flex-direction: row;
justify-content: center;
}
code, kbd {
color: #9d109d;
}
img {
display: block;
margin: 0 auto;
max-width: 100%;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #222;
color: white;
}
a {
color: aqua;
}
hr {
background-color: #ddd;
}
pre {
background-color: #353535;
}
code, kbd {
color: #ff4cff;
}
}
@media (max-width: 400px) {
pre.banner { font-size: 9px; }
}
@media (max-width: 500px) {
pre.banner { font-size: 10px; }
}

46
site/subst Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env perl
#
# Copyright (c) 2022 Omar Polo <op@omarpolo.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# subst -- filter that replaces key=values pairs
#
# usage: subst key1=val1 [... keyn=valn] [files...]
#
# Use `--' before the first file if it may contain an = in its name.
# If no files are given, read and substitute from standard input.
use v5.10;
use strict;
use warnings;
my @args = ();
while (1) {
$_ = shift;
last if !$_;
if ($_ eq '--') {
last;
} elsif ($_ !~ m/=/) {
unshift @ARGV, $_;
last;
}
my ($match, $repl) = m/^([^\s]*)=(.*)$/;
push @args, "-e", "s,$match,$repl,g";
}
# OK, shelling out to sed is a bit lame...
exec "sed", @args, @ARGV;