A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.md 7.1KB

1 year ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. title: The Fediverse, And Custom Domains
  2. url: https://aeracode.org/2022/11/01/fediverse-custom-domains/
  3. hash_url: 9a78ae9b6814326d9c3df1425006f8f4
  4. <p>For reasons that are very relevant to the events of this past week, I have
  5. decided to finally get around to setting up a Mastodon / Fediverse account.</p>
  6. <p>I wanted to do it under my own domain, but last time I looked into this
  7. (three or so years ago), that was not possible if the domain was running
  8. something <em>other</em> than a Fediverse server - if you tried to follow
  9. <code>@andrew@aeracode.org</code>, it would come along to this website and try and do some
  10. ActivityPub on it.</p>
  11. <p>Faced with the idea of implementing proxy views for all the ActivityPub
  12. endpoints within my site, I instead opted to go back to the warm, stable
  13. embrace of Twitter (ahem), and come back and see how the fediverse had evolved in
  14. a few years' time.</p>
  15. <p>Well, here we are, and not only has the software and number of people improved,
  16. so has a few aspects of the underlying protocol (and look, ActivityPub is not
  17. great, but the only thing worse than implementing a flawed protocol is to try
  18. and invent yet another one to take its place).</p>
  19. <p>In particular, Fediverse servers now go looking for server and account (Actor)
  20. information via three URLs (which ones they want seems to differ by server):</p>
  21. <ul>
  22. <li><code>/.well-known/webfinger</code></li>
  23. <li><code>/.well-known/host-meta</code></li>
  24. <li><code>/.well-known/nodeinfo</code></li>
  25. </ul>
  26. <p>The last is static, and while the first two can be static if you just have one
  27. account on a server and never want to add any more, they're really meant to be
  28. dynamic and so should be proxied through to the fediverse server.</p>
  29. <p>So, faced with this much easier problem, that's what I did. This site still
  30. runs Django under the hood (though now powered by a sqlite database created on
  31. the fly - more on that in the future), and so doing this was a simple case of
  32. adding three views:</p>
  33. <div class="language-python3"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">proxy.views</span> <span class="kn">import</span> <span class="n">proxy_view</span>
  34. <span class="k">def</span> <span class="nf">wellknown_webfinger</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
  35. <span class="n">remote_url</span> <span class="o">=</span> <span class="p">(</span>
  36. <span class="s2">"https://fedi.aeracode.org/.well-known/webfinger?"</span>
  37. <span class="o">+</span> <span class="n">request</span><span class="o">.</span><span class="n">META</span><span class="p">[</span><span class="s2">"QUERY_STRING"</span><span class="p">]</span>
  38. <span class="p">)</span>
  39. <span class="k">return</span> <span class="n">proxy_view</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">remote_url</span><span class="p">)</span>
  40. <span class="k">def</span> <span class="nf">wellknown_hostmeta</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
  41. <span class="n">remote_url</span> <span class="o">=</span> <span class="p">(</span>
  42. <span class="s2">"https://fedi.aeracode.org/.well-known/host-meta?"</span>
  43. <span class="o">+</span> <span class="n">request</span><span class="o">.</span><span class="n">META</span><span class="p">[</span><span class="s2">"QUERY_STRING"</span><span class="p">]</span>
  44. <span class="p">)</span>
  45. <span class="k">return</span> <span class="n">proxy_view</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">remote_url</span><span class="p">)</span>
  46. <span class="k">def</span> <span class="nf">wellknown_nodeinfo</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
  47. <span class="n">remote_url</span> <span class="o">=</span> <span class="s2">"https://fedi.aeracode.org/.well-known/nodeinfo"</span>
  48. <span class="k">return</span> <span class="n">proxy_view</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">remote_url</span><span class="p">)</span></pre></div>
  49. </div>
  50. <p>This uses the <code>django-proxy</code> package to provide the <code>proxy_view</code>. You might
  51. also want to put in a view that redirects <code>yourdomain.com/@username</code>:</p>
  52. <div class="language-python3"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> <span class="n">HttpResponseRedirect</span>
  53. <span class="k">def</span> <span class="nf">username_redirect</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
  54. <span class="k">return</span> <span class="n">HttpResponseRedirect</span><span class="p">(</span><span class="s2">"https://fedi.aeracode.org/@andrew"</span><span class="p">)</span></pre></div>
  55. </div>
  56. <p>Hooking these up to the right URLs is the only other thing that's needed:</p>
  57. <div class="language-python3"><div class="highlight"><pre><span></span><span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
  58. <span class="o">...</span>
  59. <span class="c1"># Fediverse</span>
  60. <span class="n">path</span><span class="p">(</span><span class="s2">".well-known/webfinger"</span><span class="p">,</span> <span class="n">blog</span><span class="o">.</span><span class="n">wellknown_webfinger</span><span class="p">),</span>
  61. <span class="n">path</span><span class="p">(</span><span class="s2">".well-known/host-meta"</span><span class="p">,</span> <span class="n">blog</span><span class="o">.</span><span class="n">wellknown_hostmeta</span><span class="p">),</span>
  62. <span class="n">path</span><span class="p">(</span><span class="s2">".well-known/nodeinfo"</span><span class="p">,</span> <span class="n">blog</span><span class="o">.</span><span class="n">wellknown_nodeinfo</span><span class="p">),</span>
  63. <span class="n">path</span><span class="p">(</span><span class="s2">"@andrew"</span><span class="p">,</span> <span class="n">blog</span><span class="o">.</span><span class="n">username_redirect</span><span class="p">),</span>
  64. <span class="p">]</span></pre></div>
  65. </div>
  66. <p>That's what's up and running on this site right now, meaning you can type
  67. <code>@andrew@aeracode.org</code> into your favourite Fediverse client and it will
  68. understand that it's meant to actually go over to <code>fedi.aeracode.org</code> to ply
  69. its ActivityPub magic. If you're a CloudFlare Pages user, Jacob has
  70. <a href="https://jacobian.org/til/my-mastodon-instance/">a nice write-up</a> on how to do
  71. a similar trick over there.</p>
  72. <p>I'm happy, and crucially, I have avoided the temptation of writing my own
  73. ActivityPub/Mastodon-compatible server in Django. For now, at least.</p>
  74. <p>Incidentally, my server is hosted by <a href="https://masto.host">masto.host</a>, who
  75. I have nothing but good things to say about so far. I will happily pay $9 a
  76. month to avoid running yet another copy of all the various datastores that
  77. Mastodon needs, just for my own private instance.</p>
  78. <p><em>Note: Updated since first publication to add</em> <code>host-meta</code>
  79. <em>and the username redirect</em></p>