Hypothesis: fossil + hugo = DCVS static site generator on shared hosting

I know, sounds :crazy_face:, amirite?

And yet… two binaries and some clever directory layouts, and you’ve got a built-in static site generator that can technically hold it’s own binaries forever, and interfaces over CGI.

I’m gonna work on this, and post about it here. I. Am. So. Fucking. Excited. :face_with_monocle:

1 Like

I don’t know about you, but I find this idea kinda difficult to explain, but that’s because I get ahead of myself and don’t understand temporal consequence.


I’ll show instead of telling. Well, I’m gonna tell you, but I’m also gonna show you. With screenshots, even!

Here’s the project I’ve had in mind for a while: +io, a database of stuff. I want to collect all the human input and output I encounter, document it, and query it when needed. All the I/O.

So I have this domain, https://allthe.io. At this moment it looks like:

Screenshot_2020-08-08 allthe io is almost here

Thanks default DreamHost page!

To get to this point I registered a domain, setup DNS for it to resolve to DreamHost, and used DreamHost shared hosting to create a hosted site along with a Let’s Encrypt cert via DreamHost’s dashboard.

The reason I’m explaining this is to make it understood that I have an account with limited server permissions and can only control the site’s web configuration via .htaccess, the per-directory config file for Apache web server. This is important to keep in mind, because this is as “shared host” as it gets.

The first step is to… gosh, generate a site. Yeah, we need to bootstrap a site.

Independently I’ve been working on a “Hugo project cookiecutter”, but it’s not ready and I know what I need to get started, so we’ll go with that: README.md, COPYING, and config/_default/config.yaml.

COPYING is the CC0 text.


# +io

A database of stuff.

config.yaml is my old standby:

baseURL: "https://allthe.io"
title: "+io"

disableHugoGeneratorInject: true
- taxonomy
- taxonomyTerm
- sitemap
- robotsTXT
- 404

Let’s run Hugo and see what happens…

Dur, need a theme, so apply tule (which I’m doing by downloading the tar and extracting it to a themes directory and adding theme: tule to the config. This isn’t the best way to do this, but we are bootstrapping and will change this later, promise!)…

There we go!

Okay, normally I’d write a small script to put in the long rsync command to upload the site to the server. But we’re gonna do something different, which means we need to switch gears and configure a fossil

Quick aside: the way +io works is by building a web accessible interface generated from multiple data sources. Because we will be creating “collections” of stuff, we’re going to break each one into it’s own repository. This seems like a lot of work. In 20 years it will not.

The next part requires fossil, a decentralized version control system you can get at https://www.fossil-scm.org.

If you haven’t used git, it kinda like that. If you’ve used git, it’s very different. Your brain will be rewarded for know about both.

I install the single binary in /opt, because I’m trendy.

I’m not going to cover using fossil. It took me a week of late nights bending my think, and I’m glad because I’ve always kinda hated git, and instead of “master” we have “trunk” which makes more sense to me because I belong in a tree (preferably suspended in a supportive, comfortable position, with free tree-wifi).

What you should know is that fossil is the kind of software sci-fi writes dream of, but in a non-sexy, practical way (unless you think knowledge preservation and situational awareness are sexy, in which case Bring Your Own Smelling Salts!). And it hosts it’s own website interface via CGI.

At this point if you aren’t excited, not sure I can help you, but we’ll continue.

Gonna make a fossil repo for the web config for allthe.io, and I’ll call it alltheio.fossil.

I keep my fossils in ~/.museum/, because a regular fossil contributor mentioned it on hackernews or something and I thought it was cute and I don’t like seeing directories if I don’t have to (hence the dot).

Right now if I type fossil all list:


So I go to .museum and fossil init alltheio.fossil:

project-id: c1065f2f1024c0fbfd0cd50494b61cdad9513a76
server-id:  a189949d8f1db7044db055344247cc1748380c8e
admin-user: maiki (initial password is "UKJt6Eju7M")

I’m gonna change that password in a sec.

Fossils are SQLite databases. :rofl: They work by “opening” them in a directory, and can be open in multiple directories at once so I guess there’s that git. :stuck_out_tongue_winking_eye:

Let’s pop over to ~/projects/allthe.io where our Hugo config is, and open it up.

$ fossil open ~/.museum/alltheio.fossil 
project-name: <unnamed>
repository:   /home/maiki/.museum/alltheio.fossil
local-root:   /home/maiki/projects/allthe.io/
config-db:    /home/maiki/.config/fossil.db
project-code: c1065f2f1024c0fbfd0cd50494b61cdad9513a76
checkout:     0a6f1aa2ae8d24032438d7c1d89b4f9c20aaa147 2020-08-09 01:00:54 UTC
tags:         trunk
comment:      initial empty check-in (user: maiki)
check-ins:    1

I like to do some prep work when I make a new fossil, which I do via the web UI. These tasks include:

  • changing my password
  • making the repo private; this is suggested as the default state to set a repo when putting it in online server mode, and opening up permissions as needed
  • name, description
  • changing default home page to README

When I type fossil ui my web browser opens…

Say whaaaat? But I don’t have time to geek out with you!

I’m gonna do each of the things I listed, and in the future I’ll show what I did (or you can read like, 10 pages of docs and know everything about fossil).

I need to add the files to the repo before my README will show, so let’s do that real quick.

$ fossil add README.md COPYING config/_default/config.yaml 
ADDED  config/_default/config.yaml
$ fossil commit -m 'hajime'
New_Version: 2b09d0319c2cdfc77ed00241a67ebaf0e76ce19bec93d01f855bb6c79b6b28fe

Cool, let’s check fossil ui:

And “home” link:

That’s the README.md text! Noice.

You’ll notice I didn’t add the tule theme; that ought to be in it’s own repo, so we won’t track it as part of this one. Also, tule is designed to be immediately replaced, a bootstrap theme if you will. For this process we’ll be keeping it “unversioned” for now… :face_with_monocle:

Alright, but wasn’t this about, um, hosting or something? Oh yeah! Let’s do that part next!

The “hosting part” is complicated and simple, so worth explaining a bit.

The web is “stateless”. It feels like a website responds to you as a person, but that’s smoke and mirrors. Each time your web browser asks for a web page the server has to figure out who you are because HTTP ain’t saying. There are several benefits to this design, but most materials you’ll find bemoan this fact, but those folks also wish to profit from the use of web “cookies”, so we can easily dismiss them.

Our site is going to be a simple static site, with a complex site accessibile from “within” it.

A “simple static site” means we’ll generate HTML files and CSS files and maybe even JavaScript files, but our web serving process comprises of serving these files directly. A different approach is WordPress, which recieves a request from a user, gets it from the web server, figures out what it is asking for, generates the web page based on the underlying PHP templates indicate, and hand the page back to the web server to serve the user a page. But hey, you can have “real-time” updates in the sidebar… :roll_eyes:

For our purposes we are generating a data source, and the web pages are human-readable documents. Our use case indicates static files be served.

A “complex site accessibile from ‘within’” refers to fossil. Fossil can run in CGI mode, something us archmages from the 90s recall, rapidly developed for use in the Browser wars… Most fossil CGI scripts are small, some even just two lines, such as:

directory: /home/maiki/repos

That will live in a file called something like script.cgi, and tells the web server, “when you get a request to the CGI url, do this script”, and our script passes the request to the fossil binary listed at the top.

Are you getting this? I know it might seem complicated, but CGI is powerful and simple, and ought to get your brain wrinkling concerning the possibilities. :slight_smile:

Next time we’ll name our script and put it in place to see how it works.


1 Like

It took me a moment to think about this, but I figured it out. It is just… kinda weird. :slight_smile:

I’m relaunching maiki.xyz, and it is built hourly, from a fossil repo that lives in the same home directory.

$ tree . -L 2
├── Maildir
│   ├── cur
│   ├── new
│   └── tmp
├── bin
│   ├── fossil
│   └── hugo
├── build.sh
├── dl
│   ├── fossil-linux-x64-2.13.tar.gz
│   └── hugo_0.78.2_Linux-64bit.tar.gz
├── logs
│   └── maiki.xyz
├── maiki.xyz
│   ├── css
│   ├── edit
│   ├── favicon.gif
│   ├── favicon.ico
│   ├── index.html
│   └── sitemap.xml
├── repos
│   └── maikixyz.fossil
└── source
    ├── COPYING
    ├── README.md
    ├── config
    ├── resources
    ├── static
    └── themes

This is a test, really, as I don’t expect others to contribute to that site; but this is set up to allow folks to raise issues, clone, make changes, and that fossil repo can handle it all.