commit - 964686ce0b77d06b8c954366db56e9a8d098b1d5
commit + ac42bb6c7f9f30028fbc63f623bf4bba99b725ad
blob - f1521270a295bd429b4e962e82efeea04b0b269d
blob + 7431a6328c8f7d85d30e234b2d9bf0a5d8b1b36d
--- site/Makefile
+++ site/Makefile
-.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
blob - b505e2ab00a63ed0957a8915891166cdeccd02b2 (mode 644)
blob + /dev/null
--- site/contrib.html
+++ /dev/null
-<!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>
blob - /dev/null
blob + 2ab5c0d1fc7b0e6c12fb00bf177037f64450298c (mode 644)
--- /dev/null
+++ site/footer.html
+ </body>
+</html>
blob - /dev/null
blob + b9f03d2884972722553225322c70853137453486 (mode 755)
--- /dev/null
+++ site/gem2html
+#!/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/&/\&/g;
+ s/</\</g;
+ s/>/\>/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>";
+}
blob - b216a5e07a4ab30d183cc145fb704566514f9f5b (mode 644)
blob + /dev/null
--- site/index.html
+++ /dev/null
-<!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: it’s 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’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/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>/<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>~/.local/share/gmid</code>)
- </li>
- <li>
- logs sent to syslog now have proper priority (before every
- message ended up as LOG_CRIT). Found by Anna
- “CyberTailor”, 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’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 “CyberTailor”, 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>
blob - /dev/null
blob + 6b63898cfe346113a3c9361b179ddeccdfba557b (mode 644)
--- /dev/null
+++ site/header.html
+<!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>
blob - 739e414e1ee54b7ad842ea9f13cb3e936dc3675c (mode 644)
blob + /dev/null
--- site/quickstart.html
+++ /dev/null
-<!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, it’s 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>
- It’s a common practice for system daemons to chroot themselves
- into a directory. From here on I’ll 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’ aren’t!
- </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>
blob - /dev/null
blob + 6c65eea57739000765980931c725e96c7a6d3eed (mode 755)
--- /dev/null
+++ site/menu.pl
+#!/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 "";
blob - /dev/null
blob + 026d3c3f1e93d4b85c5571f10f7ceb7c147dcd93 (mode 644)
--- /dev/null
+++ site/style.css
+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; }
+}
blob - /dev/null
blob + c8f63c0b97b5684486521a5d9f44c75de64107f0 (mode 755)
--- /dev/null
+++ site/subst
+#!/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;