A few months ago I had to learn a little bit about AWS. The reason for doing so vanished, and now I have some elementary solutions searching for a problem. I found a problem recently when I desired to have a self-hosted code repository. Really, I convinced myself I had a problem so I would have something to occupy my time.
The obvious questions to be suggested to my title are “why FreeBSD?” and “why Fossil?” I believe there is a lot of value in exploring alternative resources. I chose FreeBSD because I’ve been interested for a while in learning about the BSDs. The Fossil home page gives a concise rundown of Fossil’s potential benefits over other version control systems. If you are currently hosting your stuff on Github or Gitlab, or self-hosting a Gitlab instance or stand-alone git server, and everything is going well, then cool. If you are using Subversion or something else, then keep on truckin’. Fossil looks interesting, well-made, and a bit different, which is reason enough for me to toy with it. The only thing I will evangelize is against technological monoculture, and even then it’s a “Christmas and Easter only” level of commitment.
I set up my FreeBSD EC2 instance on AWS. I just followed the basic tutorial except I used Colin Percival’s ZFS-on-root EC2 images. My installation went well and I could SSH into my new instance. Percival’s images are for FreeBSD 12.0 and I wanted to update to the latest minor version 12.2. So the only two things I installed via pkg install
were tmux
and beadm
. I used beadm
to create a boot environment as a backup in case the update failed. Chapter 12 of Michael W. Lucas’s Absolute FreeBSD covers a little on using beadm
for this purpose, and of course the man pages are valuable. To do the actual update, I start tmux
and followed the FreeBSD Handbook. With tmux
, if my connection drops halfway through the update I can reconnect and reattach without losing any progress. The only conflict I had to resolve was a single file which seemed to govern dynamic zfs volume growth. I didn’t do anything fancier than side with the more recent revision since they seemed pretty identical to me. My choice didn’t seem immediately stupid, but I might be surprised later.
My ultimate goal is to set up a working Fossil server inside of a FreeBSD jail using vnet. I have had a lot of difficulty managing this from first principles, and I don’t feel alone in having difficulty setting up vnet jails. I finally found a jail orchestrator my feeble mind could understand: Pot. In addition to the github page, there are some more docs available here. I didn’t do anything fancier than follow the Getting Started Guide. The recommended values already in pot.conf
worked well for me. SO I just uncommented the lines for POT_ZFS_ROOT
, POT_FS_ROOT
, POT_EXTIF
, POT_NETWORK
, and POT_GATEWAY
. The only change I had to make was setting POT_EXTIF
to the interface on my box. From there, I followed the public bridge segment of the Networking Guide. After running pot vnet-start
, I’m ready to create my jail which will house my fossil server.
pot create -p fossil -t single -b 12.2 -N public-bridge -i auto
Then I start the jail with pot start fossil
. I can install fossil to the jail with pkg -j fossil install -y fossil
. Alternatively, I could set up a terminal inside the jail with pot term fossil
and do the normal pkg install fossil
from within there, but I keep reading that is best practice to administrate a jail from the host. But then I disregard that and log in to set up the appropriate files and start the services. I created two fossil repos, created some readmes and committed. So the directory structure within the jail looks like
/
/fossils/
- test-repo.fossil
- test-repo-2.fossil
/test-repo/
- README.txt
/test-repo-2/
- README.txt
Setting up this layout is easy, and you can follow the Quick Start Guide to get the street-fighting knowledge of Fossil needed for this post. As an example, we can creaste a third repository. cd
into /fossils
, and run fossil init test-repo-3.fossil
to initiate. As the guide says, the location and name of repository filename is just a convention. However, we are centralizing all the fossil files in a single directory and consistently supplying a .fossil
suffix so a single fossil server process can serve multiple repositories. Then we go back to root and create the directory /test-repo-3
into which we cd
. Check out the repository with
fossil open ../fossils/test-repo-3.fossil
Let’s create a dummy readme with echo "test 3" > README.txt
. fossil extras
will display all local changes. So we stage the change with fossil add README.txt
and can commit the change with fossil commit -m "Added a dummy README file
. Then our jail’s directory structure should look like.
/
/fossils/
- test-repo.fossil
- test-repo-2.fossil
/test-repo/
- README.txt
/test-repo-2/
- README.txt
/test-repo-3/
- README.txt
So now we need to configure the network. I want requests on port 80 to transfer to the jail’s port 80. It doesn’t seem like I can make these changes dynamically so I shutdown the jail with pot stop fossil
. Then I set up my desired configuration with
pot export-ports -p fossil -e 80:80
After restarting the jail with pot start fossil
, I can enter pot show fossil
which displays some basic info along with my new redirect rule. I log back in with pot term fossil
and then start the server with
fossil server --repolist -P 80 fossils/ &
The --repolist
flag specifies we are serving multiple repositories, -P 80
tells the server to listen on port 80, and fossils/
is where the list of repositories resides.
At this point I can view repositories on my web browser by going to my hosts public IP. This is far far from an ideal setup. The server should start automatically on jail setup. I should create a reverse proxy so the fossil jail never directly accesses a public network. I should enable https. I should also create a reverse proxy so I can do things like also set up a private Gitlab instance or host this blog. There are a lot of shortcomings but the advantage of being a hobbyist is never having to pretend you’re competent.