Mirroring All the Nim Packages
The Problem⌗
At $DAY_JOB we like to keep our development environment isolated from the internet1. This means we have to mirror stuff like the Ubuntu and CentOS package repositories, so they are available in our dev environment.
Recently my company has decided to try and develop some tools in Nim, meaning we now had to mirror any an all nim
packages so that Developers could install them with nimble
2.
Getting the Packages⌗
Unlike a lot of languages nim
doesn’t have a centralised package repository we can just rsync
and serve.
Instead it fetches the packages source code from a URL defined in a packages.json file, and compiles it locally.
That JSON file contains around 2000 entries so I am not going to download all of them manually.
I’m going to turn to sh
to save me from that repetitive task, but first I need all the package URLs.
Thankfully jq
already exists.
jq '.[].url' packages.json > urls
sed -i 's/"//g' urls # to get rid of the quotes
Now all I need is someway to clone them all, preferably in parallel.
#!/bin/sh
while read u ; do
GIT_TERMINAL_PROMPT=0 git clone "${u}" &
done < "${1}
wait
That script will take a list of URLs from a file (the script’s arg 1) and clone them all with git in the background3.
I set GIT_TERMINAL_PROMPT=0
so that git will fail silently instead of prompting me for a username/password.
Serving the Packages⌗
Now I could sit back and just put all these repos on a network share,
telling the devs to grab the files they need and install locally,
but that sounds like a recipe for constant maintenance.
I want to make the process of installing packages as smooth as possible.
That means serving the packages in such a way that nimble
knows how to grab,
and telling nimble
where to find them.
Apache Configuration⌗
Since the existing infrastructure was set up with apache4 I went with it.
The configuration snippet to serve the packages is:
SetEnv GIT_PROJECT_ROOT /var/www/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
<LocationMatch "^/git/.git-receive-pack$>
AuthType Basic
AuthName "Git Access"
</LocationMatch>
Note: The documentation for
git-http-backend
seems to be written for RedHat distros. Both Debian’s man page and the official git book list the wrong path forgit-http-backend
. Both documents say to set theScriptAlias
to/usr/libexec/git-core/git-http-backend/
instead of the correct/usr/lib/git-core/git-http-backend/
path. Make sure you use the correct path, and don’t forget the trailing/
like I did
Now that we are serving git we have to let nimble
know about them.
Remember that packages.json
file we got all those URLs from, nimble
uses that to figure out how to get the packages.
So we just have to place a copy with all our packages in ~/.nimble/packages_official.json
.
First step is to replace all the URLs with our new domain.
sed -i'' 's|"url": "https://.*/|"url": "https://<new.domain.name>/' packages.json
Self Service⌗
I don’t want to have to keep answering questions about how to get this working. So I made a webpage to explain how5.
<!DOCTYPE html>
<html>
<head>
<title>Nim Package Mirror</title>
<style>
ul{
column-count: auto;
column-width: 15em;
}
</style>
</head>
<body>
<h1>Our Nim Package Mirror</h1>
<ol>
<li>Install nimble (Ex <code>apt install nim</code></li>
<li>Place this <a href="./packages_official.json">file</a> in your .nimble dir.</li>
<li>Install a package as normal (Ex <code>nimble install about</code></li>
</ol>
<ul>
<!--#include file="./packages.html" -->
</ul>
</html>
That <!--#include file="./packages.html" -->
line is so I can display a list of all the packages available.
You just need tell apache to allow includes6
<directory "/var/www/html/nim/">
options includes
addtype text/html .html
addoutputfilter includes .html
</directory>
And a simple script to populate the packages.html
file:
> /var/www/html/nim/packages.html # ensure the file exists and is empty
for d in /var/nim/git/* ; do
printf "<li>%s</li>\n" "${d}" >> /var/www/html/nim/packages.html
done
Giving us a nice (if a little simple webpage).
The last step is to tell the devs about it and see if they break anything.
-
So the programmers don’t spend all their time watching cat videos. ↩︎
-
The
nim
package manager: github.com/nim-lang/nimble ↩︎ -
well at least all the ones served by git ↩︎
-
I am by no means a webdev so it is very simple ↩︎
-
props to css-tricks for the how to. ↩︎