Skip to content

Instantly share code, notes, and snippets.

@haykinson
Last active April 11, 2023 06:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haykinson/e3b7004d8e7436bf4486964b89af4ca1 to your computer and use it in GitHub Desktop.
Save haykinson/e3b7004d8e7436bf4486964b89af4ca1 to your computer and use it in GitHub Desktop.
setting up nginx for webfinger

So, you want to use username@personaldomain.example as a Mastodon profile, but don't want to run an instance with a single user? Webfinger to the rescue! If you run your own web server, or have control over it, you can set up a webfinger implementation that should transparently work with Mastodon to let people follow you regardless of which instance you're actually on.

For a great guide to doing this for Apache, please see Erik's post. This guide is about doing the same for nginx.

First, make sure that you have the nginx javascript module (njs) installed. We need the javascript module in order to be able to easily extract a urldecoded query string parameter. On Ubuntu this is a matter of running:

# apt-get install nginx-module-njs

On Debian, install libnginx-mod-http-js instead.

Then, edit /etc/nginx/nginx.conf and add the following line at the top:

load_module modules/ngx_http_js_module.so;

Test to make sure that everything worked:

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Now, create a directory in your web root, called .webfinger for example. Put in a file that looks exactly like the one on Erik's page. Name it username.json and save it.

Open your nginx site configuration (for example /etc/nginx/conf.d/default.conf for a very minimal install). Add the following:

Within your server {} block, add the following at the top:

js_import http.js;

Then, add the following:

    location ~ /.well-known/webfinger {
      rewrite_log off;
      js_set $decoded http.decoded;

      if ($args ~* "^resource=.*") {
          add_header  Content-Type    application/json;
          rewrite ^.*$ /.webfinger/$decoded.json last;
      }
      return 404;
    }

You will now need to create a file named http.js inside of /etc/nginx/:

function decoded(r) {
    if (!('resource' in r.args)) {
        return "";
    }
    let lookup_expression = /acct:(.+)@personaldomain.example/;
    var match = r.args["resource"].match(lookup_expression);
    if (!match || match.length == 0) {
        return "";
    }
    return match[1];
}

export default {decoded};

(make sure to change personaldomain.example to your actual domain!)

Test to make sure that nginx still works (nginx -t) and restart nginx (systemctl reload nginx).

If it worked so far, go to https://webfinger.net/ and use the text box at the top to look up your account. If it doesn't work, use your server logs to troubleshoot what's wrong.

And, if you've gotten this far, and everything worked, you can now use @username@personaldomain.example as a way to follow you on Mastodon!

@darac
Copy link

darac commented Apr 10, 2023

For the record, on Debian the package you want to install is libnginx-mod-http-js (this will enable the module, so need to add load_module to nginx.conf).

Also, where you've written:

You will now need to put the following file into /etc/nginx/

it should be clarified that the filename needs to be http.js, because this is the filename referenced by the js_import command.

@haykinson
Copy link
Author

@darac Thanks, updated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment