Writeup by Morgan Gangwere <morgan.gangwere!gmail.com> github.com/indrora
My original proposal and the final product look... a little bit different. In the beginning, the goal was to get the basics of what made LibraryBox and PirateBox working on a Pi, then refine them down.
What ended up happening is a mostly total rewrite of the backend, including a configuration file generator, a socket server and a handful of other little things.
The first thing I did was dig into the orignal PirateBox tree. This quickly led me down the path of going "oh dear this isn't going to end well". The original design of PirateBox and LibraryBox is to use the OpenWRT framework for configuratrion.
I looked at OpenWRT on the Pi 3. And then I saw what the work on OpenWRT for the pi 3 was... lacking.
After a little bit of soul-searching, the options were:
- port openwrt's frontend for configuration
- Write our own
Porting OpenWRT's configuration frontend would have taken a lot of work that could take more time than neccesary. I didn't want to spin my heels learning another language (lua) and trying to get lua, php and lighttpd running together.
I chose to write everything from scratch. The result was a unified frontend for content and for configuration. I decided to call this Alexandria, and in the end tackled it from three aspects:
- Configuration: There's an extensible configuration framework gives users and later developers control over what's running on their LibraryBox (or PirateBox) device.
- File browsing and upload: There's a very basic way of uploading files, plus some filtering on file-type and such that is configurable through the admin interface
- Consistent builds: Building LibraryBox doesn't take having a full OpenWRT build system now, and instead is done by running the installation sequence in-situ via qemu's ARM-usermode binfmt support. This means that now, the install sequence is a lot more like frosting a cake and less like making the cake from the raw wheat.
My workflow got me to the point I have builds up on my website: http://tsunami.zaibatsutel.net/alexandria-images/
Fun fact: if you telnet to the default installation on port :3333, you get nyancat.
Nyancat has an interesting history: In the beginning, the only two services I had were dnsmasq and hostapd. I needed something I could test the service framework on without having to constantly bake a new image and push it to the pi. The result was finding Nyancat ( http://nyancat.dakko.us/ ) which has a telnet interface, meant for pushing through inetd. I wrote a single-port safe inetd in python (tinetd) so that I could test this, and thus: You can nyancat from LibraryBox. Later, it served double-duty to make sure that the httpd side of things was working, because sometimes I would break nginx on accident and I didn't know if hostapd had broken or if it was nginx. More often than not, it was nginx.
Apple has a bad habit of changing the sands of what they consider a connectable wireless network. This has been a thorn in my side for a while, and as a result I've spent a long time digging through StackOverflow and even Apple forums. Just as a few examples:
- Apple users and network forums: https://discussions.apple.com/thread/7705927?start=0&tstart=0
- StackOverflow: https://apple.stackexchange.com/questions/62870/how-do-i-tell-an-ios-device-theres-no-internet-connection-on-the-wifi/62905
- Another StackOverflow: https://stackoverflow.com/questions/23553449/remain-connected-to-wifi-network-that-has-a-captive-portal
- More StackOverflow: https://stackoverflow.com/questions/18891706/ios7-and-captive-portals-changes-to-apple-request-url
- Once more, with feeling: https://apple.stackexchange.com/a/103122
There was a face-shaped dent in my desk through the second half of the summer.
When I got back to Albuquerque, I went to some of the local Apple developers I know and asked if they had seen this. I didn't even need to give the full symptoms and the answer I got was "We've fought this too". Turns out, Apple wants you to set a static IP address on these sorts of networks, or you can sinkhole every domain ever into being your device. Some friends of mine from a local ISP had heard rumors that speciic IPv6 ranges were allowed to be handed out, but I really didn't want to get into that at the end of all this.
It gets worse: Consuming everything makes Windows freak out in some cases; Windows wants to be safe, and when I tested Windows connecting to it in situations where Windows was set up for an "enterprise" environment (not all that uncommon in libraries and schools), doing this would upset things like ActiveDirectory and the endpoint protection features. And so Windows would get angry and toss its hands in the air and say the world is bad.
So it works on everything but Apple devices.
I had a lot of fun. It was interesting to hash out the pros and cons of simply doing a huge rewrite vs. porting it over. The technical challenges have been some of the most interesting parts of this summer.
Doing a demo and having it work was the icing on the cake.
- Apple devices don't like the Pi's wireless network.
- Nginx is hard-coded in certain places. I'd like to make it so that nginx configuration is done by the configuration generator script instead of being hand-baked. This would let proxy_pass statements be generated for services such as Calibre's server backend.
- There isn't any way to rename files or otherwise mangle files from the web interface.
- Previews require downloading the WHOLE FILE in some cases -- e.g. photos. It'd be nice to have a cache
- the install scripts are fragile
- It takes 5 minutes to get to a wireless network being around and there. This would likely need some basic tuning
- The internal storage doesn't work. Instead, all files are currently written to the SD card unless you have a disk plugged in. It's not an elegant solution, and the fix is probably easy enough to implement, I've just run out of brain cycles to dedicated to it.
- There's a handful of places that need to be fixed in the documentation. Lots of typos and the whole thing could use some pictures.
Finally, one that REALLY bugs me: I haven't tested this aginst the latest build of Raspbian. The final days of the coding period and guess what: Raspberry Pi foundation shipped Debian 9 on the Pi. Having this would have fundamentally made my life better if I had had this from the get-go, but you can't win all the time.