Super Pi Part 9: WebDAV

Posted on September 25, 2021

Just when I thought I was done adding things to Super Pi, I discovered another thing to add: a WebDAV server. I already have a Samba share, why do I need WebDAV? I've been looking at getting a Pine phone for at least 6 months now, and if I've learned anything about myself, it's that if I've been thinking about getting something that long, eventually it's going to happen. To make sure I would be able to handle not having an app store (or a more limited one), I took inventory of what I use my phone for and decided my usage could be distilled into three things: a VPN, a browser, and some way to interact with Org files (my recipe project described in a previous post is working great). I'm pretty sure the first two are covered in at least Mobian, but I need an alternative to Orgzly.

After some searching, I discovered Organice, which appears to do everything Orgzly does and more. The main difference is Organice pulls Org files down from Dropbox, Google Drive, or WebDAV; whereas Orgzly looks at files on disk, so an external program (such as Syncthing) is required for syncing. Part of the point of moving to a Pine phone is to escape Google, so Drive was out; I don't have particularly strong feelings about Dropbox, but I figured where's the fun in taking the easy way out? My one concern, though, is that I've got a pretty good flow working with Syncthing, and I'm not exactly sure what my workflow will look like for WebDAV.

I was further compelled to try WebDAV when I read that NGINX can host a WebDAV server if you install the full version, which I happened to have installed on Super Pi. After a little more research, I SSHd into Super Pi, and started slapping some config together in /etc/nginx/sites-available/webdav. A blog post here got me most of what I needed, my first iteration got me this server block:

server {
  listen 80;

  server_name webdav.my.local;
  autoindex on;

  root /var/www/html/files/;

  auth_basic "Restricted";
  auth_basic_user_file /etc/nginx/.htpasswd;

  dav_access user:rw group:rw all:r;
  dav_methods PUT DELETE MKCOL COPY MOVE;
  dav_ext_methods OPTIONS PROPFIND;

  client_body_temp_path /tmp/client-bodies;
  client_max_body_size 0;

  create_full_put_path on;
}

Super Pi is already configured to proxy domains to various servers, I just had to go into Pi-Hole and set webdav.my.local to proxy to the PI's IP, 192.168.0.23. auth_basic was also conveniently already set up thanks to Pi-Hole, so I decided to use the existing file here as well. The only extra stuff I had to do was make the /var/www/html/files/ folder. I did get mixed up on basic permissions and forgot that execute permissions were required to open a folder, but this got me sorted:

sudo chown www-data:www-data files
sudo chmod 775 files

With a quick sudo nginx -t followed by a sudo systemctl restart nginx I was able to open my Files app, go to Other Locations, and in the bottom there is a Connect to server prompt with a text box that I entered dav://webdav.my.local, and immediately got the prompt to sign in.

Organice

Getting Organice to connect to my WebDAV server was a little more involved, though. I toyed with pulling down Organice's source code and hosting it myself, but one of the JavaScript libraries threw up warnings about not running on ARM or something, so I scrapped that and decided to just go through organice.200ok.ch. There were two issues to resolve, plus one more secret issue that took me a long time to figure out.

The first issue was that Organice was hosted on HTTPS, so my WebDAV server had to be, too. Resolving this was easy, I just had to copy over the SSL settings from every other service I was proxying:

listen 443 ssl;
ssl_certificate /etc/ssl/certs/my.domains.local.crt;
ssl_certificate_key /etc/ssl/private/my.domains.local.key;
ssl_protocols TLSv1.2;
ssl_ciphers HIGH:!aNULL:MD5;

The second issue was that Organice is purely client-side, so the connections to my WebDAV server were done via client-side JavaScript which triggers CORS issues. Resolving this was fairly straightforward, Organice's documentation had most of this worked out already:

add_header 'Access-Control-Allow-Origin' * always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, OPTIONS, MOVE, DELETE, PROPFIND' always;
add_header 'Access-Control-Allow-Headers' 'Origin,Accept,X-Requested-With,Content-Length,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-CSRF-Token,Depth' always;
add_header 'Access-Control-Allow-Credentials' true always;

The secret issue was that the WebDAV library Organice used didn't play nice with NGINX's built-in basic auth, so I had to remove the two auth_basic lines from my NGINX configuration. This was a little disappointing, but authentication has always been a nice-to-have since this is all on my local network and behind a VPN.

In the end, my NGINX configuration turned into this:

server {
  listen 443 ssl;
  ssl_certificate /etc/ssl/certs/my.domains.local.crt;
  ssl_certificate_key /etc/ssl/private/my.domains.local.key;
  ssl_protocols TLSv1.2;
  ssl_ciphers HIGH:!aNULL:MD5;

  server_name webdav.my.local;
  autoindex on;

  client_body_temp_path /tmp/client-bodies;
  client_max_body_size 0;

  add_header 'Access-Control-Allow-Origin' * always;
  add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, OPTIONS, MOVE, DELETE, PROPFIND' always;
  add_header 'Access-Control-Allow-Headers' 'Origin,Accept,X-Requested-With,Content-Length,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-CSRF-Token,Depth' always;
  add_header 'Access-Control-Allow-Credentials' true always;

  root /var/www/html/files/;
  # auth_basic "Restricted";
  # auth_basic_user_file /etc/nginx/.htpasswd;

  dav_methods PUT DELETE MKCOL COPY MOVE;
  dav_ext_methods OPTIONS PROPFIND;
  dav_access user:rw group:rw all:r;

  create_full_put_path on;
}

The only annoying thing now is that on mobile I have to use Firefox beta and toggle a setting in about:config called security.enterprise_roots.enabled to true. The setting always reverts to false and it's becoming a pain to switch it all the time. When I eventually get a Pine phone, I think this will be an easy problem to fix, but on Android it's a bit of a pain.

Back to Orgzly

When I set up my repositories in Orgzly previously (in the main menu, under settings, then under sync, then once more under repositories), I completely missed that there was a WebDAV option when you hit the button to add a repository. The configuration is straightforward: simply provide the URL and in this case a bogus username and password (since auth isn't configured). Since the WebDAV is hosted locally over HTTPS, a certificate must be added even though the certificate authority is already installed on the operating system's certificate store per Super Pi Part 6. I used the same script to generate a new certificate that I provided to Orgzly. Here's the script:

openssl -x509 -req -in my.domains.local.csr -CA /home/pi/openssl/auth/myCA.pem -CAkey /home/pi/openssl/auth/myCA.key -CAcreateserial -out my.domains.local.crt -days 1825 -sha256 -extfile my.domains.local.ext

After copying the contents of the output file my.domains.local.crt to the certificate field in Orgzly, a connection can be made and Org files can be read.